blun-king-cli 9.1.567 → 9.1.570

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.
Files changed (263) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/agent-spine-plugin/.claude-plugin/marketplace.json +1 -1
  3. package/agent-spine-plugin/.claude-plugin/plugin.json +1 -1
  4. package/agent-spine-plugin/.codex-plugin/plugin.json +2 -1
  5. package/agent-spine-plugin/CHANGELOG.md +1581 -0
  6. package/agent-spine-plugin/README.md +30 -4
  7. package/agent-spine-plugin/blun.plugin.json +3 -3
  8. package/agent-spine-plugin/docs/acceptance.md +61 -0
  9. package/agent-spine-plugin/docs/assignment-continuation.md +48 -0
  10. package/agent-spine-plugin/docs/host-integration.md +178 -0
  11. package/agent-spine-plugin/docs/preflight-recall.md +69 -0
  12. package/agent-spine-plugin/docs/preservation-contract.md +53 -0
  13. package/agent-spine-plugin/docs/quality-gates.md +50 -0
  14. package/agent-spine-plugin/docs/releasing.md +85 -0
  15. package/agent-spine-plugin/docs/session-timeline.md +251 -0
  16. package/agent-spine-plugin/docs/source-roots.md +113 -0
  17. package/agent-spine-plugin/docs/structured-completion.md +67 -0
  18. package/agent-spine-plugin/docs/world-model.md +94 -0
  19. package/agent-spine-plugin/hooks/codex.json +2 -2
  20. package/agent-spine-plugin/hooks/hooks.json +1 -1
  21. package/agent-spine-plugin/hooks/version.json +1 -1
  22. package/agent-spine-plugin/package.json +13 -3
  23. package/agent-spine-plugin/scripts/check-codex-install.js +226 -0
  24. package/agent-spine-plugin/scripts/check-hosts.js +14 -5
  25. package/agent-spine-plugin/scripts/check-install-hook.js +226 -0
  26. package/agent-spine-plugin/scripts/check-install-selfstarter.js +154 -0
  27. package/agent-spine-plugin/scripts/check-install.js +478 -0
  28. package/agent-spine-plugin/scripts/check-line-budget.js +58 -0
  29. package/agent-spine-plugin/scripts/check-syntax.js +29 -0
  30. package/agent-spine-plugin/scripts/github-actions.js +11 -0
  31. package/agent-spine-plugin/scripts/hermetic-process.js +183 -0
  32. package/agent-spine-plugin/scripts/release-check.js +145 -0
  33. package/agent-spine-plugin/scripts/run-acceptance.js +19 -0
  34. package/agent-spine-plugin/scripts/run-checks.js +47 -0
  35. package/agent-spine-plugin/scripts/run-tests-hermetic.js +89 -0
  36. package/agent-spine-plugin/skills/agent-spine/SKILL.md +16 -2
  37. package/agent-spine-plugin/spine-example/1-identity.md +12 -0
  38. package/agent-spine-plugin/spine-example/2-voice.md +6 -0
  39. package/agent-spine-plugin/spine-example/3-conduct.md +8 -0
  40. package/agent-spine-plugin/spine-example/4-history.md +4 -0
  41. package/agent-spine-plugin/src/cli-agent.js +296 -0
  42. package/agent-spine-plugin/src/cli-attention.js +95 -0
  43. package/agent-spine-plugin/src/cli-autonomy.js +36 -0
  44. package/agent-spine-plugin/src/cli-common.js +71 -0
  45. package/agent-spine-plugin/src/cli-continuity.js +116 -0
  46. package/agent-spine-plugin/src/cli-core.js +128 -0
  47. package/agent-spine-plugin/src/cli-diagnostics.js +291 -0
  48. package/agent-spine-plugin/src/cli-host.js +21 -0
  49. package/agent-spine-plugin/src/cli-learning.js +305 -0
  50. package/agent-spine-plugin/src/cli-premortem.js +16 -0
  51. package/agent-spine-plugin/src/cli-sharing.js +230 -0
  52. package/agent-spine-plugin/src/cli.js +40 -1350
  53. package/agent-spine-plugin/src/codex-reader-launcher.js +182 -0
  54. package/agent-spine-plugin/src/hook.js +185 -567
  55. package/agent-spine-plugin/src/index.js +16 -2
  56. package/agent-spine-plugin/src/lib/acceptance.js +113 -11
  57. package/agent-spine-plugin/src/lib/action-lesson-recall.js +53 -0
  58. package/agent-spine-plugin/src/lib/attention-context.js +167 -0
  59. package/agent-spine-plugin/src/lib/attention-events.js +113 -0
  60. package/agent-spine-plugin/src/lib/attention-privacy.js +72 -0
  61. package/agent-spine-plugin/src/lib/attention-schema.js +164 -0
  62. package/agent-spine-plugin/src/lib/attention-storage.js +93 -0
  63. package/agent-spine-plugin/src/lib/attention.js +9 -600
  64. package/agent-spine-plugin/src/lib/audit-premortem.js +223 -0
  65. package/agent-spine-plugin/src/lib/audit.js +56 -6
  66. package/agent-spine-plugin/src/lib/autonomy-policy.js +110 -0
  67. package/agent-spine-plugin/src/lib/autonomy-store.js +202 -0
  68. package/agent-spine-plugin/src/lib/autonomy.js +8 -0
  69. package/agent-spine-plugin/src/lib/briefing.js +67 -4
  70. package/agent-spine-plugin/src/lib/catalog-document-read.js +51 -0
  71. package/agent-spine-plugin/src/lib/catalog.js +1 -1
  72. package/agent-spine-plugin/src/lib/codex-installation.js +231 -0
  73. package/agent-spine-plugin/src/lib/codex-skill-installation.js +211 -0
  74. package/agent-spine-plugin/src/lib/context.js +3 -1
  75. package/agent-spine-plugin/src/lib/delivery-agent-usage.js +224 -0
  76. package/agent-spine-plugin/src/lib/delivery-assignment.js +220 -0
  77. package/agent-spine-plugin/src/lib/delivery-command-actions.js +453 -0
  78. package/agent-spine-plugin/src/lib/delivery-knowledge.js +78 -0
  79. package/agent-spine-plugin/src/lib/delivery-premortem-binding.js +107 -0
  80. package/agent-spine-plugin/src/lib/delivery-premortem-closure.js +171 -0
  81. package/agent-spine-plugin/src/lib/delivery-premortem-codec.js +45 -0
  82. package/agent-spine-plugin/src/lib/delivery-premortem-correction.js +101 -0
  83. package/agent-spine-plugin/src/lib/delivery-premortem-file.js +21 -0
  84. package/agent-spine-plugin/src/lib/delivery-premortem-index.js +493 -0
  85. package/agent-spine-plugin/src/lib/delivery-premortem-inspection.js +37 -0
  86. package/agent-spine-plugin/src/lib/delivery-premortem-recovery.js +120 -0
  87. package/agent-spine-plugin/src/lib/delivery-premortem-rejection.js +65 -0
  88. package/agent-spine-plugin/src/lib/delivery-premortem-results.js +28 -0
  89. package/agent-spine-plugin/src/lib/delivery-premortem-session-guard.js +46 -0
  90. package/agent-spine-plugin/src/lib/delivery-premortem-write-ledger.js +285 -0
  91. package/agent-spine-plugin/src/lib/delivery-premortem.js +499 -0
  92. package/agent-spine-plugin/src/lib/delivery-shell-heredoc.js +115 -0
  93. package/agent-spine-plugin/src/lib/delivery-shell-substitutions.js +111 -0
  94. package/agent-spine-plugin/src/lib/delivery-shell-wrapper.js +64 -0
  95. package/agent-spine-plugin/src/lib/delivery-target.js +73 -0
  96. package/agent-spine-plugin/src/lib/delivery-verification.js +445 -0
  97. package/agent-spine-plugin/src/lib/documents.js +27 -5
  98. package/agent-spine-plugin/src/lib/filesystem-retry.js +2 -0
  99. package/agent-spine-plugin/src/lib/gateway-common.js +68 -0
  100. package/agent-spine-plugin/src/lib/gateway-control.js +302 -0
  101. package/agent-spine-plugin/src/lib/gateway-delivery.js +103 -0
  102. package/agent-spine-plugin/src/lib/gateway-execution.js +350 -0
  103. package/agent-spine-plugin/src/lib/gateway-host-lifecycle.js +185 -0
  104. package/agent-spine-plugin/src/lib/gateway-inspection.js +85 -0
  105. package/agent-spine-plugin/src/lib/gateway-knowledge.js +129 -0
  106. package/agent-spine-plugin/src/lib/gateway-policy-provenance.js +197 -0
  107. package/agent-spine-plugin/src/lib/gateway-premortem-disposition.js +82 -0
  108. package/agent-spine-plugin/src/lib/gateway-premortem.js +363 -0
  109. package/agent-spine-plugin/src/lib/gateway-runs.js +300 -0
  110. package/agent-spine-plugin/src/lib/gateway-runtime-identity.js +31 -0
  111. package/agent-spine-plugin/src/lib/gateway-runtime-records.js +21 -0
  112. package/agent-spine-plugin/src/lib/gateway-runtime.js +18 -1623
  113. package/agent-spine-plugin/src/lib/gateway-state-transaction.js +356 -0
  114. package/agent-spine-plugin/src/lib/gateway-state.js +342 -0
  115. package/agent-spine-plugin/src/lib/hook-artifact-guards.js +356 -0
  116. package/agent-spine-plugin/src/lib/hook-audit.js +16 -2
  117. package/agent-spine-plugin/src/lib/hook-briefing-use.js +68 -0
  118. package/agent-spine-plugin/src/lib/hook-context.js +424 -0
  119. package/agent-spine-plugin/src/lib/hook-final-message.js +26 -0
  120. package/agent-spine-plugin/src/lib/hook-input.js +27 -0
  121. package/agent-spine-plugin/src/lib/hook-output.js +140 -0
  122. package/agent-spine-plugin/src/lib/hook-premortem.js +257 -0
  123. package/agent-spine-plugin/src/lib/hook-process-advisory.js +37 -0
  124. package/agent-spine-plugin/src/lib/hook-protection.js +95 -0
  125. package/agent-spine-plugin/src/lib/hook-stop-verification.js +84 -0
  126. package/agent-spine-plugin/src/lib/hook-timeline.js +91 -0
  127. package/agent-spine-plugin/src/lib/identifier-analysis.js +446 -0
  128. package/agent-spine-plugin/src/lib/indexed-memory.js +23 -6
  129. package/agent-spine-plugin/src/lib/knowledge-evidence.js +431 -0
  130. package/agent-spine-plugin/src/lib/learning-applications.js +441 -0
  131. package/agent-spine-plugin/src/lib/learning-candidates.js +274 -0
  132. package/agent-spine-plugin/src/lib/learning-context.js +130 -0
  133. package/agent-spine-plugin/src/lib/learning-delivery-contracts.js +310 -0
  134. package/agent-spine-plugin/src/lib/learning-evaluation-contracts.js +350 -0
  135. package/agent-spine-plugin/src/lib/learning-evaluation-registration.js +372 -0
  136. package/agent-spine-plugin/src/lib/learning-evaluation-revocation.js +292 -0
  137. package/agent-spine-plugin/src/lib/learning-evidence-contracts.js +321 -0
  138. package/agent-spine-plugin/src/lib/learning-findings.js +458 -0
  139. package/agent-spine-plugin/src/lib/learning-measurement-contracts.js +285 -0
  140. package/agent-spine-plugin/src/lib/learning-measurements.js +265 -0
  141. package/agent-spine-plugin/src/lib/learning-outcome-contracts.js +165 -0
  142. package/agent-spine-plugin/src/lib/learning-outcomes.js +343 -0
  143. package/agent-spine-plugin/src/lib/learning-reconciliation.js +290 -0
  144. package/agent-spine-plugin/src/lib/learning-retry-contracts.js +188 -0
  145. package/agent-spine-plugin/src/lib/learning-schema.js +229 -0
  146. package/agent-spine-plugin/src/lib/learning-scope-targets.js +424 -0
  147. package/agent-spine-plugin/src/lib/learning-state-upgrade.js +477 -0
  148. package/agent-spine-plugin/src/lib/learning-status-configuration.js +476 -0
  149. package/agent-spine-plugin/src/lib/learning-storage.js +203 -0
  150. package/agent-spine-plugin/src/lib/learning-trial-recovery.js +218 -0
  151. package/agent-spine-plugin/src/lib/learning-validation-contracts.js +375 -0
  152. package/agent-spine-plugin/src/lib/learning-validation-renewal.js +298 -0
  153. package/agent-spine-plugin/src/lib/learning-validation-runtime.js +234 -0
  154. package/agent-spine-plugin/src/lib/learning.js +36 -6923
  155. package/agent-spine-plugin/src/lib/lesson-recall-session.js +172 -0
  156. package/agent-spine-plugin/src/lib/mcp-autonomy-tools.js +37 -0
  157. package/agent-spine-plugin/src/lib/mcp-delivery-completion.js +124 -0
  158. package/agent-spine-plugin/src/lib/mcp-delivery-tools.js +45 -0
  159. package/agent-spine-plugin/src/lib/mcp-premortem.js +68 -0
  160. package/agent-spine-plugin/src/lib/mcp-runtime.js +269 -0
  161. package/agent-spine-plugin/src/lib/mcp-source-context.js +51 -0
  162. package/agent-spine-plugin/src/lib/mcp-timeline-tools.js +164 -0
  163. package/agent-spine-plugin/src/lib/mcp-world-tools.js +52 -0
  164. package/agent-spine-plugin/src/lib/owned-file-lock.js +30 -10
  165. package/agent-spine-plugin/src/lib/project-portfolio.js +176 -0
  166. package/agent-spine-plugin/src/lib/selfstarter-core.js +382 -0
  167. package/agent-spine-plugin/src/lib/selfstarter-jobs.js +149 -0
  168. package/agent-spine-plugin/src/lib/selfstarter-lease.js +204 -0
  169. package/agent-spine-plugin/src/lib/selfstarter-policy.js +90 -0
  170. package/agent-spine-plugin/src/lib/selfstarter-workspace.js +111 -0
  171. package/agent-spine-plugin/src/lib/selfstarter.js +11 -911
  172. package/agent-spine-plugin/src/lib/session-timeline-auth.js +316 -0
  173. package/agent-spine-plugin/src/lib/session-timeline-codex.js +58 -0
  174. package/agent-spine-plugin/src/lib/session-timeline-contract.js +48 -0
  175. package/agent-spine-plugin/src/lib/session-timeline-enrollment-source.js +41 -0
  176. package/agent-spine-plugin/src/lib/session-timeline-enrollment-storage.js +132 -0
  177. package/agent-spine-plugin/src/lib/session-timeline-enrollment-transport.js +17 -0
  178. package/agent-spine-plugin/src/lib/session-timeline-enrollment.js +500 -0
  179. package/agent-spine-plugin/src/lib/session-timeline-event-extract.js +157 -0
  180. package/agent-spine-plugin/src/lib/session-timeline-host-origin.js +74 -0
  181. package/agent-spine-plugin/src/lib/session-timeline-host-receipt.js +117 -0
  182. package/agent-spine-plugin/src/lib/session-timeline-invocation.js +201 -0
  183. package/agent-spine-plugin/src/lib/session-timeline-king.js +79 -0
  184. package/agent-spine-plugin/src/lib/session-timeline-prior.js +59 -0
  185. package/agent-spine-plugin/src/lib/session-timeline-provider.js +34 -0
  186. package/agent-spine-plugin/src/lib/session-timeline-query.js +55 -0
  187. package/agent-spine-plugin/src/lib/session-timeline-results.js +31 -0
  188. package/agent-spine-plugin/src/lib/session-timeline-root.js +11 -0
  189. package/agent-spine-plugin/src/lib/session-timeline-search.js +82 -0
  190. package/agent-spine-plugin/src/lib/session-timeline-sid-acl.js +217 -0
  191. package/agent-spine-plugin/src/lib/session-timeline-source.js +83 -0
  192. package/agent-spine-plugin/src/lib/session-timeline-state.js +45 -0
  193. package/agent-spine-plugin/src/lib/session-timeline-transport.js +50 -0
  194. package/agent-spine-plugin/src/lib/session-timeline-windows-acl.js +148 -0
  195. package/agent-spine-plugin/src/lib/session-timeline.js +453 -0
  196. package/agent-spine-plugin/src/lib/source-roots.js +69 -136
  197. package/agent-spine-plugin/src/lib/source-tree-scan.js +178 -0
  198. package/agent-spine-plugin/src/lib/task-knowledge-context.js +78 -0
  199. package/agent-spine-plugin/src/lib/timeline-tool-guard.js +202 -0
  200. package/agent-spine-plugin/src/lib/world-knowledge.js +249 -0
  201. package/agent-spine-plugin/src/lib/world-model.js +278 -0
  202. package/agent-spine-plugin/src/mcp.js +20 -161
  203. package/agent-spine-plugin/src/version.js +1 -1
  204. package/agent-spine-plugin/src/worker.js +22 -5
  205. package/bin/agent-resume-snapshot.cjs +2 -2
  206. package/bin/agentspine-king-goal-inbox.mjs +111 -0
  207. package/bin/agentspine-king-goal-intake.mjs +106 -0
  208. package/bin/baseline-skill-performance-policy.cjs +1 -16
  209. package/bin/core-bootstrap.js +3 -0
  210. package/bin/curiosity-scout-policy.cjs +5 -1
  211. package/bin/input-draft-persistence.cjs +2 -2
  212. package/bin/king-tui-function-contract.json +33 -0
  213. package/bin/launcher-restart-policy.cjs +150 -0
  214. package/bin/launcher-runtime.js +56 -44
  215. package/bin/managed-context-startup-policy.cjs +27 -0
  216. package/bin/managed-plugin-selection.cjs +116 -0
  217. package/bin/mistake-relevance-policy.cjs +1 -1
  218. package/bin/observer-hooks.cjs +14 -0
  219. package/bin/oversized-context-offload-policy.cjs +86 -0
  220. package/bin/plugin-bootstrap.js +7 -40
  221. package/bin/proactive-compaction-policy.cjs +1 -1
  222. package/bin/provider-model-refresh-deadline.cjs +53 -0
  223. package/bin/provider-model-refresh-policy.cjs +107 -0
  224. package/bin/release-artifact-freeze-policy.cjs +30 -0
  225. package/bin/repeated-user-message-projection.cjs +3 -126
  226. package/bin/research-page-result.cjs +74 -0
  227. package/bin/runtime-exit-ledger.cjs +1 -0
  228. package/bin/session-compaction-policy.cjs +84 -0
  229. package/bin/skill-listing-performance-policy.cjs +2 -2
  230. package/bin/standard-tools-bootstrap.js +0 -37
  231. package/bin/subagent-skill-policy.cjs +3 -1
  232. package/bin/telegram-approval-relay.cjs +12 -7
  233. package/bin/telegram-private-conversation-policy.cjs +3 -2
  234. package/bin/telegram-queue-handoff-policy.cjs +24 -0
  235. package/bin/thinking-activity-status-policy.cjs +1 -1
  236. package/bin/thinking-only-guard.cjs +16 -12
  237. package/bin/tool-call-loop-policy.cjs +0 -2
  238. package/bin/tool-result-offload-policy.cjs +11 -2
  239. package/bin/tui-functional-contract.cjs +55 -0
  240. package/bin/update-notice.js +18 -14
  241. package/bin/user-message-offload-policy.cjs +1 -1
  242. package/bin/user-prompt-hook-origin-policy.cjs +34 -0
  243. package/bin/windows-node-crash-dump.cjs +110 -0
  244. package/blun.mjs +2861 -1173
  245. package/codebase-index/codebase_index.py +4 -3
  246. package/package.json +5 -18
  247. package/standard-skills/research-evidence/SKILL.md +39 -0
  248. package/standard-skills/research-evidence/references/evidence-format.md +82 -0
  249. package/standard-skills/research-evidence/scripts/evidence-collection.cjs +254 -0
  250. package/standard-skills/research-evidence/scripts/score-report.cjs +112 -0
  251. package/standard-skills/web-lesen/SKILL.md +37 -22
  252. package/standard-skills/web-lesen/scripts/crawl_public.py +376 -0
  253. package/telegram-plugin/DELIVERY.md +36 -0
  254. package/telegram-plugin/bin/telegram-approval-relay.cjs +13 -7
  255. package/telegram-plugin/bin/telegram-launcher-status-queue.cjs +122 -0
  256. package/telegram-plugin/bin/telegram-private-conversation-policy.cjs +3 -2
  257. package/telegram-plugin/bin/telegram-reply-parts.cjs +149 -0
  258. package/telegram-plugin/dist/bridge.mjs +7 -56
  259. package/telegram-plugin/dist/mcp-server.mjs +33 -4
  260. package/agent-spine-plugin/skill/SKILL.md +0 -76
  261. package/bin/mnemo-connect-heartbeat.cjs +0 -204
  262. package/bin/mnemo-tool-agent-policy.cjs +0 -22
  263. package/telegram-plugin/bin/telegram-mnemo-capture.cjs +0 -297
@@ -0,0 +1,375 @@
1
+ import {
2
+ METRIC_DIRECTIONS, SCOPE_FIELDS, ID_RE, DIGEST_RE, REGISTRY_BOUND_EVALUATIONS, INITIAL_TRIAL_EVALUATIONS,
3
+ TARGET_BOUND_EVALUATIONS, DEADLINE_BOUND_EVALUATIONS, STALENESS_BOUND_EVALUATIONS, INITIAL_TRIAL_APPLICATIONS, TARGET_BOUND_APPLICATIONS
4
+ } from "./learning-schema.js";
5
+ import {
6
+ exactScope, digest, learningTargetMatchesCandidate
7
+ } from "./learning-scope-targets.js";
8
+ import {
9
+ improvement
10
+ } from "./learning-reconciliation.js";
11
+
12
+ export function revokedEvaluationForCandidate(state, candidate) {
13
+ const canary = candidate?.promotion?.mode === "outcome-canary" ? candidate.promotion.canary : null;
14
+ if (canary?.evaluationId) {
15
+ return state.evaluationRevocations.find((receipt) => receipt.learningId === candidate.id
16
+ && receipt.evaluationId === canary.evaluationId
17
+ && receipt.evaluationDigest === canary.evaluationDigest) || null;
18
+ }
19
+ return state.evaluationRevocations.find((receipt) => receipt.learningId === candidate?.id) || null;
20
+ }
21
+
22
+ export function validationOutcomeReferences(receipts) {
23
+ return receipts.map((receipt) => ({ id: receipt.id, digest: receipt.digest, authority: "context-only" }))
24
+ .sort((a, b) => a.id.localeCompare(b.id));
25
+ }
26
+
27
+ export function revalidationWindowPayload({
28
+ id, status, startedAt, expiresAt, predecessorValidationId, predecessorValidationDigest, selection,
29
+ schema = "agentspine.learning-revalidation-window/v1"
30
+ }) {
31
+ const selectionBound = ["agentspine.learning-revalidation-window/v2",
32
+ "agentspine.learning-revalidation-window/v3", "agentspine.learning-revalidation-window/v4"].includes(schema);
33
+ return {
34
+ schema,
35
+ ...(selectionBound ? { id } : {}),
36
+ status,
37
+ startedAt,
38
+ expiresAt,
39
+ predecessorValidationId,
40
+ predecessorValidationDigest,
41
+ ...(selectionBound ? { selection } : {}),
42
+ authority: "context-only"
43
+ };
44
+ }
45
+
46
+ export function revalidationTrialPayload({ evaluationId, evaluationDigest, predecessorValidationId,
47
+ predecessorValidationDigest, slot, evaluatorId, evaluatorRootDigest, runId, benchmark, caseCount }) {
48
+ return {
49
+ schema: "agentspine.learning-revalidation-trial/v1",
50
+ evaluationId,
51
+ evaluationDigest,
52
+ predecessorValidationId,
53
+ predecessorValidationDigest,
54
+ slot,
55
+ evaluatorId,
56
+ evaluatorRootDigest,
57
+ runId,
58
+ benchmarkDigest: digest(benchmark),
59
+ caseCount,
60
+ authority: "context-only"
61
+ };
62
+ }
63
+
64
+ export function revalidationTrialDigest(input) {
65
+ return digest(revalidationTrialPayload(input));
66
+ }
67
+
68
+ export function storedRevalidationWindowStructure(window) {
69
+ if (!window || typeof window !== "object" || Array.isArray(window)) return false;
70
+ const payload = revalidationWindowPayload(window);
71
+ const common = ["agentspine.learning-revalidation-window/v1", "agentspine.learning-revalidation-window/v2",
72
+ "agentspine.learning-revalidation-window/v3", "agentspine.learning-revalidation-window/v4"]
73
+ .includes(window.schema)
74
+ && window.status === "active" && window.authority === "context-only"
75
+ && Number.isFinite(new Date(window.startedAt).getTime())
76
+ && Number.isFinite(new Date(window.expiresAt).getTime())
77
+ && new Date(window.expiresAt).getTime() > new Date(window.startedAt).getTime()
78
+ && ID_RE.test(window.predecessorValidationId || "")
79
+ && DIGEST_RE.test(window.predecessorValidationDigest || "");
80
+ if (!common) return false;
81
+ if (window.schema === "agentspine.learning-revalidation-window/v1") return true;
82
+ const roots = window.selection?.evaluatorRoots;
83
+ const validMode = window.schema === "agentspine.learning-revalidation-window/v2"
84
+ ? window.selection?.mode === "first-completed-turns"
85
+ : window.schema === "agentspine.learning-revalidation-window/v3"
86
+ ? window.selection?.mode === "first-admitted-turns"
87
+ : window.selection?.mode === "first-admitted-trials";
88
+ return ID_RE.test(window.id || "") && validMode
89
+ && Number.isInteger(window.selection?.requiredDeliveries)
90
+ && window.selection.requiredDeliveries >= 2 && window.selection.requiredDeliveries <= 10
91
+ && Array.isArray(roots) && roots.length === window.selection.requiredDeliveries
92
+ && roots.every((entry, index) => entry?.slot === index + 1
93
+ && DIGEST_RE.test(entry?.evaluatorRootDigest || "")
94
+ && (window.schema !== "agentspine.learning-revalidation-window/v4"
95
+ || (ID_RE.test(entry?.evaluatorId || "") && ID_RE.test(entry?.runId || "")
96
+ && Number.isInteger(entry?.caseCount) && entry.caseCount >= 1 && entry.caseCount <= 1000000
97
+ && DIGEST_RE.test(entry?.trialDigest || "")))
98
+ && entry?.authority === "context-only")
99
+ && new Set(roots.map((entry) => entry.evaluatorRootDigest)).size === roots.length
100
+ && window.selection.authority === "context-only" && window.digest === digest(payload);
101
+ }
102
+
103
+ export function revalidationWindowMatchesState(state, candidate) {
104
+ const window = candidate?.promotion?.canary?.revalidation;
105
+ if (!window) return true;
106
+ const predecessor = state.validationLeases.find((lease) => lease.id === window.predecessorValidationId
107
+ && lease.digest === window.predecessorValidationDigest && lease.learningId === candidate.id);
108
+ if (!storedRevalidationWindowStructure(window) || candidate.promotion?.canary?.status !== "validated"
109
+ || !predecessor || window.expiresAt !== predecessor.expiresAt) return false;
110
+ if (window.schema === "agentspine.learning-revalidation-window/v1") return true;
111
+ const references = predecessor.schema === "agentspine.learning-validation/v1"
112
+ ? predecessor.beforeOutcomes : predecessor.baselineOutcomes;
113
+ const baselines = references.map((reference) => state.outcomes.find((outcome) =>
114
+ outcome.id === reference.id && outcome.digest === reference.digest))
115
+ .filter(Boolean).sort((a, b) => a.measurement.evaluatorId.localeCompare(b.measurement.evaluatorId));
116
+ const contract = state.evaluations.find((entry) => entry.id === candidate.promotion?.canary?.evaluationId
117
+ && entry.digest === candidate.promotion.canary.evaluationDigest);
118
+ return baselines.length === references.length && baselines.length === window.selection.requiredDeliveries
119
+ && window.selection.evaluatorRoots.every((entry, index) => {
120
+ const baseline = baselines[index];
121
+ if (entry.evaluatorRootDigest !== baseline.measurement.evaluatorRootDigest) return false;
122
+ if (window.schema !== "agentspine.learning-revalidation-window/v4") return true;
123
+ return contract && entry.evaluatorId === baseline.measurement.evaluatorId
124
+ && entry.caseCount === baseline.coverage.caseCount
125
+ && entry.trialDigest === revalidationTrialDigest({
126
+ evaluationId: contract.id, evaluationDigest: contract.digest,
127
+ predecessorValidationId: predecessor.id, predecessorValidationDigest: predecessor.digest,
128
+ slot: entry.slot, evaluatorId: entry.evaluatorId, evaluatorRootDigest: entry.evaluatorRootDigest,
129
+ runId: entry.runId, benchmark: contract.benchmark, caseCount: entry.caseCount
130
+ });
131
+ });
132
+ }
133
+
134
+ export function validationLeasePayload({
135
+ id, learningId, evaluationId, evaluationDigest, evaluatorRegistryBindingDigest,
136
+ scope, metric, beforeOutcomes, afterOutcomes, baselineOutcomes, predecessorValidation,
137
+ renewalEvidence, selectionProof, improvement, validatedAt, expiresAt,
138
+ schema = "agentspine.learning-validation/v1"
139
+ }) {
140
+ return {
141
+ schema,
142
+ id,
143
+ learningId,
144
+ evaluationId,
145
+ evaluationDigest,
146
+ evaluatorRegistryBindingDigest,
147
+ scope,
148
+ metric,
149
+ ...(schema === "agentspine.learning-validation/v1"
150
+ ? { beforeOutcomes, afterOutcomes }
151
+ : { baselineOutcomes, predecessorValidation, renewalEvidence,
152
+ ...(["agentspine.learning-validation/v3", "agentspine.learning-validation/v4",
153
+ "agentspine.learning-validation/v5"].includes(schema)
154
+ ? { selectionProof } : {}) }),
155
+ improvement,
156
+ validatedAt,
157
+ expiresAt,
158
+ authority: "context-only"
159
+ };
160
+ }
161
+
162
+ export function storedValidationLeaseStructure(lease) {
163
+ if (!lease || typeof lease !== "object" || Array.isArray(lease)) return false;
164
+ const payload = validationLeasePayload(lease);
165
+ const validReferences = (items) => Array.isArray(items) && items.length >= 2
166
+ && items.every((entry) => ID_RE.test(entry?.id || "") && DIGEST_RE.test(entry?.digest || "")
167
+ && entry?.authority === "context-only")
168
+ && new Set(items.map((entry) => entry.id)).size === items.length;
169
+ const validPredecessor = lease.predecessorValidation && ID_RE.test(lease.predecessorValidation.id || "")
170
+ && DIGEST_RE.test(lease.predecessorValidation.digest || "")
171
+ && lease.predecessorValidation.authority === "context-only";
172
+ const validRenewalEvidence = Array.isArray(lease.renewalEvidence) && lease.renewalEvidence.length >= 2
173
+ && lease.renewalEvidence.every((entry) => ID_RE.test(entry?.measurementId || "")
174
+ && DIGEST_RE.test(entry?.measurementDigest || "") && ID_RE.test(entry?.applicationId || "")
175
+ && DIGEST_RE.test(entry?.applicationDigest || "") && ID_RE.test(entry?.deliveryId || "")
176
+ && DIGEST_RE.test(entry?.deliveryDigest || "") && DIGEST_RE.test(entry?.evaluatorRootDigest || "")
177
+ && entry?.authority === "context-only")
178
+ && new Set(lease.renewalEvidence.map((entry) => entry.measurementId)).size === lease.renewalEvidence.length
179
+ && new Set(lease.renewalEvidence.map((entry) => entry.applicationId)).size === lease.renewalEvidence.length
180
+ && new Set(lease.renewalEvidence.map((entry) => entry.deliveryId)).size === lease.renewalEvidence.length
181
+ && new Set(lease.renewalEvidence.map((entry) => entry.evaluatorRootDigest)).size === lease.renewalEvidence.length;
182
+ const admissionBound = ["agentspine.learning-validation/v4", "agentspine.learning-validation/v5"].includes(lease.schema);
183
+ const trialBound = lease.schema === "agentspine.learning-validation/v5";
184
+ const selectionEntries = admissionBound
185
+ ? lease.selectionProof?.applications : lease.selectionProof?.deliveries;
186
+ const validSelectionProof = lease.selectionProof && ID_RE.test(lease.selectionProof.revalidationWindowId || "")
187
+ && DIGEST_RE.test(lease.selectionProof.revalidationWindowDigest || "")
188
+ && (trialBound
189
+ ? lease.selectionProof.mode === "first-admitted-trials"
190
+ : lease.schema === "agentspine.learning-validation/v4"
191
+ ? lease.selectionProof.mode === "first-admitted-turns"
192
+ : lease.selectionProof.mode === "first-completed-turns")
193
+ && Number.isInteger(lease.selectionProof.requiredDeliveries)
194
+ && lease.selectionProof.requiredDeliveries >= 2 && lease.selectionProof.requiredDeliveries <= 10
195
+ && Array.isArray(selectionEntries)
196
+ && selectionEntries.length === lease.selectionProof.requiredDeliveries
197
+ && selectionEntries.every((entry, index) => entry?.slot === index + 1
198
+ && (!admissionBound
199
+ || (ID_RE.test(entry?.applicationId || "") && DIGEST_RE.test(entry?.applicationDigest || "")))
200
+ && ID_RE.test(entry?.deliveryId || "") && DIGEST_RE.test(entry?.deliveryDigest || "")
201
+ && DIGEST_RE.test(entry?.evaluatorRootDigest || "")
202
+ && (!trialBound || (ID_RE.test(entry?.evaluatorId || "") && ID_RE.test(entry?.runId || "")
203
+ && DIGEST_RE.test(entry?.trialDigest || "")))
204
+ && entry?.authority === "context-only")
205
+ && new Set(selectionEntries.map((entry) => entry.deliveryId)).size === selectionEntries.length
206
+ && new Set(selectionEntries.map((entry) => entry.evaluatorRootDigest)).size === selectionEntries.length
207
+ && (!admissionBound
208
+ || new Set(selectionEntries.map((entry) => entry.applicationId)).size === selectionEntries.length)
209
+ && lease.selectionProof.authority === "context-only";
210
+ return ["agentspine.learning-validation/v1", "agentspine.learning-validation/v2",
211
+ "agentspine.learning-validation/v3", "agentspine.learning-validation/v4",
212
+ "agentspine.learning-validation/v5"].includes(lease.schema)
213
+ && ID_RE.test(lease.id || "")
214
+ && ID_RE.test(lease.learningId || "") && ID_RE.test(lease.evaluationId || "")
215
+ && DIGEST_RE.test(lease.evaluationDigest || "") && DIGEST_RE.test(lease.evaluatorRegistryBindingDigest || "")
216
+ && lease.scope && SCOPE_FIELDS.every((field) => Object.hasOwn(lease.scope, field))
217
+ && Object.keys(lease.scope).every((field) => SCOPE_FIELDS.includes(field))
218
+ && Object.values(lease.scope).every((value) => value === null || ID_RE.test(value))
219
+ && typeof lease.metric?.name === "string" && lease.metric.name.length > 0
220
+ && METRIC_DIRECTIONS.has(lease.metric?.direction)
221
+ && (lease.schema === "agentspine.learning-validation/v1"
222
+ ? validReferences(lease.beforeOutcomes) && validReferences(lease.afterOutcomes)
223
+ : validReferences(lease.baselineOutcomes) && validPredecessor && validRenewalEvidence
224
+ && (!["agentspine.learning-validation/v3", "agentspine.learning-validation/v4",
225
+ "agentspine.learning-validation/v5"].includes(lease.schema)
226
+ || validSelectionProof))
227
+ && Number.isFinite(lease.improvement) && lease.improvement >= -1 && lease.improvement <= 1
228
+ && Number.isFinite(new Date(lease.validatedAt).getTime()) && Number.isFinite(new Date(lease.expiresAt).getTime())
229
+ && new Date(lease.expiresAt).getTime() > new Date(lease.validatedAt).getTime()
230
+ && lease.authority === "context-only" && lease.digest === digest(payload);
231
+ }
232
+
233
+ export function validationLeaseMatchesState(state, lease) {
234
+ const candidate = state.candidates.find((item) => item.id === lease.learningId);
235
+ const canary = candidate?.promotion?.mode === "outcome-canary" ? candidate.promotion.canary : null;
236
+ const contract = state.evaluations.find((item) => item.id === lease.evaluationId);
237
+ const binding = state.evaluationBindings.find((item) => item.evaluationId === lease.evaluationId);
238
+ const referencesMatch = (references, phase) => references.every((reference) => state.outcomes.some((outcome) =>
239
+ outcome.id === reference.id && outcome.digest === reference.digest && outcome.learningId === lease.learningId
240
+ && outcome.evaluationId === lease.evaluationId && outcome.phase === phase && exactScope(outcome.scope, lease.scope)));
241
+ const common = candidate && canary && canary.status === "validated"
242
+ && canary.validationLeaseId === lease.id && canary.validationLeaseDigest === lease.digest
243
+ && canary.validatedAt === lease.validatedAt && canary.expiresAt === lease.expiresAt
244
+ && Math.abs(canary.improvement - lease.improvement) <= 1e-12
245
+ && REGISTRY_BOUND_EVALUATIONS.has(contract?.schema)
246
+ && contract.digest === lease.evaluationDigest
247
+ && (!INITIAL_TRIAL_EVALUATIONS.has(contract.schema)
248
+ || canary.initialTrialsDigest === digest(contract.initialTrials))
249
+ && (!TARGET_BOUND_EVALUATIONS.has(contract.schema)
250
+ || (canary.targetDigest === contract.target.digest && learningTargetMatchesCandidate(contract.target, candidate)))
251
+ && (!DEADLINE_BOUND_EVALUATIONS.has(contract.schema)
252
+ || canary.completionPolicyDigest === contract.completionPolicy.digest)
253
+ && (!STALENESS_BOUND_EVALUATIONS.has(contract.schema)
254
+ || canary.stalenessPolicyDigest === contract.stalenessPolicy.digest)
255
+ && binding?.digest === lease.evaluatorRegistryBindingDigest
256
+ && exactScope(contract.scope, lease.scope) && digest(contract.metric) === digest(lease.metric);
257
+ const evidenceMatches = lease.schema === "agentspine.learning-validation/v1"
258
+ ? lease.beforeOutcomes.length >= contract.thresholds.beforeReceipts
259
+ && lease.afterOutcomes.length >= contract.thresholds.afterReceipts
260
+ && referencesMatch(lease.beforeOutcomes, "before") && referencesMatch(lease.afterOutcomes, "after")
261
+ && canary.beforeReceipts.length === lease.beforeOutcomes.length
262
+ && lease.beforeOutcomes.every((reference) => canary.beforeReceipts.includes(reference.id))
263
+ && canary.afterReceipts.length === lease.afterOutcomes.length
264
+ && lease.afterOutcomes.every((reference) => canary.afterReceipts.includes(reference.id))
265
+ : lease.baselineOutcomes.length >= contract.thresholds.beforeReceipts
266
+ && referencesMatch(lease.baselineOutcomes, "before")
267
+ && lease.renewalEvidence.length >= contract.thresholds.afterReceipts
268
+ && state.history.some((entry) => entry.kind === "learning-validation"
269
+ && entry.value?.id === lease.predecessorValidation.id
270
+ && entry.value?.digest === lease.predecessorValidation.digest
271
+ && storedValidationLeaseStructure(entry.value))
272
+ && lease.renewalEvidence.every((evidence) => {
273
+ const measurement = state.measurements.find((entry) => entry.id === evidence.measurementId
274
+ && entry.digest === evidence.measurementDigest);
275
+ const application = state.applications.find((entry) => entry.id === evidence.applicationId
276
+ && entry.digest === evidence.applicationDigest);
277
+ const delivery = state.deliveries.find((entry) => entry.id === evidence.deliveryId
278
+ && entry.digest === evidence.deliveryDigest);
279
+ return measurement?.phase === "after" && measurement.evaluationId === lease.evaluationId
280
+ && measurement.measurement?.evaluatorRootDigest === evidence.evaluatorRootDigest
281
+ && application?.learningId === lease.learningId && delivery?.applicationId === application.id
282
+ && delivery.learningId === lease.learningId && exactScope(measurement.scope, lease.scope)
283
+ && exactScope(application.scope, lease.scope) && exactScope(delivery.scope, lease.scope);
284
+ });
285
+ const selectionMatches = !["agentspine.learning-validation/v3", "agentspine.learning-validation/v4",
286
+ "agentspine.learning-validation/v5"]
287
+ .includes(lease.schema) || (() => {
288
+ const historicalWindow = state.history.find((entry) => entry.kind === "learning-candidate"
289
+ && entry.value?.id === lease.learningId
290
+ && entry.value?.promotion?.canary?.revalidation?.id === lease.selectionProof.revalidationWindowId
291
+ && entry.value.promotion.canary.revalidation.digest === lease.selectionProof.revalidationWindowDigest)
292
+ ?.value?.promotion?.canary?.revalidation;
293
+ if (!storedRevalidationWindowStructure(historicalWindow)
294
+ || (lease.schema === "agentspine.learning-validation/v3"
295
+ ? historicalWindow.schema !== "agentspine.learning-revalidation-window/v2"
296
+ : lease.schema === "agentspine.learning-validation/v4"
297
+ ? historicalWindow.schema !== "agentspine.learning-revalidation-window/v3"
298
+ : historicalWindow.schema !== "agentspine.learning-revalidation-window/v4")
299
+ || historicalWindow.selection.mode !== lease.selectionProof.mode
300
+ || historicalWindow.selection.requiredDeliveries !== lease.selectionProof.requiredDeliveries) return false;
301
+ const selectedEntries = ["agentspine.learning-validation/v4", "agentspine.learning-validation/v5"].includes(lease.schema)
302
+ ? lease.selectionProof.applications : lease.selectionProof.deliveries;
303
+ return selectedEntries.every((selected, index) => {
304
+ const frozen = historicalWindow.selection.evaluatorRoots[index];
305
+ const evidence = lease.renewalEvidence.find((entry) => entry.deliveryId === selected.deliveryId);
306
+ const measurement = evidence ? state.measurements.find((entry) => entry.id === evidence.measurementId
307
+ && entry.digest === evidence.measurementDigest) : null;
308
+ const application = ["agentspine.learning-validation/v4", "agentspine.learning-validation/v5"].includes(lease.schema)
309
+ ? state.applications.find((entry) => entry.id === selected.applicationId
310
+ && entry.digest === selected.applicationDigest) : null;
311
+ return frozen?.slot === selected.slot && frozen.evaluatorRootDigest === selected.evaluatorRootDigest
312
+ && (lease.schema !== "agentspine.learning-validation/v5"
313
+ || (frozen.evaluatorId === selected.evaluatorId && frozen.runId === selected.runId
314
+ && frozen.trialDigest === selected.trialDigest
315
+ && measurement?.measurement?.evaluatorId === selected.evaluatorId
316
+ && measurement?.measurement?.runId === selected.runId
317
+ && measurement?.coverage?.caseCount === frozen.caseCount
318
+ && selected.trialDigest === revalidationTrialDigest({
319
+ evaluationId: lease.evaluationId, evaluationDigest: lease.evaluationDigest,
320
+ predecessorValidationId: lease.predecessorValidation.id,
321
+ predecessorValidationDigest: lease.predecessorValidation.digest,
322
+ slot: selected.slot, evaluatorId: selected.evaluatorId,
323
+ evaluatorRootDigest: selected.evaluatorRootDigest, runId: selected.runId,
324
+ benchmark: contract.benchmark, caseCount: frozen.caseCount
325
+ })))
326
+ && (!["agentspine.learning-validation/v4", "agentspine.learning-validation/v5"].includes(lease.schema)
327
+ || (evidence?.applicationId === selected.applicationId
328
+ && evidence.applicationDigest === selected.applicationDigest
329
+ && application?.schema === (lease.schema === "agentspine.learning-validation/v5"
330
+ ? "agentspine.learning-application/v4" : "agentspine.learning-application/v3")
331
+ && application.revalidationAdmission.revalidationWindowId === historicalWindow.id
332
+ && application.revalidationAdmission.revalidationWindowDigest === historicalWindow.digest
333
+ && application.revalidationAdmission.slot === selected.slot
334
+ && application.revalidationAdmission.evaluatorRootDigest === selected.evaluatorRootDigest
335
+ && (lease.schema !== "agentspine.learning-validation/v5"
336
+ || (application.revalidationAdmission.trialDigest === selected.trialDigest
337
+ && application.revalidationAdmission.runId === selected.runId
338
+ && application.revalidationAdmission.evaluatorId === selected.evaluatorId))))
339
+ && evidence?.deliveryDigest === selected.deliveryDigest
340
+ && evidence.evaluatorRootDigest === selected.evaluatorRootDigest;
341
+ });
342
+ })();
343
+ const initialSelectionMatches = !INITIAL_TRIAL_EVALUATIONS.has(contract?.schema)
344
+ || lease.schema !== "agentspine.learning-validation/v1" || (() => {
345
+ if (lease.beforeOutcomes.length !== contract.initialTrials.requiredTrials
346
+ || lease.afterOutcomes.length !== contract.initialTrials.requiredTrials) return false;
347
+ const outcomeMatchesTrial = (reference, phase, trial) => {
348
+ const outcome = state.outcomes.find((entry) => entry.id === reference.id && entry.digest === reference.digest);
349
+ const measurement = outcome && state.measurements.find((entry) => entry.id === outcome.measurementReceiptId
350
+ && entry.digest === outcome.measurementReceiptDigest);
351
+ if (!outcome || !measurement || outcome.phase !== phase
352
+ || measurement.measurement.evaluatorId !== trial.evaluatorId
353
+ || measurement.measurement.evaluatorRootDigest !== trial.evaluatorRootDigest
354
+ || measurement.measurement.runId !== trial.runId || measurement.coverage.caseCount !== trial.caseCount) return false;
355
+ if (phase === "before") return true;
356
+ const application = state.applications.find((entry) => entry.id === outcome.applicationId
357
+ && INITIAL_TRIAL_APPLICATIONS.has(entry.schema)
358
+ && entry.initialAdmission.evaluationId === contract.id
359
+ && entry.initialAdmission.evaluationDigest === contract.digest
360
+ && entry.initialAdmission.slot === trial.slot
361
+ && entry.initialAdmission.trialDigest === trial.trialDigest
362
+ && (!TARGET_BOUND_EVALUATIONS.has(contract.schema)
363
+ || (TARGET_BOUND_APPLICATIONS.has(entry.schema)
364
+ && entry.initialAdmission.targetDigest === contract.target.digest)));
365
+ const delivery = application && state.deliveries.find((entry) => entry.id === outcome.deliveryId
366
+ && entry.applicationId === application.id);
367
+ return Boolean(application && delivery);
368
+ };
369
+ return contract.initialTrials.before.every((trial, index) =>
370
+ outcomeMatchesTrial(lease.beforeOutcomes[index], "before", trial))
371
+ && contract.initialTrials.after.every((trial, index) =>
372
+ outcomeMatchesTrial(lease.afterOutcomes[index], "after", trial));
373
+ })();
374
+ return Boolean(common && evidenceMatches && selectionMatches && initialSelectionMatches);
375
+ }