total-recall-brain 3.44.0 → 3.46.0

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 (502) hide show
  1. package/bin/total-recall.mjs +10 -6
  2. package/docs/ARCHITECTURE.md +10 -7
  3. package/docs/reference/cli-reference.md +13 -8
  4. package/frontend/dist/assets/index-BRYE1jmv.css +1 -0
  5. package/frontend/dist/assets/index-D1goIPjC.js +5598 -0
  6. package/frontend/dist/index.html +2 -2
  7. package/frontend/dist/sw.js +5 -4
  8. package/frontend/src/App.tsx +185 -238
  9. package/frontend/src/api/auth-inventory.ts +62 -0
  10. package/frontend/src/api/memory.ts +13 -8
  11. package/frontend/src/api/plugin-credentials.ts +23 -0
  12. package/frontend/src/api/plugins.ts +37 -53
  13. package/frontend/src/api/workspace-drawers.ts +97 -0
  14. package/frontend/src/components/BrainSelector.tsx +9 -3
  15. package/frontend/src/components/plugins/PluginPanel.tsx +83 -42
  16. package/frontend/src/components/plugins/PluginSettings.tsx +10 -20
  17. package/frontend/src/components/plugins/PluginWorkspace.tsx +367 -0
  18. package/frontend/src/components/plugins/ScopedPluginCommands.tsx +142 -0
  19. package/frontend/src/components/plugins/plugin-frame.ts +44 -33
  20. package/frontend/src/components/plugins/scoped-plugin-operations.ts +28 -0
  21. package/frontend/src/components/workspace/DrawerChat.tsx +110 -0
  22. package/frontend/src/components/workspace/DrawerLayout.tsx +196 -0
  23. package/frontend/src/components/workspace/DrawerMarkup.tsx +49 -0
  24. package/frontend/src/components/workspace/PluginChunkLibrary.tsx +92 -0
  25. package/frontend/src/components/workspace/PluginHome.tsx +76 -0
  26. package/frontend/src/components/workspace/WorkspaceDrawers.tsx +96 -0
  27. package/frontend/src/components/workspace/WorkspacePage.tsx +95 -0
  28. package/frontend/src/components/workspace/usePluginDesign.ts +38 -0
  29. package/frontend/src/index.css +409 -136
  30. package/frontend/src/pages/HelpPage.tsx +15 -46
  31. package/frontend/src/pages/MemoryPage.tsx +19 -36
  32. package/frontend/src/pages/SettingsPage.tsx +1 -1
  33. package/metadata.plugin.schema.json +53 -227
  34. package/package.json +1 -1
  35. package/scaffold/.agent/skills/plugin/SKILL.md +13 -11
  36. package/scaffold/.agent/skills/plugin/evals/README.md +14 -21
  37. package/scaffold/.agent/skills/plugin/evals/cases/01-fabricated-seed.mjs +15 -18
  38. package/scaffold/.agent/skills/plugin/evals/cases/02-reassuring-default.mjs +19 -24
  39. package/scaffold/.agent/skills/plugin/evals/cases/03-declared-template.mjs +12 -20
  40. package/scaffold/.agent/skills/plugin/evals/cases/04-home-collects-credential.mjs +35 -0
  41. package/scaffold/.agent/skills/plugin/evals/cases/05-host-leak-in-scaffold.mjs +8 -28
  42. package/scaffold/.agent/skills/plugin/evals/cases/06-correct-plugin.mjs +85 -47
  43. package/scaffold/.agent/skills/plugin/evals/run.mjs +17 -18
  44. package/scaffold/.agent/skills/plugin/prompts/05-credentials.md +4 -4
  45. package/scaffold/.agent/skills/plugin/prompts/07-scaffold.md +2 -2
  46. package/scaffold/.agent/skills/plugin/prompts/08-verify.md +4 -4
  47. package/scaffold/.agent/skills/plugin/references/anti-patterns.md +2 -2
  48. package/scaffold/.agent/skills/plugin/references/generative-home.md +38 -0
  49. package/scaffold/.agent/skills/plugin/references/scaffold.md +5 -5
  50. package/scaffold/.agent/skills/plugin/references/surfaces.md +13 -4
  51. package/scaffold/.agent/skills/plugin/scripts/record.mjs +75 -153
  52. package/scaffold/.agent/skills/plugin/subagents/plugin-reviewer.md +4 -4
  53. package/scaffold/.agent/skills/total-recall/plugins/auth/DESIGN.md +76 -0
  54. package/scaffold/.agent/skills/total-recall/plugins/auth/README.md +3 -1
  55. package/scaffold/.agent/skills/total-recall/plugins/auth/cli.mjs +20 -15
  56. package/scaffold/.agent/skills/total-recall/plugins/auth/package-lock.json +7 -7
  57. package/scaffold/.agent/skills/total-recall/plugins/auth/package.json +2 -1
  58. package/scaffold/.agent/skills/total-recall/plugins/auth/plugin.json +13 -51
  59. package/scaffold/.agent/skills/total-recall/plugins/auth/src/cli-secret.mjs +20 -1
  60. package/scaffold/.agent/skills/total-recall/plugins/auth/src/secrets-store.mjs +12 -1
  61. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/access-overview.md +17 -0
  62. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/agent-login.md +20 -0
  63. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/baseline-audit.md +22 -0
  64. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/credential-repository-binding.md +17 -0
  65. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/credential-store-maintenance.md +17 -0
  66. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/dashboard-password.md +18 -0
  67. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/dashboard-sessions.md +18 -0
  68. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/endpoint-probe.md +23 -0
  69. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/google-sign-in.md +21 -0
  70. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/mesh-machines.md +16 -0
  71. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/passkey-enrollment.md +21 -0
  72. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/registered-brains.md +16 -0
  73. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/scoped-access-keys.md +17 -0
  74. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/secret-inventory.md +25 -0
  75. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/signing-key-rotation.md +22 -0
  76. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/home.js +375 -0
  77. package/scaffold/.agent/skills/total-recall/plugins/automations/BRICK.md +7 -0
  78. package/scaffold/.agent/skills/total-recall/plugins/automations/DESIGN.md +53 -0
  79. package/scaffold/.agent/skills/total-recall/plugins/automations/LICENSE +21 -0
  80. package/scaffold/.agent/skills/total-recall/plugins/automations/README.md +66 -0
  81. package/scaffold/.agent/skills/total-recall/plugins/automations/adapters.mjs +247 -0
  82. package/scaffold/.agent/skills/total-recall/plugins/automations/capability/index.mjs +16 -0
  83. package/scaffold/.agent/skills/total-recall/plugins/automations/cli.mjs +130 -0
  84. package/{src/core/plugin-cron.mjs → scaffold/.agent/skills/total-recall/plugins/automations/cron.mjs} +1 -3
  85. package/scaffold/.agent/skills/total-recall/plugins/automations/inventory.mjs +88 -0
  86. package/scaffold/.agent/skills/total-recall/plugins/automations/package-lock.json +7661 -0
  87. package/scaffold/.agent/skills/total-recall/plugins/automations/package.json +36 -0
  88. package/scaffold/.agent/skills/total-recall/plugins/automations/plugin.json +151 -0
  89. package/scaffold/.agent/skills/total-recall/plugins/automations/scheduler.mjs +246 -0
  90. package/scaffold/.agent/skills/total-recall/plugins/automations/ui/automations.js +2 -0
  91. package/scaffold/.agent/skills/total-recall/plugins/automations/ui/chunks/control-ledger.md +42 -0
  92. package/scaffold/.agent/skills/total-recall/plugins/automations/ui/chunks/local-inventory-triage.md +17 -0
  93. package/scaffold/.agent/skills/total-recall/plugins/automations/ui/chunks/pending-control.md +39 -0
  94. package/scaffold/.agent/skills/total-recall/plugins/automations/ui/chunks/run-evidence.md +41 -0
  95. package/scaffold/.agent/skills/total-recall/plugins/automations/ui/chunks/schedule-vs-run-evidence.md +17 -0
  96. package/scaffold/.agent/skills/total-recall/plugins/automations/ui/chunks/source-coverage.md +41 -0
  97. package/scaffold/.agent/skills/total-recall/plugins/automations/ui/home.js +278 -0
  98. package/scaffold/.agent/skills/total-recall/plugins/code-quality/DESIGN.md +53 -0
  99. package/scaffold/.agent/skills/total-recall/plugins/code-quality/cli.mjs +23 -0
  100. package/scaffold/.agent/skills/total-recall/plugins/code-quality/commands/run-core.mjs +5 -3
  101. package/scaffold/.agent/skills/total-recall/plugins/code-quality/core/check.mjs +61 -7
  102. package/scaffold/.agent/skills/total-recall/plugins/code-quality/core/report-data.mjs +40 -14
  103. package/scaffold/.agent/skills/total-recall/plugins/code-quality/core/report.mjs +15 -40
  104. package/scaffold/.agent/skills/total-recall/plugins/code-quality/package-lock.json +7 -7
  105. package/scaffold/.agent/skills/total-recall/plugins/code-quality/package.json +2 -1
  106. package/scaffold/.agent/skills/total-recall/plugins/code-quality/plugin.json +40 -40
  107. package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/chunks/config.md +15 -0
  108. package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/chunks/detect.md +15 -0
  109. package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/chunks/gate.md +15 -0
  110. package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/chunks/init.md +15 -0
  111. package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/chunks/report.md +17 -0
  112. package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/chunks/run.md +17 -0
  113. package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/chunks/snapshot.md +15 -0
  114. package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/code-quality-report.mjs +55 -23
  115. package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/home.mjs +214 -0
  116. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/DESIGN.md +146 -0
  117. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/package-lock.json +7 -7
  118. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/package.json +2 -1
  119. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/plugin.json +51 -34
  120. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/src/command.mjs +1 -1
  121. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/create.md +35 -0
  122. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/history.md +35 -0
  123. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/library.md +49 -0
  124. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/list.md +42 -0
  125. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/promote.md +40 -0
  126. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/read.md +25 -0
  127. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/remove.md +26 -0
  128. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/rollback.md +26 -0
  129. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/show.md +53 -0
  130. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/status.md +40 -0
  131. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/test-path.md +38 -0
  132. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/test.md +46 -0
  133. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/update.md +32 -0
  134. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/home.js +533 -0
  135. package/scaffold/.agent/skills/total-recall/plugins/embeddings/DESIGN.md +110 -0
  136. package/scaffold/.agent/skills/total-recall/plugins/embeddings/package-lock.json +7 -7
  137. package/scaffold/.agent/skills/total-recall/plugins/embeddings/package.json +2 -1
  138. package/scaffold/.agent/skills/total-recall/plugins/embeddings/plugin.json +13 -10
  139. package/scaffold/.agent/skills/total-recall/plugins/embeddings/ui/chunks/benchmark.md +49 -0
  140. package/scaffold/.agent/skills/total-recall/plugins/embeddings/ui/chunks/coverage.md +53 -0
  141. package/scaffold/.agent/skills/total-recall/plugins/embeddings/ui/chunks/models.md +43 -0
  142. package/scaffold/.agent/skills/total-recall/plugins/embeddings/ui/chunks/pull.md +41 -0
  143. package/scaffold/.agent/skills/total-recall/plugins/embeddings/ui/chunks/status.md +59 -0
  144. package/scaffold/.agent/skills/total-recall/plugins/embeddings/ui/home.js +353 -0
  145. package/scaffold/.agent/skills/total-recall/plugins/git/DESIGN.md +31 -0
  146. package/scaffold/.agent/skills/total-recall/plugins/git/README.md +136 -0
  147. package/scaffold/.agent/skills/total-recall/plugins/{git-sentinel → git}/cli.mjs +140 -24
  148. package/scaffold/.agent/skills/total-recall/plugins/{git-sentinel → git}/package-lock.json +9 -9
  149. package/scaffold/.agent/skills/total-recall/plugins/{git-sentinel → git}/package.json +4 -2
  150. package/scaffold/.agent/skills/total-recall/plugins/git/plugin.json +151 -0
  151. package/scaffold/.agent/skills/total-recall/plugins/git/src/lib/context.mjs +94 -0
  152. package/scaffold/.agent/skills/total-recall/plugins/git/src/lib/phase3-spec-support.mjs +50 -0
  153. package/scaffold/.agent/skills/total-recall/plugins/git/src/lib/runtime.mjs +40 -0
  154. package/scaffold/.agent/skills/total-recall/plugins/git/src/lib/spec-support.mjs +51 -0
  155. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/_support.mjs +195 -0
  156. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/auth.mjs +201 -0
  157. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/bisect.mjs +40 -0
  158. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/cli-meta.mjs +159 -0
  159. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/commit-memory.mjs +54 -0
  160. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/commit.mjs +46 -0
  161. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/fleet.mjs +174 -0
  162. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/force-push.mjs +58 -0
  163. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/group.mjs +119 -0
  164. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/handoff.mjs +59 -0
  165. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/message.mjs +22 -0
  166. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/resolve.mjs +60 -0
  167. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/rules.mjs +81 -0
  168. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/secret-firewall.mjs +92 -0
  169. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/undo.mjs +156 -0
  170. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/unmerged.mjs +182 -0
  171. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/why.mjs +16 -0
  172. package/scaffold/.agent/skills/total-recall/plugins/git/ui/chunks/change-comparison.md +27 -0
  173. package/scaffold/.agent/skills/total-recall/plugins/git/ui/chunks/commit-identity.md +22 -0
  174. package/scaffold/.agent/skills/total-recall/plugins/git/ui/chunks/create-worktree.md +25 -0
  175. package/scaffold/.agent/skills/total-recall/plugins/git/ui/chunks/registered-worktrees.md +22 -0
  176. package/scaffold/.agent/skills/total-recall/plugins/git/ui/chunks/remove-worktree.md +23 -0
  177. package/scaffold/.agent/skills/total-recall/plugins/git/ui/chunks/repository-ledger.md +25 -0
  178. package/scaffold/.agent/skills/total-recall/plugins/git/ui/chunks/unmerged-work.md +22 -0
  179. package/scaffold/.agent/skills/total-recall/plugins/git/ui/chunks/upstream-divergence.md +17 -0
  180. package/scaffold/.agent/skills/total-recall/plugins/git/ui/chunks/worktree-conflict-triage.md +17 -0
  181. package/scaffold/.agent/skills/total-recall/plugins/git/ui/chunks/worktree-terminal.md +22 -0
  182. package/scaffold/.agent/skills/total-recall/plugins/git/ui/home.js +273 -0
  183. package/scaffold/.agent/skills/total-recall/plugins/mesh/DESIGN.md +35 -0
  184. package/scaffold/.agent/skills/total-recall/plugins/mesh/README.md +4 -5
  185. package/scaffold/.agent/skills/total-recall/plugins/mesh/cli.mjs +9 -3
  186. package/scaffold/.agent/skills/total-recall/plugins/mesh/package-lock.json +7 -7
  187. package/scaffold/.agent/skills/total-recall/plugins/mesh/package.json +2 -1
  188. package/scaffold/.agent/skills/total-recall/plugins/mesh/plugin.json +37 -39
  189. package/scaffold/.agent/skills/total-recall/plugins/mesh/src/cli/mesh.mjs +5 -3
  190. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/active-device-dispatch.md +22 -0
  191. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/control-probe.md +25 -0
  192. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/control-server.md +22 -0
  193. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/credential-readiness.md +23 -0
  194. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/elected-leader.md +22 -0
  195. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/enrollment-key.md +22 -0
  196. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/file-receipt.md +25 -0
  197. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/fleet-execution.md +23 -0
  198. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/fleet-presence.md +23 -0
  199. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/interactive-ssh.md +22 -0
  200. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/local-enrollment.md +23 -0
  201. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/mesh-policy.md +23 -0
  202. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/network-atlas.md +25 -0
  203. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/node-roster.md +26 -0
  204. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/node-selection-proof.md +17 -0
  205. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/owner-observations.md +23 -0
  206. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/peer-path.md +23 -0
  207. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/pinned-leader.md +24 -0
  208. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/reachability-evidence-ladder.md +17 -0
  209. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/recorded-login.md +23 -0
  210. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/remote-execution.md +22 -0
  211. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/secret-grants.md +26 -0
  212. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/{card.js → home.js} +93 -22
  213. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/DESIGN.md +86 -0
  214. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/README.md +44 -9
  215. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/capability/BRICK.md +1 -1
  216. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/capability/index.mjs +18 -6
  217. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/cli.mjs +128 -24
  218. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/package-lock.json +7 -7
  219. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/package.json +3 -2
  220. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/plugin.json +188 -34
  221. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/skills/meta-harness/SKILL.md +17 -3
  222. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/adoption.mjs +2 -2
  223. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/alerts.mjs +3 -3
  224. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/cascade.mjs +92 -18
  225. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/chat.mjs +80 -0
  226. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/control.mjs +145 -0
  227. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/coordinator.mjs +42 -21
  228. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/dispatch-request.mjs +4 -2
  229. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/dispatch.mjs +33 -9
  230. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/documentation.mjs +55 -11
  231. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/executor.mjs +26 -4
  232. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/gate-adapters/hermes.mjs +29 -1
  233. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/gate-adapters/index.mjs +1 -1
  234. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/included-usage.mjs +1 -1
  235. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/jobs.mjs +84 -0
  236. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/learner.mjs +3 -12
  237. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/maintenance.mjs +17 -0
  238. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/mcp-server.mjs +228 -0
  239. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/process-manager.mjs +25 -2
  240. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/reasoning.mjs +1 -1
  241. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/remote-operation.mjs +5 -1
  242. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/review.mjs +34 -3
  243. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/reviews.mjs +25 -0
  244. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/router.mjs +1 -1
  245. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/session/claude.mjs +319 -0
  246. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/session/codex.mjs +387 -0
  247. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/session/result.mjs +67 -0
  248. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/session/resume.mjs +373 -0
  249. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/session/run.mjs +223 -0
  250. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/session-jobs.mjs +72 -0
  251. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/setup.mjs +6 -3
  252. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/termination.mjs +16 -12
  253. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/threads.mjs +32 -1
  254. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/usage-queue.mjs +1 -1
  255. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/verify-ssss.mjs +3 -3
  256. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/worker.mjs +285 -40
  257. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/worktree.mjs +76 -9
  258. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/adapter-docs-freshness.md +16 -0
  259. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/chat-handoff.md +26 -0
  260. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/fleet-maintenance.md +21 -0
  261. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/harness-inventory.md +21 -0
  262. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/included-access.md +18 -0
  263. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/included-usage-verification.md +15 -0
  264. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/independent-review.md +17 -0
  265. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/managed-execution.md +20 -0
  266. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/official-documentation.md +18 -0
  267. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/quota-recovery.md +21 -0
  268. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/review-routing-decision.md +16 -0
  269. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/route-work.md +18 -0
  270. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/routing-evidence.md +18 -0
  271. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/run-ledger.md +18 -0
  272. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/home.js +198 -0
  273. package/scaffold/.agent/skills/total-recall/plugins/openwiki/DESIGN.md +75 -0
  274. package/scaffold/.agent/skills/total-recall/plugins/openwiki/README.md +2 -0
  275. package/scaffold/.agent/skills/total-recall/plugins/openwiki/cli.mjs +64 -32
  276. package/scaffold/.agent/skills/total-recall/plugins/openwiki/package-lock.json +7 -7
  277. package/scaffold/.agent/skills/total-recall/plugins/openwiki/package.json +2 -1
  278. package/scaffold/.agent/skills/total-recall/plugins/openwiki/plugin.json +10 -44
  279. package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/generate.mjs +5 -4
  280. package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/graph.mjs +3 -4
  281. package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/ingest.mjs +23 -18
  282. package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/mesh-vaults.mjs +8 -3
  283. package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/refresh-diagnostics.mjs +44 -0
  284. package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/refresh.mjs +123 -113
  285. package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/search.mjs +3 -5
  286. package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/token.mjs +21 -47
  287. package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/upstream-watcher.mjs +17 -6
  288. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/auto-refresh.md +18 -0
  289. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/bootstrap-pages.md +18 -0
  290. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/generate-wiki.md +21 -0
  291. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/generator-settings.md +18 -0
  292. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/host-probe.md +18 -0
  293. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/ingest-preview.md +18 -0
  294. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/link-hygiene.md +21 -0
  295. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/link-topology.md +19 -0
  296. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/passage-search.md +19 -0
  297. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/propagation-plan.md +18 -0
  298. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/provider-credentials.md +18 -0
  299. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/refresh-report.md +18 -0
  300. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/task-evidence.md +22 -0
  301. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/upstream-record.md +18 -0
  302. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/watch-upstream.md +18 -0
  303. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/wiki-atlas.md +19 -0
  304. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/panel.js +261 -513
  305. package/scaffold/.agent/skills/total-recall/plugins/security/DESIGN.md +84 -0
  306. package/scaffold/.agent/skills/total-recall/plugins/security/README.md +4 -2
  307. package/scaffold/.agent/skills/total-recall/plugins/security/cli.mjs +7 -19
  308. package/scaffold/.agent/skills/total-recall/plugins/security/package-lock.json +7 -7
  309. package/scaffold/.agent/skills/total-recall/plugins/security/package.json +2 -3
  310. package/scaffold/.agent/skills/total-recall/plugins/security/plugin.json +19 -52
  311. package/scaffold/.agent/skills/total-recall/plugins/security/ui/chunks/device-evidence.md +21 -0
  312. package/scaffold/.agent/skills/total-recall/plugins/security/ui/chunks/evidence-desk.md +18 -0
  313. package/scaffold/.agent/skills/total-recall/plugins/security/ui/chunks/guided-device-review.md +17 -0
  314. package/scaffold/.agent/skills/total-recall/plugins/security/ui/chunks/host-and-network.md +21 -0
  315. package/scaffold/.agent/skills/total-recall/plugins/security/ui/chunks/https-headers.md +17 -0
  316. package/scaffold/.agent/skills/total-recall/plugins/security/ui/chunks/mesh-coverage.md +18 -0
  317. package/scaffold/.agent/skills/total-recall/plugins/security/ui/chunks/private-security-tools.md +16 -0
  318. package/scaffold/.agent/skills/total-recall/plugins/security/ui/chunks/single-origin-header-check.md +17 -0
  319. package/scaffold/.agent/skills/total-recall/plugins/security/ui/chunks/source-review.md +21 -0
  320. package/scaffold/.agent/skills/total-recall/plugins/security/ui/chunks/ssh-permission-plan.md +17 -0
  321. package/scaffold/.agent/skills/total-recall/plugins/security/ui/home.js +283 -0
  322. package/scaffold/.agent/skills/total-recall/plugins/ssss/DESIGN.md +93 -0
  323. package/scaffold/.agent/skills/total-recall/plugins/ssss/package-lock.json +2 -2
  324. package/scaffold/.agent/skills/total-recall/plugins/ssss/package.json +2 -1
  325. package/scaffold/.agent/skills/total-recall/plugins/ssss/plugin.json +5 -3
  326. package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/chunks/conformance.md +26 -0
  327. package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/chunks/registry.md +37 -0
  328. package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/chunks/repair.md +42 -0
  329. package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/chunks/scaffold.md +33 -0
  330. package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/chunks/status.md +43 -0
  331. package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/chunks/validate.md +34 -0
  332. package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/chunks/validation-diagnostics.md +17 -0
  333. package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/chunks/workspace-registry-preflight.md +17 -0
  334. package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/home.js +348 -0
  335. package/scaffold/.agent/skills/total-recall/references/operations.md +3 -1
  336. package/src/cli/agent.mjs +1 -1
  337. package/src/cli/api.mjs +3 -3
  338. package/src/cli/brief.mjs +3 -0
  339. package/src/cli/command.mjs +41 -2
  340. package/src/cli/config.mjs +16 -0
  341. package/src/cli/connect.mjs +2 -7
  342. package/src/cli/dream.mjs +93 -69
  343. package/src/cli/harness.mjs +4 -4
  344. package/src/cli/help.mjs +1 -1
  345. package/src/cli/init.mjs +0 -25
  346. package/src/cli/lessons.mjs +51 -0
  347. package/src/cli/memory-plugin.mjs +1 -1
  348. package/src/cli/plugin/chunks.mjs +145 -0
  349. package/src/cli/plugin/copies.mjs +64 -14
  350. package/src/cli/plugin/create.mjs +30 -59
  351. package/src/cli/plugin/index.mjs +31 -16
  352. package/src/cli/plugin/install.mjs +10 -15
  353. package/src/cli/plugin/remove.mjs +1 -1
  354. package/src/cli/plugin/search.mjs +2 -2
  355. package/src/cli/preflight.mjs +19 -6
  356. package/src/cli/proposals.mjs +1 -1
  357. package/src/cli/recall.mjs +66 -23
  358. package/src/cli/remember.mjs +3 -14
  359. package/src/cli/server.mjs +18 -0
  360. package/src/cli/setup.mjs +2 -9
  361. package/src/cli/start.mjs +1 -0
  362. package/src/cli/startup.mjs +19 -0
  363. package/src/cli/task.mjs +9 -2
  364. package/src/cli/update.mjs +6 -2
  365. package/src/core/access-ledger.mjs +78 -0
  366. package/src/core/agent-manager.mjs +2 -2
  367. package/src/core/app-deploy/design-tokens.mjs +14 -9
  368. package/src/core/app-deploy/ui-elements.mjs +1 -1
  369. package/src/core/brain-locate.mjs +15 -0
  370. package/src/core/brain-registry.mjs +5 -0
  371. package/src/core/brain-updates.mjs +35 -11
  372. package/src/core/claude-hooks.mjs +3 -1
  373. package/src/core/cleanup-task.mjs +15 -0
  374. package/src/core/cli-commands.mjs +2 -0
  375. package/src/core/cli-maintenance.mjs +4 -1
  376. package/src/core/cli-semantic-index.mjs +23 -3
  377. package/src/core/context-compiler.mjs +20 -0
  378. package/src/core/daemon-control.mjs +5 -1
  379. package/src/core/daemon-loop.mjs +39 -62
  380. package/src/core/dashboard-bundle.mjs +261 -0
  381. package/src/core/default-plugins.mjs +1 -1
  382. package/src/core/dream.mjs +33 -105
  383. package/src/core/ensure-dependencies.mjs +152 -0
  384. package/src/core/fast-recall.mjs +2 -2
  385. package/src/core/field-evaluation.mjs +23 -0
  386. package/src/core/gate-mode.mjs +1 -1
  387. package/src/core/harness-hooks.mjs +14 -2
  388. package/src/core/lesson-hooks.mjs +74 -0
  389. package/src/core/lesson-memory.mjs +24 -0
  390. package/src/core/lesson-sessions.mjs +52 -0
  391. package/src/core/lessons.mjs +96 -0
  392. package/src/core/memory-brain.mjs +30 -8
  393. package/src/core/meta-harness.mjs +2 -2
  394. package/src/core/optimizer.mjs +66 -165
  395. package/src/core/plugin-activation.mjs +63 -20
  396. package/src/core/plugin-contracts/{card.mjs → manifest.mjs} +26 -57
  397. package/src/core/plugin-contracts/startup-check.mjs +49 -0
  398. package/src/core/plugin-contracts/ui.mjs +9 -3
  399. package/src/core/plugin-distribution.mjs +6 -6
  400. package/src/core/plugin-lifecycle.mjs +58 -0
  401. package/src/core/plugin-loader.mjs +21 -8
  402. package/src/core/plugin-runner.mjs +21 -10
  403. package/src/core/plugin-runtime.mjs +40 -1
  404. package/src/core/plugin-startup-checks.mjs +44 -0
  405. package/src/core/plugin-state.mjs +19 -5
  406. package/src/core/plugin-store.mjs +64 -33
  407. package/src/core/post-mortem.mjs +52 -36
  408. package/src/core/preflight-gate.mjs +23 -2
  409. package/src/core/project-id.mjs +15 -5
  410. package/src/core/proposal-applier.mjs +31 -2
  411. package/src/core/repo-sync.mjs +4 -6
  412. package/src/core/required-plugins.mjs +57 -10
  413. package/src/core/rule-length.mjs +23 -0
  414. package/src/core/runtime.mjs +1 -1
  415. package/src/core/scheduler.mjs +35 -43
  416. package/src/core/schema.mjs +3 -2
  417. package/src/core/search.mjs +4 -3
  418. package/src/core/server-service.mjs +148 -0
  419. package/src/core/session-watcher.mjs +19 -1
  420. package/src/core/skill-gap.mjs +16 -0
  421. package/src/core/ssss-kernel-bridge.mjs +32 -4
  422. package/src/core/ssss-operation-service.mjs +1 -0
  423. package/src/core/startup-health.mjs +34 -4
  424. package/src/core/surface.mjs +65 -54
  425. package/src/core/task-executors.mjs +54 -106
  426. package/src/core/testing/plugin-fixture.mjs +22 -21
  427. package/src/core/throttled-fetch.mjs +25 -18
  428. package/src/core/ui-chunk-choice.mjs +77 -0
  429. package/src/core/ui-chunk.registry.json +23 -0
  430. package/src/core/ui-chunks.mjs +434 -0
  431. package/src/core/validated-write.mjs +1 -0
  432. package/src/core/vault-cache.mjs +58 -59
  433. package/src/core/vector-field.mjs +134 -192
  434. package/src/core/workspace-compositions.mjs +151 -0
  435. package/src/core/workspace-drawers.mjs +79 -0
  436. package/src/server/api.mjs +4 -27
  437. package/src/server/index.mjs +28 -21
  438. package/src/server/invoke-core-child.mjs +24 -0
  439. package/src/server/invoke-core-operations.mjs +102 -0
  440. package/src/server/memory-events.mjs +31 -0
  441. package/src/server/plugin-brain-targets.mjs +89 -0
  442. package/src/server/rest.mjs +2 -0
  443. package/src/server/route-inventory.mjs +3 -2
  444. package/src/server/route-manifest.json +47 -55
  445. package/src/server/routes/_shared.mjs +7 -14
  446. package/src/server/routes/brains.mjs +29 -62
  447. package/src/server/routes/context.mjs +0 -41
  448. package/src/server/routes/dashboard.mjs +26 -0
  449. package/src/server/routes/invoke.mjs +26 -1
  450. package/src/server/routes/plugins.mjs +154 -45
  451. package/src/server/routes/ssss.mjs +0 -169
  452. package/src/server/routes/system.mjs +0 -15
  453. package/src/server/routes/tasks.mjs +0 -26
  454. package/src/server/routes/ui-chunks.mjs +192 -0
  455. package/src/server/routes/vault.mjs +2 -23
  456. package/frontend/dist/assets/index-DD4qONvH.js +0 -5607
  457. package/frontend/dist/assets/index-DtwsDyFM.css +0 -1
  458. package/frontend/src/components/plugins/card/CardEngine.tsx +0 -108
  459. package/frontend/src/components/plugins/card/CardScenes.tsx +0 -103
  460. package/frontend/src/components/plugins/card/ExecutionPicker.tsx +0 -64
  461. package/frontend/src/components/plugins/card/args.ts +0 -28
  462. package/frontend/src/components/plugins/card/card.css +0 -32
  463. package/frontend/src/components/plugins/card/cli-line.ts +0 -13
  464. package/frontend/src/components/plugins/card/contract.ts +0 -91
  465. package/frontend/src/components/plugins/card/format.ts +0 -49
  466. package/frontend/src/components/plugins/card/runner-context.ts +0 -11
  467. package/frontend/src/components/plugins/card/runner.tsx +0 -43
  468. package/frontend/src/components/plugins/card/theme.ts +0 -35
  469. package/frontend/src/components/plugins/card/use-source.ts +0 -22
  470. package/frontend/src/components/plugins/card/widgets.tsx +0 -94
  471. package/frontend/src/components/plugins/workspace/WorkspaceHost.tsx +0 -23
  472. package/frontend/src/pages/PluginsPage.tsx +0 -1719
  473. package/scaffold/.agent/skills/plugin/evals/cases/04-card-collects-credential.mjs +0 -47
  474. package/scaffold/.agent/skills/plugin/prompts/06-card.md +0 -46
  475. package/scaffold/.agent/skills/plugin/references/card.md +0 -90
  476. package/scaffold/.agent/skills/plugin/subagents/card-designer.md +0 -60
  477. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/DESIGN.md +0 -67
  478. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/card.js +0 -1179
  479. package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/DESIGN.md +0 -32
  480. package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/card.js +0 -588
  481. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/card.js +0 -575
  482. package/scaffold/.agent/skills/total-recall/plugins/embeddings/ui/DESIGN.md +0 -32
  483. package/scaffold/.agent/skills/total-recall/plugins/embeddings/ui/card.js +0 -482
  484. package/scaffold/.agent/skills/total-recall/plugins/git-sentinel/README.md +0 -53
  485. package/scaffold/.agent/skills/total-recall/plugins/git-sentinel/plugin.json +0 -129
  486. package/scaffold/.agent/skills/total-recall/plugins/git-sentinel/ui/DESIGN.md +0 -100
  487. package/scaffold/.agent/skills/total-recall/plugins/git-sentinel/ui/card.js +0 -637
  488. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/DESIGN.md +0 -217
  489. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/DESIGN.md +0 -32
  490. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/card.js +0 -1276
  491. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/DESIGN.md +0 -45
  492. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/card.js +0 -1401
  493. package/scaffold/.agent/skills/total-recall/plugins/security/scripts/build-ui.mjs +0 -4
  494. package/scaffold/.agent/skills/total-recall/plugins/security/ui/DESIGN.md +0 -41
  495. package/scaffold/.agent/skills/total-recall/plugins/security/ui/card.js +0 -396
  496. package/scaffold/.agent/skills/total-recall/plugins/security/ui/panel.js +0 -98
  497. package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/DESIGN.md +0 -15
  498. package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/card.js +0 -182
  499. package/src/core/append-log.mjs +0 -131
  500. package/src/core/plugin-tasks.mjs +0 -173
  501. package/templates/onboarding-interview.md +0 -82
  502. /package/scaffold/.agent/skills/total-recall/plugins/{git-sentinel → git}/LICENSE +0 -0
@@ -1,4 +1,5 @@
1
1
  import path from 'node:path';
2
+ import { sessionOptions } from './session/run.mjs';
2
3
 
3
4
  const DEFAULT_PERMISSIONS = Object.freeze({ read: true, write: false, send: false, destructive: false });
4
5
  export { DEFAULT_PERMISSIONS };
@@ -14,11 +15,12 @@ export function commandPermissions(value = DEFAULT_PERMISSIONS) {
14
15
  const PUBLIC_FIELDS = [
15
16
  'agent', 'cwd', 'prompt', 'permissions', 'node', 'allowUnknownAuth', 'timeoutMs',
16
17
  'model', 'tools', 'settingSources', 'allowedTools',
18
+ 'goal', 'maxTurns', 'maxTokens', 'maxBudgetUsd', 'resultSchema', 'approvalPolicy', 'questionTimeoutMs', 'effort', 'fallbackModel', 'name',
17
19
  ];
18
20
 
19
21
  export function validateDispatchRequest(request) {
20
22
  if (!request || typeof request !== 'object' || Array.isArray(request)) throw new Error('Dispatch requires a JSON object');
21
- if (Object.keys(request).some(key => !PUBLIC_FIELDS.includes(key))) throw new Error('Unsupported dispatch field; workspace context and containment are managed by Meta Harness');
23
+ if (Object.keys(request).some(key => !PUBLIC_FIELDS.includes(key))) throw new Error('Unsupported dispatch field; workspace context and containment are managed by Metaharness');
22
24
  if (typeof request.agent !== 'string' || !/^[a-z][a-z0-9-]{0,63}$/.test(request.agent) ||
23
25
  typeof request.cwd !== 'string' || !path.isAbsolute(request.cwd) || request.cwd.includes('\0') ||
24
26
  typeof request.prompt !== 'string' || !request.prompt.trim() || Buffer.byteLength(request.prompt) > 65536) {
@@ -28,7 +30,7 @@ export function validateDispatchRequest(request) {
28
30
  if (request.allowUnknownAuth !== undefined && typeof request.allowUnknownAuth !== 'boolean') throw new Error('allowUnknownAuth must be a boolean');
29
31
  const timeoutMs = request.timeoutMs === undefined ? 300000 : request.timeoutMs;
30
32
  if (!Number.isInteger(timeoutMs) || timeoutMs < 1 || timeoutMs > 540000) throw new Error('Foreground dispatch timeout must be 1..540000 ms');
31
- return { ...request, permissions: commandPermissions(request.permissions), timeoutMs };
33
+ return { ...request, ...sessionOptions(request), permissions: commandPermissions(request.permissions), timeoutMs };
32
34
  }
33
35
 
34
36
  /** The installed destination starts from its own project context and decides containment itself. */
@@ -1,17 +1,20 @@
1
1
  /** One path for every agent run: contain it if needed, dispatch it, classify the outcome, write its receipt. */
2
2
  import { executeOnNode } from './executor.mjs';
3
- import { classifyFailure, INCLUDED_BILLING, READ_ONLY_ADAPTERS } from './worker.mjs';
3
+ import { classifyFailure, INCLUDED_BILLING, READ_ONLY_ADAPTERS, cancellationResult } from './worker.mjs';
4
4
  import { recordRunReceipt } from './learner.mjs';
5
- import { isGitRepo, createWorktree, removeWorktree } from './worktree.mjs';
5
+ import { isGitRepo, createWorktree, removeWorktree, commitAll, deleteBranch } from './worktree.mjs';
6
+ import { randomUUID } from 'node:crypto';
6
7
  import { includedAdmission, openRouterAdmission, readIncludedPolicy } from './included-usage.mjs';
7
8
  import { queueIncludedJob } from './usage-queue.mjs';
8
9
 
9
10
  export async function dispatchWithReceipt(request, { dispatchFn, node = request.node || 'local', role, complexityScore, escalatedFrom,
10
- record = recordRunReceipt, replay, retryId, usagePolicy = readIncludedPolicy, admit = includedAdmission, admitOpenRouter = openRouterAdmission } = {}) {
11
+ record = recordRunReceipt, replay, retryId, manageWrites = false, usagePolicy = readIncludedPolicy, admit = includedAdmission, admitOpenRouter = openRouterAdmission } = {}) {
11
12
  const started = Date.now();
13
+ if (cancellationResult()) return cancellationResult();
12
14
  // A harness that cannot be told not to write does read-only work in a checkout that is thrown away.
13
15
  const contain = node === 'local' && request.permissions?.write !== true && !READ_ONLY_ADAPTERS.includes(request.agent) && request.isolated !== true && isGitRepo(request.cwd);
14
- let scratch = null, result, billingMode = null, launchPrevented = false;
16
+ const ownWrites = manageWrites && node === 'local' && request.permissions?.write === true && isGitRepo(request.cwd);
17
+ let scratch = null, branch = null, result, billingMode = null, launchPrevented = false;
15
18
  try {
16
19
  let effective = request;
17
20
  const policy = await usagePolicy();
@@ -24,19 +27,32 @@ export async function dispatchWithReceipt(request, { dispatchFn, node = request.
24
27
  launchPrevented = true;
25
28
  } else effective = { ...request, [INCLUDED_BILLING]: { key: admission.key, claudePlan: admission.claudePlan, openRouter: admission.openRouter } };
26
29
  }
30
+ result = cancellationResult() || result;
27
31
  if (!result) {
28
- if (contain) {
29
- scratch = createWorktree(request.cwd, { prefix: 'meta-harness-readonly-' });
30
- effective = { ...effective, cwd: scratch, contextCwd: request.contextCwd || request.cwd, isolated: true };
32
+ if (contain || ownWrites) {
33
+ branch = ownWrites ? `meta-harness/dispatch-${randomUUID()}` : null;
34
+ scratch = createWorktree(request.cwd, { ...(branch ? { branch } : {}), prefix: ownWrites ? 'meta-harness-dispatch-' : 'meta-harness-readonly-' });
35
+ effective = { ...effective, ...(branch ? { branch } : {}), cwd: scratch, contextCwd: request.contextCwd || request.cwd, isolated: true };
31
36
  }
32
37
  result = dispatchFn ? await dispatchFn(effective) : await executeOnNode(node, { ...effective, operation: 'dispatch' });
38
+ if (cancellationResult()) result = { ...result, ...cancellationResult() };
33
39
  if (contain) result = { ...result, readOnly: 'disposable-checkout' };
34
40
  }
35
41
  } catch (error) {
36
42
  const message = String(error?.message || error);
37
43
  result = { ok: false, error: message, agent: request.agent, ...(error?.code === 'NOT_READY' ? { failureKind: 'not-ready' } : classifyFailure(message)) };
38
44
  } finally {
39
- if (scratch) removeWorktree(request.cwd, scratch);
45
+ if (scratch) {
46
+ try {
47
+ if (branch) {
48
+ const commit = commitAll(scratch, result?.cancelled ? 'meta-harness: unfinished cancelled dispatch' : 'meta-harness: dispatch changes');
49
+ if (commit) result = { ...result, branch, ...(result?.ok ? { commit } : { wip: commit }) };
50
+ else if (result?.sessionId) result = { ...result, branch };
51
+ else deleteBranch(request.cwd, branch);
52
+ }
53
+ } finally { removeWorktree(request.cwd, scratch); }
54
+ if (branch && !result?.branch) deleteBranch(request.cwd, branch);
55
+ }
40
56
  }
41
57
  const durationMs = Date.now() - started;
42
58
  if (result.execution?.receiptOwner === 'destination' && result.receiptId) return { ...result, durationMs };
@@ -52,7 +68,15 @@ export async function dispatchWithReceipt(request, { dispatchFn, node = request.
52
68
  }
53
69
  }
54
70
  }
55
- if (launchPrevented) return { ...result, launchPrevented, durationMs };
71
+ if (launchPrevented) {
72
+ // A launch refused for quota is a quota wall too (A-124): record it, so routing sees the harness as
73
+ // exhausted until its reset and picks another included harness instead of choosing it again.
74
+ if (result.failureKind === 'quota') {
75
+ try { await record({ harness: request.agent, role, task: String(request.contextTask || request.prompt || '').slice(0, 200), success: false,
76
+ failureKind: 'quota', error: result.error, resetsAt: result.resetsAt || null }); } catch { /* bookkeeping must not hide the refusal */ }
77
+ }
78
+ return { ...result, launchPrevented, durationMs };
79
+ }
56
80
  // A finished run keeps its result: the worktree and any cost are real even when bookkeeping fails.
57
81
  let receipt, receiptError;
58
82
  try {
@@ -3,7 +3,11 @@ import fs from 'node:fs';
3
3
  import path from 'node:path';
4
4
  import os from 'node:os';
5
5
  import crypto from 'node:crypto';
6
- import { loadCustomAdapters } from './worker.mjs';
6
+ import { execFile } from 'node:child_process';
7
+ import { promisify } from 'node:util';
8
+ import { agentEnvironment, loadCustomAdapters } from './worker.mjs';
9
+
10
+ const exec = promisify(execFile);
7
11
 
8
12
  export const DOC_SOURCES = [
9
13
  { id: 'claude', index: 'https://code.claude.com/docs/llms.txt', prefix: 'https://code.claude.com/docs/', catalog:true },
@@ -69,7 +73,7 @@ async function download(url, fetchImpl, declaredOrigin) {
69
73
  if (declaredOrigin) allowed.add(declaredOrigin);
70
74
  for(let redirects=0;redirects<5;redirects++) {
71
75
  if(target.protocol!=='https:' || target.username || target.password || !allowed.has(target.hostname)) throw new Error(`Unapproved official documentation origin: ${target.hostname}`);
72
- const response=await fetchImpl(target,{redirect:'manual',signal:AbortSignal.timeout(20000),headers:{'User-Agent':'Total-Recall-Meta-Harness-Docs','Accept':'*/*'}});
76
+ const response=await fetchImpl(target,{redirect:'manual',signal:AbortSignal.timeout(20000),headers:{'User-Agent':'Total-Recall-Metaharness-Docs','Accept':'*/*'}});
73
77
  if(response.status>=300 && response.status<400){target=new URL(response.headers.get('location'),target);continue;}
74
78
  // Some entries advertise Markdown exports which no longer exist while the
75
79
  // same official HTML document remains available. Fetch that representation.
@@ -91,7 +95,27 @@ function links(text,base,prefix) {
91
95
  return [...new Set(values.map(value=>{try{const url=new URL(value);url.hash='';url.search='';url.pathname=url.pathname.replace(/\/{2,}/g,'/').replace(/\/$/,'') || '/';return url.href;}catch{return '';}}))]
92
96
  .filter(url=>url.startsWith(prefix) && !/%3[CE]|[<>"'`\s]/i.test(url) && !/\.(png|jpg|jpeg|svg|gif|css|js|woff2?|ico|pdf|json|ya?ml|xml|zip|gz|tgz|lock)$/i.test(url));
93
97
  }
94
- export async function refreshDocumentation({ directory = documentationDirectory(), agent, fetchImpl = fetch, now = () => new Date(), maxPages = 1500 } = {}) {
98
+ async function gitDocumentationPaths(source) {
99
+ const checkout = fs.mkdtempSync(path.join(os.tmpdir(), 'meta-harness-doc-tree-'));
100
+ const options = {
101
+ cwd: checkout, timeout: 30000, maxBuffer: 4 * 1024 * 1024,
102
+ env: { ...agentEnvironment(), GIT_TERMINAL_PROMPT: '0', GIT_CONFIG_NOSYSTEM: '1', GIT_CONFIG_GLOBAL: os.devNull },
103
+ };
104
+ try {
105
+ await exec('git', ['-c', 'http.followRedirects=false', 'clone', '--quiet', '--filter=blob:none',
106
+ '--depth=1', '--single-branch', '--branch', source.branch, '--no-checkout',
107
+ '--', `https://github.com/${source.repo}.git`, checkout], options);
108
+ const { stdout } = await exec('git', ['ls-tree', '-r', '-z', 'HEAD', '--', ...source.directories], options);
109
+ return stdout.split('\0').flatMap(entry => {
110
+ const match = /^100(?:644|755) blob [a-f0-9]+\t([\s\S]+)$/.exec(entry);
111
+ return match ? [match[1]] : [];
112
+ });
113
+ } catch {
114
+ throw new Error(`Could not read the official documentation tree through Git for ${source.repo}`);
115
+ } finally { fs.rmSync(checkout, { recursive: true, force: true }); }
116
+ }
117
+
118
+ export async function refreshDocumentation({ directory = documentationDirectory(), agent, fetchImpl = fetch, now = () => new Date(), maxPages = 1500, readGitPaths = gitDocumentationPaths } = {}) {
95
119
  const sources=sourcesFor(agent);
96
120
  if(!sources.length)throw new Error('Unknown documentation adapter');
97
121
  const reports=[];
@@ -99,11 +123,27 @@ export async function refreshDocumentation({ directory = documentationDirectory(
99
123
  const previous=metadata(directory,source.id), pages=[], queue=[source.index], seen=new Set(), queued=new Set(queue), errors=[], discovered=new Set(), skipped=[];
100
124
  // `found` marks a link taken from HTML navigation. The vendor's catalog, the index and the repository tree are authoritative; a link found by scraping is not.
101
125
  const enqueue=(url,found=false)=>{if(!queued.has(url)){queued.add(url);queue.push(url);if(found)discovered.add(url);}};
126
+ let treeSource;
102
127
  try {
103
128
  if(source.repo) {
104
- const tree=JSON.parse(await download(`https://api.github.com/repos/${source.repo}/git/trees/${source.branch}?recursive=1`,fetchImpl));
105
- if(tree.truncated)throw new Error('Official repository documentation tree is truncated');
106
- for(const entry of tree.tree || [])if(entry.type==='blob' && /\.(md|mdx)$/i.test(entry.path) && source.directories.some(dir=>entry.path.startsWith(dir)))enqueue(`https://raw.githubusercontent.com/${source.repo}/${source.branch}/${entry.path}`);
129
+ let paths;
130
+ try {
131
+ const tree = JSON.parse(await download(`https://api.github.com/repos/${source.repo}/git/trees/${source.branch}?recursive=1`, fetchImpl));
132
+ if (tree.truncated) throw new Error('Official repository documentation tree is truncated');
133
+ if (!Array.isArray(tree.tree)) throw new Error('Invalid official repository documentation tree');
134
+ paths = tree.tree.filter(entry => entry.type === 'blob').map(entry => entry.path);
135
+ treeSource = 'github-rest';
136
+ } catch (error) {
137
+ if (!/^Documentation HTTP (403|429):|^Official repository documentation tree is truncated$/.test(error.message)) throw error;
138
+ paths = await readGitPaths(source);
139
+ treeSource = 'github-git';
140
+ }
141
+ for (const file of paths) {
142
+ if (!/\.(md|mdx)$/i.test(file) || !source.directories.some(dir => file.startsWith(dir))) continue;
143
+ const encoded = file.split('/').map(encodeURIComponent).join('/');
144
+ enqueue(`https://raw.githubusercontent.com/${source.repo}/${source.branch}/${encoded}`);
145
+ }
146
+ if (queue.length === 1) throw new Error('Official repository documentation tree contains no additional pages');
107
147
  }
108
148
  // Bounded batches; follow the official index/navigation to cover agent features.
109
149
  while(queue.length) {
@@ -138,7 +178,7 @@ export async function refreshDocumentation({ directory = documentationDirectory(
138
178
  reports.push({id:source.id,ok:false,error,pages:preserved.pages?.length || 0,downloadedPages:pages.length,failedCount:errors.length,failures:errors,...(skipped.length?{skippedCount:skipped.length,skipped}:{})});continue;
139
179
  }
140
180
  atomic(path.join(directory,source.id,'index.json'),JSON.stringify({id:source.id,complete:true,checkedAt,lastAttempt:checkedAt,pages,...(skipped.length?{skipped}:{})},null,2));
141
- reports.push({id:source.id,ok:true,pages:pages.length,...(skipped.length?{skippedCount:skipped.length,skipped}:{})});
181
+ reports.push({id:source.id,ok:true,pages:pages.length,...(treeSource?{treeSource}:{}),...(skipped.length?{skippedCount:skipped.length,skipped}:{})});
142
182
  } catch(error) {
143
183
  atomic(path.join(directory,source.id,'index.json'),JSON.stringify({...previous,id:source.id,lastAttempt:now().toISOString(),error:error.message},null,2));
144
184
  reports.push({id:source.id,ok:false,error:error.message,pages:previous?.pages?.length || 0});
@@ -156,11 +196,15 @@ export async function ensureDocumentation(options={}) {
156
196
 
157
197
  export async function maintainDocumentation(options={}) {
158
198
  const status=documentationStatus(options);
159
- const next=status.agents.filter(row=>!row.fresh).sort((a,b)=>String(a.lastAttempt || '').localeCompare(String(b.lastAttempt || '')))[0];
160
- if(!next)return {...status,scope:'all-agent-documentation-current'};
161
- const refreshed=await refreshDocumentation({...options,agent:next.id});
199
+ const pending=status.agents.filter(row=>!row.fresh).sort((a,b)=>String(a.lastAttempt || '').localeCompare(String(b.lastAttempt || '')));
200
+ const reports=[];
201
+ // Missing documentation for one harness must not prevent attempts for the others.
202
+ for(const row of pending) {
203
+ try { reports.push(...(await refreshDocumentation({...options,agent:row.id})).agents); }
204
+ catch(error) { reports.push({id:row.id,ok:false,error:error.message}); }
205
+ }
162
206
  const current=documentationStatus(options);
163
- return {...refreshed,scope:'one-stale-agent-refreshed',coverage_complete:current.ok,pending:current.agents.filter(row=>!row.fresh).map(row=>row.id)};
207
+ return {...current,ok:current.ok && reports.every(row=>row.ok),scope:'all-agent-documentation',refresh:reports,coverage_complete:current.ok,pending:current.agents.filter(row=>!row.fresh).map(row=>row.id)};
164
208
  }
165
209
 
166
210
  export function readDocumentation({agent,url,directory=documentationDirectory()}) {
@@ -34,15 +34,35 @@ export async function listTargets() {
34
34
  }
35
35
 
36
36
  export function workerProgram(request) {
37
- const source = fs.readFileSync(new URL('./worker.mjs', import.meta.url), 'utf8');
38
- return source + '\nrunWorker(' + JSON.stringify(request) + ').then(result=>console.log(JSON.stringify(result))).catch(error=>{console.error(String(error?.message||"Selected agent worker failed"));process.exitCode=1;});\n';
37
+ // Materialize a portable module graph. The stdin launcher imports only Node
38
+ // built-ins. Relative imports resolve inside this owned bundle on the node.
39
+ const names = ['worker.mjs', 'control.mjs', 'jobs.mjs', 'paths.mjs', 'mcp-server.mjs',
40
+ ...fs.readdirSync(new URL('./session/', import.meta.url)).filter(name => name.endsWith('.mjs')).map(name => `session/${name}`)];
41
+ const files = Object.fromEntries(names.map(name => [name, fs.readFileSync(new URL(name, import.meta.url), 'utf8')]));
42
+ return `import fs from 'node:fs';
43
+ import os from 'node:os';
44
+ import path from 'node:path';
45
+ import { pathToFileURL } from 'node:url';
46
+ const directory = fs.mkdtempSync(path.join(os.tmpdir(), 'metaharness-worker-'));
47
+ try {
48
+ for (const [name, source] of Object.entries(${JSON.stringify(files)})) {
49
+ const file = path.join(directory, name);
50
+ fs.mkdirSync(path.dirname(file), { recursive: true });
51
+ fs.writeFileSync(file, source, { mode: 0o600 });
52
+ }
53
+ const { runWorker } = await import(pathToFileURL(path.join(directory, 'worker.mjs')).href);
54
+ console.log(JSON.stringify(await runWorker(${JSON.stringify(request)})));
55
+ } catch (error) { console.error(String(error?.message || 'Selected agent worker failed')); process.exitCode = 1; }
56
+ finally { fs.rmSync(directory, { recursive: true, force: true }); }
57
+ `;
58
+
39
59
  }
40
60
 
41
61
  function destinationDispatchResult(result, node, request) {
42
62
  let payload;
43
63
  try { payload = JSON.parse(result.output); } catch { /* No structured result from the installed owner. */ }
44
64
  if (!payload || typeof payload.ok !== 'boolean' || (payload.ok && !result.ok)) {
45
- throw notReady(`Installed Meta Harness on ${node} returned no valid dispatch outcome (exit ${result.exitCode ?? 'unknown'})`);
65
+ throw notReady(`Installed Metaharness on ${node} returned no valid dispatch outcome (exit ${result.exitCode ?? 'unknown'})`);
46
66
  }
47
67
  return { ...payload, execution: { node, workspace: request.cwd, remote: true,
48
68
  ...(typeof payload.receiptId === 'string' ? { receiptOwner: 'destination' } : {}) } };
@@ -60,7 +80,9 @@ export async function executeOnNode(node, request, { worker = runWorker, process
60
80
  if (dispatch) {
61
81
  const input = JSON.stringify(destinationDispatchRequest(request));
62
82
  if (Buffer.byteLength(input) > 65536) throw new Error('Remote dispatch request is too large');
63
- transport = { operation: 'direct', cwd: request.cwd, argv: ['total-recall', 'meta-harness', 'dispatch', '--stdin', '--json'], input, timeoutMs: 600000 };
83
+ // The transport outlives the attempt it carries by a minute, so the destination reports its own timeout (A-101).
84
+ transport = { operation: 'direct', cwd: request.cwd, argv: ['total-recall', 'meta-harness', 'dispatch', '--stdin', '--json'], input,
85
+ timeoutMs: Number.isInteger(request.timeoutMs) && request.timeoutMs > 0 ? request.timeoutMs + 60_000 : 600000 };
64
86
  }
65
87
  const managed = dispatch || (transport.argv?.[1] === 'meta-harness' &&
66
88
  ['route', 'coordinate', 'review', 'process', 'run-command', 'usage-retry'].includes(transport.argv[2]));
@@ -27,6 +27,32 @@ function withGate(text) {
27
27
  return `${text.replace(/\n*$/, text ? '\n' : '')}\nhooks:\n pre_tool_call:\n${entry}`;
28
28
  }
29
29
 
30
+ /**
31
+ * Remove every hook list item whose command runs the gate. Other tools rewrite config.yaml (the
32
+ * lesson hooks re-serialize it), so the item is found by indentation, not by its exact text: the
33
+ * item runs from its `- ` line to the next line indented no deeper than that dash.
34
+ */
35
+ export function withoutGate(text) {
36
+ if (!text.includes(GATE)) return text;
37
+ const exact = text.replace(ENTRY_LINES, '');
38
+ if (!exact.includes(GATE)) return exact;
39
+ let lines = text.split('\n');
40
+ const indent = (line) => line.match(/^ */)[0].length;
41
+ for (let guard = 0; guard < 50; guard++) {
42
+ const hit = lines.findIndex((line) => line.includes(GATE));
43
+ if (hit < 0) break;
44
+ let start = hit;
45
+ while (start >= 0 && !/^ *- /.test(lines[start])) start--;
46
+ if (start < 0 || indent(lines[start]) > indent(lines[hit])) break;
47
+ const dash = indent(lines[start]);
48
+ let end = start + 1;
49
+ while (end < lines.length && (lines[end].trim() === '' || indent(lines[end]) > dash)) end++;
50
+ while (end > start + 1 && lines[end - 1].trim() === '') end--;
51
+ lines = [...lines.slice(0, start), ...lines.slice(end)];
52
+ }
53
+ return lines.join('\n');
54
+ }
55
+
30
56
  export const hermesAdapter = {
31
57
  id: 'hermes',
32
58
  level: 'enforced',
@@ -118,7 +144,9 @@ export const hermesAdapter = {
118
144
  const present = text.includes(GATE);
119
145
  if (remove || off) {
120
146
  if (present) {
121
- if (!dryRun) fs.writeFileSync(configPath, text.replace(ENTRY_LINES, ''));
147
+ const next = withoutGate(text);
148
+ if (next.includes(GATE)) throw new Error(`could not remove the gate from ${configPath}; remove the pre_tool_call entry that runs "${GATE}" by hand`);
149
+ if (!dryRun) fs.writeFileSync(configPath, next);
122
150
  removed.push('managed pre_tool_call gate');
123
151
  }
124
152
  return { settings: configPath, added, removed };
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Gate Adapters registry for Meta Harness (tr-plugin-cli-agents).
2
+ * Gate Adapters registry for Metaharness (tr-plugin-cli-agents).
3
3
  * Provides harness-specific parsing, emission, installation and verification.
4
4
  */
5
5
  import { claudeAdapter } from './claude.mjs';
@@ -195,7 +195,7 @@ export function queryCodexAccount(cwd, { env = process.env, timeoutMs = 10000 }
195
195
  child.kill('SIGTERM');
196
196
  }
197
197
  });
198
- send({ id: 1, method: 'initialize', params: { clientInfo: { name: 'meta_harness', title: 'Meta Harness', version: '1' } } });
198
+ send({ id: 1, method: 'initialize', params: { clientInfo: { name: 'meta_harness', title: 'Metaharness', version: '1' } } });
199
199
  });
200
200
  }
201
201
 
@@ -0,0 +1,84 @@
1
+ /** Local job identity and cancellation. A terminal log result is the completion record. */
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+ import { randomUUID } from 'node:crypto';
5
+ import { configDir } from './paths.mjs';
6
+ import { createProgress } from './worker.mjs';
7
+
8
+ const jobsDir = () => path.join(configDir(), 'jobs');
9
+ export const newJobId = () => `${Date.now().toString(36)}-${randomUUID().slice(0, 8)}`;
10
+
11
+ export function startJob(operation, { id = newJobId() } = {}) {
12
+ if (!/^[a-z0-9-]+$/.test(id)) throw new Error('Invalid job ID.');
13
+ const directory = jobsDir();
14
+ fs.mkdirSync(directory, { recursive: true, mode: 0o700 });
15
+ const log = path.join(directory, `${id}.log`);
16
+ const pidFile = path.join(directory, `${id}.pid`);
17
+ const record = { job: id, pid: process.pid, operation, startedAt: new Date().toISOString() };
18
+ fs.appendFileSync(log, `${JSON.stringify(record)}\n`, { mode: 0o600 });
19
+ fs.writeFileSync(pidFile, `${process.pid}\n`, { mode: 0o600, flag: 'wx' });
20
+ const progress = createProgress({ file: path.join(directory, `${id}.events.jsonl`), harness: operation });
21
+ return { ...record, log, finish(result) {
22
+ progress.close(result);
23
+ fs.appendFileSync(log, `${JSON.stringify(result)}\n`, { mode: 0o600 });
24
+ fs.rmSync(pidFile, { force: true });
25
+ } };
26
+ }
27
+
28
+ function readJob(log) {
29
+ const lines = fs.readFileSync(log, 'utf8').trim().split('\n');
30
+ let record;
31
+ try { record = JSON.parse(lines[0]); } catch { /* old log without PID */ }
32
+ let result = null;
33
+ for (const line of lines.slice(1).reverse()) {
34
+ try {
35
+ const value = JSON.parse(line);
36
+ if (typeof value.ok === 'boolean') { result = value; break; }
37
+ } catch { /* progress text */ }
38
+ }
39
+ return { record, result };
40
+ }
41
+
42
+ export function resolveJob(target) {
43
+ if (!target) throw new Error('cancel requires a job ID or log path.');
44
+ const directory = jobsDir();
45
+ const prefix = path.basename(target).replace(/\.(?:log|pid|events\.jsonl|status\.json)$/, '');
46
+ const files = fs.existsSync(directory) ? fs.readdirSync(directory) : [];
47
+ let names = files.filter(name => name.endsWith('.log') && name.startsWith(prefix));
48
+ if (!names.length) {
49
+ // An attempt ID from watch resolves to its owning job, never directly to a PID.
50
+ const events = files.filter(name => name.endsWith('.events.jsonl') && name.startsWith(prefix))
51
+ .sort((a, b) => fs.statSync(path.join(directory, b)).mtimeMs - fs.statSync(path.join(directory, a)).mtimeMs);
52
+ let pid;
53
+ try { pid = JSON.parse(fs.readFileSync(path.join(directory, events[0].replace('.events.jsonl', '.status.json')), 'utf8')).pid; } catch { /* no matching status */ }
54
+ if (pid) names = files.filter(name => name.endsWith('.log') && readJob(path.join(directory, name)).record?.pid === pid);
55
+ }
56
+ const exact = names.find(name => name === `${prefix}.log`);
57
+ if (!names.length) throw new Error(`No job log matches ${target}.`);
58
+ if (!exact && names.length > 1) throw new Error(`More than one job matches ${target}. Use a longer job ID.`);
59
+ const log = path.join(directory, exact || names[0]);
60
+ return { id: path.basename(log, '.log'), log, ...readJob(log) };
61
+ }
62
+
63
+ export async function cancelJob(target, { timeoutMs = 60_000, pollMs = 100 } = {}) {
64
+ const job = resolveJob(target);
65
+ if (job.result) throw new Error(`Job ${job.id} has finished${job.result.cancelled ? ' (cancelled)' : ''}.`);
66
+ const pidFile = path.join(jobsDir(), `${job.id}.pid`);
67
+ let pid;
68
+ try { pid = Number(fs.readFileSync(pidFile, 'utf8').trim()); } catch { /* stale or old job */ }
69
+ if (!Number.isSafeInteger(pid) || pid <= 1 || job.record?.pid !== pid || job.record?.job !== job.id) {
70
+ throw new Error(`Job ${job.id} has no active PID record.`);
71
+ }
72
+ try { process.kill(pid, 'SIGTERM'); }
73
+ catch (error) { throw new Error(`Cannot cancel job ${job.id}: ${error.code === 'ESRCH' ? 'the process has stopped' : error.message}.`); }
74
+ const deadline = Date.now() + Math.min(timeoutMs, 60_000);
75
+ do {
76
+ const { result } = readJob(job.log);
77
+ if (result) {
78
+ if (!result.cancelled) throw new Error(`Job ${job.id} finished before it could be cancelled.`);
79
+ return { ...result, job: job.id, log: job.log };
80
+ }
81
+ await new Promise(resolve => setTimeout(resolve, pollMs));
82
+ } while (Date.now() < deadline);
83
+ throw new Error(`Job ${job.id} did not report cancellation within ${Math.min(timeoutMs, 60_000) / 1000} seconds. Log: ${job.log}`);
84
+ }
@@ -2,7 +2,6 @@
2
2
  * Execution receipts and the learning loop.
3
3
  * Receipts are an append-only SSSS ledger. Scorecards, quota walls and proposals fold from it.
4
4
  */
5
- import { spawnSync } from 'node:child_process';
6
5
  import { computeEmpiricalScorecard } from '../capability/index.mjs';
7
6
  import { receiptsFile } from './paths.mjs';
8
7
  import { classifyFailure } from './worker.mjs';
@@ -105,18 +104,10 @@ export function activeCredentialBlocks(entries = [], now = Date.now(), holdMs =
105
104
  return blocks;
106
105
  }
107
106
 
108
- /** With `emit`, proposals are written through the memory owner. A failed write is reported, never hidden. */
109
- export async function learnFromHistory({ emit = false, runner = spawnSync } = {}) {
107
+ /** Read the same receipts the router uses. Proposals stay in this report. */
108
+ export async function learnFromHistory() {
110
109
  const entries = await readReceipts();
111
110
  const scorecard = computeEmpiricalScorecard(entries);
112
111
  const proposals = proposalsFrom(scorecard, entries);
113
- const emitted = [];
114
- if (emit) for (const proposal of proposals) {
115
- const result = runner(process.env.TOTAL_RECALL_BIN || 'total-recall', ['remember', 'fact', `${proposal.reason} ${proposal.recommendation}`, '--project', '--slug', proposal.id, '--tags', `meta-harness,${proposal.id}`], { encoding: 'utf8', timeout: 30000 });
116
- const output = `${result.stdout || ''}\n${result.stderr || ''}`;
117
- // The slug is the proposal's identity, so an open proposal is reported once, however often learn runs.
118
- const existing = result.status !== 0 && /already exists/i.test(output);
119
- emitted.push({ id: proposal.id, ok: result.status === 0 || existing, ...(existing ? { existing: true } : {}), error: result.status === 0 || existing ? undefined : String(result.stderr || result.error || 'remember failed').slice(0, 300) });
120
- }
121
- return { ok: emitted.every(row => row.ok), totalHistoryRuns: entries.length, scorecard, walls: activeQuotaWalls(entries), credentialBlocks: activeCredentialBlocks(entries), proposals, ...(emit ? { emitted } : {}) };
112
+ return { ok: true, totalHistoryRuns: entries.length, scorecard, walls: activeQuotaWalls(entries), credentialBlocks: activeCredentialBlocks(entries), proposals };
122
113
  }
@@ -0,0 +1,17 @@
1
+ /** Run each maintenance owner even when another owner fails. The daemon records the result. */
2
+ import { setupIntegrations } from './setup.mjs';
3
+ import { maintainDocumentation } from './documentation.mjs';
4
+
5
+ export async function maintainIntegrations(options = {}, owners = {}) {
6
+ const steps = {
7
+ setup: owners.setup || (() => setupIntegrations()),
8
+ gates: owners.gates || (async () => (await import('./gate-adapters/index.mjs')).installAll()),
9
+ docs: owners.docs || (() => maintainDocumentation(options)),
10
+ };
11
+ const result = {};
12
+ for (const [name, execute] of Object.entries(steps)) {
13
+ try { result[name] = await execute(); }
14
+ catch (error) { result[name] = { ok: false, error: error.message }; }
15
+ }
16
+ return { ...result, ok: Object.values(result).every(step => step?.ok === true) };
17
+ }