blun-king-cli 9.1.587 → 9.1.588

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 (436) hide show
  1. package/CHANGELOG.md +11 -185
  2. package/LIESMICH.txt +51 -13
  3. package/README.md +44 -47
  4. package/agent-spine-plugin/.codex-plugin/plugin.json +16 -4
  5. package/agent-spine-plugin/CHANGELOG.md +37 -5
  6. package/agent-spine-plugin/README.md +3 -3
  7. package/agent-spine-plugin/blun.plugin.json +45 -10
  8. package/agent-spine-plugin/docs/artifact-evaluation.md +93 -0
  9. package/agent-spine-plugin/docs/host-integration.md +42 -27
  10. package/agent-spine-plugin/docs/preflight-recall.md +4 -2
  11. package/agent-spine-plugin/docs/session-timeline.md +97 -236
  12. package/agent-spine-plugin/docs/world-model.md +25 -0
  13. package/agent-spine-plugin/hooks/codex.json +1 -1
  14. package/agent-spine-plugin/hooks/hooks.json +1 -1
  15. package/agent-spine-plugin/package.json +1 -3
  16. package/agent-spine-plugin/scripts/check-hosts.js +3 -3
  17. package/agent-spine-plugin/scripts/release-check.js +10 -5
  18. package/agent-spine-plugin/scripts/run-checks.js +4 -1
  19. package/agent-spine-plugin/scripts/run-tests-hermetic.js +32 -6
  20. package/agent-spine-plugin/src/cli-learning.js +15 -0
  21. package/agent-spine-plugin/src/cli.js +2 -0
  22. package/agent-spine-plugin/src/hook.js +32 -32
  23. package/agent-spine-plugin/src/lib/action-lesson-recall.js +73 -8
  24. package/agent-spine-plugin/src/lib/briefing.js +146 -36
  25. package/agent-spine-plugin/src/lib/channel-continuity.js +19 -0
  26. package/agent-spine-plugin/src/lib/delivery-agent-usage.js +14 -7
  27. package/agent-spine-plugin/src/lib/gateway-group-response.js +128 -0
  28. package/agent-spine-plugin/src/lib/gateway-runs.js +24 -15
  29. package/agent-spine-plugin/src/lib/hook-briefing-use.js +13 -3
  30. package/agent-spine-plugin/src/lib/hook-context.js +16 -3
  31. package/agent-spine-plugin/src/lib/hook-output.js +129 -5
  32. package/agent-spine-plugin/src/lib/hook-timeline.js +5 -3
  33. package/agent-spine-plugin/src/lib/indexed-memory.js +2 -2
  34. package/agent-spine-plugin/src/lib/learning-artifact-evaluator.js +114 -0
  35. package/agent-spine-plugin/src/lib/learning-context.js +11 -4
  36. package/agent-spine-plugin/src/lib/learning-measurements.js +2 -2
  37. package/agent-spine-plugin/src/lib/mcp-runtime.js +89 -3
  38. package/agent-spine-plugin/src/lib/mcp-source-context.js +12 -2
  39. package/agent-spine-plugin/src/lib/mcp-timeline-tools.js +91 -8
  40. package/agent-spine-plugin/src/lib/mcp-world-tools.js +2 -2
  41. package/agent-spine-plugin/src/lib/owned-file-lock.js +20 -1
  42. package/agent-spine-plugin/src/lib/persona-runtime.js +2 -2
  43. package/agent-spine-plugin/src/lib/preflight-delivery-id.js +27 -0
  44. package/agent-spine-plugin/src/lib/preflight.js +4 -4
  45. package/agent-spine-plugin/src/lib/session-timeline-codex.js +15 -0
  46. package/agent-spine-plugin/src/lib/session-timeline-contract.js +12 -4
  47. package/agent-spine-plugin/src/lib/session-timeline-event-extract.js +36 -7
  48. package/agent-spine-plugin/src/lib/session-timeline-host-origin.js +13 -10
  49. package/agent-spine-plugin/src/lib/session-timeline-invocation.js +1 -1
  50. package/agent-spine-plugin/src/lib/session-timeline-king.js +14 -0
  51. package/agent-spine-plugin/src/lib/session-timeline-prior.js +18 -12
  52. package/agent-spine-plugin/src/lib/session-timeline-provider.js +5 -0
  53. package/agent-spine-plugin/src/lib/session-timeline-query.js +2 -0
  54. package/agent-spine-plugin/src/lib/session-timeline-results.js +35 -10
  55. package/agent-spine-plugin/src/lib/session-timeline-source-open.js +30 -0
  56. package/agent-spine-plugin/src/lib/session-timeline.js +122 -75
  57. package/agent-spine-plugin/src/lib/source-roots.js +3 -2
  58. package/agent-spine-plugin/src/lib/task-knowledge-context.js +22 -1
  59. package/agent-spine-plugin/src/lib/timeline-continuation-update.js +100 -0
  60. package/agent-spine-plugin/src/lib/timeline-tool-guard.js +30 -7
  61. package/agent-spine-plugin/src/lib/timeline-user-feedback.js +217 -0
  62. package/agent-spine-plugin/src/lib/timeline-world-capture.js +233 -0
  63. package/agent-spine-plugin/src/lib/world-knowledge.js +59 -2
  64. package/agent-spine-plugin/src/lib/world-model.js +64 -9
  65. package/agent-spine-plugin/src/worker.js +13 -1
  66. package/bin/blun.js +43 -28
  67. package/bin/core-bootstrap.js +5 -4
  68. package/bin/king.js +43 -28
  69. package/bin/launcher-mode.js +1 -10
  70. package/bin/launcher-runtime.js +128 -295
  71. package/bin/managed-node.js +0 -0
  72. package/bin/managed-plugin-selection.cjs +0 -1
  73. package/bin/native-module-repair.js +0 -0
  74. package/bin/node-runtime.js +0 -0
  75. package/bin/node-version.js +0 -0
  76. package/bin/plugin-bootstrap.js +56 -120
  77. package/bin/private-paths.js +11 -34
  78. package/bin/standard-tools-bootstrap.js +34 -114
  79. package/bin/turn-thinking-policy.cjs +3 -11
  80. package/bin/update-copy.js +200 -0
  81. package/bin/update-lease.js +0 -0
  82. package/bin/update-notice.js +136 -289
  83. package/bin/verify-agent-behavior.cjs +122 -0
  84. package/bin/verify-agent-components.cjs +104 -0
  85. package/bin/verify-bundled-agent-sources.cjs +57 -0
  86. package/blun.mjs +143076 -135288
  87. package/bundled-agent-sources.json +701 -0
  88. package/package.json +12 -15
  89. package/standard-skills/translate-native/README.md +1293 -0
  90. package/standard-skills/translate-native/SKILL.md +172 -22
  91. package/standard-skills/translate-native/VERSION +1 -1
  92. package/standard-skills/translate-native/agents/openai.yaml +18 -0
  93. package/standard-skills/translate-native/assets/icon.svg +8 -0
  94. package/standard-skills/translate-native/docs/BLUN_CODE_INTEGRATION.md +76 -0
  95. package/standard-skills/translate-native/docs/PREMORTEM.md +489 -0
  96. package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION.md +2035 -0
  97. package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION_API.md +1302 -0
  98. package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION_EVIDENCE_HTTP.md +136 -0
  99. package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION_HEALTH_HTTP.md +130 -0
  100. package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION_HTTP_PROVIDER.md +175 -0
  101. package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION_RECEIPT_VERIFIER_HTTP.md +86 -0
  102. package/standard-skills/translate-native/integrations/AGENT_RULES.md +32 -0
  103. package/standard-skills/translate-native/integrations/adapters/blun-code-language-guard.js +514 -0
  104. package/standard-skills/translate-native/integrations/adapters/node-language-guard.js +230 -0
  105. package/standard-skills/translate-native/integrations/audit_log.py +327 -0
  106. package/standard-skills/translate-native/integrations/claude_language_hook.js +1536 -0
  107. package/standard-skills/translate-native/integrations/commercial_localization_profile.py +42 -0
  108. package/standard-skills/translate-native/integrations/delivery-policy.example.json +28 -0
  109. package/standard-skills/translate-native/integrations/enforced_delivery.py +543 -0
  110. package/standard-skills/translate-native/integrations/guard_service.py +435 -0
  111. package/standard-skills/translate-native/integrations/language_gateway.py +67 -0
  112. package/standard-skills/translate-native/integrations/mcp_auth_headers.py +198 -0
  113. package/standard-skills/translate-native/integrations/mcp_http_gateway.py +429 -0
  114. package/standard-skills/translate-native/integrations/non_language_html_entities.js +1485 -0
  115. package/standard-skills/translate-native/integrations/pre_output_guard.py +65 -0
  116. package/standard-skills/translate-native/integrations/task_router.py +101 -0
  117. package/standard-skills/translate-native/integrations/website_localization.py +401 -0
  118. package/standard-skills/translate-native/integrations/website_localization_api.py +581 -0
  119. package/standard-skills/translate-native/integrations/website_localization_benchmark.py +1885 -0
  120. package/standard-skills/translate-native/integrations/website_localization_benchmark_campaign.py +1772 -0
  121. package/standard-skills/translate-native/integrations/website_localization_benchmark_candidate.py +506 -0
  122. package/standard-skills/translate-native/integrations/website_localization_benchmark_http.py +400 -0
  123. package/standard-skills/translate-native/integrations/website_localization_benchmark_review_store.py +781 -0
  124. package/standard-skills/translate-native/integrations/website_localization_benchmark_reviewer_http.py +500 -0
  125. package/standard-skills/translate-native/integrations/website_localization_benchmark_runtime.py +1107 -0
  126. package/standard-skills/translate-native/integrations/website_localization_benchmark_suite.py +463 -0
  127. package/standard-skills/translate-native/integrations/website_localization_cms.py +2835 -0
  128. package/standard-skills/translate-native/integrations/website_localization_cms_client.py +875 -0
  129. package/standard-skills/translate-native/integrations/website_localization_cms_dispatch.py +805 -0
  130. package/standard-skills/translate-native/integrations/website_localization_cms_http.py +588 -0
  131. package/standard-skills/translate-native/integrations/website_localization_cms_lifecycle_monitor.py +991 -0
  132. package/standard-skills/translate-native/integrations/website_localization_cms_receiver.py +1441 -0
  133. package/standard-skills/translate-native/integrations/website_localization_cms_receiver_runtime.py +414 -0
  134. package/standard-skills/translate-native/integrations/website_localization_cms_receiver_store.py +1073 -0
  135. package/standard-skills/translate-native/integrations/website_localization_cms_removal_dispatch.py +865 -0
  136. package/standard-skills/translate-native/integrations/website_localization_cms_source_client.py +583 -0
  137. package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery.py +964 -0
  138. package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery_runtime.py +665 -0
  139. package/standard-skills/translate-native/integrations/website_localization_cms_source_http.py +1153 -0
  140. package/standard-skills/translate-native/integrations/website_localization_cms_source_runtime.py +675 -0
  141. package/standard-skills/translate-native/integrations/website_localization_cms_source_service.py +1125 -0
  142. package/standard-skills/translate-native/integrations/website_localization_cms_terminal_notification.py +674 -0
  143. package/standard-skills/translate-native/integrations/website_localization_cms_terminal_notification_http.py +444 -0
  144. package/standard-skills/translate-native/integrations/website_localization_cms_terminal_notification_receiver.py +1469 -0
  145. package/standard-skills/translate-native/integrations/website_localization_cms_terminal_notification_receiver_runtime.py +1142 -0
  146. package/standard-skills/translate-native/integrations/website_localization_cms_terminal_processing_monitor.py +634 -0
  147. package/standard-skills/translate-native/integrations/website_localization_cms_terminal_receiver_client.py +804 -0
  148. package/standard-skills/translate-native/integrations/website_localization_deepl_baseline.py +922 -0
  149. package/standard-skills/translate-native/integrations/website_localization_evidence_http.py +482 -0
  150. package/standard-skills/translate-native/integrations/website_localization_health.py +1541 -0
  151. package/standard-skills/translate-native/integrations/website_localization_health_http.py +372 -0
  152. package/standard-skills/translate-native/integrations/website_localization_http_provider.py +297 -0
  153. package/standard-skills/translate-native/integrations/website_localization_native_reference_http.py +479 -0
  154. package/standard-skills/translate-native/integrations/website_localization_native_reference_intake.py +363 -0
  155. package/standard-skills/translate-native/integrations/website_localization_native_reference_queue.py +1449 -0
  156. package/standard-skills/translate-native/integrations/website_localization_native_reference_store.py +420 -0
  157. package/standard-skills/translate-native/integrations/website_localization_quality_profiles.py +235 -0
  158. package/standard-skills/translate-native/integrations/website_localization_queue.py +671 -0
  159. package/standard-skills/translate-native/integrations/website_localization_receipt_verifier_http.py +516 -0
  160. package/standard-skills/translate-native/integrations/website_localization_release.py +928 -0
  161. package/standard-skills/translate-native/integrations/website_localization_release_coordinator.py +1008 -0
  162. package/standard-skills/translate-native/integrations/website_localization_runner.py +276 -0
  163. package/standard-skills/translate-native/integrations/website_localization_runtime.py +862 -0
  164. package/standard-skills/translate-native/integrations/website_localization_service.py +350 -0
  165. package/standard-skills/translate-native/integrations/website_localization_supervisor.py +511 -0
  166. package/standard-skills/translate-native/integrations/website_localization_worker.py +663 -0
  167. package/standard-skills/translate-native/provenance.json +3 -4
  168. package/standard-skills/translate-native/references/commercial-localization.md +177 -0
  169. package/standard-skills/translate-native/scripts/blun_language_guard.py +7 -1
  170. package/standard-skills/translate-native/scripts/check_commercial_review.py +80 -0
  171. package/standard-skills/translate-native/scripts/commercial_localization_profile.py +333 -0
  172. package/standard-tools/language-guard/LICENSE +21 -0
  173. package/standard-tools/language-guard/VERSION +1 -0
  174. package/standard-tools/language-guard/blun_language_guard.py +7 -1
  175. package/standard-tools/language-guard/check_commercial_review.py +80 -0
  176. package/standard-tools/language-guard/commercial_localization_profile.py +333 -0
  177. package/standard-tools/language-guard/language_gateway.py +62 -0
  178. package/standard-tools/language-guard/pre_output_guard.py +64 -0
  179. package/standard-tools/language-guard/provenance.json +4 -11
  180. package/standard-tools/manifest.json +34 -11
  181. package/telegram-plugin/commands/access.md +2 -10
  182. package/telegram-plugin/dist/bridge.mjs +64041 -687
  183. package/telegram-plugin/dist/mcp-server.mjs +72810 -9027
  184. package/telegram-plugin/dist/noise.mjs +28 -63511
  185. package/agent-spine-plugin/CONTRIBUTING.md +0 -52
  186. package/agent-spine-plugin/SECURITY.md +0 -47
  187. package/agent-spine-plugin/docs/assignment-continuation.md +0 -48
  188. package/agent-spine-plugin/docs/releasing.md +0 -85
  189. package/agent-spine-plugin/docs/structured-completion.md +0 -67
  190. package/bin/abort-listener-policy.cjs +0 -43
  191. package/bin/active-steer-priority-policy.cjs +0 -24
  192. package/bin/agent-api-http-adapter.mjs +0 -446
  193. package/bin/agent-api-private-http-server.mjs +0 -288
  194. package/bin/agent-api-runtime.mjs +0 -252
  195. package/bin/agent-api-service-environment.mjs +0 -236
  196. package/bin/agent-api-service-host.mjs +0 -209
  197. package/bin/agent-api-service-process.mjs +0 -171
  198. package/bin/agent-api-session-registry.mjs +0 -428
  199. package/bin/agent-api-tool-broker.cjs +0 -248
  200. package/bin/agent-api-turn-controller.mjs +0 -461
  201. package/bin/agent-api-usage-journal.cjs +0 -259
  202. package/bin/agent-resume-snapshot.cjs +0 -241
  203. package/bin/agentspine-king-goal-inbox.mjs +0 -111
  204. package/bin/agentspine-king-goal-intake.mjs +0 -106
  205. package/bin/approval-rejection-stop.cjs +0 -15
  206. package/bin/assistant-message-offload-policy.cjs +0 -284
  207. package/bin/baseline-skill-performance-policy.cjs +0 -39
  208. package/bin/bash-search-scope-policy.cjs +0 -49
  209. package/bin/codebase-search-runtime.cjs +0 -23
  210. package/bin/cognitive-action-checkpoint.cjs +0 -1104
  211. package/bin/cognitive-attention-delivery.cjs +0 -76
  212. package/bin/cognitive-attention-policy.cjs +0 -143
  213. package/bin/cognitive-attention-runtime.cjs +0 -91
  214. package/bin/cognitive-context-projection.cjs +0 -73
  215. package/bin/cognitive-cross-portal-acceptance.cjs +0 -443
  216. package/bin/cognitive-effective-view.cjs +0 -77
  217. package/bin/cognitive-focus-projection.cjs +0 -206
  218. package/bin/cognitive-focus-scope.cjs +0 -37
  219. package/bin/cognitive-goal-autostart-policy.cjs +0 -72
  220. package/bin/cognitive-goal-time-trigger-controller.cjs +0 -146
  221. package/bin/cognitive-memory-adapter.cjs +0 -282
  222. package/bin/cognitive-memory-command.cjs +0 -293
  223. package/bin/cognitive-memory-provider.cjs +0 -92
  224. package/bin/cognitive-salience-policy.cjs +0 -159
  225. package/bin/cognitive-state-store.cjs +0 -508
  226. package/bin/cognitive-turn-lifecycle.cjs +0 -624
  227. package/bin/cognitive-work-focus.cjs +0 -180
  228. package/bin/compaction-history-archive.cjs +0 -166
  229. package/bin/compaction-history-startup.cjs +0 -50
  230. package/bin/compaction-model-policy.cjs +0 -31
  231. package/bin/compaction-stage-policy.cjs +0 -21
  232. package/bin/compaction-transaction-policy.cjs +0 -122
  233. package/bin/config-write-dedup-policy.cjs +0 -27
  234. package/bin/context-budget-ledger.cjs +0 -31
  235. package/bin/context-doctor-policy.cjs +0 -70
  236. package/bin/context-insight-policy.cjs +0 -36
  237. package/bin/context-performance-policy.cjs +0 -19
  238. package/bin/context-pressure-policy.cjs +0 -20
  239. package/bin/cron-run-output.cjs +0 -45
  240. package/bin/cron-run-store.cjs +0 -145
  241. package/bin/curiosity-scout-policy.cjs +0 -49
  242. package/bin/default-model-output-budget-policy.cjs +0 -28
  243. package/bin/durable-task-resume-policy.cjs +0 -130
  244. package/bin/durable-task-resume-runtime.cjs +0 -117
  245. package/bin/durable-task-resume-store.cjs +0 -88
  246. package/bin/editable-tool-approval-policy.cjs +0 -540
  247. package/bin/editable-tool-approval-runtime.cjs +0 -99
  248. package/bin/effective-system-prompt-cache-policy.cjs +0 -33
  249. package/bin/error-memory-performance-policy.cjs +0 -113
  250. package/bin/file-observation-policy.cjs +0 -133
  251. package/bin/foreground-output-capture-policy.cjs +0 -41
  252. package/bin/generated-source-health.cjs +0 -142
  253. package/bin/glob-pattern-policy.cjs +0 -13
  254. package/bin/goal-completion-evidence-policy.cjs +0 -120
  255. package/bin/grep-output-limit-policy.cjs +0 -39
  256. package/bin/historical-media-projection-policy.cjs +0 -48
  257. package/bin/history-offload-pressure-policy.cjs +0 -33
  258. package/bin/html-to-research-markdown.cjs +0 -147
  259. package/bin/identity-context-policy.cjs +0 -764
  260. package/bin/identity-journal-policy.cjs +0 -107
  261. package/bin/input-draft-persistence.cjs +0 -77
  262. package/bin/king-tui-function-contract.json +0 -33
  263. package/bin/launcher-restart-policy.cjs +0 -150
  264. package/bin/live-response-repetition-guard.cjs +0 -196
  265. package/bin/llm-config-log-dedup-policy.cjs +0 -76
  266. package/bin/loop-event-record-policy.cjs +0 -174
  267. package/bin/managed-context-startup-policy.cjs +0 -27
  268. package/bin/media-activity-layout-policy.cjs +0 -34
  269. package/bin/media-auto-retrieval-policy.cjs +0 -90
  270. package/bin/media-result-policy.cjs +0 -59
  271. package/bin/micro-compaction-policy.cjs +0 -145
  272. package/bin/mistake-relevance-policy.cjs +0 -319
  273. package/bin/model-retry-progress-policy.cjs +0 -46
  274. package/bin/native-large-file-io.cjs +0 -42
  275. package/bin/native-runtime-cache.cjs +0 -76
  276. package/bin/natural-presence-policy.cjs +0 -28
  277. package/bin/noninteractive-shell-env-policy.cjs +0 -19
  278. package/bin/observer-hooks.cjs +0 -14
  279. package/bin/outbound-claim-provenance.cjs +0 -150
  280. package/bin/oversized-context-offload-policy.cjs +0 -86
  281. package/bin/pending-media-policy.cjs +0 -182
  282. package/bin/pending-token-estimate-policy.cjs +0 -41
  283. package/bin/personal-memory-consent-policy.cjs +0 -72
  284. package/bin/personal-memory-performance-policy.cjs +0 -12
  285. package/bin/personality-choice-policy.cjs +0 -101
  286. package/bin/personality-memory-adapter.cjs +0 -379
  287. package/bin/personality-mode.cjs +0 -46
  288. package/bin/personality-setup-policy.cjs +0 -197
  289. package/bin/proactive-compaction-policy.cjs +0 -25
  290. package/bin/profile-identity-resolution.cjs +0 -136
  291. package/bin/profile-runtime.cjs +0 -318
  292. package/bin/profile-tool-exclusion-policy.cjs +0 -37
  293. package/bin/programmatic-context-isolation.cjs +0 -25
  294. package/bin/programmatic-tool-runtime.mjs +0 -627
  295. package/bin/provider-idle-timeout-policy.cjs +0 -14
  296. package/bin/provider-model-refresh-deadline.cjs +0 -53
  297. package/bin/provider-model-refresh-policy.cjs +0 -107
  298. package/bin/rate-limit-recovery-policy.cjs +0 -47
  299. package/bin/read-batch-policy.cjs +0 -32
  300. package/bin/read-continuation-policy.cjs +0 -59
  301. package/bin/recurring-cron-history-policy.cjs +0 -124
  302. package/bin/relationship-continuity-policy.cjs +0 -143
  303. package/bin/relationship-curiosity-policy.cjs +0 -107
  304. package/bin/relationship-learning-policy.cjs +0 -168
  305. package/bin/release-artifact-freeze-policy.cjs +0 -30
  306. package/bin/reload-plugin-bootstrap.cjs +0 -18
  307. package/bin/reload-queue-policy.cjs +0 -38
  308. package/bin/repeated-assistant-response-policy.cjs +0 -232
  309. package/bin/repeated-injection-projection.cjs +0 -107
  310. package/bin/repeated-user-message-projection.cjs +0 -8
  311. package/bin/research-page-result.cjs +0 -74
  312. package/bin/retry-checkpoint-policy.cjs +0 -13
  313. package/bin/runtime-exit-ledger.cjs +0 -144
  314. package/bin/scoped-cron-run-policy.cjs +0 -358
  315. package/bin/session-checkpoint-policy.cjs +0 -25
  316. package/bin/session-compaction-policy.cjs +0 -84
  317. package/bin/session-replay-policy.cjs +0 -20
  318. package/bin/session-replay-window-policy.cjs +0 -40
  319. package/bin/session-resume-checkpoint.cjs +0 -254
  320. package/bin/session-scrollback-archive.cjs +0 -229
  321. package/bin/skill-activation-performance-policy.cjs +0 -69
  322. package/bin/skill-listing-performance-policy.cjs +0 -92
  323. package/bin/soul-organization-policy.cjs +0 -78
  324. package/bin/soul-preservation-policy.cjs +0 -20
  325. package/bin/startup-preferences.cjs +0 -131
  326. package/bin/streaming-flush-performance-policy.cjs +0 -28
  327. package/bin/structured-agent-swarm-output.cjs +0 -325
  328. package/bin/structured-subagent-output.cjs +0 -252
  329. package/bin/subagent-context-fork-policy.cjs +0 -155
  330. package/bin/subagent-max-tokens-handoff-policy.cjs +0 -69
  331. package/bin/subagent-parent-responsiveness.cjs +0 -19
  332. package/bin/subagent-skill-policy.cjs +0 -206
  333. package/bin/subagent-timeout-policy.cjs +0 -182
  334. package/bin/subagent-tool-policy.cjs +0 -60
  335. package/bin/subagent-usage-rollup-policy.cjs +0 -29
  336. package/bin/system-prompt-context-policy.cjs +0 -124
  337. package/bin/system-prompt-token-cache-policy.cjs +0 -60
  338. package/bin/telegram-addressed-focus.cjs +0 -55
  339. package/bin/telegram-addressed-priority.cjs +0 -12
  340. package/bin/telegram-approval-relay.cjs +0 -290
  341. package/bin/telegram-bot-priority.cjs +0 -17
  342. package/bin/telegram-console-status-policy.cjs +0 -174
  343. package/bin/telegram-context-projection-policy.cjs +0 -141
  344. package/bin/telegram-delivery-lifecycle.cjs +0 -125
  345. package/bin/telegram-direct-focus-policy.cjs +0 -273
  346. package/bin/telegram-mcp-compatibility.cjs +0 -49
  347. package/bin/telegram-media-delivery-policy.cjs +0 -42
  348. package/bin/telegram-private-conversation-policy.cjs +0 -185
  349. package/bin/telegram-queue-handoff-policy.cjs +0 -73
  350. package/bin/telegram-remote-status-policy.cjs +0 -120
  351. package/bin/telegram-session-queue-runtime.mjs +0 -306
  352. package/bin/telegram-text-chunk-policy.cjs +0 -63
  353. package/bin/telegram-truncated-reply-policy.cjs +0 -37
  354. package/bin/telegram-urgent-policy.cjs +0 -45
  355. package/bin/telemetry-spool-policy.cjs +0 -57
  356. package/bin/thinking-activity-status-policy.cjs +0 -132
  357. package/bin/thinking-only-guard.cjs +0 -80
  358. package/bin/todo-list-turn-policy.cjs +0 -131
  359. package/bin/tool-call-loop-policy.cjs +0 -51
  360. package/bin/tool-file-persistence.cjs +0 -141
  361. package/bin/tool-result-offload-policy.cjs +0 -359
  362. package/bin/tool-result-offload-telemetry.cjs +0 -12
  363. package/bin/tool-schema-token-cache-policy.cjs +0 -41
  364. package/bin/tool-stream-preview-policy.cjs +0 -9
  365. package/bin/tui-functional-contract.cjs +0 -55
  366. package/bin/turn-tool-performance-policy.cjs +0 -486
  367. package/bin/usage-cache-efficiency-policy.cjs +0 -26
  368. package/bin/user-home-path-policy.cjs +0 -13
  369. package/bin/user-message-offload-policy.cjs +0 -103
  370. package/bin/user-prompt-hook-origin-policy.cjs +0 -34
  371. package/bin/user-tool-record-policy.cjs +0 -7
  372. package/bin/validated-learning-insight-policy.cjs +0 -58
  373. package/bin/validated-learning-outcome-trace.cjs +0 -107
  374. package/bin/validated-learning-performance-policy.cjs +0 -53
  375. package/bin/validated-learning-signal.cjs +0 -463
  376. package/bin/windows-bash-dialect-policy.cjs +0 -25
  377. package/bin/windows-node-crash-dump.cjs +0 -110
  378. package/bin/write-continuation-policy.cjs +0 -69
  379. package/codebase-index/README.md +0 -82
  380. package/codebase-index/codebase_index.py +0 -470
  381. package/standard-skills/agent-browser/SKILL.md +0 -19
  382. package/standard-skills/agent-browser/references/runtime.md +0 -8
  383. package/standard-skills/blun-session-inspector/SKILL.md +0 -41
  384. package/standard-skills/blun-session-inspector/scripts/inspect-session.cjs +0 -437
  385. package/standard-skills/design-taste-frontend/SKILL.md +0 -1206
  386. package/standard-skills/full-output-enforcement/SKILL.md +0 -49
  387. package/standard-skills/high-end-visual-design/SKILL.md +0 -98
  388. package/standard-skills/image-to-code/SKILL.md +0 -1228
  389. package/standard-skills/industrial-brutalist-ui/SKILL.md +0 -92
  390. package/standard-skills/minimalist-ui/SKILL.md +0 -85
  391. package/standard-skills/motion-design-taste/SKILL.md +0 -74
  392. package/standard-skills/playwright-testing/SKILL.md +0 -19
  393. package/standard-skills/playwright-testing/references/runtime.md +0 -7
  394. package/standard-skills/premortem/SKILL.md +0 -148
  395. package/standard-skills/redesign-existing-projects/SKILL.md +0 -178
  396. package/standard-skills/research-evidence/SKILL.md +0 -39
  397. package/standard-skills/research-evidence/references/evidence-format.md +0 -104
  398. package/standard-skills/research-evidence/scripts/evidence-collection.cjs +0 -260
  399. package/standard-skills/research-evidence/scripts/score-report.cjs +0 -130
  400. package/standard-skills/screenshot-lesen/SKILL.md +0 -52
  401. package/standard-skills/stitch-design-taste/DESIGN.md +0 -121
  402. package/standard-skills/stitch-design-taste/SKILL.md +0 -184
  403. package/standard-skills/telegram-channel/SKILL.md +0 -18
  404. package/standard-skills/telegram-channel/references/runtime.md +0 -7
  405. package/standard-skills/venture-flywheel/SKILL.md +0 -32
  406. package/standard-skills/venture-flywheel/identity/project-identity.cjs +0 -146
  407. package/standard-skills/venture-flywheel/policy/capability-engine.cjs +0 -114
  408. package/standard-skills/venture-flywheel/policy/repository-trust.cjs +0 -229
  409. package/standard-skills/venture-flywheel/references/BEISPIELE-phase0.md +0 -146
  410. package/standard-skills/venture-flywheel/references/CAPABILITY-MAP.md +0 -34
  411. package/standard-skills/venture-flywheel/references/SPEC-phase0-identity-trust.md +0 -77
  412. package/standard-skills/venture-flywheel/references/SPEC-phase0-state-events.md +0 -93
  413. package/standard-skills/venture-flywheel/schemas/capability-decision.schema.json +0 -13
  414. package/standard-skills/venture-flywheel/schemas/execution-event.schema.json +0 -44
  415. package/standard-skills/venture-flywheel/schemas/project-identity.schema.json +0 -32
  416. package/standard-skills/venture-flywheel/schemas/repository-trust.schema.json +0 -57
  417. package/standard-skills/venture-flywheel/schemas/run-transition.schema.json +0 -59
  418. package/standard-skills/venture-flywheel/state/execution-event.cjs +0 -191
  419. package/standard-skills/venture-flywheel/state/task-state-machine.cjs +0 -190
  420. package/standard-skills/web-lesen/SKILL.md +0 -73
  421. package/standard-skills/web-lesen/scripts/crawl_public.py +0 -379
  422. package/standard-skills/windows-mcp/SKILL.md +0 -19
  423. package/standard-skills/windows-mcp/references/runtime.md +0 -9
  424. package/telegram-plugin/DELIVERY.md +0 -36
  425. package/telegram-plugin/bin/telegram-approval-relay.cjs +0 -290
  426. package/telegram-plugin/bin/telegram-console-status-policy.cjs +0 -175
  427. package/telegram-plugin/bin/telegram-delivery-lifecycle.cjs +0 -125
  428. package/telegram-plugin/bin/telegram-direct-reply-policy.cjs +0 -48
  429. package/telegram-plugin/bin/telegram-launcher-status-queue.cjs +0 -122
  430. package/telegram-plugin/bin/telegram-private-conversation-policy.cjs +0 -186
  431. package/telegram-plugin/bin/telegram-remote-status-policy.cjs +0 -121
  432. package/telegram-plugin/bin/telegram-reply-parts.cjs +0 -149
  433. package/telegram-plugin/bin/telegram-text-chunk-policy.cjs +0 -63
  434. package/telegram-plugin/bin/telegram-typing-keepalive.cjs +0 -89
  435. package/telegram-plugin/compat/mcp-server-fa511cd1.mjs +0 -73825
  436. /package/{bin → scripts}/fix-node-pty-perms.js +0 -0
@@ -37,7 +37,8 @@ export function visible(candidate, entities, audience, includePrivate, groupId)
37
37
 
38
38
  export async function learningContext({
39
39
  root = process.cwd(), includePrivate = false, groupId = null, kinds = null,
40
- subjectIds = null, scope = null, maxItems = null, catalog: providedCatalog = null, now = new Date()
40
+ subjectIds = null, scope = null, maxItems = null, catalog: providedCatalog = null, now = new Date(),
41
+ taskFocus = null
41
42
  } = {}) {
42
43
  const catalog = providedCatalog || await buildCatalog(root);
43
44
  const { learning } = await loadLearning(catalog.root, catalog);
@@ -75,10 +76,14 @@ export async function learningContext({
75
76
  .filter((candidate) => !subjectFilter || subjectFilter.has(candidate.subjectId))
76
77
  .filter((candidate) => candidate.privacy !== "group" || (groupId && candidate.groupId === groupId))
77
78
  .filter((candidate) => visible(candidate, entities, audience, includePrivate, groupId));
78
- const items = applicable
79
+ const candidates = applicable
79
80
  .filter((candidate) => !invalidCanaries.has(candidate.id))
80
- .filter((candidate) => visible(candidate, entities, audience, includePrivate, groupId))
81
- .sort((a, b) => b.confidence - a.confidence || b.updatedAt.localeCompare(a.updatedAt) || a.id.localeCompare(b.id))
81
+ .filter((candidate) => visible(candidate, entities, audience, includePrivate, groupId));
82
+ const focusedTaskId = typeof taskFocus === "string" && taskFocus === runtimeScope.taskId ? taskFocus : null;
83
+ const items = candidates
84
+ .sort((a, b) => Number(Boolean(focusedTaskId && b.scope?.taskId === focusedTaskId))
85
+ - Number(Boolean(focusedTaskId && a.scope?.taskId === focusedTaskId))
86
+ || b.confidence - a.confidence || b.updatedAt.localeCompare(a.updatedAt) || a.id.localeCompare(b.id))
82
87
  .slice(0, limit)
83
88
  .map((candidate) => ({
84
89
  id: candidate.id,
@@ -97,6 +102,8 @@ export async function learningContext({
97
102
  && new Date(candidate.promotion.canary.revalidation.expiresAt).getTime() >= new Date(timestamp).getTime()
98
103
  ? "revalidating" : candidate.promotion.canary.status)
99
104
  : "not-required",
105
+ ...(focusedTaskId && candidate.scope?.taskId === focusedTaskId
106
+ ? { relevance: { taskId: focusedTaskId, match: "exact-task" } } : {}),
100
107
  authority: "context-only"
101
108
  }));
102
109
  return {
@@ -23,7 +23,7 @@ import {
23
23
 
24
24
  export async function recordLearningMeasurement({
25
25
  root = process.cwd(), id = `measurement:${randomUUID()}`, learningId, evaluationId, phase, scope, metric,
26
- measurement, coverage, measuredAt, confirmLocalMeasurement = false, now = new Date()
26
+ measurement, coverage, measuredAt, confirmLocalMeasurement = false, now = new Date(), catalog: providedCatalog = null
27
27
  }) {
28
28
  if (!confirmLocalMeasurement) throw new Error("measurement registration requires explicit local confirmation");
29
29
  if (!ID_RE.test(id || "") || !ID_RE.test(learningId || "") || !ID_RE.test(evaluationId || "")) {
@@ -205,7 +205,7 @@ export async function recordLearningMeasurement({
205
205
  state.measurementLineage.push(lineage);
206
206
  state.measurementLineage.sort((a, b) => a.measurementReceiptId.localeCompare(b.measurementReceiptId));
207
207
  return { receipt, lineage, learningPath, unchanged: false };
208
- });
208
+ }, providedCatalog);
209
209
  }
210
210
 
211
211
  export async function revokeLearningMeasurement({
@@ -25,6 +25,7 @@ import {
25
25
  import { sharedContext } from "./sharing.js";
26
26
  import { recordWorldAssertion, worldContext } from "./world-model.js";
27
27
  import { indexSessionTimeline, searchSessionTimeline } from "./session-timeline.js";
28
+ import { captureSessionTimelineEvidence } from "./timeline-world-capture.js";
28
29
  import { gatewayEnvironmentContext } from "./hook-context.js";
29
30
  import {
30
31
  timelineInvocationInput, timelineInvocationRequest
@@ -48,6 +49,66 @@ function timelineTransport(input, root, environment) {
48
49
 
49
50
  function absent(value) { return value === undefined || value === null || value === ""; }
50
51
 
52
+ function gatewayWorldRoute(environment) {
53
+ const gateway = gatewayEnvironmentContext(environment);
54
+ return gateway?.portalRef && gateway?.threadRef ? gateway : null;
55
+ }
56
+
57
+ function exactGatewayValue(args, key, value) {
58
+ if (!absent(args[key]) && args[key] !== value) {
59
+ throw new Error(`${key} does not match the authenticated gateway binding`);
60
+ }
61
+ return value ?? null;
62
+ }
63
+
64
+ function boundGatewayBriefing(args, gateway) {
65
+ if (!gateway) return args;
66
+ const result = { ...args, portalRef: gateway.portalRef, threadRef: gateway.threadRef };
67
+ for (const [key, gatewayKey] of [["host", "host"], ["entityId", "entityId"],
68
+ ["projectId", "projectId"], ["groupId", "groupId"], ["currentTaskId", "taskId"]]) {
69
+ result[key] = exactGatewayValue(args, key, gateway[gatewayKey]);
70
+ }
71
+ if (result.groupId && result.includePrivate) {
72
+ throw new Error("private briefing context cannot be requested from an authenticated group route");
73
+ }
74
+ return result;
75
+ }
76
+
77
+ function boundWorldWrite(args, environment) {
78
+ if (Object.hasOwn(args, "portalRef") || Object.hasOwn(args, "threadRef")) {
79
+ throw new Error("portal and thread references are supplied only by the authenticated gateway");
80
+ }
81
+ const gateway = gatewayWorldRoute(environment);
82
+ if (!gateway || !args.knowledgeKind || args.subjectId !== gateway.taskId) return args;
83
+ const projectId = exactGatewayValue(args, "projectId", gateway.projectId);
84
+ const groupId = exactGatewayValue(args, "groupId", gateway.groupId);
85
+ if (groupId && args.privacy !== "group") {
86
+ throw new Error("task knowledge from an authenticated group route requires group privacy");
87
+ }
88
+ if (!groupId && args.privacy === "group") {
89
+ throw new Error("group task knowledge requires an authenticated group route");
90
+ }
91
+ return { ...args, projectId, groupId, portalRef: gateway.portalRef, threadRef: gateway.threadRef };
92
+ }
93
+
94
+ function boundWorldRead(args, environment) {
95
+ if (Object.hasOwn(args, "portalRef") || Object.hasOwn(args, "threadRef")) {
96
+ throw new Error("portal and thread references are supplied only by the authenticated gateway");
97
+ }
98
+ const gateway = gatewayWorldRoute(environment);
99
+ if (!gateway) return args;
100
+ if (args.continuationTaskId && gateway.taskId && args.continuationTaskId !== gateway.taskId) {
101
+ throw new Error("continuationTaskId does not match the authenticated gateway task");
102
+ }
103
+ const projectId = exactGatewayValue(args, "projectId", gateway.projectId);
104
+ const groupId = exactGatewayValue(args, "groupId", gateway.groupId);
105
+ if (groupId && args.includePrivate) {
106
+ throw new Error("private world context cannot be requested from an authenticated group route");
107
+ }
108
+ return { ...args, projectId, groupId, portalRef: gateway.portalRef, threadRef: gateway.threadRef,
109
+ continuationTaskId: args.continuationTaskId ?? gateway.taskId };
110
+ }
111
+
51
112
  // The MCP process can outlive a host turn. A group claim that appears after a
52
113
  // private permit was issued must therefore suppress consumption here as well
53
114
  // as in PreToolUse; tool arguments cannot clear an authenticated environment.
@@ -99,7 +160,8 @@ async function callTool(name, args = {}, environment = process.env) {
99
160
  }));
100
161
  }
101
162
  if (name === "session_briefing") {
102
- const scoped = await boundBriefingArguments({ ...args, root });
163
+ const gateway = gatewayWorldRoute(environment);
164
+ const scoped = boundGatewayBriefing(await boundBriefingArguments({ ...args, root }), gateway);
103
165
  const sources = await resolveMcpSources({ ...scoped, required: Boolean(args.requirementId) });
104
166
  const briefing = await sessionBriefing({ ...scoped, host: sources.host,
105
167
  catalog: sources.catalog, userStateRoot: sources.userStateRoot, sourceDiagnostics: sources.diagnostics });
@@ -150,8 +212,12 @@ async function callTool(name, args = {}, environment = process.env) {
150
212
  if (name === "update_task") return textResult(await updateTask({ ...args, root }));
151
213
  if (name === "task_context") return textResult(await taskContext({ ...args, root }));
152
214
  if (name === "shared_context") return textResult(await sharedContext({ ...args, root }));
153
- if (name === "record_world_assertion") return textResult(await recordWorldAssertion({ ...args, root }));
154
- if (name === "world_context") return textResult(await worldContext({ ...args, root }));
215
+ if (name === "record_world_assertion") {
216
+ return textResult(await recordWorldAssertion({ ...boundWorldWrite(args, environment), root }));
217
+ }
218
+ if (name === "world_context") {
219
+ return textResult(await worldContext({ ...boundWorldRead(args, environment), root }));
220
+ }
155
221
  if (name === "project_portfolio") return textResult(await projectPortfolioContext({ ...args, root }));
156
222
  if (name === "record_project_observation") return textResult(await recordProjectObservation({ ...args, root }));
157
223
  if (name === "evaluate_autonomy_action") return textResult(await evaluateAutonomyAction({ ...args, root }));
@@ -181,10 +247,30 @@ async function callTool(name, args = {}, environment = process.env) {
181
247
  if (!invocationRequest) return textResult(unavailableTimelineInvocation("timeline-invocation-unavailable"));
182
248
  return textResult(await searchSessionTimeline({ root, host: timeline.host, sessionId: input.request.sessionId, scope: timeline.scope,
183
249
  at: args.at, query: args.query, windowSeconds: args.windowSeconds, includePriorSessions: args.includePriorSessions,
250
+ includePriorProviders: args.includePriorProviders, environment,
184
251
  enrollmentDigest: input.request.enrollmentDigest,
185
252
  hostHome: timelineHostHome(timeline.host, environment), transportDigest: timeline.transportDigest,
186
253
  invocationRequest }));
187
254
  }
255
+ if (name === "session_timeline_capture") {
256
+ const input = timelineInvocationInput(args);
257
+ if (runtimeTimelineGroup(environment, input)) return textResult(unavailableTimelineInvocation("timeline-group-suppressed"));
258
+ if (!input.valid) return textResult(unavailableTimelineInvocation(input.reason || "timeline-scope-invalid"));
259
+ const timeline = timelineTransport(input, root, environment);
260
+ if (!runtimeGatewayMatchesTimeline(environment, timeline.scope, timeline.host)) {
261
+ return textResult(unavailableTimelineInvocation("timeline-gateway-binding-mismatch"));
262
+ }
263
+ const invocationRequest = timelineInvocationRequest("capture", args, root);
264
+ if (!invocationRequest) return textResult(unavailableTimelineInvocation("timeline-invocation-unavailable"));
265
+ return textResult(await captureSessionTimelineEvidence({ root, host: timeline.host,
266
+ sessionId: input.request.sessionId, scope: timeline.scope, eventId: args.eventId,
267
+ at: args.at, query: args.query, windowSeconds: args.windowSeconds,
268
+ includePriorSessions: args.includePriorSessions, includePriorProviders: args.includePriorProviders,
269
+ interpretation: args.interpretation ?? null,
270
+ environment, enrollmentDigest: input.request.enrollmentDigest,
271
+ hostHome: timelineHostHome(timeline.host, environment), transportDigest: timeline.transportDigest,
272
+ invocationRequest }));
273
+ }
188
274
  if (name === "audit") return textResult(await runAudit(root));
189
275
  if (name === "complete_delivery") {
190
276
  const completed = await completeDelivery(args);
@@ -3,7 +3,7 @@ import { resolveHostSourceCatalog } from "./source-roots.js";
3
3
  import { inspectPremortemState } from "./delivery-premortem.js";
4
4
 
5
5
  const INTERNAL = new Set(["catalog", "userStateRoot", "sourceDiagnostics", "sourceRegistry",
6
- "env", "input", "memoryHooks", "resolvedSources"]);
6
+ "env", "input", "memoryHooks", "resolvedSources", "portalRef", "threadRef"]);
7
7
 
8
8
  export function rejectInternalSourceArguments(args) {
9
9
  for (const key of INTERNAL) {
@@ -31,8 +31,18 @@ export async function boundBriefingArguments(args) {
31
31
  }
32
32
 
33
33
  export async function resolveMcpSources({ root, cwd = root,
34
- host = process.env.AGENTSPINE_HOST || "generic", entityId = null,
34
+ host, entityId = null,
35
35
  groupId = null, projectId = null, currentTaskId = null, required = false }) {
36
+ const blunHost = Boolean(process.env.BLUN_HOME && process.env.BLUN_PLUGIN_ROOT);
37
+ const runtimeHost = blunHost && process.env.AGENTSPINE_HOST === "blun"
38
+ ? "codex" : process.env.AGENTSPINE_HOST;
39
+ const selectedHost = host === undefined ? runtimeHost : host;
40
+ // King binds both values when loading this plugin; model arguments cannot
41
+ // switch that running host to another application's private profile.
42
+ if (blunHost && selectedHost !== undefined && selectedHost !== "codex") {
43
+ throw new Error("MCP source host does not match the running BLUN host");
44
+ }
45
+ host = blunHost ? "codex" : (host === undefined ? process.env.AGENTSPINE_HOST || "generic" : host);
36
46
  const canonicalRoot = await canonicalPath(root);
37
47
  const canonicalCwd = await canonicalPath(cwd);
38
48
  if (!isInside(canonicalRoot, canonicalCwd)) throw new Error("MCP cwd must remain inside its root");
@@ -6,18 +6,60 @@ const stableId = {
6
6
  };
7
7
 
8
8
  const optionalId = { anyOf: [stableId, { type: "null" }] };
9
+ const assertionId = {
10
+ type: "string",
11
+ pattern: "^assertion:[A-Za-z0-9][A-Za-z0-9._/-]{0,190}$"
12
+ };
13
+
14
+ export const TIMELINE_INTERPRETATION_SCHEMA = "agentspine.timeline-user-feedback-interpretation-request/v1";
15
+ export const TIMELINE_CLARIFICATION_SCHEMA = "agentspine.timeline-user-feedback-clarification-request/v2";
16
+ const INTERPRETATION_KINDS = new Set([
17
+ "next-step-correction", "completion-claim", "not-current-instruction", "ambiguous"
18
+ ]);
19
+
20
+ export function timelineInterpretationRequest(value) {
21
+ if (!value || typeof value !== "object" || Array.isArray(value)
22
+ || Object.getPrototypeOf(value) !== Object.prototype) return null;
23
+ const clarificationKeys = ["schema", "feedbackAssertionIds", "targetAssertionId", "clarificationQuestion"];
24
+ if (Object.keys(value).sort().join("\0") === clarificationKeys.sort().join("\0")
25
+ && value.schema === TIMELINE_CLARIFICATION_SCHEMA
26
+ && Array.isArray(value.feedbackAssertionIds) && value.feedbackAssertionIds.length >= 2
27
+ && value.feedbackAssertionIds.length <= 3
28
+ && value.feedbackAssertionIds.every((id) => /^assertion:[A-Za-z0-9][A-Za-z0-9._/-]{0,190}$/.test(id))
29
+ && new Set(value.feedbackAssertionIds).size === value.feedbackAssertionIds.length
30
+ && [...value.feedbackAssertionIds].sort().every((id, index) => id === value.feedbackAssertionIds[index])
31
+ && /^assertion:[A-Za-z0-9][A-Za-z0-9._/-]{0,190}$/.test(value.targetAssertionId || "")
32
+ && typeof value.clarificationQuestion === "string" && Boolean(value.clarificationQuestion.trim())
33
+ && value.clarificationQuestion.length <= 300 && !/[\r\n]/u.test(value.clarificationQuestion)) {
34
+ return structuredClone(value);
35
+ }
36
+ const keys = ["schema", "feedbackAssertionId", "targetAssertionId", "kind",
37
+ "proposedNextStepSummary", "clarificationQuestion"];
38
+ if (Object.keys(value).sort().join("\0") !== keys.sort().join("\0")
39
+ || value.schema !== TIMELINE_INTERPRETATION_SCHEMA
40
+ || !/^assertion:[A-Za-z0-9][A-Za-z0-9._/-]{0,190}$/.test(value.feedbackAssertionId || "")
41
+ || !/^assertion:[A-Za-z0-9][A-Za-z0-9._/-]{0,190}$/.test(value.targetAssertionId || "")
42
+ || !INTERPRETATION_KINDS.has(value.kind)) return null;
43
+ const next = value.proposedNextStepSummary;
44
+ const question = value.clarificationQuestion;
45
+ const validNext = typeof next === "string" && Boolean(next.trim())
46
+ && next.length <= 500 && !/[\r\n]/u.test(next);
47
+ const validQuestion = typeof question === "string" && Boolean(question.trim())
48
+ && question.length <= 300 && !/[\r\n]/u.test(question);
49
+ if ((value.kind === "next-step-correction" ? !validNext || question !== null
50
+ : next !== null || (value.kind === "ambiguous" ? !validQuestion : question !== null))) return null;
51
+ return structuredClone(value);
52
+ }
9
53
 
10
54
  // Hosts qualify MCP tools differently. These prefixes must stay exact: a
11
55
  // foreign MCP server can expose an identically named tool but must never
12
56
  // receive a timeline invocation permit.
13
57
  export const AGENTSPINE_TIMELINE_TOOL_PREFIX = "mcp__plugin_agent-spine_agent-spine__";
14
58
  export const BLUN_TIMELINE_TOOL_PREFIX = "mcp__agent-spine__";
15
- export const KING_PLUGIN_TIMELINE_TOOL_PREFIX = "mcp__plugin-agent-spine_agent-spine__";
16
59
 
17
60
  const TIMELINE_TOOL_PREFIXES = [
18
61
  AGENTSPINE_TIMELINE_TOOL_PREFIX,
19
- BLUN_TIMELINE_TOOL_PREFIX,
20
- KING_PLUGIN_TIMELINE_TOOL_PREFIX
62
+ BLUN_TIMELINE_TOOL_PREFIX
21
63
  ];
22
64
 
23
65
  const SCOPE_FIELDS = [
@@ -29,6 +71,8 @@ const SCOPE_FIELDS = [
29
71
  ["currentTaskId", ["taskId", "task_id", "currentTaskId", "current_task_id"]],
30
72
  ["goalId", ["goalId", "goal_id"]],
31
73
  ["goalStepId", ["goalStepId", "goal_step_id"]],
74
+ ["portalRef", ["portalRef", "portal_ref"]],
75
+ ["threadRef", ["threadRef", "thread_ref"]],
32
76
  ["timelineVisibility", ["timelineVisibility", "timeline_visibility"]]
33
77
  ];
34
78
 
@@ -110,6 +154,7 @@ export function timelineToolKind(name) {
110
154
  const qualified = String(name || "");
111
155
  if (TIMELINE_TOOL_PREFIXES.some((prefix) => qualified === `${prefix}session_timeline_index`)) return "index";
112
156
  if (TIMELINE_TOOL_PREFIXES.some((prefix) => qualified === `${prefix}session_timeline_search`)) return "search";
157
+ if (TIMELINE_TOOL_PREFIXES.some((prefix) => qualified === `${prefix}session_timeline_capture`)) return "capture";
113
158
  return null;
114
159
  }
115
160
 
@@ -120,17 +165,22 @@ export function timelineInvocationRequest(tool, args, root) {
120
165
  const request = { root, tool, sessionId: input.request.sessionId, entityId: scope.entityId, userId: scope.userId,
121
166
  tenantId: scope.tenantId, projectId: scope.projectId, groupId: scope.groupId, taskId: scope.currentTaskId,
122
167
  goalId: scope.goalId, goalStepId: scope.goalStepId, timelineVisibility: scope.timelineVisibility,
168
+ portalRef: scope.portalRef, threadRef: scope.threadRef,
123
169
  enrollmentDigest: input.request.enrollmentDigest };
124
170
  if (tool === "index") return { ...request, maxBytes: args.maxBytes ?? 4 * 1024 * 1024 };
125
- return { ...request, at: args.at ?? null, query: args.query ?? null,
171
+ return { ...request, ...(tool === "capture" ? { eventId: args.eventId ?? null,
172
+ interpretation: args.interpretation ?? null } : {}),
173
+ at: args.at ?? null, query: args.query ?? null,
126
174
  windowSeconds: args.windowSeconds === undefined ? 0 : args.windowSeconds,
127
- includePriorSessions: args.includePriorSessions === true };
175
+ includePriorSessions: args.includePriorSessions === true,
176
+ includePriorProviders: args.includePriorProviders === true };
128
177
  }
129
178
 
130
179
  const scopeProperties = {
131
180
  host: { enum: TIMELINE_HOSTS },
132
181
  entityId: stableId, userId: stableId, tenantId: stableId, projectId: stableId,
133
- taskId: stableId, goalId: optionalId, goalStepId: optionalId
182
+ taskId: stableId, goalId: optionalId, goalStepId: optionalId,
183
+ portalRef: optionalId, threadRef: optionalId
134
184
  };
135
185
 
136
186
  export const sessionTimelineTools = [
@@ -148,7 +198,7 @@ export const sessionTimelineTools = [
148
198
  },
149
199
  {
150
200
  name: "session_timeline_search",
151
- description: "Search the current or a same-task prior explicitly enrolled immutable Claude, Codex or King source for redacted objective evidence by exact UTC time or at least two concrete terms. Prior-session search opens only one indexed source and never grants authority.",
201
+ description: "Search one enrolled immutable same-task source for objective evidence or strict user corrections. Query 'user message' explicitly selects bounded native user-message candidates without interpreting them; add exact UTC time to narrow. No source text is indexed. Cross-provider recall requires opt-in; one source is opened and no authority is granted.",
152
202
  inputSchema: {
153
203
  type: "object", additionalProperties: false,
154
204
  required: [],
@@ -158,7 +208,40 @@ export const sessionTimelineTools = [
158
208
  timelineVisibility: { const: "private-verified" }, groupId: { anyOf: [stableId, { type: "null" }] },
159
209
  at: { type: "string", format: "date-time" }, query: { type: "string", minLength: 3, maxLength: 512 },
160
210
  windowSeconds: { type: "integer", minimum: 0, maximum: 900 },
161
- includePriorSessions: { type: "boolean" } }
211
+ includePriorSessions: { type: "boolean" }, includePriorProviders: { type: "boolean" } }
212
+ }
213
+ },
214
+ {
215
+ name: "session_timeline_capture",
216
+ description: "Reopen one source-bound event. Objective fields become descriptive task state; strict prefixed corrections may replace the same-thread next step. Natural user messages remain uninterpreted beside their exact checkpoint. A second source-bound call may preserve one model interpretation as an unconfirmed proposal; it never changes continuation, proves completion or grants authority.",
217
+ inputSchema: {
218
+ type: "object", additionalProperties: false,
219
+ required: ["eventId"],
220
+ anyOf: [{ required: ["at"] }, { required: ["query"] }],
221
+ properties: { root: { type: "string", minLength: 1 }, sessionId: stableId, ...scopeProperties,
222
+ enrollmentDigest: { type: "string", pattern: "^[a-f0-9]{64}$" },
223
+ timelineVisibility: { const: "private-verified" }, groupId: { anyOf: [stableId, { type: "null" }] },
224
+ eventId: { type: "string", pattern: "^timeline-event:[a-f0-9]{32}$" },
225
+ interpretation: { oneOf: [{
226
+ type: "object", additionalProperties: false,
227
+ required: ["schema", "feedbackAssertionId", "targetAssertionId", "kind",
228
+ "proposedNextStepSummary", "clarificationQuestion"],
229
+ properties: { schema: { const: TIMELINE_INTERPRETATION_SCHEMA },
230
+ feedbackAssertionId: assertionId, targetAssertionId: assertionId,
231
+ kind: { enum: [...INTERPRETATION_KINDS] },
232
+ proposedNextStepSummary: { anyOf: [{ type: "string", minLength: 1, maxLength: 500 }, { type: "null" }] },
233
+ clarificationQuestion: { anyOf: [{ type: "string", minLength: 1, maxLength: 300 }, { type: "null" }] } }
234
+ }, {
235
+ type: "object", additionalProperties: false,
236
+ required: ["schema", "feedbackAssertionIds", "targetAssertionId", "clarificationQuestion"],
237
+ properties: { schema: { const: TIMELINE_CLARIFICATION_SCHEMA },
238
+ feedbackAssertionIds: { type: "array", minItems: 2, maxItems: 3, uniqueItems: true,
239
+ items: assertionId }, targetAssertionId: assertionId,
240
+ clarificationQuestion: { type: "string", minLength: 1, maxLength: 300 } }
241
+ }] },
242
+ at: { type: "string", format: "date-time" }, query: { type: "string", minLength: 3, maxLength: 512 },
243
+ windowSeconds: { type: "integer", minimum: 0, maximum: 900 },
244
+ includePriorSessions: { type: "boolean" }, includePriorProviders: { type: "boolean" } }
162
245
  }
163
246
  }
164
247
  ];
@@ -8,7 +8,7 @@ const nullableStableId = { anyOf: [stableId, { type: "null" }] };
8
8
  export const worldModelTools = [
9
9
  {
10
10
  name: "record_world_assertion",
11
- description: "Persist one provenance-bound world, user, relationship, or team assertion outside source files. Optional typed knowledge distinguishes facts, user preferences, decisions, task state, and error lessons. Measurements and explicit user feedback become context-only facts; model output remains a proposal. Authority predicates and secret-shaped structured knowledge are rejected.",
11
+ description: "Persist one provenance-bound world, user, relationship, or team assertion outside source files. Optional typed knowledge distinguishes facts, user preferences, decisions, task state, and error lessons. In an authenticated portal task, task-subject knowledge is bound to the gateway's opaque portal/thread route; tool arguments cannot claim that route. Measurements and explicit user feedback become context-only facts; model output remains a proposal. Authority predicates and secret-shaped structured knowledge are rejected.",
12
12
  inputSchema: {
13
13
  type: "object", additionalProperties: false,
14
14
  required: ["id", "subjectId", "predicate", "value", "evidenceKind", "evidenceId", "evidenceDigest", "observedAt"],
@@ -36,7 +36,7 @@ export const worldModelTools = [
36
36
  },
37
37
  {
38
38
  name: "world_context",
39
- description: "Read privacy-filtered world context. Conflicts, expiry, and suggestions remain separate; continuationTaskId adds bounded, sourced task-relevant knowledge.",
39
+ description: "Read privacy-filtered world context. Conflicts, expiry, and suggestions remain separate; continuationTaskId adds bounded, sourced task-relevant knowledge. An authenticated portal process automatically restricts task continuation to its opaque gateway route; route references are not accepted as tool input.",
40
40
  inputSchema: {
41
41
  type: "object", additionalProperties: false,
42
42
  properties: {
@@ -3,11 +3,26 @@ import { open, readFile, stat, unlink, utimes } from "node:fs/promises";
3
3
  import { isFileLockContention, isTransientLockMetadataError } from "./filesystem-retry.js";
4
4
 
5
5
  const LOCK_SCHEMA = "agentspine.owned-file-lock/v1";
6
+ const LOCAL_TAILS = new Map();
6
7
 
7
8
  function delay(milliseconds) {
8
9
  return new Promise((resolve) => setTimeout(resolve, milliseconds));
9
10
  }
10
11
 
12
+ async function serialize(path, task) {
13
+ const previous = LOCAL_TAILS.get(path) || Promise.resolve();
14
+ let release;
15
+ const current = new Promise(resolve => { release = resolve; });
16
+ const tail = previous.catch(() => {}).then(() => current);
17
+ LOCAL_TAILS.set(path, tail);
18
+ await previous.catch(() => {});
19
+ try { return await task(); }
20
+ finally {
21
+ release();
22
+ if (LOCAL_TAILS.get(path) === tail) LOCAL_TAILS.delete(path);
23
+ }
24
+ }
25
+
11
26
  function lockPayload(token, acquiredAt, leaseMs) {
12
27
  return {
13
28
  schema: LOCK_SCHEMA,
@@ -66,7 +81,7 @@ async function removeStaleLock(path, staleAfterMs, assertPath = null) {
66
81
  }
67
82
  }
68
83
 
69
- export async function withOwnedFileLock(path, task, {
84
+ async function acquire(path, task, {
70
85
  staleAfterMs = 15000,
71
86
  heartbeatIntervalMs = 1000,
72
87
  retryDelayMs = 25,
@@ -161,3 +176,7 @@ export async function withOwnedFileLock(path, task, {
161
176
  }
162
177
  }
163
178
  }
179
+
180
+ export function withOwnedFileLock(path, task, options) {
181
+ return serialize(path, () => acquire(path, task, options));
182
+ }
@@ -3,7 +3,7 @@ import { constants as fsConstants } from "node:fs";
3
3
  import { lstat, open, opendir, readFile, realpath, stat, unlink, writeFile } from "node:fs/promises";
4
4
  import { isAbsolute, join } from "node:path";
5
5
  import { buildCatalog } from "./catalog.js";
6
- import { isFileLockContention, replaceFileWithRetry } from "./filesystem-retry.js";
6
+ import { isFileLockContention, isTransientLockMetadataError, replaceFileWithRetry } from "./filesystem-retry.js";
7
7
  import { linkEntities, loadGraph, unlinkEntities, upsertEntity } from "./graph.js";
8
8
  import { isInside, projectStateDir } from "./paths.js";
9
9
 
@@ -175,7 +175,7 @@ async function withLock(paths, task) {
175
175
  try {
176
176
  const metadata = await stat(lockPath);
177
177
  if (Date.now() - metadata.mtimeMs > 90000) await unlink(lockPath);
178
- } catch (lockError) { if (lockError.code !== "ENOENT") throw lockError; }
178
+ } catch (lockError) { if (!isTransientLockMetadataError(lockError)) throw lockError; }
179
179
  await new Promise((resolve) => setTimeout(resolve, 25));
180
180
  }
181
181
  }
@@ -0,0 +1,27 @@
1
+ import { createHash, randomBytes } from "node:crypto";
2
+
3
+ const ID = /^[A-Za-z0-9][A-Za-z0-9:_.@/+~-]{0,255}$/;
4
+ const issued = new WeakMap();
5
+
6
+ function exact(value, field) {
7
+ if (value === null || value === undefined || value === "") return null;
8
+ if (typeof value !== "string" || !ID.test(value) || value.includes("*")) {
9
+ throw new Error(`${field} must be one exact ID`);
10
+ }
11
+ return value;
12
+ }
13
+
14
+ // Without a host ID, only the parsed invocation object can verify its receipt.
15
+ export function preflightDeliveryId(input, { issue = false } = {}) {
16
+ if (!input || typeof input !== "object") return null;
17
+ const turn = exact(input.turn_id, "turnId");
18
+ const event = exact(input.event_id ?? input.hook_event_id, "hookEventId");
19
+ if (turn && event) return `host-turn:${createHash("sha256").update(`${turn}\0${event}`).digest("hex").slice(0, 32)}`;
20
+ if (turn || event) return turn || event;
21
+ let id = issued.get(input);
22
+ if (!id && issue) {
23
+ id = `hook-invocation:${randomBytes(16).toString("hex")}`;
24
+ issued.set(input, id);
25
+ }
26
+ return id || null;
27
+ }
@@ -5,6 +5,7 @@ import { lstat, mkdir, open, readFile, realpath, stat, unlink, writeFile } from
5
5
  import { basename, dirname, isAbsolute, join, relative, resolve } from "node:path";
6
6
  import { isFileLockContention, replaceFileWithRetry } from "./filesystem-retry.js";
7
7
  import { ancestorsBetween, isInside, stateRoot } from "./paths.js";
8
+ import { preflightDeliveryId } from "./preflight-delivery-id.js";
8
9
  import { resolveHostSourceCatalog } from "./source-roots.js";
9
10
 
10
11
  export const PREFLIGHT_SCHEMA = "agentspine.preflight/v2";
@@ -493,8 +494,8 @@ export async function runPreflight({ input, scope, resolvedSources, prompt, now
493
494
  if (typeof prompt !== "string" || !prompt.length || Buffer.byteLength(prompt) > 64 * 1024) throw new Error("preflight requires one bounded prompt");
494
495
  const exactScope = scopeFromInput({ input, scope, resolvedSources, env });
495
496
  const promptDigest = sha256(prompt);
496
- const deliveryId = exactId(input.event_id ?? input.hook_event_id, "hookEventId",
497
- `prompt:${sha256(`${exactScope.sessionId}\0${promptDigest}`).slice(0, 32)}`);
497
+ const deliveryId = preflightDeliveryId(input, { issue: true });
498
+ if (!deliveryId) throw new Error("preflight hook invocation identity is unavailable");
498
499
  const paths = storagePaths(env);
499
500
  const policy = validatePolicy(await readJson(paths.policy, MAX_POLICY_BYTES, emptyPolicy));
500
501
  const profile = policy.profiles.find((item) => item.enabled && item.agentId === exactScope.agentId && item.host === exactScope.host
@@ -590,8 +591,7 @@ export async function verifyPreflightReceipt({ receipt, input, scope, resolvedSo
590
591
  || receipt.tenantId !== exactScope.tenantId || receipt.host !== exactScope.host || receipt.profileId !== exactScope.profileId
591
592
  || receipt.sessionId !== exactScope.sessionId || receipt.projectId !== exactScope.projectId || receipt.cwdDigest !== sha256(exactScope.cwd)
592
593
  || receipt.taskId !== exactScope.taskId || receipt.groupId !== exactScope.groupId) return false;
593
- const deliveryId = exactId(input.event_id ?? input.hook_event_id, "hookEventId",
594
- `prompt:${sha256(`${exactScope.sessionId}\0${sha256(prompt)}`).slice(0, 32)}`);
594
+ const deliveryId = preflightDeliveryId(input);
595
595
  if (receipt.deliveryId !== deliveryId) return false;
596
596
  const { id: _id, bodyDigest, signature, ...body } = receipt;
597
597
  if (digestObject(body) !== bodyDigest) return false;
@@ -56,3 +56,18 @@ export function codexTimelineToolResult(line) {
56
56
  }
57
57
  return typeof output === "string" ? { role: "tool", content: output, nativeMessageId: item.call_id } : null;
58
58
  }
59
+
60
+ export function codexTimelineUserMessage(line) {
61
+ if (!RECORDS.has(line?.type) || line.schema_version !== undefined) {
62
+ throw new Error("codex-history-format-mismatch");
63
+ }
64
+ if (line.type !== "response_item") return null;
65
+ const item = line.payload;
66
+ if (!item || item.type !== "message" || item.role !== "user" || !Array.isArray(item.content)
67
+ || item.content.length > 12 || item.content.some((part) => part?.type !== "input_text"
68
+ || typeof part.text !== "string")) return null;
69
+ const nativeMessageId = item.id === undefined ? undefined : ID.test(item.id) ? item.id : null;
70
+ if (nativeMessageId === null) return null;
71
+ return { role: "user", content: item.content.map((part) => part.text).join("\n"),
72
+ ...(nativeMessageId ? { nativeMessageId } : {}) };
73
+ }
@@ -7,7 +7,7 @@ export function safeTimelineId(value) {
7
7
  }
8
8
 
9
9
  export function sessionTimelineBinding({ host, sessionId, scope }) {
10
- return {
10
+ const binding = {
11
11
  host: validTimelineHost(host) ? host : null,
12
12
  sessionId: safeTimelineId(sessionId),
13
13
  entityId: safeTimelineId(scope?.entityId),
@@ -19,6 +19,11 @@ export function sessionTimelineBinding({ host, sessionId, scope }) {
19
19
  goalId: safeTimelineId(scope?.goalId),
20
20
  goalStepId: safeTimelineId(scope?.goalStepId)
21
21
  };
22
+ if (scope?.portalRef || scope?.threadRef) {
23
+ binding.portalRef = safeTimelineId(scope?.portalRef);
24
+ binding.threadRef = safeTimelineId(scope?.threadRef);
25
+ }
26
+ return binding;
22
27
  }
23
28
 
24
29
  export function hasTimelineGroupScope(scope) {
@@ -31,12 +36,13 @@ export function hasVerifiedTimelinePrivateScope(scope) {
31
36
 
32
37
  export function completeTimelineBinding(value) {
33
38
  return validTimelineHost(value.host) && !value.groupId
39
+ && Boolean(value.portalRef) === Boolean(value.threadRef)
34
40
  && ["sessionId", "entityId", "userId", "tenantId", "projectId", "taskId"].every((key) => value[key]);
35
41
  }
36
42
 
37
43
  export function sameTimelineBinding(left, right) {
38
- return ["host", "sessionId", "entityId", "userId", "tenantId", "projectId", "groupId", "taskId", "goalId", "goalStepId"]
39
- .every((key) => left[key] === right[key]);
44
+ return ["host", "sessionId", "entityId", "userId", "tenantId", "projectId", "groupId", "taskId", "goalId", "goalStepId",
45
+ "portalRef", "threadRef"].every((key) => (left[key] ?? null) === (right[key] ?? null));
40
46
  }
41
47
 
42
48
  export function validTimelineBinding(value) {
@@ -44,5 +50,7 @@ export function validTimelineBinding(value) {
44
50
  && [value.sessionId, value.entityId, value.userId, value.tenantId, value.projectId, value.taskId]
45
51
  .every((item) => typeof item === "string" && TIMELINE_ID_RE.test(item))
46
52
  && [value.groupId, value.goalId, value.goalStepId]
47
- .every((item) => item === null || (typeof item === "string" && TIMELINE_ID_RE.test(item)));
53
+ .every((item) => item === null || (typeof item === "string" && TIMELINE_ID_RE.test(item)))
54
+ && ((value.portalRef === undefined && value.threadRef === undefined)
55
+ || [value.portalRef, value.threadRef].every((item) => typeof item === "string" && TIMELINE_ID_RE.test(item)));
48
56
  }