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.
- package/bin/total-recall.mjs +7 -2
- package/frontend/dist/assets/index-BRYE1jmv.css +1 -0
- package/frontend/dist/assets/index-D1goIPjC.js +5598 -0
- package/frontend/dist/index.html +2 -2
- package/frontend/dist/sw.js +5 -4
- package/frontend/src/App.tsx +183 -236
- package/frontend/src/api/auth-inventory.ts +62 -0
- package/frontend/src/api/memory.ts +13 -8
- package/frontend/src/api/plugin-credentials.ts +23 -0
- package/frontend/src/api/plugins.ts +37 -53
- package/frontend/src/api/workspace-drawers.ts +97 -0
- package/frontend/src/components/BrainSelector.tsx +9 -3
- package/frontend/src/components/plugins/PluginPanel.tsx +83 -42
- package/frontend/src/components/plugins/PluginSettings.tsx +10 -20
- package/frontend/src/components/plugins/PluginWorkspace.tsx +367 -0
- package/frontend/src/components/plugins/ScopedPluginCommands.tsx +142 -0
- package/frontend/src/components/plugins/plugin-frame.ts +44 -33
- package/frontend/src/components/plugins/scoped-plugin-operations.ts +28 -0
- package/frontend/src/components/workspace/DrawerChat.tsx +110 -0
- package/frontend/src/components/workspace/DrawerLayout.tsx +196 -0
- package/frontend/src/components/workspace/DrawerMarkup.tsx +49 -0
- package/frontend/src/components/workspace/PluginChunkLibrary.tsx +92 -0
- package/frontend/src/components/workspace/PluginHome.tsx +76 -0
- package/frontend/src/components/workspace/WorkspaceDrawers.tsx +96 -0
- package/frontend/src/components/workspace/WorkspacePage.tsx +95 -0
- package/frontend/src/components/workspace/usePluginDesign.ts +38 -0
- package/frontend/src/index.css +409 -136
- package/frontend/src/pages/HelpPage.tsx +15 -46
- package/frontend/src/pages/MemoryPage.tsx +19 -36
- package/frontend/src/pages/SettingsPage.tsx +1 -1
- package/metadata.plugin.schema.json +53 -227
- package/package.json +1 -1
- package/scaffold/.agent/skills/plugin/SKILL.md +13 -11
- package/scaffold/.agent/skills/plugin/evals/README.md +14 -21
- package/scaffold/.agent/skills/plugin/evals/cases/01-fabricated-seed.mjs +15 -18
- package/scaffold/.agent/skills/plugin/evals/cases/02-reassuring-default.mjs +19 -24
- package/scaffold/.agent/skills/plugin/evals/cases/03-declared-template.mjs +12 -20
- package/scaffold/.agent/skills/plugin/evals/cases/04-home-collects-credential.mjs +35 -0
- package/scaffold/.agent/skills/plugin/evals/cases/05-host-leak-in-scaffold.mjs +8 -28
- package/scaffold/.agent/skills/plugin/evals/cases/06-correct-plugin.mjs +85 -47
- package/scaffold/.agent/skills/plugin/evals/run.mjs +17 -18
- package/scaffold/.agent/skills/plugin/prompts/05-credentials.md +4 -4
- package/scaffold/.agent/skills/plugin/prompts/07-scaffold.md +2 -2
- package/scaffold/.agent/skills/plugin/prompts/08-verify.md +4 -4
- package/scaffold/.agent/skills/plugin/references/anti-patterns.md +2 -2
- package/scaffold/.agent/skills/plugin/references/generative-home.md +38 -0
- package/scaffold/.agent/skills/plugin/references/scaffold.md +5 -5
- package/scaffold/.agent/skills/plugin/references/surfaces.md +13 -4
- package/scaffold/.agent/skills/plugin/scripts/record.mjs +75 -153
- package/scaffold/.agent/skills/plugin/subagents/plugin-reviewer.md +4 -4
- package/scaffold/.agent/skills/total-recall/plugins/auth/DESIGN.md +76 -0
- package/scaffold/.agent/skills/total-recall/plugins/auth/README.md +3 -1
- package/scaffold/.agent/skills/total-recall/plugins/auth/cli.mjs +20 -15
- package/scaffold/.agent/skills/total-recall/plugins/auth/package-lock.json +6 -6
- package/scaffold/.agent/skills/total-recall/plugins/auth/package.json +2 -1
- package/scaffold/.agent/skills/total-recall/plugins/auth/plugin.json +13 -51
- package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/access-overview.md +17 -0
- package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/agent-login.md +20 -0
- package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/baseline-audit.md +22 -0
- package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/credential-repository-binding.md +17 -0
- package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/credential-store-maintenance.md +17 -0
- package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/dashboard-password.md +18 -0
- package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/dashboard-sessions.md +18 -0
- package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/endpoint-probe.md +23 -0
- package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/google-sign-in.md +21 -0
- package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/mesh-machines.md +16 -0
- package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/passkey-enrollment.md +21 -0
- package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/registered-brains.md +16 -0
- package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/scoped-access-keys.md +17 -0
- package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/secret-inventory.md +25 -0
- package/scaffold/.agent/skills/total-recall/plugins/auth/ui/chunks/signing-key-rotation.md +22 -0
- package/scaffold/.agent/skills/total-recall/plugins/auth/ui/home.js +375 -0
- package/scaffold/.agent/skills/total-recall/plugins/automations/{ui/DESIGN.md → DESIGN.md} +32 -21
- package/scaffold/.agent/skills/total-recall/plugins/automations/adapters.mjs +17 -1
- package/scaffold/.agent/skills/total-recall/plugins/automations/cli.mjs +10 -1
- package/scaffold/.agent/skills/total-recall/plugins/automations/package-lock.json +6 -6
- package/scaffold/.agent/skills/total-recall/plugins/automations/package.json +4 -3
- package/scaffold/.agent/skills/total-recall/plugins/automations/plugin.json +11 -27
- package/scaffold/.agent/skills/total-recall/plugins/automations/ui/automations.js +2 -2
- package/scaffold/.agent/skills/total-recall/plugins/automations/ui/chunks/control-ledger.md +42 -0
- package/scaffold/.agent/skills/total-recall/plugins/automations/ui/chunks/local-inventory-triage.md +17 -0
- package/scaffold/.agent/skills/total-recall/plugins/automations/ui/chunks/pending-control.md +39 -0
- package/scaffold/.agent/skills/total-recall/plugins/automations/ui/chunks/run-evidence.md +41 -0
- package/scaffold/.agent/skills/total-recall/plugins/automations/ui/chunks/schedule-vs-run-evidence.md +17 -0
- package/scaffold/.agent/skills/total-recall/plugins/automations/ui/chunks/source-coverage.md +41 -0
- package/scaffold/.agent/skills/total-recall/plugins/automations/ui/{card.js → home.js} +32 -27
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/DESIGN.md +53 -0
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/cli.mjs +23 -0
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/commands/run-core.mjs +4 -2
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/core/check.mjs +4 -2
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/package-lock.json +6 -6
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/package.json +2 -1
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/plugin.json +40 -40
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/chunks/config.md +15 -0
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/chunks/detect.md +15 -0
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/chunks/gate.md +15 -0
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/chunks/init.md +15 -0
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/chunks/report.md +17 -0
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/chunks/run.md +17 -0
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/chunks/snapshot.md +15 -0
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/code-quality-report.mjs +55 -23
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/home.mjs +214 -0
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/DESIGN.md +146 -0
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/package-lock.json +6 -6
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/package.json +2 -1
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/plugin.json +51 -34
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/src/command.mjs +1 -1
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/create.md +35 -0
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/history.md +35 -0
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/library.md +49 -0
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/list.md +42 -0
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/promote.md +40 -0
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/read.md +25 -0
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/remove.md +26 -0
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/rollback.md +26 -0
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/show.md +53 -0
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/status.md +40 -0
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/test-path.md +38 -0
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/test.md +46 -0
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/chunks/update.md +32 -0
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/home.js +533 -0
- package/scaffold/.agent/skills/total-recall/plugins/embeddings/DESIGN.md +110 -0
- package/scaffold/.agent/skills/total-recall/plugins/embeddings/package-lock.json +6 -6
- package/scaffold/.agent/skills/total-recall/plugins/embeddings/package.json +2 -1
- package/scaffold/.agent/skills/total-recall/plugins/embeddings/plugin.json +13 -10
- package/scaffold/.agent/skills/total-recall/plugins/embeddings/ui/chunks/benchmark.md +49 -0
- package/scaffold/.agent/skills/total-recall/plugins/embeddings/ui/chunks/coverage.md +53 -0
- package/scaffold/.agent/skills/total-recall/plugins/embeddings/ui/chunks/models.md +43 -0
- package/scaffold/.agent/skills/total-recall/plugins/embeddings/ui/chunks/pull.md +41 -0
- package/scaffold/.agent/skills/total-recall/plugins/embeddings/ui/chunks/status.md +59 -0
- package/scaffold/.agent/skills/total-recall/plugins/embeddings/ui/home.js +353 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/DESIGN.md +31 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/README.md +25 -1
- package/scaffold/.agent/skills/total-recall/plugins/git/cli.mjs +5 -1
- package/scaffold/.agent/skills/total-recall/plugins/git/package-lock.json +6 -6
- package/scaffold/.agent/skills/total-recall/plugins/git/package.json +2 -1
- package/scaffold/.agent/skills/total-recall/plugins/git/plugin.json +17 -27
- package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/commit-memory.mjs +30 -6
- package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/fleet.mjs +24 -6
- package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/secret-firewall.mjs +33 -7
- package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/undo.mjs +29 -5
- package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/unmerged.mjs +182 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/ui/chunks/change-comparison.md +27 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/ui/chunks/commit-identity.md +22 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/ui/chunks/create-worktree.md +25 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/ui/chunks/registered-worktrees.md +22 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/ui/chunks/remove-worktree.md +23 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/ui/chunks/repository-ledger.md +25 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/ui/chunks/unmerged-work.md +22 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/ui/chunks/upstream-divergence.md +17 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/ui/chunks/worktree-conflict-triage.md +17 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/ui/chunks/worktree-terminal.md +22 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/ui/home.js +273 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/DESIGN.md +35 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/README.md +4 -5
- package/scaffold/.agent/skills/total-recall/plugins/mesh/cli.mjs +9 -3
- package/scaffold/.agent/skills/total-recall/plugins/mesh/package-lock.json +6 -6
- package/scaffold/.agent/skills/total-recall/plugins/mesh/package.json +2 -1
- package/scaffold/.agent/skills/total-recall/plugins/mesh/plugin.json +37 -39
- package/scaffold/.agent/skills/total-recall/plugins/mesh/src/cli/mesh.mjs +5 -3
- package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/active-device-dispatch.md +22 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/control-probe.md +25 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/control-server.md +22 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/credential-readiness.md +23 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/elected-leader.md +22 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/enrollment-key.md +22 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/file-receipt.md +25 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/fleet-execution.md +23 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/fleet-presence.md +23 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/interactive-ssh.md +22 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/local-enrollment.md +23 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/mesh-policy.md +23 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/network-atlas.md +25 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/node-roster.md +26 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/node-selection-proof.md +17 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/owner-observations.md +23 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/peer-path.md +23 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/pinned-leader.md +24 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/reachability-evidence-ladder.md +17 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/recorded-login.md +23 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/remote-execution.md +22 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/chunks/secret-grants.md +26 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/{card.js → home.js} +93 -22
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/DESIGN.md +86 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/README.md +19 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/cli.mjs +5 -1
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/package-lock.json +6 -6
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/package.json +2 -1
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/plugin.json +43 -22
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/chat.mjs +80 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/adapter-docs-freshness.md +16 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/chat-handoff.md +26 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/fleet-maintenance.md +21 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/harness-inventory.md +21 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/included-access.md +18 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/included-usage-verification.md +15 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/independent-review.md +17 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/managed-execution.md +20 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/official-documentation.md +18 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/quota-recovery.md +21 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/review-routing-decision.md +16 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/route-work.md +18 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/routing-evidence.md +18 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/run-ledger.md +18 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/home.js +198 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/DESIGN.md +75 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/README.md +2 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/cli.mjs +17 -14
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/package-lock.json +6 -6
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/package.json +2 -1
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/plugin.json +10 -44
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/generate.mjs +5 -4
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/graph.mjs +3 -4
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/ingest.mjs +23 -18
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/mesh-vaults.mjs +8 -3
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/refresh.mjs +6 -3
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/search.mjs +3 -5
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/token.mjs +21 -47
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/upstream-watcher.mjs +17 -6
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/auto-refresh.md +18 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/bootstrap-pages.md +18 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/generate-wiki.md +21 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/generator-settings.md +18 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/host-probe.md +18 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/ingest-preview.md +18 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/link-hygiene.md +21 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/link-topology.md +19 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/passage-search.md +19 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/propagation-plan.md +18 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/provider-credentials.md +18 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/refresh-report.md +18 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/task-evidence.md +22 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/upstream-record.md +18 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/watch-upstream.md +18 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/chunks/wiki-atlas.md +19 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/panel.js +261 -513
- package/scaffold/.agent/skills/total-recall/plugins/security/DESIGN.md +84 -0
- package/scaffold/.agent/skills/total-recall/plugins/security/README.md +4 -2
- package/scaffold/.agent/skills/total-recall/plugins/security/cli.mjs +7 -19
- package/scaffold/.agent/skills/total-recall/plugins/security/package-lock.json +6 -6
- package/scaffold/.agent/skills/total-recall/plugins/security/package.json +2 -3
- package/scaffold/.agent/skills/total-recall/plugins/security/plugin.json +19 -52
- package/scaffold/.agent/skills/total-recall/plugins/security/ui/chunks/device-evidence.md +21 -0
- package/scaffold/.agent/skills/total-recall/plugins/security/ui/chunks/evidence-desk.md +18 -0
- package/scaffold/.agent/skills/total-recall/plugins/security/ui/chunks/guided-device-review.md +17 -0
- package/scaffold/.agent/skills/total-recall/plugins/security/ui/chunks/host-and-network.md +21 -0
- package/scaffold/.agent/skills/total-recall/plugins/security/ui/chunks/https-headers.md +17 -0
- package/scaffold/.agent/skills/total-recall/plugins/security/ui/chunks/mesh-coverage.md +18 -0
- package/scaffold/.agent/skills/total-recall/plugins/security/ui/chunks/private-security-tools.md +16 -0
- package/scaffold/.agent/skills/total-recall/plugins/security/ui/chunks/single-origin-header-check.md +17 -0
- package/scaffold/.agent/skills/total-recall/plugins/security/ui/chunks/source-review.md +21 -0
- package/scaffold/.agent/skills/total-recall/plugins/security/ui/chunks/ssh-permission-plan.md +17 -0
- package/scaffold/.agent/skills/total-recall/plugins/security/ui/home.js +283 -0
- package/scaffold/.agent/skills/total-recall/plugins/ssss/DESIGN.md +93 -0
- package/scaffold/.agent/skills/total-recall/plugins/ssss/package-lock.json +2 -2
- package/scaffold/.agent/skills/total-recall/plugins/ssss/package.json +2 -1
- package/scaffold/.agent/skills/total-recall/plugins/ssss/plugin.json +5 -3
- package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/chunks/conformance.md +26 -0
- package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/chunks/registry.md +37 -0
- package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/chunks/repair.md +42 -0
- package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/chunks/scaffold.md +33 -0
- package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/chunks/status.md +43 -0
- package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/chunks/validate.md +34 -0
- package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/chunks/validation-diagnostics.md +17 -0
- package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/chunks/workspace-registry-preflight.md +17 -0
- package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/home.js +348 -0
- package/scaffold/.agent/skills/total-recall/references/operations.md +2 -0
- package/src/cli/api.mjs +3 -3
- package/src/cli/brief.mjs +3 -0
- package/src/cli/config.mjs +16 -0
- package/src/cli/connect.mjs +2 -7
- package/src/cli/plugin/chunks.mjs +145 -0
- package/src/cli/plugin/create.mjs +24 -52
- package/src/cli/plugin/index.mjs +20 -9
- package/src/cli/setup.mjs +2 -9
- package/src/cli/start.mjs +1 -0
- package/src/cli/startup.mjs +18 -0
- package/src/core/app-deploy/design-tokens.mjs +14 -9
- package/src/core/app-deploy/ui-elements.mjs +1 -1
- package/src/core/brain-registry.mjs +5 -0
- package/src/core/brain-updates.mjs +5 -1
- package/src/core/daemon-control.mjs +5 -1
- package/src/core/dashboard-bundle.mjs +261 -0
- package/src/core/default-plugin-refresh.mjs +39 -0
- package/src/core/ensure-dependencies.mjs +19 -15
- package/src/core/memory-brain.mjs +30 -8
- package/src/core/plugin-activation.mjs +63 -20
- package/src/core/plugin-contracts/{card.mjs → manifest.mjs} +23 -57
- package/src/core/plugin-contracts/startup-check.mjs +49 -0
- package/src/core/plugin-contracts/ui.mjs +9 -3
- package/src/core/plugin-distribution.mjs +6 -6
- package/src/core/plugin-lifecycle.mjs +58 -0
- package/src/core/plugin-loader.mjs +9 -5
- package/src/core/plugin-runner.mjs +21 -10
- package/src/core/plugin-startup-checks.mjs +44 -0
- package/src/core/plugin-state.mjs +19 -5
- package/src/core/plugin-store.mjs +30 -11
- package/src/core/project-id.mjs +15 -5
- package/src/core/required-plugins.mjs +31 -6
- package/src/core/schema.mjs +2 -0
- package/src/core/ssss-operation-service.mjs +1 -0
- package/src/core/startup-health.mjs +28 -3
- package/src/core/testing/plugin-fixture.mjs +22 -21
- package/src/core/throttled-fetch.mjs +25 -18
- package/src/core/ui-chunk-choice.mjs +77 -0
- package/src/core/ui-chunk.registry.json +23 -0
- package/src/core/ui-chunks.mjs +434 -0
- package/src/core/vault-cache.mjs +58 -59
- package/src/core/workspace-compositions.mjs +151 -0
- package/src/core/workspace-drawers.mjs +79 -0
- package/src/server/api.mjs +4 -27
- package/src/server/index.mjs +28 -21
- package/src/server/memory-events.mjs +31 -0
- package/src/server/plugin-brain-targets.mjs +89 -0
- package/src/server/rest.mjs +2 -0
- package/src/server/route-inventory.mjs +3 -2
- package/src/server/route-manifest.json +52 -4
- package/src/server/routes/_shared.mjs +7 -14
- package/src/server/routes/brains.mjs +29 -44
- package/src/server/routes/dashboard.mjs +26 -0
- package/src/server/routes/plugins.mjs +154 -45
- package/src/server/routes/ui-chunks.mjs +192 -0
- package/frontend/dist/assets/index-DACh1dhx.js +0 -5613
- package/frontend/dist/assets/index-DtwsDyFM.css +0 -1
- package/frontend/src/components/plugins/card/CardEngine.tsx +0 -108
- package/frontend/src/components/plugins/card/CardScenes.tsx +0 -103
- package/frontend/src/components/plugins/card/ExecutionPicker.tsx +0 -64
- package/frontend/src/components/plugins/card/args.ts +0 -28
- package/frontend/src/components/plugins/card/card.css +0 -32
- package/frontend/src/components/plugins/card/cli-line.ts +0 -13
- package/frontend/src/components/plugins/card/contract.ts +0 -91
- package/frontend/src/components/plugins/card/format.ts +0 -49
- package/frontend/src/components/plugins/card/runner-context.ts +0 -11
- package/frontend/src/components/plugins/card/runner.tsx +0 -43
- package/frontend/src/components/plugins/card/theme.ts +0 -35
- package/frontend/src/components/plugins/card/use-source.ts +0 -22
- package/frontend/src/components/plugins/card/widgets.tsx +0 -94
- package/frontend/src/components/plugins/workspace/WorkspaceHost.tsx +0 -23
- package/frontend/src/pages/PluginsPage.tsx +0 -1719
- package/scaffold/.agent/skills/plugin/evals/cases/04-card-collects-credential.mjs +0 -47
- package/scaffold/.agent/skills/plugin/prompts/06-card.md +0 -46
- package/scaffold/.agent/skills/plugin/references/card.md +0 -90
- package/scaffold/.agent/skills/plugin/subagents/card-designer.md +0 -60
- package/scaffold/.agent/skills/total-recall/plugins/auth/ui/DESIGN.md +0 -67
- package/scaffold/.agent/skills/total-recall/plugins/auth/ui/card.js +0 -1179
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/DESIGN.md +0 -32
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/card.js +0 -588
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/card.js +0 -575
- package/scaffold/.agent/skills/total-recall/plugins/embeddings/ui/DESIGN.md +0 -32
- package/scaffold/.agent/skills/total-recall/plugins/embeddings/ui/card.js +0 -482
- package/scaffold/.agent/skills/total-recall/plugins/git/ui/DESIGN.md +0 -100
- package/scaffold/.agent/skills/total-recall/plugins/git/ui/card.js +0 -637
- package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/DESIGN.md +0 -217
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/DESIGN.md +0 -32
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/card.js +0 -1276
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/DESIGN.md +0 -45
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/card.js +0 -1401
- package/scaffold/.agent/skills/total-recall/plugins/security/scripts/build-ui.mjs +0 -4
- package/scaffold/.agent/skills/total-recall/plugins/security/ui/DESIGN.md +0 -41
- package/scaffold/.agent/skills/total-recall/plugins/security/ui/card.js +0 -396
- package/scaffold/.agent/skills/total-recall/plugins/security/ui/panel.js +0 -98
- package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/DESIGN.md +0 -15
- package/scaffold/.agent/skills/total-recall/plugins/ssss/ui/card.js +0 -182
|
@@ -31,8 +31,8 @@ import {
|
|
|
31
31
|
} from './plugin-bundle.mjs';
|
|
32
32
|
import { writeVfsDocument, patchVfsDocument, deleteVfsDocument, appendVfsEvent } from './ssss-operation-service.mjs';
|
|
33
33
|
import { findVfsDocumentByPath } from './vfs-documents.mjs';
|
|
34
|
-
import { readActivationRecord, projectActivationOverride } from './plugin-state.mjs';
|
|
35
|
-
import { REQUIRED_INSTALLATION_PLUGIN_IDS } from './default-plugins.mjs';
|
|
34
|
+
import { readActivationRecord, projectActivationOverride, pluginActivation } from './plugin-state.mjs';
|
|
35
|
+
import { DEFAULT_PLUGIN_IDS, REQUIRED_INSTALLATION_PLUGIN_IDS } from './default-plugins.mjs';
|
|
36
36
|
|
|
37
37
|
const execFileAsync = promisify(execFile);
|
|
38
38
|
const ID_PATTERN = /^[a-z][a-z0-9-]{1,63}$/;
|
|
@@ -183,7 +183,7 @@ export async function patchPluginRecord(plugin, patches) {
|
|
|
183
183
|
* setting so it follows the shared one again. The overlay never installs the
|
|
184
184
|
* plugin: a repository without it uses the shared folder's copy.
|
|
185
185
|
*/
|
|
186
|
-
export async function patchProjectActivationRecord(id, projectRoot, runtimeEnabled, { manifest = null } = {}) {
|
|
186
|
+
export async function patchProjectActivationRecord(id, projectRoot, runtimeEnabled, { manifest = null, onUse = false } = {}) {
|
|
187
187
|
if (!ID_PATTERN.test(id)) throw new Error('Invalid plugin identity');
|
|
188
188
|
const pluginsDir = projectPluginsDir(projectRoot);
|
|
189
189
|
const vaultRoot = vaultForPluginsDir(pluginsDir);
|
|
@@ -194,7 +194,7 @@ export async function patchProjectActivationRecord(id, projectRoot, runtimeEnabl
|
|
|
194
194
|
if (runtimeEnabled === null) {
|
|
195
195
|
const existing = readProjectActivationRecord(id, projectRoot);
|
|
196
196
|
if (!existing) return null;
|
|
197
|
-
const { runtime_enabled: _dropped, ...frontmatter } = { ...(existing.frontmatter || {}) };
|
|
197
|
+
const { runtime_enabled: _dropped, runtime_on_use: _onUse, ...frontmatter } = { ...(existing.frontmatter || {}) };
|
|
198
198
|
await writeVfsDocument(recordPath(id), {
|
|
199
199
|
...frontmatter,
|
|
200
200
|
type: 'plugin_record',
|
|
@@ -210,7 +210,7 @@ export async function patchProjectActivationRecord(id, projectRoot, runtimeEnabl
|
|
|
210
210
|
if (typeof runtimeEnabled !== 'boolean') throw new Error('Plugin activation requires a boolean or null');
|
|
211
211
|
const previous = readProjectActivationRecord(id, projectRoot);
|
|
212
212
|
if (previous) {
|
|
213
|
-
return patchVfsDocument(recordPath(id), { runtime_enabled: runtimeEnabled, timestamp: now }, {
|
|
213
|
+
return patchVfsDocument(recordPath(id), { runtime_enabled: runtimeEnabled, runtime_on_use: onUse, timestamp: now }, {
|
|
214
214
|
actorRole: 'system',
|
|
215
215
|
intent: `Set repository activation for plugin ${id}`,
|
|
216
216
|
vaultRoot
|
|
@@ -226,6 +226,7 @@ export async function patchProjectActivationRecord(id, projectRoot, runtimeEnabl
|
|
|
226
226
|
category: 'plugins',
|
|
227
227
|
tags: ['plugin', 'activation-override'],
|
|
228
228
|
runtime_enabled: runtimeEnabled,
|
|
229
|
+
runtime_on_use: onUse,
|
|
229
230
|
source: { kind: 'shared', ref: globalPluginsDir() }
|
|
230
231
|
};
|
|
231
232
|
await writeVfsDocument(recordPath(id), frontmatter, buildPluginDocumentBody(m, id), {
|
|
@@ -236,8 +237,19 @@ export async function patchProjectActivationRecord(id, projectRoot, runtimeEnabl
|
|
|
236
237
|
return frontmatter;
|
|
237
238
|
}
|
|
238
239
|
|
|
240
|
+
function describeActivation(plugin, projectRoot) {
|
|
241
|
+
const required = REQUIRED_INSTALLATION_PLUGIN_IDS.includes(plugin.id);
|
|
242
|
+
try {
|
|
243
|
+
const { state, enabled, mode } = pluginActivation(plugin, { projectRoot });
|
|
244
|
+
return { state, enabled, required, ...(mode ? { mode } : {}) };
|
|
245
|
+
} catch {
|
|
246
|
+
// An unreadable repository policy is an error, never shared enablement.
|
|
247
|
+
return { state: 'error', enabled: false, required };
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
239
251
|
/** Facts about one installed plugin, merged with its record. */
|
|
240
|
-
export function describePlugin(plugin) {
|
|
252
|
+
export function describePlugin(plugin, projectRoot = process.cwd()) {
|
|
241
253
|
const record = readPluginRecord(plugin);
|
|
242
254
|
const m = plugin.manifest || {};
|
|
243
255
|
let current = null;
|
|
@@ -248,6 +260,7 @@ export function describePlugin(plugin) {
|
|
|
248
260
|
const taskRuns = record?.task_runs || {};
|
|
249
261
|
return {
|
|
250
262
|
id: plugin.id,
|
|
263
|
+
core: DEFAULT_PLUGIN_IDS.includes(plugin.id),
|
|
251
264
|
name: m.name || plugin.id,
|
|
252
265
|
version: m.version || '0.0.0',
|
|
253
266
|
description: m.description || '',
|
|
@@ -284,13 +297,18 @@ export function describePlugin(plugin) {
|
|
|
284
297
|
ui: m.ui || null,
|
|
285
298
|
configuration: m.configuration || null,
|
|
286
299
|
manifest: m,
|
|
287
|
-
|
|
288
|
-
activation: { state: plugin.valid && record?.runtime_enabled !== false ? 'active' : 'inactive', enabled: plugin.valid && record?.runtime_enabled !== false }
|
|
300
|
+
activation: describeActivation(plugin, projectRoot)
|
|
289
301
|
};
|
|
290
302
|
}
|
|
291
303
|
|
|
292
|
-
export function listInstalledPlugins(projectRoot = process.cwd()) {
|
|
293
|
-
return discoverPlugins(projectRoot).map(
|
|
304
|
+
export function listInstalledPlugins(projectRoot = process.cwd(), { descriptions } = {}) {
|
|
305
|
+
return discoverPlugins(projectRoot).map(plugin => {
|
|
306
|
+
const description = descriptions?.get(plugin.dir);
|
|
307
|
+
if (description) return { ...description, activation: describeActivation(plugin, projectRoot) };
|
|
308
|
+
const result = describePlugin(plugin, projectRoot);
|
|
309
|
+
descriptions?.set(plugin.dir, result);
|
|
310
|
+
return result;
|
|
311
|
+
});
|
|
294
312
|
}
|
|
295
313
|
|
|
296
314
|
/** Bundled plugins shipped in the package, flagged with whether they are installed here. */
|
|
@@ -344,7 +362,8 @@ export async function recompileAfterPluginMutation(projectRoot = process.cwd(),
|
|
|
344
362
|
// read on demand at preflight, so a shared plugin change compiles no other repository
|
|
345
363
|
// (ON-DEMAND-CONTEXT-01; one install used to rebuild all registered brains).
|
|
346
364
|
await compileLayer(compileSurface, projectRoot, isGlobal);
|
|
347
|
-
|
|
365
|
+
// A shared change made from the dashboard's global brain has no repository to refresh.
|
|
366
|
+
if (isGlobal && projectRoot) {
|
|
348
367
|
// The repository the command ran in refreshes its own catalog now, so its plugin library
|
|
349
368
|
// never lags the change. That compile is cheap: entry files and vault indexes keep their
|
|
350
369
|
// own triggers, so only the catalog and CLI index move.
|
package/src/core/project-id.mjs
CHANGED
|
@@ -7,6 +7,8 @@ import fs from 'node:fs';
|
|
|
7
7
|
import path from 'node:path';
|
|
8
8
|
import { randomUUID } from 'node:crypto';
|
|
9
9
|
|
|
10
|
+
const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
|
|
11
|
+
|
|
10
12
|
function brainJsonPath(brainDir) {
|
|
11
13
|
return path.join(brainDir, 'config', 'brain.json');
|
|
12
14
|
}
|
|
@@ -35,21 +37,21 @@ export function readProjectId(brainDir) {
|
|
|
35
37
|
* Return the project's id, creating a random UUID on first use.
|
|
36
38
|
* @returns {{ project_id: string, created: boolean }}
|
|
37
39
|
*/
|
|
38
|
-
export function ensureProjectId(brainDir) {
|
|
40
|
+
export function ensureProjectId(brainDir, { fallbackId } = {}) {
|
|
39
41
|
const file = brainJsonPath(brainDir);
|
|
40
42
|
let cfg;
|
|
41
43
|
try { cfg = JSON.parse(fs.readFileSync(file, 'utf8')); }
|
|
42
44
|
catch (err) { if (err.code === 'ENOENT') cfg = {}; else throw new Error('Existing project identity is unreadable or malformed'); }
|
|
43
45
|
if (!cfg || typeof cfg !== 'object' || Array.isArray(cfg)) throw new Error('Existing project identity must be an object');
|
|
44
46
|
if (cfg.project_id) return { project_id: cfg.project_id, created: false };
|
|
45
|
-
cfg.project_id = randomUUID();
|
|
47
|
+
cfg.project_id = fallbackId || randomUUID();
|
|
46
48
|
writeJsonAtomic(file, cfg);
|
|
47
49
|
return { project_id: cfg.project_id, created: true };
|
|
48
50
|
}
|
|
49
51
|
|
|
50
52
|
/**
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
+
* Make the registry agree with each project's brain.json. If the disk identity
|
|
54
|
+
* is missing, preserve a unique valid UUID already published in the registry.
|
|
53
55
|
* @returns {{ total: number, created: number, synced: number, missing_brain: number }}
|
|
54
56
|
*/
|
|
55
57
|
export function repairProjectIds(globalBrainDir) {
|
|
@@ -57,13 +59,21 @@ export function repairProjectIds(globalBrainDir) {
|
|
|
57
59
|
const list = readJson(registryPath, []);
|
|
58
60
|
const out = { total: 0, created: 0, synced: 0, missing_brain: 0 };
|
|
59
61
|
if (!Array.isArray(list)) return out;
|
|
62
|
+
const owners = new Map();
|
|
63
|
+
for (const row of list) {
|
|
64
|
+
const onDisk = typeof row?.brainDir === 'string' ? readProjectId(row.brainDir) : null;
|
|
65
|
+
for (const id of new Set([row?.project_id, onDisk])) {
|
|
66
|
+
if (typeof id === 'string' && UUID.test(id)) owners.set(id, (owners.get(id) || 0) + 1);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
60
69
|
for (const row of list) {
|
|
61
70
|
out.total++;
|
|
62
71
|
if (!row?.brainDir || !fs.existsSync(row.brainDir)) {
|
|
63
72
|
out.missing_brain++;
|
|
64
73
|
continue;
|
|
65
74
|
}
|
|
66
|
-
const
|
|
75
|
+
const fallbackId = owners.get(row.project_id) === 1 ? row.project_id : undefined;
|
|
76
|
+
const { project_id, created } = ensureProjectId(row.brainDir, { fallbackId });
|
|
67
77
|
if (created) out.created++;
|
|
68
78
|
if (row.project_id !== project_id) {
|
|
69
79
|
row.project_id = project_id;
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
import fs from 'node:fs';
|
|
11
11
|
import path from 'node:path';
|
|
12
12
|
import { createRequire } from 'node:module';
|
|
13
|
-
import { readPluginsDir, globalPluginsDir, PACKAGE_ROOT, resolvePluginFile } from './plugin-loader.mjs';
|
|
13
|
+
import { readPluginsDir, globalPluginsDir, PACKAGE_ROOT, resolvePluginFile, validatePluginManifest } from './plugin-loader.mjs';
|
|
14
14
|
import { DEFAULT_PLUGIN_IDS, REQUIRED_INSTALLATION_PLUGIN_IDS } from './default-plugins.mjs';
|
|
15
15
|
import { comparePackageVersions } from './package-version.mjs';
|
|
16
16
|
import { preparePluginDependencies } from './plugin-dependencies.mjs';
|
|
@@ -113,14 +113,39 @@ export function inspectRequiredPlugins(brainDir, { pluginsDir, sharedBrainDir =
|
|
|
113
113
|
return { status: errors.length ? 'failed' : 'ready', errors, source, installations };
|
|
114
114
|
}
|
|
115
115
|
|
|
116
|
-
|
|
116
|
+
const LEGACY_PRESENTATION_FIELDS = ['card', 'card_face', 'card_layout'];
|
|
117
|
+
|
|
118
|
+
function hasLegacyPresentation(manifest) {
|
|
119
|
+
return LEGACY_PRESENTATION_FIELDS.some(field => Object.hasOwn(manifest, field))
|
|
120
|
+
|| (Array.isArray(manifest.ui?.elements) && manifest.ui.elements.some(element => ['card', 'card-face'].includes(element?.kind)));
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function hasPluginFiles(directory, files) {
|
|
124
|
+
return files.every(file => fs.statSync(resolvePluginFile(directory, file)).isFile());
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function runtimeFiles(manifest) {
|
|
128
|
+
return ['package.json', ...(manifest.cli ? [manifest.cli.handler] : []), ...Object.values(manifest.runtime?.modules || {})];
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/** Refresh older copies and migrate the retired presentation of an otherwise intact same-release copy. */
|
|
117
132
|
function isStaleInstall(target, source) {
|
|
118
133
|
try {
|
|
119
134
|
// A link is its owner's checkout. Replacing it would delete that repository's files, .git included.
|
|
120
135
|
if (fs.lstatSync(target).isSymbolicLink()) return false;
|
|
121
|
-
const installed = JSON.parse(fs.readFileSync(path.join(target, 'plugin.json'), 'utf8'))
|
|
122
|
-
const bundled = JSON.parse(fs.readFileSync(path.join(source, 'plugin.json'), 'utf8'))
|
|
123
|
-
|
|
136
|
+
const installed = JSON.parse(fs.readFileSync(path.join(target, 'plugin.json'), 'utf8'));
|
|
137
|
+
const bundled = JSON.parse(fs.readFileSync(path.join(source, 'plugin.json'), 'utf8'));
|
|
138
|
+
if (comparePackageVersions(installed.version, bundled.version) === -1) return true;
|
|
139
|
+
if (installed.version !== bundled.version || installed.id !== bundled.id || bundled.id !== path.basename(source)
|
|
140
|
+
|| installed.cli?.command !== bundled.cli?.command || !hasLegacyPresentation(installed)
|
|
141
|
+
|| hasLegacyPresentation(bundled) || !bundled.ui?.home || !validatePluginManifest(bundled).valid) return false;
|
|
142
|
+
|
|
143
|
+
const migrated = { ...installed, ui: bundled.ui };
|
|
144
|
+
for (const field of LEGACY_PRESENTATION_FIELDS) delete migrated[field];
|
|
145
|
+
if (!validatePluginManifest(migrated).valid || !hasPluginFiles(target, runtimeFiles(installed))) return false;
|
|
146
|
+
return hasPluginFiles(source, [
|
|
147
|
+
...runtimeFiles(bundled), bundled.ui.design_tokens, ...bundled.ui.elements.map(element => element.module),
|
|
148
|
+
]);
|
|
124
149
|
} catch { return false; }
|
|
125
150
|
}
|
|
126
151
|
|
|
@@ -165,7 +190,7 @@ function installDefaultsInto(brainDir, sourceDir) {
|
|
|
165
190
|
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
166
191
|
fs.cpSync(source, target, { recursive: true, force: false, errorOnExist: true });
|
|
167
192
|
} else if (isStaleInstall(target, source)) {
|
|
168
|
-
//
|
|
193
|
+
// Keep installed dependencies when refreshing the bundled plugin files.
|
|
169
194
|
for (const entry of fs.readdirSync(target)) if (entry !== 'node_modules') fs.rmSync(path.join(target, entry), { recursive: true, force: true });
|
|
170
195
|
for (const entry of fs.readdirSync(source)) if (entry !== 'node_modules') fs.cpSync(path.join(source, entry), path.join(target, entry), { recursive: true });
|
|
171
196
|
}
|
package/src/core/schema.mjs
CHANGED
|
@@ -1034,6 +1034,8 @@ export const PluginRecordSchema = z.object({
|
|
|
1034
1034
|
task_runs: z.record(z.string()).optional(),
|
|
1035
1035
|
/** Explicit mesh node for commands with selected-node placement. */
|
|
1036
1036
|
task_nodes: z.record(z.string().min(1)).optional(),
|
|
1037
|
+
runtime_enabled: z.boolean().optional(),
|
|
1038
|
+
runtime_on_use: z.boolean().optional(),
|
|
1037
1039
|
}).passthrough();
|
|
1038
1040
|
|
|
1039
1041
|
const SECRET_KEY_PATTERN = /^(.*_)?(secret|token|password|api[_-]?key|private[_-]?key|credentials|auth[_-]?header|bearer)$/i;
|
|
@@ -46,6 +46,7 @@ export function patchVfsDocument(vfsPath, patches, options = {}) {
|
|
|
46
46
|
type: 'patch',
|
|
47
47
|
...envelopeBase(vfsPath, options),
|
|
48
48
|
patches,
|
|
49
|
+
...(options.expectedBeforeHash === undefined ? {} : { expected_before_hash: options.expectedBeforeHash }),
|
|
49
50
|
}, options);
|
|
50
51
|
}
|
|
51
52
|
|
|
@@ -10,6 +10,23 @@ import { CLI_COMMANDS } from './cli-commands.mjs';
|
|
|
10
10
|
const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../..');
|
|
11
11
|
export const cliEntry = path.join(packageRoot, 'bin/total-recall.mjs');
|
|
12
12
|
|
|
13
|
+
/** Whether this package's dashboard bundle is as new as its frontend sources (the server rebuilds it). */
|
|
14
|
+
async function defaultDashboardCheck() {
|
|
15
|
+
try {
|
|
16
|
+
const { checkDistFreshness, dashboardTargets } = await import('./dashboard-bundle.mjs');
|
|
17
|
+
if (!fs.existsSync(path.join(packageRoot, 'frontend', 'package.json'))) return { status: 'not-shipped' };
|
|
18
|
+
const result = await checkDistFreshness(dashboardTargets(packageRoot));
|
|
19
|
+
const status = result.ok ? 'current' : result.reason === 'missing-bundle' ? 'missing' : 'stale';
|
|
20
|
+
return {
|
|
21
|
+
status,
|
|
22
|
+
...(result.bundle ? { built_at: new Date(result.bundle.mtimeMs).toISOString() } : {}),
|
|
23
|
+
...(!result.ok && result.source ? { newer_source: path.relative(packageRoot, result.source.path) } : {}),
|
|
24
|
+
};
|
|
25
|
+
} catch (error) {
|
|
26
|
+
return { status: 'unknown', reason: error.message };
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
13
30
|
export function runBounded(binary, args, { cwd = process.cwd(), timeoutMs = 15000, maxBytes = 262144 } = {}) {
|
|
14
31
|
return new Promise(resolve => {
|
|
15
32
|
let child, output = '', stderr = '', size = 0, reason = null, settled = false, timer, escalation;
|
|
@@ -81,8 +98,8 @@ export function processIdentity(pidFile, hint, { alive = pid => { try { process.
|
|
|
81
98
|
}
|
|
82
99
|
|
|
83
100
|
/** The single installation-aware daemon observation for status and lifecycle. */
|
|
84
|
-
export function observeDaemon(brainDir, { identity = processIdentity } = {}) {
|
|
85
|
-
const expected_entry =
|
|
101
|
+
export function observeDaemon(brainDir, { identity = processIdentity, expectedEntry = path.join(packageRoot, 'src', 'core', 'daemon-loop.mjs') } = {}) {
|
|
102
|
+
const expected_entry = expectedEntry;
|
|
86
103
|
return { ...identity(path.join(brainDir, 'daemon.pid'), expected_entry), expected_entry, source: 'local-pid' };
|
|
87
104
|
}
|
|
88
105
|
|
|
@@ -130,7 +147,8 @@ export async function fetchStartup(url, options = {}, fetchImpl = fetch) {
|
|
|
130
147
|
}
|
|
131
148
|
|
|
132
149
|
export async function startupHealth({ cwd = process.cwd(), brainDir, brainUrl = null, token = null, brainId = null, ensure = false,
|
|
133
|
-
appCheck = null, appStart = null, run = runBounded, fetchImpl = fetch, onDiskVersion = packageVersionOnDisk, listener = verifyListener, platform = process.platform, home = os.homedir(), identity = processIdentity
|
|
150
|
+
appCheck = null, appStart = null, run = runBounded, fetchImpl = fetch, onDiskVersion = packageVersionOnDisk, listener = verifyListener, platform = process.platform, home = os.homedir(), identity = processIdentity,
|
|
151
|
+
dashboardCheck = null, pluginChecks = null } = {}) {
|
|
134
152
|
const actions = [];
|
|
135
153
|
const serverFile = path.join(brainDir, 'server.pid');
|
|
136
154
|
const report = { checked_at: new Date().toISOString(), server: { status: 'not-configured' }, brain: { status: 'unknown' }, daemon: { status: 'unknown' },
|
|
@@ -235,6 +253,13 @@ export async function startupHealth({ cwd = process.cwd(), brainDir, brainUrl =
|
|
|
235
253
|
}
|
|
236
254
|
const { inspectRequiredPlugins } = await import('./required-plugins.mjs');
|
|
237
255
|
report.required_plugins = inspectRequiredPlugins(brainDir);
|
|
256
|
+
// Reported, not part of readiness: a stale dashboard or unfinished work still
|
|
257
|
+
// leaves the runtime usable, but neither may stay invisible.
|
|
258
|
+
report.dashboard = await (dashboardCheck ?? defaultDashboardCheck)();
|
|
259
|
+
report.plugin_checks = await (pluginChecks ?? (async () => {
|
|
260
|
+
const { runPluginStartupChecks } = await import('./plugin-startup-checks.mjs');
|
|
261
|
+
return runPluginStartupChecks({ cwd });
|
|
262
|
+
}))();
|
|
238
263
|
report.shared_ready = report.required_plugins.status === 'ready' && report.server.status === 'ready' && report.brain.status === 'ready' && report.daemon.status === 'running' && report.ssss.status === 'available';
|
|
239
264
|
report.ready_scope = appCheck ? 'shared-and-declared-current-repo-app' : 'shared-runtime-only';
|
|
240
265
|
report.ready = report.shared_ready && (!appCheck || report.app.status === 'ready');
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Fixture manifests for specs that exercise plumbing rather than
|
|
2
|
+
* Fixture manifests for specs that exercise plumbing rather than Home design.
|
|
3
3
|
*
|
|
4
|
-
* Every real plugin has a bespoke
|
|
4
|
+
* Every real plugin has a bespoke native Home declared in `ui.elements[]`, and the
|
|
5
5
|
* validator enforces it. Specs that install, copy, vendor, discover or compile a
|
|
6
6
|
* plugin still need a manifest that satisfies that contract, or they fail on a
|
|
7
|
-
* rule they are not testing. This module supplies
|
|
7
|
+
* rule they are not testing. This module supplies a minimal native Home so
|
|
8
8
|
* those specs keep asserting what they mean to assert.
|
|
9
9
|
*
|
|
10
|
-
* The
|
|
10
|
+
* The Home here is deliberately generic and exists only in tests. Production
|
|
11
11
|
* plugin UI is always hand-authored per plugin (invariants-b6e8fcac).
|
|
12
12
|
*/
|
|
13
13
|
import fs from 'node:fs';
|
|
@@ -16,45 +16,46 @@ import path from 'node:path';
|
|
|
16
16
|
const nodeFs = fs;
|
|
17
17
|
const nodePath = path;
|
|
18
18
|
|
|
19
|
-
/** The smallest valid
|
|
20
|
-
export const
|
|
19
|
+
/** The smallest valid native Home. Declared once, as every plugin declares one. */
|
|
20
|
+
export const FIXTURE_HOME = Object.freeze({
|
|
21
|
+
home: 'home',
|
|
21
22
|
design_tokens: 'ui/DESIGN.md',
|
|
22
23
|
elements: [
|
|
23
24
|
{
|
|
24
|
-
id: '
|
|
25
|
-
kind: '
|
|
26
|
-
tag: 'tr-fixture-
|
|
27
|
-
module: 'ui/
|
|
28
|
-
description: 'Fixture
|
|
25
|
+
id: 'home',
|
|
26
|
+
kind: 'panel',
|
|
27
|
+
tag: 'tr-fixture-home',
|
|
28
|
+
module: 'ui/home.js',
|
|
29
|
+
description: 'Fixture native Home',
|
|
29
30
|
},
|
|
30
31
|
],
|
|
31
32
|
});
|
|
32
33
|
|
|
33
|
-
/** Source of the element module referenced by
|
|
34
|
-
export const
|
|
34
|
+
/** Source of the element module referenced by FIXTURE_HOME. */
|
|
35
|
+
export const FIXTURE_HOME_SOURCE = 'export const tag = "tr-fixture-home";\n';
|
|
35
36
|
|
|
36
37
|
/**
|
|
37
|
-
* Merge a
|
|
38
|
+
* Merge a native Home into a fixture manifest.
|
|
38
39
|
*
|
|
39
|
-
* Pass `ui: null` to omit the
|
|
40
|
+
* Pass `ui: null` to omit the Home deliberately, e.g. when asserting that a
|
|
40
41
|
* plugin without one is rejected.
|
|
41
42
|
*/
|
|
42
|
-
export function
|
|
43
|
+
export function withFixtureHome(manifest = {}) {
|
|
43
44
|
if (manifest.ui === null) {
|
|
44
45
|
const { ui: _omitted, ...rest } = manifest;
|
|
45
46
|
return rest;
|
|
46
47
|
}
|
|
47
|
-
return { ...manifest, ui: manifest.ui ?? { ...
|
|
48
|
+
return { ...manifest, ui: manifest.ui ?? { ...FIXTURE_HOME } };
|
|
48
49
|
}
|
|
49
50
|
|
|
50
51
|
/**
|
|
51
|
-
* Write `plugin.json` for a fixture plugin, declaring a
|
|
52
|
+
* Write `plugin.json` for a fixture plugin, declaring a Home unless the manifest
|
|
52
53
|
* explicitly opts out with `ui: null`.
|
|
53
54
|
*
|
|
54
55
|
* Returns the manifest that was written.
|
|
55
56
|
*/
|
|
56
57
|
export function writeFixturePlugin(pluginDir, manifest, { fs = nodeFs, path = nodePath } = {}) {
|
|
57
|
-
const written =
|
|
58
|
+
const written = withFixtureHome(manifest);
|
|
58
59
|
nodeFs.writeFileSync(
|
|
59
60
|
nodePath.join(pluginDir, 'plugin.json'),
|
|
60
61
|
JSON.stringify(written, null, 2),
|
|
@@ -62,8 +63,8 @@ export function writeFixturePlugin(pluginDir, manifest, { fs = nodeFs, path = no
|
|
|
62
63
|
if (written.ui?.elements?.length) {
|
|
63
64
|
const uiDir = nodePath.join(pluginDir, 'ui');
|
|
64
65
|
nodeFs.mkdirSync(uiDir, { recursive: true });
|
|
65
|
-
nodeFs.writeFileSync(nodePath.join(uiDir, '
|
|
66
|
-
nodeFs.writeFileSync(nodePath.join(uiDir, 'DESIGN.md'), '# Fixture
|
|
66
|
+
nodeFs.writeFileSync(nodePath.join(uiDir, 'home.js'), FIXTURE_HOME_SOURCE);
|
|
67
|
+
nodeFs.writeFileSync(nodePath.join(uiDir, 'DESIGN.md'), '# Fixture Home\n');
|
|
67
68
|
}
|
|
68
69
|
return written;
|
|
69
70
|
}
|
|
@@ -135,31 +135,38 @@ export async function loadFirewallPolicy(brainDir) {
|
|
|
135
135
|
|
|
136
136
|
applyPolicy();
|
|
137
137
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
138
|
+
const watch = (target, onChange, clear) => {
|
|
139
|
+
try {
|
|
140
|
+
const watcher = fs.watch(target, onChange);
|
|
141
|
+
watcher.on('error', error => {
|
|
142
|
+
watcher.close();
|
|
143
|
+
clear(watcher);
|
|
144
|
+
logger.warn('throttled-fetch', `Network policy watcher unavailable: ${error.message}`);
|
|
145
|
+
});
|
|
146
|
+
watcher.unref();
|
|
147
|
+
return watcher;
|
|
148
|
+
} catch (error) {
|
|
149
|
+
logger.warn('throttled-fetch', `Network policy watcher unavailable: ${error.message}`);
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
const watchPolicy = () => {
|
|
154
|
+
if (policyWatcher || !fs.existsSync(policyPath)) return;
|
|
155
|
+
policyWatcher = watch(policyPath, event => {
|
|
156
|
+
if (event === 'change') applyPolicy();
|
|
157
|
+
}, watcher => { if (policyWatcher === watcher) policyWatcher = null; });
|
|
158
|
+
};
|
|
159
|
+
watchPolicy();
|
|
147
160
|
|
|
148
161
|
// Also watch the parent directory so we pick up the policy file being
|
|
149
162
|
// created after boot (e.g. first-run setups where the doc doesn't exist
|
|
150
163
|
// yet). Attach the direct file watcher once it appears.
|
|
151
164
|
if (!parentWatcher && fs.existsSync(systemDir)) {
|
|
152
|
-
parentWatcher =
|
|
165
|
+
parentWatcher = watch(systemDir, (_event, filename) => {
|
|
153
166
|
if (filename !== 'network-policy.md') return;
|
|
154
167
|
applyPolicy();
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
if (evt === 'change') applyPolicy();
|
|
158
|
-
});
|
|
159
|
-
policyWatcher.unref();
|
|
160
|
-
}
|
|
161
|
-
});
|
|
162
|
-
parentWatcher.unref();
|
|
168
|
+
watchPolicy();
|
|
169
|
+
}, watcher => { if (parentWatcher === watcher) parentWatcher = null; });
|
|
163
170
|
}
|
|
164
171
|
} catch (err) {
|
|
165
172
|
logger.error('throttled-fetch', `Failed to load network policy: ${err.message}`);
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { getPluginById } from './plugin-loader.mjs';
|
|
2
|
+
import { pluginActivation } from './plugin-state.mjs';
|
|
3
|
+
|
|
4
|
+
const decisionLimit = 20;
|
|
5
|
+
|
|
6
|
+
async function requestChoice(state, questions, { projectRoot = process.cwd(), brainDir } = {}) {
|
|
7
|
+
const plugin = getPluginById('decision', projectRoot);
|
|
8
|
+
if (!plugin?.valid || !pluginActivation(plugin, { projectRoot }).enabled ||
|
|
9
|
+
!plugin.manifest.cli?.subcommands?.some(command => command.name === 'run')) return null;
|
|
10
|
+
const { runPluginCommand } = await import('./plugin-runner.mjs');
|
|
11
|
+
const run = await runPluginCommand(plugin, {
|
|
12
|
+
subcommand: 'run',
|
|
13
|
+
args: ['--state', JSON.stringify(state), '--questions', JSON.stringify(questions), '--json'],
|
|
14
|
+
timeoutMs: 15_000,
|
|
15
|
+
cwd: projectRoot ?? brainDir ?? process.cwd(),
|
|
16
|
+
projectRoot,
|
|
17
|
+
});
|
|
18
|
+
if ((!run.ok && run.exitCode !== 4) || run.truncated) return null;
|
|
19
|
+
return JSON.parse(run.stdout);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export async function chooseUiChunk(chunks, query, surface, decide = requestChoice) {
|
|
23
|
+
const result = await chooseBlocks(chunks, query, surface, ['selected_chunk'], decide);
|
|
24
|
+
const { keys, ...selection } = result;
|
|
25
|
+
return { ...selection, key: keys[0] ?? null };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export async function chooseUiComposition(chunks, query, decide, target) {
|
|
29
|
+
const choose = decide ?? ((state, questions) => requestChoice(state, questions, target));
|
|
30
|
+
return chooseBlocks(chunks, query, 'page', ['selected_chunk', 'supporting_chunk', 'reference_chunk'], choose, false);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const instructions = {
|
|
34
|
+
selected_chunk: 'Choose the primary block that best accomplishes the requested intent.',
|
|
35
|
+
supporting_chunk: 'Choose an additional block that helps accomplish the same task without repeating the primary block.',
|
|
36
|
+
reference_chunk: 'Choose an optional readout or reference block that gives useful context for the task.',
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
async function chooseBlocks(chunks, query, surface, slots, decide, skipSingle = true) {
|
|
40
|
+
const shortlist = chunks.slice(0, decisionLimit);
|
|
41
|
+
if (!shortlist.length) return { source: 'lexical', keys: [], reason: 'no-matches' };
|
|
42
|
+
const fallback = { source: 'lexical', keys: shortlist.slice(0, slots.length).map(chunk => chunk.key) };
|
|
43
|
+
if (skipSingle && shortlist.length === 1) return { ...fallback, reason: 'single-match' };
|
|
44
|
+
|
|
45
|
+
const criteria = Object.fromEntries(shortlist.map(chunk => {
|
|
46
|
+
const description = [chunk.title, chunk.description, ...chunk.intents, ...(chunk.operations || []), ...(chunk.data || [])].join(' ').slice(0, 600);
|
|
47
|
+
return [chunk.key, description];
|
|
48
|
+
}));
|
|
49
|
+
criteria.none = 'No eligible chunk fits this intent.';
|
|
50
|
+
const questions = Object.fromEntries(slots.slice(0, shortlist.length).map(slot => [slot, {
|
|
51
|
+
type: 'choice',
|
|
52
|
+
instructions: `${instructions[slot]} Choose none when nothing fits.`,
|
|
53
|
+
criteria,
|
|
54
|
+
}]));
|
|
55
|
+
let result;
|
|
56
|
+
try {
|
|
57
|
+
result = await decide({ intent: query, surface: surface ?? null }, questions);
|
|
58
|
+
} catch {
|
|
59
|
+
return { ...fallback, reason: 'decision-unavailable' };
|
|
60
|
+
}
|
|
61
|
+
if (result?.ok !== true) return { ...fallback, reason: 'decision-unavailable' };
|
|
62
|
+
const eligible = new Set(shortlist.map(chunk => chunk.key));
|
|
63
|
+
const primary = result.answers?.selected_chunk;
|
|
64
|
+
if (!confident(primary)) return { ...fallback, reason: 'decision-abstained' };
|
|
65
|
+
if (primary.choice === 'none') return { source: 'decision', keys: [], reason: 'no-fit', confidence: primary.confidence };
|
|
66
|
+
if (!eligible.has(primary.choice)) return { source: 'decision', keys: [], reason: 'invalid-choice' };
|
|
67
|
+
const keys = new Set([primary.choice]);
|
|
68
|
+
for (const slot of Object.keys(questions).slice(1)) {
|
|
69
|
+
const answer = result.answers?.[slot];
|
|
70
|
+
if (confident(answer) && eligible.has(answer.choice)) keys.add(answer.choice);
|
|
71
|
+
}
|
|
72
|
+
return { source: 'decision', keys: [...keys], confidence: primary.confidence };
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function confident(answer) {
|
|
76
|
+
return answer?.act === true && Number.isFinite(answer.confidence) && answer.confidence >= 0.5 && answer.confidence <= 1;
|
|
77
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"registry": "ui-chunk",
|
|
3
|
+
"extends": "ssss",
|
|
4
|
+
"version": "1.1.0",
|
|
5
|
+
"description": "Portable owner-authored HTML chunks for Total Recall workspace surfaces.",
|
|
6
|
+
"document_primitives": {
|
|
7
|
+
"chunk": {
|
|
8
|
+
"family": "capability",
|
|
9
|
+
"append_only": false,
|
|
10
|
+
"portability": "structural",
|
|
11
|
+
"filename_convention": "A kebab-case chunk ID under ui/chunks/ with the .md extension.",
|
|
12
|
+
"required_fields": ["type", "title", "description", "timestamp", "plugin", "id", "intents", "surfaces"],
|
|
13
|
+
"optional_fields": ["panel", "operations", "data"],
|
|
14
|
+
"immutable_fields": ["plugin", "id"],
|
|
15
|
+
"enums": { "surfaces": ["page", "left", "right", "bottom"] },
|
|
16
|
+
"patterns": {
|
|
17
|
+
"plugin": "^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$",
|
|
18
|
+
"id": "^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$"
|
|
19
|
+
},
|
|
20
|
+
"notes": "The body holds HTML. The host validates surface membership, file ownership and native panel bindings before publishing the catalog."
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|