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
@@ -10,7 +10,7 @@
10
10
  import fs from 'node:fs';
11
11
  import path from 'node:path';
12
12
  import { createRequire } from 'node:module';
13
- import { readPluginsDir, globalPluginsDir, PACKAGE_ROOT, resolvePluginFile } from './plugin-loader.mjs';
13
+ import { readPluginsDir, globalPluginsDir, PACKAGE_ROOT, resolvePluginFile, validatePluginManifest } from './plugin-loader.mjs';
14
14
  import { DEFAULT_PLUGIN_IDS, REQUIRED_INSTALLATION_PLUGIN_IDS } from './default-plugins.mjs';
15
15
  import { comparePackageVersions } from './package-version.mjs';
16
16
  import { preparePluginDependencies } from './plugin-dependencies.mjs';
@@ -113,14 +113,39 @@ export function inspectRequiredPlugins(brainDir, { pluginsDir, sharedBrainDir =
113
113
  return { status: errors.length ? 'failed' : 'ready', errors, source, installations };
114
114
  }
115
115
 
116
- /** Only a copy that declares an older release than the bundled one is refreshed; damaged same-release copies still fail. */
116
+ const LEGACY_PRESENTATION_FIELDS = ['card', 'card_face', 'card_layout'];
117
+
118
+ function hasLegacyPresentation(manifest) {
119
+ return LEGACY_PRESENTATION_FIELDS.some(field => Object.hasOwn(manifest, field))
120
+ || (Array.isArray(manifest.ui?.elements) && manifest.ui.elements.some(element => ['card', 'card-face'].includes(element?.kind)));
121
+ }
122
+
123
+ function hasPluginFiles(directory, files) {
124
+ return files.every(file => fs.statSync(resolvePluginFile(directory, file)).isFile());
125
+ }
126
+
127
+ function runtimeFiles(manifest) {
128
+ return ['package.json', ...(manifest.cli ? [manifest.cli.handler] : []), ...Object.values(manifest.runtime?.modules || {})];
129
+ }
130
+
131
+ /** Refresh older copies and migrate the retired presentation of an otherwise intact same-release copy. */
117
132
  function isStaleInstall(target, source) {
118
133
  try {
119
134
  // A link is its owner's checkout. Replacing it would delete that repository's files, .git included.
120
135
  if (fs.lstatSync(target).isSymbolicLink()) return false;
121
- const installed = JSON.parse(fs.readFileSync(path.join(target, 'plugin.json'), 'utf8')).version;
122
- const bundled = JSON.parse(fs.readFileSync(path.join(source, 'plugin.json'), 'utf8')).version;
123
- return comparePackageVersions(installed, bundled) === -1;
136
+ const installed = JSON.parse(fs.readFileSync(path.join(target, 'plugin.json'), 'utf8'));
137
+ const bundled = JSON.parse(fs.readFileSync(path.join(source, 'plugin.json'), 'utf8'));
138
+ if (comparePackageVersions(installed.version, bundled.version) === -1) return true;
139
+ if (installed.version !== bundled.version || installed.id !== bundled.id || bundled.id !== path.basename(source)
140
+ || installed.cli?.command !== bundled.cli?.command || !hasLegacyPresentation(installed)
141
+ || hasLegacyPresentation(bundled) || !bundled.ui?.home || !validatePluginManifest(bundled).valid) return false;
142
+
143
+ const migrated = { ...installed, ui: bundled.ui };
144
+ for (const field of LEGACY_PRESENTATION_FIELDS) delete migrated[field];
145
+ if (!validatePluginManifest(migrated).valid || !hasPluginFiles(target, runtimeFiles(installed))) return false;
146
+ return hasPluginFiles(source, [
147
+ ...runtimeFiles(bundled), bundled.ui.design_tokens, ...bundled.ui.elements.map(element => element.module),
148
+ ]);
124
149
  } catch { return false; }
125
150
  }
126
151
 
@@ -165,7 +190,7 @@ function installDefaultsInto(brainDir, sourceDir) {
165
190
  fs.mkdirSync(path.dirname(target), { recursive: true });
166
191
  fs.cpSync(source, target, { recursive: true, force: false, errorOnExist: true });
167
192
  } else if (isStaleInstall(target, source)) {
168
- // A vendored copy that no longer validates (or predates the bundled release) is replaced; node_modules stays.
193
+ // Keep installed dependencies when refreshing the bundled plugin files.
169
194
  for (const entry of fs.readdirSync(target)) if (entry !== 'node_modules') fs.rmSync(path.join(target, entry), { recursive: true, force: true });
170
195
  for (const entry of fs.readdirSync(source)) if (entry !== 'node_modules') fs.cpSync(path.join(source, entry), path.join(target, entry), { recursive: true });
171
196
  }
@@ -1034,6 +1034,8 @@ export const PluginRecordSchema = z.object({
1034
1034
  task_runs: z.record(z.string()).optional(),
1035
1035
  /** Explicit mesh node for commands with selected-node placement. */
1036
1036
  task_nodes: z.record(z.string().min(1)).optional(),
1037
+ runtime_enabled: z.boolean().optional(),
1038
+ runtime_on_use: z.boolean().optional(),
1037
1039
  }).passthrough();
1038
1040
 
1039
1041
  const SECRET_KEY_PATTERN = /^(.*_)?(secret|token|password|api[_-]?key|private[_-]?key|credentials|auth[_-]?header|bearer)$/i;
@@ -46,6 +46,7 @@ export function patchVfsDocument(vfsPath, patches, options = {}) {
46
46
  type: 'patch',
47
47
  ...envelopeBase(vfsPath, options),
48
48
  patches,
49
+ ...(options.expectedBeforeHash === undefined ? {} : { expected_before_hash: options.expectedBeforeHash }),
49
50
  }, options);
50
51
  }
51
52
 
@@ -10,6 +10,23 @@ import { CLI_COMMANDS } from './cli-commands.mjs';
10
10
  const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../..');
11
11
  export const cliEntry = path.join(packageRoot, 'bin/total-recall.mjs');
12
12
 
13
+ /** Whether this package's dashboard bundle is as new as its frontend sources (the server rebuilds it). */
14
+ async function defaultDashboardCheck() {
15
+ try {
16
+ const { checkDistFreshness, dashboardTargets } = await import('./dashboard-bundle.mjs');
17
+ if (!fs.existsSync(path.join(packageRoot, 'frontend', 'package.json'))) return { status: 'not-shipped' };
18
+ const result = await checkDistFreshness(dashboardTargets(packageRoot));
19
+ const status = result.ok ? 'current' : result.reason === 'missing-bundle' ? 'missing' : 'stale';
20
+ return {
21
+ status,
22
+ ...(result.bundle ? { built_at: new Date(result.bundle.mtimeMs).toISOString() } : {}),
23
+ ...(!result.ok && result.source ? { newer_source: path.relative(packageRoot, result.source.path) } : {}),
24
+ };
25
+ } catch (error) {
26
+ return { status: 'unknown', reason: error.message };
27
+ }
28
+ }
29
+
13
30
  export function runBounded(binary, args, { cwd = process.cwd(), timeoutMs = 15000, maxBytes = 262144 } = {}) {
14
31
  return new Promise(resolve => {
15
32
  let child, output = '', stderr = '', size = 0, reason = null, settled = false, timer, escalation;
@@ -81,8 +98,8 @@ export function processIdentity(pidFile, hint, { alive = pid => { try { process.
81
98
  }
82
99
 
83
100
  /** The single installation-aware daemon observation for status and lifecycle. */
84
- export function observeDaemon(brainDir, { identity = processIdentity } = {}) {
85
- const expected_entry = path.join(packageRoot, 'src', 'core', 'daemon-loop.mjs');
101
+ export function observeDaemon(brainDir, { identity = processIdentity, expectedEntry = path.join(packageRoot, 'src', 'core', 'daemon-loop.mjs') } = {}) {
102
+ const expected_entry = expectedEntry;
86
103
  return { ...identity(path.join(brainDir, 'daemon.pid'), expected_entry), expected_entry, source: 'local-pid' };
87
104
  }
88
105
 
@@ -130,7 +147,8 @@ export async function fetchStartup(url, options = {}, fetchImpl = fetch) {
130
147
  }
131
148
 
132
149
  export async function startupHealth({ cwd = process.cwd(), brainDir, brainUrl = null, token = null, brainId = null, ensure = false,
133
- appCheck = null, appStart = null, run = runBounded, fetchImpl = fetch, onDiskVersion = packageVersionOnDisk, listener = verifyListener, platform = process.platform, home = os.homedir(), identity = processIdentity } = {}) {
150
+ appCheck = null, appStart = null, run = runBounded, fetchImpl = fetch, onDiskVersion = packageVersionOnDisk, listener = verifyListener, platform = process.platform, home = os.homedir(), identity = processIdentity,
151
+ dashboardCheck = null, pluginChecks = null } = {}) {
134
152
  const actions = [];
135
153
  const serverFile = path.join(brainDir, 'server.pid');
136
154
  const report = { checked_at: new Date().toISOString(), server: { status: 'not-configured' }, brain: { status: 'unknown' }, daemon: { status: 'unknown' },
@@ -235,6 +253,13 @@ export async function startupHealth({ cwd = process.cwd(), brainDir, brainUrl =
235
253
  }
236
254
  const { inspectRequiredPlugins } = await import('./required-plugins.mjs');
237
255
  report.required_plugins = inspectRequiredPlugins(brainDir);
256
+ // Reported, not part of readiness: a stale dashboard or unfinished work still
257
+ // leaves the runtime usable, but neither may stay invisible.
258
+ report.dashboard = await (dashboardCheck ?? defaultDashboardCheck)();
259
+ report.plugin_checks = await (pluginChecks ?? (async () => {
260
+ const { runPluginStartupChecks } = await import('./plugin-startup-checks.mjs');
261
+ return runPluginStartupChecks({ cwd });
262
+ }))();
238
263
  report.shared_ready = report.required_plugins.status === 'ready' && report.server.status === 'ready' && report.brain.status === 'ready' && report.daemon.status === 'running' && report.ssss.status === 'available';
239
264
  report.ready_scope = appCheck ? 'shared-and-declared-current-repo-app' : 'shared-runtime-only';
240
265
  report.ready = report.shared_ready && (!appCheck || report.app.status === 'ready');
@@ -1,13 +1,13 @@
1
1
  /**
2
- * Fixture manifests for specs that exercise plumbing rather than card design.
2
+ * Fixture manifests for specs that exercise plumbing rather than Home design.
3
3
  *
4
- * Every real plugin has a bespoke card face declared in `ui.elements[]`, and the
4
+ * Every real plugin has a bespoke native Home declared in `ui.elements[]`, and the
5
5
  * validator enforces it. Specs that install, copy, vendor, discover or compile a
6
6
  * plugin still need a manifest that satisfies that contract, or they fail on a
7
- * rule they are not testing. This module supplies the smallest honest face so
7
+ * rule they are not testing. This module supplies a minimal native Home so
8
8
  * those specs keep asserting what they mean to assert.
9
9
  *
10
- * The face here is deliberately generic and exists only in tests. Production
10
+ * The Home here is deliberately generic and exists only in tests. Production
11
11
  * plugin UI is always hand-authored per plugin (invariants-b6e8fcac).
12
12
  */
13
13
  import fs from 'node:fs';
@@ -16,45 +16,46 @@ import path from 'node:path';
16
16
  const nodeFs = fs;
17
17
  const nodePath = path;
18
18
 
19
- /** The smallest valid card face. Declared once, as every plugin declares one. */
20
- export const FIXTURE_CARD_FACE = Object.freeze({
19
+ /** The smallest valid native Home. Declared once, as every plugin declares one. */
20
+ export const FIXTURE_HOME = Object.freeze({
21
+ home: 'home',
21
22
  design_tokens: 'ui/DESIGN.md',
22
23
  elements: [
23
24
  {
24
- id: 'card',
25
- kind: 'card',
26
- tag: 'tr-fixture-card',
27
- module: 'ui/card.js',
28
- description: 'Fixture card face',
25
+ id: 'home',
26
+ kind: 'panel',
27
+ tag: 'tr-fixture-home',
28
+ module: 'ui/home.js',
29
+ description: 'Fixture native Home',
29
30
  },
30
31
  ],
31
32
  });
32
33
 
33
- /** Source of the element module referenced by FIXTURE_CARD_FACE. */
34
- export const FIXTURE_CARD_SOURCE = 'export const tag = "tr-fixture-card";\n';
34
+ /** Source of the element module referenced by FIXTURE_HOME. */
35
+ export const FIXTURE_HOME_SOURCE = 'export const tag = "tr-fixture-home";\n';
35
36
 
36
37
  /**
37
- * Merge a bespoke face into a fixture manifest.
38
+ * Merge a native Home into a fixture manifest.
38
39
  *
39
- * Pass `ui: null` to omit the face deliberately, e.g. when asserting that a
40
+ * Pass `ui: null` to omit the Home deliberately, e.g. when asserting that a
40
41
  * plugin without one is rejected.
41
42
  */
42
- export function withFixtureFace(manifest = {}) {
43
+ export function withFixtureHome(manifest = {}) {
43
44
  if (manifest.ui === null) {
44
45
  const { ui: _omitted, ...rest } = manifest;
45
46
  return rest;
46
47
  }
47
- return { ...manifest, ui: manifest.ui ?? { ...FIXTURE_CARD_FACE } };
48
+ return { ...manifest, ui: manifest.ui ?? { ...FIXTURE_HOME } };
48
49
  }
49
50
 
50
51
  /**
51
- * Write `plugin.json` for a fixture plugin, declaring a face unless the manifest
52
+ * Write `plugin.json` for a fixture plugin, declaring a Home unless the manifest
52
53
  * explicitly opts out with `ui: null`.
53
54
  *
54
55
  * Returns the manifest that was written.
55
56
  */
56
57
  export function writeFixturePlugin(pluginDir, manifest, { fs = nodeFs, path = nodePath } = {}) {
57
- const written = withFixtureFace(manifest);
58
+ const written = withFixtureHome(manifest);
58
59
  nodeFs.writeFileSync(
59
60
  nodePath.join(pluginDir, 'plugin.json'),
60
61
  JSON.stringify(written, null, 2),
@@ -62,8 +63,8 @@ export function writeFixturePlugin(pluginDir, manifest, { fs = nodeFs, path = no
62
63
  if (written.ui?.elements?.length) {
63
64
  const uiDir = nodePath.join(pluginDir, 'ui');
64
65
  nodeFs.mkdirSync(uiDir, { recursive: true });
65
- nodeFs.writeFileSync(nodePath.join(uiDir, 'card.js'), FIXTURE_CARD_SOURCE);
66
- nodeFs.writeFileSync(nodePath.join(uiDir, 'DESIGN.md'), '# Fixture card\n');
66
+ nodeFs.writeFileSync(nodePath.join(uiDir, 'home.js'), FIXTURE_HOME_SOURCE);
67
+ nodeFs.writeFileSync(nodePath.join(uiDir, 'DESIGN.md'), '# Fixture Home\n');
67
68
  }
68
69
  return written;
69
70
  }
@@ -135,31 +135,38 @@ export async function loadFirewallPolicy(brainDir) {
135
135
 
136
136
  applyPolicy();
137
137
 
138
- // Watch the file directly if it exists.
139
- if (!policyWatcher && fs.existsSync(policyPath)) {
140
- policyWatcher = fs.watch(policyPath, (eventType) => {
141
- if (eventType === 'change') applyPolicy();
142
- });
143
- // Unref so this watcher does not prevent one-shot CLI commands (e.g.
144
- // `recall`) from exiting cleanly once their work is done.
145
- policyWatcher.unref();
146
- }
138
+ const watch = (target, onChange, clear) => {
139
+ try {
140
+ const watcher = fs.watch(target, onChange);
141
+ watcher.on('error', error => {
142
+ watcher.close();
143
+ clear(watcher);
144
+ logger.warn('throttled-fetch', `Network policy watcher unavailable: ${error.message}`);
145
+ });
146
+ watcher.unref();
147
+ return watcher;
148
+ } catch (error) {
149
+ logger.warn('throttled-fetch', `Network policy watcher unavailable: ${error.message}`);
150
+ return null;
151
+ }
152
+ };
153
+ const watchPolicy = () => {
154
+ if (policyWatcher || !fs.existsSync(policyPath)) return;
155
+ policyWatcher = watch(policyPath, event => {
156
+ if (event === 'change') applyPolicy();
157
+ }, watcher => { if (policyWatcher === watcher) policyWatcher = null; });
158
+ };
159
+ watchPolicy();
147
160
 
148
161
  // Also watch the parent directory so we pick up the policy file being
149
162
  // created after boot (e.g. first-run setups where the doc doesn't exist
150
163
  // yet). Attach the direct file watcher once it appears.
151
164
  if (!parentWatcher && fs.existsSync(systemDir)) {
152
- parentWatcher = fs.watch(systemDir, (eventType, filename) => {
165
+ parentWatcher = watch(systemDir, (_event, filename) => {
153
166
  if (filename !== 'network-policy.md') return;
154
167
  applyPolicy();
155
- if (!policyWatcher && fs.existsSync(policyPath)) {
156
- policyWatcher = fs.watch(policyPath, (evt) => {
157
- if (evt === 'change') applyPolicy();
158
- });
159
- policyWatcher.unref();
160
- }
161
- });
162
- parentWatcher.unref();
168
+ watchPolicy();
169
+ }, watcher => { if (parentWatcher === watcher) parentWatcher = null; });
163
170
  }
164
171
  } catch (err) {
165
172
  logger.error('throttled-fetch', `Failed to load network policy: ${err.message}`);
@@ -0,0 +1,77 @@
1
+ import { getPluginById } from './plugin-loader.mjs';
2
+ import { pluginActivation } from './plugin-state.mjs';
3
+
4
+ const decisionLimit = 20;
5
+
6
+ async function requestChoice(state, questions, { projectRoot = process.cwd(), brainDir } = {}) {
7
+ const plugin = getPluginById('decision', projectRoot);
8
+ if (!plugin?.valid || !pluginActivation(plugin, { projectRoot }).enabled ||
9
+ !plugin.manifest.cli?.subcommands?.some(command => command.name === 'run')) return null;
10
+ const { runPluginCommand } = await import('./plugin-runner.mjs');
11
+ const run = await runPluginCommand(plugin, {
12
+ subcommand: 'run',
13
+ args: ['--state', JSON.stringify(state), '--questions', JSON.stringify(questions), '--json'],
14
+ timeoutMs: 15_000,
15
+ cwd: projectRoot ?? brainDir ?? process.cwd(),
16
+ projectRoot,
17
+ });
18
+ if ((!run.ok && run.exitCode !== 4) || run.truncated) return null;
19
+ return JSON.parse(run.stdout);
20
+ }
21
+
22
+ export async function chooseUiChunk(chunks, query, surface, decide = requestChoice) {
23
+ const result = await chooseBlocks(chunks, query, surface, ['selected_chunk'], decide);
24
+ const { keys, ...selection } = result;
25
+ return { ...selection, key: keys[0] ?? null };
26
+ }
27
+
28
+ export async function chooseUiComposition(chunks, query, decide, target) {
29
+ const choose = decide ?? ((state, questions) => requestChoice(state, questions, target));
30
+ return chooseBlocks(chunks, query, 'page', ['selected_chunk', 'supporting_chunk', 'reference_chunk'], choose, false);
31
+ }
32
+
33
+ const instructions = {
34
+ selected_chunk: 'Choose the primary block that best accomplishes the requested intent.',
35
+ supporting_chunk: 'Choose an additional block that helps accomplish the same task without repeating the primary block.',
36
+ reference_chunk: 'Choose an optional readout or reference block that gives useful context for the task.',
37
+ };
38
+
39
+ async function chooseBlocks(chunks, query, surface, slots, decide, skipSingle = true) {
40
+ const shortlist = chunks.slice(0, decisionLimit);
41
+ if (!shortlist.length) return { source: 'lexical', keys: [], reason: 'no-matches' };
42
+ const fallback = { source: 'lexical', keys: shortlist.slice(0, slots.length).map(chunk => chunk.key) };
43
+ if (skipSingle && shortlist.length === 1) return { ...fallback, reason: 'single-match' };
44
+
45
+ const criteria = Object.fromEntries(shortlist.map(chunk => {
46
+ const description = [chunk.title, chunk.description, ...chunk.intents, ...(chunk.operations || []), ...(chunk.data || [])].join(' ').slice(0, 600);
47
+ return [chunk.key, description];
48
+ }));
49
+ criteria.none = 'No eligible chunk fits this intent.';
50
+ const questions = Object.fromEntries(slots.slice(0, shortlist.length).map(slot => [slot, {
51
+ type: 'choice',
52
+ instructions: `${instructions[slot]} Choose none when nothing fits.`,
53
+ criteria,
54
+ }]));
55
+ let result;
56
+ try {
57
+ result = await decide({ intent: query, surface: surface ?? null }, questions);
58
+ } catch {
59
+ return { ...fallback, reason: 'decision-unavailable' };
60
+ }
61
+ if (result?.ok !== true) return { ...fallback, reason: 'decision-unavailable' };
62
+ const eligible = new Set(shortlist.map(chunk => chunk.key));
63
+ const primary = result.answers?.selected_chunk;
64
+ if (!confident(primary)) return { ...fallback, reason: 'decision-abstained' };
65
+ if (primary.choice === 'none') return { source: 'decision', keys: [], reason: 'no-fit', confidence: primary.confidence };
66
+ if (!eligible.has(primary.choice)) return { source: 'decision', keys: [], reason: 'invalid-choice' };
67
+ const keys = new Set([primary.choice]);
68
+ for (const slot of Object.keys(questions).slice(1)) {
69
+ const answer = result.answers?.[slot];
70
+ if (confident(answer) && eligible.has(answer.choice)) keys.add(answer.choice);
71
+ }
72
+ return { source: 'decision', keys: [...keys], confidence: primary.confidence };
73
+ }
74
+
75
+ function confident(answer) {
76
+ return answer?.act === true && Number.isFinite(answer.confidence) && answer.confidence >= 0.5 && answer.confidence <= 1;
77
+ }
@@ -0,0 +1,23 @@
1
+ {
2
+ "registry": "ui-chunk",
3
+ "extends": "ssss",
4
+ "version": "1.1.0",
5
+ "description": "Portable owner-authored HTML chunks for Total Recall workspace surfaces.",
6
+ "document_primitives": {
7
+ "chunk": {
8
+ "family": "capability",
9
+ "append_only": false,
10
+ "portability": "structural",
11
+ "filename_convention": "A kebab-case chunk ID under ui/chunks/ with the .md extension.",
12
+ "required_fields": ["type", "title", "description", "timestamp", "plugin", "id", "intents", "surfaces"],
13
+ "optional_fields": ["panel", "operations", "data"],
14
+ "immutable_fields": ["plugin", "id"],
15
+ "enums": { "surfaces": ["page", "left", "right", "bottom"] },
16
+ "patterns": {
17
+ "plugin": "^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$",
18
+ "id": "^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$"
19
+ },
20
+ "notes": "The body holds HTML. The host validates surface membership, file ownership and native panel bindings before publishing the catalog."
21
+ }
22
+ }
23
+ }