blun-king-cli 9.1.567 → 9.1.569
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/agent-spine-plugin/.claude-plugin/marketplace.json +1 -1
- package/agent-spine-plugin/.claude-plugin/plugin.json +1 -1
- package/agent-spine-plugin/.codex-plugin/plugin.json +2 -1
- package/agent-spine-plugin/CHANGELOG.md +1581 -0
- package/agent-spine-plugin/README.md +30 -4
- package/agent-spine-plugin/blun.plugin.json +3 -3
- package/agent-spine-plugin/docs/acceptance.md +61 -0
- package/agent-spine-plugin/docs/assignment-continuation.md +48 -0
- package/agent-spine-plugin/docs/host-integration.md +178 -0
- package/agent-spine-plugin/docs/preflight-recall.md +69 -0
- package/agent-spine-plugin/docs/preservation-contract.md +53 -0
- package/agent-spine-plugin/docs/quality-gates.md +50 -0
- package/agent-spine-plugin/docs/releasing.md +85 -0
- package/agent-spine-plugin/docs/session-timeline.md +251 -0
- package/agent-spine-plugin/docs/source-roots.md +113 -0
- package/agent-spine-plugin/docs/structured-completion.md +67 -0
- package/agent-spine-plugin/docs/world-model.md +94 -0
- package/agent-spine-plugin/hooks/codex.json +2 -2
- package/agent-spine-plugin/hooks/hooks.json +1 -1
- package/agent-spine-plugin/hooks/version.json +1 -1
- package/agent-spine-plugin/package.json +13 -3
- package/agent-spine-plugin/scripts/check-codex-install.js +226 -0
- package/agent-spine-plugin/scripts/check-hosts.js +14 -5
- package/agent-spine-plugin/scripts/check-install-hook.js +226 -0
- package/agent-spine-plugin/scripts/check-install-selfstarter.js +154 -0
- package/agent-spine-plugin/scripts/check-install.js +478 -0
- package/agent-spine-plugin/scripts/check-line-budget.js +58 -0
- package/agent-spine-plugin/scripts/check-syntax.js +29 -0
- package/agent-spine-plugin/scripts/github-actions.js +11 -0
- package/agent-spine-plugin/scripts/hermetic-process.js +183 -0
- package/agent-spine-plugin/scripts/release-check.js +145 -0
- package/agent-spine-plugin/scripts/run-acceptance.js +19 -0
- package/agent-spine-plugin/scripts/run-checks.js +47 -0
- package/agent-spine-plugin/scripts/run-tests-hermetic.js +89 -0
- package/agent-spine-plugin/skills/agent-spine/SKILL.md +16 -2
- package/agent-spine-plugin/spine-example/1-identity.md +12 -0
- package/agent-spine-plugin/spine-example/2-voice.md +6 -0
- package/agent-spine-plugin/spine-example/3-conduct.md +8 -0
- package/agent-spine-plugin/spine-example/4-history.md +4 -0
- package/agent-spine-plugin/src/cli-agent.js +296 -0
- package/agent-spine-plugin/src/cli-attention.js +95 -0
- package/agent-spine-plugin/src/cli-autonomy.js +36 -0
- package/agent-spine-plugin/src/cli-common.js +71 -0
- package/agent-spine-plugin/src/cli-continuity.js +116 -0
- package/agent-spine-plugin/src/cli-core.js +128 -0
- package/agent-spine-plugin/src/cli-diagnostics.js +291 -0
- package/agent-spine-plugin/src/cli-host.js +21 -0
- package/agent-spine-plugin/src/cli-learning.js +305 -0
- package/agent-spine-plugin/src/cli-premortem.js +16 -0
- package/agent-spine-plugin/src/cli-sharing.js +230 -0
- package/agent-spine-plugin/src/cli.js +40 -1350
- package/agent-spine-plugin/src/codex-reader-launcher.js +182 -0
- package/agent-spine-plugin/src/hook.js +185 -567
- package/agent-spine-plugin/src/index.js +16 -2
- package/agent-spine-plugin/src/lib/acceptance.js +113 -11
- package/agent-spine-plugin/src/lib/action-lesson-recall.js +53 -0
- package/agent-spine-plugin/src/lib/attention-context.js +167 -0
- package/agent-spine-plugin/src/lib/attention-events.js +113 -0
- package/agent-spine-plugin/src/lib/attention-privacy.js +72 -0
- package/agent-spine-plugin/src/lib/attention-schema.js +164 -0
- package/agent-spine-plugin/src/lib/attention-storage.js +93 -0
- package/agent-spine-plugin/src/lib/attention.js +9 -600
- package/agent-spine-plugin/src/lib/audit-premortem.js +223 -0
- package/agent-spine-plugin/src/lib/audit.js +56 -6
- package/agent-spine-plugin/src/lib/autonomy-policy.js +110 -0
- package/agent-spine-plugin/src/lib/autonomy-store.js +202 -0
- package/agent-spine-plugin/src/lib/autonomy.js +8 -0
- package/agent-spine-plugin/src/lib/briefing.js +67 -4
- package/agent-spine-plugin/src/lib/catalog-document-read.js +51 -0
- package/agent-spine-plugin/src/lib/catalog.js +1 -1
- package/agent-spine-plugin/src/lib/codex-installation.js +231 -0
- package/agent-spine-plugin/src/lib/codex-skill-installation.js +211 -0
- package/agent-spine-plugin/src/lib/context.js +3 -1
- package/agent-spine-plugin/src/lib/delivery-agent-usage.js +224 -0
- package/agent-spine-plugin/src/lib/delivery-assignment.js +220 -0
- package/agent-spine-plugin/src/lib/delivery-command-actions.js +453 -0
- package/agent-spine-plugin/src/lib/delivery-knowledge.js +78 -0
- package/agent-spine-plugin/src/lib/delivery-premortem-binding.js +107 -0
- package/agent-spine-plugin/src/lib/delivery-premortem-closure.js +171 -0
- package/agent-spine-plugin/src/lib/delivery-premortem-codec.js +45 -0
- package/agent-spine-plugin/src/lib/delivery-premortem-correction.js +101 -0
- package/agent-spine-plugin/src/lib/delivery-premortem-file.js +21 -0
- package/agent-spine-plugin/src/lib/delivery-premortem-index.js +493 -0
- package/agent-spine-plugin/src/lib/delivery-premortem-inspection.js +37 -0
- package/agent-spine-plugin/src/lib/delivery-premortem-recovery.js +120 -0
- package/agent-spine-plugin/src/lib/delivery-premortem-rejection.js +65 -0
- package/agent-spine-plugin/src/lib/delivery-premortem-results.js +28 -0
- package/agent-spine-plugin/src/lib/delivery-premortem-session-guard.js +46 -0
- package/agent-spine-plugin/src/lib/delivery-premortem-write-ledger.js +285 -0
- package/agent-spine-plugin/src/lib/delivery-premortem.js +499 -0
- package/agent-spine-plugin/src/lib/delivery-shell-heredoc.js +115 -0
- package/agent-spine-plugin/src/lib/delivery-shell-substitutions.js +111 -0
- package/agent-spine-plugin/src/lib/delivery-shell-wrapper.js +64 -0
- package/agent-spine-plugin/src/lib/delivery-target.js +73 -0
- package/agent-spine-plugin/src/lib/delivery-verification.js +445 -0
- package/agent-spine-plugin/src/lib/documents.js +27 -5
- package/agent-spine-plugin/src/lib/filesystem-retry.js +2 -0
- package/agent-spine-plugin/src/lib/gateway-common.js +68 -0
- package/agent-spine-plugin/src/lib/gateway-control.js +302 -0
- package/agent-spine-plugin/src/lib/gateway-delivery.js +103 -0
- package/agent-spine-plugin/src/lib/gateway-execution.js +350 -0
- package/agent-spine-plugin/src/lib/gateway-host-lifecycle.js +185 -0
- package/agent-spine-plugin/src/lib/gateway-inspection.js +85 -0
- package/agent-spine-plugin/src/lib/gateway-knowledge.js +129 -0
- package/agent-spine-plugin/src/lib/gateway-policy-provenance.js +197 -0
- package/agent-spine-plugin/src/lib/gateway-premortem-disposition.js +82 -0
- package/agent-spine-plugin/src/lib/gateway-premortem.js +363 -0
- package/agent-spine-plugin/src/lib/gateway-runs.js +300 -0
- package/agent-spine-plugin/src/lib/gateway-runtime-identity.js +31 -0
- package/agent-spine-plugin/src/lib/gateway-runtime-records.js +21 -0
- package/agent-spine-plugin/src/lib/gateway-runtime.js +18 -1623
- package/agent-spine-plugin/src/lib/gateway-state-transaction.js +356 -0
- package/agent-spine-plugin/src/lib/gateway-state.js +342 -0
- package/agent-spine-plugin/src/lib/hook-artifact-guards.js +356 -0
- package/agent-spine-plugin/src/lib/hook-audit.js +16 -2
- package/agent-spine-plugin/src/lib/hook-briefing-use.js +68 -0
- package/agent-spine-plugin/src/lib/hook-context.js +424 -0
- package/agent-spine-plugin/src/lib/hook-final-message.js +26 -0
- package/agent-spine-plugin/src/lib/hook-input.js +27 -0
- package/agent-spine-plugin/src/lib/hook-output.js +140 -0
- package/agent-spine-plugin/src/lib/hook-premortem.js +257 -0
- package/agent-spine-plugin/src/lib/hook-process-advisory.js +37 -0
- package/agent-spine-plugin/src/lib/hook-protection.js +95 -0
- package/agent-spine-plugin/src/lib/hook-stop-verification.js +84 -0
- package/agent-spine-plugin/src/lib/hook-timeline.js +91 -0
- package/agent-spine-plugin/src/lib/identifier-analysis.js +446 -0
- package/agent-spine-plugin/src/lib/indexed-memory.js +23 -6
- package/agent-spine-plugin/src/lib/knowledge-evidence.js +431 -0
- package/agent-spine-plugin/src/lib/learning-applications.js +441 -0
- package/agent-spine-plugin/src/lib/learning-candidates.js +274 -0
- package/agent-spine-plugin/src/lib/learning-context.js +130 -0
- package/agent-spine-plugin/src/lib/learning-delivery-contracts.js +310 -0
- package/agent-spine-plugin/src/lib/learning-evaluation-contracts.js +350 -0
- package/agent-spine-plugin/src/lib/learning-evaluation-registration.js +372 -0
- package/agent-spine-plugin/src/lib/learning-evaluation-revocation.js +292 -0
- package/agent-spine-plugin/src/lib/learning-evidence-contracts.js +321 -0
- package/agent-spine-plugin/src/lib/learning-findings.js +458 -0
- package/agent-spine-plugin/src/lib/learning-measurement-contracts.js +285 -0
- package/agent-spine-plugin/src/lib/learning-measurements.js +265 -0
- package/agent-spine-plugin/src/lib/learning-outcome-contracts.js +165 -0
- package/agent-spine-plugin/src/lib/learning-outcomes.js +343 -0
- package/agent-spine-plugin/src/lib/learning-reconciliation.js +290 -0
- package/agent-spine-plugin/src/lib/learning-retry-contracts.js +188 -0
- package/agent-spine-plugin/src/lib/learning-schema.js +229 -0
- package/agent-spine-plugin/src/lib/learning-scope-targets.js +424 -0
- package/agent-spine-plugin/src/lib/learning-state-upgrade.js +477 -0
- package/agent-spine-plugin/src/lib/learning-status-configuration.js +476 -0
- package/agent-spine-plugin/src/lib/learning-storage.js +203 -0
- package/agent-spine-plugin/src/lib/learning-trial-recovery.js +218 -0
- package/agent-spine-plugin/src/lib/learning-validation-contracts.js +375 -0
- package/agent-spine-plugin/src/lib/learning-validation-renewal.js +298 -0
- package/agent-spine-plugin/src/lib/learning-validation-runtime.js +234 -0
- package/agent-spine-plugin/src/lib/learning.js +36 -6923
- package/agent-spine-plugin/src/lib/lesson-recall-session.js +172 -0
- package/agent-spine-plugin/src/lib/mcp-autonomy-tools.js +37 -0
- package/agent-spine-plugin/src/lib/mcp-delivery-completion.js +124 -0
- package/agent-spine-plugin/src/lib/mcp-delivery-tools.js +45 -0
- package/agent-spine-plugin/src/lib/mcp-premortem.js +68 -0
- package/agent-spine-plugin/src/lib/mcp-runtime.js +269 -0
- package/agent-spine-plugin/src/lib/mcp-source-context.js +51 -0
- package/agent-spine-plugin/src/lib/mcp-timeline-tools.js +164 -0
- package/agent-spine-plugin/src/lib/mcp-world-tools.js +52 -0
- package/agent-spine-plugin/src/lib/owned-file-lock.js +30 -10
- package/agent-spine-plugin/src/lib/project-portfolio.js +176 -0
- package/agent-spine-plugin/src/lib/selfstarter-core.js +382 -0
- package/agent-spine-plugin/src/lib/selfstarter-jobs.js +149 -0
- package/agent-spine-plugin/src/lib/selfstarter-lease.js +204 -0
- package/agent-spine-plugin/src/lib/selfstarter-policy.js +90 -0
- package/agent-spine-plugin/src/lib/selfstarter-workspace.js +111 -0
- package/agent-spine-plugin/src/lib/selfstarter.js +11 -911
- package/agent-spine-plugin/src/lib/session-timeline-auth.js +316 -0
- package/agent-spine-plugin/src/lib/session-timeline-codex.js +58 -0
- package/agent-spine-plugin/src/lib/session-timeline-contract.js +48 -0
- package/agent-spine-plugin/src/lib/session-timeline-enrollment-source.js +41 -0
- package/agent-spine-plugin/src/lib/session-timeline-enrollment-storage.js +132 -0
- package/agent-spine-plugin/src/lib/session-timeline-enrollment-transport.js +17 -0
- package/agent-spine-plugin/src/lib/session-timeline-enrollment.js +500 -0
- package/agent-spine-plugin/src/lib/session-timeline-event-extract.js +157 -0
- package/agent-spine-plugin/src/lib/session-timeline-host-origin.js +74 -0
- package/agent-spine-plugin/src/lib/session-timeline-host-receipt.js +117 -0
- package/agent-spine-plugin/src/lib/session-timeline-invocation.js +201 -0
- package/agent-spine-plugin/src/lib/session-timeline-king.js +79 -0
- package/agent-spine-plugin/src/lib/session-timeline-prior.js +59 -0
- package/agent-spine-plugin/src/lib/session-timeline-provider.js +34 -0
- package/agent-spine-plugin/src/lib/session-timeline-query.js +55 -0
- package/agent-spine-plugin/src/lib/session-timeline-results.js +31 -0
- package/agent-spine-plugin/src/lib/session-timeline-root.js +11 -0
- package/agent-spine-plugin/src/lib/session-timeline-search.js +82 -0
- package/agent-spine-plugin/src/lib/session-timeline-sid-acl.js +217 -0
- package/agent-spine-plugin/src/lib/session-timeline-source.js +83 -0
- package/agent-spine-plugin/src/lib/session-timeline-state.js +45 -0
- package/agent-spine-plugin/src/lib/session-timeline-transport.js +50 -0
- package/agent-spine-plugin/src/lib/session-timeline-windows-acl.js +148 -0
- package/agent-spine-plugin/src/lib/session-timeline.js +453 -0
- package/agent-spine-plugin/src/lib/source-roots.js +69 -136
- package/agent-spine-plugin/src/lib/source-tree-scan.js +178 -0
- package/agent-spine-plugin/src/lib/task-knowledge-context.js +78 -0
- package/agent-spine-plugin/src/lib/timeline-tool-guard.js +202 -0
- package/agent-spine-plugin/src/lib/world-knowledge.js +249 -0
- package/agent-spine-plugin/src/lib/world-model.js +278 -0
- package/agent-spine-plugin/src/mcp.js +20 -161
- package/agent-spine-plugin/src/version.js +1 -1
- package/agent-spine-plugin/src/worker.js +22 -5
- package/bin/agent-resume-snapshot.cjs +2 -2
- package/bin/agentspine-king-goal-inbox.mjs +111 -0
- package/bin/agentspine-king-goal-intake.mjs +106 -0
- package/bin/baseline-skill-performance-policy.cjs +1 -16
- package/bin/core-bootstrap.js +2 -0
- package/bin/curiosity-scout-policy.cjs +5 -1
- package/bin/input-draft-persistence.cjs +2 -2
- package/bin/king-tui-function-contract.json +33 -0
- package/bin/launcher-restart-policy.cjs +150 -0
- package/bin/launcher-runtime.js +56 -44
- package/bin/managed-context-startup-policy.cjs +27 -0
- package/bin/managed-plugin-selection.cjs +116 -0
- package/bin/mistake-relevance-policy.cjs +1 -1
- package/bin/observer-hooks.cjs +14 -0
- package/bin/oversized-context-offload-policy.cjs +86 -0
- package/bin/plugin-bootstrap.js +7 -40
- package/bin/proactive-compaction-policy.cjs +1 -1
- package/bin/provider-model-refresh-deadline.cjs +53 -0
- package/bin/provider-model-refresh-policy.cjs +107 -0
- package/bin/release-artifact-freeze-policy.cjs +30 -0
- package/bin/repeated-user-message-projection.cjs +3 -126
- package/bin/research-page-result.cjs +74 -0
- package/bin/runtime-exit-ledger.cjs +1 -0
- package/bin/session-compaction-policy.cjs +84 -0
- package/bin/skill-listing-performance-policy.cjs +2 -2
- package/bin/standard-tools-bootstrap.js +0 -37
- package/bin/subagent-skill-policy.cjs +3 -1
- package/bin/telegram-approval-relay.cjs +12 -7
- package/bin/telegram-private-conversation-policy.cjs +3 -2
- package/bin/telegram-queue-handoff-policy.cjs +24 -0
- package/bin/thinking-activity-status-policy.cjs +1 -1
- package/bin/thinking-only-guard.cjs +16 -12
- package/bin/tool-call-loop-policy.cjs +0 -2
- package/bin/tool-result-offload-policy.cjs +11 -2
- package/bin/tui-functional-contract.cjs +55 -0
- package/bin/update-notice.js +18 -14
- package/bin/user-message-offload-policy.cjs +1 -1
- package/bin/user-prompt-hook-origin-policy.cjs +34 -0
- package/bin/windows-node-crash-dump.cjs +110 -0
- package/blun.mjs +2517 -1048
- package/codebase-index/codebase_index.py +4 -3
- package/package.json +3 -17
- package/standard-skills/research-evidence/SKILL.md +39 -0
- package/standard-skills/research-evidence/references/evidence-format.md +82 -0
- package/standard-skills/research-evidence/scripts/evidence-collection.cjs +254 -0
- package/standard-skills/research-evidence/scripts/score-report.cjs +112 -0
- package/standard-skills/web-lesen/SKILL.md +37 -22
- package/standard-skills/web-lesen/scripts/crawl_public.py +376 -0
- package/telegram-plugin/DELIVERY.md +36 -0
- package/telegram-plugin/bin/telegram-approval-relay.cjs +13 -7
- package/telegram-plugin/bin/telegram-launcher-status-queue.cjs +122 -0
- package/telegram-plugin/bin/telegram-private-conversation-policy.cjs +3 -2
- package/telegram-plugin/bin/telegram-reply-parts.cjs +149 -0
- package/telegram-plugin/dist/bridge.mjs +7 -56
- package/telegram-plugin/dist/mcp-server.mjs +33 -4
- package/agent-spine-plugin/skill/SKILL.md +0 -76
- package/bin/mnemo-connect-heartbeat.cjs +0 -204
- package/bin/mnemo-tool-agent-policy.cjs +0 -22
- package/telegram-plugin/bin/telegram-mnemo-capture.cjs +0 -297
|
@@ -0,0 +1,477 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DIGEST_RE, PROTECTED_LESSON_RE, LINEAGE_EVALUATIONS, ROOT_BOUND_EVALUATIONS, REGISTRY_BOUND_EVALUATIONS, INITIAL_TRIAL_EVALUATIONS,
|
|
3
|
+
TARGET_BOUND_EVALUATIONS, DEADLINE_BOUND_EVALUATIONS, TRIAL_RETRY_EVALUATIONS, STALENESS_BOUND_EVALUATIONS, CANDIDATE_ADMISSION_EVALUATIONS, CANDIDATE_EVIDENCE_LINEAGE_EVALUATIONS,
|
|
4
|
+
DELIVERABLE_APPLICATIONS, INITIAL_TRIAL_APPLICATIONS, TARGET_BOUND_APPLICATIONS, DEADLINE_BOUND_APPLICATIONS, defaults
|
|
5
|
+
} from "./learning-schema.js";
|
|
6
|
+
import {
|
|
7
|
+
normalizeStoredScope, scopeContains, exactScope, digest, learningTargetMatchesCandidate, storedEvidenceRevocationStructure,
|
|
8
|
+
evidenceRevocationMatchesState, storedOutcomeStructure, storedMeasurementStructure, storedMeasurementRevocationStructure, measurementRevocationMatchesState, measurementRunDigest,
|
|
9
|
+
evaluatorRootRunDigest, storedEvaluatorRecordStructure, storedEvaluationBindingStructure, storedEvaluationRevocationStructure, evaluationRevocationMatchesState
|
|
10
|
+
} from "./learning-scope-targets.js";
|
|
11
|
+
import {
|
|
12
|
+
revalidationWindowMatchesState, storedValidationLeaseStructure, validationLeaseMatchesState
|
|
13
|
+
} from "./learning-validation-contracts.js";
|
|
14
|
+
import {
|
|
15
|
+
storedValidationRevocationStructure, validationRevocationMatchesState
|
|
16
|
+
} from "./learning-validation-runtime.js";
|
|
17
|
+
import {
|
|
18
|
+
storedMeasurementLineageStructure, storedEvidenceSourceAttestationRevocationStructure, evidenceSourceAttestationRevocationMatchesState
|
|
19
|
+
} from "./learning-measurement-contracts.js";
|
|
20
|
+
import {
|
|
21
|
+
storedCandidateEvidenceLineageStructure, candidateEvidenceLineageMatchesEvaluation, candidateAdmissionMatches
|
|
22
|
+
} from "./learning-evidence-contracts.js";
|
|
23
|
+
import {
|
|
24
|
+
storedEvaluationStructure, storedApplicationStructure, initialAdmissionsMatchState, storedTrialFailureStructure, trialFailureMatchesState, storedTrialFailureRevocationStructure,
|
|
25
|
+
trialFailureRevocationMatchesState
|
|
26
|
+
} from "./learning-evaluation-contracts.js";
|
|
27
|
+
import {
|
|
28
|
+
trialRetryMatchesState, storedTrialRetryExhaustionStructure, trialRetryExhaustionMatchesState, revalidationAdmissionsMatchState
|
|
29
|
+
} from "./learning-retry-contracts.js";
|
|
30
|
+
import {
|
|
31
|
+
storedDeliveryStructure, storedApplicationRevocationStructure, applicationRevocationMatchesState, storedDeliveryRevocationStructure, deliveryRevocationMatchesState, storedOutcomeRevocationStructure,
|
|
32
|
+
outcomeRevocationMatchesState
|
|
33
|
+
} from "./learning-delivery-contracts.js";
|
|
34
|
+
|
|
35
|
+
export function normalizeState(value, root) {
|
|
36
|
+
if (!value || typeof value !== "object" || Array.isArray(value)
|
|
37
|
+
|| value.schema !== "agentspine.learning/v1" || value.root !== root
|
|
38
|
+
|| !value.config || typeof value.config !== "object" || Array.isArray(value.config)
|
|
39
|
+
|| !Array.isArray(value.candidates) || !value.candidates.every((item) => item && typeof item === "object" && Array.isArray(item.evidence))
|
|
40
|
+
|| (value.outcomes !== undefined && (!Array.isArray(value.outcomes) || !value.outcomes.every((item) => item && typeof item === "object")))
|
|
41
|
+
|| (value.measurements !== undefined && (!Array.isArray(value.measurements) || !value.measurements.every((item) => item && typeof item === "object")))
|
|
42
|
+
|| (value.measurementLineage !== undefined && (!Array.isArray(value.measurementLineage) || !value.measurementLineage.every((item) => item && typeof item === "object")))
|
|
43
|
+
|| (value.candidateEvidenceLineage !== undefined && (!Array.isArray(value.candidateEvidenceLineage)
|
|
44
|
+
|| !value.candidateEvidenceLineage.every((item) => item && typeof item === "object")))
|
|
45
|
+
|| (value.applications !== undefined && (!Array.isArray(value.applications) || !value.applications.every((item) => item && typeof item === "object")))
|
|
46
|
+
|| (value.deliveries !== undefined && (!Array.isArray(value.deliveries) || !value.deliveries.every((item) => item && typeof item === "object")))
|
|
47
|
+
|| (value.evaluations !== undefined && (!Array.isArray(value.evaluations) || !value.evaluations.every((item) => item && typeof item === "object")))
|
|
48
|
+
|| (value.evaluatorRegistry !== undefined && (!Array.isArray(value.evaluatorRegistry) || !value.evaluatorRegistry.every((item) => item && typeof item === "object")))
|
|
49
|
+
|| (value.evaluationBindings !== undefined && (!Array.isArray(value.evaluationBindings) || !value.evaluationBindings.every((item) => item && typeof item === "object")))
|
|
50
|
+
|| (value.validationLeases !== undefined && (!Array.isArray(value.validationLeases) || !value.validationLeases.every((item) => item && typeof item === "object")))
|
|
51
|
+
|| (value.trialFailures !== undefined && (!Array.isArray(value.trialFailures) || !value.trialFailures.every((item) => item && typeof item === "object")))
|
|
52
|
+
|| (value.trialFailureRevocations !== undefined && (!Array.isArray(value.trialFailureRevocations)
|
|
53
|
+
|| !value.trialFailureRevocations.every((item) => item && typeof item === "object")))
|
|
54
|
+
|| (value.trialRetryExhaustions !== undefined && (!Array.isArray(value.trialRetryExhaustions)
|
|
55
|
+
|| !value.trialRetryExhaustions.every((item) => item && typeof item === "object")))
|
|
56
|
+
|| (value.evaluationRevocations !== undefined && (!Array.isArray(value.evaluationRevocations)
|
|
57
|
+
|| !value.evaluationRevocations.every((item) => item && typeof item === "object")))
|
|
58
|
+
|| (value.evidenceSourceAttestationRevocations !== undefined
|
|
59
|
+
&& (!Array.isArray(value.evidenceSourceAttestationRevocations)
|
|
60
|
+
|| !value.evidenceSourceAttestationRevocations.every((item) => item && typeof item === "object")))
|
|
61
|
+
|| (value.validationRevocations !== undefined && (!Array.isArray(value.validationRevocations)
|
|
62
|
+
|| !value.validationRevocations.every((item) => item && typeof item === "object")))
|
|
63
|
+
|| (value.evidenceRevocations !== undefined && (!Array.isArray(value.evidenceRevocations)
|
|
64
|
+
|| !value.evidenceRevocations.every((item) => item && typeof item === "object")))
|
|
65
|
+
|| (value.measurementRevocations !== undefined && (!Array.isArray(value.measurementRevocations)
|
|
66
|
+
|| !value.measurementRevocations.every((item) => item && typeof item === "object")))
|
|
67
|
+
|| (value.applicationRevocations !== undefined && (!Array.isArray(value.applicationRevocations)
|
|
68
|
+
|| !value.applicationRevocations.every((item) => item && typeof item === "object")))
|
|
69
|
+
|| (value.deliveryRevocations !== undefined && (!Array.isArray(value.deliveryRevocations)
|
|
70
|
+
|| !value.deliveryRevocations.every((item) => item && typeof item === "object")))
|
|
71
|
+
|| (value.outcomeRevocations !== undefined && (!Array.isArray(value.outcomeRevocations)
|
|
72
|
+
|| !value.outcomeRevocations.every((item) => item && typeof item === "object")))
|
|
73
|
+
|| !Array.isArray(value.history) || !value.history.every((item) => item && typeof item === "object")) {
|
|
74
|
+
throw new Error("learning state structure is invalid; run the audit before learning");
|
|
75
|
+
}
|
|
76
|
+
const normalized = {
|
|
77
|
+
...value,
|
|
78
|
+
config: { ...defaults(), ...value.config },
|
|
79
|
+
candidates: value.candidates.map((candidate) => ({
|
|
80
|
+
...candidate,
|
|
81
|
+
scope: normalizeStoredScope(candidate.scope, candidate.subjectId, candidate.groupId),
|
|
82
|
+
requiresLocalReview: candidate.requiresLocalReview ?? PROTECTED_LESSON_RE.test(candidate.claim || "")
|
|
83
|
+
})),
|
|
84
|
+
outcomes: value.outcomes || [],
|
|
85
|
+
measurements: value.measurements || [],
|
|
86
|
+
measurementLineage: value.measurementLineage || [],
|
|
87
|
+
candidateEvidenceLineage: value.candidateEvidenceLineage || [],
|
|
88
|
+
applications: value.applications || [],
|
|
89
|
+
deliveries: value.deliveries || [],
|
|
90
|
+
evaluations: value.evaluations || [],
|
|
91
|
+
evaluatorRegistry: value.evaluatorRegistry || [],
|
|
92
|
+
evaluationBindings: value.evaluationBindings || [],
|
|
93
|
+
validationLeases: value.validationLeases || [],
|
|
94
|
+
trialFailures: value.trialFailures || [],
|
|
95
|
+
trialFailureRevocations: value.trialFailureRevocations || [],
|
|
96
|
+
trialRetryExhaustions: value.trialRetryExhaustions || [],
|
|
97
|
+
evaluationRevocations: value.evaluationRevocations || [],
|
|
98
|
+
evidenceSourceAttestationRevocations: value.evidenceSourceAttestationRevocations || [],
|
|
99
|
+
validationRevocations: value.validationRevocations || [],
|
|
100
|
+
evidenceRevocations: value.evidenceRevocations || [],
|
|
101
|
+
measurementRevocations: value.measurementRevocations || [],
|
|
102
|
+
applicationRevocations: value.applicationRevocations || [],
|
|
103
|
+
deliveryRevocations: value.deliveryRevocations || [],
|
|
104
|
+
outcomeRevocations: value.outcomeRevocations || []
|
|
105
|
+
};
|
|
106
|
+
if (normalized.outcomes.some((receipt) => !storedOutcomeStructure(receipt))) {
|
|
107
|
+
throw new Error("learning outcome state is invalid; run the audit before learning");
|
|
108
|
+
}
|
|
109
|
+
if (normalized.measurements.some((receipt) => !storedMeasurementStructure(receipt))) {
|
|
110
|
+
throw new Error("learning measurement state is invalid; run the audit before learning");
|
|
111
|
+
}
|
|
112
|
+
if (normalized.measurementLineage.some((receipt) => !storedMeasurementLineageStructure(receipt))) {
|
|
113
|
+
throw new Error("learning measurement lineage state is invalid; run the audit before learning");
|
|
114
|
+
}
|
|
115
|
+
if (normalized.candidateEvidenceLineage.some((receipt) => !storedCandidateEvidenceLineageStructure(receipt))) {
|
|
116
|
+
throw new Error("learning candidate evidence lineage state is invalid; run the audit before learning");
|
|
117
|
+
}
|
|
118
|
+
const evidenceLineageDigests = new Set();
|
|
119
|
+
const evidenceLineageIndependence = new Set();
|
|
120
|
+
for (const receipt of normalized.candidateEvidenceLineage) {
|
|
121
|
+
const evidenceKey = `${receipt.scopeDigest}\0${receipt.evidenceDigest}`;
|
|
122
|
+
const independenceKey = `${receipt.scopeDigest}\0${receipt.independenceDigest}`;
|
|
123
|
+
if (evidenceLineageDigests.has(evidenceKey) || evidenceLineageIndependence.has(independenceKey)) {
|
|
124
|
+
throw new Error("learning candidate evidence lineage is replayed; run the audit before learning");
|
|
125
|
+
}
|
|
126
|
+
evidenceLineageDigests.add(evidenceKey);
|
|
127
|
+
evidenceLineageIndependence.add(independenceKey);
|
|
128
|
+
}
|
|
129
|
+
if (normalized.applications.some((receipt) => !storedApplicationStructure(receipt))) {
|
|
130
|
+
throw new Error("learning application state is invalid; run the audit before learning");
|
|
131
|
+
}
|
|
132
|
+
if (normalized.deliveries.some((receipt) => !storedDeliveryStructure(receipt))) {
|
|
133
|
+
throw new Error("learning delivery state is invalid; run the audit before learning");
|
|
134
|
+
}
|
|
135
|
+
if (normalized.evaluations.some((contract) => !storedEvaluationStructure(contract))) {
|
|
136
|
+
throw new Error("learning evaluation state is invalid; run the audit before learning");
|
|
137
|
+
}
|
|
138
|
+
if (normalized.evaluations.some((contract) => TARGET_BOUND_EVALUATIONS.has(contract.schema)
|
|
139
|
+
&& !learningTargetMatchesCandidate(contract.target,
|
|
140
|
+
normalized.candidates.find((candidate) => candidate.id === contract.learningId)))) {
|
|
141
|
+
throw new Error("learning evaluation target is invalid or changed; run the audit before learning");
|
|
142
|
+
}
|
|
143
|
+
if (normalized.evaluations.some((contract) => CANDIDATE_ADMISSION_EVALUATIONS.has(contract.schema)
|
|
144
|
+
&& !candidateAdmissionMatches(contract,
|
|
145
|
+
normalized.candidates.find((candidate) => candidate.id === contract.learningId)))) {
|
|
146
|
+
throw new Error("learning candidate admission is invalid or changed; run the audit before learning");
|
|
147
|
+
}
|
|
148
|
+
if (normalized.evaluations.some((contract) => CANDIDATE_EVIDENCE_LINEAGE_EVALUATIONS.has(contract.schema)
|
|
149
|
+
&& !candidateEvidenceLineageMatchesEvaluation(normalized, contract))) {
|
|
150
|
+
throw new Error("learning candidate evidence lineage binding is invalid; run the audit before learning");
|
|
151
|
+
}
|
|
152
|
+
if (normalized.evaluatorRegistry.some((record) => !storedEvaluatorRecordStructure(record))) {
|
|
153
|
+
throw new Error("learning evaluator registry is invalid; run the audit before learning");
|
|
154
|
+
}
|
|
155
|
+
if (new Set(normalized.evaluatorRegistry.map((record) => record.id)).size !== normalized.evaluatorRegistry.length
|
|
156
|
+
|| new Set(normalized.evaluatorRegistry.map((record) => record.principalDigest)).size !== normalized.evaluatorRegistry.length) {
|
|
157
|
+
throw new Error("learning evaluator registry contains duplicate identities or roots; run the audit before learning");
|
|
158
|
+
}
|
|
159
|
+
if (normalized.evaluationBindings.some((binding) => !storedEvaluationBindingStructure(binding)
|
|
160
|
+
|| !normalized.evaluations.some((contract) => contract.id === binding.evaluationId
|
|
161
|
+
&& contract.digest === binding.evaluationDigest
|
|
162
|
+
&& contract.evaluatorRoots?.length === binding.evaluators.length
|
|
163
|
+
&& binding.evaluators.every((entry) => contract.evaluatorRoots.some((root) => root.evaluatorId === entry.evaluatorId
|
|
164
|
+
&& root.principalDigest === entry.principalDigest))))) {
|
|
165
|
+
throw new Error("learning evaluator binding state is invalid; run the audit before learning");
|
|
166
|
+
}
|
|
167
|
+
if (new Set(normalized.evaluationBindings.map((binding) => binding.evaluationId)).size !== normalized.evaluationBindings.length) {
|
|
168
|
+
throw new Error("learning evaluator binding is duplicated; run the audit before learning");
|
|
169
|
+
}
|
|
170
|
+
if (normalized.evaluations.some((contract) => REGISTRY_BOUND_EVALUATIONS.has(contract.schema)
|
|
171
|
+
&& !normalized.evaluationBindings.some((binding) => binding.evaluationId === contract.id
|
|
172
|
+
&& binding.evaluationDigest === contract.digest))) {
|
|
173
|
+
throw new Error("learning evaluator binding is missing; run the audit before learning");
|
|
174
|
+
}
|
|
175
|
+
if (normalized.validationLeases.some((lease) => !storedValidationLeaseStructure(lease))) {
|
|
176
|
+
throw new Error("learning validation lease state is invalid; run the audit before learning");
|
|
177
|
+
}
|
|
178
|
+
if (new Set(normalized.validationLeases.map((lease) => lease.id)).size !== normalized.validationLeases.length
|
|
179
|
+
|| new Set(normalized.validationLeases.map((lease) => lease.learningId)).size !== normalized.validationLeases.length) {
|
|
180
|
+
throw new Error("learning validation lease is duplicated; run the audit before learning");
|
|
181
|
+
}
|
|
182
|
+
if (normalized.trialFailures.some((receipt) => !storedTrialFailureStructure(receipt)
|
|
183
|
+
|| !trialFailureMatchesState(normalized, receipt))
|
|
184
|
+
|| new Set(normalized.trialFailures.map((entry) => entry.applicationId)).size !== normalized.trialFailures.length) {
|
|
185
|
+
throw new Error("learning trial failure state is invalid; run the audit before learning");
|
|
186
|
+
}
|
|
187
|
+
if (normalized.trialFailureRevocations.some((receipt) => !storedTrialFailureRevocationStructure(receipt)
|
|
188
|
+
|| !trialFailureRevocationMatchesState(normalized, receipt))
|
|
189
|
+
|| new Set(normalized.trialFailureRevocations.map((entry) => entry.trialFailureId)).size
|
|
190
|
+
!== normalized.trialFailureRevocations.length) {
|
|
191
|
+
throw new Error("learning trial failure revocation state is invalid; run the audit before learning");
|
|
192
|
+
}
|
|
193
|
+
const retryContracts = normalized.evaluations.filter((contract) => TRIAL_RETRY_EVALUATIONS.has(contract.schema));
|
|
194
|
+
if (retryContracts.some((contract) => !trialRetryMatchesState(normalized, contract))
|
|
195
|
+
|| new Set(retryContracts.map((contract) => contract.retry.trialFailureRevocationId)).size
|
|
196
|
+
!== retryContracts.length) {
|
|
197
|
+
throw new Error("learning trial retry state is invalid; run the audit before learning");
|
|
198
|
+
}
|
|
199
|
+
if (normalized.trialRetryExhaustions.some((receipt) => !storedTrialRetryExhaustionStructure(receipt)
|
|
200
|
+
|| !trialRetryExhaustionMatchesState(normalized, receipt))
|
|
201
|
+
|| new Set(normalized.trialRetryExhaustions.map((entry) => entry.correctiveEvaluationId)).size
|
|
202
|
+
!== normalized.trialRetryExhaustions.length
|
|
203
|
+
|| new Set(normalized.trialRetryExhaustions.map((entry) => entry.trialFailureId)).size
|
|
204
|
+
!== normalized.trialRetryExhaustions.length) {
|
|
205
|
+
throw new Error("learning trial retry exhaustion state is invalid; run the audit before learning");
|
|
206
|
+
}
|
|
207
|
+
if (normalized.evaluationRevocations.some((receipt) => !storedEvaluationRevocationStructure(receipt)
|
|
208
|
+
|| !evaluationRevocationMatchesState(normalized, receipt))
|
|
209
|
+
|| new Set(normalized.evaluationRevocations.map((entry) => entry.evaluationId)).size
|
|
210
|
+
!== normalized.evaluationRevocations.length) {
|
|
211
|
+
throw new Error("learning evaluation revocation state is invalid; run the audit before learning");
|
|
212
|
+
}
|
|
213
|
+
if (normalized.evidenceSourceAttestationRevocations.some((receipt) =>
|
|
214
|
+
!storedEvidenceSourceAttestationRevocationStructure(receipt)
|
|
215
|
+
|| !evidenceSourceAttestationRevocationMatchesState(normalized, receipt))
|
|
216
|
+
|| new Set(normalized.evidenceSourceAttestationRevocations.map((entry) =>
|
|
217
|
+
`${entry.evaluationId}\0${entry.evidenceDigest}`)).size
|
|
218
|
+
!== normalized.evidenceSourceAttestationRevocations.length) {
|
|
219
|
+
throw new Error("learning evidence source attestation revocation state is invalid; run the audit before learning");
|
|
220
|
+
}
|
|
221
|
+
if (normalized.validationRevocations.some((receipt) => !storedValidationRevocationStructure(receipt)
|
|
222
|
+
|| !validationRevocationMatchesState(normalized, receipt))
|
|
223
|
+
|| new Set(normalized.validationRevocations.map((entry) => entry.validationLeaseId)).size
|
|
224
|
+
!== normalized.validationRevocations.length) {
|
|
225
|
+
throw new Error("learning validation revocation state is invalid; run the audit before learning");
|
|
226
|
+
}
|
|
227
|
+
if (normalized.evidenceRevocations.some((receipt) => !storedEvidenceRevocationStructure(receipt)
|
|
228
|
+
|| !evidenceRevocationMatchesState(normalized, receipt))
|
|
229
|
+
|| new Set(normalized.evidenceRevocations.map((entry) => `${entry.learningId}\0${entry.evidenceId}`)).size
|
|
230
|
+
!== normalized.evidenceRevocations.length) {
|
|
231
|
+
throw new Error("learning evidence revocation state is invalid; run the audit before learning");
|
|
232
|
+
}
|
|
233
|
+
if (normalized.measurementRevocations.some((receipt) => !storedMeasurementRevocationStructure(receipt)
|
|
234
|
+
|| !measurementRevocationMatchesState(normalized, receipt))
|
|
235
|
+
|| new Set(normalized.measurementRevocations.map((entry) => entry.measurementId)).size
|
|
236
|
+
!== normalized.measurementRevocations.length) {
|
|
237
|
+
throw new Error("learning measurement revocation state is invalid; run the audit before learning");
|
|
238
|
+
}
|
|
239
|
+
if (normalized.applicationRevocations.some((receipt) => !storedApplicationRevocationStructure(receipt)
|
|
240
|
+
|| !applicationRevocationMatchesState(normalized, receipt))
|
|
241
|
+
|| new Set(normalized.applicationRevocations.map((entry) => entry.applicationId)).size
|
|
242
|
+
!== normalized.applicationRevocations.length) {
|
|
243
|
+
throw new Error("learning application revocation state is invalid; run the audit before learning");
|
|
244
|
+
}
|
|
245
|
+
if (normalized.deliveryRevocations.some((receipt) => !storedDeliveryRevocationStructure(receipt)
|
|
246
|
+
|| !deliveryRevocationMatchesState(normalized, receipt))
|
|
247
|
+
|| new Set(normalized.deliveryRevocations.map((entry) => entry.deliveryId)).size
|
|
248
|
+
!== normalized.deliveryRevocations.length) {
|
|
249
|
+
throw new Error("learning delivery revocation state is invalid; run the audit before learning");
|
|
250
|
+
}
|
|
251
|
+
if (normalized.outcomeRevocations.some((receipt) => !storedOutcomeRevocationStructure(receipt)
|
|
252
|
+
|| !outcomeRevocationMatchesState(normalized, receipt))
|
|
253
|
+
|| new Set(normalized.outcomeRevocations.map((entry) => entry.outcomeId)).size
|
|
254
|
+
!== normalized.outcomeRevocations.length) {
|
|
255
|
+
throw new Error("learning outcome revocation state is invalid; run the audit before learning");
|
|
256
|
+
}
|
|
257
|
+
if (normalized.candidates.some((candidate) => candidate.promotion?.canary?.revalidation
|
|
258
|
+
&& !revalidationWindowMatchesState(normalized, candidate))) {
|
|
259
|
+
throw new Error("learning revalidation window state is invalid; run the audit before learning");
|
|
260
|
+
}
|
|
261
|
+
if (!revalidationAdmissionsMatchState(normalized)) {
|
|
262
|
+
throw new Error("learning revalidation admission state is invalid; run the audit before learning");
|
|
263
|
+
}
|
|
264
|
+
if (!initialAdmissionsMatchState(normalized)) {
|
|
265
|
+
throw new Error("learning initial trial admission state is invalid; run the audit before learning");
|
|
266
|
+
}
|
|
267
|
+
if (normalized.outcomes.some((receipt) => {
|
|
268
|
+
const candidate = normalized.candidates.find((item) => item.id === receipt.learningId);
|
|
269
|
+
return !candidate || !scopeContains(candidate.scope, receipt.scope);
|
|
270
|
+
})) throw new Error("learning outcome scope is invalid; run the audit before learning");
|
|
271
|
+
if (normalized.applications.some((receipt) => {
|
|
272
|
+
const candidate = normalized.candidates.find((item) => item.id === receipt.learningId);
|
|
273
|
+
return !candidate || !scopeContains(candidate.scope, receipt.scope);
|
|
274
|
+
})) throw new Error("learning application scope is invalid; run the audit before learning");
|
|
275
|
+
if (normalized.deliveries.some((receipt) => {
|
|
276
|
+
const application = normalized.applications.find((item) => item.id === receipt.applicationId);
|
|
277
|
+
return !application || application.learningId !== receipt.learningId
|
|
278
|
+
|| !DELIVERABLE_APPLICATIONS.has(application.schema)
|
|
279
|
+
|| application.sessionId !== receipt.sessionId || application.preflightReceiptId !== receipt.preflightReceiptId
|
|
280
|
+
|| !exactScope(application.scope, receipt.scope)
|
|
281
|
+
|| new Date(receipt.completedAt).getTime() < new Date(application.projectedAt).getTime()
|
|
282
|
+
|| new Date(receipt.completedAt).getTime() > new Date(application.deliveryExpiresAt).getTime();
|
|
283
|
+
})) throw new Error("learning delivery binding is invalid; run the audit before learning");
|
|
284
|
+
if (normalized.evaluations.some((contract) => {
|
|
285
|
+
const candidate = normalized.candidates.find((item) => item.id === contract.learningId);
|
|
286
|
+
return !candidate || !scopeContains(candidate.scope, contract.scope);
|
|
287
|
+
})) throw new Error("learning evaluation scope is invalid; run the audit before learning");
|
|
288
|
+
if (normalized.measurements.some((receipt) => {
|
|
289
|
+
const candidate = normalized.candidates.find((item) => item.id === receipt.learningId);
|
|
290
|
+
const contract = normalized.evaluations.find((item) => item.id === receipt.evaluationId);
|
|
291
|
+
const evaluatorRoot = ROOT_BOUND_EVALUATIONS.has(contract?.schema)
|
|
292
|
+
? contract.evaluatorRoots.find((root) => root.evaluatorId === receipt.measurement?.evaluatorId) : null;
|
|
293
|
+
return !candidate || !contract || !LINEAGE_EVALUATIONS.has(contract.schema)
|
|
294
|
+
|| contract.learningId !== receipt.learningId || !exactScope(contract.scope, receipt.scope)
|
|
295
|
+
|| contract.metric.name !== receipt.metric.name || contract.metric.direction !== receipt.metric.direction
|
|
296
|
+
|| !contract.evaluatorIds.includes(receipt.measurement.evaluatorId)
|
|
297
|
+
|| contract.benchmark.datasetDigest !== receipt.coverage.datasetDigest
|
|
298
|
+
|| (ROOT_BOUND_EVALUATIONS.has(contract.schema)
|
|
299
|
+
&& (receipt.schema !== "agentspine.learning-measurement/v2"
|
|
300
|
+
|| evaluatorRoot?.principalDigest !== receipt.measurement?.evaluatorRootDigest))
|
|
301
|
+
|| receipt.coverage.caseCount < contract.benchmark.minCases
|
|
302
|
+
|| !scopeContains(candidate.scope, receipt.scope)
|
|
303
|
+
|| new Date(receipt.measuredAt).getTime() < new Date(contract.registeredAt).getTime()
|
|
304
|
+
|| new Date(receipt.measuredAt).getTime() > new Date(contract.expiresAt).getTime();
|
|
305
|
+
})) throw new Error("learning measurement binding is invalid; run the audit before learning");
|
|
306
|
+
if (normalized.measurements.some((receipt) => {
|
|
307
|
+
const contract = normalized.evaluations.find((entry) => entry.id === receipt.evaluationId);
|
|
308
|
+
if (!INITIAL_TRIAL_EVALUATIONS.has(contract?.schema)) return false;
|
|
309
|
+
const retainedByValidation = normalized.validationLeases.some((lease) =>
|
|
310
|
+
lease?.renewalEvidence?.some((entry) => entry.measurementId === receipt.id
|
|
311
|
+
&& entry.measurementDigest === receipt.digest));
|
|
312
|
+
if (retainedByValidation) return false;
|
|
313
|
+
const revalidationApplication = receipt.phase === "after" ? normalized.applications.find((entry) =>
|
|
314
|
+
entry.schema === "agentspine.learning-application/v4" && entry.learningId === receipt.learningId
|
|
315
|
+
&& entry.revalidationAdmission.evaluatorId === receipt.measurement?.evaluatorId
|
|
316
|
+
&& entry.revalidationAdmission.evaluatorRootDigest === receipt.measurement?.evaluatorRootDigest
|
|
317
|
+
&& entry.revalidationAdmission.runId === receipt.measurement?.runId) : null;
|
|
318
|
+
if (revalidationApplication) {
|
|
319
|
+
const delivery = normalized.deliveries.find((entry) => entry.applicationId === revalidationApplication.id);
|
|
320
|
+
return !delivery || new Date(receipt.measuredAt).getTime() < new Date(delivery.completedAt).getTime();
|
|
321
|
+
}
|
|
322
|
+
const trial = contract.initialTrials?.[receipt.phase]?.find((entry) =>
|
|
323
|
+
entry.evaluatorId === receipt.measurement?.evaluatorId);
|
|
324
|
+
if (!trial || receipt.measurement.evaluatorRootDigest !== trial.evaluatorRootDigest
|
|
325
|
+
|| receipt.measurement.runId !== trial.runId || receipt.coverage.caseCount !== trial.caseCount) return true;
|
|
326
|
+
if (receipt.phase !== "after") return false;
|
|
327
|
+
const application = normalized.applications.find((entry) => INITIAL_TRIAL_APPLICATIONS.has(entry.schema)
|
|
328
|
+
&& entry.learningId === receipt.learningId && entry.initialAdmission.evaluationId === contract.id
|
|
329
|
+
&& entry.initialAdmission.evaluationDigest === contract.digest && entry.initialAdmission.slot === trial.slot
|
|
330
|
+
&& entry.initialAdmission.trialDigest === trial.trialDigest
|
|
331
|
+
&& (!TARGET_BOUND_EVALUATIONS.has(contract.schema)
|
|
332
|
+
|| (TARGET_BOUND_APPLICATIONS.has(entry.schema)
|
|
333
|
+
&& entry.initialAdmission.targetDigest === contract.target.digest)));
|
|
334
|
+
const delivery = application && normalized.deliveries.find((entry) => entry.applicationId === application.id);
|
|
335
|
+
return !delivery || new Date(receipt.measuredAt).getTime() < new Date(delivery.completedAt).getTime()
|
|
336
|
+
|| (DEADLINE_BOUND_APPLICATIONS.has(application.schema)
|
|
337
|
+
&& new Date(receipt.measuredAt).getTime() > new Date(application.outcomeExpiresAt).getTime());
|
|
338
|
+
})) throw new Error("learning initial trial measurement binding is invalid; run the audit before learning");
|
|
339
|
+
const pairedOutcomeKeys = new Set();
|
|
340
|
+
const pairedAfterApplications = new Set();
|
|
341
|
+
for (const receipt of normalized.outcomes) {
|
|
342
|
+
if (!["agentspine.learning-outcome/v8", "agentspine.learning-outcome/v9"].includes(receipt.schema)) continue;
|
|
343
|
+
const evaluatorKey = receipt.schema === "agentspine.learning-outcome/v9"
|
|
344
|
+
? receipt.measurement.evaluatorRootDigest : receipt.measurement.evaluatorId;
|
|
345
|
+
const key = `${receipt.evaluationId}\0${receipt.phase}\0${evaluatorKey}`;
|
|
346
|
+
if (pairedOutcomeKeys.has(key)) {
|
|
347
|
+
throw new Error("learning paired evaluator outcome is duplicated; run the audit before learning");
|
|
348
|
+
}
|
|
349
|
+
pairedOutcomeKeys.add(key);
|
|
350
|
+
if (receipt.phase === "after") {
|
|
351
|
+
const applicationKey = `${receipt.evaluationId}\0${receipt.applicationId}`;
|
|
352
|
+
if (pairedAfterApplications.has(applicationKey)) {
|
|
353
|
+
throw new Error("learning paired outcome turn is duplicated; run the audit before learning");
|
|
354
|
+
}
|
|
355
|
+
pairedAfterApplications.add(applicationKey);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
if (normalized.outcomes.some((receipt) => ["agentspine.learning-outcome/v2", "agentspine.learning-outcome/v3", "agentspine.learning-outcome/v4", "agentspine.learning-outcome/v5", "agentspine.learning-outcome/v6", "agentspine.learning-outcome/v7", "agentspine.learning-outcome/v8", "agentspine.learning-outcome/v9"].includes(receipt.schema)
|
|
359
|
+
&& receipt.phase === "after" && !normalized.applications.some((application) => application.id === receipt.applicationId
|
|
360
|
+
&& application.learningId === receipt.learningId && exactScope(application.scope, receipt.scope)
|
|
361
|
+
&& new Date(receipt.measuredAt).getTime() >= new Date(application.projectedAt).getTime()
|
|
362
|
+
&& new Date(receipt.measuredAt).getTime() <= new Date(application.expiresAt).getTime()
|
|
363
|
+
&& (!DEADLINE_BOUND_APPLICATIONS.has(application.schema)
|
|
364
|
+
|| new Date(receipt.measuredAt).getTime() <= new Date(application.outcomeExpiresAt).getTime())))) {
|
|
365
|
+
throw new Error("learning outcome application binding is invalid; run the audit before learning");
|
|
366
|
+
}
|
|
367
|
+
if (normalized.outcomes.some((receipt) => ["agentspine.learning-outcome/v3", "agentspine.learning-outcome/v4", "agentspine.learning-outcome/v5", "agentspine.learning-outcome/v6", "agentspine.learning-outcome/v7", "agentspine.learning-outcome/v8", "agentspine.learning-outcome/v9"].includes(receipt.schema)
|
|
368
|
+
&& !normalized.evaluations.some((contract) => contract.id === receipt.evaluationId
|
|
369
|
+
&& contract.learningId === receipt.learningId && exactScope(contract.scope, receipt.scope)
|
|
370
|
+
&& contract.metric.name === receipt.metric.name && contract.metric.direction === receipt.metric.direction
|
|
371
|
+
&& contract.evaluatorIds.includes(receipt.measurement.evaluatorId)
|
|
372
|
+
&& (receipt.schema !== "agentspine.learning-outcome/v9"
|
|
373
|
+
|| (ROOT_BOUND_EVALUATIONS.has(contract.schema)
|
|
374
|
+
&& contract.evaluatorRoots.some((root) => root.evaluatorId === receipt.measurement.evaluatorId
|
|
375
|
+
&& root.principalDigest === receipt.measurement.evaluatorRootDigest)))
|
|
376
|
+
&& new Date(receipt.measuredAt).getTime() >= new Date(contract.registeredAt).getTime()
|
|
377
|
+
&& new Date(receipt.measuredAt).getTime() <= new Date(contract.expiresAt).getTime()))) {
|
|
378
|
+
throw new Error("learning outcome evaluation binding is invalid; run the audit before learning");
|
|
379
|
+
}
|
|
380
|
+
if (normalized.outcomes.some((receipt) => ["agentspine.learning-outcome/v5", "agentspine.learning-outcome/v6", "agentspine.learning-outcome/v7", "agentspine.learning-outcome/v8", "agentspine.learning-outcome/v9"].includes(receipt.schema)
|
|
381
|
+
&& !normalized.evaluations.some((contract) => contract.id === receipt.evaluationId
|
|
382
|
+
&& ((receipt.schema === "agentspine.learning-outcome/v5" && contract.schema === "agentspine.learning-evaluation/v2")
|
|
383
|
+
|| (receipt.schema === "agentspine.learning-outcome/v6" && contract.schema === "agentspine.learning-evaluation/v3")
|
|
384
|
+
|| (receipt.schema === "agentspine.learning-outcome/v7" && contract.schema === "agentspine.learning-evaluation/v4")
|
|
385
|
+
|| (receipt.schema === "agentspine.learning-outcome/v8" && contract.schema === "agentspine.learning-evaluation/v5")
|
|
386
|
+
|| (receipt.schema === "agentspine.learning-outcome/v9" && ROOT_BOUND_EVALUATIONS.has(contract.schema)))
|
|
387
|
+
&& receipt.coverage?.datasetDigest === contract.benchmark.datasetDigest
|
|
388
|
+
&& receipt.coverage?.caseCount >= contract.benchmark.minCases))) {
|
|
389
|
+
throw new Error("learning outcome coverage binding is invalid; run the audit before learning");
|
|
390
|
+
}
|
|
391
|
+
const provenanceKeys = new Set();
|
|
392
|
+
for (const receipt of normalized.outcomes) {
|
|
393
|
+
if (receipt.schema !== "agentspine.learning-outcome/v6") continue;
|
|
394
|
+
const key = `${receipt.evaluationId}\0${receipt.measurement?.sourceDigest || ""}`;
|
|
395
|
+
if (!DIGEST_RE.test(receipt.measurement?.sourceDigest || "") || provenanceKeys.has(key)) {
|
|
396
|
+
throw new Error("learning outcome provenance is missing or replayed; run the audit before learning");
|
|
397
|
+
}
|
|
398
|
+
provenanceKeys.add(key);
|
|
399
|
+
}
|
|
400
|
+
const measurementSources = new Set();
|
|
401
|
+
const measurementRuns = new Set();
|
|
402
|
+
const evaluatorRootRuns = new Set();
|
|
403
|
+
const lineageIds = new Set();
|
|
404
|
+
for (const lineage of normalized.measurementLineage) {
|
|
405
|
+
if (measurementSources.has(lineage.sourceDigest) || measurementRuns.has(lineage.runDigest)
|
|
406
|
+
|| (lineage.schema === "agentspine.learning-measurement-lineage/v2" && evaluatorRootRuns.has(lineage.rootRunDigest))
|
|
407
|
+
|| lineageIds.has(lineage.measurementReceiptId)) {
|
|
408
|
+
throw new Error("learning measurement lineage is replayed; run the audit before learning");
|
|
409
|
+
}
|
|
410
|
+
measurementSources.add(lineage.sourceDigest);
|
|
411
|
+
measurementRuns.add(lineage.runDigest);
|
|
412
|
+
if (lineage.schema === "agentspine.learning-measurement-lineage/v2") evaluatorRootRuns.add(lineage.rootRunDigest);
|
|
413
|
+
lineageIds.add(lineage.measurementReceiptId);
|
|
414
|
+
}
|
|
415
|
+
if (normalized.measurements.some((receipt) => !normalized.measurementLineage.some((lineage) =>
|
|
416
|
+
lineage.measurementReceiptId === receipt.id && lineage.learningId === receipt.learningId
|
|
417
|
+
&& lineage.evaluationId === receipt.evaluationId && lineage.sourceDigest === receipt.measurement.sourceDigest
|
|
418
|
+
&& lineage.runDigest === measurementRunDigest(receipt.measurement.evaluatorId, receipt.measurement.runId)
|
|
419
|
+
&& (receipt.schema !== "agentspine.learning-measurement/v2"
|
|
420
|
+
|| (lineage.schema === "agentspine.learning-measurement-lineage/v2"
|
|
421
|
+
&& lineage.evaluatorRootDigest === receipt.measurement.evaluatorRootDigest
|
|
422
|
+
&& lineage.rootRunDigest === evaluatorRootRunDigest(receipt.measurement.evaluatorRootDigest, receipt.measurement.runId)))
|
|
423
|
+
&& lineage.registeredAt === receipt.measuredAt))) {
|
|
424
|
+
throw new Error("learning measurement lineage binding is invalid; run the audit before learning");
|
|
425
|
+
}
|
|
426
|
+
const consumedMeasurements = new Set();
|
|
427
|
+
for (const receipt of normalized.outcomes) {
|
|
428
|
+
if (!["agentspine.learning-outcome/v7", "agentspine.learning-outcome/v8", "agentspine.learning-outcome/v9"].includes(receipt.schema)) continue;
|
|
429
|
+
const measurement = normalized.measurements.find((item) => item.id === receipt.measurementReceiptId);
|
|
430
|
+
if (!measurement || measurement.digest !== receipt.measurementReceiptDigest
|
|
431
|
+
|| measurement.learningId !== receipt.learningId || measurement.evaluationId !== receipt.evaluationId
|
|
432
|
+
|| measurement.phase !== receipt.phase || !exactScope(measurement.scope, receipt.scope)
|
|
433
|
+
|| digest(measurement.metric) !== digest(receipt.metric) || digest(measurement.measurement) !== digest(receipt.measurement)
|
|
434
|
+
|| digest(measurement.coverage) !== digest(receipt.coverage) || measurement.measuredAt !== receipt.measuredAt
|
|
435
|
+
|| consumedMeasurements.has(measurement.id)) {
|
|
436
|
+
throw new Error("learning outcome measurement binding is invalid or replayed; run the audit before learning");
|
|
437
|
+
}
|
|
438
|
+
consumedMeasurements.add(measurement.id);
|
|
439
|
+
}
|
|
440
|
+
if (normalized.outcomes.some((receipt) => ["agentspine.learning-outcome/v8", "agentspine.learning-outcome/v9"].includes(receipt.schema)
|
|
441
|
+
&& receipt.phase === "after" && !normalized.outcomes.some((before) =>
|
|
442
|
+
before.schema === receipt.schema && before.phase === "before"
|
|
443
|
+
&& before.learningId === receipt.learningId && before.evaluationId === receipt.evaluationId
|
|
444
|
+
&& before.measurement.evaluatorId === receipt.measurement.evaluatorId
|
|
445
|
+
&& (receipt.schema !== "agentspine.learning-outcome/v9"
|
|
446
|
+
|| before.measurement.evaluatorRootDigest === receipt.measurement.evaluatorRootDigest)
|
|
447
|
+
&& before.measurement.kind === receipt.measurement.kind
|
|
448
|
+
&& before.coverage.caseCount === receipt.coverage.caseCount
|
|
449
|
+
&& exactScope(before.scope, receipt.scope)))) {
|
|
450
|
+
throw new Error("learning paired outcome evaluator binding is invalid; run the audit before learning");
|
|
451
|
+
}
|
|
452
|
+
if (normalized.outcomes.some((receipt) => ["agentspine.learning-outcome/v4", "agentspine.learning-outcome/v5", "agentspine.learning-outcome/v6", "agentspine.learning-outcome/v7", "agentspine.learning-outcome/v8", "agentspine.learning-outcome/v9"].includes(receipt.schema)
|
|
453
|
+
&& (receipt.phase === "after" ? !normalized.deliveries.some((delivery) => delivery.id === receipt.deliveryId
|
|
454
|
+
&& delivery.applicationId === receipt.applicationId && delivery.learningId === receipt.learningId
|
|
455
|
+
&& exactScope(delivery.scope, receipt.scope)
|
|
456
|
+
&& new Date(receipt.measuredAt).getTime() >= new Date(delivery.completedAt).getTime()) : receipt.deliveryId !== null))) {
|
|
457
|
+
throw new Error("learning outcome delivery binding is invalid; run the audit before learning");
|
|
458
|
+
}
|
|
459
|
+
if (normalized.candidates.some((candidate) => candidate.status === "accepted"
|
|
460
|
+
&& candidate.promotion?.mode === "outcome-canary" && candidate.promotion.canary?.evaluationId
|
|
461
|
+
&& !normalized.evaluations.some((contract) => contract.id === candidate.promotion.canary.evaluationId
|
|
462
|
+
&& contract.learningId === candidate.id && contract.digest === candidate.promotion.canary.evaluationDigest
|
|
463
|
+
&& exactScope(contract.scope, candidate.promotion.canary.scope)
|
|
464
|
+
&& (!TARGET_BOUND_EVALUATIONS.has(contract.schema)
|
|
465
|
+
|| (candidate.promotion.canary.targetDigest === contract.target.digest
|
|
466
|
+
&& learningTargetMatchesCandidate(contract.target, candidate)))
|
|
467
|
+
&& (!DEADLINE_BOUND_EVALUATIONS.has(contract.schema)
|
|
468
|
+
|| candidate.promotion.canary.completionPolicyDigest === contract.completionPolicy.digest)
|
|
469
|
+
&& (!STALENESS_BOUND_EVALUATIONS.has(contract.schema)
|
|
470
|
+
|| candidate.promotion.canary.stalenessPolicyDigest === contract.stalenessPolicy.digest)))) {
|
|
471
|
+
throw new Error("learning canary evaluation binding is invalid; run the audit before learning");
|
|
472
|
+
}
|
|
473
|
+
if (normalized.validationLeases.some((lease) => !validationLeaseMatchesState(normalized, lease))) {
|
|
474
|
+
throw new Error("learning validation lease binding is invalid; run the audit before learning");
|
|
475
|
+
}
|
|
476
|
+
return normalized;
|
|
477
|
+
}
|