total-recall-brain 3.45.0 → 3.46.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (362) hide show
  1. package/bin/total-recall.mjs +4 -2
  2. package/frontend/dist/assets/index-BRYE1jmv.css +1 -0
  3. package/frontend/dist/assets/index-D1goIPjC.js +5598 -0
  4. package/frontend/dist/index.html +2 -2
  5. package/frontend/dist/sw.js +5 -4
  6. package/frontend/src/App.tsx +183 -236
  7. package/frontend/src/api/auth-inventory.ts +62 -0
  8. package/frontend/src/api/memory.ts +13 -8
  9. package/frontend/src/api/plugin-credentials.ts +23 -0
  10. package/frontend/src/api/plugins.ts +37 -53
  11. package/frontend/src/api/workspace-drawers.ts +97 -0
  12. package/frontend/src/components/BrainSelector.tsx +9 -3
  13. package/frontend/src/components/plugins/PluginPanel.tsx +83 -42
  14. package/frontend/src/components/plugins/PluginSettings.tsx +10 -20
  15. package/frontend/src/components/plugins/PluginWorkspace.tsx +367 -0
  16. package/frontend/src/components/plugins/ScopedPluginCommands.tsx +142 -0
  17. package/frontend/src/components/plugins/plugin-frame.ts +44 -33
  18. package/frontend/src/components/plugins/scoped-plugin-operations.ts +28 -0
  19. package/frontend/src/components/workspace/DrawerChat.tsx +110 -0
  20. package/frontend/src/components/workspace/DrawerLayout.tsx +196 -0
  21. package/frontend/src/components/workspace/DrawerMarkup.tsx +49 -0
  22. package/frontend/src/components/workspace/PluginChunkLibrary.tsx +92 -0
  23. package/frontend/src/components/workspace/PluginHome.tsx +76 -0
  24. package/frontend/src/components/workspace/WorkspaceDrawers.tsx +96 -0
  25. package/frontend/src/components/workspace/WorkspacePage.tsx +95 -0
  26. package/frontend/src/components/workspace/usePluginDesign.ts +38 -0
  27. package/frontend/src/index.css +409 -136
  28. package/frontend/src/pages/HelpPage.tsx +15 -46
  29. package/frontend/src/pages/MemoryPage.tsx +19 -36
  30. package/frontend/src/pages/SettingsPage.tsx +1 -1
  31. package/metadata.plugin.schema.json +53 -227
  32. package/package.json +1 -1
  33. package/scaffold/.agent/skills/plugin/SKILL.md +13 -11
  34. package/scaffold/.agent/skills/plugin/evals/README.md +14 -21
  35. package/scaffold/.agent/skills/plugin/evals/cases/01-fabricated-seed.mjs +15 -18
  36. package/scaffold/.agent/skills/plugin/evals/cases/02-reassuring-default.mjs +19 -24
  37. package/scaffold/.agent/skills/plugin/evals/cases/03-declared-template.mjs +12 -20
  38. package/scaffold/.agent/skills/plugin/evals/cases/04-home-collects-credential.mjs +35 -0
  39. package/scaffold/.agent/skills/plugin/evals/cases/05-host-leak-in-scaffold.mjs +8 -28
  40. package/scaffold/.agent/skills/plugin/evals/cases/06-correct-plugin.mjs +85 -47
  41. package/scaffold/.agent/skills/plugin/evals/run.mjs +17 -18
  42. package/scaffold/.agent/skills/plugin/prompts/05-credentials.md +4 -4
  43. package/scaffold/.agent/skills/plugin/prompts/07-scaffold.md +2 -2
  44. package/scaffold/.agent/skills/plugin/prompts/08-verify.md +4 -4
  45. package/scaffold/.agent/skills/plugin/references/anti-patterns.md +2 -2
  46. package/scaffold/.agent/skills/plugin/references/generative-home.md +38 -0
  47. package/scaffold/.agent/skills/plugin/references/scaffold.md +5 -5
  48. package/scaffold/.agent/skills/plugin/references/surfaces.md +13 -4
  49. package/scaffold/.agent/skills/plugin/scripts/record.mjs +75 -153
  50. package/scaffold/.agent/skills/plugin/subagents/plugin-reviewer.md +4 -4
  51. package/scaffold/.agent/skills/total-recall/plugins/auth/DESIGN.md +76 -0
  52. package/scaffold/.agent/skills/total-recall/plugins/auth/README.md +3 -1
  53. package/scaffold/.agent/skills/total-recall/plugins/auth/cli.mjs +20 -15
  54. package/scaffold/.agent/skills/total-recall/plugins/auth/package-lock.json +6 -6
  55. package/scaffold/.agent/skills/total-recall/plugins/auth/package.json +2 -1
  56. package/scaffold/.agent/skills/total-recall/plugins/auth/plugin.json +13 -51
  57. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/access-overview.md +17 -0
  58. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/agent-login.md +20 -0
  59. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/baseline-audit.md +22 -0
  60. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/credential-repository-binding.md +17 -0
  61. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/credential-store-maintenance.md +17 -0
  62. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/dashboard-password.md +18 -0
  63. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/dashboard-sessions.md +18 -0
  64. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/endpoint-probe.md +23 -0
  65. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/google-sign-in.md +21 -0
  66. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/mesh-machines.md +16 -0
  67. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/passkey-enrollment.md +21 -0
  68. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/registered-brains.md +16 -0
  69. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/scoped-access-keys.md +17 -0
  70. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/secret-inventory.md +25 -0
  71. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/signing-key-rotation.md +22 -0
  72. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/home.js +375 -0
  73. package/scaffold/.agent/skills/total-recall/plugins/automations/{ui/DESIGN.md → DESIGN.md} +32 -21
  74. package/scaffold/.agent/skills/total-recall/plugins/automations/adapters.mjs +17 -1
  75. package/scaffold/.agent/skills/total-recall/plugins/automations/cli.mjs +10 -1
  76. package/scaffold/.agent/skills/total-recall/plugins/automations/package-lock.json +6 -6
  77. package/scaffold/.agent/skills/total-recall/plugins/automations/package.json +4 -3
  78. package/scaffold/.agent/skills/total-recall/plugins/automations/plugin.json +11 -27
  79. package/scaffold/.agent/skills/total-recall/plugins/automations/ui/automations.js +2 -2
  80. package/scaffold/.agent/skills/total-recall/plugins/automations/ui/chunks/control-ledger.md +42 -0
  81. package/scaffold/.agent/skills/total-recall/plugins/automations/ui/chunks/local-inventory-triage.md +17 -0
  82. package/scaffold/.agent/skills/total-recall/plugins/automations/ui/chunks/pending-control.md +39 -0
  83. package/scaffold/.agent/skills/total-recall/plugins/automations/ui/chunks/run-evidence.md +41 -0
  84. package/scaffold/.agent/skills/total-recall/plugins/automations/ui/chunks/schedule-vs-run-evidence.md +17 -0
  85. package/scaffold/.agent/skills/total-recall/plugins/automations/ui/chunks/source-coverage.md +41 -0
  86. package/scaffold/.agent/skills/total-recall/plugins/automations/ui/{card.js → home.js} +32 -27
  87. package/scaffold/.agent/skills/total-recall/plugins/code-quality/DESIGN.md +53 -0
  88. package/scaffold/.agent/skills/total-recall/plugins/code-quality/cli.mjs +23 -0
  89. package/scaffold/.agent/skills/total-recall/plugins/code-quality/commands/run-core.mjs +4 -2
  90. package/scaffold/.agent/skills/total-recall/plugins/code-quality/core/check.mjs +4 -2
  91. package/scaffold/.agent/skills/total-recall/plugins/code-quality/package-lock.json +6 -6
  92. package/scaffold/.agent/skills/total-recall/plugins/code-quality/package.json +2 -1
  93. package/scaffold/.agent/skills/total-recall/plugins/code-quality/plugin.json +40 -40
  94. package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/chunks/config.md +15 -0
  95. package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/chunks/detect.md +15 -0
  96. package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/chunks/gate.md +15 -0
  97. package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/chunks/init.md +15 -0
  98. package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/chunks/report.md +17 -0
  99. package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/chunks/run.md +17 -0
  100. package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/chunks/snapshot.md +15 -0
  101. package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/code-quality-report.mjs +55 -23
  102. package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/home.mjs +214 -0
  103. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/DESIGN.md +146 -0
  104. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/package-lock.json +6 -6
  105. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/package.json +2 -1
  106. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/plugin.json +51 -34
  107. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/src/command.mjs +1 -1
  108. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/create.md +35 -0
  109. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/history.md +35 -0
  110. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/library.md +49 -0
  111. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/list.md +42 -0
  112. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/promote.md +40 -0
  113. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/read.md +25 -0
  114. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/remove.md +26 -0
  115. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/rollback.md +26 -0
  116. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/show.md +53 -0
  117. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/status.md +40 -0
  118. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/test-path.md +38 -0
  119. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/test.md +46 -0
  120. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/update.md +32 -0
  121. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/home.js +533 -0
  122. package/scaffold/.agent/skills/total-recall/plugins/embeddings/DESIGN.md +110 -0
  123. package/scaffold/.agent/skills/total-recall/plugins/embeddings/package-lock.json +6 -6
  124. package/scaffold/.agent/skills/total-recall/plugins/embeddings/package.json +2 -1
  125. package/scaffold/.agent/skills/total-recall/plugins/embeddings/plugin.json +13 -10
  126. package/scaffold/.agent/skills/total-recall/plugins/embeddings/ui/chunks/benchmark.md +49 -0
  127. package/scaffold/.agent/skills/total-recall/plugins/embeddings/ui/chunks/coverage.md +53 -0
  128. package/scaffold/.agent/skills/total-recall/plugins/embeddings/ui/chunks/models.md +43 -0
  129. package/scaffold/.agent/skills/total-recall/plugins/embeddings/ui/chunks/pull.md +41 -0
  130. package/scaffold/.agent/skills/total-recall/plugins/embeddings/ui/chunks/status.md +59 -0
  131. package/scaffold/.agent/skills/total-recall/plugins/embeddings/ui/home.js +353 -0
  132. package/scaffold/.agent/skills/total-recall/plugins/git/DESIGN.md +31 -0
  133. package/scaffold/.agent/skills/total-recall/plugins/git/README.md +25 -1
  134. package/scaffold/.agent/skills/total-recall/plugins/git/cli.mjs +5 -1
  135. package/scaffold/.agent/skills/total-recall/plugins/git/package-lock.json +6 -6
  136. package/scaffold/.agent/skills/total-recall/plugins/git/package.json +2 -1
  137. package/scaffold/.agent/skills/total-recall/plugins/git/plugin.json +17 -27
  138. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/commit-memory.mjs +30 -6
  139. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/fleet.mjs +24 -6
  140. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/secret-firewall.mjs +33 -7
  141. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/undo.mjs +29 -5
  142. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/unmerged.mjs +182 -0
  143. package/scaffold/.agent/skills/total-recall/plugins/git/ui/chunks/change-comparison.md +27 -0
  144. package/scaffold/.agent/skills/total-recall/plugins/git/ui/chunks/commit-identity.md +22 -0
  145. package/scaffold/.agent/skills/total-recall/plugins/git/ui/chunks/create-worktree.md +25 -0
  146. package/scaffold/.agent/skills/total-recall/plugins/git/ui/chunks/registered-worktrees.md +22 -0
  147. package/scaffold/.agent/skills/total-recall/plugins/git/ui/chunks/remove-worktree.md +23 -0
  148. package/scaffold/.agent/skills/total-recall/plugins/git/ui/chunks/repository-ledger.md +25 -0
  149. package/scaffold/.agent/skills/total-recall/plugins/git/ui/chunks/unmerged-work.md +22 -0
  150. package/scaffold/.agent/skills/total-recall/plugins/git/ui/chunks/upstream-divergence.md +17 -0
  151. package/scaffold/.agent/skills/total-recall/plugins/git/ui/chunks/worktree-conflict-triage.md +17 -0
  152. package/scaffold/.agent/skills/total-recall/plugins/git/ui/chunks/worktree-terminal.md +22 -0
  153. package/scaffold/.agent/skills/total-recall/plugins/git/ui/home.js +273 -0
  154. package/scaffold/.agent/skills/total-recall/plugins/mesh/DESIGN.md +35 -0
  155. package/scaffold/.agent/skills/total-recall/plugins/mesh/README.md +4 -5
  156. package/scaffold/.agent/skills/total-recall/plugins/mesh/cli.mjs +9 -3
  157. package/scaffold/.agent/skills/total-recall/plugins/mesh/package-lock.json +6 -6
  158. package/scaffold/.agent/skills/total-recall/plugins/mesh/package.json +2 -1
  159. package/scaffold/.agent/skills/total-recall/plugins/mesh/plugin.json +37 -39
  160. package/scaffold/.agent/skills/total-recall/plugins/mesh/src/cli/mesh.mjs +5 -3
  161. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/active-device-dispatch.md +22 -0
  162. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/control-probe.md +25 -0
  163. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/control-server.md +22 -0
  164. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/credential-readiness.md +23 -0
  165. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/elected-leader.md +22 -0
  166. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/enrollment-key.md +22 -0
  167. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/file-receipt.md +25 -0
  168. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/fleet-execution.md +23 -0
  169. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/fleet-presence.md +23 -0
  170. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/interactive-ssh.md +22 -0
  171. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/local-enrollment.md +23 -0
  172. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/mesh-policy.md +23 -0
  173. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/network-atlas.md +25 -0
  174. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/node-roster.md +26 -0
  175. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/node-selection-proof.md +17 -0
  176. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/owner-observations.md +23 -0
  177. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/peer-path.md +23 -0
  178. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/pinned-leader.md +24 -0
  179. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/reachability-evidence-ladder.md +17 -0
  180. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/recorded-login.md +23 -0
  181. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/remote-execution.md +22 -0
  182. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/secret-grants.md +26 -0
  183. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/{card.js → home.js} +93 -22
  184. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/DESIGN.md +86 -0
  185. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/README.md +19 -0
  186. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/cli.mjs +5 -1
  187. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/package-lock.json +6 -6
  188. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/package.json +2 -1
  189. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/plugin.json +43 -22
  190. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/chat.mjs +80 -0
  191. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/adapter-docs-freshness.md +16 -0
  192. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/chat-handoff.md +26 -0
  193. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/fleet-maintenance.md +21 -0
  194. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/harness-inventory.md +21 -0
  195. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/included-access.md +18 -0
  196. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/included-usage-verification.md +15 -0
  197. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/independent-review.md +17 -0
  198. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/managed-execution.md +20 -0
  199. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/official-documentation.md +18 -0
  200. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/quota-recovery.md +21 -0
  201. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/review-routing-decision.md +16 -0
  202. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/route-work.md +18 -0
  203. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/routing-evidence.md +18 -0
  204. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/run-ledger.md +18 -0
  205. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/home.js +198 -0
  206. package/scaffold/.agent/skills/total-recall/plugins/openwiki/DESIGN.md +75 -0
  207. package/scaffold/.agent/skills/total-recall/plugins/openwiki/README.md +2 -0
  208. package/scaffold/.agent/skills/total-recall/plugins/openwiki/cli.mjs +17 -14
  209. package/scaffold/.agent/skills/total-recall/plugins/openwiki/package-lock.json +6 -6
  210. package/scaffold/.agent/skills/total-recall/plugins/openwiki/package.json +2 -1
  211. package/scaffold/.agent/skills/total-recall/plugins/openwiki/plugin.json +10 -44
  212. package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/generate.mjs +5 -4
  213. package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/graph.mjs +3 -4
  214. package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/ingest.mjs +23 -18
  215. package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/mesh-vaults.mjs +8 -3
  216. package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/refresh.mjs +6 -3
  217. package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/search.mjs +3 -5
  218. package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/token.mjs +21 -47
  219. package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/upstream-watcher.mjs +17 -6
  220. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/auto-refresh.md +18 -0
  221. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/bootstrap-pages.md +18 -0
  222. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/generate-wiki.md +21 -0
  223. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/generator-settings.md +18 -0
  224. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/host-probe.md +18 -0
  225. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/ingest-preview.md +18 -0
  226. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/link-hygiene.md +21 -0
  227. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/link-topology.md +19 -0
  228. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/passage-search.md +19 -0
  229. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/propagation-plan.md +18 -0
  230. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/provider-credentials.md +18 -0
  231. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/refresh-report.md +18 -0
  232. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/task-evidence.md +22 -0
  233. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/upstream-record.md +18 -0
  234. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/watch-upstream.md +18 -0
  235. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/wiki-atlas.md +19 -0
  236. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/panel.js +261 -513
  237. package/scaffold/.agent/skills/total-recall/plugins/security/DESIGN.md +84 -0
  238. package/scaffold/.agent/skills/total-recall/plugins/security/README.md +4 -2
  239. package/scaffold/.agent/skills/total-recall/plugins/security/cli.mjs +7 -19
  240. package/scaffold/.agent/skills/total-recall/plugins/security/package-lock.json +6 -6
  241. package/scaffold/.agent/skills/total-recall/plugins/security/package.json +2 -3
  242. package/scaffold/.agent/skills/total-recall/plugins/security/plugin.json +19 -52
  243. package/scaffold/.agent/skills/total-recall/plugins/security/ui/chunks/device-evidence.md +21 -0
  244. package/scaffold/.agent/skills/total-recall/plugins/security/ui/chunks/evidence-desk.md +18 -0
  245. package/scaffold/.agent/skills/total-recall/plugins/security/ui/chunks/guided-device-review.md +17 -0
  246. package/scaffold/.agent/skills/total-recall/plugins/security/ui/chunks/host-and-network.md +21 -0
  247. package/scaffold/.agent/skills/total-recall/plugins/security/ui/chunks/https-headers.md +17 -0
  248. package/scaffold/.agent/skills/total-recall/plugins/security/ui/chunks/mesh-coverage.md +18 -0
  249. package/scaffold/.agent/skills/total-recall/plugins/security/ui/chunks/private-security-tools.md +16 -0
  250. package/scaffold/.agent/skills/total-recall/plugins/security/ui/chunks/single-origin-header-check.md +17 -0
  251. package/scaffold/.agent/skills/total-recall/plugins/security/ui/chunks/source-review.md +21 -0
  252. package/scaffold/.agent/skills/total-recall/plugins/security/ui/chunks/ssh-permission-plan.md +17 -0
  253. package/scaffold/.agent/skills/total-recall/plugins/security/ui/home.js +283 -0
  254. package/scaffold/.agent/skills/total-recall/plugins/ssss/DESIGN.md +93 -0
  255. package/scaffold/.agent/skills/total-recall/plugins/ssss/package-lock.json +2 -2
  256. package/scaffold/.agent/skills/total-recall/plugins/ssss/package.json +2 -1
  257. package/scaffold/.agent/skills/total-recall/plugins/ssss/plugin.json +5 -3
  258. package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/chunks/conformance.md +26 -0
  259. package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/chunks/registry.md +37 -0
  260. package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/chunks/repair.md +42 -0
  261. package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/chunks/scaffold.md +33 -0
  262. package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/chunks/status.md +43 -0
  263. package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/chunks/validate.md +34 -0
  264. package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/chunks/validation-diagnostics.md +17 -0
  265. package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/chunks/workspace-registry-preflight.md +17 -0
  266. package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/home.js +348 -0
  267. package/scaffold/.agent/skills/total-recall/references/operations.md +2 -0
  268. package/src/cli/api.mjs +3 -3
  269. package/src/cli/brief.mjs +3 -0
  270. package/src/cli/config.mjs +16 -0
  271. package/src/cli/connect.mjs +2 -7
  272. package/src/cli/plugin/chunks.mjs +145 -0
  273. package/src/cli/plugin/create.mjs +24 -52
  274. package/src/cli/plugin/index.mjs +20 -9
  275. package/src/cli/setup.mjs +2 -9
  276. package/src/cli/start.mjs +1 -0
  277. package/src/cli/startup.mjs +18 -0
  278. package/src/core/app-deploy/design-tokens.mjs +14 -9
  279. package/src/core/app-deploy/ui-elements.mjs +1 -1
  280. package/src/core/brain-registry.mjs +5 -0
  281. package/src/core/brain-updates.mjs +5 -1
  282. package/src/core/daemon-control.mjs +5 -1
  283. package/src/core/dashboard-bundle.mjs +261 -0
  284. package/src/core/ensure-dependencies.mjs +19 -15
  285. package/src/core/memory-brain.mjs +30 -8
  286. package/src/core/plugin-activation.mjs +63 -20
  287. package/src/core/plugin-contracts/{card.mjs → manifest.mjs} +23 -57
  288. package/src/core/plugin-contracts/startup-check.mjs +49 -0
  289. package/src/core/plugin-contracts/ui.mjs +9 -3
  290. package/src/core/plugin-distribution.mjs +6 -6
  291. package/src/core/plugin-lifecycle.mjs +58 -0
  292. package/src/core/plugin-loader.mjs +9 -5
  293. package/src/core/plugin-runner.mjs +21 -10
  294. package/src/core/plugin-startup-checks.mjs +44 -0
  295. package/src/core/plugin-state.mjs +19 -5
  296. package/src/core/plugin-store.mjs +30 -11
  297. package/src/core/project-id.mjs +15 -5
  298. package/src/core/required-plugins.mjs +31 -6
  299. package/src/core/schema.mjs +2 -0
  300. package/src/core/ssss-operation-service.mjs +1 -0
  301. package/src/core/startup-health.mjs +28 -3
  302. package/src/core/testing/plugin-fixture.mjs +22 -21
  303. package/src/core/throttled-fetch.mjs +25 -18
  304. package/src/core/ui-chunk-choice.mjs +77 -0
  305. package/src/core/ui-chunk.registry.json +23 -0
  306. package/src/core/ui-chunks.mjs +434 -0
  307. package/src/core/vault-cache.mjs +58 -59
  308. package/src/core/workspace-compositions.mjs +151 -0
  309. package/src/core/workspace-drawers.mjs +79 -0
  310. package/src/server/api.mjs +4 -27
  311. package/src/server/index.mjs +28 -21
  312. package/src/server/memory-events.mjs +31 -0
  313. package/src/server/plugin-brain-targets.mjs +89 -0
  314. package/src/server/rest.mjs +2 -0
  315. package/src/server/route-inventory.mjs +3 -2
  316. package/src/server/route-manifest.json +52 -4
  317. package/src/server/routes/_shared.mjs +7 -14
  318. package/src/server/routes/brains.mjs +29 -44
  319. package/src/server/routes/dashboard.mjs +26 -0
  320. package/src/server/routes/plugins.mjs +154 -45
  321. package/src/server/routes/ui-chunks.mjs +192 -0
  322. package/frontend/dist/assets/index-DACh1dhx.js +0 -5613
  323. package/frontend/dist/assets/index-DtwsDyFM.css +0 -1
  324. package/frontend/src/components/plugins/card/CardEngine.tsx +0 -108
  325. package/frontend/src/components/plugins/card/CardScenes.tsx +0 -103
  326. package/frontend/src/components/plugins/card/ExecutionPicker.tsx +0 -64
  327. package/frontend/src/components/plugins/card/args.ts +0 -28
  328. package/frontend/src/components/plugins/card/card.css +0 -32
  329. package/frontend/src/components/plugins/card/cli-line.ts +0 -13
  330. package/frontend/src/components/plugins/card/contract.ts +0 -91
  331. package/frontend/src/components/plugins/card/format.ts +0 -49
  332. package/frontend/src/components/plugins/card/runner-context.ts +0 -11
  333. package/frontend/src/components/plugins/card/runner.tsx +0 -43
  334. package/frontend/src/components/plugins/card/theme.ts +0 -35
  335. package/frontend/src/components/plugins/card/use-source.ts +0 -22
  336. package/frontend/src/components/plugins/card/widgets.tsx +0 -94
  337. package/frontend/src/components/plugins/workspace/WorkspaceHost.tsx +0 -23
  338. package/frontend/src/pages/PluginsPage.tsx +0 -1719
  339. package/scaffold/.agent/skills/plugin/evals/cases/04-card-collects-credential.mjs +0 -47
  340. package/scaffold/.agent/skills/plugin/prompts/06-card.md +0 -46
  341. package/scaffold/.agent/skills/plugin/references/card.md +0 -90
  342. package/scaffold/.agent/skills/plugin/subagents/card-designer.md +0 -60
  343. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/DESIGN.md +0 -67
  344. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/card.js +0 -1179
  345. package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/DESIGN.md +0 -32
  346. package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/card.js +0 -588
  347. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/card.js +0 -575
  348. package/scaffold/.agent/skills/total-recall/plugins/embeddings/ui/DESIGN.md +0 -32
  349. package/scaffold/.agent/skills/total-recall/plugins/embeddings/ui/card.js +0 -482
  350. package/scaffold/.agent/skills/total-recall/plugins/git/ui/DESIGN.md +0 -100
  351. package/scaffold/.agent/skills/total-recall/plugins/git/ui/card.js +0 -637
  352. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/DESIGN.md +0 -217
  353. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/DESIGN.md +0 -32
  354. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/card.js +0 -1276
  355. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/DESIGN.md +0 -45
  356. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/card.js +0 -1401
  357. package/scaffold/.agent/skills/total-recall/plugins/security/scripts/build-ui.mjs +0 -4
  358. package/scaffold/.agent/skills/total-recall/plugins/security/ui/DESIGN.md +0 -41
  359. package/scaffold/.agent/skills/total-recall/plugins/security/ui/card.js +0 -396
  360. package/scaffold/.agent/skills/total-recall/plugins/security/ui/panel.js +0 -98
  361. package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/DESIGN.md +0 -15
  362. package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/card.js +0 -182
@@ -1,4 +1,4 @@
1
- /** The mesh operator's five views. All observations arrive through the scoped host. */
1
+ /** Mesh Home uses owner commands for independent fleet observations. */
2
2
  const DASH = '—';
3
3
  const words = value => typeof value === 'string' && value ? value : DASH;
4
4
  const list = value => Array.isArray(value) ? value : [];
@@ -65,9 +65,9 @@ export function capabilityState(node, column) {
65
65
  function hostName(url) { try { return new URL(url).host; } catch { return DASH; } }
66
66
  const sourceLabels = { grants: 'Secrets', plugins: 'Plugins', updates: 'Updates', tasks: 'Scheduled work', agents: 'Agents', alerts: 'Alerts', deployments: 'Deployments', policy: 'Policy', presence: 'Presence' };
67
67
 
68
- export class MeshlinkControlCard extends HTMLElement {
68
+ export class MeshHome extends HTMLElement {
69
69
  constructor() {
70
- super(); this.status = null; this.doctor = null; this.leader = null;
70
+ super(); this.status = null; this.nodes = null; this.credential = null; this.doctor = null; this.leader = null;
71
71
  this.errors = {}; this.views = {}; this.loading = {}; this.pings = {};
72
72
  this.screen = 'machines'; this.selected = null; this.filters = new Set();
73
73
  this.loginDrafts = {};
@@ -80,11 +80,8 @@ export class MeshlinkControlCard extends HTMLElement {
80
80
  connectedCallback() {
81
81
  if (!this.shadowRoot) this.attachShadow({ mode: 'open' });
82
82
  this.render();
83
- this.onScreen = event => { if ((!event.detail?.pluginId || event.detail.pluginId === this.host?.pluginId) && this.screens.some(s => s.id === event.detail?.screen)) void this.show(event.detail.screen); };
84
- window.addEventListener('plugin-show-screen', this.onScreen);
85
83
  void this.read();
86
84
  }
87
- disconnectedCallback() { window.removeEventListener('plugin-show-screen', this.onScreen); }
88
85
  async call(operation, args = []) {
89
86
  if (!this.host?.run) throw new Error('Mesh command runner unavailable. Open this view in the dashboard.');
90
87
  const result = await this.host.run(operation, args);
@@ -96,19 +93,29 @@ export class MeshlinkControlCard extends HTMLElement {
96
93
  try {
97
94
  const value = asObject(await this.call(op, args));
98
95
  if (!value || key === 'doctor' && !Array.isArray(value) || key !== 'doctor' && Array.isArray(value)) throw new Error('Command returned an unreadable observation.');
96
+ if (key === 'nodes' && !Array.isArray(value.nodes)) throw new Error('Mesh did not return a node list.');
97
+ if (key === 'credential' && typeof value.present !== 'boolean') throw new Error('Auth did not return credential presence.');
99
98
  this[key] = value;
100
- } catch (error) { this.errors[key] = error.message; }
99
+ } catch (error) { this.errors[key] = key === 'credential' ? 'Credential status is unavailable from Auth.' : error.message; }
101
100
  this.paint();
102
101
  }
103
102
  read() {
104
103
  if (this.busy) return this.readPromise;
104
+ if (!this.loading.doctor) { this.doctor = null; delete this.errors.doctor; }
105
105
  this.busy = true; this.lastAttempt = new Date().toISOString(); this.pings = {}; this.paint();
106
106
  this.readPromise = Promise.all([
107
- this.readOne('status', 'status', ['--json']), this.readOne('doctor', 'doctor', ['--json']),
107
+ this.readOne('status', 'status', ['--json']), this.readOne('nodes', 'nodes', ['--json']),
108
+ this.readOne('credential', 'token-status', ['--json']),
108
109
  this.readOne('leader', 'leader', ['--json']), this.readView(this.screen, true),
109
110
  ]).finally(() => { this.busy = false; this.paint(); });
110
111
  return this.readPromise;
111
112
  }
113
+ async readDoctor() {
114
+ if (this.loading.doctor) return;
115
+ this.loading.doctor = true;
116
+ try { await this.readOne('doctor', 'doctor', ['--json']); }
117
+ finally { delete this.loading.doctor; this.paint(); }
118
+ }
112
119
  async readView(screen, force = false) {
113
120
  if (this.loading[screen]) return this.loading[screen];
114
121
  if (this.views[screen] && !force) return;
@@ -126,7 +133,6 @@ export class MeshlinkControlCard extends HTMLElement {
126
133
  async show(screen) {
127
134
  if (!this.screens.some(s => s.id === screen)) return;
128
135
  this.screen = screen; this.confirmEnrollment = false; this.paint();
129
- this.host?.screenChanged?.(screen);
130
136
  if (this.busy) await this.readPromise;
131
137
  await this.readView(screen);
132
138
  }
@@ -168,29 +174,92 @@ export class MeshlinkControlCard extends HTMLElement {
168
174
  render() {
169
175
  this.shadowRoot.innerHTML = `
170
176
  <style>
171
- :host { --face-bg:var(--bg-primary,#0b1020); --face-panel:var(--bg-secondary,#121933); --face-line:var(--border,#26305a); --face-text:var(--text-primary,#e8ecff); --face-muted:var(--text-secondary,#aab5d7); --face-brand:var(--accent,#818cf8); --face-ok:#34d399; --face-warn:#fbbf24; --face-danger:#f87171; display:block; color:var(--face-text); background:var(--face-bg); font:14px/1.5 system-ui,sans-serif; padding:16px; container-type:inline-size; border:1px solid var(--face-line); border-radius:8px; }
172
- * { box-sizing:border-box; min-width:0; } h2,h3,p { margin:0 0 8px; } h2 { font-size:18px; } h3 { font-size:14px; } button,input { font:inherit; min-height:44px; color:inherit; background:var(--face-bg); border:1px solid var(--face-line); border-radius:5px; padding:8px 12px; } button { cursor:pointer; text-align:left; } button:hover { border-color:var(--face-brand); } button:disabled { opacity:.65; cursor:wait; } button:focus-visible,input:focus-visible,summary:focus-visible { outline:2px solid var(--face-brand); outline-offset:2px; } [data-tone=ok] { color:var(--face-ok); } [data-tone=warn] { color:var(--face-warn); } [data-tone=danger] { color:var(--face-danger); } .muted,dt,small { color:var(--face-muted); } .strip { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:12px; margin-bottom:14px; } .strip strong { display:block; overflow-wrap:anywhere; } .verdict { border-left:3px solid currentColor; padding:8px 12px; background:var(--face-panel); } nav { display:flex; flex-wrap:wrap; gap:6px; margin:14px 0; } nav button[aria-selected=true] { border-color:var(--face-brand); background:var(--face-panel); } .refresh { margin-left:auto; } .block { padding:14px; background:var(--face-panel); border:1px solid var(--face-line); border-radius:6px; margin-bottom:12px; overflow-wrap:anywhere; } .panes { display:grid; grid-template-columns:minmax(190px,.8fr) minmax(0,1.6fr); gap:12px; align-items:start; } .roster { display:grid; gap:6px; } .roster button { display:grid; gap:3px; width:100%; } .roster button[aria-pressed=true] { border-color:var(--face-brand); } .ladder { display:grid; gap:8px; } .rung { display:grid; grid-template-columns:70px 1fr; gap:8px; border:1px dashed var(--face-line); padding:10px; border-radius:4px; } .rung[data-state=passed] { border-style:solid; border-left:4px solid var(--face-ok); } .rung[data-state=failed] { border-style:double; border-left:4px solid var(--face-danger); } .rung[data-state=na] { border-style:dotted; color:var(--face-muted); } .actions,.filters { display:flex; flex-wrap:wrap; gap:8px; margin:10px 0; } .filters label { display:flex; align-items:center; gap:6px; min-height:44px; padding:0 8px; border:1px solid var(--face-line); border-radius:4px; } .filters input { min-height:20px; width:20px; } dl { display:grid; grid-template-columns:minmax(80px,.6fr) minmax(0,1.4fr); gap:5px 12px; margin:10px 0; } dd { margin:0; overflow-wrap:anywhere; } .command { white-space:pre-wrap; overflow-wrap:anywhere; font:12px/1.6 ui-monospace,monospace; background:var(--face-bg); padding:12px; border:1px solid var(--face-line); border-radius:4px; } .error { color:var(--face-danger); padding:10px; border:1px solid var(--face-danger); border-radius:4px; margin:8px 0; overflow-wrap:anywhere; } .flow { border-bottom:1px solid var(--face-line); padding:12px 0; } .flow:last-child { border:0; } .table-wrap { max-width:100%; overflow:auto; } table { border-collapse:collapse; width:100%; font-size:12px; } th,td { text-align:left; padding:9px; border:1px solid var(--face-line); vertical-align:top; } th { background:var(--face-bg); } summary { min-height:44px; cursor:pointer; padding:10px 0; } .recorded { margin-top:12px; } .login-form { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:8px; } .login-form label { display:grid; gap:3px; } .login-form button { grid-column:1/-1; } .danger { border-color:var(--face-danger); } .foot { margin-top:12px; font-size:12px; color:var(--face-muted); }
173
- @container(max-width:690px) { .panes,.strip { grid-template-columns:1fr; } .strip { gap:6px; } .strip strong { display:inline; margin-right:8px; } .login-form { grid-template-columns:1fr; } } @media(prefers-reduced-motion:reduce) { * { animation:none; transition:none; } }
177
+ :host {
178
+ display:block; container-type:inline-size;
179
+ color:var(--color-text,CanvasText); background:var(--color-background,Canvas);
180
+ border:1px solid var(--color-border,currentColor); border-radius:var(--radius-md,8px);
181
+ padding:var(--spacing-md,16px); font:14px/1.5 var(--typography-body-font-family,system-ui,sans-serif);
182
+ }
183
+ * { box-sizing:border-box; min-width:0; }
184
+ h2,h3,p { margin:0 0 8px; }
185
+ h2 { font:600 clamp(1.5rem,5vw,2rem)/1.2 var(--typography-heading-font-family,Georgia,serif); }
186
+ h3 { font-size:1rem; }
187
+ header svg { width:1.1em; height:1.1em; vertical-align:middle; color:var(--color-accent,currentColor); }
188
+ button,input {
189
+ font:inherit; min-height:44px; color:inherit; background:var(--color-background,Canvas);
190
+ border:1px solid var(--color-border,currentColor); border-radius:var(--radius-md,8px); padding:8px 12px;
191
+ }
192
+ button { cursor:pointer; text-align:left; }
193
+ button:disabled { opacity:.65; cursor:wait; }
194
+ button:hover,nav button[aria-selected=true],.roster button[aria-pressed=true] { border-color:var(--color-accent,currentColor); }
195
+ button:focus-visible,input:focus-visible,summary:focus-visible { outline:2px solid var(--color-accent,currentColor); outline-offset:2px; }
196
+ [data-tone=ok] { color:var(--color-ok,currentColor); }
197
+ [data-tone=warn] { color:var(--color-warn,currentColor); }
198
+ [data-tone=danger],.error { color:var(--color-danger,currentColor); }
199
+ .muted,dt,small { color:var(--color-muted,currentColor); }
200
+ .strip { display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); gap:12px; margin:14px 0; }
201
+ .strip div { border-top:1px solid var(--color-border,currentColor); padding-top:8px; }
202
+ .strip strong { display:block; overflow-wrap:anywhere; }
203
+ .verdict { border-inline-start:3px solid currentColor; padding:8px 12px; background:var(--color-surface,Canvas); }
204
+ nav,.actions,.filters { display:flex; flex-wrap:wrap; gap:8px; margin:12px 0; }
205
+ nav button[aria-selected=true] { background:var(--color-surface,Canvas); }
206
+ .block { padding:14px; background:var(--color-surface,Canvas); border:1px solid var(--color-border,currentColor); border-radius:var(--radius-md,8px); margin-bottom:12px; overflow-wrap:anywhere; }
207
+ .panes { display:grid; grid-template-columns:minmax(190px,.8fr) minmax(0,1.6fr); gap:12px; align-items:start; }
208
+ .roster,.ladder { display:grid; gap:8px; }
209
+ .roster button { display:grid; gap:3px; width:100%; }
210
+ .rung { display:grid; grid-template-columns:70px 1fr; gap:8px; border:1px dashed var(--color-border,currentColor); padding:10px; }
211
+ .rung[data-state=passed] { border-style:solid; border-inline-start:4px solid var(--color-ok,currentColor); }
212
+ .rung[data-state=failed] { border-style:double; border-inline-start:4px solid var(--color-danger,currentColor); }
213
+ .rung[data-state=na] { border-style:dotted; color:var(--color-muted,currentColor); }
214
+ .filters label { display:flex; align-items:center; gap:6px; min-height:44px; padding:0 8px; border:1px solid var(--color-border,currentColor); }
215
+ .filters input { min-height:20px; width:20px; }
216
+ dl { display:grid; grid-template-columns:minmax(80px,.6fr) minmax(0,1.4fr); gap:5px 12px; margin:10px 0; }
217
+ dd { margin:0; overflow-wrap:anywhere; }
218
+ .command { white-space:pre-wrap; overflow-wrap:anywhere; font:12px/1.6 var(--typography-mono-font-family,ui-monospace,monospace); background:var(--color-background,Canvas); padding:12px; border:1px solid var(--color-border,currentColor); }
219
+ .error { padding:10px; border:1px solid currentColor; margin:8px 0; overflow-wrap:anywhere; }
220
+ .flow { border-bottom:1px solid var(--color-border,currentColor); padding:12px 0; }
221
+ .flow:last-child { border:0; }
222
+ .table-wrap { max-width:100%; overflow:auto; }
223
+ table { border-collapse:collapse; width:100%; font-size:12px; }
224
+ th,td { text-align:left; padding:9px; border:1px solid var(--color-border,currentColor); vertical-align:top; }
225
+ th { background:var(--color-background,Canvas); }
226
+ summary { min-height:44px; cursor:pointer; padding:10px 0; }
227
+ .recorded,.foot { margin-top:12px; }
228
+ .login-form { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:8px; }
229
+ .login-form label { display:grid; gap:3px; }
230
+ .login-form button { grid-column:1/-1; }
231
+ .danger { border-color:var(--color-danger,currentColor); }
232
+ .foot { font-size:12px; color:var(--color-muted,currentColor); }
233
+ @container(max-width:690px) {
234
+ .panes,.login-form { grid-template-columns:1fr; }
235
+ .strip { grid-template-columns:repeat(2,minmax(0,1fr)); }
236
+ }
174
237
  </style>
175
- <header><h2><svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" aria-hidden="true"><circle cx="12" cy="4" r="3"/><circle cx="4" cy="19" r="3"/><circle cx="20" cy="19" r="3"/><path d="M10 7 5 16m9-9 5 9M7 19h10"/></svg> HEADSCALE <small>· Your machines</small></h2><div id="strip" class="strip"></div><p id="verdict" class="verdict"></p></header>
176
- <nav id="tabs" role="tablist" aria-label="Mesh views"></nav><div id="errors" role="status"></div><main id="body" role="tabpanel"></main><footer id="foot" class="foot"></footer>`;
238
+ <header><h2><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" aria-hidden="true"><circle cx="12" cy="4" r="3"/><circle cx="4" cy="19" r="3"/><circle cx="20" cy="19" r="3"/><path d="M10 7 5 16m9-9 5 9M7 19h10"/></svg> Network atlas</h2><div id="strip" class="strip"></div><p id="verdict" class="verdict"></p></header>
239
+ <div id="controls" class="actions"></div><nav id="tabs" role="tablist" aria-label="Mesh views"></nav><div id="errors" role="status"></div><main id="body" role="tabpanel"></main><footer id="foot" class="foot"></footer>`;
177
240
  this.paint();
178
241
  }
179
242
  paint() {
180
243
  const root = this.shadowRoot; if (!root?.querySelector('#body')) return;
181
244
  const focused = root.activeElement;
182
245
  const focusKey = focused && ['id', 'aria-label', 'name'].map(attribute => [attribute, focused.getAttribute(attribute)]).find(([, value]) => value);
183
- const verdict = meshVerdict(this.status, this.doctor, this.leader);
246
+ const roster = this.nodes ? { ...this.status, nodes: this.nodes.nodes } : this.status;
247
+ const verdict = meshVerdict(this.status && roster, this.doctor, this.leader);
184
248
  root.querySelector('#verdict').textContent = verdict.text; root.querySelector('#verdict').dataset.tone = verdict.tone;
185
249
  const status = this.status;
186
250
  root.querySelector('#strip').replaceChildren(...[
187
251
  ['Control', `${hostName(status?.control?.url)} · ${status?.control?.verified === true ? 'Verified' : 'Not verified'}`],
252
+ ['Auth credential', this.credential?.present === true ? 'Saved in Auth' : this.credential?.present === false ? 'Missing' : this.errors.credential ? 'Unavailable' : 'Checking'],
188
253
  ['Leader', `${words(this.leader?.leader?.hostname)} · ${words(this.leader?.leader?.strategy)}`],
189
254
  ['This machine', `${words(status?.enrollment?.hostname)} · ${words(status?.enrollment?.state)}`],
190
255
  ].map(([title, value]) => this.el('div', {}, this.el('strong', { text: title }), this.el('span', { text: value }))));
191
- root.querySelector('#tabs').replaceChildren(...this.screens.map(screen => this.button(screen.label, () => void this.show(screen.id), { role: 'tab', id: `tab-${screen.id}`, 'aria-selected': String(this.screen === screen.id), 'aria-controls': 'body' })), this.button(this.busy ? 'Reading…' : 'Refresh', () => void this.read(), { class: 'refresh', ...(this.busy ? { disabled: '' } : {}) }));
256
+ root.querySelector('#tabs').replaceChildren(...this.screens.map(screen => this.button(screen.label, () => void this.show(screen.id), { role: 'tab', id: `tab-${screen.id}`, 'aria-selected': String(this.screen === screen.id), 'aria-controls': 'body' })));
257
+ root.querySelector('#controls').replaceChildren(
258
+ this.button(this.busy ? 'Reading…' : 'Refresh network', () => void this.read(), { id: 'refresh', ...(this.busy ? { disabled: '' } : {}) }),
259
+ ...(this.canRun('doctor') ? [this.button(this.loading.doctor ? 'Verifying…' : 'Verify fleet execution', () => void this.readDoctor(), { id: 'verify-fleet', ...(this.loading.doctor ? { disabled: '' } : {}) })] : [])
260
+ );
192
261
  root.querySelector('#errors').replaceChildren(...Object.entries(this.errors).map(([key, error]) => this.text(`${key}: ${error}`, 'error')), ...(status?.control?.error || status?.control?.reason ? [this.text(`Control: ${status.control.error || status.control.reason}`, 'error')] : []), ...(this.actionMessage ? [this.text(this.actionMessage)] : []));
193
- const nodes = joinNodes(status, this.doctor);
262
+ const nodes = joinNodes(roster, this.doctor);
194
263
  const body = root.querySelector('#body'); body.setAttribute('aria-labelledby', `tab-${this.screen}`);
195
264
  const firstRun = status?.configured === false && ['no-headscale-api-key', 'no-control-url'].includes(status.control?.reason);
196
265
  body.replaceChildren(firstRun ? this.firstRun() : this.screen === 'machines' ? this.machines(nodes) : this.screen === 'flows' ? this.flows() : this.screen === 'placement' ? this.placement(nodes) : this.screen === 'boundary' ? this.boundary(nodes) : this.join());
@@ -216,7 +285,8 @@ export class MeshlinkControlCard extends HTMLElement {
216
285
  [...roster.children].forEach((button, index) => button.append(this.el('strong', { text: words(live[index].hostname) }), this.el('span', { text: live[index].label, dataset: { tone: live[index].tone } }), this.el('small', { text: this.presenceFor(live[index]) })));
217
286
  const recorded = nodes.filter(node => node.vaultOnly);
218
287
  if (recorded.length) roster.append(this.el('details', { class: 'recorded' }, this.el('summary', { text: `${recorded.length} recorded-only record${recorded.length === 1 ? '' : 's'}` }), recorded.map(node => this.text(`${words(node.hostname)} · recorded ${words(node.last_heartbeat)}`, 'muted'))));
219
- return this.el('div', { class: 'panes' }, this.section(`${this.status ? live.length : DASH} members`, roster), selected ? this.machineDetail(selected) : this.section('Machines', this.text(this.status ? 'No member machines returned.' : 'Machine inventory is unreadable.')));
288
+ const inventoryRead = Boolean(this.nodes || this.status);
289
+ return this.el('div', { class: 'panes' }, this.section(`${inventoryRead ? live.length : DASH} members`, roster), selected ? this.machineDetail(selected) : this.section('Machines', this.text(inventoryRead ? 'No member machines returned.' : 'Machine inventory is unreadable.')));
220
290
  }
221
291
  machineDetail(node) {
222
292
  const ping = this.pings[node.ip];
@@ -227,11 +297,12 @@ export class MeshlinkControlCard extends HTMLElement {
227
297
  ['Login', node.self || !applicable ? 'na' : node.access_state === 'configured' ? 'passed' : 'failed', node.self ? 'Not applicable · local execution' : !applicable ? 'Not applicable · no remote shell on this device' : node.access_state === 'configured' ? `Recorded ${words(node.access?.ssh_user)} · verified ${words(node.access?.verified_at)}` : 'No SSH login recorded'],
228
298
  ['Run', !applicable ? 'na' : node.reach === 'reachable' ? 'passed' : node.reach === 'unreachable' ? 'failed' : 'checking', !applicable ? 'Not applicable' : node.reach === 'reachable' ? 'Probe command executed' : node.reason || 'Not yet checked'],
229
299
  ];
230
- const actions = this.el('div', { class: 'actions' }, !node.self && node.ip ? this.button('Ping now', () => void this.ping(node)) : null, applicable ? this.button('Verify execution', () => void this.readOne('doctor', 'doctor', ['--json'])) : null);
300
+ const actions = !node.self && node.ip && this.canRun('ping')
301
+ ? this.el('div', { class: 'actions' }, this.button('Ping now', () => void this.ping(node))) : null;
231
302
  const detail = this.section(words(node.hostname), this.text(`${words(node.ip)} · ${words(node.os)}`, 'muted'), this.el('div', { class: 'ladder' }, rungs.map(([name, state, evidence]) => this.el('div', { class: 'rung', dataset: { state } }, this.el('strong', { text: name }), this.el('div', {}, this.el('b', { text: state === 'na' ? 'Not applicable' : state === 'checking' ? 'Not yet checked' : state === 'passed' ? 'Passed' : 'Failed' }), this.text(evidence, 'muted'))))), actions);
232
303
  if (node.loginApplicable && node.access_state !== 'configured') {
233
304
  if (this.canRun('access')) detail.append(this.button('Find a login', () => void this.action('access', ['discover', node.ip], 'Login discovery')), this.loginForm(node));
234
- else detail.append(this.text('This card is read-only. Find or record a login through the CLI.'), this.command(`total-recall mesh access discover ${node.ip}\ntotal-recall mesh access ${node.ip} --user <login>`));
305
+ else detail.append(this.text('This Home is read-only. Find or record a login through the CLI.'), this.command(`total-recall mesh access discover ${node.ip}\ntotal-recall mesh access ${node.ip} --user <login>`));
235
306
  }
236
307
  if (node.reach === 'reachable' && !node.self) detail.append(this.text('SSH handoff'), this.command(`total-recall mesh ssh ${node.ip}`));
237
308
  detail.append(this.el('h3', { text: 'Recorded earlier' }), this.fields([
@@ -362,8 +433,8 @@ export class MeshlinkControlCard extends HTMLElement {
362
433
  view.append(this.button(`Re-enroll ${target}`, () => { this.confirmEnrollment = true; this.paint(); }, { class: 'danger' }));
363
434
  if (this.confirmEnrollment) view.append(this.text(`Re-enroll ${target}? This may interrupt its mesh connection.`, 'error'), this.button(`Confirm re-enrollment of ${target}`, () => { this.confirmEnrollment = false; void this.action('enroll', ['--force'], 'Re-enrollment'); }, { class: 'danger', 'data-action': 'confirm-enroll' }), this.button('Cancel', () => { this.confirmEnrollment = false; this.paint(); }));
364
435
  }
365
- else if (enrollment.hostname) view.append(this.text(`This card is read-only. Re-enrolling ${target} can interrupt its connection; use the CLI after confirming that target.`), this.command('total-recall mesh enroll --force'));
436
+ else if (enrollment.hostname) view.append(this.text(`This Home is read-only. Re-enrolling ${target} can interrupt its connection. Use the CLI after confirming that target.`), this.command('total-recall mesh enroll --force'));
366
437
  return view;
367
438
  }
368
439
  }
369
- if (!customElements.get('tr-mesh-card')) customElements.define('tr-mesh-card', MeshlinkControlCard);
440
+ customElements.define('mesh-home', MeshHome);
@@ -0,0 +1,86 @@
1
+ ---
2
+ name: Metaharness
3
+ description: A clear handoff from Total Recall's brain selection to the operator's chosen Chat harness.
4
+ colors:
5
+ canvas: '#0c1427'
6
+ background: '{colors.canvas}'
7
+ surface: '#1e293b'
8
+ text: '#f1f5f9'
9
+ muted: '#94a3b8'
10
+ signal: '#38bdf8'
11
+ primary: '#3b82f6'
12
+ line: '#334155'
13
+ success: '#10b981'
14
+ warning: '#f59e0b'
15
+ danger: '#ef4444'
16
+ typography:
17
+ title:
18
+ fontFamily: system-ui, sans-serif
19
+ fontSize: 18px
20
+ fontWeight: 650
21
+ lineHeight: 1.2
22
+ body:
23
+ fontFamily: system-ui, sans-serif
24
+ fontSize: 14px
25
+ lineHeight: 1.5
26
+ label:
27
+ fontFamily: ui-monospace, monospace
28
+ fontSize: 11px
29
+ fontWeight: 600
30
+ letterSpacing: 0.08em
31
+ rounded:
32
+ frame: 8px
33
+ spacing:
34
+ inset: 16px
35
+ row: 12px
36
+ components:
37
+ chat-handoff:
38
+ backgroundColor: '{colors.canvas}'
39
+ textColor: '{colors.text}'
40
+ typography: '{typography.body}'
41
+ rounded: '{rounded.frame}'
42
+ padding: '{spacing.inset}'
43
+ ---
44
+
45
+ ## Overview
46
+
47
+ Metaharness works like a dispatch board. Readers should understand the selected
48
+ harness, the brain scope and the next action from a quick scan.
49
+
50
+ ## Colors
51
+
52
+ Use the deep navy {colors.canvas} under pale {colors.text}. Reserve blue
53
+ {colors.signal} for the route between the brain selection and its destination.
54
+ Use status colors for verified outcomes from the host.
55
+
56
+ ## Typography
57
+
58
+ Use the quiet, compact {typography.label} for handoff stages. Use
59
+ {typography.title} for the section heading and {typography.body} for instructions.
60
+
61
+ ## Layout
62
+
63
+ Give the heading and route a full-width row at narrow drawer sizes. Stack route
64
+ stages when their labels would wrap. In a wider drawer, use one route line.
65
+
66
+ ## Elevation & Depth
67
+
68
+ Separate the saved route from its controls with a single border. Keep the
69
+ workflow blocks flat so their order stays clear when combined in a drawer.
70
+
71
+ ## Shapes
72
+
73
+ Use compact rounded frames and controls. Label the route stages with text.
74
+
75
+ ## Components
76
+
77
+ The Chat handoff block explains the route. The native Home shows the saved
78
+ harness, registered choices and the optional destination. The bottom drawer
79
+ supplies brain selection and the launch and copy controls. Each operational
80
+ block describes one separate workflow and its observed owner data.
81
+
82
+ ## Do's and Don'ts
83
+
84
+ Show the route in reading order. Keep operational state sourced from Metaharness.
85
+ Keep the handoff marker still and show clear focus and loading states. Use text
86
+ to distinguish saved configuration, draft behavior and unavailable reads.
@@ -173,6 +173,25 @@ follows this foundation and requires its own current audit and plan.
173
173
 
174
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.
175
175
 
176
+ ## Default Chat
177
+
178
+ Open **Metaharness** from the dashboard's Plugins folder to select and save a
179
+ default harness. The Chat drawer uses that default with the selected brains.
180
+ Customize the native Home in `DESIGN.md`. The owner blocks in `ui/chunks/`
181
+ cover execution, routing, usage, documentation, maintenance and run evidence.
182
+
183
+ `total-recall meta-harness chat-default codex --json` sets the host's default
184
+ Chat harness. Choose an adapter from the catalog or from the choices returned
185
+ by `total-recall meta-harness chat-target --json`. The default applies to every
186
+ brain selection.
187
+
188
+ For example, `total-recall meta-harness chat-target --brains global,project:docs --json`
189
+ returns the chosen harness and draft context for those two brain IDs. A Codex
190
+ target opens a native draft that the operator can review before sending. Other
191
+ harnesses can use an explicit HTTPS launch URL configured with `--url` and
192
+ copyable context. Use a launch URL without embedded credentials, a query, or a
193
+ fragment. Omitting `--url` selects the adapter's built-in handoff, if available.
194
+
176
195
  ## Using this from an agent
177
196
 
178
197
  Send work here to run it in another agent harness, or to find out which harness should take it. Native subagents are separate and never need this.
@@ -29,7 +29,9 @@ import { appendCommand, waitingRequests } from './src/control.mjs';
29
29
  import { sessionOptions } from './src/session/run.mjs';
30
30
  import { continueJob } from './src/session-jobs.mjs';
31
31
 
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'];
32
+ import { chatTarget, setChatDefault } from './src/chat.mjs';
33
+
34
+ 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', '--brains'];
33
35
  export function parseArguments(args) {
34
36
  const positional = [];
35
37
  for (let index = 1; index < args.length; index += 1) {
@@ -135,6 +137,8 @@ async function runOperation(argv) {
135
137
  let result;
136
138
  if (operation === 'status') result = {...await inspectNode(value('--node') || 'local'),documentation:documentationStatus()};
137
139
  else if (operation === 'catalog') result = { adapters: getActiveAdapters(), permissions: ['read', 'write', 'send', 'destructive'] };
140
+ else if (operation === 'chat-target') result = chatTarget(value('--brains'));
141
+ else if (operation === 'chat-default') result = setChatDefault(positional[0], value('--url'));
138
142
  else if (operation === 'nodes') result = await listTargets();
139
143
  else if (operation === 'adoption') {
140
144
  const node = value('--node');
@@ -1,17 +1,17 @@
1
1
  {
2
2
  "name": "tr-plugin-meta-harness",
3
- "version": "0.3.13",
3
+ "version": "0.4.0",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "tr-plugin-meta-harness",
9
- "version": "0.3.13",
9
+ "version": "0.4.0",
10
10
  "dependencies": {
11
11
  "@gregiteen/ssss-cli": "0.14.5"
12
12
  },
13
13
  "devDependencies": {
14
- "total-recall-brain": "3.44.0"
14
+ "total-recall-brain": "3.45.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.44.0",
5550
- "resolved": "https://registry.npmjs.org/total-recall-brain/-/total-recall-brain-3.44.0.tgz",
5551
- "integrity": "sha512-VNPaIO9zsSwoxAsJ5ByIQBP9zPpLq4RiQO7Vrex4rBOHFQJT50P7utcZiLMSZTyZJU4C/m5uB8qTCSBMp6+l6Q==",
5549
+ "version": "3.45.0",
5550
+ "resolved": "https://registry.npmjs.org/total-recall-brain/-/total-recall-brain-3.45.0.tgz",
5551
+ "integrity": "sha512-HDYfROazZbsLHQsFPnlBcSpe1HL1QEi7JG8x/eNRUI06RxVQsZWl8LwBo2lTWjWRDrKmCy7BUmSXQDuWF3lrEw==",
5552
5552
  "dev": true,
5553
5553
  "license": "MIT",
5554
5554
  "workspaces": [
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tr-plugin-meta-harness",
3
- "version": "0.3.13",
3
+ "version": "0.4.0",
4
4
  "description": "Total Recall Metaharness plugin",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -12,6 +12,7 @@
12
12
  "cli.mjs",
13
13
  "plugin.json",
14
14
  "README.md",
15
+ "DESIGN.md",
15
16
  "src/",
16
17
  "!src/**/*.spec.mjs",
17
18
  "ui/",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "id": "meta-harness",
3
3
  "name": "Metaharness",
4
- "version": "0.3.13",
4
+ "version": "0.4.0",
5
5
  "description": "Discover, configure, document, track, and run coding agent harnesses through Total Recall across mesh nodes.",
6
6
  "gate": {
7
7
  "tasks": ["Run work in another agent harness", "Choose which harness takes a task", "Check harness versions, sign-in and quota", "Read a harness's official documentation"],
@@ -45,6 +45,41 @@
45
45
  "output": "json",
46
46
  "args": []
47
47
  },
48
+ {
49
+ "name": "chat-target",
50
+ "description": "Resolve the default Chat harness and prepare a draft for the selected brains",
51
+ "effect": "read",
52
+ "output": "json",
53
+ "args": [
54
+ {
55
+ "name": "brains",
56
+ "flag": "--brains",
57
+ "type": "string",
58
+ "label": "Selected brain IDs, comma separated"
59
+ }
60
+ ]
61
+ },
62
+ {
63
+ "name": "chat-default",
64
+ "description": "Save the default Chat harness for every brain selection",
65
+ "effect": "write",
66
+ "output": "json",
67
+ "args": [
68
+ {
69
+ "name": "adapter",
70
+ "type": "string",
71
+ "label": "Metaharness adapter ID",
72
+ "required": true,
73
+ "positional": true
74
+ },
75
+ {
76
+ "name": "url",
77
+ "flag": "--url",
78
+ "type": "string",
79
+ "label": "Optional Chat launch URL"
80
+ }
81
+ ]
82
+ },
48
83
  {
49
84
  "name": "nodes",
50
85
  "description": "List recorded mesh targets without probing or changing them",
@@ -815,29 +850,15 @@
815
850
  "font": "system"
816
851
  },
817
852
  "ui": {
853
+ "home": "home",
854
+ "design_tokens": "DESIGN.md",
818
855
  "elements": [
819
856
  {
820
- "id": "meta-harness-card",
821
- "kind": "card",
822
- "tag": "meta-harness-card",
823
- "module": "ui/card.js",
824
- "description": "Metaharness multi-agent coordination matrix"
825
- }
826
- ]
827
- },
828
- "card_face": {
829
- "quick_actions": [
830
- {
831
- "subcommand": "status",
832
- "label": "Local agents"
833
- },
834
- {
835
- "subcommand": "nodes",
836
- "label": "Mesh nodes"
837
- },
838
- {
839
- "subcommand": "catalog",
840
- "label": "Adapters"
857
+ "id": "home",
858
+ "kind": "panel",
859
+ "tag": "tr-metaharness-home",
860
+ "module": "ui/home.js",
861
+ "description": "Default Chat harness and launch destination"
841
862
  }
842
863
  ]
843
864
  },
@@ -0,0 +1,80 @@
1
+ import path from 'node:path';
2
+ import { configDir } from './paths.mjs';
3
+ import { PluginStateStore } from './ssss-store.mjs';
4
+ import { getActiveAdapters } from './worker.mjs';
5
+
6
+ const CODEX_DRAFT = 'codex://threads/new';
7
+ const MAX_SELECTION_BYTES = 16_384;
8
+ const MAX_DRAFT_LINK_LENGTH = 8_192;
9
+ const UNSAFE_TEXT = /[\p{Cc}\p{Cf}\p{Zl}\p{Zp}]/u;
10
+ const BRAIN_ID = /^(?:global|project:[^,]+|tenant:[a-zA-Z0-9._-]+)$/u;
11
+ const ADAPTER_ID = /^[a-z][a-z0-9-]{0,63}$/;
12
+
13
+ // Chat preferences follow the dashboard's brain. The auth store override is
14
+ // exclusively for credentials and may point outside an isolated dashboard.
15
+ const chatStore = () => new PluginStateStore(
16
+ path.join(configDir({ ...process.env, TR_SECRETS_BRAIN: undefined }), 'chat-default.json'),
17
+ 'meta-harness',
18
+ );
19
+ const displayAdapter = ({ id, name }) => ({ id, name });
20
+
21
+ function brainContext(selection) {
22
+ if (typeof selection !== 'string' || Buffer.byteLength(selection) > MAX_SELECTION_BYTES || UNSAFE_TEXT.test(selection)) {
23
+ throw new Error('Chat requires a bounded comma-separated list of brain IDs');
24
+ }
25
+ const ids = [...new Set(selection.split(',').map(id => id.trim()))];
26
+ if (ids.some(id => !BRAIN_ID.test(id))) throw new Error('Chat brain IDs must use global, project:<name>, or tenant:<name>');
27
+ return `Use this Total Recall brain selection for Chat: ${JSON.stringify(ids)}. Resolve the selected IDs through Total Recall before retrieving or writing memory.`;
28
+ }
29
+
30
+ function launchUrl(adapterId, value) {
31
+ if (value === undefined) return undefined;
32
+ const message = 'Use an HTTPS launch URL without credentials, a query or a fragment, or a Codex Chat link for Codex';
33
+ if (typeof value !== 'string' || value.length > 2048 || UNSAFE_TEXT.test(value) || /\s|\\/u.test(value)) {
34
+ throw new Error(message);
35
+ }
36
+ if (adapterId === 'codex' && /^codex:\/\/threads\/[a-zA-Z0-9_-]{1,128}$/.test(value)) return value;
37
+ if (!value.startsWith('https://') || /[?#]/.test(value)) throw new Error(message);
38
+ const url = URL.parse(value);
39
+ if (!url?.hostname || url.username || url.password) throw new Error(message);
40
+ return url.href;
41
+ }
42
+
43
+ function resolveTarget(settings, adapters, context) {
44
+ const choices = adapters.map(displayAdapter);
45
+ if (!settings) return { ok: true, configured: false, choices, context };
46
+ const adapter = adapters.find(({ id }) => id === settings.adapterId);
47
+ if (!adapter) {
48
+ return {
49
+ ok: true, configured: false, choices, context,
50
+ warning: 'The saved Chat harness is unavailable. Choose a new default.',
51
+ };
52
+ }
53
+
54
+ const target = launchUrl(adapter.id, settings.url) ?? (adapter.id === 'codex' ? CODEX_DRAFT : undefined);
55
+ let href = target;
56
+ if (target === CODEX_DRAFT) {
57
+ const draft = `${target}?prompt=${encodeURIComponent(context)}`;
58
+ if (draft.length <= MAX_DRAFT_LINK_LENGTH) href = draft;
59
+ }
60
+ return { ok: true, configured: true, choices, context, harness: displayAdapter(adapter), ...(href ? { href } : {}) };
61
+ }
62
+
63
+ /** Return a draft target. The caller decides when to open it and the operator submits in the harness. */
64
+ export function chatTarget(brains = 'global') {
65
+ const context = brainContext(brains);
66
+ const settings = chatStore().read(null);
67
+ if (settings !== null && (!settings || typeof settings.adapterId !== 'string' || !ADAPTER_ID.test(settings.adapterId))) {
68
+ throw new Error('The saved Chat default is invalid');
69
+ }
70
+ return resolveTarget(settings, getActiveAdapters(), context);
71
+ }
72
+
73
+ /** Only the adapter and optional launch URL are persistent. */
74
+ export function setChatDefault(adapterId, url) {
75
+ const adapters = getActiveAdapters();
76
+ if (!adapters.some(({ id }) => id === adapterId)) throw new Error('Choose a registered Metaharness adapter for Chat');
77
+ const settings = { adapterId, url: launchUrl(adapterId, url) };
78
+ chatStore().write(settings);
79
+ return resolveTarget(settings, adapters, brainContext('global'));
80
+ }
@@ -0,0 +1,16 @@
1
+ ---
2
+ type: ui-chunk:chunk
3
+ plugin: meta-harness
4
+ id: adapter-docs-freshness
5
+ title: Check harness documentation freshness
6
+ description: Distinguish an absent documentation cache from an outdated snapshot, then inspect the official source that governs the adapter.
7
+ timestamp: "2026-11-08T23:12:00Z"
8
+ intents: [check harness docs freshness, find the official source for a harness, verify adapter behavior against current docs]
9
+ surfaces: [page]
10
+ operations: [docs-status, docs-sources, docs-search, docs-read]
11
+ data: ["docs-status:/ok", "docs-sources:/sources"]
12
+ ---
13
+ <section>
14
+ <h2>Check the documentation cache before using it</h2>
15
+ <p>Read documentation status and identify the official source. Search the current snapshot for the behavior you need. Refresh stale or missing documentation through the owner before relying on it.</p>
16
+ </section>
@@ -0,0 +1,26 @@
1
+ ---
2
+ type: ui-chunk:chunk
3
+ title: Chat handoff
4
+ description: Explain how Total Recall passes the selected brain IDs to a draft in the default Metaharness Chat destination.
5
+ timestamp: '2026-11-08T04:00:00Z'
6
+ plugin: meta-harness
7
+ id: chat-handoff
8
+ intents:
9
+ - open the default chat harness
10
+ - carry selected brains into chat
11
+ - prepare a draft for review
12
+ surfaces: [page, bottom]
13
+ panel: home
14
+ operations: [chat-target, chat-default]
15
+ data: ["chat-target:/configured", "chat-target:/harness/id", "chat-default:/configured"]
16
+ ---
17
+ <section aria-label="Metaharness Chat handoff" data-design-component="chat-handoff" style="box-sizing:border-box;min-width:0;padding:var(--spacing-inset,16px);border:1px solid var(--color-line,#334155);border-radius:var(--radius-frame,8px);background:var(--color-canvas,#0c1427);color:var(--color-text,#f1f5f9);font:14px/1.5 var(--typography-body-font-family,system-ui)">
18
+ <p style="margin:0 0 6px;color:var(--color-signal,#38bdf8);font:600 11px/1.4 var(--typography-label-font-family,monospace);letter-spacing:.08em;text-transform:uppercase">Metaharness / Chat</p>
19
+ <h2 style="margin:0 0 12px;font-size:var(--typography-title-font-size,18px);line-height:1.2;font-weight:650">Carry your brain selection into Chat</h2>
20
+ <ol aria-label="Handoff stages" style="display:flex;flex-wrap:wrap;gap:6px 24px;margin:0 0 12px;padding:8px 12px 8px 32px;border-left:2px solid var(--color-signal,#38bdf8);background:var(--color-surface,#1e293b)">
21
+ <li>Choose brains</li>
22
+ <li>Open the default harness</li>
23
+ <li>Review the draft</li>
24
+ </ol>
25
+ <p style="margin:0;color:var(--color-muted,#94a3b8)">Chat keeps the same default as you switch brains. The draft carries the selected brain IDs so the harness can resolve them through Total Recall.</p>
26
+ </section>