total-recall-brain 3.44.0 → 3.46.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/total-recall.mjs +10 -6
- package/docs/ARCHITECTURE.md +10 -7
- package/docs/reference/cli-reference.md +13 -8
- 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 +185 -238
- 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 +7 -7
- 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/src/cli-secret.mjs +20 -1
- package/scaffold/.agent/skills/total-recall/plugins/auth/src/secrets-store.mjs +12 -1
- 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/BRICK.md +7 -0
- package/scaffold/.agent/skills/total-recall/plugins/automations/DESIGN.md +53 -0
- package/scaffold/.agent/skills/total-recall/plugins/automations/LICENSE +21 -0
- package/scaffold/.agent/skills/total-recall/plugins/automations/README.md +66 -0
- package/scaffold/.agent/skills/total-recall/plugins/automations/adapters.mjs +247 -0
- package/scaffold/.agent/skills/total-recall/plugins/automations/capability/index.mjs +16 -0
- package/scaffold/.agent/skills/total-recall/plugins/automations/cli.mjs +130 -0
- package/{src/core/plugin-cron.mjs → scaffold/.agent/skills/total-recall/plugins/automations/cron.mjs} +1 -3
- package/scaffold/.agent/skills/total-recall/plugins/automations/inventory.mjs +88 -0
- package/scaffold/.agent/skills/total-recall/plugins/automations/package-lock.json +7661 -0
- package/scaffold/.agent/skills/total-recall/plugins/automations/package.json +36 -0
- package/scaffold/.agent/skills/total-recall/plugins/automations/plugin.json +151 -0
- package/scaffold/.agent/skills/total-recall/plugins/automations/scheduler.mjs +246 -0
- package/scaffold/.agent/skills/total-recall/plugins/automations/ui/automations.js +2 -0
- 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/home.js +278 -0
- 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 +5 -3
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/core/check.mjs +61 -7
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/core/report-data.mjs +40 -14
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/core/report.mjs +15 -40
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/package-lock.json +7 -7
- 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 +7 -7
- 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 +7 -7
- 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 +136 -0
- package/scaffold/.agent/skills/total-recall/plugins/{git-sentinel → git}/cli.mjs +140 -24
- package/scaffold/.agent/skills/total-recall/plugins/{git-sentinel → git}/package-lock.json +9 -9
- package/scaffold/.agent/skills/total-recall/plugins/{git-sentinel → git}/package.json +4 -2
- package/scaffold/.agent/skills/total-recall/plugins/git/plugin.json +151 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/src/lib/context.mjs +94 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/src/lib/phase3-spec-support.mjs +50 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/src/lib/runtime.mjs +40 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/src/lib/spec-support.mjs +51 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/_support.mjs +195 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/auth.mjs +201 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/bisect.mjs +40 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/cli-meta.mjs +159 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/commit-memory.mjs +54 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/commit.mjs +46 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/fleet.mjs +174 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/force-push.mjs +58 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/group.mjs +119 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/handoff.mjs +59 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/message.mjs +22 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/resolve.mjs +60 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/rules.mjs +81 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/secret-firewall.mjs +92 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/undo.mjs +156 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/unmerged.mjs +182 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/why.mjs +16 -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 +7 -7
- 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 +44 -9
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/capability/BRICK.md +1 -1
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/capability/index.mjs +18 -6
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/cli.mjs +128 -24
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/package-lock.json +7 -7
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/package.json +3 -2
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/plugin.json +188 -34
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/skills/meta-harness/SKILL.md +17 -3
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/adoption.mjs +2 -2
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/alerts.mjs +3 -3
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/cascade.mjs +92 -18
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/chat.mjs +80 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/control.mjs +145 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/coordinator.mjs +42 -21
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/dispatch-request.mjs +4 -2
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/dispatch.mjs +33 -9
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/documentation.mjs +55 -11
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/executor.mjs +26 -4
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/gate-adapters/hermes.mjs +29 -1
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/gate-adapters/index.mjs +1 -1
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/included-usage.mjs +1 -1
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/jobs.mjs +84 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/learner.mjs +3 -12
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/maintenance.mjs +17 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/mcp-server.mjs +228 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/process-manager.mjs +25 -2
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/reasoning.mjs +1 -1
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/remote-operation.mjs +5 -1
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/review.mjs +34 -3
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/reviews.mjs +25 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/router.mjs +1 -1
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/session/claude.mjs +319 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/session/codex.mjs +387 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/session/result.mjs +67 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/session/resume.mjs +373 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/session/run.mjs +223 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/session-jobs.mjs +72 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/setup.mjs +6 -3
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/termination.mjs +16 -12
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/threads.mjs +32 -1
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/usage-queue.mjs +1 -1
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/verify-ssss.mjs +3 -3
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/worker.mjs +285 -40
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/worktree.mjs +76 -9
- 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 +64 -32
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/package-lock.json +7 -7
- 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-diagnostics.mjs +44 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/refresh.mjs +123 -113
- 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 +7 -7
- 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 +3 -1
- package/src/cli/agent.mjs +1 -1
- package/src/cli/api.mjs +3 -3
- package/src/cli/brief.mjs +3 -0
- package/src/cli/command.mjs +41 -2
- package/src/cli/config.mjs +16 -0
- package/src/cli/connect.mjs +2 -7
- package/src/cli/dream.mjs +93 -69
- package/src/cli/harness.mjs +4 -4
- package/src/cli/help.mjs +1 -1
- package/src/cli/init.mjs +0 -25
- package/src/cli/lessons.mjs +51 -0
- package/src/cli/memory-plugin.mjs +1 -1
- package/src/cli/plugin/chunks.mjs +145 -0
- package/src/cli/plugin/copies.mjs +64 -14
- package/src/cli/plugin/create.mjs +30 -59
- package/src/cli/plugin/index.mjs +31 -16
- package/src/cli/plugin/install.mjs +10 -15
- package/src/cli/plugin/remove.mjs +1 -1
- package/src/cli/plugin/search.mjs +2 -2
- package/src/cli/preflight.mjs +19 -6
- package/src/cli/proposals.mjs +1 -1
- package/src/cli/recall.mjs +66 -23
- package/src/cli/remember.mjs +3 -14
- package/src/cli/server.mjs +18 -0
- package/src/cli/setup.mjs +2 -9
- package/src/cli/start.mjs +1 -0
- package/src/cli/startup.mjs +19 -0
- package/src/cli/task.mjs +9 -2
- package/src/cli/update.mjs +6 -2
- package/src/core/access-ledger.mjs +78 -0
- package/src/core/agent-manager.mjs +2 -2
- package/src/core/app-deploy/design-tokens.mjs +14 -9
- package/src/core/app-deploy/ui-elements.mjs +1 -1
- package/src/core/brain-locate.mjs +15 -0
- package/src/core/brain-registry.mjs +5 -0
- package/src/core/brain-updates.mjs +35 -11
- package/src/core/claude-hooks.mjs +3 -1
- package/src/core/cleanup-task.mjs +15 -0
- package/src/core/cli-commands.mjs +2 -0
- package/src/core/cli-maintenance.mjs +4 -1
- package/src/core/cli-semantic-index.mjs +23 -3
- package/src/core/context-compiler.mjs +20 -0
- package/src/core/daemon-control.mjs +5 -1
- package/src/core/daemon-loop.mjs +39 -62
- package/src/core/dashboard-bundle.mjs +261 -0
- package/src/core/default-plugins.mjs +1 -1
- package/src/core/dream.mjs +33 -105
- package/src/core/ensure-dependencies.mjs +152 -0
- package/src/core/fast-recall.mjs +2 -2
- package/src/core/field-evaluation.mjs +23 -0
- package/src/core/gate-mode.mjs +1 -1
- package/src/core/harness-hooks.mjs +14 -2
- package/src/core/lesson-hooks.mjs +74 -0
- package/src/core/lesson-memory.mjs +24 -0
- package/src/core/lesson-sessions.mjs +52 -0
- package/src/core/lessons.mjs +96 -0
- package/src/core/memory-brain.mjs +30 -8
- package/src/core/meta-harness.mjs +2 -2
- package/src/core/optimizer.mjs +66 -165
- package/src/core/plugin-activation.mjs +63 -20
- package/src/core/plugin-contracts/{card.mjs → manifest.mjs} +26 -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 +21 -8
- package/src/core/plugin-runner.mjs +21 -10
- package/src/core/plugin-runtime.mjs +40 -1
- package/src/core/plugin-startup-checks.mjs +44 -0
- package/src/core/plugin-state.mjs +19 -5
- package/src/core/plugin-store.mjs +64 -33
- package/src/core/post-mortem.mjs +52 -36
- package/src/core/preflight-gate.mjs +23 -2
- package/src/core/project-id.mjs +15 -5
- package/src/core/proposal-applier.mjs +31 -2
- package/src/core/repo-sync.mjs +4 -6
- package/src/core/required-plugins.mjs +57 -10
- package/src/core/rule-length.mjs +23 -0
- package/src/core/runtime.mjs +1 -1
- package/src/core/scheduler.mjs +35 -43
- package/src/core/schema.mjs +3 -2
- package/src/core/search.mjs +4 -3
- package/src/core/server-service.mjs +148 -0
- package/src/core/session-watcher.mjs +19 -1
- package/src/core/skill-gap.mjs +16 -0
- package/src/core/ssss-kernel-bridge.mjs +32 -4
- package/src/core/ssss-operation-service.mjs +1 -0
- package/src/core/startup-health.mjs +34 -4
- package/src/core/surface.mjs +65 -54
- package/src/core/task-executors.mjs +54 -106
- 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/validated-write.mjs +1 -0
- package/src/core/vault-cache.mjs +58 -59
- package/src/core/vector-field.mjs +134 -192
- 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/invoke-core-child.mjs +24 -0
- package/src/server/invoke-core-operations.mjs +102 -0
- 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 +47 -55
- package/src/server/routes/_shared.mjs +7 -14
- package/src/server/routes/brains.mjs +29 -62
- package/src/server/routes/context.mjs +0 -41
- package/src/server/routes/dashboard.mjs +26 -0
- package/src/server/routes/invoke.mjs +26 -1
- package/src/server/routes/plugins.mjs +154 -45
- package/src/server/routes/ssss.mjs +0 -169
- package/src/server/routes/system.mjs +0 -15
- package/src/server/routes/tasks.mjs +0 -26
- package/src/server/routes/ui-chunks.mjs +192 -0
- package/src/server/routes/vault.mjs +2 -23
- package/frontend/dist/assets/index-DD4qONvH.js +0 -5607
- 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-sentinel/README.md +0 -53
- package/scaffold/.agent/skills/total-recall/plugins/git-sentinel/plugin.json +0 -129
- package/scaffold/.agent/skills/total-recall/plugins/git-sentinel/ui/DESIGN.md +0 -100
- package/scaffold/.agent/skills/total-recall/plugins/git-sentinel/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
- package/src/core/append-log.mjs +0 -131
- package/src/core/plugin-tasks.mjs +0 -173
- package/templates/onboarding-interview.md +0 -82
- /package/scaffold/.agent/skills/total-recall/plugins/{git-sentinel → git}/LICENSE +0 -0
|
@@ -20,11 +20,13 @@
|
|
|
20
20
|
|
|
21
21
|
import fs from 'node:fs';
|
|
22
22
|
import path from 'node:path';
|
|
23
|
-
import {
|
|
24
|
-
import { getEmbedding,
|
|
23
|
+
import { loadNodes } from './vault.mjs';
|
|
24
|
+
import { getEmbedding, loadEmbeddingsIndex } from './embeddings.mjs';
|
|
25
25
|
import { inferMemoryLayer } from './memory-layers.mjs';
|
|
26
26
|
import { logger } from './logger.mjs';
|
|
27
27
|
import { brainDir } from './config.mjs';
|
|
28
|
+
import { readAccess, recordAccess, lastUsedMs, activeDays, activeDaysSince } from './access-ledger.mjs';
|
|
29
|
+
import { atomicWrite } from './vault-files.mjs';
|
|
28
30
|
|
|
29
31
|
const DERIVED_DIR = path.join(brainDir, 'memory-derived');
|
|
30
32
|
|
|
@@ -32,10 +34,6 @@ function fieldPath(derivedDir = DERIVED_DIR) {
|
|
|
32
34
|
return path.join(derivedDir, 'vector-field.json');
|
|
33
35
|
}
|
|
34
36
|
|
|
35
|
-
function queryLogPath(derivedDir = DERIVED_DIR) {
|
|
36
|
-
return path.join(derivedDir, 'query-log.jsonl');
|
|
37
|
-
}
|
|
38
|
-
|
|
39
37
|
const LN2 = Math.log(2);
|
|
40
38
|
|
|
41
39
|
// ─── Half-Life Constants (milliseconds) ─────────────────────────────────────
|
|
@@ -74,12 +72,14 @@ const HALF_LIFE_TABLE = {
|
|
|
74
72
|
*/
|
|
75
73
|
function computeHalfLife(node) {
|
|
76
74
|
// Priority overrides category
|
|
77
|
-
if (node.priority === 'absolute') return Infinity;
|
|
75
|
+
if (node.priority === 'absolute' || HALF_LIFE_TABLE[node.category] === Infinity) return Infinity;
|
|
76
|
+
const configuredDays = Number(node.decay?.half_life_days);
|
|
77
|
+
const categoryHL = configuredDays > 0 ? configuredDays * 86400000 :
|
|
78
|
+
(HALF_LIFE_TABLE[node.category] || HALF_LIFE_TABLE.fact);
|
|
78
79
|
if (node.priority === 'high') {
|
|
79
|
-
const categoryHL = HALF_LIFE_TABLE[node.category] || HALF_LIFE_TABLE.fact;
|
|
80
80
|
return Math.max(categoryHL, HALF_LIFE_TABLE._high);
|
|
81
81
|
}
|
|
82
|
-
return
|
|
82
|
+
return categoryHL;
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
/**
|
|
@@ -120,7 +120,7 @@ function computeNovelty(accessCount) {
|
|
|
120
120
|
/**
|
|
121
121
|
* Compile the full vector field from the vault.
|
|
122
122
|
*
|
|
123
|
-
* 1.
|
|
123
|
+
* 1. Read existing active-node embeddings → position vectors
|
|
124
124
|
* 2. Compute half-life, trajectory, novelty per point
|
|
125
125
|
* 3. Compute full pairwise covariance → coupling matrix
|
|
126
126
|
* 4. Extract dependency graph
|
|
@@ -128,133 +128,97 @@ function computeNovelty(accessCount) {
|
|
|
128
128
|
*/
|
|
129
129
|
export async function compileField({ vaultDir, derivedDir = DERIVED_DIR } = {}) {
|
|
130
130
|
const startTime = Date.now();
|
|
131
|
-
const allNodes =
|
|
131
|
+
const allNodes = loadNodes(vaultDir || path.join(brainDir, 'memory-vault')).filter(n => n.status === 'active');
|
|
132
132
|
const totalNodes = allNodes.length;
|
|
133
133
|
const now = Date.now();
|
|
134
134
|
|
|
135
135
|
logger.info('vector-field', `Compiling field from ${totalNodes} nodes...`);
|
|
136
136
|
|
|
137
|
-
|
|
138
|
-
const queryHistory = loadQueryHistory(derivedDir);
|
|
137
|
+
const ledger = readAccess(derivedDir);
|
|
139
138
|
|
|
140
|
-
// ── Phase 1:
|
|
141
|
-
const existingIndex = loadEmbeddingsIndex(derivedDir);
|
|
139
|
+
// ── Phase 1: Read stored vectors and compute physics ──
|
|
140
|
+
const existingIndex = fs.existsSync(path.join(derivedDir, 'embeddings.db')) ? loadEmbeddingsIndex(derivedDir) : {};
|
|
142
141
|
const points = [];
|
|
143
|
-
const newlyEmbedded = new Map();
|
|
144
|
-
let embedded = 0;
|
|
145
142
|
let cached = 0;
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
let embedding;
|
|
157
|
-
if (existingIndex[node.slug]?.embedding) {
|
|
158
|
-
embedding = existingIndex[node.slug].embedding;
|
|
159
|
-
cached++;
|
|
160
|
-
} else {
|
|
161
|
-
try {
|
|
162
|
-
embedding = await getEmbedding(text);
|
|
163
|
-
newlyEmbedded.set(node.slug, embedding);
|
|
164
|
-
embedded++;
|
|
165
|
-
} catch (err) {
|
|
166
|
-
logger.error('vector-field', `Failed to embed ${node.slug}: ${err.message}`);
|
|
167
|
-
continue;
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
// ── Physics computation ──
|
|
172
|
-
const decay = node.decay || {};
|
|
173
|
-
const accessCount = decay.access_count || 0;
|
|
174
|
-
const lastAccessed = node.last_accessed ? new Date(node.last_accessed).getTime() : 0;
|
|
175
|
-
const createdAt = node.created ? new Date(node.created).getTime() : now;
|
|
176
|
-
const ageMs = now - createdAt;
|
|
177
|
-
|
|
178
|
-
// Half-life
|
|
179
|
-
const halfLife = computeHalfLife(node);
|
|
180
|
-
const lambda = decayConstant(halfLife);
|
|
181
|
-
|
|
182
|
-
// Velocity: dR/dt from query log
|
|
183
|
-
const { velocity, trajectory } = computeTrajectory(node.slug, queryHistory, now);
|
|
184
|
-
|
|
185
|
-
// Novelty
|
|
186
|
-
const novelty = computeNovelty(accessCount);
|
|
187
|
-
|
|
188
|
-
// Peak relevance (baseline from importance + priority)
|
|
189
|
-
const importanceWeight = (node.importance || 3) / 5;
|
|
190
|
-
const priorityWeight = node.priority === 'absolute' ? 1.0 : node.priority === 'high' ? 0.8 : node.priority === 'normal' ? 0.5 : 0.3;
|
|
191
|
-
const peakRelevance = Math.max(importanceWeight, priorityWeight);
|
|
192
|
-
|
|
193
|
-
// Time since last access (for decay computation at sample time)
|
|
194
|
-
const timeSinceAccess = lastAccessed > 0 ? now - lastAccessed : ageMs;
|
|
195
|
-
|
|
196
|
-
// Dependencies: extract from node.related field
|
|
197
|
-
const dependencies = node.related ? (Array.isArray(node.related) ? node.related : String(node.related).split(',').map(s => s.trim())) : [];
|
|
198
|
-
|
|
199
|
-
// Precompute L2 norm
|
|
200
|
-
let mag = 0;
|
|
201
|
-
for (let j = 0; j < embedding.length; j++) mag += embedding[j] * embedding[j];
|
|
202
|
-
mag = Math.sqrt(mag);
|
|
203
|
-
|
|
204
|
-
points.push({
|
|
205
|
-
slug: node.slug,
|
|
206
|
-
title: node.title || node.slug,
|
|
207
|
-
category: node.category || 'unknown',
|
|
208
|
-
layer: inferMemoryLayer(node),
|
|
209
|
-
embedding,
|
|
210
|
-
magnitude: mag,
|
|
211
|
-
// ── Physics ──
|
|
212
|
-
half_life: isFinite(halfLife) ? halfLife : null, // null = infinite
|
|
213
|
-
lambda, // decay constant
|
|
214
|
-
peak_relevance: peakRelevance, // R₀
|
|
215
|
-
velocity, // dR/dt
|
|
216
|
-
trajectory, // d²R/dt² (acceleration)
|
|
217
|
-
novelty, // information density
|
|
218
|
-
// ── Metadata ──
|
|
219
|
-
access_count: accessCount,
|
|
220
|
-
last_accessed: lastAccessed,
|
|
221
|
-
created_at: createdAt,
|
|
222
|
-
time_since_access: timeSinceAccess,
|
|
223
|
-
importance: node.importance || 3,
|
|
224
|
-
priority: node.priority || 'normal',
|
|
225
|
-
dependencies,
|
|
226
|
-
body_length: (node.body || node.content || '').length,
|
|
227
|
-
});
|
|
143
|
+
let missing = 0;
|
|
144
|
+
let dimensions = null;
|
|
145
|
+
|
|
146
|
+
for (const node of allNodes) {
|
|
147
|
+
const embedding = existingIndex[node.slug]?.embedding;
|
|
148
|
+
if (!Array.isArray(embedding) || !embedding.length || !embedding.every(Number.isFinite) ||
|
|
149
|
+
!embedding.some(value => value !== 0) || (dimensions !== null && embedding.length !== dimensions)) {
|
|
150
|
+
missing++;
|
|
151
|
+
continue;
|
|
228
152
|
}
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
(
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
153
|
+
dimensions ??= embedding.length;
|
|
154
|
+
cached++;
|
|
155
|
+
|
|
156
|
+
// ── Physics computation ──
|
|
157
|
+
const { accessCount, lastAccessed, elapsedMs, velocity, trajectory } = accessPhysics(node, ledger, now);
|
|
158
|
+
const createdAt = new Date(node.created || now).getTime();
|
|
159
|
+
const halfLife = computeHalfLife(node);
|
|
160
|
+
const lambda = decayConstant(halfLife);
|
|
161
|
+
|
|
162
|
+
// Novelty
|
|
163
|
+
const novelty = computeNovelty(accessCount);
|
|
164
|
+
|
|
165
|
+
// Peak relevance (baseline from importance + priority)
|
|
166
|
+
const importanceWeight = (node.importance || 3) / 5;
|
|
167
|
+
const priorityWeight = node.priority === 'absolute' ? 1.0 : node.priority === 'high' ? 0.8 : node.priority === 'normal' ? 0.5 : 0.3;
|
|
168
|
+
const peakRelevance = Math.max(importanceWeight, priorityWeight);
|
|
169
|
+
|
|
170
|
+
// Time since last access (for decay computation at sample time)
|
|
171
|
+
const timeSinceAccess = elapsedMs;
|
|
172
|
+
|
|
173
|
+
// Dependencies: extract from node.related field
|
|
174
|
+
const dependencies = node.related ? (Array.isArray(node.related) ? node.related : String(node.related).split(',').map(s => s.trim())) : [];
|
|
175
|
+
|
|
176
|
+
// Precompute L2 norm
|
|
177
|
+
let mag = 0;
|
|
178
|
+
for (let j = 0; j < embedding.length; j++) mag += embedding[j] * embedding[j];
|
|
179
|
+
mag = Math.sqrt(mag);
|
|
180
|
+
|
|
181
|
+
points.push({
|
|
182
|
+
slug: node.slug,
|
|
183
|
+
title: node.title || node.slug,
|
|
184
|
+
category: node.category || 'unknown',
|
|
185
|
+
layer: inferMemoryLayer(node),
|
|
186
|
+
embedding,
|
|
187
|
+
magnitude: mag,
|
|
188
|
+
// ── Physics ──
|
|
189
|
+
half_life: isFinite(halfLife) ? halfLife : null, // null = infinite
|
|
190
|
+
lambda, // decay constant
|
|
191
|
+
peak_relevance: peakRelevance, // R₀
|
|
192
|
+
velocity, // dR/dt
|
|
193
|
+
trajectory, // d²R/dt² (acceleration)
|
|
194
|
+
novelty, // information density
|
|
195
|
+
// ── Metadata ──
|
|
196
|
+
access_count: accessCount,
|
|
197
|
+
last_accessed: lastAccessed,
|
|
198
|
+
created_at: createdAt,
|
|
199
|
+
time_since_access: timeSinceAccess,
|
|
200
|
+
importance: node.importance || 3,
|
|
201
|
+
priority: node.priority || 'normal',
|
|
202
|
+
dependencies,
|
|
203
|
+
body_length: (node.body || node.content || '').length,
|
|
204
|
+
});
|
|
239
205
|
}
|
|
240
206
|
|
|
241
207
|
const embedMs = Date.now() - startTime;
|
|
242
|
-
logger.info('vector-field', `
|
|
208
|
+
logger.info('vector-field', `Loaded ${cached} existing vectors; ${missing} missing or incompatible`);
|
|
243
209
|
|
|
244
210
|
// ── Phase 2: Pairwise covariance matrix ──
|
|
245
211
|
const N = points.length;
|
|
246
212
|
const slugIndex = points.map(p => p.slug);
|
|
247
|
-
const covariance = new
|
|
213
|
+
const covariance = Array.from({ length: N }, () => new Float32Array(N));
|
|
248
214
|
|
|
249
215
|
for (let i = 0; i < N; i++) {
|
|
250
|
-
covariance[i] = new Float32Array(N);
|
|
251
216
|
for (let j = i; j < N; j++) {
|
|
252
217
|
if (i === j) {
|
|
253
218
|
covariance[i][j] = 1.0;
|
|
254
219
|
} else {
|
|
255
220
|
const sim = fastCosine(points[i].embedding, points[j].embedding, points[i].magnitude, points[j].magnitude);
|
|
256
221
|
covariance[i][j] = sim;
|
|
257
|
-
if (!covariance[j]) covariance[j] = new Float32Array(N);
|
|
258
222
|
covariance[j][i] = sim;
|
|
259
223
|
}
|
|
260
224
|
}
|
|
@@ -274,7 +238,8 @@ export async function compileField({ vaultDir, derivedDir = DERIVED_DIR } = {})
|
|
|
274
238
|
meta: {
|
|
275
239
|
total_nodes: totalNodes,
|
|
276
240
|
points_compiled: N,
|
|
277
|
-
embedded_new:
|
|
241
|
+
embedded_new: 0,
|
|
242
|
+
missing_embeddings: missing,
|
|
278
243
|
embedded_cached: cached,
|
|
279
244
|
embed_ms: embedMs,
|
|
280
245
|
covariance_ms: covMs,
|
|
@@ -289,54 +254,51 @@ export async function compileField({ vaultDir, derivedDir = DERIVED_DIR } = {})
|
|
|
289
254
|
|
|
290
255
|
const outPath = fieldPath(derivedDir);
|
|
291
256
|
fs.mkdirSync(path.dirname(outPath), { recursive: true });
|
|
292
|
-
|
|
257
|
+
atomicWrite(outPath, JSON.stringify(field));
|
|
293
258
|
|
|
294
259
|
logger.info('vector-field', `Field compiled: ${N} points, ${N * N} couplings, ${field.meta.infinite_halflife} immortal, ${field.meta.with_dependencies} with deps, ${field.meta.compile_ms}ms`);
|
|
295
260
|
|
|
296
261
|
return field;
|
|
297
262
|
}
|
|
298
263
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
const
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
if (!entry.hits?.includes(slug)) continue;
|
|
312
|
-
const age = now - entry.t;
|
|
313
|
-
if (age < WINDOW) w0++;
|
|
314
|
-
else if (age < 2 * WINDOW) w1++;
|
|
315
|
-
else if (age < 3 * WINDOW) w2++;
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
// Velocity = first derivative (recent vs previous)
|
|
319
|
-
const velocity = (w0 - w1) * 0.1;
|
|
320
|
-
|
|
321
|
-
// Trajectory = second derivative (acceleration of velocity)
|
|
322
|
-
const v_prev = (w1 - w2) * 0.1;
|
|
323
|
-
const trajectory = velocity - v_prev; // positive = accelerating, negative = decelerating
|
|
324
|
-
|
|
325
|
-
return {
|
|
326
|
-
velocity: Math.max(-1, Math.min(1, velocity)),
|
|
327
|
-
trajectory: Math.max(-1, Math.min(1, trajectory)),
|
|
328
|
-
};
|
|
264
|
+
/** Read live usage. Old ledgers have no daily counts, so their trend is unknown (zero). */
|
|
265
|
+
function accessPhysics(node, ledger, now) {
|
|
266
|
+
const entry = ledger[node.slug];
|
|
267
|
+
const accessCount = Math.max(0, Number(entry?.count ?? node.access_count ?? node.decay?.access_count) || 0);
|
|
268
|
+
const lastAccessed = lastUsedMs(node, ledger);
|
|
269
|
+
const days = activeDays(ledger).filter(day => day <= new Date(now).toISOString().slice(0, 10));
|
|
270
|
+
const counts = [0, 1, 2].map(offset => Number(entry?.daily_counts?.[days.at(-1 - offset)]) || 0);
|
|
271
|
+
const clamp = value => Math.max(-1, Math.min(1, value));
|
|
272
|
+
return { accessCount, lastAccessed,
|
|
273
|
+
elapsedMs: days.length ? activeDaysSince({ _active_days: days }, lastAccessed) * 86400000 : Math.max(0, now - lastAccessed),
|
|
274
|
+
velocity: clamp((counts[0] - counts[1]) * .1),
|
|
275
|
+
trajectory: clamp((counts[0] - 2 * counts[1] + counts[2]) * .1) };
|
|
329
276
|
}
|
|
330
277
|
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
278
|
+
/** Re-rank only recall candidates. No provider call or access write. */
|
|
279
|
+
export function rankWithField(results, { field, derivedDir = DERIVED_DIR, now = Date.now() } = {}) {
|
|
280
|
+
if (!field) throw new Error('Vector field not compiled. Run total-recall recall --compile-field first.');
|
|
281
|
+
const ledger = readAccess(derivedDir);
|
|
282
|
+
const indexes = new Map(field.points.map((point, index) => [point.slug, index]));
|
|
283
|
+
const ranked = results.map(result => {
|
|
284
|
+
const index = result.type === 'session' ? undefined : indexes.get(result.slug);
|
|
285
|
+
if (index === undefined) return result;
|
|
286
|
+
const point = field.points[index];
|
|
287
|
+
const physics = accessPhysics({ ...point, last_accessed: point.last_accessed, created: point.created_at }, ledger, now);
|
|
288
|
+
const relevance = effectiveRelevance(point.peak_relevance, point.lambda, physics.elapsedMs, physics.trajectory);
|
|
289
|
+
let coupling = 0, peers = 0;
|
|
290
|
+
for (const candidate of results) {
|
|
291
|
+
const other = candidate.type === 'session' ? undefined : indexes.get(candidate.slug);
|
|
292
|
+
if (other === undefined || other === index) continue;
|
|
293
|
+
coupling += Math.max(0, field.covariance[index][other]) * candidate.score;
|
|
294
|
+
peers++;
|
|
295
|
+
}
|
|
296
|
+
// The base score remains the main signal. Missing vectors and sessions retain their score.
|
|
297
|
+
const score = result.score * (.7 + .3 * relevance) + .05 * physics.velocity +
|
|
298
|
+
.05 * computeNovelty(physics.accessCount) + .15 * (peers ? coupling / peers : 0);
|
|
299
|
+
return { ...result, base_score: result.score, score: round4(score), field_score: round4(score) };
|
|
300
|
+
});
|
|
301
|
+
return ranked.sort((a, b) => b.score - a.score);
|
|
340
302
|
}
|
|
341
303
|
|
|
342
304
|
// ─── Fast Cosine ────────────────────────────────────────────────────────────
|
|
@@ -381,7 +343,14 @@ export async function sampleField({
|
|
|
381
343
|
if (!field) throw new Error('Vector field not compiled. Run compileField() first.');
|
|
382
344
|
}
|
|
383
345
|
|
|
384
|
-
const
|
|
346
|
+
const ledger = readAccess(derivedDir);
|
|
347
|
+
const points = field.points.map(point => {
|
|
348
|
+
const usage = accessPhysics({ ...point, created: point.created_at }, ledger, now);
|
|
349
|
+
return { ...point, velocity: usage.velocity, trajectory: usage.trajectory,
|
|
350
|
+
novelty: computeNovelty(usage.accessCount), access_count: usage.accessCount,
|
|
351
|
+
last_accessed: usage.lastAccessed, time_since_access: usage.elapsedMs };
|
|
352
|
+
});
|
|
353
|
+
const { covariance } = field;
|
|
385
354
|
const N = points.length;
|
|
386
355
|
if (N === 0) return { results: [], query_embedding: [], sample_ms: 0, interference: [] };
|
|
387
356
|
|
|
@@ -401,7 +370,7 @@ export async function sampleField({
|
|
|
401
370
|
const decayedScores = new Float64Array(N);
|
|
402
371
|
for (let i = 0; i < N; i++) {
|
|
403
372
|
const p = points[i];
|
|
404
|
-
const elapsed = p.
|
|
373
|
+
const elapsed = p.time_since_access || 0;
|
|
405
374
|
const decayedRelevance = effectiveRelevance(p.peak_relevance, p.lambda, elapsed, p.trajectory);
|
|
406
375
|
// Blend: 70% similarity, 30% decayed relevance
|
|
407
376
|
decayedScores[i] = (directScores[i] * 0.7) + (decayedRelevance * 0.3);
|
|
@@ -460,7 +429,7 @@ export async function sampleField({
|
|
|
460
429
|
// ── Format results ──
|
|
461
430
|
const results = topResults.map(({ index, score }) => {
|
|
462
431
|
const p = points[index];
|
|
463
|
-
const elapsed = p.
|
|
432
|
+
const elapsed = p.time_since_access || 0;
|
|
464
433
|
const remainingHL = p.lambda > 0 ? Math.round((LN2 / p.lambda) / (24 * 60 * 60 * 1000)) : null;
|
|
465
434
|
return {
|
|
466
435
|
slug: p.slug,
|
|
@@ -485,7 +454,7 @@ export async function sampleField({
|
|
|
485
454
|
});
|
|
486
455
|
|
|
487
456
|
const sampleMs = Date.now() - startTime;
|
|
488
|
-
|
|
457
|
+
recordAccess(derivedDir, results.map(r => r.slug));
|
|
489
458
|
|
|
490
459
|
logger.info('vector-field', `Sampled in ${sampleMs}ms: ${results.length} results, ${depsPulledIn.length} deps pulled, ${interference.length} interference pairs`);
|
|
491
460
|
|
|
@@ -557,52 +526,25 @@ function round4(n) { return Math.round(n * 10000) / 10000; }
|
|
|
557
526
|
// ─── Field Loading ──────────────────────────────────────────────────────────
|
|
558
527
|
|
|
559
528
|
let _cachedField = null;
|
|
560
|
-
let
|
|
529
|
+
let _cachedFieldStamp = null;
|
|
561
530
|
|
|
562
531
|
export function loadField(derivedDir = DERIVED_DIR) {
|
|
563
532
|
try {
|
|
564
533
|
const fp = fieldPath(derivedDir);
|
|
565
534
|
if (!fs.existsSync(fp)) return null;
|
|
566
535
|
const stat = fs.statSync(fp);
|
|
567
|
-
|
|
536
|
+
const stamp = `${path.resolve(fp)}:${stat.mtimeMs}:${stat.ctimeMs}:${stat.size}`;
|
|
537
|
+
if (_cachedField && stamp === _cachedFieldStamp) return _cachedField;
|
|
568
538
|
const raw = JSON.parse(fs.readFileSync(fp, 'utf8'));
|
|
539
|
+
if (!Array.isArray(raw.points) || !Array.isArray(raw.covariance) ||
|
|
540
|
+
raw.covariance.length !== raw.points.length || raw.covariance.some(row =>
|
|
541
|
+
!Array.isArray(row) || row.length !== raw.points.length || !row.every(Number.isFinite))) return null;
|
|
569
542
|
_cachedField = raw;
|
|
570
|
-
|
|
543
|
+
_cachedFieldStamp = stamp;
|
|
571
544
|
return raw;
|
|
572
545
|
} catch { return null; }
|
|
573
546
|
}
|
|
574
547
|
|
|
575
|
-
// ─── Query Logging ──────────────────────────────────────────────────────────
|
|
576
|
-
|
|
577
|
-
function logQuery(query, hitSlugs, derivedDir = DERIVED_DIR) {
|
|
578
|
-
try {
|
|
579
|
-
const logPath = queryLogPath(derivedDir);
|
|
580
|
-
fs.mkdirSync(path.dirname(logPath), { recursive: true });
|
|
581
|
-
fs.appendFileSync(logPath, JSON.stringify({ t: Date.now(), q: query.slice(0, 200), hits: hitSlugs.slice(0, 20) }) + '\n');
|
|
582
|
-
} catch { /* fire and forget */ }
|
|
583
|
-
}
|
|
584
|
-
|
|
585
|
-
// ─── Velocity Recomputation ─────────────────────────────────────────────────
|
|
586
|
-
|
|
587
|
-
/**
|
|
588
|
-
* Recompute velocity + trajectory vectors from query log.
|
|
589
|
-
* Call periodically (dream cycle) to update the field in-place.
|
|
590
|
-
*/
|
|
591
|
-
export function recomputeVelocities(field, derivedDir = DERIVED_DIR) {
|
|
592
|
-
if (!field) return field;
|
|
593
|
-
const now = Date.now();
|
|
594
|
-
const history = loadQueryHistory(derivedDir);
|
|
595
|
-
|
|
596
|
-
for (const point of field.points) {
|
|
597
|
-
const { velocity, trajectory } = computeTrajectory(point.slug, history, now);
|
|
598
|
-
point.velocity = velocity;
|
|
599
|
-
point.trajectory = trajectory;
|
|
600
|
-
point.novelty = computeNovelty(point.access_count);
|
|
601
|
-
}
|
|
602
|
-
|
|
603
|
-
return field;
|
|
604
|
-
}
|
|
605
|
-
|
|
606
548
|
// ─── Field Statistics ───────────────────────────────────────────────────────
|
|
607
549
|
|
|
608
550
|
export function fieldStats(derivedDir = DERIVED_DIR) {
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { executePluginState, listPluginStates, PluginStateStore } from './plugin-state-store.mjs';
|
|
4
|
+
import { getUiChunk, UiChunkInputError } from './ui-chunks.mjs';
|
|
5
|
+
import { getPluginById } from './plugin-loader.mjs';
|
|
6
|
+
import { pluginActivation } from './plugin-state.mjs';
|
|
7
|
+
|
|
8
|
+
const OWNER = 'workspace-ui';
|
|
9
|
+
const SAVED_PAGES = 'workspace-pages';
|
|
10
|
+
const ID = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/;
|
|
11
|
+
const VERSION = /^[a-f0-9]{64}$/;
|
|
12
|
+
const MAX_PAGE_BLOCKS = 24;
|
|
13
|
+
|
|
14
|
+
function stateFile(brainDir, plugin) {
|
|
15
|
+
if (typeof plugin !== 'string' || plugin.length > 64 || !ID.test(plugin)) throw new UiChunkInputError('Invalid plugin ID.');
|
|
16
|
+
return path.join(brainDir, 'config', 'workspace-compositions', plugin + '.json');
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function readCompositionState(brainDir, plugin, projectRoot) {
|
|
20
|
+
const store = new PluginStateStore(stateFile(brainDir, plugin), OWNER);
|
|
21
|
+
const owner = getPluginById(plugin, projectRoot);
|
|
22
|
+
if (!owner?.valid || !pluginActivation(owner, { projectRoot }).enabled) {
|
|
23
|
+
throw new UiChunkInputError('The destination plugin must be installed and enabled.');
|
|
24
|
+
}
|
|
25
|
+
const state = store.read({ keys: [] });
|
|
26
|
+
return { keys: state.keys, version: store.version };
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function readPageBlocks(brainDir, keys, projectRoot) {
|
|
30
|
+
return keys.flatMap(key => {
|
|
31
|
+
const chunk = readPageBlock(brainDir, key, projectRoot);
|
|
32
|
+
if (!chunk) return [];
|
|
33
|
+
const { html: _html, ...metadata } = chunk;
|
|
34
|
+
return [metadata];
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function readWorkspaceComposition(brainDir, plugin, projectRoot = process.cwd()) {
|
|
39
|
+
const { keys, version } = readCompositionState(brainDir, plugin, projectRoot);
|
|
40
|
+
return { chunks: readPageBlocks(brainDir, keys, projectRoot), version };
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function readPageBlock(brainDir, key, projectRoot) {
|
|
44
|
+
if (typeof key !== 'string') return null;
|
|
45
|
+
const [owner, id, ...rest] = key.split(':');
|
|
46
|
+
return ID.test(owner) && typeof id === 'string' && ID.test(id) && !rest.length
|
|
47
|
+
? getUiChunk(owner, id, { surface: 'page', brainDir, projectRoot }) : null;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export async function publishWorkspaceComposition(brainDir, plugin, keys, version, projectRoot = process.cwd()) {
|
|
51
|
+
const file = stateFile(brainDir, plugin);
|
|
52
|
+
const owner = getPluginById(plugin, projectRoot);
|
|
53
|
+
if (!owner?.valid || !pluginActivation(owner, { projectRoot }).enabled ||
|
|
54
|
+
!keys.length || keys.length > 3 || keys.some(key => !readPageBlock(brainDir, key, projectRoot))) {
|
|
55
|
+
throw new UiChunkInputError('The selected page blocks changed. Compose the view again.');
|
|
56
|
+
}
|
|
57
|
+
return executePluginState({ file, plugin: OWNER, action: 'write', value: { keys }, expectedVersion: version });
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function pageDirectory(brainDir) {
|
|
61
|
+
const config = path.join(brainDir, 'config');
|
|
62
|
+
const directory = path.join(config, SAVED_PAGES);
|
|
63
|
+
for (const candidate of [config, directory]) {
|
|
64
|
+
const stat = fs.lstatSync(candidate, { throwIfNoEntry: false });
|
|
65
|
+
if (stat && !stat.isDirectory()) throw new Error('Unsafe saved page directory');
|
|
66
|
+
}
|
|
67
|
+
return directory;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function savedPageFile(brainDir, id) {
|
|
71
|
+
if (typeof id !== 'string' || id.length > 64 || !ID.test(id)) throw new UiChunkInputError('Invalid saved page ID.');
|
|
72
|
+
return path.join(pageDirectory(brainDir), id + '.json');
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function pageConflict(message) {
|
|
76
|
+
return Object.assign(new Error(message), { status: 409 });
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function listWorkspacePages(brainDir) {
|
|
80
|
+
return listPluginStates(pageDirectory(brainDir), SAVED_PAGES)
|
|
81
|
+
.map(({ value: { id, title }, version }) => ({ id, title, version }))
|
|
82
|
+
.sort((a, b) => a.title.localeCompare(b.title) || a.id.localeCompare(b.id));
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export function readWorkspacePage(brainDir, id, projectRoot = process.cwd()) {
|
|
86
|
+
const store = new PluginStateStore(savedPageFile(brainDir, id), SAVED_PAGES);
|
|
87
|
+
const page = store.read(null);
|
|
88
|
+
if (!page) return null;
|
|
89
|
+
return { id, title: page.title, version: store.version, chunks: readPageBlocks(brainDir, page.keys, projectRoot) };
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export function prepareWorkspacePage(brainDir, id, title) {
|
|
93
|
+
const file = savedPageFile(brainDir, id);
|
|
94
|
+
const name = typeof title === 'string' ? title.trim() : '';
|
|
95
|
+
if (!name || name.length > 120 || /[\u0000-\u001f\u007f-\u009f]/u.test(title)) {
|
|
96
|
+
throw new UiChunkInputError('Enter a saved page title of up to 120 characters.');
|
|
97
|
+
}
|
|
98
|
+
const store = new PluginStateStore(file, SAVED_PAGES);
|
|
99
|
+
if (store.read(null)) throw pageConflict('That saved page ID already exists.');
|
|
100
|
+
return { title: name, file };
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function verifyPageBlocks(brainDir, keys, projectRoot) {
|
|
104
|
+
if (!Array.isArray(keys) || !keys.length || keys.length > MAX_PAGE_BLOCKS || new Set(keys).size !== keys.length) {
|
|
105
|
+
throw new UiChunkInputError(`Choose one to ${MAX_PAGE_BLOCKS} distinct page blocks.`);
|
|
106
|
+
}
|
|
107
|
+
const chunks = readPageBlocks(brainDir, keys, projectRoot);
|
|
108
|
+
if (chunks.length !== keys.length) throw pageConflict('The selected page blocks are no longer available.');
|
|
109
|
+
return chunks;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export async function createWorkspacePage(brainDir, { id, title, keys }, projectRoot = process.cwd()) {
|
|
113
|
+
const page = prepareWorkspacePage(brainDir, id, title);
|
|
114
|
+
const chunks = verifyPageBlocks(brainDir, keys, projectRoot);
|
|
115
|
+
try {
|
|
116
|
+
const { version } = await executePluginState({
|
|
117
|
+
file: page.file, plugin: SAVED_PAGES, action: 'write',
|
|
118
|
+
value: { id, title: page.title, keys }, expectedVersion: null,
|
|
119
|
+
});
|
|
120
|
+
return { id, title: page.title, version, chunks };
|
|
121
|
+
} catch (error) {
|
|
122
|
+
if (error.message.startsWith('Plugin state version conflict')) throw pageConflict('That saved page ID already exists.');
|
|
123
|
+
throw error;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export async function updateWorkspacePage(brainDir, { id, keys, revision }, projectRoot = process.cwd()) {
|
|
128
|
+
if (typeof revision !== 'string' || !VERSION.test(revision)) {
|
|
129
|
+
throw new UiChunkInputError('Supply the current saved page revision.');
|
|
130
|
+
}
|
|
131
|
+
const file = savedPageFile(brainDir, id);
|
|
132
|
+
const store = new PluginStateStore(file, SAVED_PAGES);
|
|
133
|
+
const page = store.read(null);
|
|
134
|
+
if (!page) throw Object.assign(new Error('Saved page unavailable'), { status: 404 });
|
|
135
|
+
if (store.version !== revision) throw pageConflict('The saved page changed. Read its current revision before editing.');
|
|
136
|
+
const chunks = verifyPageBlocks(brainDir, keys, projectRoot);
|
|
137
|
+
const { version } = await executePluginState({
|
|
138
|
+
file, plugin: SAVED_PAGES, action: 'write',
|
|
139
|
+
value: { id, title: page.title, keys }, expectedVersion: revision,
|
|
140
|
+
});
|
|
141
|
+
return { id, title: page.title, version, chunks };
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export async function saveWorkspaceCompositionPage(brainDir, { id, title, sourcePlugin, sourceVersion }, projectRoot = process.cwd()) {
|
|
145
|
+
if (typeof sourceVersion !== 'string' || !VERSION.test(sourceVersion)) {
|
|
146
|
+
throw new UiChunkInputError('Supply the published Home revision to save.');
|
|
147
|
+
}
|
|
148
|
+
const { keys, version } = readCompositionState(brainDir, sourcePlugin, projectRoot);
|
|
149
|
+
if (version !== sourceVersion) throw pageConflict('The plugin Home changed. Read its current revision before saving.');
|
|
150
|
+
return createWorkspacePage(brainDir, { id, title, keys }, projectRoot);
|
|
151
|
+
}
|