total-recall-brain 3.43.3 → 3.45.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 +6 -4
- package/docs/ARCHITECTURE.md +10 -7
- package/docs/reference/cli-reference.md +16 -9
- package/frontend/dist/assets/index-DACh1dhx.js +5613 -0
- package/frontend/dist/index.html +1 -1
- package/frontend/src/App.tsx +2 -2
- package/frontend/src/pages/PluginsPage.tsx +1 -1
- package/package.json +3 -3
- package/scaffold/.agent/skills/plugin/SKILL.md +7 -2
- package/scaffold/.agent/skills/plugin/evals/README.md +5 -0
- package/scaffold/.agent/skills/plugin/evals/cases/01-fabricated-seed.mjs +1 -0
- package/scaffold/.agent/skills/plugin/evals/cases/02-reassuring-default.mjs +1 -0
- package/scaffold/.agent/skills/plugin/evals/cases/03-declared-template.mjs +1 -0
- package/scaffold/.agent/skills/plugin/evals/cases/04-card-collects-credential.mjs +1 -0
- package/scaffold/.agent/skills/plugin/evals/cases/05-host-leak-in-scaffold.mjs +1 -0
- package/scaffold/.agent/skills/plugin/evals/cases/06-correct-plugin.mjs +1 -0
- package/scaffold/.agent/skills/plugin/evals/cases/07-missing-reuse.mjs +11 -0
- package/scaffold/.agent/skills/plugin/evals/cases/08-unresolved-owner-command.mjs +12 -0
- package/scaffold/.agent/skills/plugin/evals/cases/09-missing-brick.mjs +12 -0
- package/scaffold/.agent/skills/plugin/prompts/01-function.md +4 -3
- package/scaffold/.agent/skills/plugin/prompts/08-verify.md +1 -0
- package/scaffold/.agent/skills/plugin/references/surfaces.md +12 -2
- package/scaffold/.agent/skills/plugin/scripts/record.mjs +59 -2
- package/scaffold/.agent/skills/total-recall/plugins/auth/README.md +8 -0
- package/scaffold/.agent/skills/total-recall/plugins/auth/package-lock.json +15 -14
- package/scaffold/.agent/skills/total-recall/plugins/auth/package.json +3 -3
- package/scaffold/.agent/skills/total-recall/plugins/auth/plugin.json +1 -1
- package/scaffold/.agent/skills/total-recall/plugins/auth/src/cli-gh-login.mjs +102 -0
- package/scaffold/.agent/skills/total-recall/plugins/auth/src/cli-secret.mjs +38 -2
- package/scaffold/.agent/skills/total-recall/plugins/auth/src/login-projections.mjs +157 -13
- package/scaffold/.agent/skills/total-recall/plugins/auth/src/secrets-store.mjs +12 -1
- package/scaffold/.agent/skills/total-recall/plugins/auth/src/secrets-sync.mjs +161 -17
- package/scaffold/.agent/skills/total-recall/plugins/automations/BRICK.md +7 -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 +231 -0
- package/scaffold/.agent/skills/total-recall/plugins/automations/capability/index.mjs +16 -0
- package/scaffold/.agent/skills/total-recall/plugins/automations/cli.mjs +121 -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 +35 -0
- package/scaffold/.agent/skills/total-recall/plugins/automations/plugin.json +167 -0
- package/scaffold/.agent/skills/total-recall/plugins/automations/scheduler.mjs +246 -0
- package/scaffold/.agent/skills/total-recall/plugins/automations/ui/DESIGN.md +42 -0
- package/scaffold/.agent/skills/total-recall/plugins/automations/ui/automations.js +2 -0
- package/scaffold/.agent/skills/total-recall/plugins/automations/ui/card.js +273 -0
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/commands/run-core.mjs +1 -1
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/core/check.mjs +57 -5
- 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 +15 -14
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/package.json +3 -3
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/plugin.json +1 -1
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/package-lock.json +15 -14
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/package.json +3 -3
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/plugin.json +1 -1
- package/scaffold/.agent/skills/total-recall/plugins/embeddings/package-lock.json +15 -14
- package/scaffold/.agent/skills/total-recall/plugins/embeddings/package.json +3 -3
- package/scaffold/.agent/skills/total-recall/plugins/embeddings/plugin.json +1 -1
- package/scaffold/.agent/skills/total-recall/plugins/git/README.md +112 -0
- package/scaffold/.agent/skills/total-recall/plugins/{git-sentinel → git}/cli.mjs +135 -23
- package/scaffold/.agent/skills/total-recall/plugins/{git-sentinel → git}/package-lock.json +17 -16
- package/scaffold/.agent/skills/total-recall/plugins/{git-sentinel → git}/package.json +5 -4
- package/scaffold/.agent/skills/total-recall/plugins/git/plugin.json +161 -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 +30 -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 +156 -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 +66 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/undo.mjs +132 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/why.mjs +16 -0
- package/scaffold/.agent/skills/total-recall/plugins/{git-sentinel → git}/ui/card.js +2 -2
- package/scaffold/.agent/skills/total-recall/plugins/mesh/package-lock.json +15 -14
- package/scaffold/.agent/skills/total-recall/plugins/mesh/package.json +3 -3
- package/scaffold/.agent/skills/total-recall/plugins/mesh/plugin.json +1 -1
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/README.md +59 -10
- 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 +160 -29
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/package-lock.json +15 -14
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/package.json +4 -4
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/plugin.json +231 -16
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/skills/meta-harness/SKILL.md +19 -4
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/adoption.mjs +104 -0
- 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 +101 -16
- 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 +54 -21
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/dispatch-request.mjs +40 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/dispatch.mjs +68 -13
- 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 +64 -15
- 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 +249 -0
- 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 +6 -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/pool.mjs +16 -8
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/process-manager.mjs +26 -2
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/reasoning.mjs +6 -1
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/remote-operation.mjs +6 -2
- 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 +28 -12
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/runtime.mjs +28 -6
- 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 +110 -0
- 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 +597 -70
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/worktree.mjs +76 -9
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/DESIGN.md +5 -5
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/card.js +3 -3
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/cli.mjs +47 -18
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/package-lock.json +15 -14
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/package.json +3 -3
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/plugin.json +1 -1
- 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 +120 -113
- package/scaffold/.agent/skills/total-recall/plugins/security/package-lock.json +15 -14
- package/scaffold/.agent/skills/total-recall/plugins/security/package.json +3 -3
- package/scaffold/.agent/skills/total-recall/plugins/security/plugin.json +1 -1
- package/scaffold/.agent/skills/total-recall/plugins/ssss/assets/scaffold.json +5 -5
- package/scaffold/.agent/skills/total-recall/plugins/ssss/package-lock.json +6 -6
- package/scaffold/.agent/skills/total-recall/plugins/ssss/package.json +2 -2
- package/scaffold/.agent/skills/total-recall/plugins/ssss/plugin.json +1 -1
- package/scaffold/.agent/skills/total-recall/references/operations.md +1 -1
- package/src/cli/agent.mjs +1 -1
- package/src/cli/command.mjs +41 -2
- package/src/cli/connect.mjs +2 -29
- package/src/cli/context.mjs +1 -0
- package/src/cli/dream.mjs +93 -69
- package/src/cli/harness.mjs +4 -4
- package/src/cli/help.mjs +1 -1
- package/src/cli/ingest-okf.mjs +4 -4
- 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/copies.mjs +64 -14
- package/src/cli/plugin/create.mjs +6 -7
- package/src/cli/plugin/index.mjs +11 -7
- 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/release.mjs +4 -1
- package/src/cli/remember.mjs +3 -14
- package/src/cli/server.mjs +18 -0
- package/src/cli/startup.mjs +1 -0
- package/src/cli/task.mjs +9 -2
- package/src/cli/update.mjs +10 -3
- package/src/core/access-ledger.mjs +78 -0
- package/src/core/agent-manager.mjs +2 -2
- package/src/core/automatic-brain-updates.mjs +11 -6
- package/src/core/brain-locate.mjs +15 -0
- package/src/core/brain-updates.mjs +42 -12
- 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-compactor.mjs +7 -2
- package/src/core/context-compiler.mjs +26 -1
- package/src/core/context-policy.mjs +7 -3
- package/src/core/daemon-control.mjs +22 -0
- package/src/core/daemon-loop.mjs +39 -62
- package/src/core/default-plugins.mjs +1 -1
- package/src/core/dream.mjs +33 -105
- package/src/core/ensure-dependencies.mjs +148 -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/global-brain-updates.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/mesh-brain-updates.mjs +2 -1
- package/src/core/meta-harness.mjs +2 -2
- package/src/core/optimizer.mjs +66 -165
- package/src/core/plugin-contracts/card.mjs +3 -0
- package/src/core/plugin-loader.mjs +12 -3
- package/src/core/plugin-runtime.mjs +40 -1
- package/src/core/plugin-store.mjs +35 -23
- package/src/core/post-mortem.mjs +52 -36
- package/src/core/preflight-gate.mjs +23 -2
- package/src/core/proposal-applier.mjs +31 -2
- package/src/core/repo-sync.mjs +4 -6
- package/src/core/required-plugins.mjs +26 -4
- 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 +1 -2
- package/src/core/search.mjs +4 -3
- package/src/core/server-restart.mjs +128 -7
- 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 +33 -6
- package/src/core/startup-health.mjs +6 -1
- package/src/core/surface.mjs +68 -57
- package/src/core/task-context.mjs +9 -8
- package/src/core/task-executors.mjs +54 -106
- package/src/core/validated-write.mjs +5 -0
- package/src/core/vault-files.mjs +8 -2
- package/src/core/vault.mjs +1 -1
- package/src/core/vector-field.mjs +134 -192
- package/src/server/index.mjs +3 -1
- package/src/server/invoke-core-child.mjs +24 -0
- package/src/server/invoke-core-operations.mjs +102 -0
- package/src/server/route-manifest.json +0 -56
- package/src/server/routes/brains.mjs +0 -18
- package/src/server/routes/context.mjs +0 -41
- package/src/server/routes/invoke.mjs +26 -1
- 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/vault.mjs +2 -23
- package/frontend/dist/assets/index-DD4qONvH.js +0 -5607
- 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/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
- /package/scaffold/.agent/skills/total-recall/plugins/{git-sentinel → git}/ui/DESIGN.md +0 -0
package/frontend/dist/index.html
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
18
18
|
<link href="https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:opsz,wght@12..96,600;12..96,800&family=Cabinet+Grotesk:wght@700;800&family=Chivo+Mono:wght@500;700&family=Cinzel:wght@600;700;900&family=Cormorant+Garamond:ital,wght@0,600;0,700;1,600;1,700&family=DM+Mono:wght@500&family=DM+Sans:wght@500;700&family=Fraunces:opsz,wght@9..144,600;9..144,800&family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500;700&family=Lexend:wght@600;800&family=Newsreader:ital,opsz,wght@0,6..72,600;1,6..72,600&family=Orbitron:wght@700;900&family=Outfit:wght@500;700;800&family=Plus+Jakarta+Sans:wght@600;700;800&family=Space+Grotesk:wght@600;700&family=Syne:wght@700;800&display=swap" rel="stylesheet" />
|
|
19
19
|
<title>Total Recall — Portable Memory</title>
|
|
20
|
-
<script type="module" crossorigin src="/assets/index-
|
|
20
|
+
<script type="module" crossorigin src="/assets/index-DACh1dhx.js"></script>
|
|
21
21
|
<link rel="stylesheet" crossorigin href="/assets/index-DtwsDyFM.css">
|
|
22
22
|
</head>
|
|
23
23
|
<body>
|
package/frontend/src/App.tsx
CHANGED
|
@@ -323,7 +323,7 @@ function MainContent({ activeBrainId }: { activeBrainId: string }) {
|
|
|
323
323
|
<Route path="/memory" element={<MemoryPage activeBrainId={activeBrainId} />} />
|
|
324
324
|
<Route path="/rules" element={<RulesPage activeBrainId={activeBrainId} />} />
|
|
325
325
|
<Route path="/graph" element={<GraphPage activeBrainId={activeBrainId} />} />
|
|
326
|
-
<Route path="/tasks" element={<Navigate to="/plugins?id=
|
|
326
|
+
<Route path="/tasks" element={<Navigate to="/plugins?id=automations" replace />} />
|
|
327
327
|
<Route path="/skills" element={<Navigate to="/plugins?id=skill-manager" replace />} />
|
|
328
328
|
<Route path="/openwiki" element={<Navigate to="/plugins?id=openwiki" replace />} />
|
|
329
329
|
<Route path="/plugins" element={<PluginsPage activeBrainId={activeBrainId} />} />
|
|
@@ -339,7 +339,7 @@ function MainContent({ activeBrainId }: { activeBrainId: string }) {
|
|
|
339
339
|
{/* Legacy OS-control-plane routes → core product */}
|
|
340
340
|
<Route path="/vault" element={<Navigate to="/memory" replace />} />
|
|
341
341
|
<Route path="/inbox" element={<Navigate to="/tasks" replace />} />
|
|
342
|
-
<Route path="/automations" element={<Navigate to="/plugins?id=
|
|
342
|
+
<Route path="/automations" element={<Navigate to="/plugins?id=automations" replace />} />
|
|
343
343
|
<Route path="/files" element={<Navigate to="/memory" replace />} />
|
|
344
344
|
<Route path="/sandbox" element={<Navigate to="/memory" replace />} />
|
|
345
345
|
<Route path="/models" element={<Navigate to="/settings" replace />} />
|
|
@@ -52,7 +52,7 @@ const DEFAULT_CORE_PLUGINS = new Set([
|
|
|
52
52
|
"code-quality",
|
|
53
53
|
"security",
|
|
54
54
|
"embeddings",
|
|
55
|
-
"git
|
|
55
|
+
"git"
|
|
56
56
|
])
|
|
57
57
|
|
|
58
58
|
const AGENT_RECIPE_PROMPT = `You are my coding agent. Author a bespoke Total Recall plugin for [DOMAIN] following the Total Recall Plugin Recipe:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "total-recall-brain",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.45.0",
|
|
4
4
|
"description": "The Vibe Coding Brain & Autonomous Software Factory: memory, rules, secrets, and 33 visual plugins automatically managed across all your devices.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"sync:scaffold-plugins": "node scripts/sync-scaffold-plugins.mjs",
|
|
55
55
|
"clean": "rm -rf scratch/* .remember/* *.log",
|
|
56
56
|
"check:dist": "node scripts/check-dist-freshness.mjs",
|
|
57
|
-
"prepublishOnly": "npm run check:package && npm run check:dist && npm run check:ssss-registry && node scripts/check-scaffold-state.mjs && npm run check:plugin-versions && npm run check:help && npm run check:harness-install",
|
|
57
|
+
"prepublishOnly": "node scripts/check-publish-source.mjs && npm run check:package && npm run check:dist && npm run check:ssss-registry && node scripts/check-scaffold-state.mjs && npm run check:plugin-versions && npm run check:help && npm run check:harness-install",
|
|
58
58
|
"check:ssss-registry": "node scripts/check-ssss-registry.mjs",
|
|
59
59
|
"check:plugin-versions": "node scripts/check-plugin-versions.mjs",
|
|
60
60
|
"check:help": "node scripts/audit-help.mjs --builtins",
|
|
@@ -81,7 +81,7 @@
|
|
|
81
81
|
"homepage": "https://github.com/gregiteen/total-recall#readme",
|
|
82
82
|
"dependencies": {
|
|
83
83
|
"@simplewebauthn/server": "^13.3.2",
|
|
84
|
-
"@ssss/cli": "npm:@gregiteen/ssss-cli@0.14.
|
|
84
|
+
"@ssss/cli": "npm:@gregiteen/ssss-cli@0.14.5",
|
|
85
85
|
"bcrypt": "^6.0.0",
|
|
86
86
|
"better-sqlite3": "^12.11.1",
|
|
87
87
|
"cookie-parser": "^1.4.7",
|
|
@@ -13,6 +13,10 @@ A recipe for agents: prompts with exact specifications, executed in order. Each
|
|
|
13
13
|
|
|
14
14
|
A plugin adds **one capability** to Total Recall. Core holds portable memory and generic loading; everything else is a plugin.
|
|
15
15
|
|
|
16
|
+
## Reuse the ecosystem first
|
|
17
|
+
|
|
18
|
+
Before designing or writing a plugin, inventory `total-recall plugin library --json`, `total-recall plugin available --json` and `total-recall plugin bricks --json`. Match each dependency to an existing owner. Call installed plugins for shared services and vendor existing bricks for code the project needs to own. Document the verified gaps that need new code. Run `record.mjs --reuse` after drafting the manifest and before implementing the capability.
|
|
19
|
+
|
|
16
20
|
**A plugin is not one shape.** It declares the surfaces its capability needs, and a capability can need almost any combination — memory, context, a CLI, skills, scheduled work, runtime behaviour, a face, deployment, distribution, composition. Some plugins are only a memory category. Some are only a generator. Some are a CLI. Some are several at once. What it is, is decided by what it does.
|
|
17
21
|
|
|
18
22
|
```
|
|
@@ -29,7 +33,7 @@ evals/ proof that the recipe produces correct plugins
|
|
|
29
33
|
|
|
30
34
|
True of every plugin, whatever it turns out to be. Check every one before calling it done.
|
|
31
35
|
|
|
32
|
-
1. **Everything is declared.** If the plugin can do it, the manifest says so.
|
|
36
|
+
1. **Everything is declared.** If the plugin can do it, the manifest says so. Record its reused operations and brick dependencies as well.
|
|
33
37
|
2. **Every executable operation declares an effect** — `read`, `write`, `destructive`, `send`. The host uses it to decide what may run read-only; an agent uses it to know what needs confirmation.
|
|
34
38
|
3. **Machine-facing output is structured.** A command emits JSON under `--json` and exits non-zero on failure, so an agent acts on a result instead of scraping prose.
|
|
35
39
|
4. **Credentials are declared, never held.** Resolved only through `total-recall auth secret`. Never a second store, never `argv`, never an ambient environment variable, never a log.
|
|
@@ -45,7 +49,7 @@ True of every plugin, whatever it turns out to be. Check every one before callin
|
|
|
45
49
|
|
|
46
50
|
| # | Prompt | Produce | Check |
|
|
47
51
|
| --- | --- | --- | --- |
|
|
48
|
-
| 1 | [Establish the function](prompts/01-function.md) | the users, the tasks, the
|
|
52
|
+
| 1 | [Establish the function](prompts/01-function.md) | the users, the tasks, the reused plugins and bricks | owner interfaces and gaps are identified |
|
|
49
53
|
| 2 | [Choose the surfaces](prompts/02-surfaces.md) | the manifest's surface set | each declared surface is used |
|
|
50
54
|
| 3 | [Scaffold, then stop generating](prompts/03-scaffold.md) | repository skeleton | it exists, tests run |
|
|
51
55
|
| 4 | [Write the CLI as an agent interface](prompts/04-cli.md) | operations, args, effects, JSON | `record.mjs` passes |
|
|
@@ -68,6 +72,7 @@ node <skill>/scripts/record.mjs . --manifest # manifest only
|
|
|
68
72
|
node <skill>/scripts/record.mjs . --card # face only
|
|
69
73
|
node <skill>/scripts/record.mjs . --secrets # credential safety only
|
|
70
74
|
node <skill>/scripts/record.mjs . --scaffold # standalone scaffold only
|
|
75
|
+
node <skill>/scripts/record.mjs . --reuse # installed owner commands and required bricks
|
|
71
76
|
node <skill>/scripts/record.mjs . --json # machine-readable result
|
|
72
77
|
```
|
|
73
78
|
|
|
@@ -31,6 +31,11 @@ A case declares the failures it expects. It passes when `scripts/record.mjs` rep
|
|
|
31
31
|
| [`card-collects-credential`](cases/04-card-collects-credential.mjs) | a card collecting an API key in a password field and dispatching the raw value — generated by the old scaffolder | `never collects a credential`, `never transmits a credential` |
|
|
32
32
|
| [`host-leak-in-scaffold`](cases/05-host-leak-in-scaffold.mjs) | a capability calling the `total-recall` binary for credentials and shipping `https://example.com/checkout/success` | `no Total Recall dependency`, `no placeholder values` |
|
|
33
33
|
| [`correct-plugin`](cases/06-correct-plugin.mjs) | a plugin that follows the recipe: one bespoke face, real data only, credentials resolved through auth in the CLI, and a host-free capability | no failures |
|
|
34
|
+
| [`missing-reuse`](cases/07-missing-reuse.mjs) | an otherwise valid plugin without a reuse decision | `reuse declared` |
|
|
35
|
+
| [`unresolved-owner-command`](cases/08-unresolved-owner-command.mjs) | a reference to an operation absent from its installed owner | `owner commands resolve` |
|
|
36
|
+
| [`missing-brick`](cases/09-missing-brick.mjs) | a declared brick without a project-owned copy | `required bricks present` |
|
|
37
|
+
|
|
38
|
+
Reuse cases resolve Auth against an installed Total Recall plugin catalog. Run them from a machine with Total Recall and Auth available.
|
|
34
39
|
|
|
35
40
|
## Adding a case
|
|
36
41
|
|
|
@@ -28,6 +28,7 @@ export default {
|
|
|
28
28
|
files: {
|
|
29
29
|
'plugin.json': JSON.stringify({
|
|
30
30
|
id: 'seeded', name: 'Seeded', version: '1.0.0', description: 'A plugin that fabricates a reading.',
|
|
31
|
+
reuse: { commands: [], owned: 'Displays its own telemetry reading.' },
|
|
31
32
|
cli: { command: 'seeded', handler: './cli.mjs', subcommands: [{ name: 'sample', effect: 'read' }] },
|
|
32
33
|
status: { command: 'sample', refresh_seconds: 30 },
|
|
33
34
|
branding: { color: '#059669' },
|
|
@@ -25,6 +25,7 @@ export default {
|
|
|
25
25
|
files: {
|
|
26
26
|
'plugin.json': JSON.stringify({
|
|
27
27
|
id: 'reassuring', name: 'Reassuring', version: '1.0.0', description: 'A plugin that reassures without checking.',
|
|
28
|
+
reuse: { commands: [], owned: 'Displays the status returned by its own command.' },
|
|
28
29
|
cli: { command: 'reassuring', handler: './cli.mjs', subcommands: [{ name: 'audit', effect: 'read' }] },
|
|
29
30
|
status: { command: 'audit', refresh_seconds: 30 },
|
|
30
31
|
branding: { color: '#b45309' },
|
|
@@ -17,6 +17,7 @@ export default {
|
|
|
17
17
|
files: {
|
|
18
18
|
'plugin.json': JSON.stringify({
|
|
19
19
|
id: 'templated', name: 'Templated', version: '1.0.0', description: 'A plugin that declares a layout template.',
|
|
20
|
+
reuse: { commands: [], owned: 'Displays the plugin-specific view.' },
|
|
20
21
|
cli: { command: 'templated', handler: './cli.mjs', subcommands: [{ name: 'status', effect: 'read' }] },
|
|
21
22
|
status: { command: 'status', refresh_seconds: 30 },
|
|
22
23
|
branding: { color: '#475569' },
|
|
@@ -28,6 +28,7 @@ export default {
|
|
|
28
28
|
files: {
|
|
29
29
|
'plugin.json': JSON.stringify({
|
|
30
30
|
id: 'collecting', name: 'Collecting', version: '1.0.0', description: 'A plugin whose card collects a key.',
|
|
31
|
+
reuse: { commands: ['total-recall auth secret'], owned: 'Provides the service connection screen.' },
|
|
31
32
|
cli: { command: 'collecting', handler: './cli.mjs', subcommands: [
|
|
32
33
|
{ name: 'status', effect: 'read' },
|
|
33
34
|
{ name: 'token', effect: 'write', args: [{ name: 'key', label: 'Key', type: 'string', secret: true }] },
|
|
@@ -38,6 +38,7 @@ export default {
|
|
|
38
38
|
files: {
|
|
39
39
|
'plugin.json': JSON.stringify({
|
|
40
40
|
id: 'leaky', name: 'Leaky', version: '1.0.0', description: 'A plugin whose capability depends on the host.',
|
|
41
|
+
reuse: { commands: ['total-recall auth secret'], owned: 'Submits a checkout request to the service.' },
|
|
41
42
|
cli: { command: 'leaky', handler: './cli.mjs', subcommands: [{ name: 'status', effect: 'read' }] },
|
|
42
43
|
capability: { entry: 'capability/index.mjs', exports: ['createCheckout'] },
|
|
43
44
|
secrets: [{ key: 'LEAKY_API_KEY', description: 'Service key', required: true }],
|
|
@@ -68,6 +68,7 @@ export default {
|
|
|
68
68
|
files: {
|
|
69
69
|
'plugin.json': JSON.stringify({
|
|
70
70
|
id: 'example', name: 'Example', version: '1.0.0', description: 'A plugin that follows the recipe exactly.',
|
|
71
|
+
reuse: { commands: ['total-recall auth secret'], owned: 'Reads the service-specific status endpoint.' },
|
|
71
72
|
cli: { command: 'example', handler: './cli.mjs', subcommands: [
|
|
72
73
|
{ name: 'status', description: 'Read current status', effect: 'read', output: 'json' },
|
|
73
74
|
{ name: 'set-key', description: 'Store the service key', effect: 'write',
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import correct from './06-correct-plugin.mjs';
|
|
2
|
+
|
|
3
|
+
const { reuse, ...manifest } = JSON.parse(correct.files['plugin.json']);
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
...correct,
|
|
7
|
+
name: 'missing-reuse',
|
|
8
|
+
why: 'A plugin can otherwise pass authoring verification without identifying existing owners.',
|
|
9
|
+
files: { ...correct.files, 'plugin.json': JSON.stringify(manifest) },
|
|
10
|
+
expect: { fail: ['reuse declared'] },
|
|
11
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import correct from './06-correct-plugin.mjs';
|
|
2
|
+
|
|
3
|
+
const manifest = JSON.parse(correct.files['plugin.json']);
|
|
4
|
+
manifest.reuse.commands.push('total-recall auth nonexistent-operation');
|
|
5
|
+
|
|
6
|
+
export default {
|
|
7
|
+
...correct,
|
|
8
|
+
name: 'unresolved-owner-command',
|
|
9
|
+
why: 'A declared operation must exist in the installed owner catalog.',
|
|
10
|
+
files: { ...correct.files, 'plugin.json': JSON.stringify(manifest) },
|
|
11
|
+
expect: { fail: ['owner commands resolve'] },
|
|
12
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import correct from './06-correct-plugin.mjs';
|
|
2
|
+
|
|
3
|
+
const manifest = JSON.parse(correct.files['plugin.json']);
|
|
4
|
+
manifest.requires = ['mesh'];
|
|
5
|
+
|
|
6
|
+
export default {
|
|
7
|
+
...correct,
|
|
8
|
+
name: 'missing-brick',
|
|
9
|
+
why: 'An installed plugin is insufficient when a project declares its brick as a code dependency.',
|
|
10
|
+
files: { ...correct.files, 'plugin.json': JSON.stringify(manifest) },
|
|
11
|
+
expect: { fail: ['required bricks present'] },
|
|
12
|
+
};
|
|
@@ -9,7 +9,7 @@ Answer all five, concretely:
|
|
|
9
9
|
1. **What capability does this add?** One sentence. If it needs "and" to hold together, it is two plugins.
|
|
10
10
|
2. **Who uses it, and what two or three things do they actually do with it?** Name the tasks, not the features.
|
|
11
11
|
3. **What must be visible without a single click?** This decides the hierarchy later.
|
|
12
|
-
4. **What does it depend on outside itself?**
|
|
12
|
+
4. **What does it depend on outside itself, and who owns each dependency?** Read the installed plugin library, available plugins and project bricks. Use the owning plugin's supported interface wherever it covers the need. Vendor an existing brick when the project needs to own the code.
|
|
13
13
|
5. **Could another application want this capability?** If yes, part of this plugin is the capability and part is Total Recall presentation, and they must be separable from the first line of code.
|
|
14
14
|
|
|
15
15
|
## Correct means
|
|
@@ -17,13 +17,14 @@ Answer all five, concretely:
|
|
|
17
17
|
- You can name the users and their tasks in plain words.
|
|
18
18
|
- You know whether a scaffold is in scope (Prompt 7), because that changes where the domain logic lives.
|
|
19
19
|
- The capability is one thing, not a bundle.
|
|
20
|
+
- You can identify what the plugin reuses, how to call or vendor it, and the specific capability gap that needs new code.
|
|
20
21
|
|
|
21
22
|
If you cannot answer 1 and 2, you are not ready to write code. Stop and find out.
|
|
22
23
|
|
|
23
24
|
## Record it
|
|
24
25
|
|
|
25
|
-
|
|
26
|
+
Record the owners and reuse decisions in the project plan before implementation. Carry the exact installed operations and the plugin's own responsibility into the manifest using the [composition contract](../references/surfaces.md#composition). Write the user and task answers into `ui/DESIGN.md` for Prompt 6. Keep the scaffold answer for Prompt 7.
|
|
26
27
|
|
|
27
28
|
## Check
|
|
28
29
|
|
|
29
|
-
|
|
30
|
+
Once the manifest is drafted, run `node <skill>/scripts/record.mjs . --reuse`. Resolve any failures before implementing the capability.
|
|
@@ -12,6 +12,7 @@ Then work the list, and record the actual outcome of each. Do not tick a box you
|
|
|
12
12
|
|
|
13
13
|
- [ ] `total-recall plugin info <id>` reports no errors and no warnings.
|
|
14
14
|
- [ ] Every surface the function needs is declared, and nothing unused.
|
|
15
|
+
- [ ] Each shared dependency uses its existing owner command or a vendored brick. The reuse gate passes and the workflow tests exercise the declared interfaces.
|
|
15
16
|
- [ ] Every operation has typed arguments and an effect.
|
|
16
17
|
- [ ] `--json` works on every subcommand; failures exit non-zero; `--help` works without credentials.
|
|
17
18
|
- [ ] No secret value appears in `argv`, stdout, stderr, a log or the card state.
|
|
@@ -145,10 +145,20 @@ Use when the capability is deployed into other applications.
|
|
|
145
145
|
## Composition
|
|
146
146
|
|
|
147
147
|
```json
|
|
148
|
-
"
|
|
148
|
+
"reuse": {
|
|
149
|
+
"commands": ["total-recall auth secret"],
|
|
150
|
+
"owned": "Connects to the service and translates its records into the plugin's read model."
|
|
151
|
+
},
|
|
152
|
+
"requires": [ { "id": "mesh", "version": "^0.2.0" } ]
|
|
149
153
|
```
|
|
150
154
|
|
|
151
|
-
|
|
155
|
+
Copy exact command strings from `total-recall plugin library --json` for the installed owners this project uses. In `owned`, explain the capability the plugin supplies after the ecosystem inventory. Use an empty command list when the inventory supports that decision.
|
|
156
|
+
|
|
157
|
+
A plugin that declares secrets names `total-recall auth secret` as its credential interface. Auth itself owns that interface.
|
|
158
|
+
|
|
159
|
+
Declare portable dependencies with `requires`. Use the supported source with `total-recall plugin vendor` and inspect `total-recall plugin bricks --json` for the project-owned copy. Use `requires` only for bricks the capability actually imports. The vendor resolver checks the version constraint when it assembles a consuming project.
|
|
160
|
+
|
|
161
|
+
The full Creator check verifies these declarations against the installed commands and recorded brick payloads. Verify actual reuse through the plugin and fresh-project workflow tests.
|
|
152
162
|
|
|
153
163
|
## Credentials
|
|
154
164
|
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* non-zero on any failure and prints the real reason. Nothing here trusts a
|
|
7
7
|
* declaration: every check reads the actual files or runs the actual command.
|
|
8
8
|
*
|
|
9
|
-
* node record.mjs <pluginDir> [--manifest|--card|--secrets|--scaffold|--json]
|
|
9
|
+
* node record.mjs <pluginDir> [--manifest|--card|--secrets|--scaffold|--reuse|--json]
|
|
10
10
|
*
|
|
11
11
|
* Checks are marked PASS, FAIL or WARN. A WARN is a judgement call the agent
|
|
12
12
|
* must resolve; a FAIL is a rejection.
|
|
@@ -18,7 +18,7 @@ import { pathToFileURL } from 'node:url';
|
|
|
18
18
|
|
|
19
19
|
const args = process.argv.slice(2);
|
|
20
20
|
const json = args.includes('--json');
|
|
21
|
-
const only = ['--manifest', '--card', '--secrets', '--scaffold'].filter((f) => args.includes(f));
|
|
21
|
+
const only = ['--manifest', '--card', '--secrets', '--scaffold', '--reuse'].filter((f) => args.includes(f));
|
|
22
22
|
const root = path.resolve(args.find((a) => !a.startsWith('-')) || '.');
|
|
23
23
|
const want = (section) => only.length === 0 || only.includes(section);
|
|
24
24
|
|
|
@@ -124,6 +124,63 @@ if (manifest && want('--manifest')) {
|
|
|
124
124
|
}
|
|
125
125
|
}
|
|
126
126
|
|
|
127
|
+
/* ── reuse ───────────────────────────────────────────────────────────────── */
|
|
128
|
+
|
|
129
|
+
function pluginInventory(command) {
|
|
130
|
+
const binary = process.env.TOTAL_RECALL_BIN || 'total-recall';
|
|
131
|
+
const output = execFileSync(binary, ['plugin', command, '--json'], {
|
|
132
|
+
cwd: root, encoding: 'utf8', timeout: 15000, maxBuffer: 8 * 1024 * 1024,
|
|
133
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
134
|
+
});
|
|
135
|
+
return JSON.parse(output);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (want('--reuse') && manifest) {
|
|
139
|
+
const { reuse } = manifest;
|
|
140
|
+
const commands = reuse?.commands;
|
|
141
|
+
const validCommands = Array.isArray(commands) &&
|
|
142
|
+
commands.every((command) => typeof command === 'string' && command.startsWith('total-recall '));
|
|
143
|
+
if (typeof reuse?.owned !== 'string' || !reuse.owned.trim() || !validCommands) {
|
|
144
|
+
record('reuse', 'FAIL', 'reuse declared', 'Record reuse.commands and reuse.owned after inspecting the plugin library and project bricks');
|
|
145
|
+
} else {
|
|
146
|
+
record('reuse', 'PASS', 'reuse declared', 'Installed operations and plugin responsibility are documented');
|
|
147
|
+
if (manifest.id !== 'auth' && manifest.secrets?.length && !commands.includes('total-recall auth secret')) {
|
|
148
|
+
record('reuse', 'FAIL', 'Auth owner declared', 'Declare total-recall auth secret for the credential interface');
|
|
149
|
+
}
|
|
150
|
+
if (commands.length) {
|
|
151
|
+
try {
|
|
152
|
+
const library = pluginInventory('library');
|
|
153
|
+
const owners = new Set(library.plugins.filter((plugin) =>
|
|
154
|
+
plugin.valid && plugin.callable && plugin.id !== manifest.id).map((plugin) => plugin.id));
|
|
155
|
+
const available = new Set(library.commands.filter((entry) => owners.has(entry.plugin)).map((entry) => entry.command));
|
|
156
|
+
const unresolved = commands.flatMap((command, index) => available.has(command) ? [] : [`reuse.commands[${index}]`]);
|
|
157
|
+
const detail = unresolved.length ? `Resolve ${unresolved.join(', ')} against the installed plugin library` : `${commands.length} owner operations verified`;
|
|
158
|
+
record('reuse', unresolved.length ? 'FAIL' : 'PASS', 'owner commands resolve', detail);
|
|
159
|
+
} catch {
|
|
160
|
+
record('reuse', 'FAIL', 'owner commands resolve', 'Could not read total-recall plugin library --json');
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const requires = manifest.requires === undefined ? [] : manifest.requires;
|
|
166
|
+
const brickIds = Array.isArray(requires) && requires.map((entry) => typeof entry === 'string' ? entry : entry?.id);
|
|
167
|
+
const invalidVersion = Array.isArray(requires) && requires.some((entry) =>
|
|
168
|
+
entry?.range !== undefined || (entry?.version !== undefined && typeof entry.version !== 'string'));
|
|
169
|
+
if (!brickIds || invalidVersion || brickIds.some((id) => typeof id !== 'string' || !/^[a-z][a-z0-9-]*$/.test(id) || id === manifest.id)) {
|
|
170
|
+
record('reuse', 'FAIL', 'required bricks present', 'Declare other brick IDs in requires and use version for version constraints');
|
|
171
|
+
} else if (brickIds.length) {
|
|
172
|
+
try {
|
|
173
|
+
const bricks = pluginInventory('bricks');
|
|
174
|
+
const present = new Set(bricks.filter((brick) => ['unchanged', 'modified'].includes(brick.status)).map((brick) => brick.id));
|
|
175
|
+
const missing = brickIds.filter((id) => !present.has(id));
|
|
176
|
+
const detail = missing.length ? `Vendor required bricks through the plugin manager: ${missing.join(', ')}` : `${brickIds.length} project-owned bricks verified`;
|
|
177
|
+
record('reuse', missing.length ? 'FAIL' : 'PASS', 'required bricks present', detail);
|
|
178
|
+
} catch {
|
|
179
|
+
record('reuse', 'FAIL', 'required bricks present', 'Could not read total-recall plugin bricks --json');
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
127
184
|
/* ── card ────────────────────────────────────────────────────────────────── */
|
|
128
185
|
|
|
129
186
|
if (want('--card') && manifest) {
|
|
@@ -50,6 +50,14 @@ override; `_TR_TEST_BRAIN_DIR` and `_TR_TEST_AGENT_DIR` preserve disposable test
|
|
|
50
50
|
isolation. Resolving this path performs no credential read or initialization.
|
|
51
51
|
Explicit low-level store APIs retain their existing selected-store semantics.
|
|
52
52
|
|
|
53
|
+
## Changing `gh` scopes
|
|
54
|
+
|
|
55
|
+
`gh` signs in from `github_token` on every machine that receives it, so a rotated token lands everywhere. A login changed on the machine itself stays, and the sync reports it once.
|
|
56
|
+
|
|
57
|
+
- One machine: `gh auth refresh -h github.com -s <scope>`. Remove it with `--remove-scopes <scope>`, and the next sync returns `gh` to the store's token.
|
|
58
|
+
- Every machine: refresh on one, then `total-recall auth secret gh-login adopt`. It shows the scope change and writes nothing until `--yes`. `--revoke-old` also ends the previous token at GitHub.
|
|
59
|
+
- Compare or go back: `total-recall auth secret gh-login status` and `use-store`.
|
|
60
|
+
|
|
53
61
|
## Using this from an agent
|
|
54
62
|
|
|
55
63
|
Send anything involving a credential here: reading, storing or rotating a secret, issuing API keys, passkeys, passwords and sign-in sessions. There is one store per machine, so search it before asking anyone for a key, and never print a value.
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tr-plugin-auth",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.10",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "tr-plugin-auth",
|
|
9
|
-
"version": "1.2.
|
|
9
|
+
"version": "1.2.10",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@gregiteen/ssss-cli": "0.14.
|
|
12
|
+
"@gregiteen/ssss-cli": "0.14.5",
|
|
13
13
|
"@simplewebauthn/server": "^13.3.2",
|
|
14
14
|
"bcrypt": "^6.0.0",
|
|
15
15
|
"express": "^5.2.1",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
21
21
|
"supertest": "^7.3.1",
|
|
22
|
-
"total-recall-brain": "3.
|
|
22
|
+
"total-recall-brain": "3.44.0",
|
|
23
23
|
"vitest": "^4.1.12"
|
|
24
24
|
}
|
|
25
25
|
},
|
|
@@ -723,9 +723,9 @@
|
|
|
723
723
|
"license": "MIT"
|
|
724
724
|
},
|
|
725
725
|
"node_modules/@gregiteen/ssss-cli": {
|
|
726
|
-
"version": "0.14.
|
|
727
|
-
"resolved": "https://registry.npmjs.org/@gregiteen/ssss-cli/-/ssss-cli-0.14.
|
|
728
|
-
"integrity": "sha512-
|
|
726
|
+
"version": "0.14.5",
|
|
727
|
+
"resolved": "https://registry.npmjs.org/@gregiteen/ssss-cli/-/ssss-cli-0.14.5.tgz",
|
|
728
|
+
"integrity": "sha512-qVEYOocnwn97uJ0eDzmuwN06CYsYWr2t3+iKylpisBHX4wlLWk7P8EmFFdBlx7NyKVIZDDeYT164Gd7/T8UGgw==",
|
|
729
729
|
"license": "ISC",
|
|
730
730
|
"bin": {
|
|
731
731
|
"ssss": "scripts/ssss.mjs"
|
|
@@ -1902,9 +1902,9 @@
|
|
|
1902
1902
|
},
|
|
1903
1903
|
"node_modules/@ssss/cli": {
|
|
1904
1904
|
"name": "@gregiteen/ssss-cli",
|
|
1905
|
-
"version": "0.14.
|
|
1906
|
-
"resolved": "https://registry.npmjs.org/@gregiteen/ssss-cli/-/ssss-cli-0.14.
|
|
1907
|
-
"integrity": "sha512-
|
|
1905
|
+
"version": "0.14.5",
|
|
1906
|
+
"resolved": "https://registry.npmjs.org/@gregiteen/ssss-cli/-/ssss-cli-0.14.5.tgz",
|
|
1907
|
+
"integrity": "sha512-qVEYOocnwn97uJ0eDzmuwN06CYsYWr2t3+iKylpisBHX4wlLWk7P8EmFFdBlx7NyKVIZDDeYT164Gd7/T8UGgw==",
|
|
1908
1908
|
"dev": true,
|
|
1909
1909
|
"license": "ISC",
|
|
1910
1910
|
"bin": {
|
|
@@ -6704,9 +6704,9 @@
|
|
|
6704
6704
|
}
|
|
6705
6705
|
},
|
|
6706
6706
|
"node_modules/total-recall-brain": {
|
|
6707
|
-
"version": "3.
|
|
6708
|
-
"resolved": "https://registry.npmjs.org/total-recall-brain/-/total-recall-brain-3.
|
|
6709
|
-
"integrity": "sha512-
|
|
6707
|
+
"version": "3.44.0",
|
|
6708
|
+
"resolved": "https://registry.npmjs.org/total-recall-brain/-/total-recall-brain-3.44.0.tgz",
|
|
6709
|
+
"integrity": "sha512-VNPaIO9zsSwoxAsJ5ByIQBP9zPpLq4RiQO7Vrex4rBOHFQJT50P7utcZiLMSZTyZJU4C/m5uB8qTCSBMp6+l6Q==",
|
|
6710
6710
|
"dev": true,
|
|
6711
6711
|
"license": "MIT",
|
|
6712
6712
|
"workspaces": [
|
|
@@ -6714,7 +6714,7 @@
|
|
|
6714
6714
|
],
|
|
6715
6715
|
"dependencies": {
|
|
6716
6716
|
"@simplewebauthn/server": "^13.3.2",
|
|
6717
|
-
"@ssss/cli": "npm:@gregiteen/ssss-cli@0.14.
|
|
6717
|
+
"@ssss/cli": "npm:@gregiteen/ssss-cli@0.14.5",
|
|
6718
6718
|
"bcrypt": "^6.0.0",
|
|
6719
6719
|
"better-sqlite3": "^12.11.1",
|
|
6720
6720
|
"cookie-parser": "^1.4.7",
|
|
@@ -6737,6 +6737,7 @@
|
|
|
6737
6737
|
"antigravity": "bin/antigravity.mjs",
|
|
6738
6738
|
"total-recall": "bin/total-recall.mjs",
|
|
6739
6739
|
"total-recall-memory": "bin/total-recall-memory.mjs",
|
|
6740
|
+
"total-recall-server-release": "bin/total-recall-server-release.mjs",
|
|
6740
6741
|
"vibebrain": "bin/total-recall.mjs"
|
|
6741
6742
|
},
|
|
6742
6743
|
"optionalDependencies": {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tr-plugin-auth",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.10",
|
|
4
4
|
"description": "White-label Total Recall auth plugin: Passkey biometric FIDO2 and Google OAuth2 authentication.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "cli.mjs",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"express-rate-limit": "^8.5.1",
|
|
24
24
|
"jsonwebtoken": "^9.0.3",
|
|
25
25
|
"yaml": "^2.9.0",
|
|
26
|
-
"@gregiteen/ssss-cli": "0.14.
|
|
26
|
+
"@gregiteen/ssss-cli": "0.14.5"
|
|
27
27
|
},
|
|
28
28
|
"files": [
|
|
29
29
|
"cli.mjs",
|
|
@@ -39,6 +39,6 @@
|
|
|
39
39
|
"access": "public"
|
|
40
40
|
},
|
|
41
41
|
"overrides": {
|
|
42
|
-
"@ssss/cli": "npm:@gregiteen/ssss-cli@0.14.
|
|
42
|
+
"@ssss/cli": "npm:@gregiteen/ssss-cli@0.14.5"
|
|
43
43
|
}
|
|
44
44
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://github.com/gregiteen/total-recall/blob/main/metadata.plugin.schema.json",
|
|
3
3
|
"id": "auth",
|
|
4
4
|
"name": "Auth & Secrets",
|
|
5
|
-
"version": "1.2.
|
|
5
|
+
"version": "1.2.10",
|
|
6
6
|
"description": "Hardware WebAuthn biometric FIDO2 passkeys, OAuth session security, and access control.",
|
|
7
7
|
"author": "Total Recall contributors",
|
|
8
8
|
"license": "MIT",
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `auth secret gh-login`: see how this machine's `gh` login compares with `github_token`,
|
|
3
|
+
* share it with the mesh, or return to the store's token. Prints fingerprints, never values.
|
|
4
|
+
*/
|
|
5
|
+
import { adoptGithubLogin, githubLoginStatus, useStoreGithubLogin } from './secrets-sync.mjs';
|
|
6
|
+
|
|
7
|
+
const USAGE = 'Usage: total-recall auth secret gh-login <status|adopt [--yes] [--revoke-old]|use-store [--yes]> [--json]';
|
|
8
|
+
const COMMAND = 'total-recall auth secret gh-login';
|
|
9
|
+
|
|
10
|
+
const scopeList = (scopes) => (scopes?.length ? scopes.join(', ') : 'no classic scopes');
|
|
11
|
+
|
|
12
|
+
function tokenLine(label, token) {
|
|
13
|
+
if (token.state === 'rejected') return ` ${label} ${token.fingerprint} rejected by GitHub`;
|
|
14
|
+
if (token.state !== 'ok') return ` ${label} ${token.fingerprint} could not be checked with GitHub`;
|
|
15
|
+
return ` ${label} ${token.fingerprint} ${token.login} ${scopeList(token.scopes)}`;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function scopeChange({ added = [], removed = [], store }) {
|
|
19
|
+
if (store && store.state !== 'ok') return [' the stored token is already rejected by GitHub, so there is no scope change to compare'];
|
|
20
|
+
const lines = [];
|
|
21
|
+
if (added.length) lines.push(` gains: ${added.join(', ')}`);
|
|
22
|
+
if (removed.length) lines.push(` loses: ${removed.join(', ')}`);
|
|
23
|
+
return lines.length ? lines : [' scopes unchanged'];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function statusText(status) {
|
|
27
|
+
if (status.state === 'no-token') return ['', ' The store holds no github_token.', ''];
|
|
28
|
+
if (status.state === 'gh-missing') return ['', ' gh is not installed on this machine.', ''];
|
|
29
|
+
if (status.state === 'unreadable') return ['', ` Could not read gh's login: ${status.error}`, ''];
|
|
30
|
+
if (status.state === 'no-login') return ['', ' gh holds no login here. The next sync signs it in from github_token.', tokenLine('store', status.store), ''];
|
|
31
|
+
if (status.state === 'same') return ['', ' gh on this machine uses github_token.', tokenLine('store', status.store), ''];
|
|
32
|
+
return [
|
|
33
|
+
'',
|
|
34
|
+
' gh on this machine differs from github_token.',
|
|
35
|
+
tokenLine('gh ', status.gh),
|
|
36
|
+
tokenLine('store', status.store),
|
|
37
|
+
'',
|
|
38
|
+
' The sync leaves this login alone until github_token is rotated.',
|
|
39
|
+
` Share it with every machine: ${COMMAND} adopt`,
|
|
40
|
+
` Go back to the store's token: ${COMMAND} use-store`,
|
|
41
|
+
'',
|
|
42
|
+
];
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function adoptText(result) {
|
|
46
|
+
if (result.state === 'same') return ['', ` gh already uses ${result.key} (${result.fingerprint}).`, ''];
|
|
47
|
+
const where = result.target === 'this machine' ? 'this machine (the leader)' : `the leader (${result.target})`;
|
|
48
|
+
if (result.planned) {
|
|
49
|
+
return [
|
|
50
|
+
'',
|
|
51
|
+
` Would save gh's token (${result.gh.fingerprint}) as ${result.key} on ${where}, replacing ${result.store.fingerprint}.`,
|
|
52
|
+
' Every machine granted this key receives it on its next sync, with these scopes:',
|
|
53
|
+
` ${scopeList(result.gh.scopes)}`,
|
|
54
|
+
...scopeChange(result),
|
|
55
|
+
...(result.revoke_old && result.store.state === 'ok' ? [' Then ends the old token at GitHub. That cannot be undone.'] : []),
|
|
56
|
+
' Run again with --yes to do it.',
|
|
57
|
+
'',
|
|
58
|
+
];
|
|
59
|
+
}
|
|
60
|
+
const lines = ['', ` ✅ ${result.key} is now gh's token (${result.gh.fingerprint}), saved on ${where}.`, ...scopeChange(result)];
|
|
61
|
+
if (result.leader_gh === 'failed') lines.push(" ❌ The leader's gh did not sign in, so it still uses the old token.");
|
|
62
|
+
if (result.revocation?.skipped) lines.push(` ❌ The old token still works: ${result.revocation.skipped}.`);
|
|
63
|
+
else if (result.revocation?.revoked) lines.push(` ✅ GitHub now rejects the old token (${result.store.fingerprint}).`);
|
|
64
|
+
else if (result.revocation) lines.push(` ❌ The old token (${result.store.fingerprint}) still works (revoke request ${result.revocation.request_status ?? 'failed'}).`);
|
|
65
|
+
if (result.revocation && !result.revocation.skipped && !result.revocation.new_token_works) lines.push(' ❌ GitHub no longer accepts the new token. Sign in with gh again, then adopt again.');
|
|
66
|
+
lines.push('');
|
|
67
|
+
return lines;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function useStoreText(result) {
|
|
71
|
+
if (result.error) return ['', ` ❌ gh did not sign in: ${result.error}`, ''];
|
|
72
|
+
if (result.changed === false) return ['', ' gh already uses github_token.', ''];
|
|
73
|
+
if (result.planned) {
|
|
74
|
+
const local = result.gh ? tokenLine('gh ', result.gh) : ' gh holds no login';
|
|
75
|
+
return ['', " Would sign gh in from github_token, giving up this machine's own login.", local, tokenLine('store', result.store), ' Getting a broader login back takes a new browser approval. Run again with --yes to do it.', ''];
|
|
76
|
+
}
|
|
77
|
+
return ['', ' ✅ gh now uses github_token.', tokenLine('store', result.store), ''];
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** @returns {Promise<number>} the exit code */
|
|
81
|
+
export async function runGhLogin(brainDir, opts) {
|
|
82
|
+
const action = opts.key;
|
|
83
|
+
if (opts.unknownOption || opts.value || !['status', 'adopt', 'use-store'].includes(action)) {
|
|
84
|
+
console.error(opts.unknownOption ? ` Unknown option for gh-login: ${opts.unknownOption}` : USAGE);
|
|
85
|
+
return 1;
|
|
86
|
+
}
|
|
87
|
+
let result;
|
|
88
|
+
let text;
|
|
89
|
+
if (action === 'status') {
|
|
90
|
+
result = await githubLoginStatus({ dir: brainDir });
|
|
91
|
+
text = statusText;
|
|
92
|
+
} else if (action === 'adopt') {
|
|
93
|
+
result = await adoptGithubLogin({ dir: brainDir, yes: opts.yes === true, revokeOld: opts.revokeOld === true });
|
|
94
|
+
text = adoptText;
|
|
95
|
+
} else {
|
|
96
|
+
result = await useStoreGithubLogin({ dir: brainDir, yes: opts.yes === true });
|
|
97
|
+
text = useStoreText;
|
|
98
|
+
}
|
|
99
|
+
if (opts.json) console.log(JSON.stringify(result, null, 2));
|
|
100
|
+
else console.log(text(result).join('\n'));
|
|
101
|
+
return result.ok === false ? 1 : 0;
|
|
102
|
+
}
|