WeKnora deployment source with the reviewed wiki identity, summary and recovery fixes
Anydoc / anydoc parser engine (push) Canceled after 0s
App / Format, vet, test, and build (push) Canceled after 0s
CLI / test (macos-latest / go 1.26) (push) Canceled after 0s
CLI / test (ubuntu-latest / go 1.26) (push) Canceled after 0s
CLI / test (windows-latest / go 1.26) (push) Canceled after 0s
Build and Push Docker Image / build-ui (push) Canceled after 0s
Build and Push Docker Image / build-docreader (push) Canceled after 0s
Build and Push Docker Image / build-sandbox (push) Canceled after 0s
Build and Push Docker Image / build-app (amd64, linux/amd64, ubuntu-latest) (push) Canceled after 0s
Build and Push Docker Image / build-app (arm64, linux/arm64, ubuntu-24.04-arm) (push) Canceled after 0s
DocReader / Python tests and Go client tests (push) Canceled after 0s
Build & Publish (dsh-weknora) / Typecheck, test, pack (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (pinned) (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (latest, advisory) (push) Canceled after 0s
Frontend / Test, type-check, and build (push) Canceled after 0s
Go Lint Cache / warm lint cache (.) (push) Canceled after 0s
Go Lint Cache / warm lint cache (cli) (push) Canceled after 0s
Go Lint Cache / warm lint cache (client) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.10) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.11) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.12) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.13) (push) Canceled after 0s
Build and Push Docker Image / merge (push) Canceled after 0s
Build & Publish (dsh-weknora) / Publish to npm (push) Canceled after 0s
Build & Publish (mcp-server) / Build sdist + wheel (push) Canceled after 0s
Build & Publish (mcp-server) / Publish to PyPI (push) Canceled after 0s
Anydoc / anydoc parser engine (push) Canceled after 0s
App / Format, vet, test, and build (push) Canceled after 0s
CLI / test (macos-latest / go 1.26) (push) Canceled after 0s
CLI / test (ubuntu-latest / go 1.26) (push) Canceled after 0s
CLI / test (windows-latest / go 1.26) (push) Canceled after 0s
Build and Push Docker Image / build-ui (push) Canceled after 0s
Build and Push Docker Image / build-docreader (push) Canceled after 0s
Build and Push Docker Image / build-sandbox (push) Canceled after 0s
Build and Push Docker Image / build-app (amd64, linux/amd64, ubuntu-latest) (push) Canceled after 0s
Build and Push Docker Image / build-app (arm64, linux/arm64, ubuntu-24.04-arm) (push) Canceled after 0s
DocReader / Python tests and Go client tests (push) Canceled after 0s
Build & Publish (dsh-weknora) / Typecheck, test, pack (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (pinned) (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (latest, advisory) (push) Canceled after 0s
Frontend / Test, type-check, and build (push) Canceled after 0s
Go Lint Cache / warm lint cache (.) (push) Canceled after 0s
Go Lint Cache / warm lint cache (cli) (push) Canceled after 0s
Go Lint Cache / warm lint cache (client) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.10) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.11) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.12) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.13) (push) Canceled after 0s
Build and Push Docker Image / merge (push) Canceled after 0s
Build & Publish (dsh-weknora) / Publish to npm (push) Canceled after 0s
Build & Publish (mcp-server) / Build sdist + wheel (push) Canceled after 0s
Build & Publish (mcp-server) / Publish to PyPI (push) Canceled after 0s
This commit is contained in:
@@ -0,0 +1,171 @@
|
||||
const assert = require('node:assert/strict')
|
||||
const crypto = require('node:crypto')
|
||||
const fs = require('node:fs')
|
||||
const path = require('node:path')
|
||||
|
||||
const sixthRecoveryScope = Object.freeze({ tenant_id: 10059, dead_letter_id: 10,
|
||||
knowledge_id: 'd52e5191-1129-4934-be64-3dcc0651e52b',
|
||||
knowledge_base_id: '5d28a7e5-e00e-44a7-a0e1-c72342cdcf68',
|
||||
model_id: '404e005b-83ae-5e2e-a3b3-999f9d5cd47e',
|
||||
embedding_model_id: 'a2c3ce32-6192-46c8-8072-910abfe8afed',
|
||||
source_fingerprint: 'e6198cf7c0c3de64150a2f3944c986ee4fffaa347d31e560d8ea3d4994c92a07',
|
||||
model_fingerprint: 'e57322463beae82b3d8876f4735637b30b2bc5f65dcd716f9f26d4bcc677a12c' })
|
||||
const sixthGuardPausedOperation = Object.freeze({ id: 4144, tenant_id: sixthRecoveryScope.tenant_id,
|
||||
task_type: 'wiki:ingest', scope: 'knowledge_base', scope_id: sixthRecoveryScope.knowledge_base_id,
|
||||
op: 'ingest', dedup_key: sixthRecoveryScope.knowledge_id, fail_count: 5,
|
||||
payload: Object.freeze({ op: 'ingest', knowledge_id: sixthRecoveryScope.knowledge_id,
|
||||
recovery_dead_letter_id: 10, recovery_attempt: 5, recovery_pending_op_id: 4144, recovery_budget_version: 1 }) })
|
||||
const diagnosticPins = Object.freeze({
|
||||
release: 'public-20260920-223700', image: 'sha256:7161342591c754fa734a486e0dd56a892f0d404c97b4a524381d244a594d575e',
|
||||
source: '0e250d6605cc2ee40da694608b5b410ff92b504660d6ee38ead11e15cbf7846a',
|
||||
window: 'f2e3cb37e496df4d93d56586d9659c7ae680cc8dc8e5476136dd02d044bd908a', start: 32750, end: 65497,
|
||||
})
|
||||
const replayPins = Object.freeze({
|
||||
kind: 'candidate_layout_identity_replay_v1',
|
||||
input_run_id: 'b3cf4f6a-b734-48f3-90f8-61be44b3d813',
|
||||
input_evidence_sha256: 'b26a2ec44eeb386a7de9750566b350b6940b8abded8ca28a607d821af1ba7dbe',
|
||||
source_window_sha256: '4f61cde7c750c4ec4052ccb01626ea6122ff8d79c527c4c34abd51b9679d3d65',
|
||||
response_sha256: '39ce646b91e05437a1ad4d9ee28524048be8fdc751ecce935c3da86eed0c63d5',
|
||||
})
|
||||
const sha = value => crypto.createHash('sha256').update(value).digest('hex')
|
||||
|
||||
function validateSixthRecoveryReview(review, now = Date.now()) {
|
||||
assert.equal(review?.max_attempt, 6, 'Sixth recovery requires its own review')
|
||||
for (const [key, value] of Object.entries(sixthRecoveryScope)) assert.equal(review[key], value, `Sixth recovery review mismatch: ${key}`)
|
||||
assert.equal(review.previous_attempt, 5, 'Sixth recovery requires attempt five')
|
||||
assert.equal(review.previous_pending_op_id, 4144, 'Sixth recovery requires exact operation 4144')
|
||||
assert.equal(review.previous_error_code, 'EXTRACT_FAILED', 'Sixth recovery requires the reviewed extraction failure')
|
||||
assert.equal(review.budget_version, 1, 'Sixth recovery requires its own durable budget')
|
||||
assert.ok(Number.isSafeInteger(review.max_provider_requests) && review.max_provider_requests > 0 && review.max_provider_requests <= 1000, 'Sixth recovery request limit must be 1..1000')
|
||||
const start = Date.parse(review.budget_started_at), deadline = Date.parse(review.deadline_at)
|
||||
assert.ok(Number.isFinite(start) && start <= now && deadline > start && deadline - start <= 120 * 60000, 'Sixth recovery needs a fixed duration of at most 120 minutes')
|
||||
assert.equal(review.public_gates_passed, true, 'Sixth recovery requires fresh public verification')
|
||||
assert.ok(review.fix_release > diagnosticPins.release, 'Sixth recovery requires the newer published candidate fix')
|
||||
assert.notEqual(review.api_image_id, diagnosticPins.image, 'Sixth recovery cannot use the pre-repair image')
|
||||
const diagnostic = review.candidate_diagnostic
|
||||
assert.ok(['candidate_repair_window_v3', replayPins.kind].includes(diagnostic?.kind), 'Sixth recovery requires reviewed diagnostic or saved-response replay evidence')
|
||||
assert.match(diagnostic.run_id || '', /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/, 'Missing diagnostic run identity')
|
||||
for (const key of ['evidence_sha256', 'source_tree_hash']) assert.match(diagnostic[key] || '', /^[a-f0-9]{64}$/, `Missing diagnostic ${key}`)
|
||||
assert.equal(diagnostic.semantic_reviewed, true, 'Successful parsing needs a separate semantic review')
|
||||
}
|
||||
|
||||
function validateSixthRecovery(source, previous, review) {
|
||||
validateSixthRecoveryReview(review)
|
||||
for (const [key, value] of Object.entries(sixthRecoveryScope)) assert.equal(key === 'dead_letter_id' ? source.id : source[key], value, `Sixth recovery source mismatch: ${key}`)
|
||||
assert.equal(previous?.attempt_number, 5, 'Sixth recovery requires the exact preceding attempt')
|
||||
assert.equal(previous.pending_op_id, 4144, 'Sixth recovery requires exact preceding operation 4144')
|
||||
assert.equal(previous.recovery_status, 'stopped_budget', 'Attempt five must remain terminal')
|
||||
assert.equal(previous.error_code, 'EXTRACT_FAILED', 'Preceding extraction failure changed')
|
||||
assert.ok(!previous.pending && !previous.pending_finalize, 'Attempt five must be idle')
|
||||
const budget = previous.recovery_budget
|
||||
assert.equal(budget?.status, 'stopped_budget', 'Attempt five budget must remain terminal')
|
||||
for (const [key, value] of Object.entries(sixthRecoveryScope)) assert.equal(budget[key], value, `Preceding budget mismatch: ${key}`)
|
||||
assert.equal(budget.attempt_number, 5, 'Preceding budget attempt changed')
|
||||
assert.equal(budget.pending_op_id, 4144, 'Preceding budget operation changed')
|
||||
assert.ok(Number.isSafeInteger(previous.new_failures) && previous.new_failures >= 0, 'Invalid preceding failure count')
|
||||
if (previous.new_failures === 0) {
|
||||
// The durable guard preserves this failed operation before another dead letter.
|
||||
assert.equal(previous.span_status, 'failed', 'Guard pause requires the failed extraction span')
|
||||
assert.equal(budget.stop_reason, 'guard_rejected', 'Preceding guard stop reason changed')
|
||||
assert.equal(budget.last_phase, 'wiki_candidate_slug', 'Preceding guard phase changed')
|
||||
assert.equal(budget.reserved_provider_requests, 4, 'Preceding guard send count changed')
|
||||
assert.equal(typeof budget.paused_payload, 'string', 'Preceding paused operation is missing')
|
||||
const paused = JSON.parse(budget.paused_payload)
|
||||
assert.ok(Array.isArray(paused) && paused.length === 1, 'Expected exactly one paused operation')
|
||||
for (const [key, value] of Object.entries(sixthGuardPausedOperation)) {
|
||||
if (key === 'payload') {
|
||||
for (const [field, expected] of Object.entries(value)) assert.equal(paused[0]?.payload?.[field], expected, `Preceding paused payload changed: ${field}`)
|
||||
} else assert.equal(paused[0]?.[key], value, `Preceding paused operation changed: ${key}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function validateSixthDiagnosticEvidence(review, bytes, sourceTreeHash) {
|
||||
validateSixthRecoveryReview(review)
|
||||
assert.equal(review.candidate_diagnostic.kind, 'candidate_repair_window_v3', 'Expected original V3 evidence')
|
||||
assert.equal(sha(bytes), review.candidate_diagnostic.evidence_sha256, 'V3 evidence changed after review')
|
||||
const evidence = JSON.parse(bytes)
|
||||
assert.equal(evidence.run_id, review.candidate_diagnostic.run_id, 'V3 run changed after review')
|
||||
assert.equal(evidence.source_tree_hash, review.candidate_diagnostic.source_tree_hash, 'V3 candidate source changed')
|
||||
assert.equal(sourceTreeHash, evidence.source_tree_hash, 'Current candidate source differs from the tested V3 source')
|
||||
assert.equal(evidence.status, 'finished', 'V3 diagnostic did not finish')
|
||||
assert.equal(evidence.candidate_source_only, true, 'Expected candidate diagnostic')
|
||||
assert.equal(evidence.protected_state_unchanged, true, 'V3 changed protected state')
|
||||
assert.equal(evidence.previous_diagnostics_unchanged, true, 'V3 changed historical evidence')
|
||||
const pins = evidence.pins
|
||||
for (const [key, value] of Object.entries({ tenant: 10059, deadLetter: 10, priorAttempt: 5, priorOperation: 4144,
|
||||
document: sixthRecoveryScope.knowledge_id, kb: sixthRecoveryScope.knowledge_base_id, model: sixthRecoveryScope.model_id,
|
||||
embedding: sixthRecoveryScope.embedding_model_id, sourceFingerprint: sixthRecoveryScope.source_fingerprint,
|
||||
modelFingerprint: sixthRecoveryScope.model_fingerprint, release: diagnosticPins.release, image: diagnosticPins.image,
|
||||
maxSends: 21, durationMs: 900000 })) assert.equal(pins?.[key], value, `V3 scope mismatch: ${key}`)
|
||||
const outcome = evidence.outcome
|
||||
assert.equal(outcome?.status, 'exact_window_candidates_validated', 'V3 full window did not pass')
|
||||
assert.equal(outcome.source_hash, diagnosticPins.source, 'V3 source changed')
|
||||
assert.deepEqual(outcome.window, { start_rune: diagnosticPins.start, end_rune: diagnosticPins.end, sha256: diagnosticPins.window }, 'V3 window changed')
|
||||
assert.ok(Number.isSafeInteger(outcome.candidate_count) && outcome.candidate_count > 0, 'V3 returned no validated candidates')
|
||||
assert.ok(Number.isSafeInteger(evidence.actual_send_reservations) && evidence.actual_send_reservations >= 1 && evidence.actual_send_reservations <= 21, 'V3 send budget invalid')
|
||||
assert.equal(outcome.actual_send_reservations, evidence.actual_send_reservations, 'V3 send receipt mismatch')
|
||||
let cursor = diagnosticPins.start
|
||||
assert.ok(Array.isArray(outcome.leaves) && outcome.leaves.length > 0, 'V3 source coverage missing')
|
||||
for (const leaf of outcome.leaves) {
|
||||
assert.equal(leaf.start_rune, cursor, 'V3 source coverage has a gap')
|
||||
assert.ok(Number.isSafeInteger(leaf.end_rune) && leaf.end_rune > cursor && leaf.end_rune <= diagnosticPins.end, 'V3 source coverage range invalid')
|
||||
cursor = leaf.end_rune
|
||||
}
|
||||
assert.equal(cursor, diagnosticPins.end, 'V3 source coverage incomplete')
|
||||
assert.ok(Date.parse(review.published_at) > Date.parse(evidence.started_at), 'Published fix must follow candidate diagnostic')
|
||||
}
|
||||
|
||||
// Replaying the unchanged failed response proves the mechanical repair without
|
||||
// another provider request. The original failure remains a separate artifact.
|
||||
function validateSixthReplayEvidence(review, bytes, sourceTreeHash) {
|
||||
validateSixthRecoveryReview(review)
|
||||
assert.equal(review.candidate_diagnostic.kind, replayPins.kind, 'Expected layout identity replay')
|
||||
assert.equal(sha(bytes), review.candidate_diagnostic.evidence_sha256, 'Replay evidence changed after review')
|
||||
const evidence = JSON.parse(bytes)
|
||||
for (const [key, value] of Object.entries(replayPins)) assert.equal(evidence[key], value, `Replay input changed: ${key}`)
|
||||
assert.equal(evidence.run_id, review.candidate_diagnostic.run_id, 'Replay run changed after review')
|
||||
assert.equal(evidence.source_tree_hash, review.candidate_diagnostic.source_tree_hash, 'Replay candidate source changed')
|
||||
assert.equal(sourceTreeHash, evidence.source_tree_hash, 'Current candidate source differs from the replayed source')
|
||||
for (const [key, value] of Object.entries({ status: 'passed', model_calls: 0, production_writes: 0,
|
||||
rejected_count: 0, source_preserved: true, original_receipt_preserved: true })) {
|
||||
assert.equal(evidence[key], value, `Replay did not satisfy ${key}`)
|
||||
}
|
||||
// The actual saved response has 22 entity identities and 67 concept identities.
|
||||
// No candidate may disappear merely because its generated slug collides.
|
||||
assert.equal(evidence.entity_count, 22, 'Replay lost an entity identity')
|
||||
assert.equal(evidence.concept_count, 67, 'Replay lost a concept identity')
|
||||
assert.equal(evidence.candidate_count, 89, 'Replay must preserve every distinct candidate identity')
|
||||
const start = Date.parse(evidence.started_at), end = Date.parse(evidence.completed_at)
|
||||
assert.ok(Number.isFinite(start) && end >= start, 'Replay timing is invalid')
|
||||
assert.ok(Date.parse(review.published_at) > end, 'Published fix must follow the replay')
|
||||
}
|
||||
|
||||
function verifyReplayInputFiles(runtimeDirectory) {
|
||||
const directory = path.join(runtimeDirectory, 'acceptance/wiki-source-identity-diagnostic-private-20260921')
|
||||
const semantic = path.join(directory, `semantic-review-${replayPins.input_run_id}`)
|
||||
for (const [file, expected] of [
|
||||
[path.join(directory, 'evidence.json'), replayPins.input_evidence_sha256],
|
||||
[path.join(semantic, 'accepted/source-window.json'), replayPins.source_window_sha256],
|
||||
[path.join(semantic, 'responses/response-01.json'), replayPins.response_sha256],
|
||||
]) assert.equal(sha(fs.readFileSync(file)), expected, 'Original replay input changed')
|
||||
}
|
||||
|
||||
function candidateSourceTreeHash(sourceDirectory) {
|
||||
const files = ['go.mod', 'go.sum']
|
||||
function walk(relative) {
|
||||
for (const entry of fs.readdirSync(path.join(sourceDirectory, relative), { withFileTypes: true })) {
|
||||
assert.ok(!entry.isSymbolicLink(), 'Candidate source contains unreviewed symlink')
|
||||
const file = path.join(relative, entry.name)
|
||||
if (entry.isDirectory()) walk(file)
|
||||
else if (entry.isFile()) files.push(file)
|
||||
}
|
||||
}
|
||||
walk('internal'); walk('third_party')
|
||||
const hash = crypto.createHash('sha256')
|
||||
for (const file of files.sort()) hash.update(file + '\0' + sha(fs.readFileSync(path.join(sourceDirectory, file))) + '\n')
|
||||
return hash.digest('hex')
|
||||
}
|
||||
|
||||
module.exports = { sixthRecoveryScope, sixthGuardPausedOperation, diagnosticPins, replayPins, validateSixthRecoveryReview, validateSixthRecovery,
|
||||
validateSixthDiagnosticEvidence, validateSixthReplayEvidence, verifyReplayInputFiles, candidateSourceTreeHash }
|
||||
Reference in New Issue
Block a user