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
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import crypto from 'node:crypto';
|
|
4
|
+
import { atomicWrite } from './vault.mjs';
|
|
5
|
+
import { addTask, getTask, resolveQueueDir } from './task-envelope.mjs';
|
|
6
|
+
import { readLessonEntries, countLessonTurns, selectLessonTurns } from './lesson-sessions.mjs';
|
|
7
|
+
import { acquireBrainUpdateLock } from './brain-updates.mjs';
|
|
8
|
+
|
|
9
|
+
export const DEFAULT_LESSON_INTERVAL = 10;
|
|
10
|
+
const hash = value => crypto.createHash('sha256').update(value).digest('hex').slice(0, 12);
|
|
11
|
+
|
|
12
|
+
/** A local hook only queues work. It never calls a model or elects a leader. */
|
|
13
|
+
export function tickLessons({ brainDir, sessionId, transcriptPath, event = 'Stop', interval,
|
|
14
|
+
turnId, turnCount, harness = 'unknown', hold } = {}) {
|
|
15
|
+
if (!brainDir || !sessionId) throw new Error('Lesson review requires a brain and session id');
|
|
16
|
+
const sessionsDir = path.join(brainDir, 'sessions');
|
|
17
|
+
const configPath = path.join(brainDir, 'config', 'lessons.json');
|
|
18
|
+
if (fs.existsSync(configPath)) {
|
|
19
|
+
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
20
|
+
if (config.enabled === false) return { tasks: [], skipped: 'disabled' };
|
|
21
|
+
interval ??= config.interval;
|
|
22
|
+
if (hold === undefined) hold = config.holdWrites === true;
|
|
23
|
+
}
|
|
24
|
+
interval ??= DEFAULT_LESSON_INTERVAL;
|
|
25
|
+
if (!Number.isInteger(interval) || interval < 1) throw new Error('Lesson interval must be a positive integer');
|
|
26
|
+
hold ??= false;
|
|
27
|
+
const root = path.join(brainDir, 'lesson-reviews');
|
|
28
|
+
fs.mkdirSync(root, { recursive: true });
|
|
29
|
+
// Match writeSession's identity so native hooks and later ingest share a cursor.
|
|
30
|
+
const localTranscript = transcriptPath && path.dirname(path.resolve(transcriptPath)) === path.resolve(sessionsDir);
|
|
31
|
+
const key = transcriptPath ? (localTranscript ? path.basename(transcriptPath, '.jsonl') : hash(path.resolve(transcriptPath))) : hash(`${harness}:${sessionId}`);
|
|
32
|
+
const lock = path.join(root, `${key}.lock`);
|
|
33
|
+
const lockFd = acquireBrainUpdateLock(lock, { waitMs: 0 });
|
|
34
|
+
try {
|
|
35
|
+
const stateFile = path.join(root, `${key}.json`);
|
|
36
|
+
const state = fs.existsSync(stateFile) ? JSON.parse(fs.readFileSync(stateFile, 'utf8')) : { turns: 0, queuedThrough: 0 };
|
|
37
|
+
let entries;
|
|
38
|
+
const savedTranscript = path.join(sessionsDir, `${key}.jsonl`);
|
|
39
|
+
if (!transcriptPath && fs.existsSync(savedTranscript)) transcriptPath = savedTranscript;
|
|
40
|
+
if (transcriptPath) {
|
|
41
|
+
entries = readLessonEntries(transcriptPath);
|
|
42
|
+
turnCount = countLessonTurns(entries);
|
|
43
|
+
if (!localTranscript) {
|
|
44
|
+
fs.mkdirSync(sessionsDir, { recursive: true });
|
|
45
|
+
atomicWrite(path.join(sessionsDir, `${key}.jsonl`), entries.map(entry => JSON.stringify(entry)).join('\n') + '\n');
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if (turnCount !== undefined) {
|
|
49
|
+
if (!Number.isInteger(turnCount) || turnCount < state.turns) throw new Error('Lesson transcript turn count went backwards');
|
|
50
|
+
state.turns = turnCount;
|
|
51
|
+
} else if (event === 'UserPromptSubmit' && (!turnId || turnId !== state.lastTurnId)) {
|
|
52
|
+
state.turns++;
|
|
53
|
+
state.lastTurnId = turnId;
|
|
54
|
+
}
|
|
55
|
+
const final = event === 'SessionEnd' || event === 'session-end';
|
|
56
|
+
const tasks = [];
|
|
57
|
+
// Prompt hooks count only. Stop has the completed response and tool results.
|
|
58
|
+
if (event !== 'UserPromptSubmit' && entries) {
|
|
59
|
+
while (state.turns - state.queuedThrough >= interval || (final && state.turns > state.queuedThrough)) {
|
|
60
|
+
const fromTurn = state.queuedThrough + 1;
|
|
61
|
+
const toTurn = Math.min(state.turns, state.queuedThrough + interval);
|
|
62
|
+
const slug = `lesson-review-${key}-${fromTurn}-${toTurn}`;
|
|
63
|
+
const queueDir = resolveQueueDir(brainDir);
|
|
64
|
+
if (!getTask(queueDir, slug) && !fs.existsSync(path.join(root, `${slug}.done`))) {
|
|
65
|
+
const snapshot = path.join(root, `${slug}.jsonl`);
|
|
66
|
+
atomicWrite(snapshot, selectLessonTurns(entries, { fromTurn, toTurn }).map(entry => JSON.stringify(entry)).join('\n') + '\n');
|
|
67
|
+
addTask({ slug, intent: `Review session ${sessionId}, turns ${fromTurn}–${toTurn}`,
|
|
68
|
+
kind: 'memory', executor: 'lesson-review', category: 'lesson-review', priority: 40,
|
|
69
|
+
origin: { agent: harness, session_id: sessionId },
|
|
70
|
+
payload: { sessionPath: snapshot, fromTurn, toTurn, hold, sessionId },
|
|
71
|
+
}, queueDir);
|
|
72
|
+
}
|
|
73
|
+
tasks.push(slug);
|
|
74
|
+
state.queuedThrough = toTurn;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
atomicWrite(stateFile, JSON.stringify(state));
|
|
78
|
+
return { turns: state.turns, queuedThrough: state.queuedThrough, tasks };
|
|
79
|
+
} finally {
|
|
80
|
+
// Remove only the inode this process acquired. A dead hook's lock is reclaimed
|
|
81
|
+
// by the shared lock owner on the next tick.
|
|
82
|
+
try { if (fs.statSync(lock).ino === fs.fstatSync(lockFd).ino) fs.unlinkSync(lock); }
|
|
83
|
+
finally { fs.closeSync(lockFd); }
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** Session-ingest fallback for harnesses without a lifecycle hook. Every node calls this. */
|
|
88
|
+
export function enqueueSessionReviews({ brainDir, now = Date.now(), quietMs = 5 * 60_000, interval, hold } = {}) {
|
|
89
|
+
const dir = path.join(brainDir, 'sessions');
|
|
90
|
+
if (!fs.existsSync(dir)) return [];
|
|
91
|
+
return fs.readdirSync(dir).filter(name => name.endsWith('.jsonl')).map(name => {
|
|
92
|
+
const transcriptPath = path.join(dir, name);
|
|
93
|
+
return tickLessons({ brainDir, sessionId: path.basename(name, '.jsonl'), transcriptPath, interval, hold,
|
|
94
|
+
event: now - fs.statSync(transcriptPath).mtimeMs >= quietMs ? 'SessionEnd' : 'Stop', harness: 'session-ingest' });
|
|
95
|
+
});
|
|
96
|
+
}
|
|
@@ -5,6 +5,7 @@ import { writeFileSecure } from './secure-file.mjs';
|
|
|
5
5
|
import { ensureProjectId } from './project-id.mjs';
|
|
6
6
|
|
|
7
7
|
function ensureDir(dir) { fs.mkdirSync(dir, { recursive: true }); }
|
|
8
|
+
const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
|
|
8
9
|
|
|
9
10
|
export const VAULT_CATEGORIES = Object.freeze([
|
|
10
11
|
'invariants',
|
|
@@ -18,17 +19,33 @@ export const VAULT_CATEGORIES = Object.freeze([
|
|
|
18
19
|
'lore',
|
|
19
20
|
]);
|
|
20
21
|
|
|
22
|
+
function readBrainConfig(file) {
|
|
23
|
+
let current;
|
|
24
|
+
try { current = JSON.parse(fs.readFileSync(file, 'utf8')); }
|
|
25
|
+
catch (error) {
|
|
26
|
+
if (error.code === 'ENOENT') return {};
|
|
27
|
+
throw error;
|
|
28
|
+
}
|
|
29
|
+
if (!current || typeof current !== 'object' || Array.isArray(current)) {
|
|
30
|
+
throw new Error('Existing brain identity must be an object');
|
|
31
|
+
}
|
|
32
|
+
return current;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** Update connection settings without replacing the existing brain identity. */
|
|
36
|
+
export function writeBrainConnection(brainDir, fields) {
|
|
37
|
+
const file = path.join(brainDir, 'config', 'brain.json');
|
|
38
|
+
const current = readBrainConfig(file);
|
|
39
|
+
ensureDir(path.dirname(file));
|
|
40
|
+
writeFileSecure(file, JSON.stringify({ ...current, ...fields }, null, 2), { encoding: 'utf8', mode: 0o600 });
|
|
41
|
+
return file;
|
|
42
|
+
}
|
|
43
|
+
|
|
21
44
|
export function writeBrainIdentity(brainDir, { name, role = 'project', tags = [] } = {}) {
|
|
22
45
|
const configDir = path.join(brainDir, 'config');
|
|
23
46
|
ensureDir(configDir);
|
|
24
47
|
const brainJsonPath = path.join(configDir, 'brain.json');
|
|
25
|
-
|
|
26
|
-
if (fs.existsSync(brainJsonPath)) {
|
|
27
|
-
current = JSON.parse(fs.readFileSync(brainJsonPath, 'utf8'));
|
|
28
|
-
if (!current || typeof current !== 'object' || Array.isArray(current)) {
|
|
29
|
-
throw new Error('Existing brain identity must be an object');
|
|
30
|
-
}
|
|
31
|
-
}
|
|
48
|
+
const current = readBrainConfig(brainJsonPath);
|
|
32
49
|
const next = {
|
|
33
50
|
...current,
|
|
34
51
|
name: name || current.name || path.basename(path.resolve(brainDir, '../../..')),
|
|
@@ -54,12 +71,17 @@ export function registerProjectBrain(globalBrainDir, entry) {
|
|
|
54
71
|
|
|
55
72
|
const abs = path.resolve(entry.path);
|
|
56
73
|
const idx = list.findIndex((p) => path.resolve(p.path || '') === abs);
|
|
74
|
+
const existing = list[idx];
|
|
75
|
+
const candidateId = existing?.project_id;
|
|
76
|
+
const fallbackId = typeof candidateId === 'string' && UUID.test(candidateId) &&
|
|
77
|
+
existing.brainDir === entry.brainDir && list.filter(record => record.project_id === candidateId).length === 1
|
|
78
|
+
? candidateId : undefined;
|
|
57
79
|
const now = new Date().toISOString();
|
|
58
80
|
const row = {
|
|
59
81
|
name: entry.name,
|
|
60
82
|
path: abs,
|
|
61
83
|
brainDir: entry.brainDir,
|
|
62
|
-
project_id: ensureProjectId(entry.brainDir).project_id,
|
|
84
|
+
project_id: ensureProjectId(entry.brainDir, { fallbackId }).project_id,
|
|
63
85
|
full_brain: true,
|
|
64
86
|
layer: 'project',
|
|
65
87
|
tags: entry.tags || ['project-brain'],
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
/** Compatibility facade only. Adapter contracts, auth, usage and execution belong to
|
|
1
|
+
/** Compatibility facade only. Adapter contracts, auth, usage and execution belong to Metaharness. */
|
|
2
2
|
import { loadPluginModule } from './plugin-runtime.mjs';
|
|
3
3
|
|
|
4
4
|
let owner, ownerError;
|
|
5
5
|
try { owner = await loadPluginModule('meta-harness', 'harness-compat'); }
|
|
6
6
|
catch (error) { ownerError = error; }
|
|
7
7
|
function implementation() {
|
|
8
|
-
if (!owner) throw new Error(`
|
|
8
|
+
if (!owner) throw new Error(`Metaharness is unavailable: ${ownerError?.message || 'install the plugin'}`);
|
|
9
9
|
return owner;
|
|
10
10
|
}
|
|
11
11
|
|
package/src/core/optimizer.mjs
CHANGED
|
@@ -4,8 +4,8 @@ import crypto from 'crypto';
|
|
|
4
4
|
import matter from './frontmatter.mjs';
|
|
5
5
|
import { writeNode } from './vault.mjs';
|
|
6
6
|
import { getNodes } from './vault-cache.mjs';
|
|
7
|
+
import { readAccess, lastUsedMs, activeDaysSince } from './access-ledger.mjs';
|
|
7
8
|
import { logger } from './logger.mjs';
|
|
8
|
-
import { brainDir } from './config.mjs';
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Total Recall Optimizer
|
|
@@ -166,129 +166,6 @@ export async function generateMemoryCleanupProposals(vaultDir) {
|
|
|
166
166
|
return proposals;
|
|
167
167
|
}
|
|
168
168
|
|
|
169
|
-
/**
|
|
170
|
-
* Scans skill execution logs (if available) and proposes improvements.
|
|
171
|
-
*/
|
|
172
|
-
/**
|
|
173
|
-
* Scan skill files for quality issues and propose improvements.
|
|
174
|
-
* Looks at skill files that haven't been updated in >30 days and
|
|
175
|
-
* checks for common issues: missing examples, vague instructions, outdated commands.
|
|
176
|
-
*/
|
|
177
|
-
export async function generateSkillImprovementProposals(vaultDir) {
|
|
178
|
-
const agentDir = path.join(path.dirname(vaultDir));
|
|
179
|
-
const skillsDir = path.join(agentDir, 'skills');
|
|
180
|
-
const proposals = [];
|
|
181
|
-
|
|
182
|
-
if (!fs.existsSync(skillsDir)) return proposals;
|
|
183
|
-
|
|
184
|
-
const now = Date.now();
|
|
185
|
-
const staleCutoff = 30 * 24 * 60 * 60 * 1000; // 30 days
|
|
186
|
-
|
|
187
|
-
try {
|
|
188
|
-
const skillDirs = fs.readdirSync(skillsDir, { withFileTypes: true })
|
|
189
|
-
.filter(d => d.isDirectory())
|
|
190
|
-
.map(d => path.join(skillsDir, d.name, 'SKILL.md'))
|
|
191
|
-
.filter(p => fs.existsSync(p));
|
|
192
|
-
|
|
193
|
-
for (const skillFile of skillDirs) {
|
|
194
|
-
const stat = fs.statSync(skillFile);
|
|
195
|
-
const ageMs = now - stat.mtimeMs;
|
|
196
|
-
if (ageMs < staleCutoff) continue;
|
|
197
|
-
|
|
198
|
-
const raw = fs.readFileSync(skillFile, 'utf8');
|
|
199
|
-
const hasExamples = /##\s*example/i.test(raw);
|
|
200
|
-
const hasCaution = /caution|warning|never|must not/i.test(raw);
|
|
201
|
-
const lineCount = raw.split('\n').length;
|
|
202
|
-
|
|
203
|
-
const issues = [];
|
|
204
|
-
if (!hasExamples) issues.push('No examples section');
|
|
205
|
-
if (!hasCaution) issues.push('No caution/constraint section');
|
|
206
|
-
if (lineCount < 20) issues.push('Very short — may lack detail');
|
|
207
|
-
|
|
208
|
-
if (issues.length > 0) {
|
|
209
|
-
const skillName = path.basename(path.dirname(skillFile));
|
|
210
|
-
proposals.push(createProposal(
|
|
211
|
-
'skill-improvement',
|
|
212
|
-
`Improve skill: ${skillName} (${issues.join(', ')})`,
|
|
213
|
-
skillFile,
|
|
214
|
-
`Skill file is ${Math.floor(ageMs / 86400000)} days old. Issues: ${issues.join('; ')}`,
|
|
215
|
-
));
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
} catch (err) {
|
|
219
|
-
logger.debug('optimizer: generateSkillImprovementProposals failed to read skillsDir', { err: err.message });
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
return proposals;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
/**
|
|
226
|
-
* Scan the task queue for stuck or stalled workflows.
|
|
227
|
-
* Tasks that have been 'in-progress' for >1 hour are considered stalled.
|
|
228
|
-
*/
|
|
229
|
-
export async function generateWorkflowRepairProposals(vaultDir) {
|
|
230
|
-
const queueDir = path.join(brainDir, 'scheduler', 'queue');
|
|
231
|
-
const proposals = [];
|
|
232
|
-
|
|
233
|
-
if (!fs.existsSync(queueDir)) return proposals;
|
|
234
|
-
|
|
235
|
-
const now = Date.now();
|
|
236
|
-
const stalledCutoff = 60 * 60 * 1000; // 1 hour
|
|
237
|
-
|
|
238
|
-
try {
|
|
239
|
-
const files = fs.readdirSync(queueDir).filter(f => f.endsWith('.md'));
|
|
240
|
-
for (const file of files) {
|
|
241
|
-
const raw = fs.readFileSync(path.join(queueDir, file), 'utf8');
|
|
242
|
-
const { data } = matter(raw);
|
|
243
|
-
if (data.status !== 'in-progress') continue;
|
|
244
|
-
|
|
245
|
-
const updatedAt = new Date(data.updated_at || data.created || 0).getTime();
|
|
246
|
-
if (now - updatedAt < stalledCutoff) continue;
|
|
247
|
-
|
|
248
|
-
proposals.push(createProposal(
|
|
249
|
-
'workflow-repair',
|
|
250
|
-
`Stalled task: ${data.slug || file}`,
|
|
251
|
-
path.join(queueDir, file),
|
|
252
|
-
`Task has been in-progress for ${Math.floor((now - updatedAt) / 60000)} minutes. May need retry or cancellation.`,
|
|
253
|
-
));
|
|
254
|
-
}
|
|
255
|
-
} catch (err) {
|
|
256
|
-
logger.debug('optimizer: generateWorkflowRepairProposals failed to read queueDir', { err: err.message });
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
return proposals;
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
/**
|
|
263
|
-
* Analyze the vault's model usage patterns and propose routing improvements.
|
|
264
|
-
* Flags cases where high-priority tasks were sent to the local LLM
|
|
265
|
-
* that should have used a frontier model.
|
|
266
|
-
*/
|
|
267
|
-
export async function generateModelRoutingProposals(vaultDir) {
|
|
268
|
-
const proposals = [];
|
|
269
|
-
const nodes = getNodes(vaultDir);
|
|
270
|
-
|
|
271
|
-
// Find high-importance facts with low confidence — likely needed frontier model
|
|
272
|
-
const underconfident = nodes.filter(n =>
|
|
273
|
-
n.status === 'active' &&
|
|
274
|
-
n.category === 'facts' &&
|
|
275
|
-
n.importance >= 4 &&
|
|
276
|
-
n.confidence < 0.6 &&
|
|
277
|
-
n.source?.agent === 'fact-seeker',
|
|
278
|
-
);
|
|
279
|
-
|
|
280
|
-
for (const node of underconfident.slice(0, 5)) {
|
|
281
|
-
proposals.push(createProposal(
|
|
282
|
-
'model-routing',
|
|
283
|
-
`Re-research with frontier model: "${node.title}"`,
|
|
284
|
-
node.slug,
|
|
285
|
-
`High-importance fact (importance: ${node.importance}) has low confidence (${node.confidence}). Originally researched by local model. Frontier model may produce better synthesis.`,
|
|
286
|
-
));
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
return proposals;
|
|
290
|
-
}
|
|
291
|
-
|
|
292
169
|
/**
|
|
293
170
|
* Nodes that are important but have gone untouched — computed on demand.
|
|
294
171
|
*
|
|
@@ -310,21 +187,6 @@ export function findStaleNodes(vaultDir, { days = 30, minImportance = 4 } = {})
|
|
|
310
187
|
.sort((a, b) => new Date(a.last_accessed) - new Date(b.last_accessed));
|
|
311
188
|
}
|
|
312
189
|
|
|
313
|
-
/**
|
|
314
|
-
* @deprecated Wrote tickets nothing reads. Retained because the dream cycle's
|
|
315
|
-
* master switch (ENABLE_STALE_KNOWLEDGE_REFRESH, off) still references it.
|
|
316
|
-
* Stale nodes are surfaced to a human via findStaleNodes instead; nothing
|
|
317
|
-
* re-researches them automatically (RESEARCH_SYSTEM2).
|
|
318
|
-
*/
|
|
319
|
-
export async function generateStaleKnowledgeRefreshProposals(vaultDir) {
|
|
320
|
-
return findStaleNodes(vaultDir, { days: 30, minImportance: 4 }).map(node => createProposal(
|
|
321
|
-
'stale-knowledge-refresh',
|
|
322
|
-
`Refresh stale high-importance memory: ${node.title}`,
|
|
323
|
-
node.slug,
|
|
324
|
-
'Node has not been accessed in over 30 days but maintains high importance. Requires verification against current state.',
|
|
325
|
-
));
|
|
326
|
-
}
|
|
327
|
-
|
|
328
190
|
/**
|
|
329
191
|
* Local Eval Gate for Proposal Promotion
|
|
330
192
|
* Uses the local runtime to evaluate the validity of a proposal.
|
|
@@ -379,6 +241,14 @@ export async function evaluateProposalGate(proposal, runtimeConfig, vaultDir = n
|
|
|
379
241
|
return stamp('accepted');
|
|
380
242
|
}
|
|
381
243
|
|
|
244
|
+
// smart-decay is verified mechanically against live state: the memory still exists, is
|
|
245
|
+
// active and unprotected, and the access ledger shows no use since it was judged and for
|
|
246
|
+
// the full decay age. Only then may it reach `accepted` and auto-apply (DECAY-01).
|
|
247
|
+
if (proposal.category === 'smart-decay') {
|
|
248
|
+
const reason = verifySmartDecay(proposal, vaultDir);
|
|
249
|
+
return reason ? stamp('rejected', { rejection_reason: reason }) : stamp('accepted');
|
|
250
|
+
}
|
|
251
|
+
|
|
382
252
|
// stale-knowledge-refresh no longer produces tickets at all — the work is
|
|
383
253
|
// handed to the research queue, which can actually perform it. If one is
|
|
384
254
|
// somehow generated, it is not something to auto-accept.
|
|
@@ -422,41 +292,67 @@ Output ONLY valid JSON.`;
|
|
|
422
292
|
*
|
|
423
293
|
* @param {string} vaultDir
|
|
424
294
|
* @param {object} runtimeConfig
|
|
425
|
-
* @param {number} [ageThresholdDays=60]
|
|
295
|
+
* @param {number} [ageThresholdDays=60] Active days of the brain without a use before considering decay
|
|
426
296
|
* @returns {object[]} decay proposals
|
|
427
297
|
*/
|
|
428
|
-
|
|
429
|
-
|
|
298
|
+
/** Active days (days the brain was used), never calendar days: an idle brain never decays. */
|
|
299
|
+
export const DECAY_AGE_DAYS = 60;
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Why a smart-decay proposal may not be applied, or null when live state supports it.
|
|
303
|
+
* Shared by the gate and the applier so both check the same facts.
|
|
304
|
+
*/
|
|
305
|
+
export function verifySmartDecay(proposal, vaultDir, { now = Date.now(), ageThresholdDays = DECAY_AGE_DAYS } = {}) {
|
|
306
|
+
if (!vaultDir) return 'No vault to verify against.';
|
|
307
|
+
const slug = String(proposal.target_path || '').trim();
|
|
308
|
+
const node = getNodes(vaultDir).find(n => n.slug === slug);
|
|
309
|
+
if (!node) return `Memory ${slug} no longer exists.`;
|
|
310
|
+
if (node.status !== 'active') return `Memory ${slug} is already ${node.status}.`;
|
|
311
|
+
if (isDecayProtected(node)) return `Memory ${slug} is protected from decay.`;
|
|
312
|
+
const ledger = readAccess(path.join(path.dirname(vaultDir), 'memory-derived'));
|
|
313
|
+
const used = lastUsedMs(node, ledger);
|
|
314
|
+
if (proposal.decay_last_used_at && used > new Date(proposal.decay_last_used_at).getTime()) return `Memory ${slug} was used after it was judged.`;
|
|
315
|
+
if (activeDaysSince(ledger, used) < ageThresholdDays) return `Memory ${slug} was used within the brain's last ${ageThresholdDays} active days.`;
|
|
316
|
+
return null;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/** Memories decay never touches: rules, absolute-priority and importance-5 memories. */
|
|
320
|
+
export function isDecayProtected(node) {
|
|
321
|
+
return node.priority === 'absolute' || node.importance >= 5
|
|
322
|
+
|| ['invariants', 'preferences', 'anti-patterns'].includes(node.category);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/** Active, unprotected memories unused for at least `ageThresholdDays` of the brain's active days. */
|
|
326
|
+
export function decayCandidates(nodes, ledger, { now = Date.now(), ageThresholdDays = DECAY_AGE_DAYS } = {}) {
|
|
327
|
+
return nodes
|
|
328
|
+
.filter(n => n.status === 'active' && n.type !== 'proposal' && !isDecayProtected(n))
|
|
329
|
+
.filter(n => activeDaysSince(ledger, lastUsedMs(n, ledger)) >= ageThresholdDays)
|
|
330
|
+
.sort((a, b) => lastUsedMs(a, ledger) - lastUsedMs(b, ledger));
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
export async function runSmartDecay(vaultDir, runtimeConfig, ageThresholdDays = DECAY_AGE_DAYS, { derivedDir = path.join(path.dirname(vaultDir), 'memory-derived'), call } = {}) {
|
|
334
|
+
const callLocalRuntime = call || (await import('./runtime.mjs')).callLocalRuntime;
|
|
430
335
|
const nodes = getNodes(vaultDir);
|
|
431
336
|
const now = Date.now();
|
|
432
|
-
const
|
|
337
|
+
const ledger = readAccess(derivedDir);
|
|
433
338
|
const proposals = [];
|
|
434
339
|
|
|
435
|
-
//
|
|
436
|
-
const
|
|
437
|
-
if (n.status !== 'active') return false;
|
|
438
|
-
if (n.priority === 'absolute') return false;
|
|
439
|
-
if (n.importance >= 5) return false;
|
|
440
|
-
const lastAccessed = new Date(n.last_accessed || n.updated || 0).getTime();
|
|
441
|
-
return (now - lastAccessed) > ageThresholdMs;
|
|
442
|
-
});
|
|
443
|
-
|
|
444
|
-
// Process up to 5 candidates per run to avoid excessive LLM calls
|
|
445
|
-
const batch = candidates.slice(0, 5);
|
|
340
|
+
// Oldest unused first, up to 5 per run to bound model calls.
|
|
341
|
+
const batch = decayCandidates(nodes, ledger, { now, ageThresholdDays }).slice(0, 5);
|
|
446
342
|
|
|
447
343
|
for (const node of batch) {
|
|
448
|
-
const ageDays =
|
|
344
|
+
const ageDays = activeDaysSince(ledger, lastUsedMs(node, ledger));
|
|
449
345
|
|
|
450
346
|
const prompt = [
|
|
451
347
|
`## Memory Node: ${node.slug}`,
|
|
452
348
|
`Title: "${node.title}"`,
|
|
453
|
-
`Category: ${node.category} | Importance: ${node.importance} |
|
|
349
|
+
`Category: ${node.category} | Importance: ${node.importance} | Unused for ${ageDays} active days of its brain`,
|
|
454
350
|
`Tags: ${(node.tags || []).join(', ')}`,
|
|
455
351
|
'',
|
|
456
352
|
'## Body',
|
|
457
353
|
(node.body || '').slice(0, 800),
|
|
458
354
|
'',
|
|
459
|
-
`This node has not been
|
|
355
|
+
`This node has not been used on the last ${ageDays} days its brain was active. Should it be retained, archived, or decayed?`,
|
|
460
356
|
].join('\n');
|
|
461
357
|
|
|
462
358
|
try {
|
|
@@ -468,15 +364,20 @@ export async function runSmartDecay(vaultDir, runtimeConfig, ageThresholdDays =
|
|
|
468
364
|
const verdict = result.verdict || 'RETAINED';
|
|
469
365
|
|
|
470
366
|
if (verdict !== 'RETAINED') {
|
|
471
|
-
proposals.push(
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
367
|
+
proposals.push({
|
|
368
|
+
...createProposal(
|
|
369
|
+
'smart-decay',
|
|
370
|
+
`Smart Decay [${verdict}]: "${node.title}"`,
|
|
371
|
+
node.slug,
|
|
372
|
+
`Unused for ${ageDays} active days. Reasoning: ${result.reasoning || 'No reasoning provided.'} Confidence adjustment: ${result.confidence_adjustment || 0}`,
|
|
373
|
+
),
|
|
374
|
+
// The gate re-checks that the memory has not been used since this judgement.
|
|
375
|
+
decay_verdict: verdict,
|
|
376
|
+
decay_last_used_at: new Date(lastUsedMs(node, ledger)).toISOString(),
|
|
377
|
+
});
|
|
477
378
|
}
|
|
478
|
-
} catch {
|
|
479
|
-
|
|
379
|
+
} catch (err) {
|
|
380
|
+
logger.warn('optimizer', `Smart decay could not evaluate ${node.slug}: ${err.message}`);
|
|
480
381
|
}
|
|
481
382
|
}
|
|
482
383
|
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
/** Host activation policy; never pretends a provider or external daemon is healthy. */
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { getPlugin, globalPluginsDir, projectPluginsDir, vaultForPluginsDir } from './plugin-loader.mjs';
|
|
4
|
+
import { patchPluginRecord, patchProjectActivationRecord, recordPath, emit, vaultFor, recompileAfterPluginMutation } from './plugin-store.mjs';
|
|
5
|
+
import { patchVfsDocument } from './ssss-operation-service.mjs';
|
|
6
|
+
import { pluginActivation, readActivationRecord, usesSharedPluginPolicy } from './plugin-state.mjs';
|
|
7
|
+
import { moveRepositoryPluginState, withRepositoryPluginLifecycle } from './plugin-lifecycle.mjs';
|
|
5
8
|
import { REQUIRED_INSTALLATION_PLUGIN_IDS } from './default-plugins.mjs';
|
|
6
9
|
export { pluginActivation };
|
|
7
10
|
|
|
@@ -14,38 +17,78 @@ export { pluginActivation };
|
|
|
14
17
|
* following the shared setting (`clear: true`).
|
|
15
18
|
*/
|
|
16
19
|
export async function setPluginActive(id, enabled, { projectRoot = process.cwd(), scope = 'project', clear = false } = {}) {
|
|
17
|
-
|
|
20
|
+
const onUse = enabled === 'on-use';
|
|
21
|
+
if (onUse && (scope !== 'project' || !projectRoot || projectPluginsDir(projectRoot) === globalPluginsDir() || clear)) {
|
|
22
|
+
throw new Error('On use is available for individual repository brains.');
|
|
23
|
+
}
|
|
24
|
+
if ((enabled === false || onUse) && REQUIRED_INSTALLATION_PLUGIN_IDS.includes(id)) {
|
|
18
25
|
throw new Error('Required plugin ' + id + ' cannot be disabled');
|
|
19
26
|
}
|
|
20
27
|
if (clear === true) {
|
|
21
28
|
const plugin = getPlugin(id, projectRoot);
|
|
22
29
|
if (!plugin?.valid) throw new Error(`Plugin ${id} is missing or invalid`);
|
|
23
|
-
await
|
|
24
|
-
|
|
30
|
+
await withRepositoryPluginLifecycle(projectRoot, id, async brain => {
|
|
31
|
+
if (!usesSharedPluginPolicy(plugin) || pluginActivation(plugin, { projectRoot: null }).enabled) {
|
|
32
|
+
moveRepositoryPluginState(brain, id, 'restore');
|
|
33
|
+
}
|
|
34
|
+
await patchProjectActivationRecord(id, projectRoot, null);
|
|
35
|
+
await emit(vaultForPluginsDir(projectPluginsDir(projectRoot)), id, 'activation-cleared', {});
|
|
36
|
+
});
|
|
25
37
|
const compilation = await recompileAfterPluginMutation(projectRoot, false);
|
|
26
38
|
return { pluginId: id, activation: pluginActivation(plugin, { projectRoot }), scope: 'shared', compilation };
|
|
27
39
|
}
|
|
28
|
-
if (
|
|
40
|
+
if (onUse) enabled = false;
|
|
41
|
+
if (typeof enabled !== 'boolean') throw new Error('Plugin activation requires a boolean or On use');
|
|
29
42
|
const plugin = getPlugin(id, projectRoot);
|
|
30
43
|
if (!plugin?.valid) throw new Error(`Plugin ${id} is missing or invalid`);
|
|
31
44
|
if (scope === 'shared') {
|
|
32
|
-
if (plugin
|
|
33
|
-
await patchPluginRecord(plugin, { runtime_enabled: enabled });
|
|
45
|
+
if (!usesSharedPluginPolicy(plugin)) throw new Error(`Plugin ${id} is a ${plugin.scope} copy without a shared setting to change`);
|
|
46
|
+
await patchPluginRecord(plugin, { runtime_enabled: enabled, runtime_on_use: false });
|
|
34
47
|
await emit(vaultFor(plugin), id, enabled ? 'activated' : 'deactivated', { enabled, scope: 'shared' });
|
|
35
48
|
const compilation = await recompileAfterPluginMutation(projectRoot, true);
|
|
36
49
|
return { pluginId: id, activation: pluginActivation(plugin, { projectRoot }), scope: 'shared', compilation };
|
|
37
50
|
}
|
|
38
51
|
// Repository scope. A repository-owned copy already is that repository's setting.
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
52
|
+
const event = onUse ? 'activation-on-use' : enabled ? 'activated' : 'deactivated';
|
|
53
|
+
const shared = usesSharedPluginPolicy(plugin);
|
|
54
|
+
const resultScope = shared ? 'project' : plugin.scope;
|
|
55
|
+
const vaultRoot = shared ? vaultForPluginsDir(projectPluginsDir(projectRoot)) : vaultFor(plugin);
|
|
56
|
+
const cleanup = await withRepositoryPluginLifecycle(projectRoot, id, async brain => {
|
|
57
|
+
if (onUse && !brain) throw new Error('On use is available for individual repository brains.');
|
|
58
|
+
let result = enabled ? moveRepositoryPluginState(brain, id, 'restore') : undefined;
|
|
59
|
+
if (shared) await patchProjectActivationRecord(id, projectRoot, enabled, { manifest: plugin.manifest, onUse });
|
|
60
|
+
else await patchPluginRecord(plugin, { runtime_enabled: enabled, runtime_on_use: onUse });
|
|
61
|
+
if (!enabled && !onUse) {
|
|
62
|
+
try { result = moveRepositoryPluginState(brain, id, 'archive'); }
|
|
63
|
+
catch (error) {
|
|
64
|
+
result = { ok: false, state: 'pending', error: error.code ? `Could not archive repository plugin state (${error.code}).` : error.message };
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
await emit(vaultRoot, id, event, { enabled, scope: resultScope, ...(result ? { cleanup: result.state } : {}) });
|
|
68
|
+
return result;
|
|
69
|
+
});
|
|
70
|
+
const compilation = await recompileAfterPluginMutation(projectRoot, false);
|
|
71
|
+
return { pluginId: id, activation: pluginActivation(plugin, { projectRoot }), scope: resultScope, compilation, ...(cleanup ? { cleanup } : {}) };
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** Claim one armed project policy through the SSSS compare-and-set writer. */
|
|
75
|
+
export async function activatePluginOnUse(id, { projectRoot = process.cwd() } = {}) {
|
|
76
|
+
if (!projectRoot || projectPluginsDir(projectRoot) === globalPluginsDir()) return null;
|
|
77
|
+
const plugin = getPlugin(id, projectRoot);
|
|
78
|
+
if (!plugin?.valid || pluginActivation(plugin, { projectRoot }).mode !== 'on-use') return null;
|
|
79
|
+
const vaultRoot = usesSharedPluginPolicy(plugin) ? vaultForPluginsDir(projectPluginsDir(projectRoot)) : vaultFor(plugin);
|
|
80
|
+
const cleanup = await withRepositoryPluginLifecycle(projectRoot, id, async brain => {
|
|
81
|
+
if (!brain) return null;
|
|
82
|
+
const current = readActivationRecord(path.join(vaultRoot, recordPath(id)), id, { withHash: true });
|
|
83
|
+
if (current?.record.runtime_on_use !== true) return null;
|
|
84
|
+
const result = moveRepositoryPluginState(brain, id, 'restore');
|
|
85
|
+
await patchVfsDocument(recordPath(id), { runtime_enabled: true, runtime_on_use: false, timestamp: new Date().toISOString() }, {
|
|
86
|
+
vaultRoot, expectedBeforeHash: current.hash, intent: 'Activate plugin on deliberate use',
|
|
87
|
+
});
|
|
88
|
+
await emit(vaultRoot, id, 'activated-on-use', { enabled: true, scope: 'project', cleanup: result.state });
|
|
89
|
+
return result;
|
|
90
|
+
});
|
|
91
|
+
if (!cleanup) return null;
|
|
49
92
|
const compilation = await recompileAfterPluginMutation(projectRoot, false);
|
|
50
|
-
return { pluginId: id, activation: pluginActivation(plugin, { projectRoot }), scope: 'project', compilation };
|
|
93
|
+
return { pluginId: id, activation: pluginActivation(plugin, { projectRoot }), scope: 'project', compilation, cleanup };
|
|
51
94
|
}
|