total-recall-brain 3.45.0 → 3.46.1

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 (363) hide show
  1. package/bin/total-recall.mjs +7 -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/default-plugin-refresh.mjs +39 -0
  285. package/src/core/ensure-dependencies.mjs +19 -15
  286. package/src/core/memory-brain.mjs +30 -8
  287. package/src/core/plugin-activation.mjs +63 -20
  288. package/src/core/plugin-contracts/{card.mjs → manifest.mjs} +23 -57
  289. package/src/core/plugin-contracts/startup-check.mjs +49 -0
  290. package/src/core/plugin-contracts/ui.mjs +9 -3
  291. package/src/core/plugin-distribution.mjs +6 -6
  292. package/src/core/plugin-lifecycle.mjs +58 -0
  293. package/src/core/plugin-loader.mjs +9 -5
  294. package/src/core/plugin-runner.mjs +21 -10
  295. package/src/core/plugin-startup-checks.mjs +44 -0
  296. package/src/core/plugin-state.mjs +19 -5
  297. package/src/core/plugin-store.mjs +30 -11
  298. package/src/core/project-id.mjs +15 -5
  299. package/src/core/required-plugins.mjs +31 -6
  300. package/src/core/schema.mjs +2 -0
  301. package/src/core/ssss-operation-service.mjs +1 -0
  302. package/src/core/startup-health.mjs +28 -3
  303. package/src/core/testing/plugin-fixture.mjs +22 -21
  304. package/src/core/throttled-fetch.mjs +25 -18
  305. package/src/core/ui-chunk-choice.mjs +77 -0
  306. package/src/core/ui-chunk.registry.json +23 -0
  307. package/src/core/ui-chunks.mjs +434 -0
  308. package/src/core/vault-cache.mjs +58 -59
  309. package/src/core/workspace-compositions.mjs +151 -0
  310. package/src/core/workspace-drawers.mjs +79 -0
  311. package/src/server/api.mjs +4 -27
  312. package/src/server/index.mjs +28 -21
  313. package/src/server/memory-events.mjs +31 -0
  314. package/src/server/plugin-brain-targets.mjs +89 -0
  315. package/src/server/rest.mjs +2 -0
  316. package/src/server/route-inventory.mjs +3 -2
  317. package/src/server/route-manifest.json +52 -4
  318. package/src/server/routes/_shared.mjs +7 -14
  319. package/src/server/routes/brains.mjs +29 -44
  320. package/src/server/routes/dashboard.mjs +26 -0
  321. package/src/server/routes/plugins.mjs +154 -45
  322. package/src/server/routes/ui-chunks.mjs +192 -0
  323. package/frontend/dist/assets/index-DACh1dhx.js +0 -5613
  324. package/frontend/dist/assets/index-DtwsDyFM.css +0 -1
  325. package/frontend/src/components/plugins/card/CardEngine.tsx +0 -108
  326. package/frontend/src/components/plugins/card/CardScenes.tsx +0 -103
  327. package/frontend/src/components/plugins/card/ExecutionPicker.tsx +0 -64
  328. package/frontend/src/components/plugins/card/args.ts +0 -28
  329. package/frontend/src/components/plugins/card/card.css +0 -32
  330. package/frontend/src/components/plugins/card/cli-line.ts +0 -13
  331. package/frontend/src/components/plugins/card/contract.ts +0 -91
  332. package/frontend/src/components/plugins/card/format.ts +0 -49
  333. package/frontend/src/components/plugins/card/runner-context.ts +0 -11
  334. package/frontend/src/components/plugins/card/runner.tsx +0 -43
  335. package/frontend/src/components/plugins/card/theme.ts +0 -35
  336. package/frontend/src/components/plugins/card/use-source.ts +0 -22
  337. package/frontend/src/components/plugins/card/widgets.tsx +0 -94
  338. package/frontend/src/components/plugins/workspace/WorkspaceHost.tsx +0 -23
  339. package/frontend/src/pages/PluginsPage.tsx +0 -1719
  340. package/scaffold/.agent/skills/plugin/evals/cases/04-card-collects-credential.mjs +0 -47
  341. package/scaffold/.agent/skills/plugin/prompts/06-card.md +0 -46
  342. package/scaffold/.agent/skills/plugin/references/card.md +0 -90
  343. package/scaffold/.agent/skills/plugin/subagents/card-designer.md +0 -60
  344. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/DESIGN.md +0 -67
  345. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/card.js +0 -1179
  346. package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/DESIGN.md +0 -32
  347. package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/card.js +0 -588
  348. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/card.js +0 -575
  349. package/scaffold/.agent/skills/total-recall/plugins/embeddings/ui/DESIGN.md +0 -32
  350. package/scaffold/.agent/skills/total-recall/plugins/embeddings/ui/card.js +0 -482
  351. package/scaffold/.agent/skills/total-recall/plugins/git/ui/DESIGN.md +0 -100
  352. package/scaffold/.agent/skills/total-recall/plugins/git/ui/card.js +0 -637
  353. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/DESIGN.md +0 -217
  354. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/DESIGN.md +0 -32
  355. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/card.js +0 -1276
  356. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/DESIGN.md +0 -45
  357. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/card.js +0 -1401
  358. package/scaffold/.agent/skills/total-recall/plugins/security/scripts/build-ui.mjs +0 -4
  359. package/scaffold/.agent/skills/total-recall/plugins/security/ui/DESIGN.md +0 -41
  360. package/scaffold/.agent/skills/total-recall/plugins/security/ui/card.js +0 -396
  361. package/scaffold/.agent/skills/total-recall/plugins/security/ui/panel.js +0 -98
  362. package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/DESIGN.md +0 -15
  363. package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/card.js +0 -182
@@ -0,0 +1,145 @@
1
+ import { parseArgs } from 'node:util';
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+ import { auditUiChunkCoverage, getUiChunk, searchUiChunks, uiChunkRegistryPath, validateUiChunkFile } from '../../core/ui-chunks.mjs';
5
+ import { chooseUiChunk } from '../../core/ui-chunk-choice.mjs';
6
+ import { callApi } from '../api.mjs';
7
+
8
+ const help = [
9
+ 'Usage: total-recall plugin chunks [query] [--plugin ID] [--surface page|left|right|bottom] [--limit N] [--decision|--workspace] [--brain ID] [--json]',
10
+ ' total-recall plugin chunks get <plugin:id> [--surface SURFACE] [--workspace] [--brain ID] [--json]',
11
+ ' total-recall plugin chunks validate <file> [--plugin-dir DIR] [--json]',
12
+ ' total-recall plugin chunks registry',
13
+ ' total-recall plugin chunks coverage [--plugin ID] [--json]',
14
+ ' total-recall plugin chunks add <id.md> --plugin ID [--brain ID] [--json]',
15
+ ' total-recall plugin chunks page <id> --brain ID [--json]',
16
+ ' total-recall plugin chunks page <id> <plugin:block>... --brain ID (--title TITLE | --revision VERSION) [--json]',
17
+ '',
18
+ 'Use --decision with a concise, non-sensitive query to request a ranked choice through the configured Decision plugin.',
19
+ 'Search and validation run locally by default. Decision requests send only the query and up to 20 eligible metadata records.',
20
+ 'Agents use total-recall decision compose to publish a Jev-selected page.',
21
+ ].join('\n');
22
+
23
+ export async function runPluginChunks(args) {
24
+ const asJson = args.includes('--json');
25
+ try {
26
+ const { values, positionals } = parseArgs({
27
+ args,
28
+ allowPositionals: true,
29
+ options: {
30
+ json: { type: 'boolean' },
31
+ help: { type: 'boolean', short: 'h' },
32
+ decision: { type: 'boolean' },
33
+ workspace: { type: 'boolean' },
34
+ brain: { type: 'string' },
35
+ surface: { type: 'string' },
36
+ plugin: { type: 'string' },
37
+ limit: { type: 'string' },
38
+ 'plugin-dir': { type: 'string' },
39
+ title: { type: 'string' },
40
+ revision: { type: 'string' },
41
+ },
42
+ });
43
+ if (values.help) return console.log(help);
44
+
45
+ const [verb, target, ...extra] = positionals;
46
+ if (verb === 'page') {
47
+ const { brain, title, revision } = values;
48
+ if (!target || !brain?.trim() || values.plugin || values.workspace || values.decision || values.surface || values.limit || values['plugin-dir']) throw new Error(help);
49
+ const writing = extra.length > 0;
50
+ const create = typeof title === 'string' && title.trim() && revision === undefined;
51
+ const edit = typeof revision === 'string' && revision.trim() && title === undefined;
52
+ if (writing ? !create && !edit : title !== undefined || revision !== undefined) throw new Error(help);
53
+ const collection = '/api/workspace/pages';
54
+ const detail = collection + '/' + encodeURIComponent(target);
55
+ const response = !writing
56
+ ? await callApi('GET', detail, { query: { brain } })
57
+ : await callApi(edit ? 'PUT' : 'POST', edit ? detail : collection, {
58
+ data: JSON.stringify({ id: target, brainId: brain, title, revision, keys: extra }),
59
+ });
60
+ if (!response.ok) throw new Error(response.body?.error || 'Could not access the saved page.');
61
+ const page = response.body;
62
+ if (asJson) return console.log(JSON.stringify({ ok: true, ...page }));
63
+ console.log(page.path || `${page.title} (${page.version})`);
64
+ for (const chunk of page.chunks) console.log(chunk.key);
65
+ return;
66
+ }
67
+ if (values.title !== undefined || values.revision !== undefined) throw new Error(help);
68
+ if (values.brain !== undefined && ((!values.workspace && verb !== 'add') || !values.brain.trim())) {
69
+ throw new Error('--brain requires a registered brain ID and --workspace, or an add operation.');
70
+ }
71
+ if (values.workspace && (values.decision || ['add', 'coverage', 'registry', 'validate'].includes(verb))) throw new Error(help);
72
+ if (verb === 'add') {
73
+ if (!target || !values.plugin || extra.length || values.decision || values.surface || values.limit || values['plugin-dir'] || path.extname(target) !== '.md') throw new Error(help);
74
+ const stat = fs.statSync(target);
75
+ if (!stat.isFile() || stat.size > 64 * 1024) throw new Error('Choose a Markdown block no larger than 64 KiB.');
76
+ const markdown = fs.readFileSync(target, 'utf8');
77
+ const { ok, body } = await callApi('POST', '/api/ui-chunks/pool', {
78
+ data: JSON.stringify({ plugin: values.plugin, id: path.basename(target, '.md'), markdown, brainId: values.brain }),
79
+ });
80
+ if (!ok) throw new Error(body?.error || 'The dashboard could not add the block.');
81
+ return console.log(asJson ? JSON.stringify({ ok, ...body }) : 'Added ' + body.chunk.key);
82
+ }
83
+ if (verb === 'coverage') {
84
+ if (target || values.decision || values.surface || values.limit || values['plugin-dir']) throw new Error(help);
85
+ const plugins = auditUiChunkCoverage({ plugin: values.plugin });
86
+ if (values.plugin && !plugins.length) throw new Error('Plugin is not installed.');
87
+ if (asJson) return console.log(JSON.stringify({ ok: true, plugins }));
88
+ for (const item of plugins) {
89
+ const bound = item.operations.total - item.operations.missing.length;
90
+ console.log(`${item.plugin}: ${item.pageBlocks} page blocks, ${bound}/${item.operations.total} operations, ${item.dataBindings.length} data bindings, design ${item.design || 'missing'}${item.partial ? ' (partial audit)' : ''}`);
91
+ }
92
+ return;
93
+ }
94
+ if (verb === 'registry') {
95
+ if (target || values.decision || values.surface || values.plugin || values.limit || values['plugin-dir']) throw new Error(help);
96
+ return console.log(asJson ? JSON.stringify({ ok: true, file: uiChunkRegistryPath }) : uiChunkRegistryPath);
97
+ }
98
+ if (verb === 'validate') {
99
+ if (!target || extra.length || values.decision || values.surface || values.plugin || values.limit) throw new Error(help);
100
+ const chunk = validateUiChunkFile(target, { pluginDir: values['plugin-dir'] });
101
+ return console.log(asJson ? JSON.stringify({ ok: true, chunk }) : 'Validated ' + chunk.key);
102
+ }
103
+ if (values['plugin-dir']) throw new Error('--plugin-dir is only available with validate.');
104
+ if (verb === 'get') {
105
+ if (!target || extra.length || values.decision || values.plugin || values.limit) throw new Error(help);
106
+ const [plugin, id, ...rest] = target.split(':');
107
+ if (!plugin || !id || rest.length) throw new Error('Specify a chunk as plugin:id.');
108
+ const query = values.surface ? { surface: values.surface } : {};
109
+ if (values.brain) query.brain = values.brain;
110
+ const chunk = values.workspace
111
+ ? (await callApi('GET', `/api/ui-chunks/${encodeURIComponent(plugin)}/${encodeURIComponent(id)}`, { query })).body?.chunk
112
+ : getUiChunk(plugin, id, { surface: values.surface });
113
+ if (!chunk) throw new Error('UI chunk unavailable.');
114
+ return console.log(asJson ? JSON.stringify({ ok: true, chunk }) : chunk.html);
115
+ }
116
+
117
+ const query = positionals.join(' ').trim();
118
+ const limit = values.limit === undefined ? undefined : Number(values.limit);
119
+ if (values.decision && !query) throw new Error('--decision requires an explicit query.');
120
+ let result;
121
+ if (values.workspace) {
122
+ const filters = Object.fromEntries(Object.entries({ plugin: values.plugin, surface: values.surface, q: query, limit, brain: values.brain }).filter(([, value]) => value !== undefined));
123
+ const response = await callApi('GET', '/api/ui-chunks', { query: filters });
124
+ if (!response.ok) throw new Error(response.body?.error || 'The dashboard could not read the workspace pool.');
125
+ result = response.body;
126
+ } else {
127
+ result = searchUiChunks({ plugin: values.plugin, surface: values.surface, query, limit });
128
+ }
129
+ if (values.decision) result.selection = await chooseUiChunk(result.chunks, query, values.surface);
130
+ if (asJson) return console.log(JSON.stringify({ ok: true, ...result }));
131
+ for (const chunk of result.chunks) console.log(chunk.key + ' ' + chunk.title + ' [' + chunk.surfaces.join(', ') + ']');
132
+ if (!result.chunks.length) console.log('No eligible UI chunks.');
133
+ for (const issue of result.diagnostics) {
134
+ console.error(issue.plugin + (issue.id ? ':' + issue.id : '') + ' ' + issue.message);
135
+ }
136
+ if (result.selection) {
137
+ const { key, source, reason } = result.selection;
138
+ console.log('Selection (' + source + '): ' + (key ?? 'none') + (reason ? ' (' + reason + ')' : ''));
139
+ }
140
+ } catch (error) {
141
+ process.exitCode = 1;
142
+ if (asJson) console.log(JSON.stringify({ ok: false, error: error.message }));
143
+ else console.error(error.message);
144
+ }
145
+ }
@@ -113,10 +113,7 @@ export async function createPlugin(args = []) {
113
113
  // Every plugin is installed in the shared folder; --global is accepted and changes nothing.
114
114
  let withCli = args.includes("--with-cli");
115
115
  const withGenerator = args.includes("--with-generator");
116
- // A card face is bespoke owner code, authored by hand once the plugin's
117
- // function is understood. The scaffold deliberately ships without one, so
118
- // there is nothing to generate here; `--with-ui` is accepted only to explain
119
- // that to anyone who asks for it.
116
+ // The owner authors the native Home after defining the plugin's workflows.
120
117
  const asksForUi = args.includes("--with-ui");
121
118
  const withTask = args.includes("--with-task");
122
119
  const createGithub = args.includes("--github");
@@ -251,17 +248,15 @@ export async function createPlugin(args = []) {
251
248
  version: "0.1.0",
252
249
  description: pluginDesc,
253
250
  license: "MIT",
254
- // Declares this plugin as a fresh scaffold so it can install before its
255
- // bespoke card face exists. Remove the flag when the face is authored.
251
+ auth: { plugin: "auth", methods: ["passkey", "google-oauth2"], session_verification: true },
252
+ // An unfinished scaffold can install while the owner writes its Home.
256
253
  scaffold: true,
257
254
  // How work reaches this plugin. `preflight coverage` reports it until tasks are written.
258
255
  gate: { tasks: [], owned_commands: [] }
259
256
  };
260
257
  if (useCases.length > 0) manifest.use_cases = useCases;
261
258
 
262
- // House rule: a plugin for a service that needs an API key ships a CLI to save
263
- // it, so it works the moment the key is pasted. Its card face is authored by
264
- // hand later, like every other face.
259
+ // A plugin with a provider credential can save it through the shared Auth CLI.
265
260
  if (apiKeys.length) {
266
261
  withCli = true;
267
262
  manifest.secrets = apiKeys.map((key) => ({ key, description: `${pluginName} service API key (paste it in the plugin UI)`, required: true }));
@@ -301,8 +296,7 @@ export async function createPlugin(args = []) {
301
296
  ]
302
297
  });
303
298
  }
304
- // The card contract reads the plugin's real state through a declared read
305
- // command; a scaffold without this shows no live status.
299
+ // Give the Home a declared read operation for live status.
306
300
  manifest.status = { command: "status", refresh_seconds: 60 };
307
301
 
308
302
  const cliContent = `#!/usr/bin/env node
@@ -358,12 +352,6 @@ export default run;
358
352
  manifest.tasks = [{ intent: taskIntent, schedule: taskSchedule, command: taskCommand, placement: 'selected-node' }];
359
353
  }
360
354
 
361
- // No UI is generated. Every plugin must have a card face, but a face is
362
- // bespoke owner code authored by hand once the plugin's function is known:
363
- // a generated stub is what produced a ecosystem of identical cards. The
364
- // scaffold therefore reports the face as outstanding rather than faking one.
365
- const cardOutstanding = true;
366
-
367
355
  if (isCapability) {
368
356
  manifest.deploy = {
369
357
  targets: ["ssss-app", "nextjs", "react", "flask"],
@@ -445,19 +433,12 @@ export default generateContext;
445
433
  fs.writeFileSync(path.join(pluginDir, "generator.mjs"), generatorContent, "utf8");
446
434
  }
447
435
 
448
- manifest.capability = {
449
- entry: "capability/index.mjs",
450
- exports: ["getCapabilityStatus"]
451
- };
452
-
453
436
  const validation = validatePluginManifest(manifest);
454
437
  if (!validation.valid) {
455
438
  console.error("❌ Validation failed for generated manifest:", validation.errors);
456
439
  fs.rmSync(pluginDir, { recursive: true, force: true });
457
440
  process.exit(1);
458
441
  }
459
- // The scaffold installs without a card face, and says so. Its face is
460
- // authored by hand next; the warning is the reminder, not a failure.
461
442
  if (validation.warnings?.length) {
462
443
  for (const warning of validation.warnings) console.log(`⚠️ ${warning}`);
463
444
  }
@@ -492,7 +473,7 @@ export default generateContext;
492
473
  if (category) lines.push(`- **SSSS Category**: \`${category}\``);
493
474
  if (withCli) lines.push(`- **CLI Command**: \`npx total-recall ${id}\``);
494
475
  if (withTask) lines.push(`- **Scheduled task**: \`${taskCommand}\` at \`${taskSchedule}\` (selected node; implement the command and choose a node before use)`);
495
- if (asksForUi) lines.push('- **UI**: no card face is generated. Author `ui/card.js` and `ui/DESIGN.md` by hand for this plugin\'s own function, then declare the face in `ui.elements[]`');
476
+ if (asksForUi) lines.push('- **UI**: author the plugin workspace and its native panels for this plugin’s own function. Declare the panels in `ui.elements[]`.');
496
477
  if (apiKeys.length) lines.push('- **API key**: paste it in the plugin UI (`save-token` event) or pipe it to `npx total-recall ' + id + ' token set --stdin`; stored as `' + apiKeys[0] + '` in the secrets store');
497
478
  lines.push(
498
479
  "",
@@ -506,6 +487,24 @@ export default generateContext;
506
487
  ""
507
488
  );
508
489
 
490
+ lines.push(
491
+ "## Authoring generative UI",
492
+ "",
493
+ "Keep a bespoke `DESIGN.md` at the plugin root. Describe the palette, typography, layout, interaction and accessibility. Work with the user on the design and assets. Package this file and the authored blocks with the plugin.",
494
+ "",
495
+ "Author one SSSS Markdown document per reusable block at `ui/chunks/<id>.md`. Use `type: ui-chunk:chunk`, the manifest ID as `plugin`, the filename stem as `id`, a `title`, `description`, ISO `timestamp`, meaningful `intents` and supported `surfaces` from `page`, `left`, `right` and `bottom`. Use raw HTML for the body.",
496
+ "",
497
+ "Declare the native workspace entry in `ui.home` and its design in `ui.design_tokens`. Bind each block to exact manifest operation names in `operations` and verified fields in `data` using `operation:/json/pointer`. Declare browser-safe inputs so users can run the operation in place. Use a native `panel` for specialized editable controls. Keep credentials and private data out of routing metadata.",
498
+ "",
499
+ "Find the extension with `total-recall plugin chunks registry` and verify each block with `total-recall plugin chunks validate <file>`. Compare `total-recall plugin chunks coverage --plugin <id>` with the owner inventory. Use `total-recall plugin chunks <intent> --surface <surface>` to find blocks. Add `--decision` to request an explicit typed choice. The result identifies a block by its stable `plugin:id`.",
500
+ "",
501
+ "Keep packaged defaults in the owner repository. Users can choose and arrange installed blocks, provide their own HTML and edit the design with their agent. Submit broadly useful owner changes to the plugin repository.",
502
+ "",
503
+ "An agent can author any additional SSSS block for an enabled plugin. For a task-specific block, use `total-recall plugin chunks add <id.md> --plugin <owner> --brain <brain> --json` to validate and publish it. Read the result back by its stable `owner:id` key.",
504
+ "",
505
+ "For contextual selection, use `total-recall decision compose --plugin <owner> --intent <intent> --page <id> --title <title> --brain <brain>`. For exact placement, use `total-recall plugin chunks page <id> <owner:block>... --title <title> --brain <brain>`. To edit an existing page, read it with the same command without block keys, then pass its complete ordered keys and `--revision <version>` instead of `--title`. Reopen the saved page and verify each workflow against real data.",
506
+ ""
507
+ );
509
508
  fs.writeFileSync(path.join(pluginDir, "README.md"), lines.join("\n"), "utf8");
510
509
 
511
510
  // ── Standalone repository files ──────────────────────────────────────────
@@ -533,34 +532,7 @@ export default generateContext;
533
532
  fs.writeFileSync(path.join(pluginDir, '.gitignore'), 'node_modules/\n.env*\n.agent/skills/total-recall/\ndist/\nreports/\n.DS_Store\nINSTRUCTIONS.md\nAGENTS.md\n', 'utf8');
534
533
  fs.writeFileSync(path.join(pluginDir, 'LICENSE'), mitLicense(holder), 'utf8');
535
534
 
536
- // Capability brick
537
- fs.mkdirSync(path.join(pluginDir, 'capability'), { recursive: true });
538
- fs.writeFileSync(path.join(pluginDir, 'capability', 'index.mjs'), `/**
539
- * Portable capability brick for ${pluginName}.
540
- * Zero host dependencies; pure portable JavaScript.
541
- */
542
- export async function getCapabilityStatus() {
543
- return { ready: true, initialized: true };
544
- }
545
- `, 'utf8');
546
- fs.writeFileSync(path.join(pluginDir, 'capability', 'BRICK.md'), `# ${pluginName} — Capability Brick
547
-
548
- Portable core capability for ${pluginName}.
549
-
550
- ## Exported Functions
551
- - \`getCapabilityStatus()\`: Returns capability readiness and initialization status.
552
- `, 'utf8');
553
-
554
535
  fs.mkdirSync(path.join(pluginDir, 'test'), { recursive: true });
555
- fs.writeFileSync(path.join(pluginDir, 'test', 'capability.test.mjs'), `import test from 'node:test';
556
- import assert from 'node:assert/strict';
557
- import { getCapabilityStatus } from '../capability/index.mjs';
558
-
559
- test('capability brick loads and exports status', async () => {
560
- const status = await getCapabilityStatus();
561
- assert.equal(status.ready, true);
562
- });
563
- `, 'utf8');
564
536
  fs.writeFileSync(path.join(pluginDir, 'test', 'manifest.test.mjs'), `import test from 'node:test';
565
537
  import assert from 'node:assert/strict';
566
538
  import fs from 'node:fs';
@@ -10,6 +10,7 @@ import { getPlugin, getPluginMonetization, globalPluginsDir, projectPluginsDir }
10
10
  import { describePlugin, pruneReplacementArchives, replacementArchiveDir } from '../../core/plugin-store.mjs';
11
11
  import { buildPluginCatalog } from '../../core/plugin-catalog.mjs';
12
12
  import { setPluginActive } from '../../core/plugin-activation.mjs';
13
+ import { detectProjectBrain } from '../../core/brain-locate.mjs';
13
14
 
14
15
  function printHelp() {
15
16
  console.log(`
@@ -26,6 +27,7 @@ Usage:
26
27
  Commands:
27
28
  list Installed plugins (project & global) with source and sharing
28
29
  library [--plugin ID] Installed CLI operation library (--json for agents)
30
+ chunks [query] Search installed SSSS UI chunks and validate owner files
29
31
  refresh Rebuild installed command inventories and instruction surfaces
30
32
  copies [dir] [--apply] Audit repository copies of shared defaults and shadow links. --apply
31
33
  deletes bundled matches, unlinks shadows (on/off records are kept)
@@ -39,6 +41,7 @@ Commands:
39
41
  on <id> / off <id> Enable/disable host execution for this repository alone
40
42
  --all-repos Change the shared setting for every repository
41
43
  --clear Drop this repository's override; follow the shared setting
44
+ on-use <id> Activate when deliberately opened or used in this repository
42
45
  available [query] Plugins bundled with this Total Recall package
43
46
  peers [query] Plugins your mesh peers share (queried live)
44
47
  search <query> Search bundled plugins and mesh peers
@@ -75,7 +78,7 @@ Commands:
75
78
  --category <cat> Declare an SSSS memory category
76
79
  --with-cli Generate CLI command handler
77
80
  --with-generator Generate context generator
78
- --with-ui Generate token-driven panel element
81
+ --with-ui Include owner UI authoring instructions
79
82
  --with-task Declare a selected-node scheduled task
80
83
  --task-command <cmd> Task CLI subcommand (requires --with-task)
81
84
  --task-schedule <cron> Five-field local-time schedule
@@ -116,33 +119,41 @@ export async function run(argv = []) {
116
119
  if (!result.ok || !setup.ok) process.exitCode = 1;
117
120
  return;
118
121
  }
119
- if (command === 'on' || command === 'off') {
122
+ if (['on', 'off', 'on-use'].includes(command)) {
123
+ const projectRoot = detectProjectBrain(process.cwd())?.projectRoot ?? process.cwd();
120
124
  const id = rest.find(argument => !argument.startsWith('-'));
121
125
  if (!id) throw new Error(`Usage: total-recall plugin ${command} <id> [--all-repos|--clear]`);
122
126
  const flags = rest.filter(argument => argument.startsWith('-'));
127
+ if (command === 'on-use' && flags.some(flag => flag !== '--json')) throw new Error('Use on-use for one repository without --all-repos or --clear.');
123
128
  const unknown = flags.find(flag => !['--all-repos', '--clear', '--json'].includes(flag));
124
129
  if (unknown) throw new Error(`Unsupported plugin ${command} option: ${unknown}`);
125
130
  if (flags.includes('--all-repos') && flags.includes('--clear')) throw new Error('Choose --all-repos or --clear, not both');
126
131
  if (flags.includes('--clear')) {
127
132
  if (command === 'off') throw new Error('--clear removes a repository override; use it with on, not off');
128
- const cleared = await setPluginActive(id, true, { clear: true });
133
+ const cleared = await setPluginActive(id, true, { clear: true, projectRoot });
129
134
  const activation = cleared.activation || {};
130
135
  console.log(flags.includes('--json') ? JSON.stringify(cleared)
131
136
  : `♻️ ${id} follows the shared setting again in this repository (${activation.state || 'unknown'})`);
132
137
  if (!cleared.compilation.ok) process.exitCode = 1;
133
138
  return;
134
139
  }
135
- const result = await setPluginActive(id, command === 'on', { scope: flags.includes('--all-repos') ? 'shared' : 'project' });
140
+ const result = await setPluginActive(id, command === 'on-use' ? command : command === 'on', { projectRoot, scope: flags.includes('--all-repos') ? 'shared' : 'project' });
136
141
  const activation = result.activation || {};
137
142
  if (flags.includes('--json')) console.log(JSON.stringify(result));
138
- else console.log(`${command === 'on' ? '✅' : '⛔'} ${id} ${command === 'on' ? 'enabled' : 'disabled'} for ${result.scope === 'shared' ? 'every repository' : 'this repository'} (${activation.state || 'unknown'})`);
139
- if (!result.compilation.ok) process.exitCode = 1;
143
+ else if (command === 'on-use') console.log(`${id} will activate on use in this repository.`);
144
+ else {
145
+ console.log(`${command === 'on' ? '✅' : '⛔'} ${id} ${command === 'on' ? 'enabled' : 'disabled'} for ${result.scope === 'shared' ? 'every repository' : 'this repository'} (${activation.state || 'unknown'})`);
146
+ if (result.cleanup?.state === 'archived') console.log('Repository plugin state archived.');
147
+ if (result.cleanup?.state === 'restored') console.log('Repository plugin state restored.');
148
+ if (result.cleanup?.ok === false) console.error(`Cleanup pending. ${result.cleanup.error}`);
149
+ }
150
+ if (!result.compilation.ok || result.cleanup?.ok === false) process.exitCode = 1;
140
151
  return;
141
152
  }
142
153
 
143
- if (command === 'card' || command === 'card-face' || command === 'skin') {
144
- await managePluginCard(rest);
145
- return;
154
+ if (command === 'chunks') {
155
+ const { runPluginChunks } = await import('./chunks.mjs');
156
+ return runPluginChunks(rest);
146
157
  }
147
158
 
148
159
  if (rest.includes('--help') || rest.includes('-h')) {
package/src/cli/setup.mjs CHANGED
@@ -22,6 +22,7 @@ import path from 'node:path';
22
22
  import https from 'node:https';
23
23
  import { fileURLToPath } from 'node:url';
24
24
  import { resolveAgentDir, resolveBrainDir } from './agent-dir.mjs';
25
+ import { writeBrainConnection } from '../core/memory-brain.mjs';
25
26
  const { loadSecrets, saveSecrets } = await __loadOwnedPlugin('auth', 'secrets-store');
26
27
 
27
28
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
@@ -375,15 +376,7 @@ async function getGitHubUser(githubToken) {
375
376
  // ─── Store brain config ───────────────────────────────────────────────────────
376
377
 
377
378
  async function storeBrainConfig(brDir, brainUrl, token, provider, apiKey, extra = {}) {
378
- const configDir = path.join(brDir, 'config');
379
- fs.mkdirSync(configDir, { recursive: true });
380
-
381
- // brain.json
382
- fs.writeFileSync(
383
- path.join(configDir, 'brain.json'),
384
- JSON.stringify({ url: brainUrl, token, provider, ...extra }, null, 2),
385
- 'utf8'
386
- );
379
+ writeBrainConnection(brDir, { url: brainUrl, token, provider, ...extra });
387
380
 
388
381
  // secrets.enc
389
382
  let secrets = {};
package/src/cli/start.mjs CHANGED
@@ -39,6 +39,7 @@ export default function start(args) {
39
39
  --help Show this help
40
40
 
41
41
  The server reads config from ~/.agent/config/security.yml.
42
+ TR_DASHBOARD_BRAIN_DIR can select the dashboard's global memory and project registry.
42
43
  Use Cloudflare or Caddy in front for HTTPS when accessing remotely.
43
44
  `);
44
45
  return;
@@ -16,6 +16,23 @@ export async function inspectStartup(options = {}) {
16
16
  return startupHealth({ brainDir: globalBrain, brainUrl: url, token, brainId: cfg.layer === 'project' && cfg.name ? `project:${cfg.name}` : null, ...options });
17
17
  }
18
18
 
19
+ /**
20
+ * One line per thing a session should see at start: a dashboard older than its
21
+ * sources, and each plugin startup check that needs attention or could not run.
22
+ */
23
+ export function startupFindings(report) {
24
+ const lines = [];
25
+ const dashboard = report.dashboard;
26
+ if (dashboard && ['stale', 'missing'].includes(dashboard.status)) {
27
+ lines.push(`Dashboard: bundle ${dashboard.status}${dashboard.newer_source ? ` (${dashboard.newer_source} is newer)` : ''}; the server rebuilds it, see /health dashboard.`);
28
+ } else if (dashboard?.status === 'unknown') lines.push(`Dashboard: freshness unknown (${dashboard.reason}).`);
29
+ for (const check of report.plugin_checks || []) {
30
+ if (check.status === 'attention') lines.push(`${check.command}: ${check.summary}`);
31
+ else if (check.status === 'unavailable') lines.push(`${check.command}: unavailable (${check.reason})${check.summary ? ` ${check.summary}` : ''}`);
32
+ }
33
+ return lines;
34
+ }
35
+
19
36
  export default async function startup(args = []) {
20
37
  if (!args.length || args.includes('--help') || args.includes('-h')) {
21
38
  console.log('Usage: total-recall startup check|ensure [--json] [--app-check <registered-repo-command>] [--app-start <registered-repo-command>]\ncheck is read-only. ensure starts only missing configured local managed services and an explicitly declared current-repo app command; never restarts running/unknown or remote services. SSSS is checked as tooling, not a fabricated daemon. App health JSON must contain ok:true and status:ready|healthy|running. No declaration means app readiness is unknown.');
@@ -39,6 +56,7 @@ export default async function startup(args = []) {
39
56
  if (report.server?.reason) console.log(`Server: ${report.server.reason}`);
40
57
  if (report.server?.stale) console.log(`Server: running ${report.server.stale.running} with ${report.server.stale.on_disk} on disk; it has not been replaced.`);
41
58
  for (const error of report.required_plugins?.errors || []) console.log(`Required plugin: ${error}`);
59
+ for (const line of startupFindings(report)) console.log(line);
42
60
  const harnesses = await queryHarnessUsage().catch(() => []);
43
61
  const availH = harnesses.filter(h => h.available);
44
62
  const readyH = availH.filter(h => h.authed);
@@ -62,38 +62,43 @@ export function extractFrontmatter(content) {
62
62
  * @returns {object}
63
63
  */
64
64
  export function resolveTokenReferences(tokens) {
65
+ let visits = 0;
66
+ function checkBudget(depth) {
67
+ if (++visits > 20_000 || depth > 64) throw new DesignTokenError(['token references exceed the expansion limit']);
68
+ }
69
+
65
70
  function getNested(obj, pathParts) {
66
71
  let curr = obj;
67
72
  for (const p of pathParts) {
68
- if (curr === undefined || curr === null) return undefined;
73
+ if (!isPlainObject(curr) || !Object.hasOwn(curr, p)) return undefined;
69
74
  curr = curr[p];
70
75
  }
71
76
  return curr;
72
77
  }
73
78
 
74
- function resolveVal(val, seen) {
79
+ function resolveVal(val, seen, depth) {
80
+ checkBudget(depth);
75
81
  if (typeof val !== 'string') return val;
76
82
  const whole = val.match(/^\{([a-zA-Z0-9_.-]+)\}$/);
77
83
  if (whole && !seen.has(whole[1])) {
78
84
  const target = getNested(tokens, whole[1].split('.'));
79
85
  // A whole-value reference may point at a composite (e.g. a typography style).
80
- if (isPlainObject(target)) return walk(target, new Set([...seen, whole[1]]));
86
+ if (isPlainObject(target)) return walk(target, new Set([...seen, whole[1]]), depth + 1);
81
87
  }
82
88
  return val.replace(/\{([a-zA-Z0-9_.-]+)\}/g, (match, tokenPath) => {
83
89
  if (seen.has(tokenPath)) return match;
84
90
  const resolved = getNested(tokens, tokenPath.split('.'));
85
91
  if (typeof resolved === 'string' || typeof resolved === 'number') {
86
- return String(resolveVal(resolved, new Set([...seen, tokenPath])));
92
+ return String(resolveVal(resolved, new Set([...seen, tokenPath]), depth + 1));
87
93
  }
88
94
  return match;
89
95
  });
90
96
  }
91
97
 
92
- function walk(node, seen = new Set()) {
93
- if (!isPlainObject(node)) return resolveVal(node, seen);
94
- const out = {};
95
- for (const [k, v] of Object.entries(node)) out[k] = walk(v, seen);
96
- return out;
98
+ function walk(node, seen = new Set(), depth = 0) {
99
+ checkBudget(depth);
100
+ if (!isPlainObject(node)) return resolveVal(node, seen, depth);
101
+ return Object.fromEntries(Object.entries(node).map(([k, v]) => [k, walk(v, seen, depth + 1)]));
97
102
  }
98
103
 
99
104
  return walk(tokens);
@@ -251,7 +251,7 @@ export function generateUiElements(manifest, { pluginDir, target, tokens, typesc
251
251
  };
252
252
  add(UI_MANIFEST_FILE, `${JSON.stringify(uiManifest, null, 2)}\n`);
253
253
 
254
- const first = elements[0];
254
+ const first = elements.find(element => element.id === spec.home) ?? elements[0];
255
255
  const hasTokens = Boolean(tokenInfo.source);
256
256
  const usage = (target === 'react'
257
257
  ? [
@@ -24,6 +24,11 @@ export function globalBrainDirFor(env = process.env) {
24
24
  return path.join(agentDir, 'skills', 'total-recall');
25
25
  }
26
26
 
27
+ /** The dashboard can read a host brain while preview plugin state stays isolated. */
28
+ export function dashboardBrainDir(env = process.env, fallback = globalBrainDirFor(env)) {
29
+ return env.TR_DASHBOARD_BRAIN_DIR ? path.resolve(env.TR_DASHBOARD_BRAIN_DIR) : fallback;
30
+ }
31
+
27
32
  function togglesPath(globalBrainDir) {
28
33
  return path.join(globalBrainDir, 'config', 'brain-toggles.json');
29
34
  }
@@ -340,7 +340,11 @@ export async function updateAllBrains(opts = {}) {
340
340
  // A lockfile-only update builds no tree, so it runs no lifecycle scripts: npm still
341
341
  // ran a checkout's own postinstall here, which fails in a repository that was never
342
342
  // installed (a postinstall calling a tool that is not yet installed, 2026-11-09).
343
- else if (!needsInstall) args.push(group.manager === 'pnpm' ? '--lockfile-only' : '--package-lock-only', '--ignore-scripts');
343
+ // Only where no tree exists: npm's lockfile-only mode also rewrites the tree record
344
+ // (node_modules/.package-lock.json) to versions it never installs, and npm then reports the
345
+ // stale tree "up to date" forever (21 plugins on @ssss/cli 0.14.4 under 0.14.5, 2026-11-12).
346
+ // A tree that exists gets a real install, so the tree and its record agree.
347
+ else if (!needsInstall && noInstallTree(group.owner)) args.push(group.manager === 'pnpm' ? '--lockfile-only' : '--package-lock-only', '--ignore-scripts');
344
348
  const install = exec(group.manager, args, { cwd: group.owner, env: installEnv(), encoding: 'utf8',
345
349
  timeout: 600000, maxBuffer: 8 * 1024 * 1024 });
346
350
  if (install.status !== 0) throw new Error(install.error?.message || install.stderr?.trim().slice(-1500) || `Install exited ${install.status}`);
@@ -33,7 +33,11 @@ export function getDaemonObservation() { return observeDaemon(brainDir); }
33
33
  * @returns {'running'|'dead'|'not_started'|'conflict'|'unknown'}
34
34
  */
35
35
  export function getDaemonStatus() {
36
- const { status } = getDaemonObservation();
36
+ // A supervised daemon can run from a different verified installation than the server.
37
+ const entry = process.env.TR_SUPERVISED_DAEMON_ENTRY;
38
+ const { status } = process.env.DISABLE_DAEMON === 'true' && entry && path.isAbsolute(entry)
39
+ ? observeDaemon(brainDir, { expectedEntry: entry })
40
+ : getDaemonObservation();
37
41
  return status === 'not-started' ? 'not_started' : status === 'stopped' ? 'dead' : status;
38
42
  }
39
43