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,228 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP stdio (JSONL), with the initialize lifecycle used by Claude and Codex.
|
|
3
|
+
* Protocol: https://modelcontextprotocol.io/specification/2025-11-25
|
|
4
|
+
* Approval result: https://code.claude.com/docs/en/agent-sdk/user-input
|
|
5
|
+
*/
|
|
6
|
+
import { createInterface } from 'node:readline';
|
|
7
|
+
import { execFile } from 'node:child_process';
|
|
8
|
+
import { promisify } from 'node:util';
|
|
9
|
+
import { randomUUID } from 'node:crypto';
|
|
10
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
11
|
+
import { brainDir } from './paths.mjs';
|
|
12
|
+
import { appendEvent, jobPaths, tailInbox } from './control.mjs';
|
|
13
|
+
|
|
14
|
+
const execute = promisify(execFile);
|
|
15
|
+
export const QUESTION_TIMEOUT_MS = 10 * 60_000;
|
|
16
|
+
export const NO_ANSWER = 'No answer; proceed on your best judgment';
|
|
17
|
+
const versions = ['2025-11-25', '2025-06-18', '2025-03-26', '2024-11-05'];
|
|
18
|
+
const object = value => value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
19
|
+
const textResult = text => ({ content: [{ type: 'text', text }] });
|
|
20
|
+
const fault = (code, message) => Object.assign(new Error(message), { code });
|
|
21
|
+
|
|
22
|
+
export const MCP_TOOLS = [
|
|
23
|
+
{ name: 'ask', description: 'Ask the operator questions and wait for a reply.', inputSchema: {
|
|
24
|
+
type: 'object', properties: { questions: { type: 'array', minItems: 1, items: { oneOf: [{ type: 'string', minLength: 1 }, { type: 'object' }] } } }, required: ['questions'], additionalProperties: false,
|
|
25
|
+
} },
|
|
26
|
+
{ name: 'approve', description: 'Answer a Claude Code permission prompt under the job approval policy.', inputSchema: {
|
|
27
|
+
type: 'object', properties: { tool_name: { type: 'string', minLength: 1 }, input: { type: 'object' }, tool_use_id: { type: 'string' } }, required: ['tool_name', 'input'],
|
|
28
|
+
} },
|
|
29
|
+
];
|
|
30
|
+
|
|
31
|
+
/** Return Claude's --mcp-config object and Codex's -c arguments. No shell parses these values. */
|
|
32
|
+
export function mcpConfigFor(job, options = {}) {
|
|
33
|
+
const id = jobPaths(job).id;
|
|
34
|
+
const command = process.execPath;
|
|
35
|
+
const args = [fileURLToPath(import.meta.url), '--approvals', options.approvalPolicy || 'auto',
|
|
36
|
+
'--question-timeout-ms', String(options.questionTimeoutMs ?? options.timeoutMs ?? QUESTION_TIMEOUT_MS)];
|
|
37
|
+
const env = { TR_METAHARNESS_JOB: id, TR_SECRETS_BRAIN: brainDir() };
|
|
38
|
+
if (process.env.TOTAL_RECALL_BIN) env.TOTAL_RECALL_BIN = process.env.TOTAL_RECALL_BIN;
|
|
39
|
+
const claude = { mcpServers: { metaharness: { command, args, env } } };
|
|
40
|
+
const tomlEnv = `{ ${Object.entries(env).map(([key, value]) => `${key} = ${JSON.stringify(value)}`).join(', ')} }`;
|
|
41
|
+
const codex = ['-c', `mcp_servers.metaharness.command=${JSON.stringify(command)}`,
|
|
42
|
+
'-c', `mcp_servers.metaharness.args=${JSON.stringify(args)}`, '-c', `mcp_servers.metaharness.env=${tomlEnv}`,
|
|
43
|
+
'-c', `mcp_servers.metaharness.tool_timeout_sec=${Math.ceil(Number(args.at(-1)) / 1000) + 60}`];
|
|
44
|
+
return { claude, codex, claudeArgs: ['--mcp-config', JSON.stringify(claude), '--permission-prompt-tool', 'mcp__metaharness__approve'], codexArgs: codex };
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** The decision owner returns a typed choice. Missing or failed decisions deny the call. */
|
|
48
|
+
async function decideApproval(request, { signal } = {}) {
|
|
49
|
+
const questions = { approval: { type: 'choice', instructions: 'Apply Total Recall rules to this tool request. Allow only if the request is authorized. Deny if authorization is unclear.',
|
|
50
|
+
criteria: { allow: 'Authorized by the operator and the applicable rules.', deny: 'Not authorized or prohibited by a rule.' } } };
|
|
51
|
+
const { stdout } = await execute(process.env.TOTAL_RECALL_BIN || 'total-recall',
|
|
52
|
+
['decision', 'run', '--state', JSON.stringify({ request }), '--questions', JSON.stringify(questions), '--json'],
|
|
53
|
+
{ encoding: 'utf8', timeout: 60_000, maxBuffer: 1024 * 1024, signal });
|
|
54
|
+
const record = JSON.parse(stdout);
|
|
55
|
+
if (record.ok === false) throw new Error(record.error || 'The decision owner failed.');
|
|
56
|
+
const answer = record.answers?.approval ?? record.decision?.answers?.approval ?? record.result?.approval;
|
|
57
|
+
const value = typeof answer === 'string' ? answer : answer?.choice;
|
|
58
|
+
if (!['allow', 'deny'].includes(value)) throw new Error('The decision owner returned no allow or deny answer.');
|
|
59
|
+
return { value, record };
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Resolve all pending calls on close; no poll timer or child command outlives the server. */
|
|
63
|
+
export function createMcpTools({ job = process.env.TR_METAHARNESS_JOB, approvalPolicy = 'auto',
|
|
64
|
+
questionTimeoutMs = QUESTION_TIMEOUT_MS, timeoutMs, decisionFn = decideApproval, alertFn,
|
|
65
|
+
deferQuestions = process.env.TR_METAHARNESS_DEFER_QUESTIONS !== '0' } = {}) {
|
|
66
|
+
jobPaths(job);
|
|
67
|
+
if (!['auto', 'operator', 'rules'].includes(approvalPolicy)) throw new Error('Approval policy must be auto, operator, or rules.');
|
|
68
|
+
questionTimeoutMs = timeoutMs ?? questionTimeoutMs;
|
|
69
|
+
if (!Number.isSafeInteger(questionTimeoutMs) || questionTimeoutMs < 1) throw new Error('Question timeout must be a positive number of milliseconds.');
|
|
70
|
+
const pending = new Map();
|
|
71
|
+
const lifetime = new AbortController();
|
|
72
|
+
const children = new Set();
|
|
73
|
+
const notify = event => {
|
|
74
|
+
const task = alertFn ? Promise.resolve().then(() => alertFn(event)) : execute(process.env.TOTAL_RECALL_BIN || 'total-recall',
|
|
75
|
+
['alerts', 'send', '--title', `Metaharness: ${event.kind}`, '--message', `Job ${job}: ${event.text}`, '--severity', 'info', '--source', 'meta-harness'],
|
|
76
|
+
{ timeout: 15_000, maxBuffer: 65536, signal: lifetime.signal });
|
|
77
|
+
children.add(task);
|
|
78
|
+
task.catch(() => {}).finally(() => children.delete(task));
|
|
79
|
+
};
|
|
80
|
+
const watcher = tailInbox(job, command => {
|
|
81
|
+
const wait = pending.get(command.requestId);
|
|
82
|
+
if (!wait || command.type !== (wait.kind === 'question' ? 'reply' : 'approve')) return false;
|
|
83
|
+
wait.finish({ value: wait.kind === 'question' ? command.text : command.value, commandId: command.id });
|
|
84
|
+
return { via: 'metaharness' };
|
|
85
|
+
}, { recipient: 'mcp', onError: error => {
|
|
86
|
+
for (const wait of pending.values()) wait.fail(error);
|
|
87
|
+
} });
|
|
88
|
+
|
|
89
|
+
const waitFor = (event, signal) => new Promise((resolve, reject) => {
|
|
90
|
+
let timer;
|
|
91
|
+
const cleanup = () => { clearTimeout(timer); pending.delete(event.requestId); signal?.removeEventListener('abort', abort); };
|
|
92
|
+
const finish = value => { cleanup(); resolve(value); };
|
|
93
|
+
const fail = error => { cleanup(); reject(error); };
|
|
94
|
+
const abort = () => fail(new Error('The request was cancelled.'));
|
|
95
|
+
pending.set(event.requestId, { kind: event.kind, finish, fail });
|
|
96
|
+
signal?.addEventListener('abort', abort, { once: true });
|
|
97
|
+
if (signal?.aborted || lifetime.signal.aborted) { abort(); return; }
|
|
98
|
+
timer = setTimeout(() => finish({ value: event.kind === 'question' ? NO_ANSWER : 'deny', timeout: true }), questionTimeoutMs);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
return {
|
|
102
|
+
async call(name, args, { signal, defer = deferQuestions } = {}) {
|
|
103
|
+
if (lifetime.signal.aborted) throw new Error('The MCP server has closed.');
|
|
104
|
+
if (name === 'ask') {
|
|
105
|
+
if (!object(args) || !Array.isArray(args.questions) || !args.questions.length ||
|
|
106
|
+
args.questions.some(q => typeof q === 'string' ? !q.trim() : !object(q))) throw fault(-32602, 'ask requires a non-empty questions array.');
|
|
107
|
+
} else if (name === 'approve') {
|
|
108
|
+
if (!object(args) || typeof args.tool_name !== 'string' || !args.tool_name.trim() || !object(args.input) ||
|
|
109
|
+
(args.tool_use_id !== undefined && typeof args.tool_use_id !== 'string')) throw fault(-32602, 'approve requires tool_name and input.');
|
|
110
|
+
} else throw fault(-32602, `Unknown tool: ${name}`);
|
|
111
|
+
const requestId = randomUUID();
|
|
112
|
+
if (name === 'ask' && defer) {
|
|
113
|
+
// A question costs nothing while it waits (A-125): record it, tell the agent to end its turn,
|
|
114
|
+
// and let the session runner start the next turn with the operator's answer. Holding the tool
|
|
115
|
+
// call open made Codex call the model every few seconds while it waited.
|
|
116
|
+
const event = { kind: 'question', source: 'deferred', requestId, text: JSON.stringify(args.questions), questions: args.questions };
|
|
117
|
+
appendEvent(job, event);
|
|
118
|
+
notify(event);
|
|
119
|
+
return textResult(`Your question went to the operator (request ${requestId}). End your turn now and do no other work. The operator's answer arrives as the next message in this session.`);
|
|
120
|
+
}
|
|
121
|
+
const event = { kind: name === 'ask' ? 'question' : 'approval', source: 'mcp', requestId,
|
|
122
|
+
text: name === 'ask' ? JSON.stringify(args.questions) : `${args.tool_name}: ${JSON.stringify(args.input)}`,
|
|
123
|
+
...(name === 'ask' ? { questions: args.questions } : { request: args, policy: approvalPolicy }) };
|
|
124
|
+
appendEvent(job, event);
|
|
125
|
+
let answer;
|
|
126
|
+
try {
|
|
127
|
+
if (name === 'ask' || approvalPolicy === 'operator') {
|
|
128
|
+
// Register the waiter before notifying the operator.
|
|
129
|
+
const waiting = waitFor(event, signal);
|
|
130
|
+
notify(event);
|
|
131
|
+
answer = await waiting;
|
|
132
|
+
} else if (approvalPolicy === 'auto') answer = { value: 'allow', policy: 'auto' };
|
|
133
|
+
else {
|
|
134
|
+
try { answer = { ...await decisionFn(args, { signal: signal ? AbortSignal.any([signal, lifetime.signal]) : lifetime.signal }), policy: 'rules' }; }
|
|
135
|
+
catch (error) { answer = { value: 'deny', policy: 'rules', error: error.message }; }
|
|
136
|
+
if (!['allow', 'deny'].includes(answer.value)) answer = { value: 'deny', policy: 'rules', error: 'Invalid decision answer.' };
|
|
137
|
+
}
|
|
138
|
+
} catch (error) {
|
|
139
|
+
appendEvent(job, { kind: 'ack', command: name, requestId, ok: true, cancelled: true, text: error.message });
|
|
140
|
+
throw error;
|
|
141
|
+
}
|
|
142
|
+
// tailInbox records delivery; this event records the actual answer and policy decision.
|
|
143
|
+
appendEvent(job, { kind: 'ack', command: name, requestId, ok: true, ...answer, text: String(answer.value) });
|
|
144
|
+
if (name === 'ask') return textResult(String(answer.value));
|
|
145
|
+
const result = answer.value === 'allow' ? { behavior: 'allow', updatedInput: args.input }
|
|
146
|
+
: { behavior: 'deny', message: answer.timeout ? 'Approval timed out.' : answer.error || 'The request was denied.' };
|
|
147
|
+
return textResult(JSON.stringify(result));
|
|
148
|
+
},
|
|
149
|
+
async close() {
|
|
150
|
+
lifetime.abort();
|
|
151
|
+
for (const wait of pending.values()) wait.fail(new Error('The MCP server has closed.'));
|
|
152
|
+
await watcher.close();
|
|
153
|
+
await Promise.allSettled(children);
|
|
154
|
+
},
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/** Never log on stdout here: every line must be a JSON-RPC message. */
|
|
159
|
+
export async function runMcpServer({ input = process.stdin, output = process.stdout, ...options } = {}) {
|
|
160
|
+
const tools = createMcpTools(options);
|
|
161
|
+
const lines = createInterface({ input, crlfDelay: Infinity });
|
|
162
|
+
const calls = new Map();
|
|
163
|
+
let initialized = false, ready = false, closed = false;
|
|
164
|
+
const write = message => { if (!closed) output.write(JSON.stringify(message) + '\n'); };
|
|
165
|
+
const respond = (id, result) => write({ jsonrpc: '2.0', id, result });
|
|
166
|
+
const error = (id, code, message) => write({ jsonrpc: '2.0', id, error: { code, message } });
|
|
167
|
+
const handle = async message => {
|
|
168
|
+
if (!object(message) || message.jsonrpc !== '2.0' || typeof message.method !== 'string' ||
|
|
169
|
+
(Object.hasOwn(message, 'id') && typeof message.id !== 'string' && typeof message.id !== 'number') ||
|
|
170
|
+
(message.params !== undefined && !object(message.params))) {
|
|
171
|
+
error(null, -32600, 'Invalid Request'); return;
|
|
172
|
+
}
|
|
173
|
+
const { id, method, params = {} } = message;
|
|
174
|
+
if (id === undefined) {
|
|
175
|
+
if (method === 'notifications/initialized' && initialized) ready = true;
|
|
176
|
+
if (method === 'notifications/cancelled') calls.get(params.requestId)?.controller.abort();
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
if (calls.has(id)) { error(id, -32600, 'Duplicate request ID'); return; }
|
|
180
|
+
if (method === 'initialize') {
|
|
181
|
+
if (initialized) { error(id, -32600, 'Already initialized'); return; }
|
|
182
|
+
if (typeof params.protocolVersion !== 'string' || !object(params.capabilities) || !object(params.clientInfo)) {
|
|
183
|
+
error(id, -32602, 'initialize requires protocolVersion, capabilities, and clientInfo'); return;
|
|
184
|
+
}
|
|
185
|
+
initialized = true;
|
|
186
|
+
respond(id, { protocolVersion: versions.includes(params.protocolVersion) ? params.protocolVersion : versions[0],
|
|
187
|
+
capabilities: { tools: {} }, serverInfo: { name: 'metaharness', version: '1.0.0' } });
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
if (method === 'ping') { respond(id, {}); return; }
|
|
191
|
+
if (!ready) { error(id, -32002, 'Initialize the MCP session first'); return; }
|
|
192
|
+
if (method === 'tools/list') { respond(id, { tools: MCP_TOOLS }); return; }
|
|
193
|
+
if (method !== 'tools/call') { error(id, -32601, 'Method not found'); return; }
|
|
194
|
+
if (typeof params.name !== 'string') { error(id, -32602, 'tools/call requires a tool name'); return; }
|
|
195
|
+
const controller = new AbortController();
|
|
196
|
+
const call = { controller };
|
|
197
|
+
calls.set(id, call);
|
|
198
|
+
call.done = (async () => {
|
|
199
|
+
try { respond(id, await tools.call(params.name, params.arguments, { signal: controller.signal })); }
|
|
200
|
+
catch (failure) {
|
|
201
|
+
if (typeof failure.code === 'number') error(id, failure.code, failure.message);
|
|
202
|
+
else respond(id, { ...textResult(failure.message), isError: true });
|
|
203
|
+
} finally { calls.delete(id); }
|
|
204
|
+
})();
|
|
205
|
+
};
|
|
206
|
+
lines.on('line', line => {
|
|
207
|
+
let message;
|
|
208
|
+
try { message = JSON.parse(line); } catch { error(null, -32700, 'Parse error'); return; }
|
|
209
|
+
void handle(message).catch(failure => error(message?.id ?? null, -32603, failure.message));
|
|
210
|
+
});
|
|
211
|
+
try { await new Promise((resolve, reject) => { lines.once('close', resolve); input.once('error', reject); output.once('error', reject); }); }
|
|
212
|
+
finally {
|
|
213
|
+
closed = true;
|
|
214
|
+
lines.close();
|
|
215
|
+
for (const call of calls.values()) call.controller.abort();
|
|
216
|
+
await tools.close();
|
|
217
|
+
await Promise.allSettled([...calls.values()].map(call => call.done));
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
export const startMcpServer = runMcpServer;
|
|
222
|
+
|
|
223
|
+
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
|
|
224
|
+
const value = flag => { const i = process.argv.indexOf(flag); return i < 0 ? undefined : process.argv[i + 1]; };
|
|
225
|
+
await runMcpServer({ approvalPolicy: value('--approvals') || 'auto',
|
|
226
|
+
questionTimeoutMs: value('--question-timeout-ms') === undefined ? QUESTION_TIMEOUT_MS : Number(value('--question-timeout-ms')) })
|
|
227
|
+
.catch(error => { console.error(`Metaharness MCP: ${error.message}`); process.exitCode = 1; });
|
|
228
|
+
}
|
|
@@ -161,7 +161,7 @@ export async function executeProcessTask(job, dependencies = {}) {
|
|
|
161
161
|
tools: job.options.tools, settingSources: job.options.settingSources, model: job.options.model,
|
|
162
162
|
allowUnknownAuth: job.options.allowUnknownAuth === true, timeoutMs: job.options.timeoutMs,
|
|
163
163
|
}, { role: 'Process', node: 'local' });
|
|
164
|
-
if (result.ok && worktree) commit = commitAll(worktree, '
|
|
164
|
+
if (result.ok && worktree) commit = commitAll(worktree, 'Metaharness managed agent work');
|
|
165
165
|
} catch (error) {
|
|
166
166
|
result = { ok: false, error: error.message };
|
|
167
167
|
}
|
|
@@ -169,9 +169,18 @@ export async function executeProcessTask(job, dependencies = {}) {
|
|
|
169
169
|
if (worktree) { (dependencies.removeWorktree || removeWorktree)(job.cwd, worktree); worktree = null; }
|
|
170
170
|
if (branch && !commit) { (dependencies.deleteBranch || deleteBranch)(job.cwd, branch); branch = null; }
|
|
171
171
|
} catch (error) { result = { ...result, ok: false, error: `${result.error ? result.error + '; ' : ''}Isolation cleanup failed: ${error.message}` }; }
|
|
172
|
-
|
|
172
|
+
const record = updateAgentRecord(job.id, { status: result.ok ? 'completed' : 'failed', exitCode: result.exitCode ?? (result.ok ? 0 : 1), error: result.ok ? null : result.error,
|
|
173
173
|
...(result.queueId ? { queueId: result.queueId } : {}),
|
|
174
174
|
result: result.response || null, branch, commit, worktreePath: worktree, endedAt: new Date().toISOString() });
|
|
175
|
+
return {
|
|
176
|
+
...record,
|
|
177
|
+
...(Array.isArray(result.toolResults) ? {
|
|
178
|
+
toolResults: result.toolResults,
|
|
179
|
+
toolExecutionVerified: result.toolExecutionVerified,
|
|
180
|
+
commandExecutionVerified: result.commandExecutionVerified,
|
|
181
|
+
} : {}),
|
|
182
|
+
...(result.toolEvidenceError ? { toolEvidenceError: result.toolEvidenceError } : {}),
|
|
183
|
+
};
|
|
175
184
|
}
|
|
176
185
|
|
|
177
186
|
export async function killAgent(idOrPid, dependencies = {}) {
|
|
@@ -211,6 +220,20 @@ export async function getAgentLogs(idOrPid, tailLines = 50, dependencies = {}) {
|
|
|
211
220
|
if (record.remote) {
|
|
212
221
|
const result = await remoteCall(record.node, record.cwd, ['logs', record.id, '--tail', String(tailLines)], dependencies);
|
|
213
222
|
if (typeof result.logs !== 'string') throw new Error('Remote owner returned no logs');
|
|
223
|
+
if (['starting', 'running'].includes(record.status)) {
|
|
224
|
+
for (const line of result.logs.trimEnd().split('\n').reverse()) {
|
|
225
|
+
let terminal;
|
|
226
|
+
try { terminal = JSON.parse(line); } catch { continue; }
|
|
227
|
+
if (terminal?.id !== record.id || !['completed', 'failed', 'killed'].includes(terminal.status) ||
|
|
228
|
+
typeof terminal.endedAt !== 'string' || !Number.isFinite(Date.parse(terminal.endedAt))) continue;
|
|
229
|
+
updateAgentRecord(record.id, {
|
|
230
|
+
status: terminal.status,
|
|
231
|
+
exitCode: Number.isInteger(terminal.exitCode) ? terminal.exitCode : null,
|
|
232
|
+
endedAt: terminal.endedAt,
|
|
233
|
+
});
|
|
234
|
+
break;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
214
237
|
return result.logs;
|
|
215
238
|
}
|
|
216
239
|
if (path.dirname(record.logFile || '') !== logDirectory()) throw new Error('Invalid managed log path');
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** Headless reasoning belongs to
|
|
1
|
+
/** Headless reasoning belongs to Metaharness, including config, readiness and receipts. */
|
|
2
2
|
import fs from 'node:fs';
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import { brainDir } from './paths.mjs';
|
|
@@ -9,6 +9,7 @@ const BOOLEAN_FLAGS = {
|
|
|
9
9
|
};
|
|
10
10
|
const VALUE_FLAGS = {
|
|
11
11
|
mode: '--mode', orchestrator: '--orchestrator', explorer: '--explorer', architect: '--architect', implementer: '--implementer',
|
|
12
|
+
goal: '--goal', maxTurns: '--max-turns', maxBudgetUsd: '--max-budget-usd', maxTokens: '--max-tokens', approvalPolicy: '--approvals', questionTimeoutMs: '--question-timeout-ms', resultSchema: '--result-schema',
|
|
12
13
|
verifier: '--verifier', reviewer: '--reviewer', author: '--author', threadId: '--thread', branch: '--branch',
|
|
13
14
|
};
|
|
14
15
|
const OPERATION_KEYS = {
|
|
@@ -33,9 +34,12 @@ export async function forwardRemoteOperation(operation, task, options = {}) {
|
|
|
33
34
|
if (typeof task !== 'string' || !task.trim()) throw new Error('Remote operation requires a task description');
|
|
34
35
|
argv.push(task);
|
|
35
36
|
}
|
|
36
|
-
|
|
37
|
+
const controls = ['route', 'coordinate'].includes(operation) ? ['goal', 'maxTurns', 'maxBudgetUsd', 'maxTokens', 'approvalPolicy', 'questionTimeoutMs', 'resultSchema'] : [];
|
|
38
|
+
for (const key of [...OPERATION_KEYS[operation], ...controls]) {
|
|
37
39
|
if (BOOLEAN_FLAGS[key]) { if (options[key] === true) argv.push(BOOLEAN_FLAGS[key]); }
|
|
38
40
|
else if (options[key] !== undefined && options[key] !== null) {
|
|
41
|
+
if (['maxTurns', 'maxBudgetUsd', 'maxTokens', 'questionTimeoutMs'].includes(key)) { argv.push(VALUE_FLAGS[key], String(options[key])); continue; }
|
|
42
|
+
if (key === 'resultSchema' && typeof options[key] !== 'string') { argv.push('--result-schema-json', JSON.stringify(options[key])); continue; }
|
|
39
43
|
if (typeof options[key] !== 'string' || !options[key] || /\0/.test(options[key])) throw new Error(`Invalid remote ${key}`);
|
|
40
44
|
argv.push(VALUE_FLAGS[key], options[key]);
|
|
41
45
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Metaharness Universal Cross-Model Adversarial Code Review Engine
|
|
3
3
|
*
|
|
4
4
|
* Runs automated code reviews across integrated agent platforms (claude, codex, agy,
|
|
5
5
|
* grok, dsh, hermes, etc.).
|
|
@@ -19,6 +19,7 @@ import { resolvePool, localExecutionNode } from './pool.mjs';
|
|
|
19
19
|
import { lastJsonWith } from './json-reply.mjs';
|
|
20
20
|
import { createWorktree, removeWorktree, commitAll, headCommit } from './worktree.mjs';
|
|
21
21
|
import { forwardRemoteOperation } from './remote-operation.mjs';
|
|
22
|
+
import { recordReview } from './reviews.mjs';
|
|
22
23
|
|
|
23
24
|
const MAX_DIFF = 30000;
|
|
24
25
|
// Generated surfaces say nothing a reviewer can act on, and they crowd out the source.
|
|
@@ -129,11 +130,13 @@ export function buildReviewPrompt(diff, context = {}) {
|
|
|
129
130
|
You are an independent, highly critical senior security and architecture engineer performing an adversarial code review.
|
|
130
131
|
You did NOT write this code. Do not rubber-stamp. Look for vulnerabilities, silent failures, regressions, anti-patterns, and test coverage gaps.
|
|
131
132
|
|
|
132
|
-
${task}${branch}${context.stat ? `Files changed:\n${context.stat}\n\n` : ''}${context.untracked?.length ? `New untracked files, not in the diff; read them too:\n${context.untracked.slice(0, 100).join('\n')}\n\n` : ''}${diff.length > MAX_DIFF ? `This diff is cut at ${MAX_DIFF} of ${diff.length} characters. Read the remainder from the repository and say so if you could not.\n` : ''}GIT DIFF TO REVIEW:
|
|
133
|
+
${task}${branch}${context.evidence ? `Job evidence (recorded by Metaharness, not by the author):\n${JSON.stringify(context.evidence, null, 2).slice(0, 8000)}\n\n` : ''}${context.stat ? `Files changed:\n${context.stat}\n\n` : ''}${context.untracked?.length ? `New untracked files, not in the diff; read them too:\n${context.untracked.slice(0, 100).join('\n')}\n\n` : ''}${diff.length > MAX_DIFF ? `This diff is cut at ${MAX_DIFF} of ${diff.length} characters. Read the remainder from the repository and say so if you could not.\n` : ''}GIT DIFF TO REVIEW:
|
|
133
134
|
\`\`\`diff
|
|
134
135
|
${diff.slice(0, MAX_DIFF)}
|
|
135
136
|
\`\`\`
|
|
136
137
|
|
|
138
|
+
Judge the diff. Use the job evidence for claims about how the job ran (questions asked, replies, the goal check, the gate). A claim you cannot verify from the diff or the evidence is a "suggestion" marked unverified in its issue text; it is never "critical" or blocking. Mark a finding "critical" only for a defect in the diff itself.
|
|
139
|
+
|
|
137
140
|
Evaluate the diff against these strict criteria:
|
|
138
141
|
1. Security & Blast Radius (privilege escalation, token leakage, unhandled exceptions)
|
|
139
142
|
2. Invariant & Rule Adherence (does it break existing contracts or introduce silent side effects?)
|
|
@@ -166,14 +169,39 @@ export function parseReviewVerdict(response) {
|
|
|
166
169
|
return { verdict: 'NEEDS_DISCUSSION', parsed: false, riskScore: null, summary: text.slice(0, 300) || 'The reviewer returned nothing readable.', findings: [] };
|
|
167
170
|
}
|
|
168
171
|
|
|
172
|
+
export function reviewBlocksPush(result) {
|
|
173
|
+
if (result?.ok !== true) return true;
|
|
174
|
+
if (result.verdict === 'NO_DIFF') return false;
|
|
175
|
+
const review = result.review;
|
|
176
|
+
// R45.8: only blocking findings stop the push; other findings go to the job result.
|
|
177
|
+
// An unreadable review cannot clear a push, so it blocks.
|
|
178
|
+
return !review || review.parsed === false ||
|
|
179
|
+
review.findings?.some(f => f.blocking === true || ['blocking', 'critical'].includes(f.severity)) === true;
|
|
180
|
+
}
|
|
181
|
+
|
|
169
182
|
export async function executeCodeReview(options = {}) {
|
|
170
183
|
const remote = await forwardRemoteOperation('review', null, options);
|
|
171
184
|
if (remote) return remote;
|
|
172
185
|
localExecutionNode(options);
|
|
186
|
+
const selection = { workspace: options.cwd || process.cwd(), target: options.target || (options.staged ? '--staged' : 'working tree'), reviewer: options.reviewer || null };
|
|
187
|
+
let result;
|
|
188
|
+
try { result = await executeLocalReview(options, selection); }
|
|
189
|
+
catch (error) {
|
|
190
|
+
// Preserve the existing CLI error contract, but retain failed attempts too.
|
|
191
|
+
try { recordReview({ ok: false, error: error.message }, selection); }
|
|
192
|
+
catch (storeError) { throw new Error(`${error.message}; review store failed: ${storeError.message}`); }
|
|
193
|
+
throw error;
|
|
194
|
+
}
|
|
195
|
+
try { return { ...result, reviewId: recordReview(result, selection).id }; }
|
|
196
|
+
catch (error) { return { ...result, ok: false, reviewStoreError: error.message }; }
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
async function executeLocalReview(options, selection) {
|
|
173
200
|
const cwd = options.cwd || process.cwd();
|
|
174
201
|
const author = options.author || null;
|
|
175
202
|
const diffResult = extractGitDiff({ cwd, target: options.target, staged: options.staged });
|
|
176
203
|
if (!diffResult.ok) throw new Error(`Failed to read the diff: ${diffResult.error}`);
|
|
204
|
+
Object.assign(selection, { diff: diffResult.diff, untracked: diffResult.untracked, target: diffResult.target, commit: headCommit(cwd) });
|
|
177
205
|
if (!diffResult.diff && !diffResult.untracked?.length) return { ok: true, verdict: 'NO_DIFF', target: diffResult.target, summary: `Nothing to review for ${diffResult.target}.` };
|
|
178
206
|
|
|
179
207
|
const { ready, excluded } = await resolvePool(options);
|
|
@@ -184,13 +212,16 @@ export async function executeCodeReview(options = {}) {
|
|
|
184
212
|
const reviewerFamily = ADAPTER_CATALOG[reviewer.id]?.family || reviewer.family || null;
|
|
185
213
|
if (author && (reviewer.id === author || (authorFamily && authorFamily === reviewerFamily))) throw new Error(`${reviewer.id} shares a model family with the author ${author}, so it cannot review this independently`);
|
|
186
214
|
const independence = author ? 'verified' : 'unverified: the author was not named';
|
|
215
|
+
selection.reviewer = reviewer.id;
|
|
187
216
|
const truncated = diffResult.diff.length > MAX_DIFF;
|
|
188
217
|
const snapshot = reviewSnapshot(cwd, diffResult);
|
|
218
|
+
selection.commit = snapshot.commit;
|
|
189
219
|
let result;
|
|
190
220
|
try { result = await dispatchWithReceipt({
|
|
191
221
|
agent: reviewer.id, node: 'local', cwd: snapshot.directory, contextCwd: cwd, contextTask: options.task || `Review the code changes in ${diffResult.target}`,
|
|
192
|
-
prompt: buildReviewPrompt(diffResult.diff, { task: options.task, branch: options.branch || diffResult.target, stat: diffResult.stat, untracked: diffResult.untracked }),
|
|
222
|
+
prompt: buildReviewPrompt(diffResult.diff, { task: options.task, evidence: options.evidence, branch: options.branch || diffResult.target, stat: diffResult.stat, untracked: diffResult.untracked }),
|
|
193
223
|
permissions: { read: true, write: false }, allowUnknownAuth: options.allowUnknownAuth === true,
|
|
224
|
+
...(reviewer.id === 'codex' ? { reviewTarget: { type: 'custom', instructions: buildReviewPrompt(diffResult.diff, { task: options.task, evidence: options.evidence, branch: diffResult.target }) } } : {}),
|
|
194
225
|
}, { dispatchFn: options.dispatchFn, role: 'Reviewer' }); }
|
|
195
226
|
finally { removeWorktree(cwd, snapshot.directory); }
|
|
196
227
|
if (!result.ok) return { ok: false, target: diffResult.target, reviewer: reviewer.id, error: result.error, failureKind: result.failureKind, excluded };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/** Review results are append-only SSSS records, independent of thread lifetime. */
|
|
2
|
+
import crypto from 'node:crypto';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { threadsFile } from './paths.mjs';
|
|
5
|
+
import { PluginStateStore } from './ssss-store.mjs';
|
|
6
|
+
|
|
7
|
+
const store = () => new PluginStateStore(path.join(path.dirname(threadsFile()), 'meta-harness-reviews.jsonl'), 'meta-harness');
|
|
8
|
+
const dispositions = { APPROVE: 'approved', REQUEST_CHANGES: 'changes_requested', NEEDS_DISCUSSION: 'needs_discussion', NO_DIFF: 'no_diff', FAILED: 'failed' };
|
|
9
|
+
|
|
10
|
+
export function readReviews() { return store().read([]); }
|
|
11
|
+
export function recordReview(result, selection = {}) {
|
|
12
|
+
const review = result.review;
|
|
13
|
+
const verdict = review?.verdict || result.verdict || 'FAILED';
|
|
14
|
+
if (!dispositions[verdict]) throw new Error('Invalid review verdict');
|
|
15
|
+
const entry = {
|
|
16
|
+
id: `review-${crypto.randomUUID()}`, timestamp: new Date().toISOString(),
|
|
17
|
+
workspace: selection.workspace, target: review?.target || result.target || selection.target || null,
|
|
18
|
+
commit: review?.snapshotCommit || selection.commit || null,
|
|
19
|
+
diff: selection.diff || '', untracked: selection.untracked || [],
|
|
20
|
+
reviewer: review?.reviewer || result.reviewer || selection.reviewer || null,
|
|
21
|
+
verdict, disposition: dispositions[verdict], result,
|
|
22
|
+
};
|
|
23
|
+
store().append(entry);
|
|
24
|
+
return entry;
|
|
25
|
+
}
|