total-recall-brain 3.43.3 → 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 (252) hide show
  1. package/bin/total-recall.mjs +6 -4
  2. package/docs/ARCHITECTURE.md +10 -7
  3. package/docs/reference/cli-reference.md +16 -9
  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 +3 -3
  9. package/scaffold/.agent/skills/plugin/SKILL.md +7 -2
  10. package/scaffold/.agent/skills/plugin/evals/README.md +5 -0
  11. package/scaffold/.agent/skills/plugin/evals/cases/01-fabricated-seed.mjs +1 -0
  12. package/scaffold/.agent/skills/plugin/evals/cases/02-reassuring-default.mjs +1 -0
  13. package/scaffold/.agent/skills/plugin/evals/cases/03-declared-template.mjs +1 -0
  14. package/scaffold/.agent/skills/plugin/evals/cases/04-card-collects-credential.mjs +1 -0
  15. package/scaffold/.agent/skills/plugin/evals/cases/05-host-leak-in-scaffold.mjs +1 -0
  16. package/scaffold/.agent/skills/plugin/evals/cases/06-correct-plugin.mjs +1 -0
  17. package/scaffold/.agent/skills/plugin/evals/cases/07-missing-reuse.mjs +11 -0
  18. package/scaffold/.agent/skills/plugin/evals/cases/08-unresolved-owner-command.mjs +12 -0
  19. package/scaffold/.agent/skills/plugin/evals/cases/09-missing-brick.mjs +12 -0
  20. package/scaffold/.agent/skills/plugin/prompts/01-function.md +4 -3
  21. package/scaffold/.agent/skills/plugin/prompts/08-verify.md +1 -0
  22. package/scaffold/.agent/skills/plugin/references/surfaces.md +12 -2
  23. package/scaffold/.agent/skills/plugin/scripts/record.mjs +59 -2
  24. package/scaffold/.agent/skills/total-recall/plugins/auth/README.md +8 -0
  25. package/scaffold/.agent/skills/total-recall/plugins/auth/package-lock.json +15 -14
  26. package/scaffold/.agent/skills/total-recall/plugins/auth/package.json +3 -3
  27. package/scaffold/.agent/skills/total-recall/plugins/auth/plugin.json +1 -1
  28. package/scaffold/.agent/skills/total-recall/plugins/auth/src/cli-gh-login.mjs +102 -0
  29. package/scaffold/.agent/skills/total-recall/plugins/auth/src/cli-secret.mjs +38 -2
  30. package/scaffold/.agent/skills/total-recall/plugins/auth/src/login-projections.mjs +157 -13
  31. package/scaffold/.agent/skills/total-recall/plugins/auth/src/secrets-store.mjs +12 -1
  32. package/scaffold/.agent/skills/total-recall/plugins/auth/src/secrets-sync.mjs +161 -17
  33. package/scaffold/.agent/skills/total-recall/plugins/automations/BRICK.md +7 -0
  34. package/scaffold/.agent/skills/total-recall/plugins/automations/LICENSE +21 -0
  35. package/scaffold/.agent/skills/total-recall/plugins/automations/README.md +66 -0
  36. package/scaffold/.agent/skills/total-recall/plugins/automations/adapters.mjs +231 -0
  37. package/scaffold/.agent/skills/total-recall/plugins/automations/capability/index.mjs +16 -0
  38. package/scaffold/.agent/skills/total-recall/plugins/automations/cli.mjs +121 -0
  39. package/{src/core/plugin-cron.mjs → scaffold/.agent/skills/total-recall/plugins/automations/cron.mjs} +1 -3
  40. package/scaffold/.agent/skills/total-recall/plugins/automations/inventory.mjs +88 -0
  41. package/scaffold/.agent/skills/total-recall/plugins/automations/package-lock.json +7661 -0
  42. package/scaffold/.agent/skills/total-recall/plugins/automations/package.json +35 -0
  43. package/scaffold/.agent/skills/total-recall/plugins/automations/plugin.json +167 -0
  44. package/scaffold/.agent/skills/total-recall/plugins/automations/scheduler.mjs +246 -0
  45. package/scaffold/.agent/skills/total-recall/plugins/automations/ui/DESIGN.md +42 -0
  46. package/scaffold/.agent/skills/total-recall/plugins/automations/ui/automations.js +2 -0
  47. package/scaffold/.agent/skills/total-recall/plugins/automations/ui/card.js +273 -0
  48. package/scaffold/.agent/skills/total-recall/plugins/code-quality/commands/run-core.mjs +1 -1
  49. package/scaffold/.agent/skills/total-recall/plugins/code-quality/core/check.mjs +57 -5
  50. package/scaffold/.agent/skills/total-recall/plugins/code-quality/core/report-data.mjs +40 -14
  51. package/scaffold/.agent/skills/total-recall/plugins/code-quality/core/report.mjs +15 -40
  52. package/scaffold/.agent/skills/total-recall/plugins/code-quality/package-lock.json +15 -14
  53. package/scaffold/.agent/skills/total-recall/plugins/code-quality/package.json +3 -3
  54. package/scaffold/.agent/skills/total-recall/plugins/code-quality/plugin.json +1 -1
  55. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/package-lock.json +15 -14
  56. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/package.json +3 -3
  57. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/plugin.json +1 -1
  58. package/scaffold/.agent/skills/total-recall/plugins/embeddings/package-lock.json +15 -14
  59. package/scaffold/.agent/skills/total-recall/plugins/embeddings/package.json +3 -3
  60. package/scaffold/.agent/skills/total-recall/plugins/embeddings/plugin.json +1 -1
  61. package/scaffold/.agent/skills/total-recall/plugins/git/README.md +112 -0
  62. package/scaffold/.agent/skills/total-recall/plugins/{git-sentinel → git}/cli.mjs +135 -23
  63. package/scaffold/.agent/skills/total-recall/plugins/{git-sentinel → git}/package-lock.json +17 -16
  64. package/scaffold/.agent/skills/total-recall/plugins/{git-sentinel → git}/package.json +5 -4
  65. package/scaffold/.agent/skills/total-recall/plugins/git/plugin.json +161 -0
  66. package/scaffold/.agent/skills/total-recall/plugins/git/src/lib/context.mjs +94 -0
  67. package/scaffold/.agent/skills/total-recall/plugins/git/src/lib/phase3-spec-support.mjs +50 -0
  68. package/scaffold/.agent/skills/total-recall/plugins/git/src/lib/runtime.mjs +40 -0
  69. package/scaffold/.agent/skills/total-recall/plugins/git/src/lib/spec-support.mjs +51 -0
  70. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/_support.mjs +195 -0
  71. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/auth.mjs +201 -0
  72. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/bisect.mjs +40 -0
  73. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/cli-meta.mjs +159 -0
  74. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/commit-memory.mjs +30 -0
  75. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/commit.mjs +46 -0
  76. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/fleet.mjs +156 -0
  77. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/force-push.mjs +58 -0
  78. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/group.mjs +119 -0
  79. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/handoff.mjs +59 -0
  80. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/message.mjs +22 -0
  81. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/resolve.mjs +60 -0
  82. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/rules.mjs +81 -0
  83. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/secret-firewall.mjs +66 -0
  84. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/undo.mjs +132 -0
  85. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/why.mjs +16 -0
  86. package/scaffold/.agent/skills/total-recall/plugins/{git-sentinel → git}/ui/card.js +2 -2
  87. package/scaffold/.agent/skills/total-recall/plugins/mesh/package-lock.json +15 -14
  88. package/scaffold/.agent/skills/total-recall/plugins/mesh/package.json +3 -3
  89. package/scaffold/.agent/skills/total-recall/plugins/mesh/plugin.json +1 -1
  90. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/README.md +59 -10
  91. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/capability/BRICK.md +1 -1
  92. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/capability/index.mjs +18 -6
  93. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/cli.mjs +160 -29
  94. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/package-lock.json +15 -14
  95. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/package.json +4 -4
  96. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/plugin.json +231 -16
  97. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/skills/meta-harness/SKILL.md +19 -4
  98. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/adoption.mjs +104 -0
  99. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/alerts.mjs +3 -3
  100. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/cascade.mjs +101 -16
  101. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/control.mjs +145 -0
  102. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/coordinator.mjs +54 -21
  103. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/dispatch-request.mjs +40 -0
  104. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/dispatch.mjs +68 -13
  105. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/documentation.mjs +55 -11
  106. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/executor.mjs +64 -15
  107. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/gate-adapters/hermes.mjs +29 -1
  108. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/gate-adapters/index.mjs +1 -1
  109. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/included-usage.mjs +249 -0
  110. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/jobs.mjs +84 -0
  111. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/learner.mjs +6 -12
  112. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/maintenance.mjs +17 -0
  113. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/mcp-server.mjs +228 -0
  114. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/pool.mjs +16 -8
  115. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/process-manager.mjs +26 -2
  116. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/reasoning.mjs +6 -1
  117. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/remote-operation.mjs +6 -2
  118. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/review.mjs +34 -3
  119. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/reviews.mjs +25 -0
  120. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/router.mjs +28 -12
  121. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/runtime.mjs +28 -6
  122. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/session/claude.mjs +319 -0
  123. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/session/codex.mjs +387 -0
  124. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/session/result.mjs +67 -0
  125. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/session/resume.mjs +373 -0
  126. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/session/run.mjs +223 -0
  127. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/session-jobs.mjs +72 -0
  128. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/setup.mjs +6 -3
  129. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/termination.mjs +16 -12
  130. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/threads.mjs +32 -1
  131. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/usage-queue.mjs +110 -0
  132. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/verify-ssss.mjs +3 -3
  133. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/worker.mjs +597 -70
  134. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/worktree.mjs +76 -9
  135. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/DESIGN.md +5 -5
  136. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/card.js +3 -3
  137. package/scaffold/.agent/skills/total-recall/plugins/openwiki/cli.mjs +47 -18
  138. package/scaffold/.agent/skills/total-recall/plugins/openwiki/package-lock.json +15 -14
  139. package/scaffold/.agent/skills/total-recall/plugins/openwiki/package.json +3 -3
  140. package/scaffold/.agent/skills/total-recall/plugins/openwiki/plugin.json +1 -1
  141. package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/refresh-diagnostics.mjs +44 -0
  142. package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/refresh.mjs +120 -113
  143. package/scaffold/.agent/skills/total-recall/plugins/security/package-lock.json +15 -14
  144. package/scaffold/.agent/skills/total-recall/plugins/security/package.json +3 -3
  145. package/scaffold/.agent/skills/total-recall/plugins/security/plugin.json +1 -1
  146. package/scaffold/.agent/skills/total-recall/plugins/ssss/assets/scaffold.json +5 -5
  147. package/scaffold/.agent/skills/total-recall/plugins/ssss/package-lock.json +6 -6
  148. package/scaffold/.agent/skills/total-recall/plugins/ssss/package.json +2 -2
  149. package/scaffold/.agent/skills/total-recall/plugins/ssss/plugin.json +1 -1
  150. package/scaffold/.agent/skills/total-recall/references/operations.md +1 -1
  151. package/src/cli/agent.mjs +1 -1
  152. package/src/cli/command.mjs +41 -2
  153. package/src/cli/connect.mjs +2 -29
  154. package/src/cli/context.mjs +1 -0
  155. package/src/cli/dream.mjs +93 -69
  156. package/src/cli/harness.mjs +4 -4
  157. package/src/cli/help.mjs +1 -1
  158. package/src/cli/ingest-okf.mjs +4 -4
  159. package/src/cli/init.mjs +0 -25
  160. package/src/cli/lessons.mjs +51 -0
  161. package/src/cli/memory-plugin.mjs +1 -1
  162. package/src/cli/plugin/copies.mjs +64 -14
  163. package/src/cli/plugin/create.mjs +6 -7
  164. package/src/cli/plugin/index.mjs +11 -7
  165. package/src/cli/plugin/install.mjs +10 -15
  166. package/src/cli/plugin/remove.mjs +1 -1
  167. package/src/cli/plugin/search.mjs +2 -2
  168. package/src/cli/preflight.mjs +19 -6
  169. package/src/cli/proposals.mjs +1 -1
  170. package/src/cli/recall.mjs +66 -23
  171. package/src/cli/release.mjs +4 -1
  172. package/src/cli/remember.mjs +3 -14
  173. package/src/cli/server.mjs +18 -0
  174. package/src/cli/startup.mjs +1 -0
  175. package/src/cli/task.mjs +9 -2
  176. package/src/cli/update.mjs +10 -3
  177. package/src/core/access-ledger.mjs +78 -0
  178. package/src/core/agent-manager.mjs +2 -2
  179. package/src/core/automatic-brain-updates.mjs +11 -6
  180. package/src/core/brain-locate.mjs +15 -0
  181. package/src/core/brain-updates.mjs +42 -12
  182. package/src/core/claude-hooks.mjs +3 -1
  183. package/src/core/cleanup-task.mjs +15 -0
  184. package/src/core/cli-commands.mjs +2 -0
  185. package/src/core/cli-maintenance.mjs +4 -1
  186. package/src/core/cli-semantic-index.mjs +23 -3
  187. package/src/core/context-compactor.mjs +7 -2
  188. package/src/core/context-compiler.mjs +26 -1
  189. package/src/core/context-policy.mjs +7 -3
  190. package/src/core/daemon-control.mjs +22 -0
  191. package/src/core/daemon-loop.mjs +39 -62
  192. package/src/core/default-plugins.mjs +1 -1
  193. package/src/core/dream.mjs +33 -105
  194. package/src/core/ensure-dependencies.mjs +148 -0
  195. package/src/core/fast-recall.mjs +2 -2
  196. package/src/core/field-evaluation.mjs +23 -0
  197. package/src/core/gate-mode.mjs +1 -1
  198. package/src/core/global-brain-updates.mjs +1 -1
  199. package/src/core/harness-hooks.mjs +14 -2
  200. package/src/core/lesson-hooks.mjs +74 -0
  201. package/src/core/lesson-memory.mjs +24 -0
  202. package/src/core/lesson-sessions.mjs +52 -0
  203. package/src/core/lessons.mjs +96 -0
  204. package/src/core/mesh-brain-updates.mjs +2 -1
  205. package/src/core/meta-harness.mjs +2 -2
  206. package/src/core/optimizer.mjs +66 -165
  207. package/src/core/plugin-contracts/card.mjs +3 -0
  208. package/src/core/plugin-loader.mjs +12 -3
  209. package/src/core/plugin-runtime.mjs +40 -1
  210. package/src/core/plugin-store.mjs +35 -23
  211. package/src/core/post-mortem.mjs +52 -36
  212. package/src/core/preflight-gate.mjs +23 -2
  213. package/src/core/proposal-applier.mjs +31 -2
  214. package/src/core/repo-sync.mjs +4 -6
  215. package/src/core/required-plugins.mjs +26 -4
  216. package/src/core/rule-length.mjs +23 -0
  217. package/src/core/runtime.mjs +1 -1
  218. package/src/core/scheduler.mjs +35 -43
  219. package/src/core/schema.mjs +1 -2
  220. package/src/core/search.mjs +4 -3
  221. package/src/core/server-restart.mjs +128 -7
  222. package/src/core/server-service.mjs +148 -0
  223. package/src/core/session-watcher.mjs +19 -1
  224. package/src/core/skill-gap.mjs +16 -0
  225. package/src/core/ssss-kernel-bridge.mjs +33 -6
  226. package/src/core/startup-health.mjs +6 -1
  227. package/src/core/surface.mjs +68 -57
  228. package/src/core/task-context.mjs +9 -8
  229. package/src/core/task-executors.mjs +54 -106
  230. package/src/core/validated-write.mjs +5 -0
  231. package/src/core/vault-files.mjs +8 -2
  232. package/src/core/vault.mjs +1 -1
  233. package/src/core/vector-field.mjs +134 -192
  234. package/src/server/index.mjs +3 -1
  235. package/src/server/invoke-core-child.mjs +24 -0
  236. package/src/server/invoke-core-operations.mjs +102 -0
  237. package/src/server/route-manifest.json +0 -56
  238. package/src/server/routes/brains.mjs +0 -18
  239. package/src/server/routes/context.mjs +0 -41
  240. package/src/server/routes/invoke.mjs +26 -1
  241. package/src/server/routes/ssss.mjs +0 -169
  242. package/src/server/routes/system.mjs +0 -15
  243. package/src/server/routes/tasks.mjs +0 -26
  244. package/src/server/routes/vault.mjs +2 -23
  245. package/frontend/dist/assets/index-DD4qONvH.js +0 -5607
  246. package/scaffold/.agent/skills/total-recall/plugins/git-sentinel/README.md +0 -53
  247. package/scaffold/.agent/skills/total-recall/plugins/git-sentinel/plugin.json +0 -129
  248. package/src/core/append-log.mjs +0 -131
  249. package/src/core/plugin-tasks.mjs +0 -173
  250. package/templates/onboarding-interview.md +0 -82
  251. /package/scaffold/.agent/skills/total-recall/plugins/{git-sentinel → git}/LICENSE +0 -0
  252. /package/scaffold/.agent/skills/total-recall/plugins/{git-sentinel → git}/ui/DESIGN.md +0 -0
@@ -20,18 +20,32 @@ export const diffBetween = (cwd, base, head) => must(cwd, ['diff', `${base}...${
20
20
  const ACTIVE_WORKTREES = new Map();
21
21
 
22
22
  /** `branch` creates a new branch from `ref`. Without it, the checkout is detached at `ref` (read-only use). */
23
- export function createWorktree(cwd, { branch, ref = 'HEAD', prefix = 'meta-harness-' } = {}) {
23
+ export function createWorktree(cwd, { branch, ref = 'HEAD', prefix = 'meta-harness-', existingBranch = false } = {}) {
24
24
  const directory = fs.mkdtempSync(path.join(os.tmpdir(), prefix));
25
- const args = branch ? ['worktree', 'add', '-b', branch, directory, ref] : ['worktree', 'add', '--detach', directory, ref];
25
+ const args = branch ? existingBranch ? ['worktree', 'add', directory, branch] : ['worktree', 'add', '-b', branch, directory, ref] : ['worktree', 'add', '--detach', directory, ref];
26
26
  const result = git(cwd, args, 120000);
27
27
  if (result.status !== 0) {
28
28
  fs.rmSync(directory, { recursive: true, force: true });
29
29
  throw new Error(`Creating a worktree failed: ${String(result.stderr).trim().slice(0, 300)}`);
30
30
  }
31
- ACTIVE_WORKTREES.set(directory, { cwd, branch: branch || null });
31
+ ACTIVE_WORKTREES.set(directory, { cwd, branch: branch || null, base: headCommit(directory) });
32
32
  seedMandatorySkills(cwd, directory);
33
+ linkPrivatePlans(cwd, directory);
33
34
  return directory;
34
35
  }
36
+ /**
37
+ * Plans in docs/projects are private and untracked in public repositories, so a checkout lacks them
38
+ * and an agent would start a duplicate plan (A-116). Link the one real plan folder in; never commit it.
39
+ */
40
+ const PLANS = 'docs/projects';
41
+ function linkPrivatePlans(cwd, directory) {
42
+ const root = git(cwd, ['rev-parse', '--show-toplevel']).stdout.trim();
43
+ const source = path.join(root, PLANS), target = path.join(directory, PLANS);
44
+ if (!root || !fs.existsSync(source) || fs.existsSync(target)) return;
45
+ if (git(cwd, ['ls-files', '--', PLANS]).stdout.trim()) return;
46
+ fs.mkdirSync(path.dirname(target), { recursive: true });
47
+ fs.symlinkSync(source, target);
48
+ }
35
49
  /**
36
50
  * An agent's own Total Recall preflight needs these two files at the repository root, and they are
37
51
  * usually gitignored, so a fresh checkout lacks them and every agent inside it would report itself blocked.
@@ -57,17 +71,58 @@ export function linkDependencies(cwd, directory) {
57
71
  const target = path.join(directory, '.agent/skills/code-quality');
58
72
  if (fs.existsSync(quality) && !fs.existsSync(target)) fs.cpSync(quality, target, { recursive: true, filter: source => !source.includes(`${path.sep}reports`) });
59
73
  }
74
+ /**
75
+ * Give an agent's checkout its own dependencies before it starts (A-109). A link would let an
76
+ * agent's `npm install` write into the operator's tree, so the checkout gets a copy-on-write
77
+ * clone of `node_modules` (macOS clonefile, Linux reflink: no extra disk), or, when the operator
78
+ * has none, a frozen install from the lockfile. Returns what it did, for the attempt record.
79
+ */
80
+ export function provideDependencies(cwd, directory, { run = spawnSync } = {}) {
81
+ if (!fs.existsSync(path.join(directory, 'package.json'))) return { action: 'none', reason: 'no package.json' };
82
+ const target = path.join(directory, 'node_modules');
83
+ if (fs.existsSync(target)) return { action: 'present' };
84
+ const modules = path.join(cwd, 'node_modules');
85
+ if (fs.existsSync(modules)) {
86
+ const args = process.platform === 'darwin' ? ['-c', '-R', modules, target] : ['-a', '--reflink=auto', modules, target];
87
+ const copied = run('cp', args, { stdio: 'ignore' });
88
+ if (copied.status === 0) return { action: 'cloned' };
89
+ }
90
+ const lock = [['package-lock.json', 'npm', ['ci', '--no-audit', '--no-fund']], ['pnpm-lock.yaml', 'pnpm', ['install', '--frozen-lockfile']], ['yarn.lock', 'yarn', ['install', '--frozen-lockfile']]]
91
+ .find(([file]) => fs.existsSync(path.join(directory, file)));
92
+ if (!lock) return { action: 'none', reason: 'no lockfile' };
93
+ const installed = run(lock[1], lock[2], { cwd: directory, stdio: 'ignore', timeout: 600000 });
94
+ return installed.status === 0 ? { action: 'installed', manager: lock[1] } : { action: 'failed', manager: lock[1] };
95
+ }
96
+
97
+ /**
98
+ * Push a finished job's branch (A-113, Greg 2026-11-09: agents push finished work themselves).
99
+ * Only `meta-harness/...` branches are pushed, so a job can never push a deploy branch.
100
+ * No `origin` remote means nothing to push. Returns what happened, for the job record.
101
+ */
102
+ export function pushBranch(cwd, branch) {
103
+ if (!branch || !branch.startsWith('meta-harness/')) return { pushed: false, reason: 'not a job branch' };
104
+ if (git(cwd, ['remote', 'get-url', 'origin']).status !== 0) return { pushed: false, reason: 'no origin remote' };
105
+ const result = git(cwd, ['push', '-q', '-u', 'origin', `${branch}:${branch}`], 120000);
106
+ return result.status === 0 ? { pushed: true, remote: 'origin', branch } : { pushed: false, reason: String(result.stderr || result.error || '').trim().slice(0, 300) };
107
+ }
60
108
  export const deleteBranch = (cwd, branch) => git(cwd, ['branch', '-D', branch]).status === 0;
61
109
  export function removeWorktree(cwd, directory) {
62
110
  if (!directory) return;
63
111
  ACTIVE_WORKTREES.delete(directory);
64
- try { if (fs.lstatSync(path.join(directory, 'node_modules')).isSymbolicLink()) fs.rmSync(path.join(directory, 'node_modules')); } catch { /* no link */ }
112
+ for (const link of ['node_modules', PLANS]) {
113
+ try { if (fs.lstatSync(path.join(directory, link)).isSymbolicLink()) fs.rmSync(path.join(directory, link)); } catch { /* no link */ }
114
+ }
65
115
  git(cwd, ['worktree', 'remove', '--force', directory], 60000);
66
116
  fs.rmSync(directory, { recursive: true, force: true });
67
117
  }
68
118
  /** Commit whatever the agent left. Returns the commit, or null when it changed nothing. */
69
119
  export function commitAll(directory, message) {
70
- must(directory, ['add', '-A', '--', '.', ':!node_modules'], 'Staging agent changes');
120
+ // Stage everything git does not ignore. Naming node_modules in the pathspec fails when it is
121
+ // ignored (A-114), so it is unstaged afterwards instead, for repositories that do not ignore it.
122
+ must(directory, ['add', '-A'], 'Staging agent changes');
123
+ git(directory, ['rm', '-r', '--cached', '-q', '--ignore-unmatch', '--', 'node_modules']);
124
+ // The linked private plan folder (A-116) is the operator's, never part of the agent's commit.
125
+ try { if (fs.lstatSync(path.join(directory, PLANS)).isSymbolicLink()) git(directory, ['rm', '-r', '--cached', '-q', '--ignore-unmatch', '--', PLANS]); } catch { /* no link */ }
71
126
  // Seeded skills are scaffolding, not the agent's work. A repository that tracks them keeps normal history.
72
127
  for (const file of MANDATORY_SKILLS) if (git(directory, ['cat-file', '-e', `HEAD:${file}`]).status !== 0) git(directory, ['rm', '--cached', '-q', '--ignore-unmatch', '--', file]);
73
128
  if (git(directory, ['diff', '--cached', '--quiet']).status === 0) return null;
@@ -77,10 +132,22 @@ export function commitAll(directory, message) {
77
132
  must(directory, ['commit', '-m', message], 'Committing agent changes');
78
133
  return headCommit(directory);
79
134
  }
80
- /** A stopped run's checkouts and unfinished branches go with it. A branch already handed back has no active checkout. */
81
- export function removeActiveWorktrees() {
82
- for (const [directory, { cwd, branch }] of [...ACTIVE_WORKTREES]) {
135
+ /** Remove owned checkouts. Cancellation keeps branches that contain work. */
136
+ export function removeActiveWorktrees({ preserveChanges = false } = {}) {
137
+ const saved = [];
138
+ for (const [directory, { cwd, branch, base }] of [...ACTIVE_WORKTREES]) {
139
+ let wip = null;
140
+ if (preserveChanges && branch) {
141
+ try { wip = commitAll(directory, 'meta-harness: unfinished work from a cancelled job'); }
142
+ catch (error) {
143
+ // Do not destroy edits if the WIP commit fails (for example, a credential file).
144
+ saved.push({ branch, directory, error: error.message });
145
+ continue;
146
+ }
147
+ if (wip || headCommit(directory) !== base) saved.push({ branch, wip, commit: headCommit(directory) });
148
+ }
83
149
  removeWorktree(cwd, directory);
84
- if (branch) deleteBranch(cwd, branch);
150
+ if (branch && (!preserveChanges || !saved.some(item => item.branch === branch))) deleteBranch(cwd, branch);
85
151
  }
152
+ return saved;
86
153
  }
@@ -1,9 +1,9 @@
1
- # DESIGN.md — Meta Harness
1
+ # DESIGN.md — Metaharness
2
2
 
3
3
  ```yaml
4
4
  tokens:
5
- brand-name: "Meta Harness"
6
- wordmark: "META HARNESS"
5
+ brand-name: "Metaharness"
6
+ wordmark: "METAHARNESS"
7
7
  color-primary: "#3b82f6"
8
8
  color-background: "#0c1427"
9
9
  color-surface: "#1e293b"
@@ -20,8 +20,8 @@ tokens:
20
20
  ```
21
21
 
22
22
  ## Brand & Typographic Wordmark
23
- - **Name**: Meta Harness
24
- - **Wordmark Logo**: `META HARNESS` (clean typographic badge, no invented cyber delimiters)
23
+ - **Name**: Metaharness
24
+ - **Wordmark Logo**: `METAHARNESS` (clean typographic badge, no invented cyber delimiters)
25
25
  - **Palette**: Primary `#3b82f6`, Surface `#0c1427`, Secondary Surface `#1e293b`, Accent `#38bdf8`, Line `#1e293b`, Text `#f1f5f9`.
26
26
  - **States**: Verified Pass `#10b981`, Warning `#f59e0b`, Danger `#ef4444`.
27
27
 
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Meta Harness — Multi-Agent Coordination & Inspection Console
2
+ * Metaharness — Multi-Agent Coordination & Inspection Console
3
3
  *
4
4
  * Bespoke operator interface for terminal coding agent fleet management.
5
5
  * Displays real-time agent discovery matrix, mesh node targets, authentication
@@ -855,9 +855,9 @@ export class CommandFleetCard extends HTMLElement {
855
855
 
856
856
  <div class="header">
857
857
  <div class="brand-group">
858
- <div class="wordmark-badge">META HARNESS</div>
858
+ <div class="wordmark-badge">METAHARNESS</div>
859
859
  <div class="title-meta">
860
- <h3 class="plugin-title">Meta Harness Fleet</h3>
860
+ <h3 class="plugin-title">Metaharness Fleet</h3>
861
861
  <p class="plugin-subtitle">Multi-agent runtime coordination, quotas & benchmarks</p>
862
862
  </div>
863
863
  </div>
@@ -16,6 +16,7 @@ import { getTokenStatus, setTokenValue } from './src/token.mjs';
16
16
  import { lintWikiHubs } from './src/lint.mjs';
17
17
  import { generateWiki } from './src/generate.mjs';
18
18
  import { retrieveContext } from './src/context-provider.mjs';
19
+ import { refreshDiagnostics } from './src/refresh-diagnostics.mjs';
19
20
 
20
21
  /**
21
22
  * Regenerate the generated pages of every registered project that carries them.
@@ -25,7 +26,14 @@ import { retrieveContext } from './src/context-provider.mjs';
25
26
  * Defaults to a report; --apply performs the refreshes, because regenerating a
26
27
  * repository's documentation is a write to that repository.
27
28
  */
28
- async function refreshCommand(args) {
29
+ export async function refreshCommand(args, {
30
+ read = readProjects, dueFor = isDue, refresh = refreshProjectAsync,
31
+ getKey = resolveKey, configFor = loadOpenWikiConfig,
32
+ } = {}) {
33
+ if (args.includes('--help') || args.includes('-h')) {
34
+ console.log('Usage: total-recall openwiki refresh [--repo <name>] [--apply] [--force] [--diagnostics [--slot <local-minute>]] [--json]');
35
+ return;
36
+ }
29
37
  const json = args.includes('--json');
30
38
  const apply = args.includes('--apply');
31
39
  const force = args.includes('--force');
@@ -37,7 +45,7 @@ async function refreshCommand(args) {
37
45
 
38
46
  let projects;
39
47
  try {
40
- projects = readProjects();
48
+ projects = read();
41
49
  } catch (err) {
42
50
  if (json) console.log(JSON.stringify({ ok: false, error: err.message }));
43
51
  else console.error(`OpenWiki refresh: ${err.message}`);
@@ -52,20 +60,28 @@ async function refreshCommand(args) {
52
60
  return;
53
61
  }
54
62
 
63
+ if (args.includes('--diagnostics')) {
64
+ const slotIndex = args.indexOf('--slot');
65
+ const result = await refreshDiagnostics({ projects, slot: slotIndex >= 0 ? args[slotIndex + 1] : null });
66
+ console.log(JSON.stringify(result, null, 2));
67
+ if (!result.ok) process.exitCode = 1;
68
+ return;
69
+ }
70
+
55
71
  const reports = [];
56
72
  for (const project of projects) {
57
73
  let state;
58
74
  try {
59
- state = force ? { due: true, ...staleness(project.root) } : isDue(project);
75
+ state = dueFor(project, { force });
60
76
  } catch (err) {
61
- reports.push({ ...project, action: 'skipped', reason: err.message });
77
+ reports.push({ ...project, action: 'failed', reason: err.message });
62
78
  continue;
63
79
  }
64
80
  if (!state.due) {
65
81
  if (state.skipped) {
66
82
  reports.push({ ...project, action: 'skipped', reason: state.reason });
67
83
  } else {
68
- reports.push({ ...project, action: 'current', generatedAt: state.generatedAt, commitsSince: state.commitsSince });
84
+ reports.push({ ...project, action: 'current', reason: state.reason, generationCommit: state.generationCommit, generationTime: state.generationTime, generatedAt: state.generatedAt, commitsSince: state.commitsSince });
69
85
  }
70
86
  continue;
71
87
  }
@@ -73,7 +89,10 @@ async function refreshCommand(args) {
73
89
  ...project,
74
90
  action: 'due',
75
91
  uninitialized: Boolean(state.uninitialized),
92
+ mode: state.mode,
76
93
  generatedAt: state.generatedAt,
94
+ generationCommit: state.generationCommit,
95
+ generationTime: state.generationTime,
77
96
  commitsSince: state.commitsSince,
78
97
  reason: state.reason
79
98
  });
@@ -82,8 +101,8 @@ async function refreshCommand(args) {
82
101
  const due = reports.filter((r) => r.action === 'due');
83
102
  let payloadBudgetNote = null;
84
103
  if (apply && due.length) {
85
- const config = loadOpenWikiConfig();
86
- const { key, from } = resolveKey({ provider: config.provider });
104
+ const config = configFor();
105
+ const { key, from } = getKey({ provider: config.provider });
87
106
  if (!key) {
88
107
  const keyName = config.provider === 'google' ? 'GOOGLE_API_KEY' : 'OPENROUTER_API_KEY';
89
108
  const error = `No model credential for provider '${config.provider}'. Save via: total-recall auth secret set ${keyName} --stdin`;
@@ -109,20 +128,25 @@ async function refreshCommand(args) {
109
128
  while (queueIndex < due.length) {
110
129
  const itemIndex = queueIndex++;
111
130
  const entry = due[itemIndex];
112
- const mode = entry.uninitialized ? 'init' : 'update';
131
+ const mode = entry.mode || (entry.uninitialized ? 'init' : 'update');
113
132
  if (!json) {
114
133
  console.log(`[${itemIndex + 1}/${due.length}] ▶ ${entry.name.padEnd(28)} starting ${mode}...`);
115
134
  }
116
- const result = await refreshProjectAsync(
117
- { name: entry.name, root: entry.root },
118
- { key, model: config.model, provider: config.provider, timeoutMs: config.timeout_ms }
119
- );
135
+ let result;
136
+ try {
137
+ result = await refresh(
138
+ { name: entry.name, root: entry.root },
139
+ { key, model: config.model, provider: config.provider, timeoutMs: config.timeout_ms }
140
+ );
141
+ } catch (error) {
142
+ result = { action: 'failed', reason: error.message.split(key).join('[REDACTED]') };
143
+ }
120
144
  completedCount++;
121
145
  const index = reports.findIndex((r) => r.root === entry.root);
122
146
  reports[index] = { ...reports[index], ...result, credential: from };
123
147
  if (!json) {
124
- const duration = Math.round((Date.now() - (result.startedAt || Date.now())) / 1000);
125
- const icon = result.action === 'failed' ? '✖' : '✔';
148
+ const duration = Math.round((result.durationMs || 0) / 1000);
149
+ const icon = ['failed', 'partial'].includes(result.action) ? '✖' : '✔';
126
150
  console.log(`[${completedCount}/${due.length}] ${icon} ${entry.name.padEnd(28)} ${result.action} (${duration}s)${result.reason ? ` — ${result.reason}` : ''}`);
127
151
  }
128
152
  }
@@ -133,8 +157,9 @@ async function refreshCommand(args) {
133
157
  }
134
158
 
135
159
  const failed = reports.filter((r) => r.action === 'failed');
160
+ const partial = reports.filter((r) => r.action === 'partial');
136
161
  const payload = {
137
- ok: failed.length === 0,
162
+ ok: failed.length === 0 && partial.length === 0,
138
163
  applied: apply,
139
164
  retention: describeRetention(),
140
165
  note: payloadBudgetNote,
@@ -145,6 +170,8 @@ async function refreshCommand(args) {
145
170
  uninitialized: reports.filter((r) => r.uninitialized).length,
146
171
  refreshed: reports.filter((r) => r.action === 'refreshed' || r.action === 'initialized').length,
147
172
  failed: failed.length,
173
+ partial: partial.length,
174
+ skipped: reports.filter((r) => r.action === 'skipped').length,
148
175
  current: reports.filter((r) => r.action === 'current').length,
149
176
  },
150
177
  reports,
@@ -152,15 +179,17 @@ async function refreshCommand(args) {
152
179
  if (json) console.log(JSON.stringify(payload, null, 2));
153
180
  else {
154
181
  console.log(`OpenWiki refresh (${apply ? 'apply' : 'report'}): ${payload.counts.registered} registered, ${payload.counts.due} due (${payload.counts.uninitialized} uninitialized)`);
155
- for (const r of reports) {
182
+ // Put failures last so bounded scheduler tails retain their causes.
183
+ for (const r of [...reports].sort((a, b) => Number(['failed', 'partial'].includes(a.action)) - Number(['failed', 'partial'].includes(b.action)))) {
156
184
  if (r.action === 'current') continue;
157
- const age = r.uninitialized ? 'uninitialized' : (r.generatedAt ? `generated ${r.generatedAt.slice(0, 10)}` : 'never generated');
185
+ const age = r.action === 'skipped' ? 'outside repository generation' : r.generationTime ? `generated ${r.generationTime} at ${r.generationCommit}` : r.uninitialized ? 'uninitialized' : (r.generatedAt ? `last attempt ${r.generatedAt}; generation commit unknown` : 'never generated');
158
186
  console.log(` ${r.action.padEnd(9)} ${r.name.padEnd(28)} ${age}${Number.isFinite(r.commitsSince) && r.commitsSince !== Infinity ? `, ${r.commitsSince} commits since` : ''}${r.reason ? ` — ${r.reason}` : ''}`);
159
187
  }
160
188
  if (payloadBudgetNote) console.log(payloadBudgetNote);
161
189
  if (!apply && due.length) console.log('Re-run with --apply to regenerate. Pages are a projection; vault content is never touched.');
162
190
  }
163
- if (failed.length) process.exitCode = 1;
191
+ if (!payload.ok) process.exitCode = 1;
192
+ return payload;
164
193
  }
165
194
 
166
195
  async function probeCommand(args) {
@@ -1,18 +1,18 @@
1
1
  {
2
2
  "name": "tr-plugin-openwiki",
3
- "version": "0.1.9",
3
+ "version": "0.1.11",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "tr-plugin-openwiki",
9
- "version": "0.1.9",
9
+ "version": "0.1.11",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
- "@gregiteen/ssss-cli": "0.14.4"
12
+ "@gregiteen/ssss-cli": "0.14.5"
13
13
  },
14
14
  "devDependencies": {
15
- "total-recall-brain": "3.42.1"
15
+ "total-recall-brain": "3.44.0"
16
16
  }
17
17
  },
18
18
  "node_modules/@alcalzone/ansi-tokenize": {
@@ -715,9 +715,9 @@
715
715
  "license": "MIT"
716
716
  },
717
717
  "node_modules/@gregiteen/ssss-cli": {
718
- "version": "0.14.4",
719
- "resolved": "https://registry.npmjs.org/@gregiteen/ssss-cli/-/ssss-cli-0.14.4.tgz",
720
- "integrity": "sha512-R6JIgPRvS9xXp0xb6BYO3rauv+72r35GIiDrJcvbjPdTSHFZXr8/jRxFOgoF8yTed/5xyGFF3ey3DI9bOjmHVA==",
718
+ "version": "0.14.5",
719
+ "resolved": "https://registry.npmjs.org/@gregiteen/ssss-cli/-/ssss-cli-0.14.5.tgz",
720
+ "integrity": "sha512-qVEYOocnwn97uJ0eDzmuwN06CYsYWr2t3+iKylpisBHX4wlLWk7P8EmFFdBlx7NyKVIZDDeYT164Gd7/T8UGgw==",
721
721
  "license": "ISC",
722
722
  "bin": {
723
723
  "ssss": "scripts/ssss.mjs"
@@ -1590,9 +1590,9 @@
1590
1590
  },
1591
1591
  "node_modules/@ssss/cli": {
1592
1592
  "name": "@gregiteen/ssss-cli",
1593
- "version": "0.14.4",
1594
- "resolved": "https://registry.npmjs.org/@gregiteen/ssss-cli/-/ssss-cli-0.14.4.tgz",
1595
- "integrity": "sha512-R6JIgPRvS9xXp0xb6BYO3rauv+72r35GIiDrJcvbjPdTSHFZXr8/jRxFOgoF8yTed/5xyGFF3ey3DI9bOjmHVA==",
1593
+ "version": "0.14.5",
1594
+ "resolved": "https://registry.npmjs.org/@gregiteen/ssss-cli/-/ssss-cli-0.14.5.tgz",
1595
+ "integrity": "sha512-qVEYOocnwn97uJ0eDzmuwN06CYsYWr2t3+iKylpisBHX4wlLWk7P8EmFFdBlx7NyKVIZDDeYT164Gd7/T8UGgw==",
1596
1596
  "dev": true,
1597
1597
  "license": "ISC",
1598
1598
  "bin": {
@@ -5529,9 +5529,9 @@
5529
5529
  }
5530
5530
  },
5531
5531
  "node_modules/total-recall-brain": {
5532
- "version": "3.42.1",
5533
- "resolved": "https://registry.npmjs.org/total-recall-brain/-/total-recall-brain-3.42.1.tgz",
5534
- "integrity": "sha512-woH7mdkGwPFYlKPZurhE8L3BPe+cSeIruNGaPOjGZJm/O8C92Bbr1gsdOY0tTLg5QHlgPHcXG1GMtsm9lPDz8w==",
5532
+ "version": "3.44.0",
5533
+ "resolved": "https://registry.npmjs.org/total-recall-brain/-/total-recall-brain-3.44.0.tgz",
5534
+ "integrity": "sha512-VNPaIO9zsSwoxAsJ5ByIQBP9zPpLq4RiQO7Vrex4rBOHFQJT50P7utcZiLMSZTyZJU4C/m5uB8qTCSBMp6+l6Q==",
5535
5535
  "dev": true,
5536
5536
  "license": "MIT",
5537
5537
  "workspaces": [
@@ -5539,7 +5539,7 @@
5539
5539
  ],
5540
5540
  "dependencies": {
5541
5541
  "@simplewebauthn/server": "^13.3.2",
5542
- "@ssss/cli": "npm:@gregiteen/ssss-cli@0.14.4",
5542
+ "@ssss/cli": "npm:@gregiteen/ssss-cli@0.14.5",
5543
5543
  "bcrypt": "^6.0.0",
5544
5544
  "better-sqlite3": "^12.11.1",
5545
5545
  "cookie-parser": "^1.4.7",
@@ -5562,6 +5562,7 @@
5562
5562
  "antigravity": "bin/antigravity.mjs",
5563
5563
  "total-recall": "bin/total-recall.mjs",
5564
5564
  "total-recall-memory": "bin/total-recall-memory.mjs",
5565
+ "total-recall-server-release": "bin/total-recall-server-release.mjs",
5565
5566
  "vibebrain": "bin/total-recall.mjs"
5566
5567
  },
5567
5568
  "optionalDependencies": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tr-plugin-openwiki",
3
- "version": "0.1.9",
3
+ "version": "0.1.11",
4
4
  "type": "module",
5
5
  "description": "Multi-repo knowledge graph and documentation wiki engine for Total Recall",
6
6
  "scripts": {
@@ -20,9 +20,9 @@
20
20
  "templates/"
21
21
  ],
22
22
  "dependencies": {
23
- "@gregiteen/ssss-cli": "0.14.4"
23
+ "@gregiteen/ssss-cli": "0.14.5"
24
24
  },
25
25
  "overrides": {
26
- "@ssss/cli": "npm:@gregiteen/ssss-cli@0.14.4"
26
+ "@ssss/cli": "npm:@gregiteen/ssss-cli@0.14.5"
27
27
  }
28
28
  }
@@ -2,7 +2,7 @@
2
2
  "$schema": "https://github.com/gregiteen/total-recall/blob/main/metadata.plugin.schema.json",
3
3
  "id": "openwiki",
4
4
  "name": "OpenWiki",
5
- "version": "0.1.9",
5
+ "version": "0.1.11",
6
6
  "description": "Multi-repo knowledge graph and documentation wiki engine for Total Recall.",
7
7
  "license": "MIT",
8
8
  "runtime": {
@@ -0,0 +1,44 @@
1
+ import fs from 'node:fs';
2
+ import os from 'node:os';
3
+ import path from 'node:path';
4
+ import { pathToFileURL } from 'node:url';
5
+ import { readProjects } from './refresh.mjs';
6
+
7
+ /** Read through Total Recall's event service. Never open vault files here. */
8
+ async function readTaskEvents(options) {
9
+ const service = process.env.TR_PACKAGE_ROOT
10
+ ? pathToFileURL(path.join(process.env.TR_PACKAGE_ROOT, 'src', 'core', 'ssss-operation-service.mjs')).href
11
+ : 'total-recall-brain/src/core/ssss-operation-service.mjs';
12
+ const { listVfsEvents } = await import(service);
13
+ return listVfsEvents(options);
14
+ }
15
+
16
+ export async function refreshDiagnostics({
17
+ projects = readProjects(),
18
+ vaultRoot = path.join(os.homedir(), '.agent', 'skills', 'total-recall', 'memory-vault'),
19
+ listEvents = readTaskEvents,
20
+ slot = null,
21
+ } = {}) {
22
+ let taskEvents = [], eventError = null;
23
+ try {
24
+ taskEvents = (await listEvents({ vaultRoot })).flatMap(event => {
25
+ let payload = event.payload || event.content;
26
+ if (typeof payload === 'string') {
27
+ try { payload = JSON.parse(payload); } catch { return []; }
28
+ }
29
+ return payload?.kind === 'plugin.task_run' && payload.plugin_id === 'openwiki' && payload.command === 'auto-refresh'
30
+ ? [{ at: event.timestamp || event.created_at || null, ...payload }] : [];
31
+ });
32
+ } catch (error) { eventError = error.message; }
33
+ taskEvents.sort((a, b) => String(a.at).localeCompare(String(b.at)));
34
+ taskEvents = slot ? taskEvents.filter(event => event.slot === slot) : taskEvents.slice(-1);
35
+ const reports = projects.map(project => {
36
+ const logPath = path.join(project.root, 'openwiki', '.refresh-attempt.json');
37
+ try { return { ...project, logPath, attempt: JSON.parse(fs.readFileSync(logPath, 'utf8')) }; }
38
+ catch (error) { return { ...project, logPath, attempt: null, logError: error.code === 'ENOENT' ? 'No retained generator output' : error.message }; }
39
+ });
40
+ return {
41
+ ok: !eventError, eventError, taskEvents, reports,
42
+ note: 'Task events retain only an output tail. Full legacy generator output was not saved; it cannot be reconstructed from that tail.',
43
+ };
44
+ }