total-recall-brain 3.44.0 → 3.45.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 (212) hide show
  1. package/bin/total-recall.mjs +6 -4
  2. package/docs/ARCHITECTURE.md +10 -7
  3. package/docs/reference/cli-reference.md +13 -8
  4. package/frontend/dist/assets/index-DACh1dhx.js +5613 -0
  5. package/frontend/dist/index.html +1 -1
  6. package/frontend/src/App.tsx +2 -2
  7. package/frontend/src/pages/PluginsPage.tsx +1 -1
  8. package/package.json +1 -1
  9. package/scaffold/.agent/skills/total-recall/plugins/auth/package-lock.json +7 -7
  10. package/scaffold/.agent/skills/total-recall/plugins/auth/package.json +1 -1
  11. package/scaffold/.agent/skills/total-recall/plugins/auth/plugin.json +1 -1
  12. package/scaffold/.agent/skills/total-recall/plugins/auth/src/cli-secret.mjs +20 -1
  13. package/scaffold/.agent/skills/total-recall/plugins/auth/src/secrets-store.mjs +12 -1
  14. package/scaffold/.agent/skills/total-recall/plugins/automations/BRICK.md +7 -0
  15. package/scaffold/.agent/skills/total-recall/plugins/automations/LICENSE +21 -0
  16. package/scaffold/.agent/skills/total-recall/plugins/automations/README.md +66 -0
  17. package/scaffold/.agent/skills/total-recall/plugins/automations/adapters.mjs +231 -0
  18. package/scaffold/.agent/skills/total-recall/plugins/automations/capability/index.mjs +16 -0
  19. package/scaffold/.agent/skills/total-recall/plugins/automations/cli.mjs +121 -0
  20. package/{src/core/plugin-cron.mjs → scaffold/.agent/skills/total-recall/plugins/automations/cron.mjs} +1 -3
  21. package/scaffold/.agent/skills/total-recall/plugins/automations/inventory.mjs +88 -0
  22. package/scaffold/.agent/skills/total-recall/plugins/automations/package-lock.json +7661 -0
  23. package/scaffold/.agent/skills/total-recall/plugins/automations/package.json +35 -0
  24. package/scaffold/.agent/skills/total-recall/plugins/automations/plugin.json +167 -0
  25. package/scaffold/.agent/skills/total-recall/plugins/automations/scheduler.mjs +246 -0
  26. package/scaffold/.agent/skills/total-recall/plugins/automations/ui/DESIGN.md +42 -0
  27. package/scaffold/.agent/skills/total-recall/plugins/automations/ui/automations.js +2 -0
  28. package/scaffold/.agent/skills/total-recall/plugins/automations/ui/card.js +273 -0
  29. package/scaffold/.agent/skills/total-recall/plugins/code-quality/commands/run-core.mjs +1 -1
  30. package/scaffold/.agent/skills/total-recall/plugins/code-quality/core/check.mjs +57 -5
  31. package/scaffold/.agent/skills/total-recall/plugins/code-quality/core/report-data.mjs +40 -14
  32. package/scaffold/.agent/skills/total-recall/plugins/code-quality/core/report.mjs +15 -40
  33. package/scaffold/.agent/skills/total-recall/plugins/code-quality/package-lock.json +7 -7
  34. package/scaffold/.agent/skills/total-recall/plugins/code-quality/package.json +1 -1
  35. package/scaffold/.agent/skills/total-recall/plugins/code-quality/plugin.json +1 -1
  36. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/package-lock.json +7 -7
  37. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/package.json +1 -1
  38. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/plugin.json +1 -1
  39. package/scaffold/.agent/skills/total-recall/plugins/embeddings/package-lock.json +7 -7
  40. package/scaffold/.agent/skills/total-recall/plugins/embeddings/package.json +1 -1
  41. package/scaffold/.agent/skills/total-recall/plugins/embeddings/plugin.json +1 -1
  42. package/scaffold/.agent/skills/total-recall/plugins/git/README.md +112 -0
  43. package/scaffold/.agent/skills/total-recall/plugins/{git-sentinel → git}/cli.mjs +135 -23
  44. package/scaffold/.agent/skills/total-recall/plugins/{git-sentinel → git}/package-lock.json +7 -7
  45. package/scaffold/.agent/skills/total-recall/plugins/{git-sentinel → git}/package.json +2 -1
  46. package/scaffold/.agent/skills/total-recall/plugins/git/plugin.json +161 -0
  47. package/scaffold/.agent/skills/total-recall/plugins/git/src/lib/context.mjs +94 -0
  48. package/scaffold/.agent/skills/total-recall/plugins/git/src/lib/phase3-spec-support.mjs +50 -0
  49. package/scaffold/.agent/skills/total-recall/plugins/git/src/lib/runtime.mjs +40 -0
  50. package/scaffold/.agent/skills/total-recall/plugins/git/src/lib/spec-support.mjs +51 -0
  51. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/_support.mjs +195 -0
  52. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/auth.mjs +201 -0
  53. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/bisect.mjs +40 -0
  54. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/cli-meta.mjs +159 -0
  55. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/commit-memory.mjs +30 -0
  56. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/commit.mjs +46 -0
  57. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/fleet.mjs +156 -0
  58. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/force-push.mjs +58 -0
  59. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/group.mjs +119 -0
  60. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/handoff.mjs +59 -0
  61. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/message.mjs +22 -0
  62. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/resolve.mjs +60 -0
  63. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/rules.mjs +81 -0
  64. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/secret-firewall.mjs +66 -0
  65. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/undo.mjs +132 -0
  66. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/why.mjs +16 -0
  67. package/scaffold/.agent/skills/total-recall/plugins/{git-sentinel → git}/ui/card.js +2 -2
  68. package/scaffold/.agent/skills/total-recall/plugins/mesh/package-lock.json +7 -7
  69. package/scaffold/.agent/skills/total-recall/plugins/mesh/package.json +1 -1
  70. package/scaffold/.agent/skills/total-recall/plugins/mesh/plugin.json +1 -1
  71. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/README.md +25 -9
  72. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/capability/BRICK.md +1 -1
  73. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/capability/index.mjs +18 -6
  74. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/cli.mjs +124 -24
  75. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/package-lock.json +7 -7
  76. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/package.json +2 -2
  77. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/plugin.json +147 -14
  78. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/skills/meta-harness/SKILL.md +17 -3
  79. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/adoption.mjs +2 -2
  80. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/alerts.mjs +3 -3
  81. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/cascade.mjs +92 -18
  82. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/control.mjs +145 -0
  83. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/coordinator.mjs +42 -21
  84. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/dispatch-request.mjs +4 -2
  85. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/dispatch.mjs +33 -9
  86. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/documentation.mjs +55 -11
  87. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/executor.mjs +26 -4
  88. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/gate-adapters/hermes.mjs +29 -1
  89. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/gate-adapters/index.mjs +1 -1
  90. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/included-usage.mjs +1 -1
  91. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/jobs.mjs +84 -0
  92. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/learner.mjs +3 -12
  93. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/maintenance.mjs +17 -0
  94. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/mcp-server.mjs +228 -0
  95. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/process-manager.mjs +25 -2
  96. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/reasoning.mjs +1 -1
  97. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/remote-operation.mjs +5 -1
  98. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/review.mjs +34 -3
  99. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/reviews.mjs +25 -0
  100. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/router.mjs +1 -1
  101. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/session/claude.mjs +319 -0
  102. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/session/codex.mjs +387 -0
  103. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/session/result.mjs +67 -0
  104. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/session/resume.mjs +373 -0
  105. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/session/run.mjs +223 -0
  106. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/session-jobs.mjs +72 -0
  107. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/setup.mjs +6 -3
  108. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/termination.mjs +16 -12
  109. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/threads.mjs +32 -1
  110. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/usage-queue.mjs +1 -1
  111. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/verify-ssss.mjs +3 -3
  112. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/worker.mjs +285 -40
  113. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/worktree.mjs +76 -9
  114. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/DESIGN.md +5 -5
  115. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/card.js +3 -3
  116. package/scaffold/.agent/skills/total-recall/plugins/openwiki/cli.mjs +47 -18
  117. package/scaffold/.agent/skills/total-recall/plugins/openwiki/package-lock.json +7 -7
  118. package/scaffold/.agent/skills/total-recall/plugins/openwiki/package.json +1 -1
  119. package/scaffold/.agent/skills/total-recall/plugins/openwiki/plugin.json +1 -1
  120. package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/refresh-diagnostics.mjs +44 -0
  121. package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/refresh.mjs +120 -113
  122. package/scaffold/.agent/skills/total-recall/plugins/security/package-lock.json +7 -7
  123. package/scaffold/.agent/skills/total-recall/plugins/security/package.json +1 -1
  124. package/scaffold/.agent/skills/total-recall/plugins/security/plugin.json +1 -1
  125. package/scaffold/.agent/skills/total-recall/references/operations.md +1 -1
  126. package/src/cli/agent.mjs +1 -1
  127. package/src/cli/command.mjs +41 -2
  128. package/src/cli/dream.mjs +93 -69
  129. package/src/cli/harness.mjs +4 -4
  130. package/src/cli/help.mjs +1 -1
  131. package/src/cli/init.mjs +0 -25
  132. package/src/cli/lessons.mjs +51 -0
  133. package/src/cli/memory-plugin.mjs +1 -1
  134. package/src/cli/plugin/copies.mjs +64 -14
  135. package/src/cli/plugin/create.mjs +6 -7
  136. package/src/cli/plugin/index.mjs +11 -7
  137. package/src/cli/plugin/install.mjs +10 -15
  138. package/src/cli/plugin/remove.mjs +1 -1
  139. package/src/cli/plugin/search.mjs +2 -2
  140. package/src/cli/preflight.mjs +19 -6
  141. package/src/cli/proposals.mjs +1 -1
  142. package/src/cli/recall.mjs +66 -23
  143. package/src/cli/remember.mjs +3 -14
  144. package/src/cli/server.mjs +18 -0
  145. package/src/cli/startup.mjs +1 -0
  146. package/src/cli/task.mjs +9 -2
  147. package/src/cli/update.mjs +6 -2
  148. package/src/core/access-ledger.mjs +78 -0
  149. package/src/core/agent-manager.mjs +2 -2
  150. package/src/core/brain-locate.mjs +15 -0
  151. package/src/core/brain-updates.mjs +31 -11
  152. package/src/core/claude-hooks.mjs +3 -1
  153. package/src/core/cleanup-task.mjs +15 -0
  154. package/src/core/cli-commands.mjs +2 -0
  155. package/src/core/cli-maintenance.mjs +4 -1
  156. package/src/core/cli-semantic-index.mjs +23 -3
  157. package/src/core/context-compiler.mjs +20 -0
  158. package/src/core/daemon-loop.mjs +39 -62
  159. package/src/core/default-plugins.mjs +1 -1
  160. package/src/core/dream.mjs +33 -105
  161. package/src/core/ensure-dependencies.mjs +148 -0
  162. package/src/core/fast-recall.mjs +2 -2
  163. package/src/core/field-evaluation.mjs +23 -0
  164. package/src/core/gate-mode.mjs +1 -1
  165. package/src/core/harness-hooks.mjs +14 -2
  166. package/src/core/lesson-hooks.mjs +74 -0
  167. package/src/core/lesson-memory.mjs +24 -0
  168. package/src/core/lesson-sessions.mjs +52 -0
  169. package/src/core/lessons.mjs +96 -0
  170. package/src/core/meta-harness.mjs +2 -2
  171. package/src/core/optimizer.mjs +66 -165
  172. package/src/core/plugin-contracts/card.mjs +3 -0
  173. package/src/core/plugin-loader.mjs +12 -3
  174. package/src/core/plugin-runtime.mjs +40 -1
  175. package/src/core/plugin-store.mjs +35 -23
  176. package/src/core/post-mortem.mjs +52 -36
  177. package/src/core/preflight-gate.mjs +23 -2
  178. package/src/core/proposal-applier.mjs +31 -2
  179. package/src/core/repo-sync.mjs +4 -6
  180. package/src/core/required-plugins.mjs +26 -4
  181. package/src/core/rule-length.mjs +23 -0
  182. package/src/core/runtime.mjs +1 -1
  183. package/src/core/scheduler.mjs +35 -43
  184. package/src/core/schema.mjs +1 -2
  185. package/src/core/search.mjs +4 -3
  186. package/src/core/server-service.mjs +148 -0
  187. package/src/core/session-watcher.mjs +19 -1
  188. package/src/core/skill-gap.mjs +16 -0
  189. package/src/core/ssss-kernel-bridge.mjs +32 -4
  190. package/src/core/startup-health.mjs +6 -1
  191. package/src/core/surface.mjs +65 -54
  192. package/src/core/task-executors.mjs +54 -106
  193. package/src/core/validated-write.mjs +1 -0
  194. package/src/core/vector-field.mjs +134 -192
  195. package/src/server/invoke-core-child.mjs +24 -0
  196. package/src/server/invoke-core-operations.mjs +102 -0
  197. package/src/server/route-manifest.json +0 -56
  198. package/src/server/routes/brains.mjs +0 -18
  199. package/src/server/routes/context.mjs +0 -41
  200. package/src/server/routes/invoke.mjs +26 -1
  201. package/src/server/routes/ssss.mjs +0 -169
  202. package/src/server/routes/system.mjs +0 -15
  203. package/src/server/routes/tasks.mjs +0 -26
  204. package/src/server/routes/vault.mjs +2 -23
  205. package/frontend/dist/assets/index-DD4qONvH.js +0 -5607
  206. package/scaffold/.agent/skills/total-recall/plugins/git-sentinel/README.md +0 -53
  207. package/scaffold/.agent/skills/total-recall/plugins/git-sentinel/plugin.json +0 -129
  208. package/src/core/append-log.mjs +0 -131
  209. package/src/core/plugin-tasks.mjs +0 -173
  210. package/templates/onboarding-interview.md +0 -82
  211. /package/scaffold/.agent/skills/total-recall/plugins/{git-sentinel → git}/LICENSE +0 -0
  212. /package/scaffold/.agent/skills/total-recall/plugins/{git-sentinel → git}/ui/DESIGN.md +0 -0
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "tr-plugin-mesh",
3
- "version": "0.2.9",
3
+ "version": "0.2.10",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "tr-plugin-mesh",
9
- "version": "0.2.9",
9
+ "version": "0.2.10",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
12
  "@gregiteen/ssss-cli": "0.14.5",
@@ -15,7 +15,7 @@
15
15
  "devDependencies": {
16
16
  "jsdom": "^29.1.1",
17
17
  "supertest": "^7.3.1",
18
- "total-recall-brain": "3.43.3",
18
+ "total-recall-brain": "3.44.0",
19
19
  "vitest": "^4.1.12"
20
20
  }
21
21
  },
@@ -7177,9 +7177,9 @@
7177
7177
  }
7178
7178
  },
7179
7179
  "node_modules/total-recall-brain": {
7180
- "version": "3.43.3",
7181
- "resolved": "https://registry.npmjs.org/total-recall-brain/-/total-recall-brain-3.43.3.tgz",
7182
- "integrity": "sha512-yjfPN/BQxEEa+iodyFXQov/6fRt1pZg/7RcmgsbpALwBt6Ki3JJjT3tzArBC7NxHQmXgGYyKnCYId6xe/W2rPg==",
7180
+ "version": "3.44.0",
7181
+ "resolved": "https://registry.npmjs.org/total-recall-brain/-/total-recall-brain-3.44.0.tgz",
7182
+ "integrity": "sha512-VNPaIO9zsSwoxAsJ5ByIQBP9zPpLq4RiQO7Vrex4rBOHFQJT50P7utcZiLMSZTyZJU4C/m5uB8qTCSBMp6+l6Q==",
7183
7183
  "dev": true,
7184
7184
  "license": "MIT",
7185
7185
  "workspaces": [
@@ -7187,7 +7187,7 @@
7187
7187
  ],
7188
7188
  "dependencies": {
7189
7189
  "@simplewebauthn/server": "^13.3.2",
7190
- "@ssss/cli": "npm:@gregiteen/ssss-cli@0.14.4",
7190
+ "@ssss/cli": "npm:@gregiteen/ssss-cli@0.14.5",
7191
7191
  "bcrypt": "^6.0.0",
7192
7192
  "better-sqlite3": "^12.11.1",
7193
7193
  "cookie-parser": "^1.4.7",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tr-plugin-mesh",
3
- "version": "0.2.9",
3
+ "version": "0.2.10",
4
4
  "type": "module",
5
5
  "description": "Headscale and Tailscale SSH control-server mesh administration and node discovery",
6
6
  "scripts": {
@@ -2,7 +2,7 @@
2
2
  "$schema": "https://github.com/gregiteen/total-recall/blob/main/metadata.plugin.schema.json",
3
3
  "id": "mesh",
4
4
  "name": "Headscale",
5
- "version": "0.2.9",
5
+ "version": "0.2.10",
6
6
  "description": "Control-server mesh administration, Tailscale SSH, and peer node discovery.",
7
7
  "license": "MIT",
8
8
  "requires": [
@@ -1,4 +1,4 @@
1
- # Meta Harness
1
+ # Metaharness
2
2
 
3
3
  Built-in and validated custom adapters share one plugin. Use `dispatch` or
4
4
  `route --execute` for agent work. `runtime <agent> ...` accepts supported maintenance
@@ -17,10 +17,12 @@ is removed after execution. Setup failure or an unready context stops dispatch.
17
17
  `docs-refresh`, `docs-ensure`, `docs-status`, `docs-read` and `docs-search` manage
18
18
  downloaded official documentation rather than a list of links. Content is hashed,
19
19
  bounded and refreshed after 24 hours. Maintenance uses the existing Total Recall
20
- daemon's plugin task, refreshing one stale adapter per run. Failed pages remain
20
+ daemon's plugin task, attempting every stale adapter per run. Failed pages remain
21
21
  visible as failures and cannot certify complete coverage; successful cached
22
22
  content remains readable. `setup --node <recorded-node>` selects maintenance
23
- placement without creating a second scheduler.
23
+ placement for `maintenance`, `maintenance --models` and `alerts check` without
24
+ creating a second scheduler. Each maintenance step reports its failures. A failed
25
+ setup or gate install does not prevent documentation refresh for other harnesses.
24
26
 
25
27
  Standalone Total Recall owner for CLI-agent discovery and explicit mesh command execution. Install with `total-recall plugin install <path-or-private-git-url>`. Installation rebuilds the plugin inventory, CLI library and connected instruction surfaces. No model account is created or selected automatically.
26
28
 
@@ -43,7 +45,7 @@ The report separates native login and hook configuration from recent hook
43
45
  decisions and completed managed runs. Its run evidence is historical; use the
44
46
  timestamps and last attempt to see whether an agent has since stopped working.
45
47
  Native hook activity alone does not prove that an agent was launched through
46
- Meta Harness. A fleet report lists offline nodes, missing CLI access, and
48
+ Metaharness. A fleet report lists offline nodes, missing CLI access, and
47
49
  installed versions that cannot provide adoption evidence.
48
50
 
49
51
  `request.json` selects one installed plugin operation, its literal arguments, a node and an agent:
@@ -61,7 +63,7 @@ installed versions that cannot provide adoption evidence.
61
63
  }
62
64
  ```
63
65
 
64
- For remote nodes, supply `execution.cwd` as an explicit absolute workspace. `agent: "direct"` runs the actual installed Total Recall CLI without a model. A remote agent task enters the destination's installed Meta Harness and records its receipt there. Remote access comes from recorded mesh entities and verified SSH configuration; unavailable nodes or binaries produce errors. Secrets are never accepted in an agent prompt. Existing account metadata is inspected without printing credentials or substituting provider API keys.
66
+ For remote nodes, supply `execution.cwd` as an explicit absolute workspace. `agent: "direct"` runs the actual installed Total Recall CLI without a model. A remote agent task enters the destination's installed Metaharness and records its receipt there. Remote access comes from recorded mesh entities and verified SSH configuration; unavailable nodes or binaries produce errors. Secrets are never accepted in an agent prompt. Existing account metadata is inspected without printing credentials or substituting provider API keys.
65
67
 
66
68
  The four permissions are strict boolean **command-effect admission controls**. They allow or deny the selected plugin command before dispatch. They are not a network policy or an OS sandbox for every action a model might propose. Supported adapter write modes are scoped through the vendor CLI; vendor approval and sandbox defaults stay enabled. The host's authenticated authorization still applies.
67
69
 
@@ -75,9 +77,9 @@ Run `total-recall meta-harness included-enforce` to limit this node's managed di
75
77
 
76
78
  To approve OpenRouter on this node, run `total-recall meta-harness openrouter-bind <harness> <auth-key-name> --model <openrouter-model-id> --json`. Then select that harness by name when dispatching. Automatic routing continues to choose from the included subscription pool.
77
79
 
78
- Run `total-recall harness dispatch codex "Run pwd and report the output" --json` to see the final reply and `toolResults`. Codex, Claude, DSH, Pi, Hermes and OpenClaw report native tool outcomes, available exit codes and bounded output. OpenClaw reports `toolEvidenceError` if its gateway cannot return the run's tool results. Adoption receipts retain the outcomes without the output text.
80
+ Run `total-recall harness dispatch codex "Run pwd and report the output" --json` to see the final reply and `toolResults`. Codex, Claude, DSH, Pi, Hermes and OpenClaw report native tool outcomes, available exit codes and bounded output. OpenClaw reports `toolEvidenceError` if its gateway cannot return the run's tool results. For background jobs, run `total-recall meta-harness process logs <job-id> --json` and read `toolResults` in the completion record. Adoption receipts retain the outcomes without the output text.
79
81
 
80
- For Claude Max, sign in on the execution host with `claude auth login --claudeai`. Check that Usage credits are off in the account's Usage settings. Pass `{"organization":"<orgId from claude auth status>","usageCreditsEnabled":false}` to `included-bind-claude-plan --stdin`. Meta Harness prefers the bound plan and checks the native login on every turn. Keep Usage credits off on that account. Claude manages that switch and enforces the plan limits. [Claude's subscription and SDK billing](https://support.claude.com/en/articles/15036540-use-the-claude-agent-sdk-with-your-claude-plan)
82
+ For Claude Max, sign in on the execution host with `claude auth login --claudeai`. Check that Usage credits are off in the account's Usage settings. Pass `{"organization":"<orgId from claude auth status>","usageCreditsEnabled":false}` to `included-bind-claude-plan --stdin`. Metaharness prefers the bound plan and checks the native login on every turn. Keep Usage credits off on that account. Claude manages that switch and enforces the plan limits. [Claude's subscription and SDK billing](https://support.claude.com/en/articles/15036540-use-the-claude-agent-sdk-with-your-claude-plan)
81
83
 
82
84
  Before using `included-bind-claude --stdin`, verify the Max credit grant, key hint and organization in Claude Console. Supply `keyName` (the Total Recall Auth entry), `organization`, the masked `keyHint`, `expiresAt`, `creditSource: "claude-max"`, `paidBalanceCents: 0` and false values for `autoReload`, `paymentMethod` and `invoiced`. The binding expires with the observed grant. Reverify after a key or billing change.
83
85
 
@@ -126,6 +128,20 @@ SSSS execution receipts. Actual process exit and finish metadata are distinct fr
126
128
  verification results; unavailable model metadata remains null. Thread operations
127
129
  include list, show, create, update, close and delete, using native SSSS state.
128
130
 
131
+ Every review result is stored in an append-only SSSS ledger beside the thread
132
+ store. It retains the selected diff, commit, reviewer, verdict and disposition,
133
+ including failed reviews and `NO_DIFF`. `reviews --json` reads the ledger.
134
+ Deleting a thread does not remove its reviews. A failed ledger write returns
135
+ `ok: false` with `reviewStoreError` and the completed result.
136
+
137
+ `learn` reports scorecards, walls and proposals from run receipts. Routing reads
138
+ these receipts directly. The memory emit option has been removed.
139
+
140
+ `threads cleanup-fixtures --dry-run` previews the one-time cleanup of exact test
141
+ fixture titles. `threads cleanup-fixtures` applies it and stores the removed IDs,
142
+ titles, statuses, source test files and retained IDs in the same SSSS operation.
143
+ Real end-to-end job threads stay in place, including failed attempts.
144
+
129
145
  Custom adapter declarations preserve scoped credentials, optional authentication
130
146
  probes and HTTPS documentation URLs. IDs and paths reject traversal and symbolic
131
147
  links. Credentials reach only the declaring runner through the auth store. A
@@ -148,14 +164,14 @@ The active five-file suite and evidence live in
148
164
  owner/core suites, plugin/scaffold validation, real dashboard inspection and
149
165
  recorded acceptance evidence. Fixture tests do not certify live accounts, remote
150
166
  execution or recurring maintenance. The operator requires completing verification
151
- before Meta Harness runs task work.
167
+ before Metaharness runs task work.
152
168
 
153
169
  Cloudroom setup material remains under `cloudroom/`. Its plugin implementation
154
170
  follows this foundation and requires its own current audit and plan.
155
171
 
156
172
  ### Installed and standalone verification
157
173
 
158
- Use the installed plugin for CLI execution and maintenance. The repository has a pure planning capability under `capability/`. The current manifest does not declare it for vendoring. See the [Meta Harness tracker](docs/projects/in-progress/META_HARNESS_UNIFICATION/META_HARNESS_UNIFICATION_PROJECT_TRACKER.md) for current package, execution and hook acceptance.
174
+ Use the installed plugin for CLI execution and maintenance. The repository has a pure planning capability under `capability/`. The current manifest does not declare it for vendoring. See the [Metaharness tracker](docs/projects/in-progress/META_HARNESS_UNIFICATION/META_HARNESS_UNIFICATION_PROJECT_TRACKER.md) for current package, execution and hook acceptance.
159
175
 
160
176
  ## Using this from an agent
161
177
 
@@ -1,4 +1,4 @@
1
- # Meta Harness Capability Brick
1
+ # Metaharness Capability Brick
2
2
 
3
3
  A zero-dependency, host-free pure ES module providing universal agent harness discovery, two-stage complexity classification, cost-vs-frontier routing, gate cascade evaluation, and execution envelope construction.
4
4
 
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Meta Harness Capability Brick
2
+ * Metaharness Capability Brick
3
3
  * Zero-dependency, host-free pure ES module for agent routing,
4
4
  * complexity classification, adapter discovery, gate cascades, and SSSS receipts.
5
5
  * Works identically in any standalone app, edge device, workstation, or cloud environment.
@@ -34,7 +34,7 @@ export const ADAPTER_CATALOG = {
34
34
  contextLimit: 200000,
35
35
  modalities: ['text', 'code'],
36
36
  features: ['subagents', 'mcp', 'headless', 'compact', 'plan_mode'],
37
- flags: { prompt: '-p', nonInteractive: '--permission-mode acceptEdits', planMode: '--permission-mode plan', output: '--output-format json' }
37
+ flags: { prompt: '-p', nonInteractive: '--permission-mode bypassPermissions', planMode: '--permission-mode plan', output: '--output-format json' }
38
38
  },
39
39
  codex: {
40
40
  id: 'codex',
@@ -49,7 +49,7 @@ export const ADAPTER_CATALOG = {
49
49
  contextLimit: 128000,
50
50
  modalities: ['text', 'code'],
51
51
  features: ['mcp', 'headless', 'streaming'],
52
- flags: { prompt: 'exec', nonInteractive: '--sandbox workspace-write', planMode: '--sandbox read-only', output: '--json' }
52
+ flags: { prompt: 'exec', nonInteractive: '--sandbox danger-full-access', planMode: '--sandbox read-only', output: '--json' }
53
53
  },
54
54
  grok: {
55
55
  id: 'grok',
@@ -256,15 +256,27 @@ export function classifyTaskComplexity(taskDescription, options = {}) {
256
256
  score += 30;
257
257
  factors.push('security-sensitive');
258
258
  }
259
- if (/multi-file|across (all|every)|entire (repo|fleet)|worktree/.test(text)) {
259
+ if (/multi-file|across (all|every)|entire (repo|fleet)|worktree|every (mesh )?(node|machine|host|repo)|(all|several|multiple) (repos|repositories|nodes|machines)|\bmesh\b|\bfleet\b/.test(text)) {
260
260
  score += 25;
261
261
  factors.push('broad-blast-radius');
262
262
  }
263
+ if (/\bproduction\b|\bdeploy|roll ?out|\bdroplet\b|\bcore\b|\bmigration\b|\brelease\b/.test(text)) {
264
+ score += 15;
265
+ factors.push('production-or-core');
266
+ }
263
267
  if (/benchmark|telemetry|concurrency|race condition|memory leak/.test(text)) {
264
268
  score += 20;
265
269
  factors.push('complex-debugging');
266
270
  }
267
- if (/typo|rename|docstring|comment|formatting|readme|lint fix/.test(text)) {
271
+ // Several distinct pieces of work (comma or semicolon separated clauses, phases) are not one edit.
272
+ const clauses = text.split(/[,;]|\band then\b|\bthen\b|\bplus\b/).filter(part => part.trim().split(/\s+/).length >= 3).length;
273
+ if (clauses >= 4 || /phases? \d+ (and|&) \d+/.test(text)) {
274
+ score += 15;
275
+ factors.push('multi-part-work');
276
+ }
277
+ // An easy-sounding word ("rename", "readme") lowers the score only when nothing else carries risk:
278
+ // a rename across repositories or a credential change is not a typo fix.
279
+ if (/typo|rename|docstring|comment|formatting|readme|lint fix/.test(text) && factors.length === 0) {
268
280
  score -= 30;
269
281
  factors.push('low-complexity-edit');
270
282
  }
@@ -645,7 +657,7 @@ export function decomposeTask(taskDescription, options = {}) {
645
657
  }
646
658
 
647
659
  /**
648
- * Meta Harness Brick Factory
660
+ * Metaharness Brick Factory
649
661
  */
650
662
  export function createMetaHarness(customAdapters = {}) {
651
663
  const mergedAdapters = { ...ADAPTER_CATALOG, ...customAdapters };
@@ -5,10 +5,11 @@ import { pathToFileURL } from 'node:url';
5
5
  import { configDir } from './src/paths.mjs';
6
6
  import { inspectAgents, getActiveAdapters, getCustomAdaptersDirs, loadCustomAdapters, validateCustomAdapter, adapterPath } from './src/worker.mjs';
7
7
  import { inspectNode, listTargets, executeCommand, executeOnNode } from './src/executor.mjs';
8
- import { DOC_SOURCES, documentationStatus, refreshDocumentation, ensureDocumentation, maintainDocumentation, readDocumentation, searchDocumentation } from './src/documentation.mjs';
8
+ import { DOC_SOURCES, documentationStatus, refreshDocumentation, ensureDocumentation, readDocumentation, searchDocumentation } from './src/documentation.mjs';
9
9
  import { manageRuntime, validateRuntimeOperation } from './src/runtime.mjs';
10
10
  import { validateDispatchRequest } from './src/dispatch-request.mjs';
11
11
  import { setupIntegrations } from './src/setup.mjs';
12
+ import { maintainIntegrations } from './src/maintenance.mjs';
12
13
  import { inspectUpstreamFleet, getAgentChangelog } from './src/tracker.mjs';
13
14
  import { inspectQuotas, getBenchmarks, routeTask } from './src/router.mjs';
14
15
  import { coordinateTask } from './src/coordinator.mjs';
@@ -18,11 +19,17 @@ import { resolvePool } from './src/pool.mjs';
18
19
  import { checkAlerts, notifyAlert } from './src/alerts.mjs';
19
20
  import { learnFromHistory, voidReceipts } from './src/learner.mjs';
20
21
  import { decomposeTask } from './capability/index.mjs';
21
- import { listThreads, getThread, createThread, updateThread, closeThread, deleteThread } from './src/threads.mjs';
22
+ import { listThreads, getThread, createThread, updateThread, closeThread, deleteThread, cleanupFixtureThreads } from './src/threads.mjs';
23
+ import { readReviews } from './src/reviews.mjs';
22
24
  import { executeCodeReview } from './src/review.mjs';
23
- import { stopOnTermination } from './src/termination.mjs';
25
+ import { stopOnTermination, finishCancellation } from './src/termination.mjs';
26
+ import { cancellationResult } from './src/worker.mjs';
27
+ import { startJob, newJobId, cancelJob, resolveJob } from './src/jobs.mjs';
28
+ import { appendCommand, waitingRequests } from './src/control.mjs';
29
+ import { sessionOptions } from './src/session/run.mjs';
30
+ import { continueJob } from './src/session-jobs.mjs';
24
31
 
25
- const VALUE_FLAGS = ['--node', '--mode', '--orchestrator', '--branch', '--reviewer', '--thread', '--status', '--platform', '--agent', '--url', '--query', '--tier', '--threshold', '--author', '--explorer', '--architect', '--implementer', '--verifier', '--title', '--summary', '--cwd', '--tools', '--setting-sources', '--model', '--name', '--tail', '--timeout-ms', '--void', '--reason'];
32
+ const VALUE_FLAGS = ['--result-schema-json', '--goal', '--max-turns', '--max-budget-usd', '--max-tokens', '--result-schema', '--at', '--node', '--mode', '--orchestrator', '--branch', '--reviewer', '--thread', '--status', '--platform', '--agent', '--url', '--query', '--tier', '--threshold', '--author', '--explorer', '--architect', '--implementer', '--verifier', '--title', '--summary', '--cwd', '--tools', '--setting-sources', '--model', '--name', '--tail', '--timeout-ms', '--void', '--reason', '--approvals', '--question-timeout-ms'];
26
33
  export function parseArguments(args) {
27
34
  const positional = [];
28
35
  for (let index = 1; index < args.length; index += 1) {
@@ -38,30 +45,68 @@ export function parseArguments(args) {
38
45
  return { positional, value, has: name => args.includes(name) };
39
46
  }
40
47
 
41
- export async function run(argv = []) {
48
+ export async function run(argv = [], { backgroundJobId } = {}) {
49
+ // MCP owns stdin/stdout for its whole lifetime. The CLI result wrapper must stay out of that stream.
50
+ if (argv[3] === 'mcp' && !argv.includes('--help') && !argv.includes('-h')) {
51
+ try { await runOperation(argv); }
52
+ catch (error) { console.error(`Metaharness MCP: ${error.message}`); process.exitCode = 1; }
53
+ return;
54
+ }
42
55
  stopOnTermination();
43
- try { await runOperation(argv); }
56
+ let job, result;
57
+ const previousJob = process.env.TR_METAHARNESS_JOB;
58
+ try {
59
+ const args = argv.slice(3), operation = args[0];
60
+ if (!args.includes('--help') && !args.includes('-h') && !args.includes('--background') &&
61
+ (['dispatch', 'fork', 'resume'].includes(operation) || (['route', 'coordinate', 'orchestrate'].includes(operation) && args.includes('--execute')))) {
62
+ job = startJob(operation, backgroundJobId ? { id: backgroundJobId } : {});
63
+ process.env.TR_METAHARNESS_JOB = job.job;
64
+ }
65
+ result = await runOperation(argv);
66
+ }
44
67
  catch (error) {
45
68
  const message = String(error?.message || error);
46
- if (argv.includes('--json')) console.log(JSON.stringify({ ok: false, error: message }));
47
- else console.error(`meta-harness: ${message}`);
69
+ result = { ok: false, error: message };
70
+ if (!argv.includes('--json')) console.error(`meta-harness: ${message}`);
48
71
  process.exitCode = 1;
49
72
  }
73
+ result = finishCancellation(result);
74
+ if (result !== undefined) {
75
+ if (job) {
76
+ if (result.execution?.remote && result.job) result.execution = { ...result.execution, remoteJob: result.job };
77
+ result = { ...result, job: job.job };
78
+ }
79
+ job?.finish(result);
80
+ if (!backgroundJobId) console.log(JSON.stringify(result));
81
+ }
82
+ if (previousJob === undefined) delete process.env.TR_METAHARNESS_JOB;
83
+ else process.env.TR_METAHARNESS_JOB = previousJob;
50
84
  }
51
85
 
52
86
  /** The host stops a plugin command after 10 minutes, so long runs detach and report through their thread and log. */
53
87
  async function detachRun(argv) {
54
88
  const directory = path.join(configDir(), 'jobs');
55
89
  fs.mkdirSync(directory, { recursive: true, mode: 0o700 });
56
- const log = path.join(directory, `${Date.now().toString(36)}.log`);
90
+ const id = newJobId();
91
+ const log = path.join(directory, `${id}.log`);
57
92
  const output = fs.openSync(log, 'a', 0o600);
58
93
  const entry = new URL('./cli.mjs', import.meta.url).href;
59
- const child = spawn(process.execPath, ['--input-type=module', '-e', `import(${JSON.stringify(entry)}).then(m=>m.run(${JSON.stringify(argv.filter(arg => arg !== '--background'))}))`], { cwd: process.cwd(), detached: true, stdio: ['ignore', output, output], env: process.env });
94
+ const input = argv[3] === 'dispatch' ? fs.readFileSync(0, 'utf8') : null;
95
+ const child = spawn(process.execPath, ['--input-type=module', '-e', `import(${JSON.stringify(entry)}).then(m=>m.run(${JSON.stringify(argv.filter(arg => arg !== '--background'))}, {backgroundJobId:${JSON.stringify(id)}}))`], { cwd: process.cwd(), detached: true, stdio: [input === null ? 'ignore' : 'pipe', output, output], env: process.env });
96
+ if (input !== null) { child.stdin.on('error', () => {}); child.stdin.end(input); }
60
97
  try {
61
98
  await new Promise((resolve, reject) => { child.once('spawn', resolve); child.once('error', reject); });
99
+ const deadline = Date.now() + 10_000;
100
+ while (!fs.statSync(log).size) {
101
+ if (child.exitCode !== null || Date.now() > deadline) {
102
+ child.kill('SIGTERM');
103
+ throw new Error(`The background job did not record its PID. Log: ${log}`);
104
+ }
105
+ await new Promise(resolve => setTimeout(resolve, 20));
106
+ }
62
107
  child.unref();
63
108
  } finally { fs.closeSync(output); }
64
- return { ok: true, background: true, pid: child.pid, log, follow: `The final JSON result is written to ${log}; a pipeline also records a thread.` };
109
+ return { ok: true, background: true, job: id, pid: child.pid, log, follow: `The final JSON result is written to ${log}; a pipeline also records a thread.` };
65
110
  }
66
111
 
67
112
  async function runOperation(argv) {
@@ -81,7 +126,12 @@ async function runOperation(argv) {
81
126
  for(const command of manifest.cli.subcommands)console.log(` ${command.name} ${(command.args || []).map(arg=>arg.flag?`${arg.flag} <${arg.name}>`:`<${arg.name}>`).join(' ')} — ${command.description}`);
82
127
  return;
83
128
  }
84
- if (has('--background') && ['route', 'coordinate', 'orchestrate'].includes(operation) && has('--execute')) { console.log(JSON.stringify(await detachRun(argv))); return; }
129
+ if (has('--background') && (['dispatch', 'fork', 'resume'].includes(operation) || (['route', 'coordinate', 'orchestrate'].includes(operation) && has('--execute')))) return detachRun(argv);
130
+ const controls = () => sessionOptions({ cwd: value('--cwd') || process.cwd(),
131
+ ...(value('--result-schema-json') !== undefined ? { resultSchema: JSON.parse(value('--result-schema-json')) } : {}),
132
+ ...Object.fromEntries([['goal', '--goal'], ['maxTurns', '--max-turns'], ['maxBudgetUsd', '--max-budget-usd'], ['maxTokens', '--max-tokens'],
133
+ ['resultSchema', '--result-schema'], ['approvalPolicy', '--approvals'], ['questionTimeoutMs', '--question-timeout-ms']]
134
+ .filter(([, flag]) => value(flag) !== undefined).map(([key, flag]) => [key, ['maxTurns', 'maxBudgetUsd', 'maxTokens', 'questionTimeoutMs'].includes(key) ? Number(value(flag)) : value(flag)])) });
85
135
  let result;
86
136
  if (operation === 'status') result = {...await inspectNode(value('--node') || 'local'),documentation:documentationStatus()};
87
137
  else if (operation === 'catalog') result = { adapters: getActiveAdapters(), permissions: ['read', 'write', 'send', 'destructive'] };
@@ -122,7 +172,7 @@ async function runOperation(argv) {
122
172
  else if (operation === 'route') {
123
173
  const task = positional.join(' ');
124
174
  if (!task) throw new Error('route requires a task description');
125
- const options = { jev: has('--jev'), preferLocal: has('--prefer-local'), preferFrontier: has('--prefer-frontier'), node: value('--node'), cwd: value('--cwd'), allowUnknownAuth: has('--allow-unknown-auth'), ...remoteTimeout() };
175
+ const options = { ...controls(), jev: has('--jev'), preferLocal: has('--prefer-local'), preferFrontier: has('--prefer-frontier'), node: value('--node'), cwd: value('--cwd'), allowUnknownAuth: has('--allow-unknown-auth'), ...remoteTimeout() };
126
176
  result = has('--execute') ? await executeRoutedTask(task, { ...options, gate: has('--gate'), gateOptions: { tier: value('--tier') || 'fast' } }) : await routeTask(task, options);
127
177
  if (!result.ok) process.exitCode = 1;
128
178
  }
@@ -136,7 +186,7 @@ async function runOperation(argv) {
136
186
  const task = positional.join(' ');
137
187
  if (!task) throw new Error(`${operation} requires a task description`);
138
188
  result = await coordinateTask(task, {
139
- mode: value('--mode') || 'pipeline', execute: has('--execute'), orchestrator: value('--orchestrator'), explorer: value('--explorer'), architect: value('--architect'), implementer: value('--implementer'), verifier: value('--verifier'),
189
+ ...controls(), mode: value('--mode') || 'pipeline', execute: has('--execute'), orchestrator: value('--orchestrator'), explorer: value('--explorer'), architect: value('--architect'), implementer: value('--implementer'), verifier: value('--verifier'),
140
190
  branch: value('--branch'), subagents: !has('--no-subagents'), autoReview: has('--auto-review'), gate: has('--gate'), gateOptions: { tier: value('--tier') || 'fast' }, allowSameFamily: has('--allow-same-family'), reviewer: value('--reviewer'),
141
191
  node: value('--node') || 'local', cwd: value('--cwd'), allowUnknownAuth: has('--allow-unknown-auth'), ...remoteTimeout(),
142
192
  });
@@ -151,6 +201,8 @@ async function runOperation(argv) {
151
201
  status: statusIdx >= 0 ? args[statusIdx + 1] : undefined,
152
202
  platform: platformIdx >= 0 ? args[platformIdx + 1] : undefined
153
203
  });
204
+ } else if (sub === 'cleanup-fixtures') {
205
+ result = cleanupFixtureThreads({ dryRun: has('--dry-run') });
154
206
  } else if (sub === 'show' || sub === 'get') {
155
207
  const id = args[2];
156
208
  if (!id) throw new Error('threads show requires a thread id');
@@ -181,14 +233,16 @@ async function runOperation(argv) {
181
233
  throw new Error(`Unsupported threads operation: ${sub}`);
182
234
  }
183
235
  }
236
+ else if (operation === 'reviews') result = { ok: true, reviews: readReviews() };
184
237
  else if (operation === 'review') {
185
238
  result = await executeCodeReview({ target: positional[0] || null, reviewer: value('--reviewer'), author: value('--author'), threadId: value('--thread'), staged: has('--staged'), node: value('--node') || 'local', cwd: value('--cwd'), allowUnknownAuth: has('--allow-unknown-auth'), ...remoteTimeout() });
186
239
  if (!result.ok) process.exitCode = 1;
187
240
  }
188
241
  else if (operation === 'learn') {
242
+ if (has('--emit')) throw new Error('learn --emit was removed. Routing reads run receipts directly.');
189
243
  result = value('--void') !== undefined
190
244
  ? await voidReceipts({ ids: String(value('--void')).split(',').map(id => id.trim()).filter(Boolean), reason: value('--reason') })
191
- : await learnFromHistory({ emit: has('--emit') });
245
+ : await learnFromHistory();
192
246
  if (!result.ok) process.exitCode = 1;
193
247
  }
194
248
  else if (operation === 'alerts') {
@@ -196,7 +250,7 @@ async function runOperation(argv) {
196
250
  if (sub === 'check') {
197
251
  const { quotas } = await inspectQuotas({});
198
252
  result = await checkAlerts({ quotas, threshold: Number(value('--threshold')) || 85, dryRun: has('--dry-run') });
199
- } else if (sub === 'test') result = await notifyAlert({ title: 'Meta Harness: test alert', message: 'Alert delivery check.', dryRun: has('--dry-run') });
253
+ } else if (sub === 'test') result = await notifyAlert({ title: 'Metaharness: test alert', message: 'Alert delivery check.', dryRun: has('--dry-run') });
200
254
  else throw new Error(`Unsupported alerts operation: ${sub}`);
201
255
  if (!result.ok) process.exitCode = 1;
202
256
  }
@@ -256,11 +310,7 @@ async function runOperation(argv) {
256
310
  const { syncModelCatalog } = await import('./src/model-catalog.mjs');
257
311
  result = await syncModelCatalog();
258
312
  } else {
259
- const setup=await setupIntegrations();
260
- const { installAll } = await import('./src/gate-adapters/index.mjs');
261
- const gates=await installAll();
262
- const docs=await maintainDocumentation(options);
263
- result={...docs,ok:docs.ok!==false&&gates.ok,setup,gates};
313
+ result=await maintainIntegrations(options);
264
314
  }
265
315
  } else result = operation==='docs-status' ? documentationStatus(options) : operation==='docs-ensure' ? await ensureDocumentation(options) : await refreshDocumentation(options);
266
316
  if(!result.ok)process.exitCode=1;
@@ -296,11 +346,60 @@ async function runOperation(argv) {
296
346
  result = { ok: true, logs: await processes.getAgentLogs(target, Number(value('--tail') || 50)) };
297
347
  } else throw new Error(`Unsupported process operation: ${action}`);
298
348
  }
349
+ else if (operation === 'fork' || operation === 'resume') {
350
+ if (positional.length !== (operation === 'fork' ? 1 : 2)) throw new Error(`${operation} requires a job${operation === 'resume' ? ' and quoted text' : ''}.`);
351
+ result = await continueJob(positional[0], operation === 'fork' ? 'Continue from this session.' : positional[1], { fork: operation === 'fork', atTurn: value('--at') });
352
+ if (!result.ok) process.exitCode = 1;
353
+ }
354
+ else if (operation === 'cancel') {
355
+ result = await cancelJob(positional[0]);
356
+ }
357
+ else if (['reply', 'approve', 'interrupt', 'goal'].includes(operation)) {
358
+ if (!positional[0]) throw new Error(`${operation} requires a job ID.`);
359
+ if (positional.length !== (operation === 'approve' ? 3 : operation === 'interrupt' ? 1 : 2)) {
360
+ throw new Error(`${operation}: supply a job${operation === 'approve' ? ', request ID, and allow or deny' : operation === 'interrupt' ? '' : ' and quoted text'}.`);
361
+ }
362
+ result = await appendCommand(positional[0], { type: operation,
363
+ ...(operation === 'approve' ? { requestId: positional[1], value: positional[2] } : operation === 'interrupt' ? {} : { text: positional[1] }) },
364
+ { local: has('--local-delivery') });
365
+ }
366
+ else if (operation === 'mcp') {
367
+ const { runMcpServer, QUESTION_TIMEOUT_MS } = await import('./src/mcp-server.mjs');
368
+ await runMcpServer({ approvalPolicy: value('--approvals') || 'auto',
369
+ questionTimeoutMs: value('--question-timeout-ms') === undefined ? QUESTION_TIMEOUT_MS : Number(value('--question-timeout-ms')) });
370
+ return;
371
+ }
372
+ else if (operation === 'watch') {
373
+ // A-107: a dispatched agent's live status and latest events, by log path or job prefix.
374
+ const target = positional[0];
375
+ const jobs = path.join(configDir(), 'jobs');
376
+ let file = target && target.endsWith('.events.jsonl') ? path.resolve(target) : null;
377
+ if (target && !file) {
378
+ try {
379
+ const job = resolveJob(target);
380
+ const canonical = path.join(jobs, `${job.id}.events.jsonl`);
381
+ if (fs.existsSync(canonical)) file = canonical;
382
+ } catch (error) {
383
+ if (!error.message.startsWith('No job log matches')) throw error;
384
+ }
385
+ }
386
+ if (!file) {
387
+ const names = fs.existsSync(jobs) ? fs.readdirSync(jobs).filter(name => name.endsWith('.events.jsonl') && (!target || name.startsWith(target))) : [];
388
+ const newest = names.map(name => ({ name, at: fs.statSync(path.join(jobs, name)).mtimeMs })).sort((a, b) => b.at - a.at)[0];
389
+ if (!newest) throw new Error(target ? `No job log matches ${target}` : 'No dispatched job has a live log yet');
390
+ file = path.join(jobs, newest.name);
391
+ }
392
+ const { readProgress } = await import('./src/worker.mjs');
393
+ result = { ok: true, file, ...readProgress(file, Number(value('--tail') || 20)), waiting: waitingRequests(file) };
394
+ }
299
395
  else if(operation==='dispatch') {
300
396
  if(!args.includes('--stdin'))throw new Error('Task requests must arrive through stdin: pass --stdin with JSON {agent, cwd, prompt}');
301
397
  const input=fs.readFileSync(0,'utf8');if(Buffer.byteLength(input)>65536)throw new Error('Task request too large');
302
- const request=validateDispatchRequest(JSON.parse(input));
303
- result=await dispatchWithReceipt(request,{node:request.node || 'local',role:'Dispatch'});
398
+ const request=validateDispatchRequest({...JSON.parse(input),...controls()});
399
+ // A-107: a local dispatch streams its agent's events to a live log, announced before it starts.
400
+ const progressFile=(request.node||'local')==='local'?path.join(configDir(),'jobs',`${process.env.TR_METAHARNESS_JOB || `dispatch-${Date.now().toString(36)}-${request.agent}`}.events.jsonl`):undefined;
401
+ if(progressFile)console.error(JSON.stringify({progress:progressFile,agent:request.agent}));
402
+ result=await dispatchWithReceipt(progressFile?{...request,progressFile}:request,{node:request.node || 'local',role:'Dispatch',manageWrites:true});
304
403
  if(!result.ok)process.exitCode=1;
305
404
  }
306
405
  else if (operation === 'inspect') {
@@ -321,6 +420,7 @@ async function runOperation(argv) {
321
420
  result = await executeCommand({ ...request, plugin });
322
421
  if (!result.ok) process.exitCode = 1;
323
422
  } else throw new Error(`Unknown operation: ${operation}`);
324
- console.log(JSON.stringify(result));
423
+ if (cancellationResult()) process.exitCode = cancellationResult().exitCode;
424
+ return result;
325
425
  }
326
426
  export default run;
@@ -1,17 +1,17 @@
1
1
  {
2
2
  "name": "tr-plugin-meta-harness",
3
- "version": "0.3.9",
3
+ "version": "0.3.13",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "tr-plugin-meta-harness",
9
- "version": "0.3.9",
9
+ "version": "0.3.13",
10
10
  "dependencies": {
11
11
  "@gregiteen/ssss-cli": "0.14.5"
12
12
  },
13
13
  "devDependencies": {
14
- "total-recall-brain": "3.43.3"
14
+ "total-recall-brain": "3.44.0"
15
15
  }
16
16
  },
17
17
  "node_modules/@alcalzone/ansi-tokenize": {
@@ -5546,9 +5546,9 @@
5546
5546
  }
5547
5547
  },
5548
5548
  "node_modules/total-recall-brain": {
5549
- "version": "3.43.3",
5550
- "resolved": "https://registry.npmjs.org/total-recall-brain/-/total-recall-brain-3.43.3.tgz",
5551
- "integrity": "sha512-yjfPN/BQxEEa+iodyFXQov/6fRt1pZg/7RcmgsbpALwBt6Ki3JJjT3tzArBC7NxHQmXgGYyKnCYId6xe/W2rPg==",
5549
+ "version": "3.44.0",
5550
+ "resolved": "https://registry.npmjs.org/total-recall-brain/-/total-recall-brain-3.44.0.tgz",
5551
+ "integrity": "sha512-VNPaIO9zsSwoxAsJ5ByIQBP9zPpLq4RiQO7Vrex4rBOHFQJT50P7utcZiLMSZTyZJU4C/m5uB8qTCSBMp6+l6Q==",
5552
5552
  "dev": true,
5553
5553
  "license": "MIT",
5554
5554
  "workspaces": [
@@ -5556,7 +5556,7 @@
5556
5556
  ],
5557
5557
  "dependencies": {
5558
5558
  "@simplewebauthn/server": "^13.3.2",
5559
- "@ssss/cli": "npm:@gregiteen/ssss-cli@0.14.4",
5559
+ "@ssss/cli": "npm:@gregiteen/ssss-cli@0.14.5",
5560
5560
  "bcrypt": "^6.0.0",
5561
5561
  "better-sqlite3": "^12.11.1",
5562
5562
  "cookie-parser": "^1.4.7",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "tr-plugin-meta-harness",
3
- "version": "0.3.9",
4
- "description": "Total Recall Meta Harness plugin",
3
+ "version": "0.3.13",
4
+ "description": "Total Recall Metaharness plugin",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "test": "node --import ./test/isolate.mjs --test test/*.test.mjs",