blun-king-cli 9.1.566 → 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.
Files changed (262) hide show
  1. package/agent-spine-plugin/.claude-plugin/marketplace.json +1 -1
  2. package/agent-spine-plugin/.claude-plugin/plugin.json +1 -1
  3. package/agent-spine-plugin/.codex-plugin/plugin.json +2 -1
  4. package/agent-spine-plugin/CHANGELOG.md +1581 -0
  5. package/agent-spine-plugin/README.md +30 -4
  6. package/agent-spine-plugin/blun.plugin.json +3 -3
  7. package/agent-spine-plugin/docs/acceptance.md +61 -0
  8. package/agent-spine-plugin/docs/assignment-continuation.md +48 -0
  9. package/agent-spine-plugin/docs/host-integration.md +178 -0
  10. package/agent-spine-plugin/docs/preflight-recall.md +69 -0
  11. package/agent-spine-plugin/docs/preservation-contract.md +53 -0
  12. package/agent-spine-plugin/docs/quality-gates.md +50 -0
  13. package/agent-spine-plugin/docs/releasing.md +85 -0
  14. package/agent-spine-plugin/docs/session-timeline.md +251 -0
  15. package/agent-spine-plugin/docs/source-roots.md +113 -0
  16. package/agent-spine-plugin/docs/structured-completion.md +67 -0
  17. package/agent-spine-plugin/docs/world-model.md +94 -0
  18. package/agent-spine-plugin/hooks/codex.json +2 -2
  19. package/agent-spine-plugin/hooks/hooks.json +1 -1
  20. package/agent-spine-plugin/hooks/version.json +1 -1
  21. package/agent-spine-plugin/package.json +13 -3
  22. package/agent-spine-plugin/scripts/check-codex-install.js +226 -0
  23. package/agent-spine-plugin/scripts/check-hosts.js +14 -5
  24. package/agent-spine-plugin/scripts/check-install-hook.js +226 -0
  25. package/agent-spine-plugin/scripts/check-install-selfstarter.js +154 -0
  26. package/agent-spine-plugin/scripts/check-install.js +478 -0
  27. package/agent-spine-plugin/scripts/check-line-budget.js +58 -0
  28. package/agent-spine-plugin/scripts/check-syntax.js +29 -0
  29. package/agent-spine-plugin/scripts/github-actions.js +11 -0
  30. package/agent-spine-plugin/scripts/hermetic-process.js +183 -0
  31. package/agent-spine-plugin/scripts/release-check.js +145 -0
  32. package/agent-spine-plugin/scripts/run-acceptance.js +19 -0
  33. package/agent-spine-plugin/scripts/run-checks.js +47 -0
  34. package/agent-spine-plugin/scripts/run-tests-hermetic.js +89 -0
  35. package/agent-spine-plugin/skills/agent-spine/SKILL.md +16 -2
  36. package/agent-spine-plugin/spine-example/1-identity.md +12 -0
  37. package/agent-spine-plugin/spine-example/2-voice.md +6 -0
  38. package/agent-spine-plugin/spine-example/3-conduct.md +8 -0
  39. package/agent-spine-plugin/spine-example/4-history.md +4 -0
  40. package/agent-spine-plugin/src/cli-agent.js +296 -0
  41. package/agent-spine-plugin/src/cli-attention.js +95 -0
  42. package/agent-spine-plugin/src/cli-autonomy.js +36 -0
  43. package/agent-spine-plugin/src/cli-common.js +71 -0
  44. package/agent-spine-plugin/src/cli-continuity.js +116 -0
  45. package/agent-spine-plugin/src/cli-core.js +128 -0
  46. package/agent-spine-plugin/src/cli-diagnostics.js +291 -0
  47. package/agent-spine-plugin/src/cli-host.js +21 -0
  48. package/agent-spine-plugin/src/cli-learning.js +305 -0
  49. package/agent-spine-plugin/src/cli-premortem.js +16 -0
  50. package/agent-spine-plugin/src/cli-sharing.js +230 -0
  51. package/agent-spine-plugin/src/cli.js +40 -1350
  52. package/agent-spine-plugin/src/codex-reader-launcher.js +182 -0
  53. package/agent-spine-plugin/src/hook.js +185 -567
  54. package/agent-spine-plugin/src/index.js +16 -2
  55. package/agent-spine-plugin/src/lib/acceptance.js +113 -11
  56. package/agent-spine-plugin/src/lib/action-lesson-recall.js +53 -0
  57. package/agent-spine-plugin/src/lib/attention-context.js +167 -0
  58. package/agent-spine-plugin/src/lib/attention-events.js +113 -0
  59. package/agent-spine-plugin/src/lib/attention-privacy.js +72 -0
  60. package/agent-spine-plugin/src/lib/attention-schema.js +164 -0
  61. package/agent-spine-plugin/src/lib/attention-storage.js +93 -0
  62. package/agent-spine-plugin/src/lib/attention.js +9 -600
  63. package/agent-spine-plugin/src/lib/audit-premortem.js +223 -0
  64. package/agent-spine-plugin/src/lib/audit.js +56 -6
  65. package/agent-spine-plugin/src/lib/autonomy-policy.js +110 -0
  66. package/agent-spine-plugin/src/lib/autonomy-store.js +202 -0
  67. package/agent-spine-plugin/src/lib/autonomy.js +8 -0
  68. package/agent-spine-plugin/src/lib/briefing.js +67 -4
  69. package/agent-spine-plugin/src/lib/catalog-document-read.js +51 -0
  70. package/agent-spine-plugin/src/lib/catalog.js +1 -1
  71. package/agent-spine-plugin/src/lib/codex-installation.js +231 -0
  72. package/agent-spine-plugin/src/lib/codex-skill-installation.js +211 -0
  73. package/agent-spine-plugin/src/lib/context.js +3 -1
  74. package/agent-spine-plugin/src/lib/delivery-agent-usage.js +224 -0
  75. package/agent-spine-plugin/src/lib/delivery-assignment.js +220 -0
  76. package/agent-spine-plugin/src/lib/delivery-command-actions.js +453 -0
  77. package/agent-spine-plugin/src/lib/delivery-knowledge.js +78 -0
  78. package/agent-spine-plugin/src/lib/delivery-premortem-binding.js +107 -0
  79. package/agent-spine-plugin/src/lib/delivery-premortem-closure.js +171 -0
  80. package/agent-spine-plugin/src/lib/delivery-premortem-codec.js +45 -0
  81. package/agent-spine-plugin/src/lib/delivery-premortem-correction.js +101 -0
  82. package/agent-spine-plugin/src/lib/delivery-premortem-file.js +21 -0
  83. package/agent-spine-plugin/src/lib/delivery-premortem-index.js +493 -0
  84. package/agent-spine-plugin/src/lib/delivery-premortem-inspection.js +37 -0
  85. package/agent-spine-plugin/src/lib/delivery-premortem-recovery.js +120 -0
  86. package/agent-spine-plugin/src/lib/delivery-premortem-rejection.js +65 -0
  87. package/agent-spine-plugin/src/lib/delivery-premortem-results.js +28 -0
  88. package/agent-spine-plugin/src/lib/delivery-premortem-session-guard.js +46 -0
  89. package/agent-spine-plugin/src/lib/delivery-premortem-write-ledger.js +285 -0
  90. package/agent-spine-plugin/src/lib/delivery-premortem.js +499 -0
  91. package/agent-spine-plugin/src/lib/delivery-shell-heredoc.js +115 -0
  92. package/agent-spine-plugin/src/lib/delivery-shell-substitutions.js +111 -0
  93. package/agent-spine-plugin/src/lib/delivery-shell-wrapper.js +64 -0
  94. package/agent-spine-plugin/src/lib/delivery-target.js +73 -0
  95. package/agent-spine-plugin/src/lib/delivery-verification.js +445 -0
  96. package/agent-spine-plugin/src/lib/documents.js +27 -5
  97. package/agent-spine-plugin/src/lib/filesystem-retry.js +2 -0
  98. package/agent-spine-plugin/src/lib/gateway-common.js +68 -0
  99. package/agent-spine-plugin/src/lib/gateway-control.js +302 -0
  100. package/agent-spine-plugin/src/lib/gateway-delivery.js +103 -0
  101. package/agent-spine-plugin/src/lib/gateway-execution.js +350 -0
  102. package/agent-spine-plugin/src/lib/gateway-host-lifecycle.js +185 -0
  103. package/agent-spine-plugin/src/lib/gateway-inspection.js +85 -0
  104. package/agent-spine-plugin/src/lib/gateway-knowledge.js +129 -0
  105. package/agent-spine-plugin/src/lib/gateway-policy-provenance.js +197 -0
  106. package/agent-spine-plugin/src/lib/gateway-premortem-disposition.js +82 -0
  107. package/agent-spine-plugin/src/lib/gateway-premortem.js +363 -0
  108. package/agent-spine-plugin/src/lib/gateway-runs.js +300 -0
  109. package/agent-spine-plugin/src/lib/gateway-runtime-identity.js +31 -0
  110. package/agent-spine-plugin/src/lib/gateway-runtime-records.js +21 -0
  111. package/agent-spine-plugin/src/lib/gateway-runtime.js +18 -1623
  112. package/agent-spine-plugin/src/lib/gateway-state-transaction.js +356 -0
  113. package/agent-spine-plugin/src/lib/gateway-state.js +342 -0
  114. package/agent-spine-plugin/src/lib/hook-artifact-guards.js +356 -0
  115. package/agent-spine-plugin/src/lib/hook-audit.js +16 -2
  116. package/agent-spine-plugin/src/lib/hook-briefing-use.js +68 -0
  117. package/agent-spine-plugin/src/lib/hook-context.js +424 -0
  118. package/agent-spine-plugin/src/lib/hook-final-message.js +26 -0
  119. package/agent-spine-plugin/src/lib/hook-input.js +27 -0
  120. package/agent-spine-plugin/src/lib/hook-output.js +140 -0
  121. package/agent-spine-plugin/src/lib/hook-premortem.js +257 -0
  122. package/agent-spine-plugin/src/lib/hook-process-advisory.js +37 -0
  123. package/agent-spine-plugin/src/lib/hook-protection.js +95 -0
  124. package/agent-spine-plugin/src/lib/hook-stop-verification.js +84 -0
  125. package/agent-spine-plugin/src/lib/hook-timeline.js +91 -0
  126. package/agent-spine-plugin/src/lib/identifier-analysis.js +446 -0
  127. package/agent-spine-plugin/src/lib/indexed-memory.js +23 -6
  128. package/agent-spine-plugin/src/lib/knowledge-evidence.js +431 -0
  129. package/agent-spine-plugin/src/lib/learning-applications.js +441 -0
  130. package/agent-spine-plugin/src/lib/learning-candidates.js +274 -0
  131. package/agent-spine-plugin/src/lib/learning-context.js +130 -0
  132. package/agent-spine-plugin/src/lib/learning-delivery-contracts.js +310 -0
  133. package/agent-spine-plugin/src/lib/learning-evaluation-contracts.js +350 -0
  134. package/agent-spine-plugin/src/lib/learning-evaluation-registration.js +372 -0
  135. package/agent-spine-plugin/src/lib/learning-evaluation-revocation.js +292 -0
  136. package/agent-spine-plugin/src/lib/learning-evidence-contracts.js +321 -0
  137. package/agent-spine-plugin/src/lib/learning-findings.js +458 -0
  138. package/agent-spine-plugin/src/lib/learning-measurement-contracts.js +285 -0
  139. package/agent-spine-plugin/src/lib/learning-measurements.js +265 -0
  140. package/agent-spine-plugin/src/lib/learning-outcome-contracts.js +165 -0
  141. package/agent-spine-plugin/src/lib/learning-outcomes.js +343 -0
  142. package/agent-spine-plugin/src/lib/learning-reconciliation.js +290 -0
  143. package/agent-spine-plugin/src/lib/learning-retry-contracts.js +188 -0
  144. package/agent-spine-plugin/src/lib/learning-schema.js +229 -0
  145. package/agent-spine-plugin/src/lib/learning-scope-targets.js +424 -0
  146. package/agent-spine-plugin/src/lib/learning-state-upgrade.js +477 -0
  147. package/agent-spine-plugin/src/lib/learning-status-configuration.js +476 -0
  148. package/agent-spine-plugin/src/lib/learning-storage.js +203 -0
  149. package/agent-spine-plugin/src/lib/learning-trial-recovery.js +218 -0
  150. package/agent-spine-plugin/src/lib/learning-validation-contracts.js +375 -0
  151. package/agent-spine-plugin/src/lib/learning-validation-renewal.js +298 -0
  152. package/agent-spine-plugin/src/lib/learning-validation-runtime.js +234 -0
  153. package/agent-spine-plugin/src/lib/learning.js +36 -6923
  154. package/agent-spine-plugin/src/lib/lesson-recall-session.js +172 -0
  155. package/agent-spine-plugin/src/lib/mcp-autonomy-tools.js +37 -0
  156. package/agent-spine-plugin/src/lib/mcp-delivery-completion.js +124 -0
  157. package/agent-spine-plugin/src/lib/mcp-delivery-tools.js +45 -0
  158. package/agent-spine-plugin/src/lib/mcp-premortem.js +68 -0
  159. package/agent-spine-plugin/src/lib/mcp-runtime.js +269 -0
  160. package/agent-spine-plugin/src/lib/mcp-source-context.js +51 -0
  161. package/agent-spine-plugin/src/lib/mcp-timeline-tools.js +164 -0
  162. package/agent-spine-plugin/src/lib/mcp-world-tools.js +52 -0
  163. package/agent-spine-plugin/src/lib/owned-file-lock.js +30 -10
  164. package/agent-spine-plugin/src/lib/project-portfolio.js +176 -0
  165. package/agent-spine-plugin/src/lib/selfstarter-core.js +382 -0
  166. package/agent-spine-plugin/src/lib/selfstarter-jobs.js +149 -0
  167. package/agent-spine-plugin/src/lib/selfstarter-lease.js +204 -0
  168. package/agent-spine-plugin/src/lib/selfstarter-policy.js +90 -0
  169. package/agent-spine-plugin/src/lib/selfstarter-workspace.js +111 -0
  170. package/agent-spine-plugin/src/lib/selfstarter.js +11 -911
  171. package/agent-spine-plugin/src/lib/session-timeline-auth.js +316 -0
  172. package/agent-spine-plugin/src/lib/session-timeline-codex.js +58 -0
  173. package/agent-spine-plugin/src/lib/session-timeline-contract.js +48 -0
  174. package/agent-spine-plugin/src/lib/session-timeline-enrollment-source.js +41 -0
  175. package/agent-spine-plugin/src/lib/session-timeline-enrollment-storage.js +132 -0
  176. package/agent-spine-plugin/src/lib/session-timeline-enrollment-transport.js +17 -0
  177. package/agent-spine-plugin/src/lib/session-timeline-enrollment.js +500 -0
  178. package/agent-spine-plugin/src/lib/session-timeline-event-extract.js +157 -0
  179. package/agent-spine-plugin/src/lib/session-timeline-host-origin.js +74 -0
  180. package/agent-spine-plugin/src/lib/session-timeline-host-receipt.js +117 -0
  181. package/agent-spine-plugin/src/lib/session-timeline-invocation.js +201 -0
  182. package/agent-spine-plugin/src/lib/session-timeline-king.js +79 -0
  183. package/agent-spine-plugin/src/lib/session-timeline-prior.js +59 -0
  184. package/agent-spine-plugin/src/lib/session-timeline-provider.js +34 -0
  185. package/agent-spine-plugin/src/lib/session-timeline-query.js +55 -0
  186. package/agent-spine-plugin/src/lib/session-timeline-results.js +31 -0
  187. package/agent-spine-plugin/src/lib/session-timeline-root.js +11 -0
  188. package/agent-spine-plugin/src/lib/session-timeline-search.js +82 -0
  189. package/agent-spine-plugin/src/lib/session-timeline-sid-acl.js +217 -0
  190. package/agent-spine-plugin/src/lib/session-timeline-source.js +83 -0
  191. package/agent-spine-plugin/src/lib/session-timeline-state.js +45 -0
  192. package/agent-spine-plugin/src/lib/session-timeline-transport.js +50 -0
  193. package/agent-spine-plugin/src/lib/session-timeline-windows-acl.js +148 -0
  194. package/agent-spine-plugin/src/lib/session-timeline.js +453 -0
  195. package/agent-spine-plugin/src/lib/source-roots.js +69 -136
  196. package/agent-spine-plugin/src/lib/source-tree-scan.js +178 -0
  197. package/agent-spine-plugin/src/lib/task-knowledge-context.js +78 -0
  198. package/agent-spine-plugin/src/lib/timeline-tool-guard.js +202 -0
  199. package/agent-spine-plugin/src/lib/world-knowledge.js +249 -0
  200. package/agent-spine-plugin/src/lib/world-model.js +278 -0
  201. package/agent-spine-plugin/src/mcp.js +20 -161
  202. package/agent-spine-plugin/src/version.js +1 -1
  203. package/agent-spine-plugin/src/worker.js +22 -5
  204. package/bin/agent-resume-snapshot.cjs +2 -2
  205. package/bin/agentspine-king-goal-inbox.mjs +111 -0
  206. package/bin/agentspine-king-goal-intake.mjs +106 -0
  207. package/bin/baseline-skill-performance-policy.cjs +1 -16
  208. package/bin/core-bootstrap.js +2 -0
  209. package/bin/curiosity-scout-policy.cjs +5 -1
  210. package/bin/input-draft-persistence.cjs +2 -2
  211. package/bin/king-tui-function-contract.json +33 -0
  212. package/bin/launcher-restart-policy.cjs +150 -0
  213. package/bin/launcher-runtime.js +56 -44
  214. package/bin/managed-context-startup-policy.cjs +27 -0
  215. package/bin/managed-plugin-selection.cjs +116 -0
  216. package/bin/mistake-relevance-policy.cjs +1 -1
  217. package/bin/observer-hooks.cjs +14 -0
  218. package/bin/oversized-context-offload-policy.cjs +86 -0
  219. package/bin/plugin-bootstrap.js +7 -40
  220. package/bin/proactive-compaction-policy.cjs +1 -1
  221. package/bin/provider-model-refresh-deadline.cjs +53 -0
  222. package/bin/provider-model-refresh-policy.cjs +107 -0
  223. package/bin/release-artifact-freeze-policy.cjs +30 -0
  224. package/bin/repeated-user-message-projection.cjs +3 -126
  225. package/bin/research-page-result.cjs +74 -0
  226. package/bin/runtime-exit-ledger.cjs +1 -0
  227. package/bin/session-compaction-policy.cjs +84 -0
  228. package/bin/skill-listing-performance-policy.cjs +2 -2
  229. package/bin/standard-tools-bootstrap.js +0 -37
  230. package/bin/subagent-skill-policy.cjs +3 -1
  231. package/bin/telegram-approval-relay.cjs +12 -7
  232. package/bin/telegram-private-conversation-policy.cjs +3 -2
  233. package/bin/telegram-queue-handoff-policy.cjs +24 -0
  234. package/bin/thinking-activity-status-policy.cjs +1 -1
  235. package/bin/thinking-only-guard.cjs +16 -12
  236. package/bin/tool-call-loop-policy.cjs +0 -2
  237. package/bin/tool-result-offload-policy.cjs +11 -2
  238. package/bin/tui-functional-contract.cjs +55 -0
  239. package/bin/update-notice.js +18 -14
  240. package/bin/user-message-offload-policy.cjs +1 -1
  241. package/bin/user-prompt-hook-origin-policy.cjs +34 -0
  242. package/bin/windows-node-crash-dump.cjs +110 -0
  243. package/blun.mjs +2517 -1048
  244. package/codebase-index/codebase_index.py +4 -3
  245. package/package.json +3 -17
  246. package/standard-skills/research-evidence/SKILL.md +39 -0
  247. package/standard-skills/research-evidence/references/evidence-format.md +82 -0
  248. package/standard-skills/research-evidence/scripts/evidence-collection.cjs +254 -0
  249. package/standard-skills/research-evidence/scripts/score-report.cjs +112 -0
  250. package/standard-skills/web-lesen/SKILL.md +37 -22
  251. package/standard-skills/web-lesen/scripts/crawl_public.py +376 -0
  252. package/telegram-plugin/DELIVERY.md +36 -0
  253. package/telegram-plugin/bin/telegram-approval-relay.cjs +13 -7
  254. package/telegram-plugin/bin/telegram-launcher-status-queue.cjs +122 -0
  255. package/telegram-plugin/bin/telegram-private-conversation-policy.cjs +3 -2
  256. package/telegram-plugin/bin/telegram-reply-parts.cjs +149 -0
  257. package/telegram-plugin/dist/bridge.mjs +11 -57
  258. package/telegram-plugin/dist/mcp-server.mjs +33 -4
  259. package/agent-spine-plugin/skill/SKILL.md +0 -76
  260. package/bin/mnemo-connect-heartbeat.cjs +0 -204
  261. package/bin/mnemo-tool-agent-policy.cjs +0 -22
  262. package/telegram-plugin/bin/telegram-mnemo-capture.cjs +0 -297
@@ -0,0 +1,441 @@
1
+ import { createHash, randomUUID } from "node:crypto";
2
+ import {
3
+ ID_RE, INITIAL_TRIAL_EVALUATIONS, DEADLINE_BOUND_EVALUATIONS, DELIVERABLE_APPLICATIONS, INITIAL_TRIAL_APPLICATIONS, TARGET_BOUND_APPLICATIONS,
4
+ DELIVERY_REVOCATION_REASONS, OUTCOME_REVOCATION_REASONS, APPLICATION_REVOCATION_REASONS
5
+ } from "./learning-schema.js";
6
+ import {
7
+ normalizeScope, exactScope, digest, learningTargetForCandidate
8
+ } from "./learning-scope-targets.js";
9
+ import {
10
+ revokedEvaluationForCandidate
11
+ } from "./learning-validation-contracts.js";
12
+ import {
13
+ revokedValidationForCandidate
14
+ } from "./learning-validation-runtime.js";
15
+ import {
16
+ evaluationStalenessPolicy, revokedEvidenceSourceAttestationForCandidate
17
+ } from "./learning-measurement-contracts.js";
18
+ import {
19
+ applicationPayload
20
+ } from "./learning-evaluation-contracts.js";
21
+ import {
22
+ deliveryPayload, applicationRevocationPayload, revokedApplication, revokedApplicationForCandidate, deliveryRevocationPayload, revokedDelivery,
23
+ outcomeRevocationPayload, revokedOutcome
24
+ } from "./learning-delivery-contracts.js";
25
+ import {
26
+ date, safeText, mutation
27
+ } from "./learning-storage.js";
28
+
29
+ export async function recordLearningApplications({
30
+ root = process.cwd(), items, scope, preflightReceipt, sessionBriefingDigest, projectedAt = new Date()
31
+ }) {
32
+ if (!Array.isArray(items)) throw new Error("learning application items must be an array");
33
+ if (!preflightReceipt || preflightReceipt.schema !== "agentspine.preflight/v2"
34
+ || preflightReceipt.status !== "ready" || !ID_RE.test(preflightReceipt.id || "")
35
+ || !/^[a-f0-9]{64}$/.test(preflightReceipt.promptDigest || "")
36
+ || !/^[a-f0-9]{64}$/.test(preflightReceipt.briefingDigest || "")
37
+ || !ID_RE.test(preflightReceipt.sessionId || "")
38
+ || !/^[a-f0-9]{64}$/.test(sessionBriefingDigest || "")) {
39
+ throw new Error("learning applications require one valid consumed preflight binding");
40
+ }
41
+ const runtimeScope = normalizeScope(scope);
42
+ const timestamp = date(projectedAt, "projectedAt");
43
+ const preflightCreated = new Date(preflightReceipt.createdAt).getTime();
44
+ const preflightExpires = new Date(preflightReceipt.expiresAt).getTime();
45
+ if (!Number.isFinite(preflightCreated) || !Number.isFinite(preflightExpires)
46
+ || preflightCreated > new Date(timestamp).getTime() || preflightExpires < new Date(timestamp).getTime()) {
47
+ throw new Error("learning application preflight binding is stale");
48
+ }
49
+ if (preflightReceipt.agentId !== runtimeScope.personaId || preflightReceipt.userId !== runtimeScope.userId
50
+ || preflightReceipt.tenantId !== runtimeScope.tenantId || preflightReceipt.projectId !== runtimeScope.projectId
51
+ || preflightReceipt.groupId !== runtimeScope.groupId || preflightReceipt.taskId !== runtimeScope.taskId) {
52
+ throw new Error("learning application preflight scope does not match the projected turn");
53
+ }
54
+ return mutation(root, (state, _catalog, learningPath) => {
55
+ const pending = state.applications.filter((application) =>
56
+ DELIVERABLE_APPLICATIONS.has(application.schema)
57
+ && application.sessionId === preflightReceipt.sessionId
58
+ && application.preflightReceiptId !== preflightReceipt.id
59
+ && new Date(application.deliveryExpiresAt).getTime() >= new Date(timestamp).getTime()
60
+ && !state.deliveries.some((delivery) => delivery.applicationId === application.id));
61
+ if (pending.length) {
62
+ throw new Error("this session already has an unconfirmed learning application; await Stop or its bounded expiry");
63
+ }
64
+ const receipts = [];
65
+ for (const item of items.filter((entry) => ["active", "revalidating"].includes(entry?.outcomeStatus))) {
66
+ const candidate = state.candidates.find((entry) => entry.id === item.id);
67
+ const canary = candidate?.promotion?.canary;
68
+ const revalidating = item.outcomeStatus === "revalidating";
69
+ if (!candidate || candidate.status !== "accepted" || candidate.promotion?.mode !== "outcome-canary"
70
+ || revokedEvaluationForCandidate(state, candidate)
71
+ || revokedEvidenceSourceAttestationForCandidate(state, candidate)
72
+ || revokedValidationForCandidate(state, candidate)
73
+ || revokedApplicationForCandidate(state, candidate)
74
+ || (revalidating ? canary?.status !== "validated" || canary.revalidation?.status !== "active"
75
+ || new Date(canary.revalidation.expiresAt).getTime() < new Date(timestamp).getTime()
76
+ : canary?.status !== "active")
77
+ || !exactScope(canary.scope, runtimeScope)) {
78
+ throw new Error(`active learning application no longer matches its exact scope: ${item.id || "unknown"}`);
79
+ }
80
+ const expiresAt = revalidating ? canary.revalidation.expiresAt : canary.expiresAt;
81
+ let deliveryExpiresAt = new Date(Math.min(new Date(expiresAt).getTime(),
82
+ new Date(timestamp).getTime() + 5 * 60_000)).toISOString();
83
+ let outcomeExpiresAt;
84
+ let completionPolicyDigest;
85
+ const material = `${candidate.id}\0${preflightReceipt.id}\0${sessionBriefingDigest}`;
86
+ const id = `application:${createHash("sha256").update(material).digest("hex").slice(0, 32)}`;
87
+ const existing = state.applications.find((entry) => entry.id === id);
88
+ if (existing) {
89
+ const sameBinding = existing.learningId === candidate.id && exactScope(existing.scope, runtimeScope)
90
+ && existing.preflightReceiptId === preflightReceipt.id && existing.promptDigest === preflightReceipt.promptDigest
91
+ && existing.preflightBriefingDigest === preflightReceipt.briefingDigest
92
+ && existing.sessionBriefingDigest === sessionBriefingDigest;
93
+ if (!sameBinding) throw new Error("learning application receipt IDs are immutable");
94
+ receipts.push(existing);
95
+ continue;
96
+ }
97
+ let schema = "agentspine.learning-application/v2";
98
+ let revalidationAdmission;
99
+ let initialAdmission;
100
+ if (revalidating && ["agentspine.learning-revalidation-window/v3",
101
+ "agentspine.learning-revalidation-window/v4"].includes(canary.revalidation.schema)) {
102
+ const window = canary.revalidation;
103
+ const priorAdmissions = state.applications.filter((application) =>
104
+ ["agentspine.learning-application/v3", "agentspine.learning-application/v4"].includes(application.schema)
105
+ && application.revalidationAdmission.revalidationWindowId === window.id
106
+ && application.revalidationAdmission.revalidationWindowDigest === window.digest);
107
+ if (priorAdmissions.length < window.selection.requiredDeliveries) {
108
+ const slot = priorAdmissions.length + 1;
109
+ const trial = window.selection.evaluatorRoots[slot - 1];
110
+ schema = window.schema === "agentspine.learning-revalidation-window/v4"
111
+ ? "agentspine.learning-application/v4" : "agentspine.learning-application/v3";
112
+ revalidationAdmission = {
113
+ revalidationWindowId: window.id,
114
+ revalidationWindowDigest: window.digest,
115
+ slot,
116
+ evaluatorRootDigest: trial.evaluatorRootDigest,
117
+ ...(schema === "agentspine.learning-application/v4" ? {
118
+ evaluatorId: trial.evaluatorId, runId: trial.runId, trialDigest: trial.trialDigest
119
+ } : {}),
120
+ authority: "context-only"
121
+ };
122
+ }
123
+ }
124
+ if (!revalidating) {
125
+ const evaluation = state.evaluations.find((entry) => entry.id === canary.evaluationId
126
+ && entry.digest === canary.evaluationDigest && entry.learningId === candidate.id);
127
+ if (INITIAL_TRIAL_EVALUATIONS.has(evaluation?.schema)) {
128
+ const priorAdmissions = state.applications.filter((application) =>
129
+ INITIAL_TRIAL_APPLICATIONS.has(application.schema)
130
+ && application.initialAdmission.evaluationId === evaluation.id
131
+ && application.initialAdmission.evaluationDigest === evaluation.digest);
132
+ if (priorAdmissions.length < evaluation.initialTrials.requiredTrials) {
133
+ const slot = priorAdmissions.length + 1;
134
+ const trial = evaluation.initialTrials.after[slot - 1];
135
+ schema = DEADLINE_BOUND_EVALUATIONS.has(evaluation.schema)
136
+ ? "agentspine.learning-application/v7"
137
+ : evaluation.schema === "agentspine.learning-evaluation/v9"
138
+ ? "agentspine.learning-application/v6" : "agentspine.learning-application/v5";
139
+ initialAdmission = {
140
+ evaluationId: evaluation.id,
141
+ evaluationDigest: evaluation.digest,
142
+ slot,
143
+ evaluatorId: trial.evaluatorId,
144
+ evaluatorRootDigest: trial.evaluatorRootDigest,
145
+ runId: trial.runId,
146
+ trialDigest: trial.trialDigest,
147
+ ...(TARGET_BOUND_APPLICATIONS.has(schema) ? { targetDigest: evaluation.target.digest } : {}),
148
+ authority: "context-only"
149
+ };
150
+ if (schema === "agentspine.learning-application/v7") {
151
+ deliveryExpiresAt = new Date(Math.min(new Date(expiresAt).getTime(),
152
+ new Date(timestamp).getTime() + evaluation.completionPolicy.deliveryTimeoutMs)).toISOString();
153
+ outcomeExpiresAt = new Date(Math.min(new Date(expiresAt).getTime(),
154
+ new Date(timestamp).getTime() + evaluation.completionPolicy.outcomeTimeoutMs)).toISOString();
155
+ completionPolicyDigest = evaluation.completionPolicy.digest;
156
+ }
157
+ }
158
+ }
159
+ }
160
+ const payload = applicationPayload({ schema, id, learningId: candidate.id, scope: runtimeScope,
161
+ preflightReceiptId: preflightReceipt.id, promptDigest: preflightReceipt.promptDigest,
162
+ preflightBriefingDigest: preflightReceipt.briefingDigest, sessionBriefingDigest,
163
+ sessionId: preflightReceipt.sessionId, projectedAt: timestamp, deliveryExpiresAt, expiresAt,
164
+ revalidationAdmission, initialAdmission, outcomeExpiresAt, completionPolicyDigest });
165
+ const receipt = { ...payload, digest: digest(payload) };
166
+ if (state.applications.some((entry) => entry.learningId === candidate.id
167
+ && entry.preflightReceiptId === preflightReceipt.id)) {
168
+ throw new Error("one preflight turn cannot produce conflicting learning application receipts");
169
+ }
170
+ state.applications.push(receipt);
171
+ receipts.push(receipt);
172
+ }
173
+ state.applications.sort((a, b) => a.id.localeCompare(b.id));
174
+ return { schema: "agentspine.learning-application-batch/v2", receipts, learningPath,
175
+ authority: "context-only" };
176
+ });
177
+ }
178
+
179
+ export async function revokeLearningApplication({
180
+ root = process.cwd(), applicationId, reasonCode, reason, confirmation, now = new Date()
181
+ }) {
182
+ if (confirmation !== "local-application-revocation-confirmed") {
183
+ throw new Error("application revocation requires explicit local confirmation");
184
+ }
185
+ if (!ID_RE.test(applicationId || "")) throw new Error("applicationId must be a stable identifier");
186
+ if (!APPLICATION_REVOCATION_REASONS.has(reasonCode)) {
187
+ throw new Error("reasonCode must be preflight-invalid, scope-invalid, projection-invalid, duplicate, or other");
188
+ }
189
+ const revokeReason = safeText(reason, "reason", 500);
190
+ const timestamp = date(now, "now");
191
+ return mutation(root, (state, _catalog, learningPath) => {
192
+ const application = state.applications.find((entry) => entry.id === applicationId);
193
+ if (!application) throw new Error(`unknown learning application: ${applicationId}`);
194
+ const candidate = state.candidates.find((entry) => entry.id === application.learningId);
195
+ const evaluationId = application.initialAdmission?.evaluationId || candidate?.promotion?.canary?.evaluationId;
196
+ const evaluation = state.evaluations.find((entry) => entry.id === evaluationId);
197
+ const deliveries = state.deliveries.filter((entry) => entry.applicationId === application.id);
198
+ const outcomes = state.outcomes.filter((entry) => entry.applicationId === application.id);
199
+ if (deliveries.length > 1 || outcomes.length > 1) {
200
+ throw new Error("application revocation requires one unambiguous delivery and outcome lineage");
201
+ }
202
+ const delivery = deliveries[0] || null;
203
+ const outcome = outcomes[0] || null;
204
+ if (!candidate || !evaluation || evaluation.learningId !== candidate.id
205
+ || application.learningId !== candidate.id || (outcome && outcome.deliveryId !== delivery?.id)) {
206
+ throw new Error("application revocation requires its complete immutable evaluation lineage");
207
+ }
208
+ const targetDigest = learningTargetForCandidate(candidate).digest;
209
+ const reasonDigest = digest(revokeReason);
210
+ const existing = revokedApplication(state, applicationId);
211
+ if (existing) {
212
+ if (existing.reasonCode !== reasonCode || existing.reasonDigest !== reasonDigest
213
+ || existing.applicationDigest !== application.digest || existing.evaluationDigest !== evaluation.digest
214
+ || existing.deliveryId !== (delivery?.id || null) || existing.deliveryDigest !== (delivery?.digest || null)
215
+ || existing.outcomeId !== (outcome?.id || null) || existing.outcomeDigest !== (outcome?.digest || null)
216
+ || existing.targetDigest !== targetDigest) {
217
+ throw new Error("learning application revocations are immutable");
218
+ }
219
+ return { receipt: existing, learningPath, unchanged: true, authority: "context-only" };
220
+ }
221
+ const id = `application-revocation:${createHash("sha256")
222
+ .update(`${application.id}\0${application.digest}\0${targetDigest}`).digest("hex").slice(0, 32)}`;
223
+ const payload = applicationRevocationPayload({
224
+ id,
225
+ learningId: candidate.id,
226
+ evaluationId: evaluation.id,
227
+ evaluationDigest: evaluation.digest,
228
+ applicationId: application.id,
229
+ applicationDigest: application.digest,
230
+ deliveryId: delivery?.id || null,
231
+ deliveryDigest: delivery?.digest || null,
232
+ outcomeId: outcome?.id || null,
233
+ outcomeDigest: outcome?.digest || null,
234
+ targetDigest,
235
+ reasonCode,
236
+ reasonDigest,
237
+ revokedAt: timestamp
238
+ });
239
+ const receipt = { ...payload, digest: digest(payload) };
240
+ state.applicationRevocations.push(receipt);
241
+ state.applicationRevocations.sort((a, b) => a.id.localeCompare(b.id));
242
+ return { receipt, learningPath, unchanged: false, authority: "context-only" };
243
+ });
244
+ }
245
+
246
+ export async function recordLearningDeliveries({
247
+ root = process.cwd(), sessionId, scope, hookEvent, completedAt = new Date()
248
+ }) {
249
+ if (!ID_RE.test(sessionId || "")) throw new Error("learning delivery sessionId is required");
250
+ if (!["Stop", "SubagentStop"].includes(hookEvent)) throw new Error("learning delivery requires Stop or SubagentStop");
251
+ const runtimeScope = normalizeScope(scope);
252
+ const timestamp = date(completedAt, "completedAt");
253
+ return mutation(root, (state, _catalog, learningPath) => {
254
+ const candidates = state.applications.filter((application) =>
255
+ DELIVERABLE_APPLICATIONS.has(application.schema)
256
+ && application.sessionId === sessionId && exactScope(application.scope, runtimeScope));
257
+ if (!candidates.length) return { schema: "agentspine.learning-delivery-batch/v1", status: "not-applicable",
258
+ receipts: [], learningPath, authority: "context-only" };
259
+ if (candidates.some((application) => revokedApplication(state, application.id))) {
260
+ throw new Error("learning application was explicitly revoked and cannot produce a delivery");
261
+ }
262
+ if (candidates.some((application) => {
263
+ const candidate = state.candidates.find((entry) => entry.id === application.learningId);
264
+ return revokedEvaluationForCandidate(state, candidate);
265
+ })) throw new Error("learning evaluation contract was explicitly revoked and cannot produce a delivery");
266
+ if (candidates.some((application) => {
267
+ const candidate = state.candidates.find((entry) => entry.id === application.learningId);
268
+ return revokedEvidenceSourceAttestationForCandidate(state, candidate);
269
+ })) throw new Error("learning evidence source attestation was explicitly revoked and cannot produce a delivery");
270
+ if (candidates.some((application) => {
271
+ const candidate = state.candidates.find((entry) => entry.id === application.learningId);
272
+ return revokedValidationForCandidate(state, candidate);
273
+ })) throw new Error("learning validation decision was explicitly revoked and cannot produce a delivery");
274
+ const latest = [...candidates].sort((a, b) => b.projectedAt.localeCompare(a.projectedAt))[0];
275
+ const batch = candidates.filter((application) => application.preflightReceiptId === latest.preflightReceiptId);
276
+ if (new Date(timestamp).getTime() > new Date(latest.deliveryExpiresAt).getTime()) {
277
+ return { schema: "agentspine.learning-delivery-batch/v1", status: "stale", receipts: [], learningPath,
278
+ authority: "context-only" };
279
+ }
280
+ const receipts = [];
281
+ for (const application of batch) {
282
+ const existingForApplication = state.deliveries.find((entry) => entry.applicationId === application.id);
283
+ if (existingForApplication) {
284
+ if (existingForApplication.sessionId !== sessionId || existingForApplication.hookEvent !== hookEvent
285
+ || !exactScope(existingForApplication.scope, runtimeScope)) {
286
+ throw new Error("one learning application cannot have conflicting delivery receipts");
287
+ }
288
+ receipts.push(existingForApplication);
289
+ continue;
290
+ }
291
+ const id = `delivery:${createHash("sha256").update(`${application.id}\0${hookEvent}`).digest("hex").slice(0, 32)}`;
292
+ const payload = deliveryPayload({ id, applicationId: application.id, learningId: application.learningId,
293
+ scope: runtimeScope, sessionId, preflightReceiptId: application.preflightReceiptId, hookEvent,
294
+ completedAt: timestamp });
295
+ const receipt = { ...payload, digest: digest(payload) };
296
+ if (state.deliveries.some((entry) => entry.id === id)) throw new Error("learning delivery receipt IDs are immutable");
297
+ state.deliveries.push(receipt);
298
+ receipts.push(receipt);
299
+ }
300
+ state.deliveries.sort((a, b) => a.id.localeCompare(b.id));
301
+ return { schema: "agentspine.learning-delivery-batch/v1", status: receipts.length ? "completed" : "not-applicable",
302
+ receipts, learningPath, authority: "context-only" };
303
+ });
304
+ }
305
+
306
+ export async function revokeLearningDelivery({
307
+ root = process.cwd(), deliveryId, reasonCode, reason, confirmation, now = new Date()
308
+ }) {
309
+ if (confirmation !== "local-delivery-revocation-confirmed") {
310
+ throw new Error("delivery revocation requires explicit local confirmation");
311
+ }
312
+ if (!ID_RE.test(deliveryId || "")) throw new Error("deliveryId must be a stable identifier");
313
+ if (!DELIVERY_REVOCATION_REASONS.has(reasonCode)) {
314
+ throw new Error("reasonCode must be host-invalid, session-invalid, hook-invalid, duplicate, or other");
315
+ }
316
+ const revokeReason = safeText(reason, "reason", 500);
317
+ const timestamp = date(now, "now");
318
+ return mutation(root, (state, _catalog, learningPath) => {
319
+ const delivery = state.deliveries.find((entry) => entry.id === deliveryId);
320
+ if (!delivery) throw new Error(`unknown learning delivery: ${deliveryId}`);
321
+ const application = state.applications.find((entry) => entry.id === delivery.applicationId);
322
+ const candidate = state.candidates.find((entry) => entry.id === delivery.learningId);
323
+ const outcomes = state.outcomes.filter((entry) => entry.deliveryId === delivery.id);
324
+ if (outcomes.length > 1) throw new Error("delivery revocation requires one unambiguous bound outcome");
325
+ const outcome = outcomes[0] || null;
326
+ const evaluationId = outcome?.evaluationId || candidate?.promotion?.canary?.evaluationId;
327
+ const evaluation = state.evaluations.find((entry) => entry.id === evaluationId);
328
+ if (!candidate || !application || !evaluation || application.learningId !== candidate.id
329
+ || evaluation.learningId !== candidate.id) {
330
+ throw new Error("delivery revocation requires its bound candidate, application, and evaluation contract");
331
+ }
332
+ const targetDigest = learningTargetForCandidate(candidate).digest;
333
+ const reasonDigest = digest(revokeReason);
334
+ const existing = revokedDelivery(state, deliveryId);
335
+ if (existing) {
336
+ if (existing.reasonCode !== reasonCode || existing.reasonDigest !== reasonDigest
337
+ || existing.deliveryDigest !== delivery.digest || existing.applicationDigest !== application.digest
338
+ || existing.evaluationDigest !== evaluation.digest || existing.targetDigest !== targetDigest
339
+ || existing.outcomeId !== (outcome?.id || null) || existing.outcomeDigest !== (outcome?.digest || null)) {
340
+ throw new Error("learning delivery revocations are immutable");
341
+ }
342
+ return { receipt: existing, learningPath, unchanged: true, authority: "context-only" };
343
+ }
344
+ const id = `delivery-revocation:${createHash("sha256")
345
+ .update(`${delivery.id}\0${delivery.digest}\0${targetDigest}`).digest("hex").slice(0, 32)}`;
346
+ const payload = deliveryRevocationPayload({
347
+ id,
348
+ learningId: candidate.id,
349
+ evaluationId: evaluation.id,
350
+ evaluationDigest: evaluation.digest,
351
+ applicationId: application.id,
352
+ applicationDigest: application.digest,
353
+ deliveryId: delivery.id,
354
+ deliveryDigest: delivery.digest,
355
+ outcomeId: outcome?.id || null,
356
+ outcomeDigest: outcome?.digest || null,
357
+ targetDigest,
358
+ reasonCode,
359
+ reasonDigest,
360
+ revokedAt: timestamp
361
+ });
362
+ const receipt = { ...payload, digest: digest(payload) };
363
+ state.deliveryRevocations.push(receipt);
364
+ state.deliveryRevocations.sort((a, b) => a.id.localeCompare(b.id));
365
+ return { receipt, learningPath, unchanged: false, authority: "context-only" };
366
+ });
367
+ }
368
+
369
+ export async function revokeLearningOutcome({
370
+ root = process.cwd(), outcomeId, reasonCode, reason, confirmation, now = new Date()
371
+ }) {
372
+ if (confirmation !== "local-outcome-revocation-confirmed") {
373
+ throw new Error("outcome revocation requires explicit local confirmation");
374
+ }
375
+ if (!ID_RE.test(outcomeId || "")) throw new Error("outcomeId must be a stable identifier");
376
+ if (!OUTCOME_REVOCATION_REASONS.has(reasonCode)) {
377
+ throw new Error("reasonCode must be binding-invalid, phase-invalid, scope-invalid, duplicate, or other");
378
+ }
379
+ const revokeReason = safeText(reason, "reason", 500);
380
+ const timestamp = date(now, "now");
381
+ return mutation(root, (state, _catalog, learningPath) => {
382
+ const outcome = state.outcomes.find((entry) => entry.id === outcomeId);
383
+ if (!outcome) throw new Error(`unknown learning outcome: ${outcomeId}`);
384
+ const candidate = state.candidates.find((entry) => entry.id === outcome.learningId);
385
+ const evaluation = state.evaluations.find((entry) => entry.id === outcome.evaluationId);
386
+ const measurement = outcome.measurementReceiptId
387
+ ? state.measurements.find((entry) => entry.id === outcome.measurementReceiptId) : null;
388
+ const application = outcome.applicationId
389
+ ? state.applications.find((entry) => entry.id === outcome.applicationId) : null;
390
+ const delivery = outcome.deliveryId
391
+ ? state.deliveries.find((entry) => entry.id === outcome.deliveryId) : null;
392
+ if (!candidate || !evaluation || evaluation.learningId !== candidate.id
393
+ || (outcome.measurementReceiptId && !measurement)
394
+ || (outcome.applicationId && !application) || (outcome.deliveryId && !delivery)) {
395
+ throw new Error("outcome revocation requires its complete immutable evaluation lineage");
396
+ }
397
+ const targetDigest = learningTargetForCandidate(candidate).digest;
398
+ const reasonDigest = digest(revokeReason);
399
+ const existing = revokedOutcome(state, outcomeId);
400
+ if (existing) {
401
+ if (existing.reasonCode !== reasonCode || existing.reasonDigest !== reasonDigest
402
+ || existing.outcomeDigest !== outcome.digest || existing.evaluationDigest !== evaluation.digest
403
+ || existing.measurementDigest !== (measurement?.digest || null)
404
+ || existing.applicationDigest !== (application?.digest || null)
405
+ || existing.deliveryDigest !== (delivery?.digest || null) || existing.targetDigest !== targetDigest) {
406
+ throw new Error("learning outcome revocations are immutable");
407
+ }
408
+ return { receipt: existing, learningPath, unchanged: true, authority: "context-only" };
409
+ }
410
+ const id = `outcome-revocation:${createHash("sha256")
411
+ .update(`${outcome.id}\0${outcome.digest}\0${targetDigest}`).digest("hex").slice(0, 32)}`;
412
+ const payload = outcomeRevocationPayload({
413
+ id,
414
+ learningId: candidate.id,
415
+ evaluationId: evaluation.id,
416
+ evaluationDigest: evaluation.digest,
417
+ outcomeId: outcome.id,
418
+ outcomeDigest: outcome.digest,
419
+ measurementId: measurement?.id || null,
420
+ measurementDigest: measurement?.digest || null,
421
+ applicationId: application?.id || null,
422
+ applicationDigest: application?.digest || null,
423
+ deliveryId: delivery?.id || null,
424
+ deliveryDigest: delivery?.digest || null,
425
+ targetDigest,
426
+ reasonCode,
427
+ reasonDigest,
428
+ revokedAt: timestamp
429
+ });
430
+ const receipt = { ...payload, digest: digest(payload) };
431
+ state.outcomeRevocations.push(receipt);
432
+ state.outcomeRevocations.sort((a, b) => a.id.localeCompare(b.id));
433
+ return { receipt, learningPath, unchanged: false, authority: "context-only" };
434
+ });
435
+ }
436
+
437
+ export function outcomeFresh(receipt, contract, config, now) {
438
+ const policy = evaluationStalenessPolicy(contract, config);
439
+ return new Date(receipt.measuredAt).getTime() >= new Date(now).getTime()
440
+ - policy.outcomeMaxAgeDays * 86400000;
441
+ }