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
@@ -1,135 +1,16 @@
1
- import { fileURLToPath } from "node:url";
2
- import { scanAndSave, verifyCatalog } from "./lib/catalog.js";
3
- import { readDocument, resolveContext } from "./lib/context.js";
4
- import { sessionBriefing } from "./lib/briefing.js";
5
- import { runAudit } from "./lib/audit.js";
6
- import {
7
- attentionContext, configureAttention, deleteAttention, loadAttention,
8
- recordActivity, resolveAttention, upsertAttention
9
- } from "./lib/attention.js";
10
- import {
11
- addLearningEvidence, beginLearningRevalidation, configureLearning, deleteLearning, evaluateLearning,
12
- learningContext, learningOutcomeStatus, loadLearning, proposeLearning,
13
- purgeStaleLearningApplications, purgeStaleLearningMeasurements, recordLearningMeasurement,
14
- recordLearningOutcome, registerLearningEvaluation, registerLearningEvaluator, renewLearningValidation, revokeLearningEvaluator,
15
- reviewLearning, revokeLearningApplication, revokeLearningDelivery, revokeLearningEvaluation, revokeLearningEvidence, revokeLearningMeasurement, revokeLearningOutcome, revokeLearningTrialFailure, revokeLearningValidation,
16
- revokeLearningEvidenceSourceAttestation,
17
- rollbackLearning
18
- } from "./lib/learning.js";
19
- import { configureContinuity, loadContinuity, purgeContinuity } from "./lib/continuity.js";
20
- import {
21
- checkDelegation, createTask, deleteTask, grantDelegation, loadDelegationPolicy,
22
- revokeDelegation, taskContext, updateTask
23
- } from "./lib/coordination.js";
24
- import {
25
- cancelJob, deleteJob, grantExecution, loadExecutionPolicy, registerJob,
26
- revokeExecution, selfstarterContext
27
- } from "./lib/selfstarter.js";
28
- import {
29
- channelRuntimeContext, grantChannelBinding, loadChannelPolicy, revokeChannelBinding
30
- } from "./lib/channel-runtime.js";
31
- import { personaContext, syncPersonaRosterFromEnvironment } from "./lib/persona-runtime.js";
32
- import { assignGoal, gatewayContext, resolveGoalKnowledgeGap, setGatewayControl } from "./lib/gateway-runtime.js";
33
- import {
34
- configureSharing, deleteShared, initDirectoryAdapter, publishLearning, pullShared,
35
- reviewShared, rollbackShared, sharedContext, sharedInbox
36
- } from "./lib/sharing.js";
37
- import {
38
- generateSigningIdentity, listSigningIdentities, revokeTrustedSigner,
39
- trustedSignerContext, trustSigner
40
- } from "./lib/authentication.js";
41
- import { exportHttpsSnapshot, pullHttpsSnapshot } from "./lib/https-transport.js";
42
- import { publishHttpsSnapshot } from "./lib/object-transport.js";
43
- import { loadHttpsFeedState, publishHttpsFeed, pullHttpsFeed } from "./lib/feed-transport.js";
44
- import { pullPeerCommand, servePeerOnce } from "./lib/peer-transport.js";
45
- import {
46
- initSqliteAdapter, inspectSqliteAdapter, publishSqliteSnapshot, pullSqliteSnapshot
47
- } from "./lib/sqlite-transport.js";
48
- import {
49
- annotateDocument, linkDocuments, linkEntities,
50
- relationshipContext, upsertEntity
51
- } from "./lib/graph.js";
52
- import { checkHosts } from "../scripts/check-hosts.js";
53
- import { renderAcceptanceReport, runVisibleAcceptance } from "./lib/acceptance.js";
54
- import {
55
- bindSourceRoot, inspectSourceRegistry, purgeSourceBinding, resolveHostSourceCatalog,
56
- rollbackSourceBinding
57
- } from "./lib/source-roots.js";
1
+ import { coreCommands, runCoreCommand } from "./cli-core.js";
2
+ import { attentionCommands, runAttentionCommand } from "./cli-attention.js";
3
+ import { learningCommands, runLearningCommand } from "./cli-learning.js";
4
+ import { continuityCommands, runContinuityCommand } from "./cli-continuity.js";
5
+ import { agentCommands, runAgentCommand } from "./cli-agent.js";
6
+ import { sharingCommands, runSharingCommand } from "./cli-sharing.js";
7
+ import { diagnosticsCommands, runDiagnosticsCommand } from "./cli-diagnostics.js";
8
+ import { premortemCommands, runPremortemCommand } from "./cli-premortem.js";
9
+ import { hostCommands, runHostCommand } from "./cli-host.js";
10
+ import { autonomyCommands, runAutonomyCommand } from "./cli-autonomy.js";
11
+ import { output, parse } from "./cli-common.js";
58
12
  import { VERSION } from "./version.js";
59
13
  import { isMainModule } from "./lib/runtime.js";
60
- import { scanIndexedMemoryOrphans } from "./lib/indexed-memory-offline.js";
61
- import {
62
- configurePreflightPolicy, confirmMustRemember, preflightStatus, proposeMustRemember,
63
- purgeMustRemember, rollbackMustRemember
64
- } from "./lib/preflight.js";
65
- import { readFile } from "node:fs/promises";
66
-
67
- function parse(argv) {
68
- const [command = "help", ...rest] = argv;
69
- const flags = {};
70
- const positional = [];
71
- for (let index = 0; index < rest.length; index += 1) {
72
- const token = rest[index];
73
- if (!token.startsWith("--")) {
74
- positional.push(token);
75
- continue;
76
- }
77
- const [name, inline] = token.slice(2).split("=", 2);
78
- if (inline !== undefined) flags[name] = inline;
79
- else if (rest[index + 1] && !rest[index + 1].startsWith("--")) flags[name] = rest[++index];
80
- else flags[name] = true;
81
- }
82
- return { command, flags, positional };
83
- }
84
-
85
- function output(value, json = false) {
86
- if (json) {
87
- process.stdout.write(`${JSON.stringify(value, null, 2)}\n`);
88
- return;
89
- }
90
- if (typeof value === "string") process.stdout.write(`${value}\n`);
91
- else process.stdout.write(`${JSON.stringify(value, null, 2)}\n`);
92
- }
93
-
94
- function booleanFlag(value, fallback = false) {
95
- if (value === undefined) return fallback;
96
- if (value === true || value === "true" || value === "1") return true;
97
- if (value === false || value === "false" || value === "0") return false;
98
- throw new Error(`expected boolean flag, received: ${value}`);
99
- }
100
-
101
- async function goalPlanFlag(path) {
102
- if (!path) return null;
103
- const content = await readFile(path, "utf8");
104
- if (Buffer.byteLength(content) > 64 * 1024) throw new Error("goal plan exceeds 64 KiB");
105
- const parsed = JSON.parse(content);
106
- const steps = Array.isArray(parsed) ? parsed : parsed?.steps;
107
- if (!Array.isArray(steps)) throw new Error("goal plan must be a JSON array or an object with a steps array");
108
- return steps;
109
- }
110
-
111
- function learningScope(flags) {
112
- return {
113
- personaId: flags.persona || null,
114
- userId: flags.user || null,
115
- tenantId: flags.tenant || null,
116
- projectId: flags.project || null,
117
- groupId: flags.group || null,
118
- taskId: flags.task || null
119
- };
120
- }
121
-
122
- function hasLearningScope(flags) {
123
- return ["persona", "user", "tenant", "project", "group", "task"].some((name) => flags[name] !== undefined);
124
- }
125
-
126
- function evaluatorRootsFlag(value) {
127
- return String(value || "").split(",").filter(Boolean).map((entry) => {
128
- const separator = entry.lastIndexOf("=");
129
- if (separator <= 0) throw new Error("evaluator roots must use evaluator-id=sha256 entries");
130
- return { evaluatorId: entry.slice(0, separator), principalDigest: entry.slice(separator + 1) };
131
- });
132
- }
133
14
 
134
15
  function help() {
135
16
  return `AgentSpine ${VERSION}
@@ -186,6 +67,15 @@ Usage:
186
67
  agentspine continuity-purge <entity-id> [--root path] --confirm-local-purge
187
68
  agentspine preflight-policy <policy.json> --confirm-local-policy
188
69
  agentspine preflight-status
70
+ agentspine premortem-recover <predecessor-requirement> [--root path] [--task id] [--json]
71
+ agentspine autonomy-project-set <id> --project id --tenant id (--local-root path|--public-url url) --mode observe|advise|execute|publish [--capabilities tool:name] --confirm-local-autonomy [--confirm-local-publish]
72
+ agentspine autonomy-project-revoke <id> --reason text --confirm-local-autonomy
73
+ agentspine autonomy-scan --tenant id [--group id]
74
+ agentspine autonomy-observe <id> --tenant id --kind ci|error|idea|goal|state --evidence objective|user-feedback|model-suggestion --summary text --source-digest sha256
75
+ agentspine autonomy-status [--tenant id --group id]
76
+ agentspine autonomy-check <id> --tenant id --action observe|advise|execute|publish [--capability tool:name]
77
+ agentspine portfolio --tenant id [--group id --mark-presented]
78
+ agentspine host-install codex [--codex-home path] [--skills-root path] [--package-root path] --confirm-local-host-install [--json]
189
79
  agentspine remember-propose --claim text --user id --tenant id [--project id] [--group id] [--task id]
190
80
  agentspine remember-confirm <candidate-id> [--supersedes id] --confirm-local-user
191
81
  agentspine remember-rollback <id> --confirm-local-user
@@ -195,6 +85,9 @@ Usage:
195
85
  agentspine source-bind <state-root> --host all|claude|codex --scope state-user --project path --host-home path --confirm-local-binding
196
86
  agentspine source-rollback <binding-id> --confirm-local-binding
197
87
  agentspine source-purge <binding-id> --confirm-local-binding
88
+ agentspine timeline-receipt --root path
89
+ agentspine timeline-enroll --root path --receipt asthr_… --confirm-local-timeline
90
+ agentspine timeline-enrollment-recover --root path --confirm-local-timeline-recovery
198
91
  agentspine delegation-grant <actor-id> --actions assign,manage --targets agent:id --reason text [--confirm-local-policy]
199
92
  agentspine delegation-revoke <grant-id> --reason text [--confirm-local-policy]
200
93
  agentspine delegation-check <actor-id> --action assign [--target agent:id]
@@ -254,1229 +147,26 @@ Usage:
254
147
  AgentSpine reads existing Markdown in place. It never rewrites source documents.`;
255
148
  }
256
149
 
150
+ const ROUTES = [
151
+ [coreCommands, runCoreCommand],
152
+ [attentionCommands, runAttentionCommand],
153
+ [learningCommands, runLearningCommand],
154
+ [continuityCommands, runContinuityCommand],
155
+ [agentCommands, runAgentCommand],
156
+ [sharingCommands, runSharingCommand],
157
+ [diagnosticsCommands, runDiagnosticsCommand],
158
+ [premortemCommands, runPremortemCommand],
159
+ [hostCommands, runHostCommand],
160
+ [autonomyCommands, runAutonomyCommand]
161
+ ];
162
+
257
163
  export async function run(argv = process.argv.slice(2)) {
258
164
  const { command, flags, positional } = parse(argv);
259
165
  const json = Boolean(flags.json);
260
- if (command === "help" || command === "--help" || command === "-h") return output(help());
261
- if (command === "version" || command === "--version" || command === "-v") return output(VERSION);
262
-
263
- if (command === "acceptance") {
264
- if (positional.length || Object.keys(flags).some((name) => name !== "json")) {
265
- throw new Error("acceptance supports only --json");
266
- }
267
- const report = await runVisibleAcceptance();
268
- if (json) return output(report, true);
269
- process.stdout.write(renderAcceptanceReport(report));
270
- return;
271
- }
272
-
273
- if (command === "scan") {
274
- const result = await scanAndSave(positional[0] || process.cwd());
275
- return output(json ? result : {
276
- root: result.catalog.root,
277
- catalog: result.catalogPath,
278
- documents: result.catalog.summary.total,
279
- protected: result.catalog.summary.protected,
280
- layers: result.catalog.summary.byLayer
281
- }, json);
282
- }
283
-
284
- if (command === "context") {
285
- const root = positional[0] || process.cwd();
286
- const result = await resolveContext({
287
- root,
288
- cwd: flags.cwd || root,
289
- host: flags.host || "generic",
290
- maxBytes: Number(flags["max-bytes"] || 65536),
291
- includeContent: flags["no-content"] !== true
292
- });
293
- return output(result, json);
294
- }
295
-
296
- if (command === "briefing") {
297
- const root = positional[0] || process.cwd();
298
- return output(await sessionBriefing({
299
- root, cwd: flags.cwd || root, host: flags.host || "generic",
300
- entityId: flags.entity || null, groupId: flags.group || null,
301
- userId: flags.user || null, tenantId: flags.tenant || null,
302
- projectId: flags.project || null, currentTaskId: flags["current-task"] || null,
303
- includePrivate: booleanFlag(flags["include-private"]),
304
- focusActive: !booleanFlag(flags["allow-attention"]),
305
- includeSourceContent: !booleanFlag(flags["no-source-content"]),
306
- maxBytes: Number(flags["max-bytes"] ?? 16384)
307
- }), json);
308
- }
309
-
310
- if (command === "read") {
311
- const result = await readDocument({
312
- root: flags.root || process.cwd(),
313
- path: positional[0],
314
- offset: Number(flags.offset || 0),
315
- length: Number(flags.length || 65536)
316
- });
317
- return output(json ? result : result.content, json);
318
- }
319
-
320
- if (command === "verify") {
321
- const result = await verifyCatalog(positional[0] || process.cwd());
322
- output(result, json);
323
- if (!result.ok) process.exitCode = 1;
324
- return;
325
- }
326
-
327
- if (command === "link") {
328
- const result = await linkDocuments({
329
- root: flags.root || process.cwd(), from: positional[0], to: positional[1],
330
- relation: flags.relation || "related", reason: flags.reason || "",
331
- confidence: Number(flags.confidence ?? 0.5)
332
- });
333
- return output(result, json);
334
- }
335
-
336
- if (command === "annotate") {
337
- const result = await annotateDocument({
338
- root: flags.root || process.cwd(), path: positional[0], layer: flags.layer,
339
- reason: flags.reason || "", confidence: Number(flags.confidence ?? 0.5)
340
- });
341
- return output(result, json);
342
- }
343
-
344
- if (command === "entity") {
345
- const result = await upsertEntity({
346
- root: flags.root || process.cwd(), id: positional[0], kind: flags.kind,
347
- displayName: flags.name || "", confidence: Number(flags.confidence ?? 0.5),
348
- privacy: flags.privacy || "private"
349
- });
350
- return output(result, json);
351
- }
352
-
353
- if (command === "relate") {
354
- const result = await linkEntities({
355
- root: flags.root || process.cwd(), from: positional[0], to: positional[1],
356
- relation: flags.relation || "related", reason: flags.reason || "",
357
- confidence: Number(flags.confidence ?? 0.5), privacy: flags.privacy || "private"
358
- });
359
- return output(result, json);
360
- }
361
-
362
- if (command === "relationships") {
363
- return output(await relationshipContext({
364
- root: flags.root || process.cwd(), entityId: positional[0],
365
- includePrivate: Boolean(flags["include-private"]), groupId: flags.group || null
366
- }), json);
367
- }
368
-
369
- if (command === "attention") {
370
- return output(await attentionContext({
371
- root: positional[0] || process.cwd(),
372
- includePrivate: booleanFlag(flags["include-private"]),
373
- focusActive: booleanFlag(flags["focus-active"]),
374
- markPresented: booleanFlag(flags["mark-presented"]),
375
- entityId: flags.entity || null,
376
- groupId: flags.group || null,
377
- projectId: flags.project || null,
378
- currentTaskId: flags.task || null,
379
- maxItems: flags["max-items"] === undefined ? null : Number(flags["max-items"])
380
- }), json);
381
- }
382
-
383
- if (command === "attention-events") {
384
- const { attention, attentionPath } = await loadAttention(positional[0] || process.cwd());
385
- return output({
386
- schema: "agentspine.attention-events/v1", attentionPath,
387
- events: attention.events,
388
- receipts: attention.receipts,
389
- history: booleanFlag(flags["include-history"]) ? attention.history.filter((item) => item.kind === "attention-event") : [],
390
- authority: "context-only"
391
- }, json);
392
- }
393
-
394
- if (command === "attention-add") {
395
- return output(await upsertAttention({
396
- root: flags.root || process.cwd(), id: positional[0], kind: flags.kind,
397
- summary: flags.summary, entityId: flags.entity || null, dueAt: flags.due || null,
398
- priority: Number(flags.priority ?? 50), privacy: flags.privacy || "private",
399
- groupId: flags.group || null,
400
- sourceDocument: flags.source || null, confidence: Number(flags.confidence ?? 0.5)
401
- }), json);
402
- }
403
-
404
- if (command === "attention-resolve") {
405
- return output(await resolveAttention({
406
- root: flags.root || process.cwd(), id: positional[0], status: flags.status || "completed"
407
- }), json);
408
- }
409
-
410
- if (command === "attention-touch") {
411
- return output(await recordActivity({
412
- root: flags.root || process.cwd(), entityId: positional[0], kind: flags.kind || "interaction",
413
- at: flags.at || new Date(), privacy: flags.privacy || "private", groupId: flags.group || null
414
- }), json);
415
- }
416
-
417
- if (command === "attention-delete") {
418
- return output(await deleteAttention({ root: flags.root || process.cwd(), signalId: positional[0] }), json);
419
- }
420
-
421
- if (command === "attention-event-delete") {
422
- return output(await deleteAttention({ root: flags.root || process.cwd(), eventId: positional[0] }), json);
423
- }
424
-
425
- if (command === "attention-purge") {
426
- return output(await deleteAttention({ root: flags.root || process.cwd(), entityId: positional[0] }), json);
427
- }
428
-
429
- if (command === "attention-config") {
430
- const root = positional[0] || process.cwd();
431
- const config = {};
432
- if (flags.enabled !== undefined) config.enabled = booleanFlag(flags.enabled);
433
- if (flags["min-interval-hours"] !== undefined) config.minIntervalHours = Number(flags["min-interval-hours"]);
434
- if (flags["silence-days"] !== undefined) config.entitySilenceDays = Number(flags["silence-days"]);
435
- if (flags["heartbeat-stale-minutes"] !== undefined) config.heartbeatStaleMinutes = Number(flags["heartbeat-stale-minutes"]);
436
- if (flags["max-items"] !== undefined) config.maxItems = Number(flags["max-items"]);
437
- if (flags["quiet-off"] !== undefined) config.quietHours = null;
438
- else if (flags["quiet-start"] !== undefined || flags["quiet-end"] !== undefined) {
439
- config.quietHours = {
440
- start: Number(flags["quiet-start"]), end: Number(flags["quiet-end"]),
441
- utcOffsetMinutes: Number(flags["utc-offset"] ?? 0)
442
- };
443
- }
444
- if (!Object.keys(config).length) return output((await loadAttention(root)).attention.config, json);
445
- return output(await configureAttention({ root, config }), json);
446
- }
447
-
448
- if (command === "learn-propose") {
449
- return output(await proposeLearning({
450
- root: flags.root || process.cwd(), id: positional[0], kind: flags.kind,
451
- claim: flags.claim, subjectId: flags.subject || null, privacy: flags.privacy || "private",
452
- groupId: flags.group || null, supersedesId: flags.supersedes || null,
453
- scope: hasLearningScope(flags) ? learningScope(flags) : null,
454
- evidence: {
455
- id: flags["evidence-id"], type: flags["evidence-type"] || "user-statement",
456
- summary: flags.evidence, sourceDocument: flags.source || null,
457
- confidence: Number(flags.confidence ?? 0.5), observedAt: flags.at
458
- }
459
- }), json);
460
- }
461
-
462
- if (command === "learn-evidence") {
463
- return output(await addLearningEvidence({
464
- root: flags.root || process.cwd(), id: positional[0],
465
- evidence: {
466
- id: flags["evidence-id"], type: flags.type || "interaction", summary: flags.summary,
467
- sourceDocument: flags.source || null, confidence: Number(flags.confidence ?? 0.5), observedAt: flags.at
468
- }
469
- }), json);
470
- }
471
-
472
- if (command === "learn-evidence-revoke") {
473
- return output(await revokeLearningEvidence({
474
- root: flags.root || process.cwd(), learningId: positional[0], evidenceId: flags["evidence-id"],
475
- reasonCode: flags["reason-code"], reason: flags.reason,
476
- confirmation: booleanFlag(flags["confirm-local-evidence"])
477
- ? "local-evidence-revocation-confirmed" : null
478
- }), json);
479
- }
480
-
481
- if (command === "learn-review") {
482
- return output(await reviewLearning({
483
- root: flags.root || process.cwd(), id: positional[0], decision: flags.decision,
484
- reason: flags.reason, confirmedByUser: booleanFlag(flags["confirmed-by-user"])
485
- }), json);
486
- }
487
-
488
- if (command === "learn-context") {
489
- return output(await learningContext({
490
- root: positional[0] || process.cwd(), includePrivate: booleanFlag(flags["include-private"]),
491
- groupId: flags.group || null,
492
- scope: hasLearningScope(flags) ? learningScope(flags) : null,
493
- kinds: flags.kind ? String(flags.kind).split(",").filter(Boolean) : null,
494
- subjectIds: flags.subject ? String(flags.subject).split(",").filter(Boolean) : null,
495
- maxItems: flags["max-items"] === undefined ? null : Number(flags["max-items"])
496
- }), json);
497
- }
498
-
499
- if (command === "learn-evaluate") {
500
- return output(await evaluateLearning({ root: positional[0] || process.cwd() }), json);
501
- }
502
-
503
- if (command === "learn-evaluator-register") {
504
- return output(await registerLearningEvaluator({
505
- root: flags.root || process.cwd(), id: positional[0], principalDigest: flags["principal-digest"],
506
- confirmLocalEvaluator: booleanFlag(flags["confirm-local-evaluator"])
507
- }), json);
508
- }
509
-
510
- if (command === "learn-evaluator-revoke") {
511
- return output(await revokeLearningEvaluator({
512
- root: flags.root || process.cwd(), id: positional[0], reason: flags.reason,
513
- confirmLocalEvaluator: booleanFlag(flags["confirm-local-evaluator"])
514
- }), json);
515
- }
516
-
517
- if (command === "learn-evaluation") {
518
- return output(await registerLearningEvaluation({
519
- root: flags.root || process.cwd(), id: positional[0], learningId: flags.learning,
520
- scope: learningScope(flags), metric: { name: flags.metric, direction: flags.direction },
521
- benchmark: {
522
- taskDigest: flags["task-digest"], datasetDigest: flags["dataset-digest"],
523
- protocolDigest: flags["protocol-digest"], minCases: Number(flags["min-cases"])
524
- },
525
- evaluatorIds: String(flags.evaluators || "").split(",").filter(Boolean),
526
- evaluatorRoots: evaluatorRootsFlag(flags["evaluator-roots"]),
527
- expiresAt: flags["expires-at"] || null,
528
- retryTrialFailureId: flags["retry-trial-failure"] || null,
529
- confirmLocalTrialRetry: booleanFlag(flags["confirm-local-trial-retry"]),
530
- confirmLocalEvidenceSources: booleanFlag(flags["confirm-local-evidence-sources"]),
531
- confirmLocalEvaluation: booleanFlag(flags["confirm-local-evaluation"])
532
- }), json);
533
- }
534
-
535
- if (command === "learn-revalidation-start") {
536
- return output(await beginLearningRevalidation({
537
- root: flags.root || process.cwd(), learningId: positional[0],
538
- confirmLocalValidation: booleanFlag(flags["confirm-local-validation"])
539
- }), json);
540
- }
541
-
542
- if (command === "learn-revalidate") {
543
- const measurements = String(flags.measurements || "").split(",").filter(Boolean);
544
- const applications = String(flags.applications || "").split(",").filter(Boolean);
545
- const deliveries = String(flags.deliveries || "").split(",").filter(Boolean);
546
- if (!measurements.length || measurements.length !== applications.length || measurements.length !== deliveries.length) {
547
- throw new Error("revalidation requires equally sized measurement, application, and delivery lists");
548
- }
549
- return output(await renewLearningValidation({
550
- root: flags.root || process.cwd(), learningId: positional[0],
551
- evidence: measurements.map((measurementId, index) => ({ measurementId,
552
- applicationId: applications[index], deliveryId: deliveries[index] })),
553
- confirmLocalValidation: booleanFlag(flags["confirm-local-validation"])
554
- }), json);
555
- }
556
-
557
- if (command === "learn-measurement") {
558
- return output(await recordLearningMeasurement({
559
- root: flags.root || process.cwd(), id: positional[0], learningId: flags.learning,
560
- evaluationId: flags.evaluation, phase: flags.phase, scope: learningScope(flags),
561
- metric: {
562
- name: flags.metric, direction: flags.direction, value: Number(flags.value),
563
- blockingDefects: Number(flags["blocking-defects"] ?? 0)
564
- },
565
- measurement: {
566
- kind: flags.measurement || "objective", evaluatorId: flags.evaluator,
567
- runId: flags.run, sourceDigest: flags["source-digest"]
568
- },
569
- coverage: { datasetDigest: flags["dataset-digest"], caseCount: Number(flags["case-count"]) },
570
- measuredAt: flags.at,
571
- confirmLocalMeasurement: booleanFlag(flags["confirm-local-measurement"])
572
- }), json);
573
- }
574
-
575
- if (command === "learn-measurement-revoke") {
576
- return output(await revokeLearningMeasurement({
577
- root: flags.root || process.cwd(), measurementId: positional[0], reasonCode: flags["reason-code"],
578
- reason: flags.reason,
579
- confirmation: booleanFlag(flags["confirm-local-measurement-revocation"])
580
- ? "local-measurement-revocation-confirmed" : null
581
- }), json);
582
- }
583
-
584
- if (command === "learn-evaluation-revoke") {
585
- return output(await revokeLearningEvaluation({
586
- root: flags.root || process.cwd(), evaluationId: positional[0], reasonCode: flags["reason-code"],
587
- reason: flags.reason,
588
- confirmation: booleanFlag(flags["confirm-local-evaluation-revocation"])
589
- ? "local-evaluation-revocation-confirmed" : null
590
- }), json);
591
- }
592
-
593
- if (command === "learn-evidence-source-attestation-revoke") {
594
- return output(await revokeLearningEvidenceSourceAttestation({
595
- root: flags.root || process.cwd(), evaluationId: positional[0], evidenceDigest: flags["evidence-digest"],
596
- reasonCode: flags["reason-code"], reason: flags.reason,
597
- confirmation: booleanFlag(flags["confirm-local-evidence-source-attestation-revocation"])
598
- ? "local-evidence-source-attestation-revocation-confirmed" : null
599
- }), json);
600
- }
601
-
602
- if (command === "learn-validation-revoke") {
603
- return output(await revokeLearningValidation({
604
- root: flags.root || process.cwd(), validationLeaseId: positional[0], reasonCode: flags["reason-code"],
605
- reason: flags.reason,
606
- confirmation: booleanFlag(flags["confirm-local-validation-revocation"])
607
- ? "local-validation-revocation-confirmed" : null
608
- }), json);
609
- }
610
-
611
- if (command === "learn-trial-failure-revoke") {
612
- return output(await revokeLearningTrialFailure({
613
- root: flags.root || process.cwd(), trialFailureId: positional[0], reasonCode: flags["reason-code"],
614
- reason: flags.reason,
615
- confirmation: booleanFlag(flags["confirm-local-trial-failure-revocation"])
616
- ? "local-trial-failure-revocation-confirmed" : null
617
- }), json);
618
- }
619
-
620
- if (command === "learn-application-revoke") {
621
- return output(await revokeLearningApplication({
622
- root: flags.root || process.cwd(), applicationId: positional[0], reasonCode: flags["reason-code"],
623
- reason: flags.reason,
624
- confirmation: booleanFlag(flags["confirm-local-application-revocation"])
625
- ? "local-application-revocation-confirmed" : null
626
- }), json);
627
- }
628
-
629
- if (command === "learn-delivery-revoke") {
630
- return output(await revokeLearningDelivery({
631
- root: flags.root || process.cwd(), deliveryId: positional[0], reasonCode: flags["reason-code"],
632
- reason: flags.reason,
633
- confirmation: booleanFlag(flags["confirm-local-delivery-revocation"])
634
- ? "local-delivery-revocation-confirmed" : null
635
- }), json);
636
- }
637
-
638
- if (command === "learn-outcome-revoke") {
639
- return output(await revokeLearningOutcome({
640
- root: flags.root || process.cwd(), outcomeId: positional[0], reasonCode: flags["reason-code"],
641
- reason: flags.reason,
642
- confirmation: booleanFlag(flags["confirm-local-outcome-revocation"])
643
- ? "local-outcome-revocation-confirmed" : null
644
- }), json);
645
- }
646
-
647
- if (command === "learn-outcome") {
648
- const lineage = flags["measurement-receipt"] || null;
649
- return output(await recordLearningOutcome({
650
- root: flags.root || process.cwd(), learningId: positional[0], id: flags.id,
651
- evaluationId: flags.evaluation, measurementReceiptId: lineage,
652
- applicationId: flags.application || null, deliveryId: flags.delivery || null,
653
- ...(lineage ? {} : { phase: flags.phase, scope: learningScope(flags), metric: {
654
- name: flags.metric, direction: flags.direction, value: Number(flags.value),
655
- blockingDefects: Number(flags["blocking-defects"] ?? 0)
656
- },
657
- measurement: {
658
- kind: flags.measurement || "objective", evaluatorId: flags.evaluator,
659
- sourceDigest: flags["source-digest"] || null
660
- },
661
- coverage: {
662
- datasetDigest: flags["dataset-digest"],
663
- caseCount: Number(flags["case-count"])
664
- },
665
- measuredAt: flags.at })
666
- }), json);
667
- }
668
-
669
- if (command === "learn-status") {
670
- return output(await learningOutcomeStatus({
671
- root: positional[0] || process.cwd(), scope: hasLearningScope(flags) ? learningScope(flags) : null
672
- }), json);
673
- }
674
-
675
- if (command === "learn-delivery-purge") {
676
- return output(await purgeStaleLearningApplications({
677
- root: positional[0] || process.cwd(),
678
- confirmation: booleanFlag(flags["confirm-local-purge"]) ? "local-user-purge-confirmed" : null
679
- }), json);
680
- }
681
-
682
- if (command === "learn-measurement-purge") {
683
- return output(await purgeStaleLearningMeasurements({
684
- root: positional[0] || process.cwd(),
685
- confirmation: booleanFlag(flags["confirm-local-purge"]) ? "local-user-purge-confirmed" : null
686
- }), json);
687
- }
688
-
689
- if (command === "learn-rollback") {
690
- return output(await rollbackLearning({
691
- root: flags.root || process.cwd(), id: positional[0], reason: flags.reason
692
- }), json);
693
- }
694
-
695
- if (command === "learn-delete") {
696
- return output(await deleteLearning({ root: flags.root || process.cwd(), id: positional[0] }), json);
697
- }
698
-
699
- if (command === "learn-config") {
700
- const root = positional[0] || process.cwd();
701
- const config = {};
702
- if (flags["auto-promote"] !== undefined) config.autoPromote = booleanFlag(flags["auto-promote"]);
703
- if (flags["min-confidence"] !== undefined) config.minConfidence = Number(flags["min-confidence"]);
704
- if (flags["min-evidence"] !== undefined) config.minEvidence = Number(flags["min-evidence"]);
705
- if (flags["max-items"] !== undefined) config.maxContextItems = Number(flags["max-items"]);
706
- if (flags["min-outcomes"] !== undefined) config.minOutcomeReceipts = Number(flags["min-outcomes"]);
707
- if (flags["min-improvement"] !== undefined) config.minImprovement = Number(flags["min-improvement"]);
708
- if (flags["regression-tolerance"] !== undefined) config.regressionTolerance = Number(flags["regression-tolerance"]);
709
- if (flags["outcome-max-age-days"] !== undefined) config.outcomeMaxAgeDays = Number(flags["outcome-max-age-days"]);
710
- if (flags["canary-receipts"] !== undefined) config.canaryReceipts = Number(flags["canary-receipts"]);
711
- if (flags["canary-ttl-days"] !== undefined) config.canaryTtlDays = Number(flags["canary-ttl-days"]);
712
- if (flags["initial-trial-outcome-timeout-minutes"] !== undefined) {
713
- config.initialTrialOutcomeTimeoutMinutes = Number(flags["initial-trial-outcome-timeout-minutes"]);
714
- }
715
- if (!Object.keys(config).length) return output((await loadLearning(root)).learning.config, json);
716
- return output(await configureLearning({ root, config }), json);
717
- }
718
-
719
- if (command === "continuity-config") {
720
- const root = positional[0] || process.cwd();
721
- const config = {};
722
- if (flags.enabled !== undefined) config.enabled = booleanFlag(flags.enabled);
723
- if (flags.entity !== undefined) config.defaultEntityId = flags.entity === "none" ? null : flags.entity;
724
- if (flags.project !== undefined) config.defaultProjectId = flags.project === "none" ? null : flags.project;
725
- if (flags["min-confidence"] !== undefined) config.minConfidence = Number(flags["min-confidence"]);
726
- if (flags["min-directness"] !== undefined) config.minDirectness = Number(flags["min-directness"]);
727
- if (flags["min-evidence"] !== undefined) config.minEvidence = Number(flags["min-evidence"]);
728
- if (flags["max-prompt-bytes"] !== undefined) config.maxPromptBytes = Number(flags["max-prompt-bytes"]);
729
- if (flags["max-briefing-bytes"] !== undefined) config.maxBriefingBytes = Number(flags["max-briefing-bytes"]);
730
- if (!Object.keys(config).length) return output((await loadContinuity(root)).continuity.config, json);
731
- return output(await configureContinuity({
732
- root, config,
733
- confirmation: booleanFlag(flags["confirm-local-opt-in"]) ? "local-user-opt-in" : null
734
- }), json);
735
- }
736
-
737
- if (command === "continuity-status") {
738
- const { continuity, continuityPath } = await loadContinuity(positional[0] || process.cwd());
739
- return output({
740
- schema: continuity.schema, config: continuity.config,
741
- signals: continuity.signals.length, history: continuity.history.length,
742
- continuityPath, authority: "context-only"
743
- }, json);
744
- }
745
-
746
- if (command === "continuity-purge") {
747
- return output(await purgeContinuity({
748
- root: flags.root || process.cwd(), subjectId: positional[0],
749
- confirmation: booleanFlag(flags["confirm-local-purge"]) ? "local-user-confirmed" : null
750
- }), json);
751
- }
752
-
753
- if (command === "preflight-policy") {
754
- if (!positional[0]) throw new Error("preflight-policy requires one local JSON policy file");
755
- const profile = JSON.parse(await readFile(positional[0], "utf8"));
756
- return output(await configurePreflightPolicy({ profile,
757
- confirmation: booleanFlag(flags["confirm-local-policy"]) ? "local-owner-confirmed" : null }), json);
758
- }
759
-
760
- if (command === "preflight-status") return output(await preflightStatus(), json);
761
-
762
- if (command === "remember-propose") {
763
- return output(await proposeMustRemember({ claim: flags.claim, kind: flags.kind || "critical",
764
- userId: flags.user, tenantId: flags.tenant, projectId: flags.project || null,
765
- groupId: flags.group || null, taskId: flags.task || null, sourceDigest: flags["source-digest"] || null }), json);
766
- }
767
-
768
- if (command === "remember-confirm") {
769
- return output(await confirmMustRemember({ candidateId: positional[0], supersedes: flags.supersedes || null,
770
- confirmation: booleanFlag(flags["confirm-local-user"]) ? "local-user-confirmed" : null }), json);
771
- }
772
-
773
- if (command === "remember-rollback") {
774
- return output(await rollbackMustRemember({ id: positional[0],
775
- confirmation: booleanFlag(flags["confirm-local-user"]) ? "local-user-confirmed" : null }), json);
776
- }
777
-
778
- if (command === "remember-purge") {
779
- return output(await purgeMustRemember({ id: positional[0],
780
- confirmation: booleanFlag(flags["confirm-local-purge"]) ? "local-user-purge-confirmed" : null }), json);
781
- }
782
-
783
- if (command === "source-status") {
784
- const host = flags.host || process.env.AGENTSPINE_HOST;
785
- if (!["claude", "codex"].includes(host)) throw new Error("source-status requires --host claude or --host codex");
786
- const resolved = await resolveHostSourceCatalog({ host, cwd: flags.cwd || process.cwd() });
787
- const registry = await inspectSourceRegistry();
788
- return output({ diagnostics: resolved.diagnostics, sources: resolved.catalog.documents.map((item) => ({
789
- id: item.relativePath, scope: item.sourceScope, binding: item.sourceBinding, sha256: item.sha256,
790
- bytes: item.bytes, authority: item.authority
791
- })), bindings: registry.registry.bindings, authority: "context-only" }, json);
792
- }
793
-
794
- if (command === "source-bind") {
795
- return output(await bindSourceRoot({
796
- host: flags.host, hostHome: flags["host-home"] || process.env.CLAUDE_CONFIG_DIR || process.env.CODEX_HOME || process.cwd(),
797
- projectRoot: flags.project || process.cwd(), sourceRoot: positional[0], scope: flags.scope || "state-user",
798
- confirmation: booleanFlag(flags["confirm-local-binding"]) ? "local-user-confirmed" : null
799
- }), json);
800
- }
801
-
802
- if (command === "source-rollback") {
803
- return output(await rollbackSourceBinding({ id: positional[0],
804
- confirmation: booleanFlag(flags["confirm-local-binding"]) ? "local-user-confirmed" : null }), json);
805
- }
806
-
807
- if (command === "source-purge") {
808
- return output(await purgeSourceBinding({ id: positional[0],
809
- confirmation: booleanFlag(flags["confirm-local-binding"]) ? "local-user-confirmed" : null }), json);
810
- }
811
-
812
- if (command === "delegation-grant") {
813
- return output(await grantDelegation({
814
- root: flags.root || process.cwd(), actorId: positional[0],
815
- id: flags.id, actions: String(flags.actions || "").split(",").filter(Boolean),
816
- targetIds: String(flags.targets || "*").split(",").filter(Boolean), reason: flags.reason,
817
- confirmation: booleanFlag(flags["confirm-local-policy"]) ? "local-owner-confirmed" : null
818
- }), json);
819
- }
820
-
821
- if (command === "delegation-revoke") {
822
- return output(await revokeDelegation({
823
- root: flags.root || process.cwd(), id: positional[0], reason: flags.reason,
824
- confirmation: booleanFlag(flags["confirm-local-policy"]) ? "local-owner-confirmed" : null
825
- }), json);
826
- }
827
-
828
- if (command === "delegation-check") {
829
- return output(await checkDelegation({
830
- root: flags.root || process.cwd(), actorId: positional[0], action: flags.action,
831
- targetId: flags.target || null
832
- }), json);
833
- }
834
-
835
- if (command === "delegation-policy") {
836
- return output((await loadDelegationPolicy(positional[0] || process.cwd())).policy, json);
837
- }
838
-
839
- if (command === "task-create") {
840
- return output(await createTask({
841
- root: flags.root || process.cwd(), id: positional[0], actorId: flags.actor,
842
- assigneeId: flags.assignee || null, kind: flags.kind || "task", title: flags.title,
843
- summary: flags.summary || null, projectId: flags.project || null,
844
- privacy: flags.privacy || "private", groupId: flags.group || null,
845
- priority: Number(flags.priority ?? 50), dueAt: flags.due || null
846
- }), json);
847
- }
848
-
849
- if (command === "task-update") {
850
- const patch = {};
851
- if (flags.status !== undefined) patch.status = flags.status;
852
- if (flags.assignee !== undefined) patch.assigneeId = flags.assignee;
853
- if (flags.unassign !== undefined) patch.assigneeId = null;
854
- if (flags.title !== undefined) patch.title = flags.title;
855
- if (flags.summary !== undefined) patch.summary = flags.summary;
856
- if (flags.priority !== undefined) patch.priority = Number(flags.priority);
857
- if (flags.due !== undefined) patch.dueAt = flags.due;
858
- if (flags["clear-due"] !== undefined) patch.dueAt = null;
859
- if (flags.note !== undefined) patch.note = flags.note;
860
- return output(await updateTask({
861
- root: flags.root || process.cwd(), id: positional[0], actorId: flags.actor, patch
862
- }), json);
863
- }
864
-
865
- if (command === "tasks") {
866
- return output(await taskContext({
867
- root: positional[0] || process.cwd(), includePrivate: booleanFlag(flags["include-private"]),
868
- groupId: flags.group || null, actorId: flags.actor || null, assigneeId: flags.assignee || null,
869
- projectId: flags.project || null, includeClosed: booleanFlag(flags.closed),
870
- maxItems: Number(flags["max-items"] ?? 20)
871
- }), json);
872
- }
873
-
874
- if (command === "task-delete") {
875
- return output(await deleteTask({
876
- root: flags.root || process.cwd(), id: positional[0],
877
- confirmation: booleanFlag(flags["confirm-local-policy"]) ? "local-owner-confirmed" : null
878
- }), json);
879
- }
880
-
881
- if (command === "execution-grant") {
882
- return output(await grantExecution({
883
- root: flags.root || process.cwd(), id: flags.id, jobId: positional[0], actorId: flags.actor,
884
- taskId: flags.task, targetId: flags.target, projectId: flags.project, groupId: flags.group || null,
885
- host: flags.host, capabilities: String(flags.capabilities || "").split(",").filter(Boolean),
886
- reason: flags.reason, expiresAt: flags.expires || null,
887
- confirmation: booleanFlag(flags["confirm-local-execution"]) ? "local-owner-confirmed" : null
888
- }), json);
889
- }
890
-
891
- if (command === "execution-revoke") {
892
- return output(await revokeExecution({
893
- root: flags.root || process.cwd(), id: positional[0], reason: flags.reason,
894
- confirmation: booleanFlag(flags["confirm-local-execution"]) ? "local-owner-confirmed" : null
895
- }), json);
896
- }
897
-
898
- if (command === "execution-policy") {
899
- return output((await loadExecutionPolicy(positional[0] || process.cwd())).policy, json);
900
- }
901
-
902
- if (command === "job-register") {
903
- return output(await registerJob({
904
- root: flags.root || process.cwd(), id: positional[0], grantId: flags.grant,
905
- maxRetries: Number(flags["max-retries"] ?? 3), leaseSeconds: Number(flags["lease-seconds"] ?? 120),
906
- baseRetrySeconds: Number(flags["retry-seconds"] ?? 5),
907
- confirmation: booleanFlag(flags["confirm-local-execution"]) ? "local-owner-confirmed" : null
908
- }), json);
909
- }
910
-
911
- if (command === "jobs") {
912
- return output(await selfstarterContext({
913
- root: positional[0] || process.cwd(), actorId: flags.actor || null,
914
- projectId: flags.project || null, taskId: flags.task || null,
915
- includeTerminal: booleanFlag(flags["include-terminal"])
916
- }), json);
917
- }
918
-
919
- if (command === "job-cancel") {
920
- return output(await cancelJob({
921
- root: flags.root || process.cwd(), id: positional[0], reason: flags.reason,
922
- confirmation: booleanFlag(flags["confirm-local-execution"]) ? "local-owner-confirmed" : null
923
- }), json);
924
- }
925
-
926
- if (command === "job-delete") {
927
- return output(await deleteJob({
928
- root: flags.root || process.cwd(), id: positional[0],
929
- confirmation: booleanFlag(flags["confirm-local-execution"]) ? "local-owner-confirmed" : null
930
- }), json);
931
- }
932
-
933
- if (command === "channel-bind") {
934
- return output(await grantChannelBinding({
935
- root: flags.root || process.cwd(), id: positional[0], provider: flags.provider,
936
- tenantId: flags.tenant, accountId: flags.account, chatId: flags.chat,
937
- threadId: flags.thread || null,
938
- senderIds: String(flags.senders || "").split(",").filter(Boolean),
939
- agentId: flags.agent, projectId: flags.project, groupId: flags.group || null,
940
- sessionKey: flags.session, secretEnv: flags["secret-env"], outboundSecretEnv: flags["outbound-secret-env"] || null,
941
- capabilities: String(flags.capabilities || "receive,reply").split(",").filter(Boolean),
942
- confirmation: booleanFlag(flags["confirm-local-channel"]) ? "local-owner-confirmed" : null
943
- }), json);
944
- }
945
-
946
- if (command === "channel-revoke") {
947
- return output(await revokeChannelBinding({
948
- root: flags.root || process.cwd(), id: positional[0], reason: flags.reason,
949
- confirmation: booleanFlag(flags["confirm-local-channel"]) ? "local-owner-confirmed" : null
950
- }), json);
951
- }
952
-
953
- if (command === "channel-policy") {
954
- return output((await loadChannelPolicy(positional[0] || process.cwd())).policy, json);
955
- }
956
-
957
- if (command === "channel-events") {
958
- return output(await channelRuntimeContext({
959
- root: positional[0] || process.cwd(), agentId: flags.agent || null,
960
- projectId: flags.project || null,
961
- ...(flags.group !== undefined ? { groupId: flags.group || null } : {}),
962
- provider: flags.provider || null,
963
- includeTerminal: booleanFlag(flags["include-terminal"]),
964
- maxItems: Number(flags["max-items"] ?? 20)
965
- }), json);
966
- }
967
-
968
- if (command === "persona-sync") {
969
- if (!booleanFlag(flags["confirm-local-persona"])) throw new Error("persona synchronization requires --confirm-local-persona");
970
- return output(await syncPersonaRosterFromEnvironment({
971
- root: positional[0] || process.cwd(), env: { ...process.env, AGENTSPINE_PERSONA_ROSTER_FILE: flags.roster }
972
- }), json);
973
- }
974
-
975
- if (command === "personas") {
976
- return output(await personaContext({
977
- root: positional[0] || process.cwd(), personaId: flags.persona || null,
978
- ...(flags.group !== undefined ? { groupId: flags.group || null } : {}),
979
- includeInactive: booleanFlag(flags["include-inactive"])
980
- }), json);
981
- }
982
-
983
- if (command === "goal-assign") {
984
- return output(await assignGoal({
985
- root: flags.root || process.cwd(), goalId: positional[0], agentId: flags.agent,
986
- ownerSubjectId: flags.owner, projectId: flags.project, groupId: flags.group || null,
987
- priority: Number(flags.priority ?? 70), successCriterion: flags.success,
988
- nextSafeStep: flags["next-step"] || null, steps: await goalPlanFlag(flags.plan), deadline: flags.deadline || null,
989
- confirmation: booleanFlag(flags["confirm-local-goal"]) ? "local-owner-confirmed" : null
990
- }), json);
991
- }
992
-
993
- if (command === "goal-clarify") {
994
- return output(await resolveGoalKnowledgeGap({
995
- root: flags.root || process.cwd(), goalId: positional[0], gapId: flags.gap,
996
- answer: flags.answer, answerSource: flags.source || "owner-input",
997
- sourceDigest: flags["source-digest"] || null,
998
- confirmation: booleanFlag(flags["confirm-local-goal"]) ? "local-owner-confirmed" : null
999
- }), json);
1000
- }
1001
-
1002
- if (command === "gateway-control") {
1003
- return output(await setGatewayControl({
1004
- root: positional[0] || process.cwd(),
1005
- ...(flags.enabled !== undefined ? { enabled: booleanFlag(flags.enabled) } : {}),
1006
- ...(flags["kill-switch"] !== undefined ? { killSwitch: booleanFlag(flags["kill-switch"]) } : {}),
1007
- confirmation: booleanFlag(flags["confirm-local-gateway"]) ? "local-owner-confirmed" : null
1008
- }), json);
1009
- }
1010
-
1011
- if (command === "gateway-status") {
1012
- return output(await gatewayContext({ root: positional[0] || process.cwd(), agentId: flags.agent || null }), json);
1013
- }
1014
-
1015
- if (command === "share-init") {
1016
- return output(await initDirectoryAdapter({
1017
- root: flags.root || process.cwd(), directory: positional[0], scopeId: flags.scope,
1018
- adapterId: flags.adapter, signerId: flags.signer || null,
1019
- confirmation: booleanFlag(flags["confirm-local-share"]) ? "local-share-confirmed" : null
1020
- }), json);
1021
- }
1022
-
1023
- if (command === "share-keygen") {
1024
- return output(await generateSigningIdentity({
1025
- root: flags.root || process.cwd(), signerId: positional[0], rotate: booleanFlag(flags.rotate),
1026
- publicOut: flags["public-out"] || null,
1027
- confirmation: booleanFlag(flags["confirm-local-share"]) ? "local-share-confirmed" : null
1028
- }), json);
1029
- }
1030
-
1031
- if (command === "share-signers") {
1032
- return output(await listSigningIdentities({ root: positional[0] || process.cwd() }), json);
1033
- }
1034
-
1035
- if (command === "share-trust") {
1036
- return output(await trustSigner({
1037
- root: flags.root || process.cwd(), publicIdentityPath: positional[0],
1038
- confirmation: booleanFlag(flags["confirm-local-share"]) ? "local-share-confirmed" : null
1039
- }), json);
1040
- }
1041
-
1042
- if (command === "share-trust-revoke") {
1043
- return output(await revokeTrustedSigner({
1044
- root: flags.root || process.cwd(), keyId: positional[0], reason: flags.reason,
1045
- confirmation: booleanFlag(flags["confirm-local-share"]) ? "local-share-confirmed" : null
1046
- }), json);
1047
- }
1048
-
1049
- if (command === "share-trust-list") {
1050
- return output(await trustedSignerContext({
1051
- root: positional[0] || process.cwd(), includeRevoked: booleanFlag(flags["include-revoked"])
1052
- }), json);
1053
- }
1054
-
1055
- if (command === "share-publish") {
1056
- return output(await publishLearning({
1057
- root: flags.root || process.cwd(), directory: positional[0], learningId: flags.learning,
1058
- eventId: flags.id, supersedesEventId: flags.supersedes || null, signerId: flags.signer || null,
1059
- confirmation: booleanFlag(flags["confirm-local-share"]) ? "local-share-confirmed" : null
1060
- }), json);
1061
- }
1062
-
1063
- if (command === "share-pull") {
1064
- return output(await pullShared({
1065
- root: flags.root || process.cwd(), directory: positional[0],
1066
- requireAuthenticated: booleanFlag(flags["require-authenticated"])
1067
- }), json);
1068
- }
1069
-
1070
- if (command === "share-snapshot-export") {
1071
- return output(await exportHttpsSnapshot({
1072
- root: flags.root || process.cwd(), directory: positional[0], output: flags.out,
1073
- snapshotId: flags.id,
1074
- confirmation: booleanFlag(flags["confirm-local-share"]) ? "local-share-confirmed" : null
1075
- }), json);
1076
- }
1077
-
1078
- if (command === "share-https-publish") {
1079
- return output(await publishHttpsSnapshot({
1080
- root: flags.root || process.cwd(), directory: positional[0], baseUrl: flags.base,
1081
- snapshotId: flags.id, tokenEnv: flags["token-env"] || null,
1082
- timeoutMs: Number(flags["timeout-ms"] ?? 10000),
1083
- allowPrivateNetwork: booleanFlag(flags["allow-private-network"]),
1084
- confirmation: booleanFlag(flags["confirm-local-share"]) ? "local-share-confirmed" : null
1085
- }), json);
1086
- }
1087
-
1088
- if (command === "share-https-pull") {
1089
- return output(await pullHttpsSnapshot({
1090
- root: flags.root || process.cwd(), url: positional[0], tokenEnv: flags["token-env"] || null,
1091
- timeoutMs: Number(flags["timeout-ms"] ?? 10000),
1092
- allowPrivateNetwork: booleanFlag(flags["allow-private-network"]),
1093
- confirmation: booleanFlag(flags["confirm-local-share"]) ? "local-share-confirmed" : null
1094
- }), json);
1095
- }
1096
-
1097
- if (command === "share-feed-publish") {
1098
- return output(await publishHttpsFeed({
1099
- root: flags.root || process.cwd(), directory: positional[0], baseUrl: flags.base,
1100
- feedId: flags.feed, signerId: flags.signer, snapshotId: flags.id,
1101
- tokenEnv: flags["token-env"] || null, timeoutMs: Number(flags["timeout-ms"] ?? 10000),
1102
- allowPrivateNetwork: booleanFlag(flags["allow-private-network"]),
1103
- confirmation: booleanFlag(flags["confirm-local-share"]) ? "local-share-confirmed" : null
1104
- }), json);
1105
- }
1106
-
1107
- if (command === "share-feed-pull") {
1108
- return output(await pullHttpsFeed({
1109
- root: flags.root || process.cwd(), baseUrl: flags.base, feedId: flags.feed,
1110
- tokenEnv: flags["token-env"] || null, timeoutMs: Number(flags["timeout-ms"] ?? 10000),
1111
- allowPrivateNetwork: booleanFlag(flags["allow-private-network"]),
1112
- confirmation: booleanFlag(flags["confirm-local-share"]) ? "local-share-confirmed" : null
1113
- }), json);
1114
- }
1115
-
1116
- if (command === "share-feed-state") {
1117
- return output(await loadHttpsFeedState(positional[0] || process.cwd()), json);
1118
- }
1119
-
1120
- if (command === "share-peer-serve") {
1121
- await servePeerOnce({
1122
- root: flags.root || process.cwd(), directory: positional[0], signerId: flags.signer,
1123
- input: process.stdin, output: process.stdout,
1124
- timeoutMs: Number(flags["timeout-ms"] ?? 10000),
1125
- confirmation: booleanFlag(flags["confirm-local-share"]) ? "local-share-confirmed" : null
1126
- });
1127
- return;
1128
- }
1129
-
1130
- if (command === "share-peer-pull") {
1131
- return output(await pullPeerCommand({
1132
- root: flags.root || process.cwd(), commandJson: flags["command-json"],
1133
- timeoutMs: Number(flags["timeout-ms"] ?? 10000),
1134
- maxBytes: Number(flags["max-bytes"] ?? 22 * 1024 * 1024),
1135
- confirmation: booleanFlag(flags["confirm-local-share"]) ? "local-share-confirmed" : null
1136
- }), json);
1137
- }
1138
-
1139
- if (command === "share-sqlite-init") {
1140
- return output(await initSqliteAdapter({
1141
- root: flags.root || process.cwd(), directory: positional[0], database: flags.database,
1142
- confirmation: booleanFlag(flags["confirm-local-share"]) ? "local-share-confirmed" : null
1143
- }), json);
1144
- }
1145
-
1146
- if (command === "share-sqlite-publish") {
1147
- return output(await publishSqliteSnapshot({
1148
- root: flags.root || process.cwd(), directory: positional[0], database: flags.database,
1149
- snapshotId: flags.id,
1150
- confirmation: booleanFlag(flags["confirm-local-share"]) ? "local-share-confirmed" : null
1151
- }), json);
1152
- }
1153
-
1154
- if (command === "share-sqlite-inspect") {
1155
- return output(await inspectSqliteAdapter({
1156
- root: flags.root || process.cwd(), database: flags.database
1157
- }), json);
1158
- }
1159
-
1160
- if (command === "share-sqlite-pull") {
1161
- return output(await pullSqliteSnapshot({
1162
- root: flags.root || process.cwd(), database: flags.database
1163
- }), json);
1164
- }
1165
-
1166
- if (command === "share-inbox") {
1167
- return output(await sharedInbox({ root: positional[0] || process.cwd(), status: flags.status || "pending" }), json);
1168
- }
1169
-
1170
- if (command === "share-review") {
1171
- return output(await reviewShared({
1172
- root: flags.root || process.cwd(), id: positional[0], decision: flags.decision,
1173
- reason: flags.reason, confirmedByUser: booleanFlag(flags["confirmed-by-user"])
1174
- }), json);
1175
- }
1176
-
1177
- if (command === "share-context") {
1178
- return output(await sharedContext({
1179
- root: positional[0] || process.cwd(), scopeId: flags.scope || null, groupId: flags.group || null,
1180
- includePrivate: booleanFlag(flags["include-private"]),
1181
- kinds: flags.kind ? String(flags.kind).split(",").filter(Boolean) : null,
1182
- subjectIds: flags.subject ? String(flags.subject).split(",").filter(Boolean) : null,
1183
- maxItems: flags["max-items"] === undefined ? null : Number(flags["max-items"])
1184
- }), json);
1185
- }
1186
-
1187
- if (command === "share-rollback") {
1188
- return output(await rollbackShared({
1189
- root: flags.root || process.cwd(), id: positional[0], reason: flags.reason
1190
- }), json);
1191
- }
1192
-
1193
- if (command === "share-delete") {
1194
- return output(await deleteShared({
1195
- root: flags.root || process.cwd(), id: positional[0],
1196
- confirmation: booleanFlag(flags["confirm-local-share"]) ? "local-share-confirmed" : null
1197
- }), json);
1198
- }
1199
-
1200
- if (command === "share-config") {
1201
- return output(await configureSharing({
1202
- root: positional[0] || process.cwd(), maxContextItems: Number(flags["max-items"])
1203
- }), json);
1204
- }
1205
-
1206
- if (command === "doctor") {
1207
- let hostIntegration;
1208
- try {
1209
- hostIntegration = await checkHosts(fileURLToPath(new URL("..", import.meta.url)));
1210
- } catch (error) {
1211
- hostIntegration = { ok: false, error: error.message };
1212
- }
1213
- let sourceResolution = null;
1214
- let orphanScan = null;
1215
- const sourceHost = flags.host || process.env.AGENTSPINE_HOST;
1216
- if (["claude", "codex"].includes(sourceHost)) {
1217
- try {
1218
- const resolved = await resolveHostSourceCatalog({ host: sourceHost, cwd: flags.cwd || process.cwd() });
1219
- sourceResolution = resolved.diagnostics;
1220
- if (booleanFlag(flags["offline-memory-orphans"])) {
1221
- if (sourceHost !== "claude" || !resolved.memoryRoot) throw new Error("offline memory orphan scan requires a resolved Claude project-memory root");
1222
- orphanScan = await scanIndexedMemoryOrphans(resolved.memoryRoot);
1223
- }
1224
- }
1225
- catch (error) { sourceResolution = { status: "failed-closed", reason: error.message }; }
1226
- }
1227
- let preflight;
1228
- try { preflight = await preflightStatus(); }
1229
- catch (error) { preflight = { status: "failed-closed", error: error.message }; }
1230
- let learningOutcomes;
1231
- try {
1232
- const status = await learningOutcomeStatus({ root: positional[0] || process.cwd() });
1233
- const unboundAfterReceipts = status.records.reduce((sum, item) => sum + item.afterReceipts - item.boundAfterReceipts, 0);
1234
- const undeliveredAfterReceipts = status.records.reduce((sum, item) => sum + item.afterReceipts - item.deliveredAfterReceipts, 0);
1235
- const stalePendingApplications = status.records.reduce((sum, item) => sum + item.stalePendingApplications, 0);
1236
- const totalOutcomeReceipts = status.records.reduce((sum, item) => sum + item.beforeReceipts + item.afterReceipts, 0);
1237
- const plannedOutcomeReceipts = status.records.reduce((sum, item) => sum + item.plannedOutcomeReceipts, 0);
1238
- const coverageBoundReceipts = status.records.reduce((sum, item) => sum + item.coverageBoundReceipts, 0);
1239
- const legacyCoverageReceipts = status.records.reduce((sum, item) => sum + item.legacyCoverageReceipts, 0);
1240
- const provenanceBoundReceipts = status.records.reduce((sum, item) => sum + item.provenanceBoundReceipts, 0);
1241
- const legacyProvenanceReceipts = status.records.reduce((sum, item) => sum + item.legacyProvenanceReceipts, 0);
1242
- const measurementReceipts = status.records.reduce((sum, item) => sum + item.measurementReceipts, 0);
1243
- const measurementLineageReceipts = status.records.reduce((sum, item) => sum + item.measurementLineageReceipts, 0);
1244
- const candidateEvidenceLineageReceipts = status.candidateEvidenceLineageReceipts;
1245
- const consumedMeasurementReceipts = status.records.reduce((sum, item) => sum + item.consumedMeasurementReceipts, 0);
1246
- const staleUnconsumedMeasurements = status.records.reduce((sum, item) => sum + item.staleUnconsumedMeasurements, 0);
1247
- const lineageBoundReceipts = status.records.reduce((sum, item) => sum + item.lineageBoundReceipts, 0);
1248
- const pairedOutcomeReceipts = status.records.reduce((sum, item) => sum + item.pairedOutcomeReceipts, 0);
1249
- const pairedEvaluatorPairs = status.records.reduce((sum, item) => sum + item.pairedEvaluatorPairs, 0);
1250
- const evaluatorRootBoundReceipts = status.records.reduce((sum, item) => sum + item.evaluatorRootBoundReceipts, 0);
1251
- const independentEvaluatorRoots = status.records.reduce((sum, item) => sum + item.independentEvaluatorRoots, 0);
1252
- const evaluatorRegistryContracts = status.records.reduce((sum, item) => sum + item.evaluatorRegistryContracts, 0);
1253
- const inactiveEvaluatorRegistryContracts = status.records.reduce((sum, item) => sum + item.inactiveEvaluatorRegistryContracts, 0);
1254
- const currentValidatedLessons = status.records.filter((item) => item.validationLeaseStatus === "current-validated").length;
1255
- const staleValidatedLessons = status.records.filter((item) => item.validationLeaseStatus === "stale-validated").length;
1256
- const unprovenValidatedLessons = status.records.filter((item) => item.validationLeaseStatus === "unproven-validated").length;
1257
- const revokedValidatedLessons = status.records.filter((item) => item.validationLeaseStatus === "revoked-validated").length;
1258
- const renewedValidationLeases = status.records.filter((item) =>
1259
- ["agentspine.learning-validation/v2", "agentspine.learning-validation/v3",
1260
- "agentspine.learning-validation/v4", "agentspine.learning-validation/v5"].includes(item.validationLeaseSchema)).length;
1261
- const fixedCohortValidationLeases = status.records.filter((item) =>
1262
- ["agentspine.learning-validation/v3", "agentspine.learning-validation/v4",
1263
- "agentspine.learning-validation/v5"]
1264
- .includes(item.validationLeaseSchema)).length;
1265
- const admissionBoundValidationLeases = status.records.filter((item) =>
1266
- ["agentspine.learning-validation/v4", "agentspine.learning-validation/v5"]
1267
- .includes(item.validationLeaseSchema)).length;
1268
- const trialBoundValidationLeases = status.records.filter((item) =>
1269
- item.validationLeaseSchema === "agentspine.learning-validation/v5").length;
1270
- const activeRevalidations = status.records.filter((item) => item.revalidationStatus === "active").length;
1271
- const staleRevalidations = status.records.filter((item) => item.revalidationStatus === "stale").length;
1272
- const fixedCohortRevalidations = status.records.filter((item) =>
1273
- item.revalidationStatus === "active"
1274
- && ["first-completed-turns", "first-admitted-turns",
1275
- "first-admitted-trials"].includes(item.revalidationSelectionMode)).length;
1276
- const admissionBoundRevalidations = status.records.filter((item) =>
1277
- item.revalidationStatus === "active" && ["first-admitted-turns", "first-admitted-trials"]
1278
- .includes(item.revalidationSelectionMode)).length;
1279
- const trialBoundRevalidations = status.records.filter((item) =>
1280
- item.revalidationStatus === "active" && item.revalidationSelectionMode === "first-admitted-trials").length;
1281
- const requiredRevalidationDeliveries = status.records.reduce((sum, item) =>
1282
- sum + item.revalidationRequiredDeliveries, 0);
1283
- const completedRevalidationDeliveries = status.records.reduce((sum, item) =>
1284
- sum + item.revalidationCompletedDeliveries, 0);
1285
- const admittedRevalidationApplications = status.records.reduce((sum, item) =>
1286
- sum + item.revalidationAdmittedApplications, 0);
1287
- const initialTrialContracts = status.records.filter((item) => item.initialTrialMode === "first-admitted-trials").length;
1288
- const requiredInitialTrials = status.records.reduce((sum, item) => sum + item.initialTrialSlots, 0);
1289
- const admittedInitialApplications = status.records.reduce((sum, item) =>
1290
- sum + item.initialAdmittedApplications, 0);
1291
- const completedInitialDeliveries = status.records.reduce((sum, item) =>
1292
- sum + item.initialCompletedDeliveries, 0);
1293
- const incompleteInitialAdmissions = status.records.reduce((sum, item) =>
1294
- sum + item.incompleteInitialAdmissions, 0);
1295
- const targetBoundEvaluationContracts = status.records.reduce((sum, item) =>
1296
- sum + item.targetBoundEvaluationContracts, 0);
1297
- const targetBoundApplications = status.records.reduce((sum, item) =>
1298
- sum + item.targetBoundApplications, 0);
1299
- const deadlineBoundEvaluationContracts = status.records.reduce((sum, item) =>
1300
- sum + item.deadlineBoundEvaluationContracts, 0);
1301
- const stalenessBoundEvaluationContracts = status.records.reduce((sum, item) =>
1302
- sum + item.stalenessBoundEvaluationContracts, 0);
1303
- const promotionBoundEvaluationContracts = status.records.reduce((sum, item) =>
1304
- sum + item.promotionBoundEvaluationContracts, 0);
1305
- const candidateAdmissionEvaluationContracts = status.records.reduce((sum, item) =>
1306
- sum + item.candidateAdmissionEvaluationContracts, 0);
1307
- const evidenceSourceAttestedEvaluationContracts = status.records.reduce((sum, item) =>
1308
- sum + item.evidenceSourceAttestedEvaluationContracts, 0);
1309
- const candidateEvidenceLineageEvaluationContracts = status.records.reduce((sum, item) =>
1310
- sum + item.candidateEvidenceLineageEvaluationContracts, 0);
1311
- const candidateEvidenceCohortEvaluationContracts = status.records.reduce((sum, item) =>
1312
- sum + item.candidateEvidenceCohortEvaluationContracts, 0);
1313
- const blockingDefectBoundEvaluationContracts = status.records.reduce((sum, item) =>
1314
- sum + item.blockingDefectBoundEvaluationContracts, 0);
1315
- const evidenceSourceBoundEvaluationContracts = status.records.reduce((sum, item) =>
1316
- sum + item.evidenceSourceBoundEvaluationContracts, 0);
1317
- const blockingDefectOutcomeReceipts = status.records.reduce((sum, item) =>
1318
- sum + item.blockingDefectOutcomeReceipts, 0);
1319
- const deadlineBoundApplications = status.records.reduce((sum, item) =>
1320
- sum + item.deadlineBoundApplications, 0);
1321
- const trialRetryEvaluationContracts = status.records.reduce((sum, item) =>
1322
- sum + item.trialRetryEvaluationContracts, 0);
1323
- const comparableTrialRetryEvaluationContracts = status.records.reduce((sum, item) =>
1324
- sum + item.comparableTrialRetryEvaluationContracts, 0);
1325
- const boundedTrialRetryEvaluationContracts = status.records.reduce((sum, item) =>
1326
- sum + item.boundedTrialRetryEvaluationContracts, 0);
1327
- const trialRetryExhaustionReceipts = status.records.reduce((sum, item) =>
1328
- sum + item.trialRetryExhaustionReceipts, 0);
1329
- const trialFailureReceipts = status.records.reduce((sum, item) => sum + item.trialFailureReceipts, 0);
1330
- const trialFailureRevocationReceipts = status.records.reduce((sum, item) =>
1331
- sum + item.trialFailureRevocationReceipts, 0);
1332
- const evaluationRevocationReceipts = status.records.reduce((sum, item) => sum + item.evaluationRevocationReceipts, 0);
1333
- const evidenceSourceAttestationRevocationReceipts = status.records.reduce((sum, item) =>
1334
- sum + item.evidenceSourceAttestationRevocationReceipts, 0);
1335
- const validationRevocationReceipts = status.records.reduce((sum, item) => sum + item.validationRevocationReceipts, 0);
1336
- const evidenceRevocationReceipts = status.records.reduce((sum, item) => sum + item.evidenceRevocationReceipts, 0);
1337
- const measurementRevocationReceipts = status.records.reduce((sum, item) => sum + item.measurementRevocationReceipts, 0);
1338
- const applicationRevocationReceipts = status.records.reduce((sum, item) => sum + item.applicationRevocationReceipts, 0);
1339
- const deliveryRevocationReceipts = status.records.reduce((sum, item) => sum + item.deliveryRevocationReceipts, 0);
1340
- const outcomeRevocationReceipts = status.records.reduce((sum, item) => sum + item.outcomeRevocationReceipts, 0);
1341
- const deliveryTimeoutFailures = status.records.reduce((sum, item) => sum + item.deliveryTimeoutFailures, 0);
1342
- const outcomeTimeoutFailures = status.records.reduce((sum, item) => sum + item.outcomeTimeoutFailures, 0);
1343
- const pendingInitialOutcomes = status.records.reduce((sum, item) => sum + item.pendingInitialOutcomes, 0);
1344
- const staleInitialOutcomes = status.records.reduce((sum, item) => sum + item.staleInitialOutcomes, 0);
1345
- const unplannedOutcomeReceipts = totalOutcomeReceipts - plannedOutcomeReceipts;
1346
- learningOutcomes = {
1347
- status: status.records.some((item) => ["stale", "revoked", "revoked-evaluation",
1348
- "revoked-evidence-source-attestation", "revoked-validation", "revoked-evidence",
1349
- "revoked-measurement", "revoked-application", "revoked-delivery", "revoked-outcome",
1350
- "unproven", "failed-trial"].includes(item.canaryStatus))
1351
- || unboundAfterReceipts > 0 || undeliveredAfterReceipts > 0 || unplannedOutcomeReceipts > 0
1352
- || stalePendingApplications > 0 || staleUnconsumedMeasurements > 0
1353
- || inactiveEvaluatorRegistryContracts > 0 || staleRevalidations > 0
1354
- || staleInitialOutcomes > 0 || trialFailureRevocationReceipts > 0 ? "degraded" : "healthy",
1355
- candidates: status.records.length,
1356
- activeCanaries: status.records.filter((item) => item.canaryStatus === "active").length,
1357
- validatedCanaries: status.records.filter((item) => item.canaryStatus === "validated").length,
1358
- staleCanaries: status.records.filter((item) => item.canaryStatus === "stale").length,
1359
- awaitingApplication: status.records.filter((item) => item.canaryStatus === "active" && item.applicationReceipts === 0).length,
1360
- applicationReceipts: status.records.reduce((sum, item) => sum + item.applicationReceipts, 0),
1361
- deliveryReceipts: status.records.reduce((sum, item) => sum + item.deliveryReceipts, 0),
1362
- pendingApplications: status.records.reduce((sum, item) => sum + item.pendingApplications, 0),
1363
- stalePendingApplications,
1364
- evaluationContracts: status.records.reduce((sum, item) => sum + item.evaluationContracts, 0),
1365
- targetBoundEvaluationContracts,
1366
- targetBoundApplications,
1367
- deadlineBoundEvaluationContracts,
1368
- stalenessBoundEvaluationContracts,
1369
- promotionBoundEvaluationContracts,
1370
- candidateAdmissionEvaluationContracts,
1371
- evidenceSourceAttestedEvaluationContracts,
1372
- candidateEvidenceLineageEvaluationContracts,
1373
- candidateEvidenceLineageReceipts,
1374
- candidateEvidenceCohortEvaluationContracts,
1375
- blockingDefectBoundEvaluationContracts,
1376
- evidenceSourceBoundEvaluationContracts,
1377
- blockingDefectOutcomeReceipts,
1378
- deadlineBoundApplications,
1379
- trialRetryEvaluationContracts,
1380
- comparableTrialRetryEvaluationContracts,
1381
- boundedTrialRetryEvaluationContracts,
1382
- trialRetryExhaustionReceipts,
1383
- trialFailureReceipts,
1384
- trialFailureRevocationReceipts,
1385
- evaluationRevocationReceipts,
1386
- evidenceSourceAttestationRevocationReceipts,
1387
- validationRevocationReceipts,
1388
- evidenceRevocationReceipts,
1389
- measurementRevocationReceipts,
1390
- applicationRevocationReceipts,
1391
- deliveryRevocationReceipts,
1392
- outcomeRevocationReceipts,
1393
- deliveryTimeoutFailures,
1394
- outcomeTimeoutFailures,
1395
- pendingInitialOutcomes,
1396
- staleInitialOutcomes,
1397
- plannedOutcomeReceipts,
1398
- coverageBoundReceipts,
1399
- legacyCoverageReceipts,
1400
- provenanceBoundReceipts,
1401
- legacyProvenanceReceipts,
1402
- measurementReceipts,
1403
- measurementLineageReceipts,
1404
- consumedMeasurementReceipts,
1405
- staleUnconsumedMeasurements,
1406
- lineageBoundReceipts,
1407
- pairedOutcomeReceipts,
1408
- pairedEvaluatorPairs,
1409
- evaluatorRootBoundReceipts,
1410
- independentEvaluatorRoots,
1411
- activeEvaluatorRoots: status.evaluatorRegistry.active,
1412
- revokedEvaluatorRoots: status.evaluatorRegistry.revoked,
1413
- evaluatorRegistryBindings: status.evaluatorRegistry.bindings,
1414
- validationLeases: status.evaluatorRegistry.validationLeases,
1415
- renewedValidationLeases,
1416
- fixedCohortValidationLeases,
1417
- admissionBoundValidationLeases,
1418
- trialBoundValidationLeases,
1419
- initialTrialContracts,
1420
- requiredInitialTrials,
1421
- admittedInitialApplications,
1422
- completedInitialDeliveries,
1423
- incompleteInitialAdmissions,
1424
- activeRevalidations,
1425
- staleRevalidations,
1426
- fixedCohortRevalidations,
1427
- admissionBoundRevalidations,
1428
- trialBoundRevalidations,
1429
- requiredRevalidationDeliveries,
1430
- admittedRevalidationApplications,
1431
- completedRevalidationDeliveries,
1432
- currentValidatedLessons,
1433
- staleValidatedLessons,
1434
- unprovenValidatedLessons,
1435
- revokedValidatedLessons,
1436
- evaluatorRegistryContracts,
1437
- inactiveEvaluatorRegistryContracts,
1438
- unplannedOutcomeReceipts,
1439
- boundAfterReceipts: status.records.reduce((sum, item) => sum + item.boundAfterReceipts, 0),
1440
- unboundAfterReceipts,
1441
- deliveredAfterReceipts: status.records.reduce((sum, item) => sum + item.deliveredAfterReceipts, 0),
1442
- undeliveredAfterReceipts,
1443
- contradictions: status.records.filter((item) => item.conflictsWith.length > 0).length,
1444
- authority: "context-only"
1445
- };
1446
- } catch (error) { learningOutcomes = { status: "failed-closed", error: error.message, authority: "context-only" }; }
1447
- const result = {
1448
- ok: Number(process.versions.node.split(".")[0]) >= 20 && hostIntegration.ok
1449
- && (!sourceResolution || sourceResolution.status === "loaded")
1450
- && learningOutcomes.status !== "failed-closed",
1451
- version: VERSION,
1452
- node: process.versions.node,
1453
- platform: process.platform,
1454
- preservationMode: "read-only-source-overlay",
1455
- stateDirectory: process.env.AGENTSPINE_STATE_DIR || "platform-default",
1456
- hostIntegration,
1457
- sourceResolution,
1458
- orphanScan,
1459
- preflight,
1460
- learningOutcomes
1461
- };
1462
- output(result, json);
1463
- if (!result.ok) process.exitCode = 1;
1464
- return;
1465
- }
1466
-
1467
- if (command === "audit") {
1468
- const result = await runAudit(positional[0] || process.cwd(), { host: flags.host || process.env.AGENTSPINE_HOST || null });
1469
- output(result, json);
1470
- if (!result.ok) process.exitCode = 1;
1471
- return;
1472
- }
1473
-
1474
- if (command === "mcp") {
1475
- const { startMcpServer } = await import("./mcp.js");
1476
- startMcpServer();
1477
- return;
1478
- }
1479
-
166
+ if (["help", "--help", "-h"].includes(command)) return output(help());
167
+ if (["version", "--version", "-v"].includes(command)) return output(VERSION);
168
+ const route = ROUTES.find(([commands]) => commands.has(command));
169
+ if (route) return route[1]({ command, flags, positional, json });
1480
170
  throw new Error(`Unknown command: ${command}`);
1481
171
  }
1482
172