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.
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 +7 -56
  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,223 @@
1
+ import { createHash } from "node:crypto";
2
+ import { basename } from "node:path";
3
+ import { inspectDeliveryPremortems } from "./delivery-premortem.js";
4
+ import { createPremortemAttachment } from "./delivery-premortem-closure.js";
5
+ import { premortemGoalBindingSummary } from "./delivery-premortem-binding.js";
6
+ import { inspectPremortemLaneIndexes, premortemScopeDigest } from "./delivery-premortem-index.js";
7
+ import {
8
+ inspectPremortemWriteIndexes,
9
+ inspectPremortemWriteProof
10
+ } from "./delivery-premortem-write-ledger.js";
11
+
12
+ const WRITE_INDEX_MISMATCH = "AGENTSPINE_PREMORTEM_MISMATCH";
13
+
14
+ export function premortemIndexCrossReferenceFindings(premortems, indexes, gatewayPolicy) {
15
+ const findings = [];
16
+ const statesByLane = new Map(premortems.states.map((state) => [state.laneDigest, state]));
17
+ const pointersByLane = new Map();
18
+ for (const pointer of indexes.pointers) {
19
+ const values = pointersByLane.get(pointer.laneDigest) || [];
20
+ values.push(pointer);
21
+ pointersByLane.set(pointer.laneDigest, values);
22
+ }
23
+ const stateScanComplete = !premortems.errors.length && !premortems.truncations.length;
24
+ const indexScanComplete = !indexes.errors.length && !indexes.truncations.length;
25
+ if (stateScanComplete) for (const pointer of indexes.pointers) {
26
+ const state = statesByLane.get(pointer.laneDigest);
27
+ if (!state) {
28
+ findings.push({ laneDigest: pointer.laneDigest, reason: "premortem index pointer has no state" });
29
+ continue;
30
+ }
31
+ const binding = state.binding;
32
+ const sessionDigest = createHash("sha256").update(binding.sessionId).digest("hex");
33
+ if (pointer.sessionDigest !== sessionDigest || pointer.goalId !== binding.goalId
34
+ || pointer.goalStepId !== binding.goalStepId || pointer.queueId !== binding.queueId
35
+ || pointer.gatewayAttempt !== binding.gatewayAttempt
36
+ || pointer.planDefinitionsDigest !== binding.planDefinitionsDigest) {
37
+ findings.push({ laneDigest: pointer.laneDigest,
38
+ reason: "premortem index pointer does not match state binding" });
39
+ }
40
+ }
41
+ if (indexScanComplete) for (const state of premortems.states.filter((item) => item.binding.goalId)) {
42
+ const pointers = pointersByLane.get(state.laneDigest) || [];
43
+ if (!pointers.length) findings.push({ laneDigest: state.laneDigest,
44
+ reason: "goal premortem state has no index pointer" });
45
+ else if (pointers.length > 1) findings.push({ laneDigest: state.laneDigest,
46
+ reason: "goal premortem state has multiple index pointers" });
47
+ const consumed = state.events.some((event) => event.type === "premortem-consumed");
48
+ const finalized = indexes.finalizations.some((item) => item.laneDigest === state.laneDigest);
49
+ if (consumed && !finalized) findings.push({ laneDigest: state.laneDigest,
50
+ reason: "consumed goal premortem state has no scope finalization" });
51
+ }
52
+ if (stateScanComplete && indexScanComplete) for (const finalization of indexes.finalizations) {
53
+ const scopedPointers = indexes.pointers.filter((item) => item.scopeDigest === finalization.scopeDigest);
54
+ const scopedStates = premortems.states.filter((state) => state.binding.goalId
55
+ && premortemScopeDigest(state.binding.goalId, state.binding.goalStepId,
56
+ state.binding.queueId, state.binding.gatewayAttempt) === finalization.scopeDigest);
57
+ if (finalization.status === "read-only") {
58
+ if (scopedPointers.length || scopedStates.length) findings.push({ laneDigest: null,
59
+ reason: "read-only premortem finalization retains state or index evidence" });
60
+ continue;
61
+ }
62
+ const pointer = scopedPointers.length === 1 ? scopedPointers[0] : null;
63
+ const state = scopedStates.length === 1 ? scopedStates[0] : null;
64
+ if (!pointer || !state || pointer.laneDigest !== finalization.laneDigest) {
65
+ findings.push({ laneDigest: finalization.laneDigest,
66
+ reason: "closed premortem finalization is orphaned" });
67
+ continue;
68
+ }
69
+ if (pointer.digest !== finalization.pointerDigest) findings.push({ laneDigest: state.laneDigest,
70
+ reason: "closed premortem finalization has the wrong pointer digest" });
71
+ const consumed = state.events.some((event) => event.type === "premortem-consumed");
72
+ if (!consumed || !state.closure || !state.lastWrite) findings.push({ laneDigest: state.laneDigest,
73
+ reason: "closed premortem finalization has no consumed closed state" });
74
+ else if (createPremortemAttachment(state).attachmentDigest !== finalization.attachmentDigest) {
75
+ findings.push({ laneDigest: state.laneDigest,
76
+ reason: "closed premortem finalization has the wrong attachment digest" });
77
+ }
78
+ const binding = state.binding;
79
+ const exact = finalization.goalId === binding.goalId && finalization.goalStepId === binding.goalStepId
80
+ && finalization.queueId === binding.queueId && finalization.gatewayAttempt === binding.gatewayAttempt
81
+ && finalization.planDefinitionsDigest === binding.planDefinitionsDigest
82
+ && finalization.host === binding.host && finalization.projectId === binding.projectId
83
+ && finalization.entityId === binding.entityId && finalization.groupId === binding.groupId
84
+ && finalization.taskId === binding.taskId;
85
+ const summaryDigest = createHash("sha256")
86
+ .update(JSON.stringify([premortemGoalBindingSummary(state).digest])).digest("hex");
87
+ if (!exact || finalization.bindingSummaryDigest !== summaryDigest) findings.push({ laneDigest: state.laneDigest,
88
+ reason: "closed premortem finalization has the wrong binding evidence" });
89
+ }
90
+ if (indexScanComplete) for (const goal of gatewayPolicy.goals || []) {
91
+ for (const step of goal.plan?.steps || []) {
92
+ const checkpoint = step.deliveryCheckpoint;
93
+ const outcome = step.outcomeReceipt;
94
+ if (step.status !== "completed" || !new Set(["closed", "read-only"]).has(checkpoint?.status)) continue;
95
+ const finalization = indexes.finalizations.find((item) => item.digest === checkpoint.scopeFinalizationDigest);
96
+ if (!finalization) {
97
+ findings.push({ laneDigest: checkpoint.bindingDigest ?? null,
98
+ reason: "completed goal premortem has no bound scope finalization" });
99
+ continue;
100
+ }
101
+ const exact = finalization.status === checkpoint.status && finalization.goalId === goal.goalId
102
+ && finalization.goalStepId === step.stepId && finalization.queueId === checkpoint.queueId
103
+ && finalization.gatewayAttempt === checkpoint.gatewayAttempt
104
+ && finalization.planDefinitionsDigest === checkpoint.planDefinitionsDigest
105
+ && finalization.host === checkpoint.host && finalization.projectId === checkpoint.projectId
106
+ && finalization.entityId === checkpoint.entityId && finalization.groupId === checkpoint.groupId
107
+ && finalization.taskId === (checkpoint.taskId ?? null);
108
+ if (!exact) findings.push({ laneDigest: checkpoint.bindingDigest ?? null,
109
+ reason: "completed goal premortem scope finalization has the wrong binding" });
110
+ if (checkpoint.status === "closed" && (checkpoint.sourceAttachmentDigest
111
+ !== finalization.attachmentDigest || outcome?.sourceAttachmentDigest
112
+ !== finalization.attachmentDigest)) {
113
+ findings.push({ laneDigest: checkpoint.bindingDigest ?? null,
114
+ reason: "completed goal premortem source attachment does not match scope finalization" });
115
+ }
116
+ }
117
+ }
118
+ return findings;
119
+ }
120
+
121
+ function boundedWrites(state) {
122
+ const writes = [state.firstWrite, state.lastWrite, ...(state.writeLedger || [])].filter(Boolean);
123
+ return [...new Map(writes.map((write) => [write.idDigest, {
124
+ idDigest: write.idDigest, inputDigest: write.inputDigest,
125
+ inputKnown: write.inputKnown, writeDigest: write.writeDigest || write.digest
126
+ }])).values()];
127
+ }
128
+
129
+ function sameWrite(entry, expected) {
130
+ return entry?.idDigest === expected.idDigest && entry.inputDigest === expected.inputDigest
131
+ && entry.inputKnown === expected.inputKnown && entry.writeDigest === expected.writeDigest;
132
+ }
133
+
134
+ function addIssue(target, seen, laneDigest, item, fallbackPath) {
135
+ const issue = { laneDigest, path: item.path || fallbackPath,
136
+ reason: String(item.reason || "premortem write-index inspection failed").slice(0, 400),
137
+ code: typeof item.code === "string" ? item.code : null };
138
+ const key = `${laneDigest}:${issue.code}:${issue.reason}`;
139
+ if (!seen.has(key)) {
140
+ seen.add(key);
141
+ target.push(issue);
142
+ }
143
+ }
144
+
145
+ export async function inspectPremortemWriteIndexAudit(premortems, {
146
+ inspectIndexes = inspectPremortemWriteIndexes,
147
+ inspectProof = inspectPremortemWriteProof
148
+ } = {}) {
149
+ const combined = { directories: [], paths: [], nodes: [], errors: [], uncertainties: [],
150
+ truncations: [], states: 0, attemptedProofs: 0, verifiedProofs: 0,
151
+ authority: "context-only" };
152
+ const paths = new Set();
153
+ const errorKeys = new Set();
154
+ const uncertaintyKeys = new Set();
155
+ for (const state of premortems.states.filter((item) => item.writeIndexRoot)) {
156
+ const statePath = premortems.paths.find((path) => basename(path) === `${state.laneDigest}.json`);
157
+ if (!statePath) {
158
+ addIssue(combined.uncertainties, uncertaintyKeys, state.laneDigest, {
159
+ path: premortems.directory,
160
+ reason: `premortem state ${state.laneDigest} has no inspected path`
161
+ }, premortems.directory);
162
+ if (premortems.directory) paths.add(premortems.directory);
163
+ continue;
164
+ }
165
+ combined.states += 1;
166
+ let inspected;
167
+ try {
168
+ inspected = await inspectIndexes({ statePath, state });
169
+ } catch (error) {
170
+ const target = error.code === WRITE_INDEX_MISMATCH
171
+ ? [combined.errors, errorKeys] : [combined.uncertainties, uncertaintyKeys];
172
+ addIssue(target[0], target[1], state.laneDigest, {
173
+ path: error.path || statePath, reason: error.message, code: error.code
174
+ }, statePath);
175
+ paths.add(error.path || statePath);
176
+ continue;
177
+ }
178
+ combined.directories.push(inspected.directory);
179
+ for (const path of inspected.paths) paths.add(path);
180
+ combined.nodes.push(...inspected.nodes);
181
+ combined.truncations.push(...inspected.truncations);
182
+ for (const item of inspected.errors) {
183
+ if (item.path) paths.add(item.path);
184
+ const target = item.code === WRITE_INDEX_MISMATCH
185
+ ? [combined.errors, errorKeys] : [combined.uncertainties, uncertaintyKeys];
186
+ addIssue(target[0], target[1], state.laneDigest, item, statePath);
187
+ }
188
+ for (const item of inspected.truncations) if (item.path) paths.add(item.path);
189
+ for (const expected of boundedWrites(state)) {
190
+ combined.attemptedProofs += 1;
191
+ try {
192
+ const proof = await inspectProof({ statePath, laneDigest: state.laneDigest,
193
+ rootDigest: state.writeIndexRoot, idDigest: expected.idDigest });
194
+ for (const path of proof.paths) paths.add(path);
195
+ if (!sameWrite(proof.entry, expected)) {
196
+ addIssue(combined.errors, errorKeys, state.laneDigest, {
197
+ path: proof.paths.at(-1) || statePath, code: WRITE_INDEX_MISMATCH,
198
+ reason: "premortem write index does not prove a bounded write"
199
+ }, statePath);
200
+ } else combined.verifiedProofs += 1;
201
+ } catch (error) {
202
+ const item = { path: error.path || inspected.paths[0] || statePath,
203
+ reason: error.message, code: error.code };
204
+ const target = error.code === WRITE_INDEX_MISMATCH
205
+ ? [combined.errors, errorKeys] : [combined.uncertainties, uncertaintyKeys];
206
+ addIssue(target[0], target[1], state.laneDigest, item, statePath);
207
+ }
208
+ }
209
+ }
210
+ combined.paths = [...paths].sort();
211
+ return combined;
212
+ }
213
+
214
+ export async function inspectPremortemAudit(root, gatewayPolicy) {
215
+ const premortems = await inspectDeliveryPremortems(root);
216
+ const indexes = premortems.directory
217
+ ? await inspectPremortemLaneIndexes(premortems.directory)
218
+ : { directory: null, directories: [], paths: [], pointers: [], errors: [],
219
+ finalizations: [], tamperedPointers: [], tamperedFinalizations: [], truncations: [] };
220
+ const writeIndexes = await inspectPremortemWriteIndexAudit(premortems);
221
+ const crossReferenceIssues = premortemIndexCrossReferenceFindings(premortems, indexes, gatewayPolicy);
222
+ return { premortems, indexes, writeIndexes, crossReferenceIssues };
223
+ }
@@ -22,11 +22,12 @@ import { fileURLToPath } from "node:url";
22
22
  import { checkHosts } from "../../scripts/check-hosts.js";
23
23
  import { resolveHostSourceCatalog } from "./source-roots.js";
24
24
  import { preflightStatus } from "./preflight.js";
25
+ import { inspectPremortemAudit } from "./audit-premortem.js";
26
+ import { worldModelStatePath } from "./world-model.js";
25
27
 
26
28
  function gate(id, name, ok, detail, severity = "error") {
27
29
  return { id, name, ok, severity, detail };
28
30
  }
29
-
30
31
  function authorityViolations(graph, attention, learning, continuity, coordination, sharing, trust, registry, feedState) {
31
32
  const records = [
32
33
  ...graph.edges,
@@ -125,6 +126,7 @@ export async function runAudit(root = process.cwd(), { host = null } = {}) {
125
126
  : await buildCatalog(root));
126
127
  const catalog = before;
127
128
  const catalogPath = await saveCatalog(catalog);
129
+ const worldModelPath = await worldModelStatePath(before.root);
128
130
  const { graph, graphPath } = await loadGraph(before.root, catalog);
129
131
  const { attention, attentionPath, error: attentionLoadError } = await inspectAttention(before.root, catalog);
130
132
  const { learning, learningPath, error: learningLoadError } = await inspectLearning(before.root, catalog);
@@ -152,6 +154,9 @@ export async function runAudit(root = process.cwd(), { host = null } = {}) {
152
154
  const { trust, trustPath, error: trustLoadError } = await inspectTrust(before.root, catalog);
153
155
  const { registry, registryPath, signerDirectory, errors: signerErrors } = await inspectSignerRegistry(before.root, catalog);
154
156
  const { state: feedState, statePath: feedStatePath, error: feedStateError } = await inspectHttpsFeedState(before.root);
157
+ const { premortems, indexes: premortemIndexes, writeIndexes: premortemWriteIndexes,
158
+ crossReferenceIssues: premortemCrossReferenceIssues } = await inspectPremortemAudit(
159
+ before.root, gatewayPolicy);
155
160
  const context = await resolveContext({ root: before.root, cwd: before.root, host: "generic", maxBytes: 16384, includeContent: true, catalog });
156
161
  let briefing = null;
157
162
  let briefingError = null;
@@ -175,6 +180,13 @@ export async function runAudit(root = process.cwd(), { host = null } = {}) {
175
180
  const brokenLinks = catalog.conflicts.filter((conflict) => conflict.type === "broken-link");
176
181
  const reviewConflicts = catalog.conflicts.filter((conflict) => conflict.type !== "broken-link");
177
182
  const authority = authorityViolations(graph, attention, learning, continuity, coordination, sharing, trust, registry, feedState);
183
+ const premortemRecords = premortems.states.flatMap((state) => [state, state.requirement,
184
+ state.artifact, state.firstWrite, state.lastWrite, state.closure, ...state.events].filter(Boolean))
185
+ .concat(premortemIndexes.pointers, premortemIndexes.finalizations, premortemWriteIndexes.nodes);
186
+ const premortemAuthorityIssues = premortemRecords.filter((record) => record.authority !== "context-only");
187
+ const premortemIssues = [...premortems.errors, ...premortemIndexes.errors, ...premortemWriteIndexes.errors]
188
+ .map((item) => `unreadable-state:${item.reason}`)
189
+ .concat(premortemCrossReferenceIssues.map((item) => `index-state-mismatch:${item.reason}`));
178
190
  const forbidden = forbiddenEntityKeys(graph);
179
191
  const privacyValues = new Set(["private", "shared", "group"]);
180
192
  const privateRecords = [
@@ -292,10 +304,16 @@ export async function runAudit(root = process.cwd(), { host = null } = {}) {
292
304
  ? `${catalog.documents.length} project documents; host-native source resolution failed closed: ${sourceResolutionError}`
293
305
  : sourceResolution ? `${sourceResolution.scopes.user} user, ${sourceResolution.scopes.project} project, and ${sourceResolution.scopes["project-memory"]} memory sources; broad home scan disabled`
294
306
  : `${catalog.documents.length} Markdown documents indexed`),
295
- gate(3, "State isolation", [catalogPath, graphPath, attentionPath, learningPath, continuityPath,
307
+ gate(3, "State isolation", [catalogPath, graphPath, worldModelPath, attentionPath, learningPath, continuityPath,
296
308
  policyPath, coordinationPath, executionPolicyPath, selfstarterPath, channelPolicyPath,
297
309
  channelRuntimePath, personaPolicyPath, personaRuntimePath, gatewayPolicyPath, gatewayRuntimePath,
298
- sharingPath, trustPath, registryPath, signerDirectory, feedStatePath]
310
+ sharingPath, trustPath, registryPath, signerDirectory, feedStatePath, premortems.directory,
311
+ ...premortems.paths, ...premortems.errors.map((item) => item.path), premortemIndexes.directory,
312
+ ...premortemIndexes.directories, ...premortemIndexes.paths,
313
+ ...premortemIndexes.errors.map((item) => item.path), ...premortemWriteIndexes.directories,
314
+ ...premortemWriteIndexes.paths, ...premortemWriteIndexes.errors.map((item) => item.path),
315
+ ...premortemWriteIndexes.uncertainties.map((item) => item.path),
316
+ ...premortemWriteIndexes.truncations.map((item) => item.path)].filter(Boolean)
299
317
  .every((path) => statePathIsScanExcluded(catalog, path)),
300
318
  catalog.scanPolicy?.stateRoot === "excluded"
301
319
  ? `Authenticated state is excluded from the home-root source scan for ${catalog.root}`
@@ -303,10 +321,10 @@ export async function runAudit(root = process.cwd(), { host = null } = {}) {
303
321
  gate(4, "Native hierarchy", nativeMapped.every((document) => document.hosts.length > 0), `${nativeMapped.length} host-native documents mapped`),
304
322
  gate(5, "Link integrity", brokenLinks.length === 0, brokenLinks.length ? `${brokenLinks.length} broken Markdown links` : "All indexed Markdown links resolve"),
305
323
  gate(6, "Conflict visibility", Array.isArray(catalog.conflicts), `${reviewConflicts.length} precedence or classification findings exposed`, "warning"),
306
- gate(7, "Authority boundary", authority.length === 0 && forbidden.length === 0 && policyIssues.length === 0 && coordinationAuthorityIssues.length === 0 && executionPolicyIssues.length === 0 && selfstarterAuthorityIssues.length === 0 && channelPolicyIssues.length === 0 && personaPolicyIssues.length === 0 && gatewayPolicyIssues.length === 0 && sharingAuthorityIssues.length === 0 && !preflightError, preflightError
324
+ gate(7, "Authority boundary", authority.length === 0 && premortemAuthorityIssues.length === 0 && forbidden.length === 0 && policyIssues.length === 0 && coordinationAuthorityIssues.length === 0 && executionPolicyIssues.length === 0 && selfstarterAuthorityIssues.length === 0 && channelPolicyIssues.length === 0 && personaPolicyIssues.length === 0 && gatewayPolicyIssues.length === 0 && sharingAuthorityIssues.length === 0 && !preflightError, preflightError
307
325
  ? `preflight policy or receipt state failed closed: ${preflightError}`
308
- : `${authority.length} context authority violations; ${forbidden.length} forbidden entity records; ${policyIssues.length} delegation policy findings; ${coordinationAuthorityIssues.length} assignment findings; ${executionPolicyIssues.length} execution policy findings; ${selfstarterAuthorityIssues.length} self-starter authority findings; ${channelPolicyIssues.length} channel policy findings; ${personaPolicyIssues.length} persona policy findings; ${gatewayPolicyIssues.length} gateway policy findings; ${sharingAuthorityIssues.length} shared authority findings; preflight ${preflight.status}`),
309
- gate(8, "Context privacy", privacyInvalid.length === 0 && attentionGroupInvalid.length === 0 && attentionConfigValid && attentionIssues.length === 0 && learningIssues.length === 0 && continuityIssues.length === 0 && coordinationContextIssues.length === 0 && selfstarterStateIssues.length === 0 && channelRuntimeIssues.length === 0 && personaStateIssues.length === 0 && gatewayStateIssues.length === 0 && sharingContextIssues.length === 0 && authenticationIssues.length === 0, `${graph.entities.length} entities, ${graph.entityEdges.length} relationships, ${attention.signals.length} attention cues, ${attention.events.length} lifecycle events, ${learning.candidates.length} learning records, ${(learning.candidateEvidenceLineage || []).length} candidate-evidence lineage receipts, ${(learning.evaluations || []).length} immutable evaluation contracts, ${(learning.evaluations || []).filter((item) => ["agentspine.learning-evaluation/v9", "agentspine.learning-evaluation/v10", "agentspine.learning-evaluation/v11", "agentspine.learning-evaluation/v12", "agentspine.learning-evaluation/v13", "agentspine.learning-evaluation/v14", "agentspine.learning-evaluation/v15", "agentspine.learning-evaluation/v16", "agentspine.learning-evaluation/v17", "agentspine.learning-evaluation/v18", "agentspine.learning-evaluation/v19", "agentspine.learning-evaluation/v20", "agentspine.learning-evaluation/v21", "agentspine.learning-evaluation/v22", "agentspine.learning-evaluation/v23", "agentspine.learning-evaluation/v24", "agentspine.learning-evaluation/v25", "agentspine.learning-evaluation/v26", "agentspine.learning-evaluation/v27", "agentspine.learning-evaluation/v28", "agentspine.learning-evaluation/v29"].includes(item.schema)).length} exact-target contracts, ${(learning.evaluations || []).filter((item) => ["agentspine.learning-evaluation/v8", "agentspine.learning-evaluation/v9", "agentspine.learning-evaluation/v10", "agentspine.learning-evaluation/v11", "agentspine.learning-evaluation/v12", "agentspine.learning-evaluation/v13", "agentspine.learning-evaluation/v14", "agentspine.learning-evaluation/v15", "agentspine.learning-evaluation/v16", "agentspine.learning-evaluation/v17", "agentspine.learning-evaluation/v18", "agentspine.learning-evaluation/v19", "agentspine.learning-evaluation/v20", "agentspine.learning-evaluation/v21", "agentspine.learning-evaluation/v22", "agentspine.learning-evaluation/v23", "agentspine.learning-evaluation/v24", "agentspine.learning-evaluation/v25", "agentspine.learning-evaluation/v26", "agentspine.learning-evaluation/v27", "agentspine.learning-evaluation/v28", "agentspine.learning-evaluation/v29"].includes(item.schema)).length} precommitted initial-trial contracts, ${(learning.evaluations || []).filter((item) => ["agentspine.learning-evaluation/v10", "agentspine.learning-evaluation/v11", "agentspine.learning-evaluation/v12", "agentspine.learning-evaluation/v13", "agentspine.learning-evaluation/v14", "agentspine.learning-evaluation/v15", "agentspine.learning-evaluation/v16", "agentspine.learning-evaluation/v17", "agentspine.learning-evaluation/v18", "agentspine.learning-evaluation/v19", "agentspine.learning-evaluation/v20", "agentspine.learning-evaluation/v21", "agentspine.learning-evaluation/v22", "agentspine.learning-evaluation/v23", "agentspine.learning-evaluation/v24", "agentspine.learning-evaluation/v25", "agentspine.learning-evaluation/v26", "agentspine.learning-evaluation/v27", "agentspine.learning-evaluation/v28", "agentspine.learning-evaluation/v29"].includes(item.schema)).length} deadline-bound contracts, ${(learning.evaluations || []).filter((item) => ["agentspine.learning-evaluation/v14", "agentspine.learning-evaluation/v15", "agentspine.learning-evaluation/v16", "agentspine.learning-evaluation/v17", "agentspine.learning-evaluation/v18", "agentspine.learning-evaluation/v19", "agentspine.learning-evaluation/v20", "agentspine.learning-evaluation/v21", "agentspine.learning-evaluation/v22", "agentspine.learning-evaluation/v23", "agentspine.learning-evaluation/v24", "agentspine.learning-evaluation/v25", "agentspine.learning-evaluation/v26", "agentspine.learning-evaluation/v27", "agentspine.learning-evaluation/v28", "agentspine.learning-evaluation/v29"].includes(item.schema)).length} staleness-bound contracts, ${(learning.evaluations || []).filter((item) => ["agentspine.learning-evaluation/v16", "agentspine.learning-evaluation/v17", "agentspine.learning-evaluation/v18", "agentspine.learning-evaluation/v19", "agentspine.learning-evaluation/v20", "agentspine.learning-evaluation/v21", "agentspine.learning-evaluation/v22", "agentspine.learning-evaluation/v23", "agentspine.learning-evaluation/v24", "agentspine.learning-evaluation/v25", "agentspine.learning-evaluation/v26", "agentspine.learning-evaluation/v27", "agentspine.learning-evaluation/v28", "agentspine.learning-evaluation/v29"].includes(item.schema)).length} promotion-bound contracts, ${(learning.evaluations || []).filter((item) => ["agentspine.learning-evaluation/v18", "agentspine.learning-evaluation/v19", "agentspine.learning-evaluation/v20", "agentspine.learning-evaluation/v21", "agentspine.learning-evaluation/v22", "agentspine.learning-evaluation/v23", "agentspine.learning-evaluation/v24", "agentspine.learning-evaluation/v25", "agentspine.learning-evaluation/v26", "agentspine.learning-evaluation/v27", "agentspine.learning-evaluation/v28", "agentspine.learning-evaluation/v29"].includes(item.schema)).length} candidate-admission contracts, ${(learning.evaluations || []).filter((item) => ["agentspine.learning-evaluation/v20", "agentspine.learning-evaluation/v21", "agentspine.learning-evaluation/v22", "agentspine.learning-evaluation/v23", "agentspine.learning-evaluation/v24", "agentspine.learning-evaluation/v25", "agentspine.learning-evaluation/v26", "agentspine.learning-evaluation/v27", "agentspine.learning-evaluation/v28", "agentspine.learning-evaluation/v29"].includes(item.schema)).length} candidate-evidence-cohort contracts, ${(learning.evaluations || []).filter((item) => ["agentspine.learning-evaluation/v22", "agentspine.learning-evaluation/v23", "agentspine.learning-evaluation/v24", "agentspine.learning-evaluation/v25", "agentspine.learning-evaluation/v26", "agentspine.learning-evaluation/v27", "agentspine.learning-evaluation/v28", "agentspine.learning-evaluation/v29"].includes(item.schema)).length} blocking-defect-bound contracts, ${(learning.evaluations || []).filter((item) => ["agentspine.learning-evaluation/v24", "agentspine.learning-evaluation/v25", "agentspine.learning-evaluation/v26", "agentspine.learning-evaluation/v27", "agentspine.learning-evaluation/v28", "agentspine.learning-evaluation/v29"].includes(item.schema)).length} evidence-source-bound contracts, ${(learning.evaluations || []).filter((item) => ["agentspine.learning-evaluation/v26", "agentspine.learning-evaluation/v27", "agentspine.learning-evaluation/v28", "agentspine.learning-evaluation/v29"].includes(item.schema)).length} evidence-source-attested contracts, ${(learning.evaluations || []).filter((item) => ["agentspine.learning-evaluation/v13", "agentspine.learning-evaluation/v15", "agentspine.learning-evaluation/v17", "agentspine.learning-evaluation/v19", "agentspine.learning-evaluation/v21", "agentspine.learning-evaluation/v23", "agentspine.learning-evaluation/v25", "agentspine.learning-evaluation/v27", "agentspine.learning-evaluation/v29"].includes(item.schema)).length} bounded retry contracts, ${(learning.trialRetryExhaustions || []).length} terminal retry-exhaustion receipts, ${(learning.applications || []).filter((item) => ["agentspine.learning-application/v5", "agentspine.learning-application/v6", "agentspine.learning-application/v7"].includes(item.schema)).length} immutable initial-trial admissions, ${(learning.applications || []).filter((item) => ["agentspine.learning-application/v6", "agentspine.learning-application/v7"].includes(item.schema)).length} exact-target admissions, ${(learning.applications || []).filter((item) => item.schema === "agentspine.learning-application/v7").length} deadline-bound admissions, ${(learning.trialFailures || []).length} blocking trial-failure receipts, ${(learning.evaluatorRegistry || []).length} locally confirmed evaluator roots, ${(learning.evaluationBindings || []).length} evaluator-registry bindings, ${(learning.validationLeases || []).length} immutable validation leases, ${(learning.measurements || []).length} immutable measurement runs, ${(learning.applications || []).length} turn-bound projections, ${(learning.deliveries || []).length} completed model-turn deliveries, ${(learning.evaluationRevocations || []).length} evaluation revocations, ${(learning.evidenceRevocations || []).length} evidence revocations, ${(learning.measurementRevocations || []).length} measurement revocations, ${(learning.applicationRevocations || []).length} application revocations, ${(learning.deliveryRevocations || []).length} delivery revocations, ${(learning.outcomeRevocations || []).length} outcome revocations, ${(learning.outcomes || []).length} outcome receipts, ${(learning.outcomes || []).filter((item) => ["agentspine.learning-outcome/v5", "agentspine.learning-outcome/v6", "agentspine.learning-outcome/v7", "agentspine.learning-outcome/v8", "agentspine.learning-outcome/v9"].includes(item.schema)).length} case-coverage receipts, ${(learning.outcomes || []).filter((item) => ["agentspine.learning-outcome/v6", "agentspine.learning-outcome/v7", "agentspine.learning-outcome/v8", "agentspine.learning-outcome/v9"].includes(item.schema)).length} provenance-bound receipts, ${(learning.outcomes || []).filter((item) => ["agentspine.learning-outcome/v7", "agentspine.learning-outcome/v8", "agentspine.learning-outcome/v9"].includes(item.schema)).length} lineage-bound receipts, ${(learning.outcomes || []).filter((item) => ["agentspine.learning-outcome/v8", "agentspine.learning-outcome/v9"].includes(item.schema)).length} paired-evaluator receipts and ${(learning.outcomes || []).filter((item) => item.schema === "agentspine.learning-outcome/v9").length} evaluator-root-bound receipts, ${continuity.signals.length} continuity signals, ${coordination.tasks.length} coordination items, ${selfstarter.jobs.length} self-starter jobs, ${channelRuntime.events.length} channel events, ${personaRuntime.personas.length} authenticated personas, ${gatewayRuntime.queue.length} gateway queue items, ${gatewayRuntime.outbox.length} delivery records, ${sharing.records.length} shared records, ${trust.records.length} trusted keys, ${registry.signers.length} local signers, and ${feedState.feeds.length} feed receipts checked`),
326
+ : `${authority.length} context authority violations; ${premortemAuthorityIssues.length} premortem authority violations; ${forbidden.length} forbidden entity records; ${policyIssues.length} delegation policy findings; ${coordinationAuthorityIssues.length} assignment findings; ${executionPolicyIssues.length} execution policy findings; ${selfstarterAuthorityIssues.length} self-starter authority findings; ${channelPolicyIssues.length} channel policy findings; ${personaPolicyIssues.length} persona policy findings; ${gatewayPolicyIssues.length} gateway policy findings; ${sharingAuthorityIssues.length} shared authority findings; preflight ${preflight.status}`),
327
+ gate(8, "Context privacy", privacyInvalid.length === 0 && attentionGroupInvalid.length === 0 && attentionConfigValid && attentionIssues.length === 0 && learningIssues.length === 0 && continuityIssues.length === 0 && coordinationContextIssues.length === 0 && selfstarterStateIssues.length === 0 && channelRuntimeIssues.length === 0 && personaStateIssues.length === 0 && gatewayStateIssues.length === 0 && sharingContextIssues.length === 0 && authenticationIssues.length === 0 && premortemIssues.length === 0, `${graph.entities.length} entities, ${graph.entityEdges.length} relationships, ${attention.signals.length} attention cues, ${attention.events.length} lifecycle events, ${learning.candidates.length} learning records, ${(learning.candidateEvidenceLineage || []).length} candidate-evidence lineage receipts, ${(learning.evaluations || []).length} immutable evaluation contracts, ${(learning.evaluations || []).filter((item) => ["agentspine.learning-evaluation/v9", "agentspine.learning-evaluation/v10", "agentspine.learning-evaluation/v11", "agentspine.learning-evaluation/v12", "agentspine.learning-evaluation/v13", "agentspine.learning-evaluation/v14", "agentspine.learning-evaluation/v15", "agentspine.learning-evaluation/v16", "agentspine.learning-evaluation/v17", "agentspine.learning-evaluation/v18", "agentspine.learning-evaluation/v19", "agentspine.learning-evaluation/v20", "agentspine.learning-evaluation/v21", "agentspine.learning-evaluation/v22", "agentspine.learning-evaluation/v23", "agentspine.learning-evaluation/v24", "agentspine.learning-evaluation/v25", "agentspine.learning-evaluation/v26", "agentspine.learning-evaluation/v27", "agentspine.learning-evaluation/v28", "agentspine.learning-evaluation/v29"].includes(item.schema)).length} exact-target contracts, ${(learning.evaluations || []).filter((item) => ["agentspine.learning-evaluation/v8", "agentspine.learning-evaluation/v9", "agentspine.learning-evaluation/v10", "agentspine.learning-evaluation/v11", "agentspine.learning-evaluation/v12", "agentspine.learning-evaluation/v13", "agentspine.learning-evaluation/v14", "agentspine.learning-evaluation/v15", "agentspine.learning-evaluation/v16", "agentspine.learning-evaluation/v17", "agentspine.learning-evaluation/v18", "agentspine.learning-evaluation/v19", "agentspine.learning-evaluation/v20", "agentspine.learning-evaluation/v21", "agentspine.learning-evaluation/v22", "agentspine.learning-evaluation/v23", "agentspine.learning-evaluation/v24", "agentspine.learning-evaluation/v25", "agentspine.learning-evaluation/v26", "agentspine.learning-evaluation/v27", "agentspine.learning-evaluation/v28", "agentspine.learning-evaluation/v29"].includes(item.schema)).length} precommitted initial-trial contracts, ${(learning.evaluations || []).filter((item) => ["agentspine.learning-evaluation/v10", "agentspine.learning-evaluation/v11", "agentspine.learning-evaluation/v12", "agentspine.learning-evaluation/v13", "agentspine.learning-evaluation/v14", "agentspine.learning-evaluation/v15", "agentspine.learning-evaluation/v16", "agentspine.learning-evaluation/v17", "agentspine.learning-evaluation/v18", "agentspine.learning-evaluation/v19", "agentspine.learning-evaluation/v20", "agentspine.learning-evaluation/v21", "agentspine.learning-evaluation/v22", "agentspine.learning-evaluation/v23", "agentspine.learning-evaluation/v24", "agentspine.learning-evaluation/v25", "agentspine.learning-evaluation/v26", "agentspine.learning-evaluation/v27", "agentspine.learning-evaluation/v28", "agentspine.learning-evaluation/v29"].includes(item.schema)).length} deadline-bound contracts, ${(learning.evaluations || []).filter((item) => ["agentspine.learning-evaluation/v14", "agentspine.learning-evaluation/v15", "agentspine.learning-evaluation/v16", "agentspine.learning-evaluation/v17", "agentspine.learning-evaluation/v18", "agentspine.learning-evaluation/v19", "agentspine.learning-evaluation/v20", "agentspine.learning-evaluation/v21", "agentspine.learning-evaluation/v22", "agentspine.learning-evaluation/v23", "agentspine.learning-evaluation/v24", "agentspine.learning-evaluation/v25", "agentspine.learning-evaluation/v26", "agentspine.learning-evaluation/v27", "agentspine.learning-evaluation/v28", "agentspine.learning-evaluation/v29"].includes(item.schema)).length} staleness-bound contracts, ${(learning.evaluations || []).filter((item) => ["agentspine.learning-evaluation/v16", "agentspine.learning-evaluation/v17", "agentspine.learning-evaluation/v18", "agentspine.learning-evaluation/v19", "agentspine.learning-evaluation/v20", "agentspine.learning-evaluation/v21", "agentspine.learning-evaluation/v22", "agentspine.learning-evaluation/v23", "agentspine.learning-evaluation/v24", "agentspine.learning-evaluation/v25", "agentspine.learning-evaluation/v26", "agentspine.learning-evaluation/v27", "agentspine.learning-evaluation/v28", "agentspine.learning-evaluation/v29"].includes(item.schema)).length} promotion-bound contracts, ${(learning.evaluations || []).filter((item) => ["agentspine.learning-evaluation/v18", "agentspine.learning-evaluation/v19", "agentspine.learning-evaluation/v20", "agentspine.learning-evaluation/v21", "agentspine.learning-evaluation/v22", "agentspine.learning-evaluation/v23", "agentspine.learning-evaluation/v24", "agentspine.learning-evaluation/v25", "agentspine.learning-evaluation/v26", "agentspine.learning-evaluation/v27", "agentspine.learning-evaluation/v28", "agentspine.learning-evaluation/v29"].includes(item.schema)).length} candidate-admission contracts, ${(learning.evaluations || []).filter((item) => ["agentspine.learning-evaluation/v20", "agentspine.learning-evaluation/v21", "agentspine.learning-evaluation/v22", "agentspine.learning-evaluation/v23", "agentspine.learning-evaluation/v24", "agentspine.learning-evaluation/v25", "agentspine.learning-evaluation/v26", "agentspine.learning-evaluation/v27", "agentspine.learning-evaluation/v28", "agentspine.learning-evaluation/v29"].includes(item.schema)).length} candidate-evidence-cohort contracts, ${(learning.evaluations || []).filter((item) => ["agentspine.learning-evaluation/v22", "agentspine.learning-evaluation/v23", "agentspine.learning-evaluation/v24", "agentspine.learning-evaluation/v25", "agentspine.learning-evaluation/v26", "agentspine.learning-evaluation/v27", "agentspine.learning-evaluation/v28", "agentspine.learning-evaluation/v29"].includes(item.schema)).length} blocking-defect-bound contracts, ${(learning.evaluations || []).filter((item) => ["agentspine.learning-evaluation/v24", "agentspine.learning-evaluation/v25", "agentspine.learning-evaluation/v26", "agentspine.learning-evaluation/v27", "agentspine.learning-evaluation/v28", "agentspine.learning-evaluation/v29"].includes(item.schema)).length} evidence-source-bound contracts, ${(learning.evaluations || []).filter((item) => ["agentspine.learning-evaluation/v26", "agentspine.learning-evaluation/v27", "agentspine.learning-evaluation/v28", "agentspine.learning-evaluation/v29"].includes(item.schema)).length} evidence-source-attested contracts, ${(learning.evaluations || []).filter((item) => ["agentspine.learning-evaluation/v13", "agentspine.learning-evaluation/v15", "agentspine.learning-evaluation/v17", "agentspine.learning-evaluation/v19", "agentspine.learning-evaluation/v21", "agentspine.learning-evaluation/v23", "agentspine.learning-evaluation/v25", "agentspine.learning-evaluation/v27", "agentspine.learning-evaluation/v29"].includes(item.schema)).length} bounded retry contracts, ${(learning.trialRetryExhaustions || []).length} terminal retry-exhaustion receipts, ${(learning.applications || []).filter((item) => ["agentspine.learning-application/v5", "agentspine.learning-application/v6", "agentspine.learning-application/v7"].includes(item.schema)).length} immutable initial-trial admissions, ${(learning.applications || []).filter((item) => ["agentspine.learning-application/v6", "agentspine.learning-application/v7"].includes(item.schema)).length} exact-target admissions, ${(learning.applications || []).filter((item) => item.schema === "agentspine.learning-application/v7").length} deadline-bound admissions, ${(learning.trialFailures || []).length} blocking trial-failure receipts, ${(learning.evaluatorRegistry || []).length} locally confirmed evaluator roots, ${(learning.evaluationBindings || []).length} evaluator-registry bindings, ${(learning.validationLeases || []).length} immutable validation leases, ${(learning.measurements || []).length} immutable measurement runs, ${(learning.applications || []).length} turn-bound projections, ${(learning.deliveries || []).length} completed model-turn deliveries, ${(learning.evaluationRevocations || []).length} evaluation revocations, ${(learning.evidenceRevocations || []).length} evidence revocations, ${(learning.measurementRevocations || []).length} measurement revocations, ${(learning.applicationRevocations || []).length} application revocations, ${(learning.deliveryRevocations || []).length} delivery revocations, ${(learning.outcomeRevocations || []).length} outcome revocations, ${(learning.outcomes || []).length} outcome receipts, ${(learning.outcomes || []).filter((item) => ["agentspine.learning-outcome/v5", "agentspine.learning-outcome/v6", "agentspine.learning-outcome/v7", "agentspine.learning-outcome/v8", "agentspine.learning-outcome/v9"].includes(item.schema)).length} case-coverage receipts, ${(learning.outcomes || []).filter((item) => ["agentspine.learning-outcome/v6", "agentspine.learning-outcome/v7", "agentspine.learning-outcome/v8", "agentspine.learning-outcome/v9"].includes(item.schema)).length} provenance-bound receipts, ${(learning.outcomes || []).filter((item) => ["agentspine.learning-outcome/v7", "agentspine.learning-outcome/v8", "agentspine.learning-outcome/v9"].includes(item.schema)).length} lineage-bound receipts, ${(learning.outcomes || []).filter((item) => ["agentspine.learning-outcome/v8", "agentspine.learning-outcome/v9"].includes(item.schema)).length} paired-evaluator receipts and ${(learning.outcomes || []).filter((item) => item.schema === "agentspine.learning-outcome/v9").length} evaluator-root-bound receipts, ${continuity.signals.length} continuity signals, ${coordination.tasks.length} coordination items, ${selfstarter.jobs.length} self-starter jobs, ${channelRuntime.events.length} channel events, ${personaRuntime.personas.length} authenticated personas, ${gatewayRuntime.queue.length} gateway queue items, ${gatewayRuntime.outbox.length} delivery records, ${sharing.records.length} shared records, ${trust.records.length} trusted keys, ${registry.signers.length} local signers, ${feedState.feeds.length} feed receipts, ${premortems.states.length} premortem states, and ${premortemIndexes.pointers.length} premortem index pointers checked`),
310
328
  gate(9, "Context budget", loadedBytes <= context.budget.maxBytes && briefingBudgetValid, briefingError
311
329
  ? `${loadedBytes}/${context.budget.maxBytes} source bytes; briefing failed closed: ${briefingError}`
312
330
  : `${loadedBytes}/${context.budget.maxBytes} source bytes; ${briefingBytes}/${briefing.budget.maxBytes} briefing bytes`),
@@ -321,6 +339,7 @@ export async function runAudit(root = process.cwd(), { host = null } = {}) {
321
339
  gates,
322
340
  catalogPath,
323
341
  graphPath,
342
+ worldModelPath,
324
343
  attentionPath,
325
344
  learningPath,
326
345
  continuityPath,
@@ -338,6 +357,37 @@ export async function runAudit(root = process.cwd(), { host = null } = {}) {
338
357
  trustPath,
339
358
  registryPath,
340
359
  feedStatePath,
360
+ premortemDiagnostics: {
361
+ directory: premortems.directory,
362
+ paths: [...premortems.paths, ...premortemWriteIndexes.paths],
363
+ states: premortems.states.length,
364
+ artifacts: premortems.states.filter((state) => state.artifact).length,
365
+ closures: premortems.states.filter((state) => state.closure).length,
366
+ errors: structuredClone([...premortems.errors, ...premortemWriteIndexes.errors]),
367
+ truncations: structuredClone([...premortems.truncations, ...premortemWriteIndexes.truncations]),
368
+ writeIndex: { directories: [...premortemWriteIndexes.directories],
369
+ paths: [...premortemWriteIndexes.paths], nodes: premortemWriteIndexes.nodes.length,
370
+ states: premortemWriteIndexes.states,
371
+ attemptedProofs: premortemWriteIndexes.attemptedProofs,
372
+ verifiedProofs: premortemWriteIndexes.verifiedProofs,
373
+ errors: structuredClone(premortemWriteIndexes.errors),
374
+ uncertainties: structuredClone(premortemWriteIndexes.uncertainties),
375
+ truncations: structuredClone(premortemWriteIndexes.truncations), authority: "context-only" },
376
+ index: {
377
+ directory: premortemIndexes.directory,
378
+ directories: [...premortemIndexes.directories],
379
+ paths: [...premortemIndexes.paths],
380
+ pointers: premortemIndexes.pointers.length,
381
+ finalizations: premortemIndexes.finalizations.length,
382
+ tamperedPointers: [...premortemIndexes.tamperedPointers],
383
+ tamperedFinalizations: [...premortemIndexes.tamperedFinalizations],
384
+ errors: structuredClone(premortemIndexes.errors),
385
+ truncations: structuredClone(premortemIndexes.truncations),
386
+ crossReferenceErrors: structuredClone(premortemCrossReferenceIssues),
387
+ authority: "context-only"
388
+ },
389
+ authority: "context-only"
390
+ },
341
391
  learningDiagnostics: {
342
392
  candidateEvidenceLineageReceipts:
343
393
  (learning.candidateEvidenceLineage || []).length,
@@ -0,0 +1,110 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import {
3
+ AUTONOMY_CONFIRMATION, AUTONOMY_MODES, CAPABILITY_RE, PUBLISH_CONFIRMATION,
4
+ appendHistory, canonicalLocalRoot, exactCapabilities, loadAutonomy, modeAllows,
5
+ mutateAutonomy, publicRepository, safeText, signedRecord, stableId, timestamp
6
+ } from "./autonomy-store.js";
7
+ import { loadExecutionPolicy } from "./selfstarter.js";
8
+
9
+ function confirmation(value) {
10
+ if (value !== AUTONOMY_CONFIRMATION) throw new Error("autonomy changes require explicit local-owner confirmation");
11
+ }
12
+
13
+ export async function configureAutonomyProject({
14
+ root = process.cwd(), id = `autonomy-project:${randomUUID()}`, projectId, tenantId, groupId = null,
15
+ localRoot = null, publicUrl = null, mode = "observe", capabilities = [], goal = "Maintain a bounded project overview.",
16
+ confirmation: ownerConfirmation, publishConfirmation = null, now = new Date()
17
+ }) {
18
+ confirmation(ownerConfirmation);
19
+ if (!AUTONOMY_MODES.includes(mode)) throw new Error(`mode must be one of: ${AUTONOMY_MODES.join(", ")}`);
20
+ if (Boolean(localRoot) === Boolean(publicUrl)) throw new Error("configure exactly one local root or public repository URL");
21
+ const source = localRoot
22
+ ? { kind: "local-root", value: await canonicalLocalRoot(localRoot) }
23
+ : { kind: "public-repository", value: publicRepository(publicUrl) };
24
+ const requestedCapabilities = exactCapabilities(capabilities);
25
+ if (modeAllows(mode, "execute") && !requestedCapabilities.length) throw new Error("execute and publish modes require exact capabilities");
26
+ if (mode === "publish" && publishConfirmation !== PUBLISH_CONFIRMATION) {
27
+ throw new Error("publish mode requires a separate explicit local publish confirmation");
28
+ }
29
+ const at = timestamp(now, "now");
30
+ const registrationId = stableId(id, "registrationId");
31
+ return mutateAutonomy(root, (state, paths) => {
32
+ const previous = state.projects.find((item) => item.id === registrationId);
33
+ if (previous && (previous.projectId !== projectId || previous.tenantId !== tenantId || previous.groupId !== groupId
34
+ || previous.source.kind !== source.kind || previous.source.value !== source.value)) {
35
+ throw new Error("project registration identity and scope are immutable; create a new registration");
36
+ }
37
+ state.revision += 1;
38
+ const body = {
39
+ id: registrationId, projectId: stableId(projectId, "projectId"), tenantId: stableId(tenantId, "tenantId"),
40
+ groupId: stableId(groupId, "groupId", true), source, mode, capabilities: requestedCapabilities,
41
+ goal: safeText(goal, "goal", 500), active: true, revision: state.revision,
42
+ createdAt: previous?.createdAt || at, updatedAt: at,
43
+ publishConfirmedAt: mode === "publish" ? at : null,
44
+ sourceAuthority: "explicit-local-owner-policy", authority: "explicit-local-autonomy-policy"
45
+ };
46
+ const project = signedRecord(body);
47
+ if (previous) state.projects = state.projects.map((item) => item.id === registrationId ? project : item);
48
+ else state.projects.push(project);
49
+ state.projects.sort((a, b) => a.id.localeCompare(b.id));
50
+ appendHistory(state, { kind: previous ? "project-updated" : "project-registered", projectRegistrationId: project.id, at });
51
+ return { project, policyRevision: state.revision, autonomyPath: paths.autonomyPath };
52
+ });
53
+ }
54
+
55
+ export async function revokeAutonomyProject({ root = process.cwd(), id, reason, confirmation: ownerConfirmation, now = new Date() }) {
56
+ confirmation(ownerConfirmation);
57
+ const registrationId = stableId(id, "registrationId");
58
+ const at = timestamp(now, "now");
59
+ const revokeReason = safeText(reason, "reason", 500);
60
+ return mutateAutonomy(root, (state, paths) => {
61
+ const previous = state.projects.find((item) => item.id === registrationId);
62
+ if (!previous?.active) throw new Error("project registration is unknown or already inactive");
63
+ state.revision += 1;
64
+ const { recordDigest: ignored, ...body } = previous;
65
+ const project = signedRecord({ ...body, active: false, updatedAt: at, revision: state.revision, revokedAt: at, revokeReason });
66
+ state.projects = state.projects.map((item) => item.id === registrationId ? project : item);
67
+ appendHistory(state, { kind: "project-revoked", projectRegistrationId: project.id, at });
68
+ return { project, policyRevision: state.revision, autonomyPath: paths.autonomyPath };
69
+ });
70
+ }
71
+
72
+ function exactGrant(policy, input, capability, now) {
73
+ return policy.grants.find((grant) => grant.active && grant.actorId === input.actorId
74
+ && grant.jobId === input.jobId && grant.taskId === input.taskId && grant.targetId === input.targetId
75
+ && grant.projectId === input.projectId && grant.groupId === input.groupId && grant.host === input.host
76
+ && grant.capabilities.includes(capability) && (!grant.expiresAt || new Date(grant.expiresAt) > now));
77
+ }
78
+
79
+ export async function evaluateAutonomyAction({
80
+ root = process.cwd(), registrationId, tenantId, groupId = null, action, capability = null,
81
+ actorId = null, jobId = null, taskId = null, targetId = null, projectId = null, host = null, now = new Date()
82
+ }) {
83
+ if (!AUTONOMY_MODES.includes(action)) throw new Error(`action must be one of: ${AUTONOMY_MODES.join(", ")}`);
84
+ const { state } = await loadAutonomy(root);
85
+ const project = state.projects.find((item) => item.id === stableId(registrationId, "registrationId") && item.active);
86
+ const base = { schema: "agentspine.autonomy-decision/v1", registrationId, action, allowed: false,
87
+ reason: "project-registration-unavailable", grantsAuthority: false, authority: "additional-autonomy-gate" };
88
+ if (!project || project.tenantId !== stableId(tenantId, "tenantId") || project.groupId !== stableId(groupId, "groupId", true)) return base;
89
+ if (!modeAllows(project.mode, action)) return { ...base, reason: "autonomy-mode-insufficient", configuredMode: project.mode };
90
+ if (!modeAllows(action, "execute")) return { ...base, allowed: true, reason: "configured-context-action", configuredMode: project.mode };
91
+ if (project.projectId !== projectId) return { ...base, reason: "action-project-mismatch", configuredMode: project.mode };
92
+ if (typeof capability !== "string" || !CAPABILITY_RE.test(capability) || !project.capabilities.includes(capability)) {
93
+ return { ...base, reason: "capability-not-configured", configuredMode: project.mode };
94
+ }
95
+ if (action === "publish" && !project.publishConfirmedAt) return { ...base, reason: "publish-not-confirmed", configuredMode: project.mode };
96
+ const scope = { actorId, jobId, taskId, targetId, projectId, groupId, host };
97
+ if (Object.entries(scope).some(([key, value]) => key !== "groupId" && (typeof value !== "string" || !value))) {
98
+ return { ...base, reason: "execution-scope-incomplete", configuredMode: project.mode };
99
+ }
100
+ const { policy } = await loadExecutionPolicy(root);
101
+ const grant = exactGrant(policy, scope, capability, new Date(now));
102
+ if (!grant) return { ...base, reason: "execution-grant-unavailable", configuredMode: project.mode };
103
+ return { ...base, allowed: true, reason: "configured-and-explicitly-granted", configuredMode: project.mode, grantId: grant.id };
104
+ }
105
+
106
+ export async function autonomyStatus({ root = process.cwd(), tenantId = null, groupId = null } = {}) {
107
+ const { state, autonomyPath } = await loadAutonomy(root);
108
+ const projects = state.projects.filter((item) => (!tenantId || item.tenantId === tenantId) && item.groupId === groupId);
109
+ return { schema: AUTONOMY_SCHEMA, projects, revision: state.revision, autonomyPath, authority: "context-only" };
110
+ }