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,150 @@
|
||||
'use strict'
|
||||
|
||||
// Offline, one-leaf continuation planner. This module deliberately has no
|
||||
// database, Docker, HTTP, or filesystem side effects. A production runner may
|
||||
// use the returned receipt after independently reserving its diagnostic lane.
|
||||
|
||||
const crypto = require('node:crypto')
|
||||
|
||||
const VERSION = 'wiki-leaf-diagnostic-continuation-v1'
|
||||
const MAX_MODEL_CALLS = 1
|
||||
const TERMINAL_STATUSES = new Set(['identity_failure', 'captured', 'leaf_succeeded', 'stopped_invalid', 'stopped_budget'])
|
||||
|
||||
const sha256 = value => crypto.createHash('sha256').update(value).digest('hex')
|
||||
const checkpointHash = value => sha256(JSON.stringify(value))
|
||||
|
||||
function fail(code, message) {
|
||||
const error = new Error(message || code)
|
||||
error.code = code
|
||||
throw error
|
||||
}
|
||||
|
||||
function asHash(value, label) {
|
||||
if (typeof value !== 'string' || !/^[a-f0-9]{64}$/.test(value)) fail('invalid_manifest', `${label} must be a SHA-256 hex string`)
|
||||
return value
|
||||
}
|
||||
|
||||
function validateWindow(window, index) {
|
||||
if (!window || !Number.isSafeInteger(window.start_rune) || !Number.isSafeInteger(window.end_rune)
|
||||
|| window.start_rune < 0 || window.end_rune <= window.start_rune) {
|
||||
fail('invalid_manifest', `window ${index} has an invalid rune range`)
|
||||
}
|
||||
asHash(window.text_sha256, `window ${index} text_sha256`)
|
||||
if (typeof window.key !== 'string' || window.key.length === 0) fail('invalid_manifest', `window ${index} key is required`)
|
||||
if (window.status !== 'checkpointed' && window.status !== 'missing') fail('invalid_manifest', `window ${index} status is invalid`)
|
||||
if (window.status === 'checkpointed' && window.result === undefined) fail('invalid_manifest', `window ${index} checkpoint result is missing`)
|
||||
}
|
||||
|
||||
function validateManifest(manifest, source) {
|
||||
if (!manifest || manifest.version !== VERSION) fail('invalid_manifest', 'unsupported continuation manifest version')
|
||||
const scope = manifest.scope
|
||||
if (!scope || !Number.isSafeInteger(scope.tenant_id) || scope.tenant_id <= 0
|
||||
|| typeof scope.knowledge_base_id !== 'string' || !scope.knowledge_base_id
|
||||
|| typeof scope.knowledge_id !== 'string' || !scope.knowledge_id
|
||||
|| typeof scope.model_id !== 'string' || !scope.model_id
|
||||
|| !Number.isSafeInteger(scope.parent_attempt) || scope.parent_attempt <= 0
|
||||
|| !Number.isSafeInteger(scope.parent_pending_op_id) || scope.parent_pending_op_id <= 0
|
||||
|| !Number.isSafeInteger(scope.diagnostic_pending_op_id) || scope.diagnostic_pending_op_id <= 0
|
||||
|| scope.parent_pending_op_id === scope.diagnostic_pending_op_id
|
||||
|| typeof scope.reviewed_release !== 'string' || !scope.reviewed_release
|
||||
|| typeof scope.reviewed_api_image !== 'string' || !scope.reviewed_api_image) {
|
||||
fail('invalid_manifest', 'continuation scope is incomplete')
|
||||
}
|
||||
asHash(scope.checkpoint_fingerprint, 'checkpoint_fingerprint')
|
||||
asHash(scope.source_sha256, 'source_sha256')
|
||||
if (!Number.isSafeInteger(manifest.max_model_calls) || manifest.max_model_calls !== MAX_MODEL_CALLS) {
|
||||
fail('invalid_manifest', 'diagnostic continuation must reserve exactly one model call')
|
||||
}
|
||||
if (typeof source !== 'string') fail('source_required', 'source text is required')
|
||||
if (sha256(source) !== scope.source_sha256) fail('source_changed', 'source SHA-256 does not match the reviewed scope')
|
||||
if (!Array.isArray(manifest.windows) || manifest.windows.length === 0) fail('invalid_manifest', 'windows are required')
|
||||
manifest.windows.forEach(validateWindow)
|
||||
const targets = manifest.windows.filter(window => window.status === 'missing')
|
||||
if (targets.length !== 1) fail('target_window_count', 'exactly one missing target window is required')
|
||||
const target = targets[0]
|
||||
if (!scope.target_window || scope.target_window.key !== target.key
|
||||
|| scope.target_window.start_rune !== target.start_rune
|
||||
|| scope.target_window.end_rune !== target.end_rune
|
||||
|| scope.target_window.text_sha256 !== target.text_sha256) {
|
||||
fail('target_scope_mismatch', 'target window does not match the manifest scope')
|
||||
}
|
||||
if (!manifest.windows.some(window => window.status === 'checkpointed')) fail('no_completed_siblings', 'no completed sibling window is available to resume')
|
||||
return target
|
||||
}
|
||||
|
||||
function targetIdempotencyKey(manifest) {
|
||||
const scope = manifest.scope
|
||||
return checkpointHash([VERSION, scope.tenant_id, scope.knowledge_base_id, scope.knowledge_id,
|
||||
scope.checkpoint_fingerprint, scope.target_window.key, scope.target_window.text_sha256])
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute one offline continuation. The model callback receives the exact
|
||||
* target text and may return {status: 'identity_failure', response} or
|
||||
* {status: 'leaf_succeeded', result}. No callback is made for any sibling.
|
||||
*/
|
||||
function runDiagnosticContinuation(manifest, source, modelCall, captureFailure = () => {}) {
|
||||
const target = validateManifest(manifest, source)
|
||||
if (typeof modelCall !== 'function') fail('model_callback_required', 'a model callback is required')
|
||||
if (typeof captureFailure !== 'function') fail('capture_callback_required', 'a capture callback is required')
|
||||
|
||||
const targetText = Array.from(source).slice(target.start_rune, target.end_rune).join('')
|
||||
if (sha256(targetText) !== target.text_sha256) fail('target_source_changed', 'target window text does not match its reviewed hash')
|
||||
const key = checkpointHash(['wiki-full-read-v1', targetText])
|
||||
if (key !== target.key) fail('target_key_mismatch', 'target key does not match the service checkpoint key')
|
||||
|
||||
let calls = 0
|
||||
const outcome = modelCall(targetText, {
|
||||
key,
|
||||
start_rune: target.start_rune,
|
||||
end_rune: target.end_rune,
|
||||
max_model_calls: MAX_MODEL_CALLS,
|
||||
})
|
||||
calls++
|
||||
if (calls > MAX_MODEL_CALLS) fail('model_budget_exceeded', 'diagnostic continuation exceeded its one-call budget')
|
||||
if (!outcome || !TERMINAL_STATUSES.has(outcome.status)) fail('invalid_model_outcome', 'model outcome is not a bounded terminal result')
|
||||
|
||||
const windows = manifest.windows.map(window => ({ ...window }))
|
||||
const receipt = {
|
||||
version: VERSION,
|
||||
idempotency_key: targetIdempotencyKey(manifest),
|
||||
status: outcome.status,
|
||||
model_calls: calls,
|
||||
scope: { ...manifest.scope, target_window: { ...manifest.scope.target_window } },
|
||||
completed_sibling_keys: windows.filter(window => window.status === 'checkpointed').map(window => window.key),
|
||||
target_window: { key: target.key, start_rune: target.start_rune, end_rune: target.end_rune, text_sha256: target.text_sha256 },
|
||||
}
|
||||
if (outcome.status === 'identity_failure' || outcome.status === 'captured') {
|
||||
// The model adapter must not return the raw response in the receipt. The
|
||||
// injected capture sink owns the private failure artifact and may throw.
|
||||
const response = typeof outcome.response === 'string' ? outcome.response : ''
|
||||
captureFailure({
|
||||
...receipt,
|
||||
status: 'captured',
|
||||
response_sha256: sha256(response),
|
||||
response_bytes: Buffer.byteLength(response),
|
||||
})
|
||||
receipt.status = 'captured'
|
||||
return { receipt, windows }
|
||||
}
|
||||
if (outcome.status === 'leaf_succeeded') {
|
||||
if (outcome.result === undefined) fail('missing_leaf_result', 'successful leaf did not provide a result')
|
||||
const index = windows.findIndex(window => window.key === target.key)
|
||||
windows[index] = { ...windows[index], status: 'checkpointed', result: outcome.result }
|
||||
receipt.status = 'leaf_succeeded'
|
||||
receipt.target_checkpoint_saved = true
|
||||
return { receipt, windows }
|
||||
}
|
||||
receipt.status = outcome.status
|
||||
return { receipt, windows }
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
VERSION,
|
||||
MAX_MODEL_CALLS,
|
||||
sha256,
|
||||
checkpointHash,
|
||||
targetIdempotencyKey,
|
||||
validateManifest,
|
||||
runDiagnosticContinuation,
|
||||
}
|
||||
Reference in New Issue
Block a user