total-recall-brain 3.44.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 (502) hide show
  1. package/bin/total-recall.mjs +10 -6
  2. package/docs/ARCHITECTURE.md +10 -7
  3. package/docs/reference/cli-reference.md +13 -8
  4. package/frontend/dist/assets/index-BRYE1jmv.css +1 -0
  5. package/frontend/dist/assets/index-D1goIPjC.js +5598 -0
  6. package/frontend/dist/index.html +2 -2
  7. package/frontend/dist/sw.js +5 -4
  8. package/frontend/src/App.tsx +185 -238
  9. package/frontend/src/api/auth-inventory.ts +62 -0
  10. package/frontend/src/api/memory.ts +13 -8
  11. package/frontend/src/api/plugin-credentials.ts +23 -0
  12. package/frontend/src/api/plugins.ts +37 -53
  13. package/frontend/src/api/workspace-drawers.ts +97 -0
  14. package/frontend/src/components/BrainSelector.tsx +9 -3
  15. package/frontend/src/components/plugins/PluginPanel.tsx +83 -42
  16. package/frontend/src/components/plugins/PluginSettings.tsx +10 -20
  17. package/frontend/src/components/plugins/PluginWorkspace.tsx +367 -0
  18. package/frontend/src/components/plugins/ScopedPluginCommands.tsx +142 -0
  19. package/frontend/src/components/plugins/plugin-frame.ts +44 -33
  20. package/frontend/src/components/plugins/scoped-plugin-operations.ts +28 -0
  21. package/frontend/src/components/workspace/DrawerChat.tsx +110 -0
  22. package/frontend/src/components/workspace/DrawerLayout.tsx +196 -0
  23. package/frontend/src/components/workspace/DrawerMarkup.tsx +49 -0
  24. package/frontend/src/components/workspace/PluginChunkLibrary.tsx +92 -0
  25. package/frontend/src/components/workspace/PluginHome.tsx +76 -0
  26. package/frontend/src/components/workspace/WorkspaceDrawers.tsx +96 -0
  27. package/frontend/src/components/workspace/WorkspacePage.tsx +95 -0
  28. package/frontend/src/components/workspace/usePluginDesign.ts +38 -0
  29. package/frontend/src/index.css +409 -136
  30. package/frontend/src/pages/HelpPage.tsx +15 -46
  31. package/frontend/src/pages/MemoryPage.tsx +19 -36
  32. package/frontend/src/pages/SettingsPage.tsx +1 -1
  33. package/metadata.plugin.schema.json +53 -227
  34. package/package.json +1 -1
  35. package/scaffold/.agent/skills/plugin/SKILL.md +13 -11
  36. package/scaffold/.agent/skills/plugin/evals/README.md +14 -21
  37. package/scaffold/.agent/skills/plugin/evals/cases/01-fabricated-seed.mjs +15 -18
  38. package/scaffold/.agent/skills/plugin/evals/cases/02-reassuring-default.mjs +19 -24
  39. package/scaffold/.agent/skills/plugin/evals/cases/03-declared-template.mjs +12 -20
  40. package/scaffold/.agent/skills/plugin/evals/cases/04-home-collects-credential.mjs +35 -0
  41. package/scaffold/.agent/skills/plugin/evals/cases/05-host-leak-in-scaffold.mjs +8 -28
  42. package/scaffold/.agent/skills/plugin/evals/cases/06-correct-plugin.mjs +85 -47
  43. package/scaffold/.agent/skills/plugin/evals/run.mjs +17 -18
  44. package/scaffold/.agent/skills/plugin/prompts/05-credentials.md +4 -4
  45. package/scaffold/.agent/skills/plugin/prompts/07-scaffold.md +2 -2
  46. package/scaffold/.agent/skills/plugin/prompts/08-verify.md +4 -4
  47. package/scaffold/.agent/skills/plugin/references/anti-patterns.md +2 -2
  48. package/scaffold/.agent/skills/plugin/references/generative-home.md +38 -0
  49. package/scaffold/.agent/skills/plugin/references/scaffold.md +5 -5
  50. package/scaffold/.agent/skills/plugin/references/surfaces.md +13 -4
  51. package/scaffold/.agent/skills/plugin/scripts/record.mjs +75 -153
  52. package/scaffold/.agent/skills/plugin/subagents/plugin-reviewer.md +4 -4
  53. package/scaffold/.agent/skills/total-recall/plugins/auth/DESIGN.md +76 -0
  54. package/scaffold/.agent/skills/total-recall/plugins/auth/README.md +3 -1
  55. package/scaffold/.agent/skills/total-recall/plugins/auth/cli.mjs +20 -15
  56. package/scaffold/.agent/skills/total-recall/plugins/auth/package-lock.json +7 -7
  57. package/scaffold/.agent/skills/total-recall/plugins/auth/package.json +2 -1
  58. package/scaffold/.agent/skills/total-recall/plugins/auth/plugin.json +13 -51
  59. package/scaffold/.agent/skills/total-recall/plugins/auth/src/cli-secret.mjs +20 -1
  60. package/scaffold/.agent/skills/total-recall/plugins/auth/src/secrets-store.mjs +12 -1
  61. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/access-overview.md +17 -0
  62. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/agent-login.md +20 -0
  63. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/baseline-audit.md +22 -0
  64. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/credential-repository-binding.md +17 -0
  65. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/credential-store-maintenance.md +17 -0
  66. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/dashboard-password.md +18 -0
  67. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/dashboard-sessions.md +18 -0
  68. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/endpoint-probe.md +23 -0
  69. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/google-sign-in.md +21 -0
  70. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/mesh-machines.md +16 -0
  71. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/passkey-enrollment.md +21 -0
  72. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/registered-brains.md +16 -0
  73. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/scoped-access-keys.md +17 -0
  74. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/secret-inventory.md +25 -0
  75. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/signing-key-rotation.md +22 -0
  76. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/home.js +375 -0
  77. package/scaffold/.agent/skills/total-recall/plugins/automations/BRICK.md +7 -0
  78. package/scaffold/.agent/skills/total-recall/plugins/automations/DESIGN.md +53 -0
  79. package/scaffold/.agent/skills/total-recall/plugins/automations/LICENSE +21 -0
  80. package/scaffold/.agent/skills/total-recall/plugins/automations/README.md +66 -0
  81. package/scaffold/.agent/skills/total-recall/plugins/automations/adapters.mjs +247 -0
  82. package/scaffold/.agent/skills/total-recall/plugins/automations/capability/index.mjs +16 -0
  83. package/scaffold/.agent/skills/total-recall/plugins/automations/cli.mjs +130 -0
  84. package/{src/core/plugin-cron.mjs → scaffold/.agent/skills/total-recall/plugins/automations/cron.mjs} +1 -3
  85. package/scaffold/.agent/skills/total-recall/plugins/automations/inventory.mjs +88 -0
  86. package/scaffold/.agent/skills/total-recall/plugins/automations/package-lock.json +7661 -0
  87. package/scaffold/.agent/skills/total-recall/plugins/automations/package.json +36 -0
  88. package/scaffold/.agent/skills/total-recall/plugins/automations/plugin.json +151 -0
  89. package/scaffold/.agent/skills/total-recall/plugins/automations/scheduler.mjs +246 -0
  90. package/scaffold/.agent/skills/total-recall/plugins/automations/ui/automations.js +2 -0
  91. package/scaffold/.agent/skills/total-recall/plugins/automations/ui/chunks/control-ledger.md +42 -0
  92. package/scaffold/.agent/skills/total-recall/plugins/automations/ui/chunks/local-inventory-triage.md +17 -0
  93. package/scaffold/.agent/skills/total-recall/plugins/automations/ui/chunks/pending-control.md +39 -0
  94. package/scaffold/.agent/skills/total-recall/plugins/automations/ui/chunks/run-evidence.md +41 -0
  95. package/scaffold/.agent/skills/total-recall/plugins/automations/ui/chunks/schedule-vs-run-evidence.md +17 -0
  96. package/scaffold/.agent/skills/total-recall/plugins/automations/ui/chunks/source-coverage.md +41 -0
  97. package/scaffold/.agent/skills/total-recall/plugins/automations/ui/home.js +278 -0
  98. package/scaffold/.agent/skills/total-recall/plugins/code-quality/DESIGN.md +53 -0
  99. package/scaffold/.agent/skills/total-recall/plugins/code-quality/cli.mjs +23 -0
  100. package/scaffold/.agent/skills/total-recall/plugins/code-quality/commands/run-core.mjs +5 -3
  101. package/scaffold/.agent/skills/total-recall/plugins/code-quality/core/check.mjs +61 -7
  102. package/scaffold/.agent/skills/total-recall/plugins/code-quality/core/report-data.mjs +40 -14
  103. package/scaffold/.agent/skills/total-recall/plugins/code-quality/core/report.mjs +15 -40
  104. package/scaffold/.agent/skills/total-recall/plugins/code-quality/package-lock.json +7 -7
  105. package/scaffold/.agent/skills/total-recall/plugins/code-quality/package.json +2 -1
  106. package/scaffold/.agent/skills/total-recall/plugins/code-quality/plugin.json +40 -40
  107. package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/chunks/config.md +15 -0
  108. package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/chunks/detect.md +15 -0
  109. package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/chunks/gate.md +15 -0
  110. package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/chunks/init.md +15 -0
  111. package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/chunks/report.md +17 -0
  112. package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/chunks/run.md +17 -0
  113. package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/chunks/snapshot.md +15 -0
  114. package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/code-quality-report.mjs +55 -23
  115. package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/home.mjs +214 -0
  116. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/DESIGN.md +146 -0
  117. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/package-lock.json +7 -7
  118. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/package.json +2 -1
  119. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/plugin.json +51 -34
  120. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/src/command.mjs +1 -1
  121. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/create.md +35 -0
  122. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/history.md +35 -0
  123. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/library.md +49 -0
  124. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/list.md +42 -0
  125. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/promote.md +40 -0
  126. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/read.md +25 -0
  127. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/remove.md +26 -0
  128. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/rollback.md +26 -0
  129. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/show.md +53 -0
  130. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/status.md +40 -0
  131. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/test-path.md +38 -0
  132. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/test.md +46 -0
  133. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/update.md +32 -0
  134. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/home.js +533 -0
  135. package/scaffold/.agent/skills/total-recall/plugins/embeddings/DESIGN.md +110 -0
  136. package/scaffold/.agent/skills/total-recall/plugins/embeddings/package-lock.json +7 -7
  137. package/scaffold/.agent/skills/total-recall/plugins/embeddings/package.json +2 -1
  138. package/scaffold/.agent/skills/total-recall/plugins/embeddings/plugin.json +13 -10
  139. package/scaffold/.agent/skills/total-recall/plugins/embeddings/ui/chunks/benchmark.md +49 -0
  140. package/scaffold/.agent/skills/total-recall/plugins/embeddings/ui/chunks/coverage.md +53 -0
  141. package/scaffold/.agent/skills/total-recall/plugins/embeddings/ui/chunks/models.md +43 -0
  142. package/scaffold/.agent/skills/total-recall/plugins/embeddings/ui/chunks/pull.md +41 -0
  143. package/scaffold/.agent/skills/total-recall/plugins/embeddings/ui/chunks/status.md +59 -0
  144. package/scaffold/.agent/skills/total-recall/plugins/embeddings/ui/home.js +353 -0
  145. package/scaffold/.agent/skills/total-recall/plugins/git/DESIGN.md +31 -0
  146. package/scaffold/.agent/skills/total-recall/plugins/git/README.md +136 -0
  147. package/scaffold/.agent/skills/total-recall/plugins/{git-sentinel → git}/cli.mjs +140 -24
  148. package/scaffold/.agent/skills/total-recall/plugins/{git-sentinel → git}/package-lock.json +9 -9
  149. package/scaffold/.agent/skills/total-recall/plugins/{git-sentinel → git}/package.json +4 -2
  150. package/scaffold/.agent/skills/total-recall/plugins/git/plugin.json +151 -0
  151. package/scaffold/.agent/skills/total-recall/plugins/git/src/lib/context.mjs +94 -0
  152. package/scaffold/.agent/skills/total-recall/plugins/git/src/lib/phase3-spec-support.mjs +50 -0
  153. package/scaffold/.agent/skills/total-recall/plugins/git/src/lib/runtime.mjs +40 -0
  154. package/scaffold/.agent/skills/total-recall/plugins/git/src/lib/spec-support.mjs +51 -0
  155. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/_support.mjs +195 -0
  156. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/auth.mjs +201 -0
  157. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/bisect.mjs +40 -0
  158. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/cli-meta.mjs +159 -0
  159. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/commit-memory.mjs +54 -0
  160. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/commit.mjs +46 -0
  161. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/fleet.mjs +174 -0
  162. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/force-push.mjs +58 -0
  163. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/group.mjs +119 -0
  164. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/handoff.mjs +59 -0
  165. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/message.mjs +22 -0
  166. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/resolve.mjs +60 -0
  167. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/rules.mjs +81 -0
  168. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/secret-firewall.mjs +92 -0
  169. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/undo.mjs +156 -0
  170. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/unmerged.mjs +182 -0
  171. package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/why.mjs +16 -0
  172. package/scaffold/.agent/skills/total-recall/plugins/git/ui/chunks/change-comparison.md +27 -0
  173. package/scaffold/.agent/skills/total-recall/plugins/git/ui/chunks/commit-identity.md +22 -0
  174. package/scaffold/.agent/skills/total-recall/plugins/git/ui/chunks/create-worktree.md +25 -0
  175. package/scaffold/.agent/skills/total-recall/plugins/git/ui/chunks/registered-worktrees.md +22 -0
  176. package/scaffold/.agent/skills/total-recall/plugins/git/ui/chunks/remove-worktree.md +23 -0
  177. package/scaffold/.agent/skills/total-recall/plugins/git/ui/chunks/repository-ledger.md +25 -0
  178. package/scaffold/.agent/skills/total-recall/plugins/git/ui/chunks/unmerged-work.md +22 -0
  179. package/scaffold/.agent/skills/total-recall/plugins/git/ui/chunks/upstream-divergence.md +17 -0
  180. package/scaffold/.agent/skills/total-recall/plugins/git/ui/chunks/worktree-conflict-triage.md +17 -0
  181. package/scaffold/.agent/skills/total-recall/plugins/git/ui/chunks/worktree-terminal.md +22 -0
  182. package/scaffold/.agent/skills/total-recall/plugins/git/ui/home.js +273 -0
  183. package/scaffold/.agent/skills/total-recall/plugins/mesh/DESIGN.md +35 -0
  184. package/scaffold/.agent/skills/total-recall/plugins/mesh/README.md +4 -5
  185. package/scaffold/.agent/skills/total-recall/plugins/mesh/cli.mjs +9 -3
  186. package/scaffold/.agent/skills/total-recall/plugins/mesh/package-lock.json +7 -7
  187. package/scaffold/.agent/skills/total-recall/plugins/mesh/package.json +2 -1
  188. package/scaffold/.agent/skills/total-recall/plugins/mesh/plugin.json +37 -39
  189. package/scaffold/.agent/skills/total-recall/plugins/mesh/src/cli/mesh.mjs +5 -3
  190. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/active-device-dispatch.md +22 -0
  191. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/control-probe.md +25 -0
  192. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/control-server.md +22 -0
  193. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/credential-readiness.md +23 -0
  194. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/elected-leader.md +22 -0
  195. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/enrollment-key.md +22 -0
  196. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/file-receipt.md +25 -0
  197. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/fleet-execution.md +23 -0
  198. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/fleet-presence.md +23 -0
  199. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/interactive-ssh.md +22 -0
  200. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/local-enrollment.md +23 -0
  201. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/mesh-policy.md +23 -0
  202. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/network-atlas.md +25 -0
  203. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/node-roster.md +26 -0
  204. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/node-selection-proof.md +17 -0
  205. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/owner-observations.md +23 -0
  206. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/peer-path.md +23 -0
  207. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/pinned-leader.md +24 -0
  208. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/reachability-evidence-ladder.md +17 -0
  209. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/recorded-login.md +23 -0
  210. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/remote-execution.md +22 -0
  211. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/secret-grants.md +26 -0
  212. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/{card.js → home.js} +93 -22
  213. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/DESIGN.md +86 -0
  214. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/README.md +44 -9
  215. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/capability/BRICK.md +1 -1
  216. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/capability/index.mjs +18 -6
  217. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/cli.mjs +128 -24
  218. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/package-lock.json +7 -7
  219. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/package.json +3 -2
  220. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/plugin.json +188 -34
  221. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/skills/meta-harness/SKILL.md +17 -3
  222. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/adoption.mjs +2 -2
  223. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/alerts.mjs +3 -3
  224. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/cascade.mjs +92 -18
  225. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/chat.mjs +80 -0
  226. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/control.mjs +145 -0
  227. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/coordinator.mjs +42 -21
  228. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/dispatch-request.mjs +4 -2
  229. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/dispatch.mjs +33 -9
  230. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/documentation.mjs +55 -11
  231. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/executor.mjs +26 -4
  232. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/gate-adapters/hermes.mjs +29 -1
  233. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/gate-adapters/index.mjs +1 -1
  234. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/included-usage.mjs +1 -1
  235. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/jobs.mjs +84 -0
  236. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/learner.mjs +3 -12
  237. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/maintenance.mjs +17 -0
  238. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/mcp-server.mjs +228 -0
  239. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/process-manager.mjs +25 -2
  240. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/reasoning.mjs +1 -1
  241. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/remote-operation.mjs +5 -1
  242. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/review.mjs +34 -3
  243. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/reviews.mjs +25 -0
  244. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/router.mjs +1 -1
  245. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/session/claude.mjs +319 -0
  246. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/session/codex.mjs +387 -0
  247. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/session/result.mjs +67 -0
  248. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/session/resume.mjs +373 -0
  249. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/session/run.mjs +223 -0
  250. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/session-jobs.mjs +72 -0
  251. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/setup.mjs +6 -3
  252. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/termination.mjs +16 -12
  253. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/threads.mjs +32 -1
  254. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/usage-queue.mjs +1 -1
  255. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/verify-ssss.mjs +3 -3
  256. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/worker.mjs +285 -40
  257. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/worktree.mjs +76 -9
  258. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/adapter-docs-freshness.md +16 -0
  259. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/chat-handoff.md +26 -0
  260. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/fleet-maintenance.md +21 -0
  261. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/harness-inventory.md +21 -0
  262. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/included-access.md +18 -0
  263. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/included-usage-verification.md +15 -0
  264. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/independent-review.md +17 -0
  265. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/managed-execution.md +20 -0
  266. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/official-documentation.md +18 -0
  267. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/quota-recovery.md +21 -0
  268. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/review-routing-decision.md +16 -0
  269. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/route-work.md +18 -0
  270. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/routing-evidence.md +18 -0
  271. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/run-ledger.md +18 -0
  272. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/home.js +198 -0
  273. package/scaffold/.agent/skills/total-recall/plugins/openwiki/DESIGN.md +75 -0
  274. package/scaffold/.agent/skills/total-recall/plugins/openwiki/README.md +2 -0
  275. package/scaffold/.agent/skills/total-recall/plugins/openwiki/cli.mjs +64 -32
  276. package/scaffold/.agent/skills/total-recall/plugins/openwiki/package-lock.json +7 -7
  277. package/scaffold/.agent/skills/total-recall/plugins/openwiki/package.json +2 -1
  278. package/scaffold/.agent/skills/total-recall/plugins/openwiki/plugin.json +10 -44
  279. package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/generate.mjs +5 -4
  280. package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/graph.mjs +3 -4
  281. package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/ingest.mjs +23 -18
  282. package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/mesh-vaults.mjs +8 -3
  283. package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/refresh-diagnostics.mjs +44 -0
  284. package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/refresh.mjs +123 -113
  285. package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/search.mjs +3 -5
  286. package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/token.mjs +21 -47
  287. package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/upstream-watcher.mjs +17 -6
  288. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/auto-refresh.md +18 -0
  289. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/bootstrap-pages.md +18 -0
  290. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/generate-wiki.md +21 -0
  291. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/generator-settings.md +18 -0
  292. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/host-probe.md +18 -0
  293. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/ingest-preview.md +18 -0
  294. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/link-hygiene.md +21 -0
  295. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/link-topology.md +19 -0
  296. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/passage-search.md +19 -0
  297. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/propagation-plan.md +18 -0
  298. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/provider-credentials.md +18 -0
  299. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/refresh-report.md +18 -0
  300. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/task-evidence.md +22 -0
  301. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/upstream-record.md +18 -0
  302. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/watch-upstream.md +18 -0
  303. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/wiki-atlas.md +19 -0
  304. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/panel.js +261 -513
  305. package/scaffold/.agent/skills/total-recall/plugins/security/DESIGN.md +84 -0
  306. package/scaffold/.agent/skills/total-recall/plugins/security/README.md +4 -2
  307. package/scaffold/.agent/skills/total-recall/plugins/security/cli.mjs +7 -19
  308. package/scaffold/.agent/skills/total-recall/plugins/security/package-lock.json +7 -7
  309. package/scaffold/.agent/skills/total-recall/plugins/security/package.json +2 -3
  310. package/scaffold/.agent/skills/total-recall/plugins/security/plugin.json +19 -52
  311. package/scaffold/.agent/skills/total-recall/plugins/security/ui/chunks/device-evidence.md +21 -0
  312. package/scaffold/.agent/skills/total-recall/plugins/security/ui/chunks/evidence-desk.md +18 -0
  313. package/scaffold/.agent/skills/total-recall/plugins/security/ui/chunks/guided-device-review.md +17 -0
  314. package/scaffold/.agent/skills/total-recall/plugins/security/ui/chunks/host-and-network.md +21 -0
  315. package/scaffold/.agent/skills/total-recall/plugins/security/ui/chunks/https-headers.md +17 -0
  316. package/scaffold/.agent/skills/total-recall/plugins/security/ui/chunks/mesh-coverage.md +18 -0
  317. package/scaffold/.agent/skills/total-recall/plugins/security/ui/chunks/private-security-tools.md +16 -0
  318. package/scaffold/.agent/skills/total-recall/plugins/security/ui/chunks/single-origin-header-check.md +17 -0
  319. package/scaffold/.agent/skills/total-recall/plugins/security/ui/chunks/source-review.md +21 -0
  320. package/scaffold/.agent/skills/total-recall/plugins/security/ui/chunks/ssh-permission-plan.md +17 -0
  321. package/scaffold/.agent/skills/total-recall/plugins/security/ui/home.js +283 -0
  322. package/scaffold/.agent/skills/total-recall/plugins/ssss/DESIGN.md +93 -0
  323. package/scaffold/.agent/skills/total-recall/plugins/ssss/package-lock.json +2 -2
  324. package/scaffold/.agent/skills/total-recall/plugins/ssss/package.json +2 -1
  325. package/scaffold/.agent/skills/total-recall/plugins/ssss/plugin.json +5 -3
  326. package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/chunks/conformance.md +26 -0
  327. package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/chunks/registry.md +37 -0
  328. package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/chunks/repair.md +42 -0
  329. package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/chunks/scaffold.md +33 -0
  330. package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/chunks/status.md +43 -0
  331. package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/chunks/validate.md +34 -0
  332. package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/chunks/validation-diagnostics.md +17 -0
  333. package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/chunks/workspace-registry-preflight.md +17 -0
  334. package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/home.js +348 -0
  335. package/scaffold/.agent/skills/total-recall/references/operations.md +3 -1
  336. package/src/cli/agent.mjs +1 -1
  337. package/src/cli/api.mjs +3 -3
  338. package/src/cli/brief.mjs +3 -0
  339. package/src/cli/command.mjs +41 -2
  340. package/src/cli/config.mjs +16 -0
  341. package/src/cli/connect.mjs +2 -7
  342. package/src/cli/dream.mjs +93 -69
  343. package/src/cli/harness.mjs +4 -4
  344. package/src/cli/help.mjs +1 -1
  345. package/src/cli/init.mjs +0 -25
  346. package/src/cli/lessons.mjs +51 -0
  347. package/src/cli/memory-plugin.mjs +1 -1
  348. package/src/cli/plugin/chunks.mjs +145 -0
  349. package/src/cli/plugin/copies.mjs +64 -14
  350. package/src/cli/plugin/create.mjs +30 -59
  351. package/src/cli/plugin/index.mjs +31 -16
  352. package/src/cli/plugin/install.mjs +10 -15
  353. package/src/cli/plugin/remove.mjs +1 -1
  354. package/src/cli/plugin/search.mjs +2 -2
  355. package/src/cli/preflight.mjs +19 -6
  356. package/src/cli/proposals.mjs +1 -1
  357. package/src/cli/recall.mjs +66 -23
  358. package/src/cli/remember.mjs +3 -14
  359. package/src/cli/server.mjs +18 -0
  360. package/src/cli/setup.mjs +2 -9
  361. package/src/cli/start.mjs +1 -0
  362. package/src/cli/startup.mjs +19 -0
  363. package/src/cli/task.mjs +9 -2
  364. package/src/cli/update.mjs +6 -2
  365. package/src/core/access-ledger.mjs +78 -0
  366. package/src/core/agent-manager.mjs +2 -2
  367. package/src/core/app-deploy/design-tokens.mjs +14 -9
  368. package/src/core/app-deploy/ui-elements.mjs +1 -1
  369. package/src/core/brain-locate.mjs +15 -0
  370. package/src/core/brain-registry.mjs +5 -0
  371. package/src/core/brain-updates.mjs +35 -11
  372. package/src/core/claude-hooks.mjs +3 -1
  373. package/src/core/cleanup-task.mjs +15 -0
  374. package/src/core/cli-commands.mjs +2 -0
  375. package/src/core/cli-maintenance.mjs +4 -1
  376. package/src/core/cli-semantic-index.mjs +23 -3
  377. package/src/core/context-compiler.mjs +20 -0
  378. package/src/core/daemon-control.mjs +5 -1
  379. package/src/core/daemon-loop.mjs +39 -62
  380. package/src/core/dashboard-bundle.mjs +261 -0
  381. package/src/core/default-plugins.mjs +1 -1
  382. package/src/core/dream.mjs +33 -105
  383. package/src/core/ensure-dependencies.mjs +152 -0
  384. package/src/core/fast-recall.mjs +2 -2
  385. package/src/core/field-evaluation.mjs +23 -0
  386. package/src/core/gate-mode.mjs +1 -1
  387. package/src/core/harness-hooks.mjs +14 -2
  388. package/src/core/lesson-hooks.mjs +74 -0
  389. package/src/core/lesson-memory.mjs +24 -0
  390. package/src/core/lesson-sessions.mjs +52 -0
  391. package/src/core/lessons.mjs +96 -0
  392. package/src/core/memory-brain.mjs +30 -8
  393. package/src/core/meta-harness.mjs +2 -2
  394. package/src/core/optimizer.mjs +66 -165
  395. package/src/core/plugin-activation.mjs +63 -20
  396. package/src/core/plugin-contracts/{card.mjs → manifest.mjs} +26 -57
  397. package/src/core/plugin-contracts/startup-check.mjs +49 -0
  398. package/src/core/plugin-contracts/ui.mjs +9 -3
  399. package/src/core/plugin-distribution.mjs +6 -6
  400. package/src/core/plugin-lifecycle.mjs +58 -0
  401. package/src/core/plugin-loader.mjs +21 -8
  402. package/src/core/plugin-runner.mjs +21 -10
  403. package/src/core/plugin-runtime.mjs +40 -1
  404. package/src/core/plugin-startup-checks.mjs +44 -0
  405. package/src/core/plugin-state.mjs +19 -5
  406. package/src/core/plugin-store.mjs +64 -33
  407. package/src/core/post-mortem.mjs +52 -36
  408. package/src/core/preflight-gate.mjs +23 -2
  409. package/src/core/project-id.mjs +15 -5
  410. package/src/core/proposal-applier.mjs +31 -2
  411. package/src/core/repo-sync.mjs +4 -6
  412. package/src/core/required-plugins.mjs +57 -10
  413. package/src/core/rule-length.mjs +23 -0
  414. package/src/core/runtime.mjs +1 -1
  415. package/src/core/scheduler.mjs +35 -43
  416. package/src/core/schema.mjs +3 -2
  417. package/src/core/search.mjs +4 -3
  418. package/src/core/server-service.mjs +148 -0
  419. package/src/core/session-watcher.mjs +19 -1
  420. package/src/core/skill-gap.mjs +16 -0
  421. package/src/core/ssss-kernel-bridge.mjs +32 -4
  422. package/src/core/ssss-operation-service.mjs +1 -0
  423. package/src/core/startup-health.mjs +34 -4
  424. package/src/core/surface.mjs +65 -54
  425. package/src/core/task-executors.mjs +54 -106
  426. package/src/core/testing/plugin-fixture.mjs +22 -21
  427. package/src/core/throttled-fetch.mjs +25 -18
  428. package/src/core/ui-chunk-choice.mjs +77 -0
  429. package/src/core/ui-chunk.registry.json +23 -0
  430. package/src/core/ui-chunks.mjs +434 -0
  431. package/src/core/validated-write.mjs +1 -0
  432. package/src/core/vault-cache.mjs +58 -59
  433. package/src/core/vector-field.mjs +134 -192
  434. package/src/core/workspace-compositions.mjs +151 -0
  435. package/src/core/workspace-drawers.mjs +79 -0
  436. package/src/server/api.mjs +4 -27
  437. package/src/server/index.mjs +28 -21
  438. package/src/server/invoke-core-child.mjs +24 -0
  439. package/src/server/invoke-core-operations.mjs +102 -0
  440. package/src/server/memory-events.mjs +31 -0
  441. package/src/server/plugin-brain-targets.mjs +89 -0
  442. package/src/server/rest.mjs +2 -0
  443. package/src/server/route-inventory.mjs +3 -2
  444. package/src/server/route-manifest.json +47 -55
  445. package/src/server/routes/_shared.mjs +7 -14
  446. package/src/server/routes/brains.mjs +29 -62
  447. package/src/server/routes/context.mjs +0 -41
  448. package/src/server/routes/dashboard.mjs +26 -0
  449. package/src/server/routes/invoke.mjs +26 -1
  450. package/src/server/routes/plugins.mjs +154 -45
  451. package/src/server/routes/ssss.mjs +0 -169
  452. package/src/server/routes/system.mjs +0 -15
  453. package/src/server/routes/tasks.mjs +0 -26
  454. package/src/server/routes/ui-chunks.mjs +192 -0
  455. package/src/server/routes/vault.mjs +2 -23
  456. package/frontend/dist/assets/index-DD4qONvH.js +0 -5607
  457. package/frontend/dist/assets/index-DtwsDyFM.css +0 -1
  458. package/frontend/src/components/plugins/card/CardEngine.tsx +0 -108
  459. package/frontend/src/components/plugins/card/CardScenes.tsx +0 -103
  460. package/frontend/src/components/plugins/card/ExecutionPicker.tsx +0 -64
  461. package/frontend/src/components/plugins/card/args.ts +0 -28
  462. package/frontend/src/components/plugins/card/card.css +0 -32
  463. package/frontend/src/components/plugins/card/cli-line.ts +0 -13
  464. package/frontend/src/components/plugins/card/contract.ts +0 -91
  465. package/frontend/src/components/plugins/card/format.ts +0 -49
  466. package/frontend/src/components/plugins/card/runner-context.ts +0 -11
  467. package/frontend/src/components/plugins/card/runner.tsx +0 -43
  468. package/frontend/src/components/plugins/card/theme.ts +0 -35
  469. package/frontend/src/components/plugins/card/use-source.ts +0 -22
  470. package/frontend/src/components/plugins/card/widgets.tsx +0 -94
  471. package/frontend/src/components/plugins/workspace/WorkspaceHost.tsx +0 -23
  472. package/frontend/src/pages/PluginsPage.tsx +0 -1719
  473. package/scaffold/.agent/skills/plugin/evals/cases/04-card-collects-credential.mjs +0 -47
  474. package/scaffold/.agent/skills/plugin/prompts/06-card.md +0 -46
  475. package/scaffold/.agent/skills/plugin/references/card.md +0 -90
  476. package/scaffold/.agent/skills/plugin/subagents/card-designer.md +0 -60
  477. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/DESIGN.md +0 -67
  478. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/card.js +0 -1179
  479. package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/DESIGN.md +0 -32
  480. package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/card.js +0 -588
  481. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/card.js +0 -575
  482. package/scaffold/.agent/skills/total-recall/plugins/embeddings/ui/DESIGN.md +0 -32
  483. package/scaffold/.agent/skills/total-recall/plugins/embeddings/ui/card.js +0 -482
  484. package/scaffold/.agent/skills/total-recall/plugins/git-sentinel/README.md +0 -53
  485. package/scaffold/.agent/skills/total-recall/plugins/git-sentinel/plugin.json +0 -129
  486. package/scaffold/.agent/skills/total-recall/plugins/git-sentinel/ui/DESIGN.md +0 -100
  487. package/scaffold/.agent/skills/total-recall/plugins/git-sentinel/ui/card.js +0 -637
  488. package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/DESIGN.md +0 -217
  489. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/DESIGN.md +0 -32
  490. package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/card.js +0 -1276
  491. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/DESIGN.md +0 -45
  492. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/card.js +0 -1401
  493. package/scaffold/.agent/skills/total-recall/plugins/security/scripts/build-ui.mjs +0 -4
  494. package/scaffold/.agent/skills/total-recall/plugins/security/ui/DESIGN.md +0 -41
  495. package/scaffold/.agent/skills/total-recall/plugins/security/ui/card.js +0 -396
  496. package/scaffold/.agent/skills/total-recall/plugins/security/ui/panel.js +0 -98
  497. package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/DESIGN.md +0 -15
  498. package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/card.js +0 -182
  499. package/src/core/append-log.mjs +0 -131
  500. package/src/core/plugin-tasks.mjs +0 -173
  501. package/templates/onboarding-interview.md +0 -82
  502. /package/scaffold/.agent/skills/total-recall/plugins/{git-sentinel → git}/LICENSE +0 -0
@@ -17,8 +17,8 @@
17
17
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
18
18
  <link href="https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:opsz,wght@12..96,600;12..96,800&family=Cabinet+Grotesk:wght@700;800&family=Chivo+Mono:wght@500;700&family=Cinzel:wght@600;700;900&family=Cormorant+Garamond:ital,wght@0,600;0,700;1,600;1,700&family=DM+Mono:wght@500&family=DM+Sans:wght@500;700&family=Fraunces:opsz,wght@9..144,600;9..144,800&family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500;700&family=Lexend:wght@600;800&family=Newsreader:ital,opsz,wght@0,6..72,600;1,6..72,600&family=Orbitron:wght@700;900&family=Outfit:wght@500;700;800&family=Plus+Jakarta+Sans:wght@600;700;800&family=Space+Grotesk:wght@600;700&family=Syne:wght@700;800&display=swap" rel="stylesheet" />
19
19
  <title>Total Recall — Portable Memory</title>
20
- <script type="module" crossorigin src="/assets/index-DD4qONvH.js"></script>
21
- <link rel="stylesheet" crossorigin href="/assets/index-DtwsDyFM.css">
20
+ <script type="module" crossorigin src="/assets/index-D1goIPjC.js"></script>
21
+ <link rel="stylesheet" crossorigin href="/assets/index-BRYE1jmv.css">
22
22
  </head>
23
23
  <body>
24
24
  <div id="root"></div>
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Caching strategies:
5
5
  * • App shell: Pre-cached on install
6
- * • /api/* GETs: Stale-While-Revalidate
6
+ * • /api/* GETs: Stale-While-Revalidate except live brain, plugin and chunk reads
7
7
  * • /api/memory writes (POST/PUT/PATCH/DELETE): Network-first + offline queue with Background Sync
8
8
  * • Static assets: Cache-first
9
9
  * • Everything else: Network-first
@@ -15,7 +15,7 @@
15
15
  */
16
16
 
17
17
  const CACHE_NAME = 'total-recall-v1';
18
- const API_CACHE = 'total-recall-api-v1';
18
+ const API_CACHE = 'total-recall-api-v3';
19
19
 
20
20
  // Pre-cache app shell
21
21
  const PRECACHE_URLS = [
@@ -59,8 +59,9 @@ self.addEventListener('fetch', (event) => {
59
59
  return;
60
60
  }
61
61
 
62
- // Live streaming / LLM / v1 endpoints should bypass the cache completely
63
- if (url.pathname.startsWith('/v1/')) {
62
+ // Registry, owner modules and composed views use the current authenticated state.
63
+ if (event.request.cache === 'no-store' || url.pathname.startsWith('/v1/') ||
64
+ /^\/api\/(?:brains|plugins|ui-chunks)(?:\/|$)/.test(url.pathname)) {
64
65
  return;
65
66
  }
66
67
 
@@ -1,5 +1,5 @@
1
- import { useState, useEffect } from 'react'
2
- import { BrowserRouter, Routes, Route, NavLink, Navigate, useLocation } from 'react-router-dom'
1
+ import { useState, useEffect, useRef, useCallback, type ReactNode } from 'react'
2
+ import { BrowserRouter, Routes, Route, NavLink, Navigate, useLocation, useSearchParams } from 'react-router-dom'
3
3
  import './App.css'
4
4
  import { getApiBase, setApiBase, checkSession, logout, registerUnauthedCallback, fetchHealth } from './api'
5
5
  import type { HealthData } from './types'
@@ -10,14 +10,14 @@ import NetworkPage from './pages/NetworkPage'
10
10
  import { WebhooksPage } from './pages/WebhooksPage'
11
11
  import BrainSelector from './components/BrainSelector'
12
12
  import RulesPage from './pages/RulesPage'
13
- import HelpPage from './pages/HelpPage'
14
13
  import GraphPage from './pages/GraphPage'
15
- import PluginsPage from './pages/PluginsPage'
14
+ import PluginWorkspace from './components/plugins/PluginWorkspace'
16
15
  import OnboardingPage from './pages/OnboardingPage'
17
16
  import { NotificationsPage } from './pages/NotificationsPage'
18
17
  import { isOnboardingComplete } from './utils/onboarding'
19
18
  import BrandMark from './components/brand/BrandMark'
20
- import ContextualHelp from './components/ContextualHelp'
19
+ import { WorkspaceDrawers, type WorkspaceEdge } from './components/workspace/WorkspaceDrawers'
20
+ import { SavedPages, WorkspacePage } from './components/workspace/WorkspacePage'
21
21
 
22
22
  // ─── Auth state type ──────────────────────────────────────────────────────────
23
23
  type AuthState = 'loading' | 'authed' | 'unauthed'
@@ -71,232 +71,92 @@ function networkGateTone(gate: HealthData['fetch_gate'] | undefined): {
71
71
  }
72
72
 
73
73
  interface SidebarProps {
74
- onLogout: () => void
75
- health: HealthData | null
76
74
  activeBrainId: string
77
75
  onBrainChange: (id: string) => void
76
+ open: boolean
77
+ onClose: () => void
78
+ onActivity: () => void
79
+ pluginFolder: ReactNode
80
+ savedPagesFolder: ReactNode
78
81
  }
79
82
 
80
- const getNavLinkClass = ({ isActive }: { isActive: boolean }) => `nav-link ${isActive ? 'active' : ''}`;
83
+ const getNavLinkClass = ({ isActive }: { isActive: boolean }) => `nav-link ${isActive ? 'active' : ''}`
81
84
 
82
- function Sidebar({ onLogout, health, activeBrainId, onBrainChange }: SidebarProps) {
85
+ function Sidebar({ activeBrainId, onBrainChange, open, onClose, onActivity, pluginFolder, savedPagesFolder }: SidebarProps) {
83
86
  return (
84
- <aside className="sidebar">
85
- <div className="sidebar-brand" style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '16px 14px' }}>
86
- <BrandMark animated height={44} alt="Total Recall" />
87
- <div style={{ display: 'flex', flexDirection: 'column' }}>
88
- <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
89
- <span style={{ fontSize: 15, fontWeight: 700, letterSpacing: '-0.02em', color: '#f8fafc' }}>Total Recall</span>
90
- <span style={{ fontSize: 10, fontWeight: 600, padding: '2px 5px', borderRadius: 4, background: 'rgba(59,130,246,0.15)', color: '#60a5fa', border: '1px solid rgba(59,130,246,0.3)' }}>{health?.version ? `v${health.version}` : 'Version unknown'}</span>
91
- </div>
92
- <span style={{ fontSize: 11, color: 'var(--text-tertiary)', letterSpacing: '0.01em' }}>Portable memory · any IDE</span>
93
- </div>
87
+ <aside className={`sidebar ${open ? 'open' : ''}`} id="workspace-sidebar" inert={!open}
88
+ onPointerMove={onActivity} onPointerDown={onActivity} onFocus={onActivity} onKeyDown={event => {
89
+ if (event.key === 'Escape') onClose()
90
+ else onActivity()
91
+ }}>
92
+ <div className="sidebar-brains">
93
+ <div className="nav-section-label">Brains</div>
94
+ <BrainSelector activeBrainId={activeBrainId} onBrainChange={onBrainChange} onSelectionComplete={onClose} />
94
95
  </div>
95
- <nav className="sidebar-nav">
96
- <div className="nav-section-label">Memory</div>
97
- {!isOnboardingComplete() && (
98
- <NavLink to="/onboarding" className={getNavLinkClass} id="nav-onboarding">
99
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
100
- <path d="M12 2L2 7l10 5 10-5-10-5z" /><path d="M2 17l10 5 10-5" /><path d="M2 12l10 5 10-5" />
101
- </svg>
102
- Setup
103
- </NavLink>
104
- )}
105
- <NavLink to="/memory" className={getNavLinkClass} id="nav-memory">
106
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
107
- <circle cx="12" cy="12" r="10" /><path d="M12 16v-4M12 8h.01" />
108
- </svg>
109
- Vault
110
- </NavLink>
111
- <NavLink to="/rules" className={getNavLinkClass} id="nav-rules">
112
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
113
- <path d="M14 2H6a2 2 0 0 0-2 2v16c0 1.1.9 2 2 2h12a2 2 0 0 0 2-2V8l-6-6z" />
114
- <path d="M14 3v5h5M16 13H8M16 17H8M10 9H8" />
115
- </svg>
116
- Rules
117
- </NavLink>
118
- <NavLink to="/graph" className={getNavLinkClass} id="nav-graph">
119
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
120
- <circle cx="5" cy="6" r="2" /><circle cx="19" cy="6" r="2" /><circle cx="12" cy="18" r="2" />
121
- <path d="M7 7l4 9M17 7l-4 9" />
122
- </svg>
123
- Graph
124
- </NavLink>
125
-
126
- <div className="nav-section-label">Capabilities</div>
127
- <NavLink to="/plugins" className={getNavLinkClass} id="nav-plugins">
128
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
129
- <path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z" />
130
- <polyline points="3.27 6.96 12 12.01 20.73 6.96" />
131
- <line x1="12" y1="22.08" x2="12" y2="12" />
132
- </svg>
133
- Plugins
134
- </NavLink>
135
-
136
- <div className="nav-section-label">Account</div>
137
- <NavLink to="/network" className={getNavLinkClass} id="nav-network">
138
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
139
- <rect x="2" y="2" width="20" height="8" rx="2" ry="2" />
140
- <rect x="2" y="14" width="20" height="8" rx="2" ry="2" />
141
- <line x1="6" y1="6" x2="6.01" y2="6" />
142
- <line x1="6" y1="18" x2="6.01" y2="18" />
143
- </svg>
144
- Network
145
- </NavLink>
146
- <NavLink to="/mesh" className={getNavLinkClass} id="nav-mesh">
147
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
148
- <path d="M12 2L2 7l10 5 10-5-10-5z" /><path d="M2 17l10 5 10-5" /><path d="M2 12l10 5 10-5" />
149
- </svg>
150
- Mesh
151
- </NavLink>
152
- <NavLink to="/webhooks" className={getNavLinkClass} id="nav-webhooks">
153
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
154
- <path d="M22 12h-4l-3 9L9 3l-3 9H2" />
155
- </svg>
156
- Webhooks
157
- </NavLink>
158
- <NavLink to="/secrets" className={getNavLinkClass} id="nav-secrets">
159
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
160
- <rect x="3" y="11" width="18" height="11" rx="2" ry="2" /><path d="M7 11V7a5 5 0 0110 0v4" />
161
- </svg>
162
- Secrets & Keys
163
- </NavLink>
164
- <NavLink to="/notifications" className={getNavLinkClass} id="nav-notifications">
165
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
166
- <path d="M18 8A6 6 0 006 8c0 7-3 9-3 9h18s-3-2-3-9" /><path d="M13.73 21a2 2 0 01-3.46 0" />
167
- </svg>
168
- Notifications
169
- </NavLink>
170
- <NavLink to="/settings" className={getNavLinkClass} id="nav-settings">
171
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
172
- <circle cx="12" cy="12" r="3" /><path d="M19.4 15a1.65 1.65 0 00.33 1.82l.06.06a2 2 0 010 2.83 2 2 0 01-2.83 0l-.06-.06a1.65 1.65 0 00-1.82-.33 1.65 1.65 0 00-1 1.51V21a2 2 0 01-4 0v-.09A1.65 1.65 0 009 19.4a1.65 1.65 0 00-1.82.33l-.06.06a2 2 0 01-2.83-2.83l.06-.06A1.65 1.65 0 004.68 15a1.65 1.65 0 00-1.51-1H3a2 2 0 010-4h.09A1.65 1.65 0 004.6 9a1.65 1.65 0 00-.33-1.82l-.06-.06a2 2 0 012.83-2.83l.06.06A1.65 1.65 0 009 4.68a1.65 1.65 0 001-1.51V3a2 2 0 014 0v.09a1.65 1.65 0 001 1.51 1.65 1.65 0 001.82-.33l.06-.06a2 2 0 012.83 2.83l-.06.06A1.65 1.65 0 0019.4 9a1.65 1.65 0 001.51 1H21a2 2 0 010 4h-.09a1.65 1.65 0 00-1.51 1z" />
173
- </svg>
174
- Settings
175
- </NavLink>
176
- <NavLink to="/help" className={getNavLinkClass} id="nav-help">
177
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
178
- <circle cx="12" cy="12" r="10" />
179
- <path d="M9.09 9a3 3 0 015.83 1c0 2-3 3-3 3" />
180
- <line x1="12" y1="17" x2="12.01" y2="17" />
181
- </svg>
182
- Help
183
- </NavLink>
184
- {isOnboardingComplete() && (
185
- <NavLink to="/onboarding" className={getNavLinkClass} id="nav-onboarding-replay" style={{ opacity: 0.75 }}>
186
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
187
- <path d="M12 2L2 7l10 5 10-5-10-5z" /><path d="M2 17l10 5 10-5" /><path d="M2 12l10 5 10-5" />
188
- </svg>
189
- Setup guide
190
- </NavLink>
191
- )}
96
+ <nav className="sidebar-nav" aria-label="Workspace">
97
+ {pluginFolder}
98
+ {savedPagesFolder}
99
+ <details className="sidebar-memory">
100
+ <summary className="nav-link">Memory</summary>
101
+ {!isOnboardingComplete() && <NavLink to="/onboarding" className={getNavLinkClass} id="nav-onboarding" onClick={onClose}>Setup</NavLink>}
102
+ <NavLink to="/memory" className={getNavLinkClass} id="nav-memory" onClick={onClose}>Vault</NavLink>
103
+ <NavLink to="/rules" className={getNavLinkClass} id="nav-rules" onClick={onClose}>Rules</NavLink>
104
+ <NavLink to="/graph" className={getNavLinkClass} id="nav-graph" onClick={onClose}>Graph</NavLink>
105
+ </details>
192
106
  </nav>
193
- <div className="sidebar-footer" style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
194
- <BrainSelector activeBrainId={activeBrainId} onBrainChange={onBrainChange} />
195
- <select
196
- value={getApiBase()}
197
- onChange={e => setApiBase(e.target.value)}
198
- title="API host"
199
- style={{
200
- width: '100%',
201
- background: 'rgba(148, 163, 184, 0.08)',
202
- color: 'var(--text-secondary)',
203
- border: '1px solid rgba(148, 163, 184, 0.18)',
204
- borderRadius: 8,
205
- padding: '6px 10px',
206
- fontSize: 11,
207
- fontWeight: 500,
208
- outline: 'none',
209
- cursor: 'pointer',
210
- transition: 'border-color var(--transition-fast)',
211
- }}
212
- >
107
+ </aside>
108
+ )
109
+ }
110
+
111
+ const ACCOUNT_LINKS = [
112
+ ['network', 'Network'],
113
+ ['mesh', 'Mesh'],
114
+ ['webhooks', 'Webhooks'],
115
+ ['secrets', 'Secrets & Keys'],
116
+ ['notifications', 'Notifications'],
117
+ ['settings', 'Settings'],
118
+ ] as const
119
+
120
+ function AccountMenu({ health, onLogout }: { health: HealthData | null; onLogout: () => void }) {
121
+ const menu = useRef<HTMLDetailsElement>(null)
122
+ const trigger = useRef<HTMLElement>(null)
123
+ const gate = networkGateTone(health?.fetch_gate)
124
+ const serverOk = health?.status !== 'unreachable'
125
+ const daemonOk = health?.daemon === 'running'
126
+
127
+ function close() {
128
+ if (menu.current) menu.current.open = false
129
+ }
130
+
131
+ return <details className="account-menu" ref={menu} onKeyDown={event => {
132
+ if (event.key === 'Escape') { close(); trigger.current?.focus() }
133
+ }}>
134
+ <summary className="btn btn-ghost btn-sm" ref={trigger}>Account</summary>
135
+ <nav className="account-menu-body" aria-label="Account">
136
+ {ACCOUNT_LINKS.map(([path, label]) => <NavLink key={path} to={`/${path}`} className={getNavLinkClass}
137
+ id={`nav-${path}`} onClick={close}>{label}</NavLink>)}
138
+ <NavLink to="/onboarding" className={getNavLinkClass} id="nav-onboarding-replay" onClick={close}>Setup guide</NavLink>
139
+ <label className="account-menu-host">API host
140
+ <select className="select" value={getApiBase()} onChange={event => setApiBase(event.target.value)}>
213
141
  <option value="">Local API</option>
214
- {import.meta.env.VITE_BRAIN_URL && (
215
- <option value={import.meta.env.VITE_BRAIN_URL}>{new URL(import.meta.env.VITE_BRAIN_URL).host}</option>
216
- )}
142
+ {import.meta.env.VITE_BRAIN_URL && <option value={import.meta.env.VITE_BRAIN_URL}>
143
+ {new URL(import.meta.env.VITE_BRAIN_URL).host}
144
+ </option>}
217
145
  </select>
218
- <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
219
- <div style={{ display: 'flex', flexDirection: 'column', gap: 4, fontSize: 11 }}>
220
- {(() => {
221
- const daemonOk = health?.daemon === 'running'
222
- const serverOk = health && health.status !== 'unreachable'
223
- const allGood = daemonOk && serverOk
224
- const gate = networkGateTone(health?.fetch_gate)
225
-
226
- if (!health) return <div style={{ color: 'var(--text-tertiary)' }}>Checking…</div>
227
-
228
- return (
229
- <>
230
- <style>{`@keyframes blink { 0%,100%{opacity:1;} 50%{opacity:0.3;} }`}</style>
231
- {allGood ? (
232
- <div style={{ display: 'flex', alignItems: 'center', gap: 5, color: 'var(--text-tertiary)' }}>
233
- <span className="pulse" /> All Systems Go
234
- </div>
235
- ) : (
236
- <>
237
- <StatusDot ok={!!serverOk} label={serverOk ? 'Server online' : 'Server offline'} />
238
- <StatusDot ok={daemonOk} label={daemonOk ? 'Daemon' : 'Daemon ' + (health?.daemon ?? 'unknown')} />
239
- </>
240
- )}
241
- <div
242
- data-testid="network-gate-indicator"
243
- title={gate.title}
244
- style={{ display: 'flex', alignItems: 'center', gap: 5, color: 'var(--text-tertiary)' }}
245
- >
246
- <span
247
- style={{
248
- width: 7,
249
- height: 7,
250
- borderRadius: '50%',
251
- background: gate.color,
252
- boxShadow: `0 0 6px ${gate.color}80`,
253
- display: 'inline-block',
254
- }}
255
- />
256
- <NavLink
257
- to="/network"
258
- style={{ color: 'inherit', textDecoration: 'none', fontSize: 11 }}
259
- title={gate.title}
260
- >
261
- {gate.label}
262
- </NavLink>
263
- </div>
264
- </>
265
- )
266
- })()}
267
- </div>
268
- {/* Logout button */}
269
- <button
270
- id="btn-logout"
271
- onClick={onLogout}
272
- title="Sign out"
273
- style={{
274
- background: 'none',
275
- border: '1px solid var(--border)',
276
- borderRadius: 6,
277
- cursor: 'pointer',
278
- color: 'var(--text-tertiary)',
279
- display: 'flex',
280
- alignItems: 'center',
281
- gap: 5,
282
- padding: '4px 8px',
283
- fontSize: 11,
284
- transition: 'color 0.15s, border-color 0.15s',
285
- }}
286
- onMouseEnter={e => { (e.currentTarget as HTMLElement).style.color = '#ef4444'; (e.currentTarget as HTMLElement).style.borderColor = '#ef4444' }}
287
- onMouseLeave={e => { (e.currentTarget as HTMLElement).style.color = 'var(--text-tertiary)'; (e.currentTarget as HTMLElement).style.borderColor = 'var(--border)' }}
288
- >
289
- <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
290
- <path d="M9 21H5a2 2 0 01-2-2V5a2 2 0 012-2h4"/>
291
- <polyline points="16 17 21 12 16 7"/>
292
- <line x1="21" y1="12" x2="9" y2="12"/>
293
- </svg>
294
- Sign out
295
- </button>
296
- </div>
146
+ </label>
147
+ <div className="account-menu-health">
148
+ {health ? <>
149
+ {health.version && <span>v{health.version}</span>}
150
+ <StatusDot ok={serverOk} label={serverOk ? 'Server online' : 'Server offline'} />
151
+ <StatusDot ok={daemonOk} label={daemonOk ? 'Daemon running' : `Daemon ${health.daemon ?? 'unknown'}`} />
152
+ <NavLink to="/network" title={gate.title} data-testid="network-gate-indicator" onClick={close}>
153
+ <span aria-hidden="true" style={{ color: gate.color }}>● </span>{gate.label}
154
+ </NavLink>
155
+ </> : <span>Checking status…</span>}
297
156
  </div>
298
- </aside>
299
- )
157
+ <button type="button" className="btn btn-ghost btn-sm" id="btn-logout" onClick={onLogout}>Sign out</button>
158
+ </nav>
159
+ </details>
300
160
  }
301
161
 
302
162
  // ─── Main content (routes) ────────────────────────────────────────────────────
@@ -304,13 +164,20 @@ function Sidebar({ onLogout, health, activeBrainId, onBrainChange }: SidebarProp
304
164
  function OnboardingRedirect() {
305
165
  const location = useLocation()
306
166
  // First visit: force guided onboarding until complete (local flag or vault profile)
307
- if (!isOnboardingComplete() && location.pathname !== '/onboarding') {
167
+ if (!isOnboardingComplete() && !['/onboarding', '/plugins', '/help'].includes(location.pathname)) {
308
168
  return <Navigate to="/onboarding" replace />
309
169
  }
310
170
 
311
171
  return null
312
172
  }
313
173
 
174
+ function LegacyPluginsRoute() {
175
+ const [params] = useSearchParams()
176
+ const id = params.get('id') || params.get('plugin')
177
+ const selection = new URLSearchParams(id ? { plugin: id } : { plugins: 'open' })
178
+ return <Navigate to={{ pathname: isOnboardingComplete() ? '/memory' : '/onboarding', search: `?${selection}` }} replace />
179
+ }
180
+
314
181
  function MainContent({ activeBrainId }: { activeBrainId: string }) {
315
182
  return (
316
183
  <main className="main-content" style={{ display: 'flex', flexDirection: 'column', height: '100%', overflow: 'hidden', position: 'relative' }}>
@@ -323,23 +190,23 @@ function MainContent({ activeBrainId }: { activeBrainId: string }) {
323
190
  <Route path="/memory" element={<MemoryPage activeBrainId={activeBrainId} />} />
324
191
  <Route path="/rules" element={<RulesPage activeBrainId={activeBrainId} />} />
325
192
  <Route path="/graph" element={<GraphPage activeBrainId={activeBrainId} />} />
326
- <Route path="/tasks" element={<Navigate to="/plugins?id=user-automations" replace />} />
193
+ <Route path="/tasks" element={<Navigate to="/plugins?id=automations" replace />} />
327
194
  <Route path="/skills" element={<Navigate to="/plugins?id=skill-manager" replace />} />
328
195
  <Route path="/openwiki" element={<Navigate to="/plugins?id=openwiki" replace />} />
329
- <Route path="/plugins" element={<PluginsPage activeBrainId={activeBrainId} />} />
196
+ <Route path="/plugins" element={<LegacyPluginsRoute />} />
330
197
  <Route path="/integrations" element={<Navigate to="/plugins?id=meta-harness" replace />} />
331
198
  <Route path="/keys" element={<Navigate to="/secrets" replace />} />
332
199
  <Route path="/settings" element={<SettingsPage activeBrainId={activeBrainId} />} />
333
200
  <Route path="/network" element={<NetworkPage />} />
334
201
  <Route path="/mesh" element={<Navigate to="/plugins?id=mesh" replace />} />
335
202
  <Route path="/webhooks" element={<WebhooksPage />} />
336
- <Route path="/secrets" element={<Navigate to="/plugins?id=auth" replace />} />
203
+ <Route path="/secrets" element={<Navigate to="/memory?brain=global&plugin=auth" replace />} />
337
204
  <Route path="/notifications" element={<NotificationsPage />} />
338
- <Route path="/help" element={<HelpPage />} />
205
+ <Route path="/help" element={<Navigate to={isOnboardingComplete() ? '/memory?drawer=help' : '/onboarding?drawer=help'} replace />} />
339
206
  {/* Legacy OS-control-plane routes → core product */}
340
207
  <Route path="/vault" element={<Navigate to="/memory" replace />} />
341
208
  <Route path="/inbox" element={<Navigate to="/tasks" replace />} />
342
- <Route path="/automations" element={<Navigate to="/plugins?id=user-automations" replace />} />
209
+ <Route path="/automations" element={<Navigate to="/plugins?id=automations" replace />} />
343
210
  <Route path="/files" element={<Navigate to="/memory" replace />} />
344
211
  <Route path="/sandbox" element={<Navigate to="/memory" replace />} />
345
212
  <Route path="/models" element={<Navigate to="/settings" replace />} />
@@ -360,18 +227,51 @@ function MainContent({ activeBrainId }: { activeBrainId: string }) {
360
227
  // ─── Root App with auth gate ──────────────────────────────────────────────────
361
228
 
362
229
  const BRAIN_STORAGE_KEY = 'total-recall-active-brain'
230
+ const SIDEBAR_IDLE_MS = 5000
363
231
 
364
- function App() {
232
+ function Dashboard() {
233
+ const location = useLocation()
234
+ const [params, setParams] = useSearchParams()
235
+ const requestedEdge = new URLSearchParams(location.search).get('drawer') === 'help' ? 'right' : null
236
+ const [drawerEntry, setDrawerEntry] = useState<{ key: string; edge: WorkspaceEdge | null }>(
237
+ () => ({ key: location.key, edge: requestedEdge })
238
+ )
239
+ if (drawerEntry.key !== location.key) setDrawerEntry({ key: location.key, edge: requestedEdge })
240
+ const edge = drawerEntry.key === location.key ? drawerEntry.edge : requestedEdge
241
+ const setEdge = useCallback((edge: WorkspaceEdge | null) => {
242
+ setDrawerEntry({ key: location.key, edge })
243
+ }, [location.key])
365
244
  const [authState, setAuthState] = useState<AuthState>('loading')
366
245
  const [health, setHealth] = useState<HealthData | null>(null)
367
- const [activeBrainId, setActiveBrainId] = useState(
246
+ const sidebarOpen = edge === 'left'
247
+ const sidebarToggle = useRef<HTMLButtonElement>(null)
248
+ const sidebarTimer = useRef<number | undefined>(undefined)
249
+ const [storedBrainId, setStoredBrainId] = useState(
368
250
  () => localStorage.getItem(BRAIN_STORAGE_KEY) || 'global'
369
251
  )
252
+ const pageId = location.pathname === '/memory' ? params.get('page') : null
253
+ const linkedBrainId = (pageId || params.has('plugin')) ? params.get('brain') : null
254
+ const activeBrainId = linkedBrainId || storedBrainId
255
+ const pageBrainId = activeBrainId.includes(',') ? undefined : activeBrainId
256
+ function setActiveBrainId(id: string) {
257
+ setStoredBrainId(id)
258
+ if (pageId && id !== activeBrainId) {
259
+ const next = new URLSearchParams(params)
260
+ next.delete('page')
261
+ next.delete('brain')
262
+ next.delete('plugin')
263
+ setParams(next, { replace: true })
264
+ } else if (!pageId && linkedBrainId) {
265
+ const next = new URLSearchParams(params)
266
+ next.delete('brain')
267
+ setParams(next, { replace: true })
268
+ }
269
+ }
370
270
 
371
271
  // Persist activeBrainId to localStorage on change
372
272
  useEffect(() => {
373
- localStorage.setItem(BRAIN_STORAGE_KEY, activeBrainId)
374
- }, [activeBrainId])
273
+ localStorage.setItem(BRAIN_STORAGE_KEY, storedBrainId)
274
+ }, [storedBrainId])
375
275
 
376
276
  // Register 401 interceptor so any API call that gets a 401 flips us to unauthed
377
277
  useEffect(() => {
@@ -402,6 +302,7 @@ function App() {
402
302
 
403
303
  async function handleLogout() {
404
304
  await logout()
305
+ setEdge(null)
405
306
  setAuthState('unauthed')
406
307
  }
407
308
 
@@ -409,6 +310,27 @@ function App() {
409
310
  setAuthState('authed')
410
311
  }
411
312
 
313
+ const closeSidebar = useCallback(() => {
314
+ setEdge(null)
315
+ if (document.activeElement?.closest('#workspace-sidebar')) sidebarToggle.current?.focus()
316
+ }, [setEdge])
317
+
318
+ const closeDrawer = useCallback(() => {
319
+ if (edge === 'left') closeSidebar()
320
+ else setEdge(null)
321
+ }, [edge, closeSidebar, setEdge])
322
+
323
+ const queueSidebarClose = useCallback(() => {
324
+ window.clearTimeout(sidebarTimer.current)
325
+ sidebarTimer.current = window.setTimeout(closeSidebar, SIDEBAR_IDLE_MS)
326
+ }, [closeSidebar])
327
+
328
+ useEffect(() => {
329
+ if (!sidebarOpen) return
330
+ queueSidebarClose()
331
+ return () => window.clearTimeout(sidebarTimer.current)
332
+ }, [sidebarOpen, queueSidebarClose])
333
+
412
334
  // Loading state — blank dark screen, no flash of unprotected content
413
335
  if (authState === 'loading') {
414
336
  return (
@@ -434,14 +356,39 @@ function App() {
434
356
 
435
357
  // Authed — render full dashboard
436
358
  return (
437
- <BrowserRouter>
438
- <div className="app-layout">
439
- <Sidebar onLogout={handleLogout} health={health} activeBrainId={activeBrainId} onBrainChange={setActiveBrainId} />
440
- <MainContent activeBrainId={activeBrainId} />
441
- </div>
442
- <ContextualHelp />
443
- </BrowserRouter>
359
+ <PluginWorkspace activeBrainId={activeBrainId} onOpenPlugin={closeSidebar}
360
+ renderShell={(pluginFolder, pluginPage, plugins) => {
361
+ const page = pageId ? <WorkspacePage id={pageId} brainId={pageBrainId} plugins={plugins} /> : pluginPage
362
+ return <div className="app-layout">
363
+ <Sidebar activeBrainId={activeBrainId} onBrainChange={setActiveBrainId}
364
+ open={sidebarOpen} onClose={closeSidebar} onActivity={queueSidebarClose} pluginFolder={pluginFolder}
365
+ savedPagesFolder={<SavedPages brainId={pageBrainId} drawerOpen={sidebarOpen}
366
+ activePageId={pageId} onOpenPage={closeSidebar} />} />
367
+ {edge && <div className="sidebar-scrim" aria-hidden="true" onClick={closeDrawer} />}
368
+ <button type="button" className="sidebar-handle" ref={sidebarToggle} aria-label="Workspace navigation"
369
+ aria-controls="workspace-sidebar" aria-expanded={sidebarOpen} onClick={() => setEdge(sidebarOpen ? null : 'left')}
370
+ onKeyDown={event => { if (event.key === 'Escape' && sidebarOpen) closeSidebar() }}>
371
+ <svg width="14" height="18" viewBox="0 0 14 18" fill="none" stroke="currentColor" strokeWidth="1.5" aria-hidden="true">
372
+ <path d={sidebarOpen ? 'M9 4 4 9l5 5' : 'm5 4 5 5-5 5'} />
373
+ </svg>
374
+ </button>
375
+ <div className="workspace-main" inert={edge !== null}>
376
+ <header className="workspace-toolbar" aria-label="Dashboard">
377
+ <BrandMark height={64} className="workspace-logo" />
378
+ <AccountMenu health={health} onLogout={handleLogout} />
379
+ </header>
380
+ <div className="workspace-body" hidden={!!page}>
381
+ <MainContent activeBrainId={activeBrainId} />
382
+ </div>
383
+ {page}
384
+ </div>
385
+ <WorkspaceDrawers edge={edge} onChange={setEdge} plugins={plugins} activeBrainId={activeBrainId} />
386
+ </div>
387
+ }}
388
+ />
444
389
  )
445
390
  }
446
391
 
447
- export default App
392
+ export default function App() {
393
+ return <BrowserRouter><Dashboard /></BrowserRouter>
394
+ }
@@ -0,0 +1,62 @@
1
+ import { apiFetch, getApiBase } from './_base'
2
+
3
+ const inventory = {
4
+ secrets: { path: '/api/plugins/auth/secrets?catalog=0', list: 'keys', fields: [
5
+ 'key', 'label', 'set', 'provider_name', 'repos', 'next_rotate_due', 'rotation_overdue', 'updated_at',
6
+ ] },
7
+ brains: { path: '/api/brains', list: 'brains', fields: ['id', 'name', 'layer', 'exists', 'node_count'] },
8
+ machines: { path: '/api/mesh/nodes', list: 'nodes', fields: ['hostname', 'online', 'self', 'os', 'role', 'vault_only'] },
9
+ } as const
10
+
11
+ export async function readAuthInventory(resource: unknown, signal: AbortSignal) {
12
+ if (typeof resource !== 'string' || !Object.hasOwn(inventory, resource)) throw new Error('Unknown Auth inventory')
13
+ const { path, list, fields } = inventory[resource as keyof typeof inventory]
14
+ const response = await apiFetch(getApiBase() + path, { cache: 'no-store', signal })
15
+ if (!response.ok) throw new Error(`Inventory request returned HTTP ${response.status}`)
16
+ const result = await response.json()
17
+ const rows = Array.isArray(result) && resource === 'secrets' ? result : result?.[list]
18
+ if (!Array.isArray(rows) || rows.some(row => !row || typeof row !== 'object' || Array.isArray(row))) {
19
+ throw new Error('Inventory response was incomplete')
20
+ }
21
+ return rows.map(row => Object.fromEntries(fields.flatMap(key => Object.hasOwn(row, key) ? [[key, row[key]]] : [])))
22
+ }
23
+
24
+ export async function changeAuthCredential(payload: unknown, signal: AbortSignal) {
25
+ if (!payload || typeof payload !== 'object' || Array.isArray(payload)) throw new Error('Choose a credential action.')
26
+ const change = payload as Record<string, unknown>
27
+ const key = change.key
28
+ if (typeof key !== 'string' || !key.trim() || key.length > 256 || /[\x00-\x1f\x7f/\\]/.test(key) || key === '.' || key === '..') {
29
+ throw new Error('Select a valid credential.')
30
+ }
31
+ const path = getApiBase() + '/api/plugins/auth/secrets/' + encodeURIComponent(key)
32
+ const action = change.action
33
+ let response: Response
34
+ if (action === 'edit') {
35
+ const { label, repo } = change
36
+ if (typeof label !== 'string' || label.length > 120 ||
37
+ (repo !== undefined && (typeof repo !== 'string' || repo.length > 256 || /[\x00-\x1f\x7f,]/.test(repo)))) {
38
+ throw new Error('Enter a valid label and one repository binding.')
39
+ }
40
+ response = await apiFetch(path, {
41
+ method: 'PATCH', signal, headers: { 'Content-Type': 'application/json' },
42
+ body: JSON.stringify({ label: label.trim() || null, ...(typeof repo === 'string'
43
+ ? { repos: repo.trim() ? [repo.trim()] : [] } : {}) }),
44
+ })
45
+ } else if (action === 'replace') {
46
+ const value = change.value
47
+ if (typeof value !== 'string' || !value.trim() || value.length > 16384) throw new Error('Enter the replacement value.')
48
+ response = await apiFetch(path + '/rotate', {
49
+ method: 'POST', signal, headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ value }),
50
+ })
51
+ } else if (action === 'delete' && change.confirm === key) {
52
+ response = await apiFetch(path, { method: 'DELETE', signal })
53
+ } else {
54
+ throw new Error('Choose an action and confirm deletion if requested.')
55
+ }
56
+ if (!response.ok) throw new Error(`Auth returned HTTP ${response.status}.`)
57
+ const result = await response.json()
58
+ if (action === 'delete' ? result?.found !== true : result?.key !== key) {
59
+ throw new Error('Auth did not confirm the credential change.')
60
+ }
61
+ return { ok: true }
62
+ }