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,375 @@
1
+ const template = document.createElement('template');
2
+ template.innerHTML = `
3
+ <style>
4
+ :host { display:block; color:var(--color-text,#edf6f0); font:400 .9rem/1.5 var(--typography-body-font-family,system-ui); }
5
+ * { box-sizing:border-box; }
6
+ main { background:var(--color-background,#101e19); border:1px solid var(--color-outline,#3f6350); border-radius:var(--rounded-panel,.75rem); overflow:hidden; }
7
+ header, .body { padding:clamp(14px,3vw,26px); }
8
+ header { display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between; gap:12px; }
9
+ h1,h2,p { margin:0; }
10
+ h1 { font-size:clamp(1.5rem,4vw,2.25rem); letter-spacing:-.035em; line-height:1.15; }
11
+ h2 { font-size:1.1rem; }
12
+ .eyebrow { color:var(--color-primary,#64e3a4); font:600 .72rem var(--typography-label-font-family,monospace); letter-spacing:.1em; margin-bottom:6px; }
13
+ .muted, th { color:var(--color-muted,#b1c9ba); }
14
+ header p:last-child { margin-top:6px; }
15
+ nav { display:flex; flex-wrap:wrap; gap:4px; padding:0 clamp(14px,3vw,26px); border-block-end:1px solid var(--color-outline,#3f6350); }
16
+ button, input { font:inherit; color:inherit; }
17
+ button { min-height:44px; cursor:pointer; padding:0 12px; background:var(--color-surface,#192d24); border:1px solid var(--color-outline,#3f6350); border-radius:var(--rounded-control,.4rem); }
18
+ button:disabled { opacity:.65; cursor:wait; }
19
+ nav button { background:transparent; border:1px solid transparent; border-radius:0; color:var(--color-muted,#b1c9ba); }
20
+ nav button[aria-pressed="true"] { color:var(--color-primary,#64e3a4); border-block-end:2px solid currentColor; font-weight:700; }
21
+ button:focus-visible, input:focus-visible { outline:2px solid var(--color-primary,#64e3a4); outline-offset:2px; }
22
+ .tools { display:flex; align-items:center; justify-content:space-between; gap:12px; flex-wrap:wrap; margin-bottom:12px; }
23
+ label { display:flex; flex-wrap:wrap; align-items:center; gap:8px; }
24
+ input { background:var(--color-surface,#192d24); border:1px solid var(--color-outline,#3f6350); border-radius:var(--rounded-control,.4rem); min-height:44px; padding:6px 10px; max-width:100%; }
25
+ .table { overflow:auto; max-height:430px; }
26
+ table { width:100%; border-collapse:collapse; text-align:start; }
27
+ th, td { padding:9px 10px; text-align:start; border-block-end:1px solid var(--color-outline,#3f6350); vertical-align:top; }
28
+ th { position:sticky; top:0; background:var(--color-surface,#192d24); font-size:.75rem; }
29
+ td { overflow-wrap:anywhere; }
30
+ td.actions { white-space:nowrap; }
31
+ td.actions button + button { margin-inline-start:6px; }
32
+ select { font:inherit; min-height:44px; color:inherit; background:var(--color-surface,#192d24); border:1px solid var(--color-outline,#3f6350); border-radius:var(--rounded-control,.4rem); padding:6px 10px; }
33
+ dialog { color:inherit; background:var(--color-background,#101e19); border:1px solid var(--color-outline,#3f6350); border-radius:var(--rounded-panel,.75rem); padding:20px; width:min(480px,calc(100% - 26px)); max-height:calc(100% - 26px); }
34
+ dialog::backdrop { background:#08110dcc; }
35
+ dialog label { display:grid; margin:10px 0; }
36
+ dialog .tools { margin:12px 0 0; }
37
+ .state-ready { color:var(--color-primary,#64e3a4); }
38
+ .state-attention { color:var(--color-warning,#f4d18c); }
39
+ [role="alert"] { color:var(--color-danger,#ffbbb1); }
40
+ dl { margin:0 0 16px; }
41
+ dl div { display:flex; justify-content:space-between; flex-wrap:wrap; padding:8px 0; border-block-end:1px solid var(--color-outline,#3f6350); }
42
+ dd { margin:0; }
43
+ #audit-result { margin:8px 0; }
44
+ [hidden] { display:none!important; }
45
+ </style>
46
+ <main aria-labelledby="auth-title">
47
+ <header>
48
+ <div><p class="eyebrow">ACCESS CONTROL</p><h1 id="auth-title">Auth &amp; Secrets</h1>
49
+ <p class="muted">Credentials and access across this host’s brains and machines.</p></div>
50
+ <button type="button" id="refresh">Refresh</button>
51
+ </header>
52
+ <nav aria-label="Auth views">
53
+ <button type="button" data-view="secrets" aria-pressed="true">Secrets</button>
54
+ <button type="button" data-view="brains" aria-pressed="false">Brains</button>
55
+ <button type="button" data-view="machines" aria-pressed="false">Machines</button>
56
+ <button type="button" data-view="sign-in" aria-pressed="false">Sign-in &amp; audit</button>
57
+ </nav>
58
+ <section class="body" id="inventory" aria-label="Inventory">
59
+ <div class="tools">
60
+ <p id="summary" role="status"></p>
61
+ <label id="repo-filter-label" hidden>Repository<select id="repo-filter"></select></label>
62
+ <label id="search-label">Filter inventory<input type="search" id="search" autocomplete="off"></label>
63
+ </div>
64
+ <p id="problem" role="alert" hidden></p>
65
+ <p id="receipt" role="status" hidden></p>
66
+ <div class="table" id="table" role="region" aria-label="Inventory results" tabindex="0" hidden></div>
67
+ </section>
68
+ <section class="body" id="sign-in" aria-label="Sign-in and audit" hidden>
69
+ <dl aria-live="polite">
70
+ <div><dt>Registered passkeys</dt><dd id="passkeys">Checking…</dd></div>
71
+ <div><dt>Google sign-in configuration</dt><dd id="google">Checking…</dd></div>
72
+ <div><dt>Dashboard session signing</dt><dd id="session">Checking…</dd></div>
73
+ </dl>
74
+ <h2>Security baseline</h2>
75
+ <p id="audit-result" role="status">Check the current host configuration.</p>
76
+ <button type="button" id="audit">Run baseline audit</button>
77
+ </section>
78
+ <dialog id="credential-dialog" aria-labelledby="credential-heading">
79
+ <h2 id="credential-heading"></h2>
80
+ <p id="credential-key"></p>
81
+ <div id="credential-fields">
82
+ <label>Label<input id="credential-label" maxlength="120" autocomplete="off"></label>
83
+ <label>Repository binding<input id="credential-repo" maxlength="256" list="registered-repositories" autocomplete="off"></label>
84
+ <datalist id="registered-repositories"></datalist>
85
+ <button type="button" id="credential-clear-repo">Clear binding</button>
86
+ <p class="muted" id="binding-status"></p>
87
+ <label>Replacement value<input type="password" id="credential-value" maxlength="16384" autocomplete="new-password"></label>
88
+ </div>
89
+ <div id="delete-fields" hidden>
90
+ <p>Remove this credential from this host’s encrypted store. Enter its name to confirm.</p>
91
+ <label>Credential name<input id="credential-confirm" maxlength="256" autocomplete="off"></label>
92
+ </div>
93
+ <p id="credential-error" role="alert" hidden></p>
94
+ <div class="tools">
95
+ <button type="button" id="credential-close">Cancel</button>
96
+ <button type="button" id="credential-replace">Replace value</button>
97
+ <button type="button" id="credential-save">Save details</button>
98
+ </div>
99
+ </dialog>
100
+ </main>
101
+ `;
102
+
103
+ const count = value => Number.isSafeInteger(value) && value >= 0;
104
+ const words = values => Array.isArray(values) && values.length ? values.join(', ') : 'Unbound';
105
+ const date = value => typeof value === 'string' && Number.isFinite(Date.parse(value))
106
+ ? new Intl.DateTimeFormat(undefined, { dateStyle: 'medium' }).format(new Date(value)) : 'Unscheduled';
107
+ const state = (value, positive, negative) => value === true ? positive : value === false ? negative : 'Unreported';
108
+
109
+ const views = {
110
+ secrets: {
111
+ name: 'credentials', headers: ['Credential', 'Provider', 'Bound repositories', 'Storage', 'Rotation'],
112
+ row: item => [item.label ? `${item.key} · ${item.label}` : item.key, item.provider_name || 'Unassigned', words(item.repos),
113
+ state(item.set, 'Stored', 'Empty'), item.rotation_overdue ? 'Overdue' : date(item.next_rotate_due)],
114
+ },
115
+ brains: {
116
+ name: 'brains', headers: ['Brain', 'Layer', 'Memory nodes', 'State'],
117
+ row: item => [item.name, item.layer, count(item.node_count) ? String(item.node_count) : 'Unreported',
118
+ state(item.exists, 'Present', 'Unavailable')],
119
+ },
120
+ machines: {
121
+ name: 'machines', headers: ['Machine', 'OS', 'Role', 'Mesh state'],
122
+ row: item => [item.self ? item.hostname + ' (this host)' : item.hostname, item.os || 'Unreported',
123
+ item.role || 'Unassigned', item.vault_only ? 'Registered' : state(item.online, 'Online', 'Offline')],
124
+ },
125
+ };
126
+
127
+ class AuthHome extends HTMLElement {
128
+ constructor() {
129
+ super();
130
+ this.activeView = 'secrets';
131
+ this.inventory = {};
132
+ this.attachShadow({ mode: 'open' }).append(template.content.cloneNode(true));
133
+ this.field('refresh').addEventListener('click', () => void this.load());
134
+ this.field('audit').addEventListener('click', () => void this.audit());
135
+ this.field('search').addEventListener('input', () => this.renderInventory());
136
+ this.field('repo-filter').addEventListener('change', () => this.renderInventory());
137
+ this.field('credential-close').addEventListener('click', () => this.field('credential-dialog').close());
138
+ this.field('credential-save').addEventListener('click', () => void this.changeCredential(this.credentialAction));
139
+ this.field('credential-replace').addEventListener('click', () => void this.changeCredential('replace'));
140
+ this.field('credential-repo').addEventListener('input', () => { this.bindingChanged = true; });
141
+ this.field('credential-clear-repo').addEventListener('click', () => {
142
+ this.bindingChanged = true;
143
+ this.field('credential-repo').value = '';
144
+ this.field('binding-status').textContent = 'The binding will be cleared when you save.';
145
+ });
146
+ this.field('credential-dialog').addEventListener('cancel', event => {
147
+ if (this.credentialBusy) event.preventDefault();
148
+ });
149
+ this.field('credential-dialog').addEventListener('close', () => {
150
+ this.field('credential-value').value = '';
151
+ this.field('credential-confirm').value = '';
152
+ });
153
+ for (const button of this.shadowRoot.querySelectorAll('[data-view]')) {
154
+ button.addEventListener('click', () => {
155
+ this.activeView = button.dataset.view;
156
+ this.field('search').value = '';
157
+ for (const item of this.shadowRoot.querySelectorAll('[data-view]')) {
158
+ item.setAttribute('aria-pressed', String(item === button));
159
+ }
160
+ this.renderInventory();
161
+ });
162
+ }
163
+ }
164
+
165
+ field(id) { return this.shadowRoot.getElementById(id); }
166
+
167
+ repoAliases() {
168
+ const groups = new Map();
169
+ for (const brain of this.inventory.brains?.rows || []) {
170
+ if (brain.layer !== 'project' || typeof brain.name !== 'string') continue;
171
+ const normalized = brain.name.toLowerCase().replaceAll('_', '-');
172
+ const labels = groups.get(normalized) || new Set();
173
+ labels.add(brain.name);
174
+ groups.set(normalized, labels);
175
+ }
176
+ return new Map([...groups].filter(([, labels]) => labels.size === 1)
177
+ .map(([key, labels]) => [key, [...labels][0]]));
178
+ }
179
+
180
+ renderInventory() {
181
+ const signing = this.activeView === 'sign-in';
182
+ this.field('sign-in').hidden = !signing;
183
+ this.field('inventory').hidden = signing;
184
+ if (signing) return;
185
+
186
+ const view = views[this.activeView];
187
+ const result = this.inventory[this.activeView];
188
+ const problem = this.field('problem');
189
+ const tableRegion = this.field('table');
190
+ const summary = this.field('summary');
191
+ const search = this.field('search');
192
+ const repoFilter = this.field('repo-filter');
193
+ const credentials = this.activeView === 'secrets';
194
+ problem.hidden = !result?.error;
195
+ problem.textContent = result?.error || '';
196
+ tableRegion.hidden = true;
197
+ tableRegion.replaceChildren();
198
+ this.field('search-label').hidden = !result?.rows?.length;
199
+ this.field('repo-filter-label').hidden = !credentials || !result?.rows?.length;
200
+ if (!result) { summary.textContent = `Loading ${view.name}…`; return; }
201
+ if (result.error) { summary.textContent = ''; return; }
202
+
203
+ const aliases = credentials ? this.repoAliases() : new Map();
204
+ const repoLabels = item => [...new Set((Array.isArray(item.repos) ? item.repos : []).filter(repo => typeof repo === 'string').map(repo =>
205
+ aliases.get(repo.toLowerCase().replaceAll('_', '-')) || repo))];
206
+ const selectedRepo = repoFilter.value;
207
+ if (credentials) {
208
+ const repos = [...new Set(result.rows.flatMap(repoLabels))].sort((left, right) => left.localeCompare(right));
209
+ repoFilter.replaceChildren(new Option('All repositories', ''),
210
+ ...repos.map(repo => new Option(repo, repo)));
211
+ if (repos.includes(selectedRepo)) repoFilter.value = selectedRepo;
212
+ }
213
+ const query = search.value.trim().toLocaleLowerCase();
214
+ const rows = result.rows.flatMap(item => {
215
+ const repos = credentials ? repoLabels(item) : [];
216
+ if (credentials && repoFilter.value && !repos.includes(repoFilter.value)) return [];
217
+ const values = view.row(credentials ? { ...item, repos } : item);
218
+ const searchText = values.concat(credentials ? item.repos || [] : []).join(' ').toLocaleLowerCase();
219
+ return searchText.includes(query) ? [{ item, values }] : [];
220
+ });
221
+ summary.textContent = rows.length === result.rows.length
222
+ ? `${result.rows.length} ${view.name}` : `${rows.length} of ${result.rows.length} ${view.name}`;
223
+ if (!rows.length) return;
224
+ const table = document.createElement('table');
225
+ table.setAttribute('aria-label', view.name);
226
+ const heading = table.createTHead().insertRow();
227
+ const canEdit = credentials && typeof this.host?.changeCredential === 'function';
228
+ for (const title of canEdit ? [...view.headers, 'Manage'] : view.headers) {
229
+ const cell = document.createElement('th');
230
+ cell.scope = 'col';
231
+ cell.textContent = title;
232
+ heading.append(cell);
233
+ }
234
+ const body = table.createTBody();
235
+ for (const { item, values } of rows) {
236
+ const entry = body.insertRow();
237
+ for (const value of values) {
238
+ const cell = entry.insertCell();
239
+ cell.textContent = value ?? 'Unreported';
240
+ if (['Stored', 'Online', 'Present'].includes(value)) cell.className = 'state-ready';
241
+ if (['Overdue', 'Offline', 'Empty'].includes(value)) cell.className = 'state-attention';
242
+ }
243
+ if (canEdit) {
244
+ const actions = entry.insertCell();
245
+ actions.className = 'actions';
246
+ for (const [action, label] of [['edit', 'Edit'], ['delete', 'Delete']]) {
247
+ const button = document.createElement('button');
248
+ button.type = 'button';
249
+ button.textContent = label;
250
+ button.setAttribute('aria-label', `${label} ${item.key}`);
251
+ button.addEventListener('click', () => this.openCredential(item, action));
252
+ actions.append(button);
253
+ }
254
+ }
255
+ }
256
+ tableRegion.append(table);
257
+ tableRegion.hidden = false;
258
+ }
259
+
260
+ openCredential(item, action) {
261
+ const deleting = action === 'delete';
262
+ this.selectedCredential = item;
263
+ this.credentialAction = action;
264
+ this.bindingChanged = false;
265
+ this.field('credential-heading').textContent = deleting ? 'Delete stored credential' : 'Edit credential';
266
+ this.field('credential-key').textContent = item.key;
267
+ this.field('credential-fields').hidden = deleting;
268
+ this.field('delete-fields').hidden = !deleting;
269
+ this.field('credential-replace').hidden = deleting;
270
+ this.field('credential-save').textContent = deleting ? 'Delete credential' : 'Save details';
271
+ this.field('credential-label').value = item.label || '';
272
+ this.field('credential-repo').value = (item.repos || []).length <= 1 ? item.repos?.[0] || '' : '';
273
+ this.field('registered-repositories').replaceChildren(
274
+ ...[...this.repoAliases().values()].sort().map(repo => new Option(repo, repo)),
275
+ );
276
+ this.field('credential-error').hidden = true;
277
+ this.field('binding-status').textContent = item.repos?.length > 1
278
+ ? `Current bindings: ${item.repos.join(', ')}. Select one repository to replace them.`
279
+ : '';
280
+ this.field('credential-dialog').showModal();
281
+ }
282
+
283
+ async changeCredential(action) {
284
+ if (this.credentialBusy || !this.selectedCredential) return;
285
+ const { key } = this.selectedCredential;
286
+ const error = this.field('credential-error');
287
+ const data = { action, key };
288
+ if (action === 'edit') {
289
+ data.label = this.field('credential-label').value;
290
+ if (this.bindingChanged) data.repo = this.field('credential-repo').value;
291
+ } else if (action === 'replace') {
292
+ data.value = this.field('credential-value').value;
293
+ this.field('credential-value').value = '';
294
+ } else {
295
+ data.confirm = this.field('credential-confirm').value;
296
+ }
297
+ this.credentialBusy = true;
298
+ const controls = ['credential-close', 'credential-save', 'credential-replace'];
299
+ for (const id of controls) this.field(id).disabled = true;
300
+ error.hidden = true;
301
+ try {
302
+ const result = await this.host.changeCredential(data);
303
+ if (result?.ok !== true) throw new Error('Auth did not confirm the change.');
304
+ this.field('credential-dialog').close();
305
+ const receipt = this.field('receipt');
306
+ receipt.textContent = action === 'delete' ? `Deleted ${key} from this host’s store.`
307
+ : action === 'replace' ? `Replaced the stored value for ${key}.` : `Saved details for ${key}.`;
308
+ receipt.hidden = false;
309
+ await this.load();
310
+ } catch (failure) {
311
+ error.textContent = failure.message;
312
+ error.hidden = false;
313
+ } finally {
314
+ this.credentialBusy = false;
315
+ for (const id of controls) this.field(id).disabled = false;
316
+ }
317
+ }
318
+
319
+ async load() {
320
+ const button = this.field('refresh');
321
+ if (button.disabled) return;
322
+ button.disabled = true;
323
+ this.inventory = {};
324
+ this.renderInventory();
325
+ await Promise.all([
326
+ ...Object.keys(views).map(async resource => {
327
+ try {
328
+ const rows = await this.host.readInventory(resource);
329
+ if (!Array.isArray(rows)) throw new Error('Incomplete inventory response');
330
+ this.inventory[resource] = { rows };
331
+ } catch (error) {
332
+ this.inventory[resource] = { error: `Could not load ${views[resource].name}. ${error.message}` };
333
+ }
334
+ this.renderInventory();
335
+ }),
336
+ this.loadSignIn(),
337
+ ]);
338
+ button.disabled = false;
339
+ }
340
+
341
+ async loadSignIn() {
342
+ for (const id of ['passkeys', 'google', 'session']) this.field(id).textContent = 'Checking…';
343
+ const [status, session] = await Promise.allSettled([
344
+ this.host?.run('status'), this.host?.run('session'),
345
+ ]);
346
+ const providers = status.status === 'fulfilled' ? status.value : null;
347
+ const registered = providers?.passkey?.registered_count;
348
+ this.field('passkeys').textContent = count(registered) ? String(registered) : 'Unavailable';
349
+ this.field('google').textContent = state(providers?.google_oauth2?.configured, 'Configured', 'Needs setup');
350
+ this.field('session').textContent = state(session.status === 'fulfilled' && session.value
351
+ ? session.value.session_secret_configured : null, 'Configured', 'Needs setup');
352
+ }
353
+
354
+ async audit() {
355
+ const button = this.field('audit');
356
+ const result = this.field('audit-result');
357
+ if (button.disabled) return;
358
+ button.disabled = true;
359
+ result.textContent = 'Checking this host…';
360
+ try {
361
+ let report;
362
+ try { report = await this.host.run('audit'); }
363
+ catch (error) { report = JSON.parse(error.message); }
364
+ if (typeof report?.passed !== 'boolean' || !count(report.findings_count)) throw new Error('Invalid audit response');
365
+ const findings = `${report.findings_count} ${report.findings_count === 1 ? 'finding' : 'findings'}`;
366
+ result.textContent = report.passed ? `Baseline passed with ${findings}.` : `Review required. ${findings}.`;
367
+ result.className = report.passed && !report.findings_count ? 'state-ready' : 'state-attention';
368
+ } catch {
369
+ result.textContent = 'Baseline audit unavailable. Retry or run auth audit in the terminal.';
370
+ result.className = 'state-attention';
371
+ } finally { button.disabled = false; }
372
+ }
373
+ }
374
+
375
+ if (!customElements.get('tr-auth-home')) customElements.define('tr-auth-home', AuthHome);
@@ -1,23 +1,34 @@
1
- # Automations — Control ledger
2
-
3
- ```yaml
4
- tokens:
5
- brand-name: "Automations"
6
- wordmark: "AUTOMATIONS"
7
- color-primary: "#f2bd63"
8
- color-background: "#181713"
9
- color-surface: "#24221c"
10
- color-text: "#f4efe5"
11
- color-muted: "#c5bca9"
12
- color-border: "#726652"
13
- color-success: "#a8d5b0"
14
- color-error: "#ffb5a9"
15
- color-focus: "#b8d9ff"
16
- font-family: "system-ui, sans-serif"
17
- font-mono: "ui-monospace, monospace"
18
- border-radius: "12px"
19
- spacing-unit: "8px"
20
- ```
1
+ ---
2
+ version: alpha
3
+ name: Automation Control Ledger
4
+ description: A dark operations ledger that keeps scheduling, source coverage and observed runs visually separate.
5
+ colors:
6
+ primary: "#f2bd63"
7
+ background: "#181713"
8
+ surface: "#24221c"
9
+ text: "#f4efe5"
10
+ muted: "#c5bca9"
11
+ border: "#726652"
12
+ success: "#a8d5b0"
13
+ error: "#ffb5a9"
14
+ focus: "#b8d9ff"
15
+ typography:
16
+ body: { fontFamily: "system-ui, sans-serif", fontSize: 14px, lineHeight: 1.45 }
17
+ label: { fontFamily: "ui-monospace, monospace", fontSize: 12px, fontWeight: 700 }
18
+ spacing: { sm: 8px, md: 16px, touch: 44px }
19
+ rounded: { md: 8px }
20
+ components:
21
+ ledger-note:
22
+ backgroundColor: "{colors.surface}"
23
+ textColor: "{colors.text}"
24
+ padding: "{spacing.md}"
25
+ rounded: "{rounded.md}"
26
+ ledger-label:
27
+ textColor: "{colors.primary}"
28
+ typography: "{typography.label}"
29
+ ---
30
+
31
+ # Automations Control Ledger
21
32
 
22
33
  ## Purpose and first-principles decision
23
34
  Greg checks which work is automated, where its source is available, and whether an observed run failed. He needs automation origins and coverage before interpreting counts. Replace the old chronometer card, fixed schedule chips and terminal output: they obscure these tasks and invent healthy state. Retain external element names and host.run because these are useful host contracts.
@@ -30,7 +41,7 @@ The first visible line states whether inventory is unchecked, loading, complete,
30
41
  The selected record shows trigger, enabled state, runner availability, source, placement and origin independently. Unknown values include a reason. Failed reads clear current inventory. Unsupported sources and unavailable nodes remain visible. Counts derive only from returned records and cannot imply coverage completeness.
31
42
 
32
43
  ## Interaction and safety
33
- Read through host.run('list', []) inside the sandbox. The full panel may use the authenticated generic plugin route when no host channel is available. Reject failed wrappers and malformed inventory; do not create successful fallback output. A latest-request counter prevents stale refreshes overwriting newer results. Disconnect invalidates pending work; reconnect reuses its shadow root and selected tab.
44
+ Read through the authenticated host bridge inside the sandbox. Load this node first and switch to mesh inventory through an explicit scope control. Reject failed wrappers and malformed inventory. A latest-request counter prevents stale refreshes overwriting newer results. Disconnect invalidates pending work; reconnect reuses its shadow root and selected tab.
34
45
 
35
46
  Every control is at least 44px, with visible focus. Tabs support arrow/Home/End navigation and maintain selected-screen state. Filters have labels; loading/errors use a live region. Layout becomes one column under 600px; text wraps safely. State change motion is a short content reveal; reduced motion removes it. Copy feedback follows actual clipboard completion. Source-advertised write controls state their target and require confirmation; arbitrary commands and credential inputs are absent.
36
47
 
@@ -13,6 +13,18 @@ export const coreModule = (root, name) => import(pathToFileURL(path.join(root, '
13
13
  const digest = text => crypto.createHash('sha256').update(text).digest('hex').slice(0, 20);
14
14
  export const recordId = (node, source, key) => `${source}:${digest(`${node}\0${key}`)}`;
15
15
  const text = (value, max = 240) => typeof value === 'string' ? value.slice(0, max) : '';
16
+ const credentialLine = /\b(?:authorization|bearer|password|token|credential|secret|api[-_ ]?key)\b|(?:_KEY|_TOKEN|_SECRET|_PASSWORD)\b|\b(?:sk[-_]|gh[pousr]_|github_pat_|eyJ)[a-z0-9_-]{12,}/i;
17
+
18
+ function failureReceipt(event) {
19
+ const output = text(event.output_tail, 2000).split('\n')
20
+ .map(line => credentialLine.test(line) ? '[credential diagnostic omitted]' : line)
21
+ .join('\n');
22
+ return {
23
+ timed_out: Boolean(event.timed_out),
24
+ duration_ms: Number.isFinite(event.duration_ms) ? event.duration_ms : null,
25
+ output_tail: output || null,
26
+ };
27
+ }
16
28
  const canCancelPending = async (tasks, queueDir) =>
17
29
  tasks.TASK_CANCELLATION_SUPPORTS_EXPECTED_STATUS === true
18
30
  && typeof tasks.supportsPendingTaskCancellation === 'function'
@@ -143,7 +155,11 @@ export async function sourceAdapters(ctx) {
143
155
  const matching = payloads.filter(event => event.plugin_id === record.plugin_id && event.command === record.command)
144
156
  .sort((a, b) => eventTime(a) - eventTime(b));
145
157
  const last = matching.at(-1);
146
- if (last) record.last_run = outcome(last);
158
+ if (last) {
159
+ record.last_run = outcome(last);
160
+ // The failure receipt is shown only for the record the operator asked about.
161
+ if (last.ok === false && ctx.receiptId === record.id) record.last_run.receipt = failureReceipt(last);
162
+ }
147
163
  const handled = record.last_handled_slot && matching.filter(event => event.slot === record.last_handled_slot).at(-1);
148
164
  if (handled) record.last_handled_outcome = outcome(handled);
149
165
  }
@@ -17,6 +17,7 @@ Options:
17
17
  --source <source> Filter records by source
18
18
  --trigger <kind> Filter records by trigger kind
19
19
  --state <state> Filter records by observed state
20
+ --receipt Include a failed plugin task receipt (show --local, terminal only)
20
21
  --json Machine-readable output (also the default)
21
22
  --help, -h Show this help
22
23
 
@@ -43,6 +44,7 @@ export function parseArgs(argv) {
43
44
  const flag = args.shift();
44
45
  if (flag === '--json') continue;
45
46
  if (flag === '--local') { result.localOnly = true; continue; }
47
+ if (flag === '--receipt') { result.receipt = true; continue; }
46
48
  const name = { '--node': 'node', '--source': 'source', '--trigger': 'trigger', '--state': 'state' }[flag];
47
49
  if (!name) throw new Error(`Unknown option: ${flag}`);
48
50
  const value = args.shift(); if (!value || value.startsWith('-')) throw new Error(`Missing value for ${flag}`);
@@ -50,6 +52,9 @@ export function parseArgs(argv) {
50
52
  result.filters[name] = value;
51
53
  }
52
54
  if (result.filters.source && !SOURCES.includes(result.filters.source)) throw new Error('Unknown source');
55
+ if (result.receipt && (command !== 'show' || !result.localOnly || !result.id.startsWith('plugin-tasks:'))) {
56
+ throw new Error('--receipt requires show <plugin-task-id> --local');
57
+ }
53
58
  if (command === 'cancel' && (Object.keys(result.filters).length || result.localOnly)) throw new Error('cancel accepts only a local automation id and --json');
54
59
  return result;
55
60
  }
@@ -101,13 +106,17 @@ export async function run(argv = [], dependencies = {}) {
101
106
  if (!result.ok) (dependencies.setExitCode || (code => { process.exitCode = code; }))(result.exit_code);
102
107
  return result;
103
108
  }
109
+ if (parsed.receipt && !process.stdin.isTTY) throw new Error('--receipt requires a local terminal');
104
110
  const root = dependencies.packageRoot || process.env.TR_PACKAGE_ROOT;
105
111
  if (!root) throw new Error('TR_PACKAGE_ROOT is required');
106
112
  if (parsed.command === 'cancel') {
107
113
  const result = await (dependencies.cancel || cancelAutomation)(root, parsed.id);
108
114
  write(`${JSON.stringify(result)}\n`); return result;
109
115
  }
110
- let inventory = await (dependencies.inventory || meshAutomationInventory)(root, { localOnly: parsed.localOnly });
116
+ let inventory = await (dependencies.inventory || meshAutomationInventory)(root, {
117
+ localOnly: parsed.localOnly,
118
+ ...(parsed.receipt ? { receiptId: parsed.id } : {}),
119
+ });
111
120
  inventory = filterInventory(inventory, parsed.filters);
112
121
  let result = inventory;
113
122
  if (parsed.command === 'show') {
@@ -1,19 +1,19 @@
1
1
  {
2
2
  "name": "tr-plugin-automations",
3
- "version": "1.0.4",
3
+ "version": "1.2.0",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "tr-plugin-automations",
9
- "version": "1.0.4",
9
+ "version": "1.2.0",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
12
  "@gregiteen/ssss-cli": "0.14.5"
13
13
  },
14
14
  "devDependencies": {
15
15
  "jsdom": "^29.1.1",
16
- "total-recall-brain": "3.44.0",
16
+ "total-recall-brain": "3.45.0",
17
17
  "vitest": "^4.1.10"
18
18
  }
19
19
  },
@@ -7021,9 +7021,9 @@
7021
7021
  }
7022
7022
  },
7023
7023
  "node_modules/total-recall-brain": {
7024
- "version": "3.44.0",
7025
- "resolved": "https://registry.npmjs.org/total-recall-brain/-/total-recall-brain-3.44.0.tgz",
7026
- "integrity": "sha512-VNPaIO9zsSwoxAsJ5ByIQBP9zPpLq4RiQO7Vrex4rBOHFQJT50P7utcZiLMSZTyZJU4C/m5uB8qTCSBMp6+l6Q==",
7024
+ "version": "3.45.0",
7025
+ "resolved": "https://registry.npmjs.org/total-recall-brain/-/total-recall-brain-3.45.0.tgz",
7026
+ "integrity": "sha512-HDYfROazZbsLHQsFPnlBcSpe1HL1QEi7JG8x/eNRUI06RxVQsZWl8LwBo2lTWjWRDrKmCy7BUmSXQDuWF3lrEw==",
7027
7027
  "dev": true,
7028
7028
  "license": "MIT",
7029
7029
  "workspaces": [
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tr-plugin-automations",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "type": "module",
5
5
  "description": "Scheduled plugin task runner plus automation sources, triggers, observed outcomes and coverage across the Total Recall mesh.",
6
6
  "scripts": {
@@ -19,9 +19,10 @@
19
19
  "cron.mjs",
20
20
  "capability/",
21
21
  "BRICK.md",
22
- "ui/card.js",
22
+ "DESIGN.md",
23
+ "ui/home.js",
23
24
  "ui/automations.js",
24
- "ui/DESIGN.md"
25
+ "ui/chunks/"
25
26
  ],
26
27
  "publishConfig": {
27
28
  "access": "public"
@@ -2,10 +2,14 @@
2
2
  "$schema": "https://github.com/gregiteen/total-recall/blob/main/metadata.plugin.schema.json",
3
3
  "id": "automations",
4
4
  "name": "Automations",
5
- "version": "1.1.0",
5
+ "version": "1.2.0",
6
6
  "description": "Run scheduled plugin tasks and inspect automation sources, triggers, observed outcomes and coverage across the mesh.",
7
7
  "author": "Total Recall",
8
8
  "license": "MIT",
9
+ "reuse": {
10
+ "commands": ["total-recall mesh nodes"],
11
+ "owned": "Collects automation sources, triggers, outcomes and node coverage, and delegates confirmed local task cancellation to its owner."
12
+ },
9
13
  "use_cases": [
10
14
  "automation",
11
15
  "monitoring"
@@ -43,7 +47,9 @@
43
47
  "timeout_ms": 25000,
44
48
  "effect": "read",
45
49
  "output": "json",
46
- "args": []
50
+ "args": [
51
+ { "name": "receipt", "flag": "--receipt", "type": "boolean", "label": "Local terminal failure receipt" }
52
+ ]
47
53
  },
48
54
  {
49
55
  "name": "dream",
@@ -77,13 +83,14 @@
77
83
  "daemon": ["scheduler"]
78
84
  },
79
85
  "ui": {
80
- "design_tokens": "ui/DESIGN.md",
86
+ "design_tokens": "DESIGN.md",
87
+ "home": "automations",
81
88
  "elements": [
82
89
  {
83
90
  "id": "automations",
84
91
  "kind": "panel",
85
92
  "tag": "tr-automations",
86
- "module": "ui/card.js",
93
+ "module": "ui/home.js",
87
94
  "description": "Live automation inventory with per-source node coverage",
88
95
  "events": [],
89
96
  "tokens": [
@@ -97,29 +104,6 @@
97
104
  "radius-md"
98
105
  ],
99
106
  "optional_tokens": []
100
- },
101
- {
102
- "id": "card",
103
- "kind": "card",
104
- "tag": "tr-automations-card",
105
- "module": "ui/card.js",
106
- "description": "Automations workspace"
107
- }
108
- ]
109
- },
110
- "card_face": {
111
- "skin": "standard",
112
- "theme": "precision-chronometer",
113
- "headline": "Automation sources, triggers and outcomes",
114
- "primary_color": "#f2bd63",
115
- "secondary_color": "#24221c",
116
- "accent_color": "#f2bd63",
117
- "touch_layout": "comfortable",
118
- "interactive": true,
119
- "quick_actions": [
120
- {
121
- "subcommand": "list",
122
- "label": "Inspect automations"
123
107
  }
124
108
  ]
125
109
  },
@@ -1,2 +1,2 @@
1
- /** External bundlers may use this entrypoint; the sandbox loads card.js directly. */
2
- export { AutomationsElement } from './card.js';
1
+ /** External bundlers may use this entrypoint; the sandbox loads the Home directly. */
2
+ export { AutomationsElement } from './home.js';