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
|
@@ -30,6 +30,19 @@ const PLUGIN_ROOT = fileURLToPath(new URL('..', import.meta.url));
|
|
|
30
30
|
const RETENTION_NOTE = 'pages are a projection, not canonical memory';
|
|
31
31
|
const DEFAULT_LOCK_MS = 6 * 60 * 60 * 1000;
|
|
32
32
|
|
|
33
|
+
const gitRun = (_command, args, options) => spawnSync('total-recall', ['git', ...args], options);
|
|
34
|
+
|
|
35
|
+
function readJson(file) {
|
|
36
|
+
try { return JSON.parse(fs.readFileSync(file, 'utf8')); } catch { return null; }
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** An unfinished init must resume as init, even after it has written pages. */
|
|
40
|
+
export function generationMode(root) {
|
|
41
|
+
const state = readJson(path.join(root, 'openwiki', '.run.json'));
|
|
42
|
+
if (state?.mode === 'init' && state.phase && !['complete', 'idle'].includes(state.phase)) return 'init';
|
|
43
|
+
return hasWiki(root) ? 'update' : 'init';
|
|
44
|
+
}
|
|
45
|
+
|
|
33
46
|
export function registryPath(home = os.homedir()) {
|
|
34
47
|
return path.join(home, '.agent', 'skills', 'total-recall', 'config', 'project-registry.json');
|
|
35
48
|
}
|
|
@@ -69,7 +82,7 @@ export function readProjects({ registry = registryPath() } = {}) {
|
|
|
69
82
|
});
|
|
70
83
|
}
|
|
71
84
|
|
|
72
|
-
/** Does this project carry generated pages
|
|
85
|
+
/** Does this project carry generated Markdown pages? */
|
|
73
86
|
export function hasWiki(root) {
|
|
74
87
|
const dir = path.join(root, 'openwiki');
|
|
75
88
|
const stat = fs.lstatSync(dir, { throwIfNoEntry: false });
|
|
@@ -82,15 +95,18 @@ export function hasWiki(root) {
|
|
|
82
95
|
* since the recorded generation, which is the same measure the per-repo driver
|
|
83
96
|
* used. Uncommitted work is not counted, so an open edit does not read as drift.
|
|
84
97
|
*/
|
|
85
|
-
export function isGitRepo(root, { git =
|
|
98
|
+
export function isGitRepo(root, { git = gitRun } = {}) {
|
|
86
99
|
if (fs.existsSync(path.join(root, '.git'))) return true;
|
|
87
100
|
const res = git('git', ['-C', root, 'rev-parse', '--is-inside-work-tree'], { encoding: 'utf8' });
|
|
88
|
-
|
|
101
|
+
if (res.error || res.status !== 0 || String(res.stdout).trim() !== 'true') return false;
|
|
102
|
+
const top = git('git', ['-C', root, 'rev-parse', '--show-toplevel'], { encoding: 'utf8' });
|
|
103
|
+
if (top.error || top.status !== 0) return false;
|
|
104
|
+
return fs.realpathSync(root) === fs.realpathSync(String(top.stdout).trim());
|
|
89
105
|
}
|
|
90
106
|
|
|
91
|
-
export function staleness(root, { git =
|
|
107
|
+
export function staleness(root, { git = gitRun } = {}) {
|
|
92
108
|
if (!isGitRepo(root, { git })) {
|
|
93
|
-
return { root, head: '', generatedAt: null, generatedStatus: null, files: null, lastCodeChange: null, commitsSince: 0, stale: false };
|
|
109
|
+
return { root, head: '', generationCommit: null, generationTime: null, generatedAt: null, generatedStatus: null, files: null, lastCodeChange: null, commitsSince: 0, stale: false };
|
|
94
110
|
}
|
|
95
111
|
const marker = path.join(root, 'openwiki', '.last-update.json');
|
|
96
112
|
let head = '';
|
|
@@ -104,6 +120,11 @@ export function staleness(root, { git = spawnSync } = {}) {
|
|
|
104
120
|
generatedAt = typeof parsed.updatedAt === 'string' ? parsed.updatedAt : null;
|
|
105
121
|
generatedStatus = typeof parsed.status === 'string' ? parsed.status : null;
|
|
106
122
|
} catch { /* no marker: never generated, or unreadable */ }
|
|
123
|
+
const receipt = readJson(path.join(root, 'openwiki', '.generation.json'));
|
|
124
|
+
const validReceipt = typeof receipt?.commit === 'string' && /^[a-f0-9]{7,64}$/i.test(receipt.commit)
|
|
125
|
+
&& typeof receipt.completedAt === 'string' && Number.isFinite(Date.parse(receipt.completedAt));
|
|
126
|
+
const generationCommit = validReceipt ? receipt.commit : null;
|
|
127
|
+
const generationTime = validReceipt ? receipt.completedAt : null;
|
|
107
128
|
|
|
108
129
|
// The page contents, so a refresh can be judged on what it actually rewrote.
|
|
109
130
|
// openwiki writes its marker when generation begins, so the marker alone
|
|
@@ -122,12 +143,15 @@ export function staleness(root, { git = spawnSync } = {}) {
|
|
|
122
143
|
const lastCodeChange = !log.error && log.status === 0 ? String(log.stdout || '').trim() || null : null;
|
|
123
144
|
|
|
124
145
|
let commitsSince = null;
|
|
125
|
-
if (generatedAt) {
|
|
126
|
-
const
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
146
|
+
if (generationCommit || generatedAt) {
|
|
147
|
+
const range = generationCommit ? [`${generationCommit}..HEAD`] : [`--since=${generatedAt}`, 'HEAD'];
|
|
148
|
+
const count = git('git', ['-C', root, 'rev-list', '--count', ...range, '--', '.', ':!openwiki'], { encoding: 'utf8' });
|
|
149
|
+
const value = String(count.stdout || '').trim();
|
|
150
|
+
if (!count.error && count.status === 0 && /^\d+$/.test(value)) commitsSince = Number(value);
|
|
151
|
+
}
|
|
152
|
+
const incomplete = generatedStatus === 'interrupted' || stillGenerating(root);
|
|
153
|
+
const stale = incomplete || generatedAt === null || commitsSince === null || commitsSince > 0;
|
|
154
|
+
return { root, head, generationCommit, generationTime, generatedAt, generatedStatus, files, lastCodeChange, commitsSince, stale, mode: generationMode(root) };
|
|
131
155
|
}
|
|
132
156
|
|
|
133
157
|
/**
|
|
@@ -250,14 +274,81 @@ export function stillGenerating(root) {
|
|
|
250
274
|
}
|
|
251
275
|
}
|
|
252
276
|
|
|
277
|
+
function writeReceipt(root, name, value) {
|
|
278
|
+
const dir = path.join(root, 'openwiki');
|
|
279
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
280
|
+
const target = path.join(dir, name);
|
|
281
|
+
const tmp = `${target}.${process.pid}.${Date.now()}.tmp`;
|
|
282
|
+
try {
|
|
283
|
+
fs.writeFileSync(tmp, `${JSON.stringify(value, null, 2)}\n`, { flag: 'wx', mode: 0o600 });
|
|
284
|
+
fs.renameSync(tmp, target);
|
|
285
|
+
} finally {
|
|
286
|
+
fs.rmSync(tmp, { force: true });
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
function redact(value, key) {
|
|
291
|
+
let text = String(value || '');
|
|
292
|
+
if (key) text = text.split(key).join('[REDACTED]');
|
|
293
|
+
return text.replace(/\bBearer\s+\S+/gi, 'Bearer [REDACTED]').replace(/\bsk-[\w-]+/g, '[REDACTED]');
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
function finishRefresh(project, { before, result, git, key, mode, startedAt, via, clock }) {
|
|
297
|
+
const after = staleness(project.root, { git });
|
|
298
|
+
const exitCode = result.error ? (result.error.code || 1) : result.signal ? 1 : result.status;
|
|
299
|
+
const completedAt = new Date(clock()).toISOString();
|
|
300
|
+
const stdout = redact(result.stdout, key), stderr = redact(result.stderr, key);
|
|
301
|
+
const error = redact(result.error?.message, key);
|
|
302
|
+
const lines = `${stderr}\n${stdout}`.replace(/\x1b\[[0-9;]*m/g, '').split('\n').map(line => line.trim()).filter(Boolean);
|
|
303
|
+
const diagnostic = lines.find(line => /context_length_exceeded|Provider returned error|exited without|Could not restore|interrupted OpenWiki|fetch failed/.test(line));
|
|
304
|
+
const reason = error || (result.signal ? `terminated by ${result.signal}` : diagnostic || lines.filter(line => !/^(\[ERR\]\s*)?Error Diagnostics$/.test(line)).at(-1) || `exit ${exitCode}`);
|
|
305
|
+
const wrote = pagesWritten(before, after) || (!before.files && hasWiki(project.root) ? 1 : 0);
|
|
306
|
+
const advanced = after.generatedAt !== before.generatedAt;
|
|
307
|
+
let action, failureReason;
|
|
308
|
+
if (after.generatedStatus === 'interrupted' || stillGenerating(project.root)) {
|
|
309
|
+
action = 'partial';
|
|
310
|
+
failureReason = `${wrote} page(s) rewritten, but the run did not finish; it resumes on the next refresh (${reason})`;
|
|
311
|
+
} else if (exitCode !== 0) {
|
|
312
|
+
action = 'failed'; failureReason = reason;
|
|
313
|
+
} else if (!advanced && !wrote) {
|
|
314
|
+
action = 'failed'; failureReason = 'command exited 0 and no page changed';
|
|
315
|
+
} else if (!before.head) {
|
|
316
|
+
action = 'failed'; failureReason = 'Cannot record generation without a source commit';
|
|
317
|
+
} else {
|
|
318
|
+
action = mode === 'init' ? 'initialized' : 'refreshed';
|
|
319
|
+
}
|
|
320
|
+
const logPath = path.join(project.root, 'openwiki', '.refresh-attempt.json');
|
|
321
|
+
const report = { ...project, ...after, action, reason: failureReason, exitCode, signal: result.signal || null, from: before.generatedAt, to: after.generatedAt, durationMs: clock() - startedAt, via, mode, logPath };
|
|
322
|
+
try {
|
|
323
|
+
writeReceipt(project.root, '.refresh-attempt.json', { startedAt: new Date(startedAt).toISOString(), completedAt, sourceCommit: before.head || null, action, mode, exitCode, signal: result.signal || null, error, stdout, stderr });
|
|
324
|
+
if (action === 'initialized' || action === 'refreshed') {
|
|
325
|
+
writeReceipt(project.root, '.generation.json', { commit: before.head, completedAt });
|
|
326
|
+
report.generationCommit = before.head;
|
|
327
|
+
report.generationTime = completedAt;
|
|
328
|
+
report.commitsSince = after.head === before.head ? 0 : null;
|
|
329
|
+
report.stale = after.head !== before.head;
|
|
330
|
+
} else if (before.generationCommit && before.generationTime) {
|
|
331
|
+
// Init can replace openwiki/ before it fails. Retain the last success.
|
|
332
|
+
writeReceipt(project.root, '.generation.json', { commit: before.generationCommit, completedAt: before.generationTime });
|
|
333
|
+
report.generationCommit = before.generationCommit;
|
|
334
|
+
report.generationTime = before.generationTime;
|
|
335
|
+
}
|
|
336
|
+
} catch (error) {
|
|
337
|
+
report.action = 'failed'; report.reason = `Could not save refresh receipt: ${error.message}`;
|
|
338
|
+
}
|
|
339
|
+
return report;
|
|
340
|
+
}
|
|
341
|
+
|
|
253
342
|
export function refreshProject(project, {
|
|
254
|
-
key, model = null, provider = null, binary = null, binaryArgs = [], timeoutMs = 30 * 60 * 1000, run = spawnSync, now = Date.now(), targetVersion = null, pluginRoot = PLUGIN_ROOT,
|
|
343
|
+
key, model = null, provider = null, binary = null, binaryArgs = [], timeoutMs = 30 * 60 * 1000, run = spawnSync, now = Date.now(), clock = Date.now, targetVersion = null, pluginRoot = PLUGIN_ROOT,
|
|
255
344
|
} = {}) {
|
|
256
|
-
|
|
345
|
+
const git = run === spawnSync ? gitRun : run;
|
|
346
|
+
if (!isGitRepo(project.root, { git })) {
|
|
257
347
|
return { ...project, action: 'skipped', reason: 'not a git repository' };
|
|
258
348
|
}
|
|
259
|
-
const before = staleness(project.root, { git
|
|
349
|
+
const before = staleness(project.root, { git });
|
|
260
350
|
const uninitialized = !hasWiki(project.root);
|
|
351
|
+
const mode = generationMode(project.root);
|
|
261
352
|
|
|
262
353
|
let command = binary, args = binaryArgs, via = binary ? 'explicit' : null;
|
|
263
354
|
if (!command) {
|
|
@@ -273,19 +364,12 @@ export function refreshProject(project, {
|
|
|
273
364
|
const selectedModel = model || config.model;
|
|
274
365
|
const selectedProvider = provider || config.provider;
|
|
275
366
|
|
|
276
|
-
const modeFlag =
|
|
367
|
+
const modeFlag = `--${mode}`;
|
|
277
368
|
const cmdArgs = [...args, modeFlag, '-p'];
|
|
278
369
|
if (selectedModel) {
|
|
279
370
|
cmdArgs.push('--modelId', selectedModel);
|
|
280
371
|
}
|
|
281
372
|
|
|
282
|
-
if (uninitialized) {
|
|
283
|
-
const runFile = path.join(project.root, 'openwiki', '.run.json');
|
|
284
|
-
if (fs.existsSync(runFile)) {
|
|
285
|
-
try { fs.unlinkSync(runFile); } catch {}
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
|
|
289
373
|
const childEnv = { ...process.env };
|
|
290
374
|
if (selectedProvider === 'google') {
|
|
291
375
|
childEnv.GOOGLE_API_KEY = key;
|
|
@@ -312,47 +396,18 @@ export function refreshProject(project, {
|
|
|
312
396
|
timeout: timeoutMs,
|
|
313
397
|
});
|
|
314
398
|
|
|
315
|
-
|
|
316
|
-
const exitCode = result.error ? (result.error.code || 1) : result.status;
|
|
317
|
-
const advanced = after.generatedAt !== before.generatedAt || (uninitialized && hasWiki(project.root));
|
|
318
|
-
const wrote = pagesWritten(before, after) || (uninitialized && hasWiki(project.root) ? 1 : 0);
|
|
319
|
-
|
|
320
|
-
const outcome = after.generatedStatus === 'interrupted' || stillGenerating(project.root)
|
|
321
|
-
? 'partial'
|
|
322
|
-
: (advanced ? (uninitialized ? 'initialized' : 'refreshed') : 'unchanged');
|
|
323
|
-
|
|
324
|
-
if (exitCode !== 0 && !wrote) {
|
|
325
|
-
return { ...project, action: 'failed', reason: result.error?.message || `exit ${exitCode}`, exitCode, ...after };
|
|
326
|
-
}
|
|
327
|
-
if (!advanced && !wrote) {
|
|
328
|
-
return { ...project, action: 'failed', reason: `command exited ${exitCode} and no page changed`, exitCode, ...after };
|
|
329
|
-
}
|
|
330
|
-
if (outcome === 'partial') {
|
|
331
|
-
return {
|
|
332
|
-
...project,
|
|
333
|
-
action: 'partial',
|
|
334
|
-
reason: `${wrote} page(s) rewritten, but the run did not finish (the generator was cut off); it resumes on the next refresh`,
|
|
335
|
-
exitCode,
|
|
336
|
-
from: before.generatedAt,
|
|
337
|
-
to: after.generatedAt,
|
|
338
|
-
via,
|
|
339
|
-
...after,
|
|
340
|
-
};
|
|
341
|
-
}
|
|
342
|
-
if (exitCode !== 0) {
|
|
343
|
-
return { ...project, action: 'failed', reason: result.error?.message || `exit ${exitCode}`, exitCode, ...after };
|
|
344
|
-
}
|
|
345
|
-
return { ...project, action: uninitialized ? 'initialized' : 'refreshed', from: before.generatedAt, to: after.generatedAt, durationMs: Date.now() - startedAt, via, ...after };
|
|
399
|
+
return finishRefresh(project, { before, result, git, key, mode, startedAt, via, clock });
|
|
346
400
|
}
|
|
347
401
|
|
|
348
402
|
export async function refreshProjectAsync(project, {
|
|
349
|
-
key, model = null, provider = null, binary = null, binaryArgs = [], timeoutMs = 30 * 60 * 1000, now = Date.now(), targetVersion = null, pluginRoot = PLUGIN_ROOT,
|
|
403
|
+
key, model = null, provider = null, binary = null, binaryArgs = [], timeoutMs = 30 * 60 * 1000, now = Date.now(), clock = Date.now, targetVersion = null, pluginRoot = PLUGIN_ROOT, git = gitRun, spawnProcess = spawn,
|
|
350
404
|
} = {}) {
|
|
351
|
-
if (!isGitRepo(project.root, { git
|
|
405
|
+
if (!isGitRepo(project.root, { git })) {
|
|
352
406
|
return { ...project, action: 'skipped', reason: 'not a git repository' };
|
|
353
407
|
}
|
|
354
|
-
const before = staleness(project.root, { git
|
|
408
|
+
const before = staleness(project.root, { git });
|
|
355
409
|
const uninitialized = !hasWiki(project.root);
|
|
410
|
+
const mode = generationMode(project.root);
|
|
356
411
|
let command = binary, args = binaryArgs, via = binary ? 'explicit' : null;
|
|
357
412
|
if (!command) {
|
|
358
413
|
const resolved = resolveGenerator({ run: spawnSync, targetVersion, pluginRoot, requireBundled: uninitialized });
|
|
@@ -367,19 +422,12 @@ export async function refreshProjectAsync(project, {
|
|
|
367
422
|
const selectedModel = model || config.model;
|
|
368
423
|
const selectedProvider = provider || config.provider;
|
|
369
424
|
|
|
370
|
-
const modeFlag =
|
|
425
|
+
const modeFlag = `--${mode}`;
|
|
371
426
|
const cmdArgs = [...args, modeFlag, '-p'];
|
|
372
427
|
if (selectedModel) {
|
|
373
428
|
cmdArgs.push('--modelId', selectedModel);
|
|
374
429
|
}
|
|
375
430
|
|
|
376
|
-
if (uninitialized) {
|
|
377
|
-
const runFile = path.join(project.root, 'openwiki', '.run.json');
|
|
378
|
-
if (fs.existsSync(runFile)) {
|
|
379
|
-
try { fs.unlinkSync(runFile); } catch {}
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
|
|
383
431
|
const childEnv = { ...process.env };
|
|
384
432
|
if (selectedProvider === 'google') {
|
|
385
433
|
childEnv.GOOGLE_API_KEY = key;
|
|
@@ -399,74 +447,33 @@ export async function refreshProjectAsync(project, {
|
|
|
399
447
|
|
|
400
448
|
const startedAt = now;
|
|
401
449
|
const result = await new Promise((resolve) => {
|
|
402
|
-
const proc =
|
|
450
|
+
const proc = spawnProcess(command, cmdArgs, {
|
|
403
451
|
cwd: project.root,
|
|
404
452
|
env: childEnv,
|
|
405
453
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
406
454
|
timeout: timeoutMs,
|
|
407
455
|
});
|
|
408
|
-
let stdout = '', stderr = '';
|
|
456
|
+
let stdout = '', stderr = '', error = null;
|
|
409
457
|
proc.stdout?.on('data', (d) => { stdout += d; });
|
|
410
458
|
proc.stderr?.on('data', (d) => { stderr += d; });
|
|
411
|
-
proc.on('error', (err) =>
|
|
412
|
-
proc.on('close', (status) => resolve({
|
|
459
|
+
proc.on('error', (err) => { error = err; });
|
|
460
|
+
proc.on('close', (status, signal) => resolve({ error, status, signal, stdout, stderr }));
|
|
413
461
|
});
|
|
414
|
-
|
|
415
|
-
const after = staleness(project.root, { git: spawnSync });
|
|
416
|
-
const exitCode = result.error ? (result.error.code || 1) : result.status;
|
|
417
|
-
const advanced = after.generatedAt !== before.generatedAt || (uninitialized && hasWiki(project.root));
|
|
418
|
-
const wrote = pagesWritten(before, after) || (uninitialized && hasWiki(project.root) ? 1 : 0);
|
|
419
|
-
|
|
420
|
-
const outcome = after.generatedStatus === 'interrupted' || stillGenerating(project.root)
|
|
421
|
-
? 'partial'
|
|
422
|
-
: (advanced ? (uninitialized ? 'initialized' : 'refreshed') : 'unchanged');
|
|
423
|
-
|
|
424
|
-
const extractReason = (rawErr, rawOut) => {
|
|
425
|
-
if (result.error?.message) return result.error.message;
|
|
426
|
-
const combined = `${rawErr || ''}\n${rawOut || ''}`.trim();
|
|
427
|
-
if (!combined) return `exit ${exitCode}`;
|
|
428
|
-
const lines = combined.split('\n').map((l) => l.trim()).filter(Boolean);
|
|
429
|
-
const diag = lines.find((l) => l.includes('Error Diagnostics') || l.includes('exited without') || l.includes('Could not restore') || l.includes('Provider returned error') || l.includes('fetch failed'));
|
|
430
|
-
if (diag) return diag.replace(/^\[ERR\]\s*/, '');
|
|
431
|
-
const last = lines[lines.length - 1];
|
|
432
|
-
return last ? last.replace(/^\[ERR\]\s*/, '') : `exit ${exitCode}`;
|
|
433
|
-
};
|
|
434
|
-
const failReason = extractReason(result.stderr, result.stdout);
|
|
435
|
-
|
|
436
|
-
if (exitCode !== 0 && !wrote) {
|
|
437
|
-
return { ...project, action: 'failed', reason: failReason, exitCode, ...after };
|
|
438
|
-
}
|
|
439
|
-
if (!advanced && !wrote) {
|
|
440
|
-
return { ...project, action: 'failed', reason: failReason || `command exited ${exitCode} and no page changed`, exitCode, ...after };
|
|
441
|
-
}
|
|
442
|
-
if (outcome === 'partial') {
|
|
443
|
-
return {
|
|
444
|
-
...project,
|
|
445
|
-
action: 'partial',
|
|
446
|
-
reason: `${wrote} page(s) rewritten, but the run did not finish (the generator was cut off); it resumes on the next refresh`,
|
|
447
|
-
exitCode,
|
|
448
|
-
from: before.generatedAt,
|
|
449
|
-
to: after.generatedAt,
|
|
450
|
-
via,
|
|
451
|
-
...after,
|
|
452
|
-
};
|
|
453
|
-
}
|
|
454
|
-
if (exitCode !== 0) {
|
|
455
|
-
return { ...project, action: 'failed', reason: failReason, exitCode, ...after };
|
|
456
|
-
}
|
|
457
|
-
return { ...project, action: uninitialized ? 'initialized' : 'refreshed', from: before.generatedAt, to: after.generatedAt, durationMs: Date.now() - startedAt, via, ...after };
|
|
462
|
+
return finishRefresh(project, { before, result, git, key, mode, startedAt, via, clock });
|
|
458
463
|
}
|
|
459
464
|
|
|
460
465
|
/** Is a refresh due for this project under the configured interval? */
|
|
461
|
-
export function isDue(project, { lockMs = DEFAULT_LOCK_MS, now = Date.now(), git =
|
|
466
|
+
export function isDue(project, { lockMs = DEFAULT_LOCK_MS, now = Date.now(), git = gitRun, force = false } = {}) {
|
|
462
467
|
if (!isGitRepo(project.root, { git })) {
|
|
463
468
|
return { due: false, skipped: true, reason: 'not a git repository' };
|
|
464
469
|
}
|
|
465
470
|
const state = staleness(project.root, { git });
|
|
471
|
+
if (force) return { due: true, uninitialized: !hasWiki(project.root), ...state };
|
|
466
472
|
if (!hasWiki(project.root)) {
|
|
467
473
|
return { due: true, uninitialized: true, reason: 'uninitialized (missing openwiki/ pages)', ...state };
|
|
468
474
|
}
|
|
469
475
|
if (!state.stale) return { due: false, ...state };
|
|
476
|
+
if (state.generatedStatus === 'interrupted' || stillGenerating(project.root)) return { due: true, reason: 'resume incomplete generation', ...state };
|
|
470
477
|
if (state.generatedAt) {
|
|
471
478
|
const at = Date.parse(state.generatedAt);
|
|
472
479
|
if (Number.isFinite(at) && now - at < lockMs) return { due: false, reason: 'refreshed recently', ...state };
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tr-plugin-security",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.7",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "tr-plugin-security",
|
|
9
|
-
"version": "0.3.
|
|
9
|
+
"version": "0.3.7",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@gregiteen/ssss-cli": "0.14.
|
|
12
|
+
"@gregiteen/ssss-cli": "0.14.5"
|
|
13
13
|
},
|
|
14
14
|
"devDependencies": {
|
|
15
15
|
"jsdom": "^26.1.0",
|
|
16
|
-
"total-recall-brain": "3.
|
|
16
|
+
"total-recall-brain": "3.44.0"
|
|
17
17
|
}
|
|
18
18
|
},
|
|
19
19
|
"node_modules/@alcalzone/ansi-tokenize": {
|
|
@@ -845,9 +845,9 @@
|
|
|
845
845
|
}
|
|
846
846
|
},
|
|
847
847
|
"node_modules/@gregiteen/ssss-cli": {
|
|
848
|
-
"version": "0.14.
|
|
849
|
-
"resolved": "https://registry.npmjs.org/@gregiteen/ssss-cli/-/ssss-cli-0.14.
|
|
850
|
-
"integrity": "sha512-
|
|
848
|
+
"version": "0.14.5",
|
|
849
|
+
"resolved": "https://registry.npmjs.org/@gregiteen/ssss-cli/-/ssss-cli-0.14.5.tgz",
|
|
850
|
+
"integrity": "sha512-qVEYOocnwn97uJ0eDzmuwN06CYsYWr2t3+iKylpisBHX4wlLWk7P8EmFFdBlx7NyKVIZDDeYT164Gd7/T8UGgw==",
|
|
851
851
|
"license": "ISC",
|
|
852
852
|
"bin": {
|
|
853
853
|
"ssss": "scripts/ssss.mjs"
|
|
@@ -1686,9 +1686,9 @@
|
|
|
1686
1686
|
},
|
|
1687
1687
|
"node_modules/@ssss/cli": {
|
|
1688
1688
|
"name": "@gregiteen/ssss-cli",
|
|
1689
|
-
"version": "0.14.
|
|
1690
|
-
"resolved": "https://registry.npmjs.org/@gregiteen/ssss-cli/-/ssss-cli-0.14.
|
|
1691
|
-
"integrity": "sha512-
|
|
1689
|
+
"version": "0.14.5",
|
|
1690
|
+
"resolved": "https://registry.npmjs.org/@gregiteen/ssss-cli/-/ssss-cli-0.14.5.tgz",
|
|
1691
|
+
"integrity": "sha512-qVEYOocnwn97uJ0eDzmuwN06CYsYWr2t3+iKylpisBHX4wlLWk7P8EmFFdBlx7NyKVIZDDeYT164Gd7/T8UGgw==",
|
|
1692
1692
|
"dev": true,
|
|
1693
1693
|
"license": "ISC",
|
|
1694
1694
|
"bin": {
|
|
@@ -5698,9 +5698,9 @@
|
|
|
5698
5698
|
}
|
|
5699
5699
|
},
|
|
5700
5700
|
"node_modules/total-recall-brain": {
|
|
5701
|
-
"version": "3.
|
|
5702
|
-
"resolved": "https://registry.npmjs.org/total-recall-brain/-/total-recall-brain-3.
|
|
5703
|
-
"integrity": "sha512-
|
|
5701
|
+
"version": "3.44.0",
|
|
5702
|
+
"resolved": "https://registry.npmjs.org/total-recall-brain/-/total-recall-brain-3.44.0.tgz",
|
|
5703
|
+
"integrity": "sha512-VNPaIO9zsSwoxAsJ5ByIQBP9zPpLq4RiQO7Vrex4rBOHFQJT50P7utcZiLMSZTyZJU4C/m5uB8qTCSBMp6+l6Q==",
|
|
5704
5704
|
"dev": true,
|
|
5705
5705
|
"license": "MIT",
|
|
5706
5706
|
"workspaces": [
|
|
@@ -5708,7 +5708,7 @@
|
|
|
5708
5708
|
],
|
|
5709
5709
|
"dependencies": {
|
|
5710
5710
|
"@simplewebauthn/server": "^13.3.2",
|
|
5711
|
-
"@ssss/cli": "npm:@gregiteen/ssss-cli@0.14.
|
|
5711
|
+
"@ssss/cli": "npm:@gregiteen/ssss-cli@0.14.5",
|
|
5712
5712
|
"bcrypt": "^6.0.0",
|
|
5713
5713
|
"better-sqlite3": "^12.11.1",
|
|
5714
5714
|
"cookie-parser": "^1.4.7",
|
|
@@ -5731,6 +5731,7 @@
|
|
|
5731
5731
|
"antigravity": "bin/antigravity.mjs",
|
|
5732
5732
|
"total-recall": "bin/total-recall.mjs",
|
|
5733
5733
|
"total-recall-memory": "bin/total-recall-memory.mjs",
|
|
5734
|
+
"total-recall-server-release": "bin/total-recall-server-release.mjs",
|
|
5734
5735
|
"vibebrain": "bin/total-recall.mjs"
|
|
5735
5736
|
},
|
|
5736
5737
|
"optionalDependencies": {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tr-plugin-security",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.7",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Standalone security suite for Total Recall: static analysis, file and permission hardening schemes, AES-256-GCM encryption tools, and egress audit controls",
|
|
6
6
|
"scripts": {
|
|
@@ -24,9 +24,9 @@
|
|
|
24
24
|
"access": "public"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@gregiteen/ssss-cli": "0.14.
|
|
27
|
+
"@gregiteen/ssss-cli": "0.14.5"
|
|
28
28
|
},
|
|
29
29
|
"overrides": {
|
|
30
|
-
"@ssss/cli": "npm:@gregiteen/ssss-cli@0.14.
|
|
30
|
+
"@ssss/cli": "npm:@gregiteen/ssss-cli@0.14.5"
|
|
31
31
|
}
|
|
32
32
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://github.com/gregiteen/total-recall/blob/main/metadata.plugin.schema.json",
|
|
3
3
|
"id": "security",
|
|
4
4
|
"name": "Security Assessments",
|
|
5
|
-
"version": "0.3.
|
|
5
|
+
"version": "0.3.7",
|
|
6
6
|
"description": "Machine and device security assessments for macOS, Linux, Windows, Android, Chromebook, iPhone and iPad, with explicit measured and manual coverage.",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"requires": [{ "id": "auth", "range": ">=1.2.1" }],
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.14.
|
|
2
|
+
"version": "0.14.5",
|
|
3
3
|
"files": {
|
|
4
4
|
".gitignore": {
|
|
5
5
|
"sha256": "0d6c69a5cbd2270c9163d8e1563976b6d15131d0ef599e6fbc413ee287a86da0",
|
|
@@ -18,8 +18,8 @@
|
|
|
18
18
|
"content": "# ssss-project — System Architecture & Design\n\n> Technical design and architecture specification for ssss-project.\n\n## Overview\n\n<High-level summary of the system and its primary goals.>\n\n## Component Architecture\n\n- **Vault Structure**: Typed Markdown documents under `vault/` serving as the source of truth.\n- **Workflows & Execution**: Automated procedures defined in `vault/workflows/` triggered by operational events.\n- **Capabilities & Resources**: Tools and external service integrations required for execution.\n\n## Data & Schema Contracts\n\n<Core entities, external dependencies, and integration interfaces.>\n\n## Open Decisions & Invariants\n\n- SSSS VFS is the single source of truth for application state.\n- Structural business logic is strictly decoupled from private tenant operational data.\n- App-specific primitives reside in `registry/extensions/` within this repository and extend `core`.\n- Core SSSS library (`@gregiteen/ssss-cli`) remains vendor-neutral and dependency-free.\n"
|
|
19
19
|
},
|
|
20
20
|
"package.json": {
|
|
21
|
-
"sha256": "
|
|
22
|
-
"content": "{\n \"name\": \"ssss-project\",\n \"version\": \"0.1.0\",\n \"private\": true,\n \"type\": \"module\",\n \"description\": \"An SSSS-native project — Markdown vault as source of truth.\",\n \"scripts\": {\n \"ssss\": \"ssss\",\n \"test\": \"node --test\",\n \"export\": \"ssss export vault --profile sale --out dist/bundle.ucw.json\",\n \"validate\": \"ssss conformance --engine\"\n },\n \"dependencies\": {\n \"@gregiteen/ssss-cli\": \"github:gregiteen/ssss#v0.14.
|
|
21
|
+
"sha256": "ea77c2944b853999741a8e603de257604048c63b5db8754a0e8b92f383ff973b",
|
|
22
|
+
"content": "{\n \"name\": \"ssss-project\",\n \"version\": \"0.1.0\",\n \"private\": true,\n \"type\": \"module\",\n \"description\": \"An SSSS-native project — Markdown vault as source of truth.\",\n \"scripts\": {\n \"ssss\": \"ssss\",\n \"test\": \"node --test\",\n \"export\": \"ssss export vault --profile sale --out dist/bundle.ucw.json\",\n \"validate\": \"ssss conformance --engine\"\n },\n \"dependencies\": {\n \"@gregiteen/ssss-cli\": \"github:gregiteen/ssss#v0.14.5\"\n }\n}\n"
|
|
23
23
|
},
|
|
24
24
|
"test/ssss-conformance.test.mjs": {
|
|
25
25
|
"sha256": "f626d2f56799fcfda74375d3ddf546cc181a10caf2df08b72b7f2e36782c9bc1",
|
|
@@ -43,8 +43,8 @@
|
|
|
43
43
|
}
|
|
44
44
|
},
|
|
45
45
|
"skill": {
|
|
46
|
-
"SKILL.md": "
|
|
47
|
-
"core/SKILL.md": "
|
|
46
|
+
"SKILL.md": "e5c2c0aa2c0fb5480c1f7bdb37928f935e1160bff18fd6b63366a04f3e281938",
|
|
47
|
+
"core/SKILL.md": "12543720135f13650efcd7afd751e3253996692c6ab805fd7da99788b6fc4af9",
|
|
48
48
|
"core/references/core-registry.json": "16831aa3b6be3f561a9ca7abdc36065a4843ff595aa3acf5c3fb8af2d733b7e3",
|
|
49
49
|
"core/references/ssss-spec.md": "cc319e78b1b568651d5717695348363349d502c0e20663da9858369022ddfc3b",
|
|
50
50
|
"core/scripts/maintain.mjs": "eebcae898f2ce0cf3f0059c6f6737bee8877409de2d370d54a4015a9a82414e9",
|
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tr-plugin-ssss",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "tr-plugin-ssss",
|
|
9
|
-
"version": "0.1.
|
|
9
|
+
"version": "0.1.3",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@gregiteen/ssss-cli": "0.14.
|
|
12
|
+
"@gregiteen/ssss-cli": "0.14.5"
|
|
13
13
|
}
|
|
14
14
|
},
|
|
15
15
|
"node_modules/@gregiteen/ssss-cli": {
|
|
16
|
-
"version": "0.14.
|
|
17
|
-
"resolved": "https://registry.npmjs.org/@gregiteen/ssss-cli/-/ssss-cli-0.14.
|
|
18
|
-
"integrity": "sha512-
|
|
16
|
+
"version": "0.14.5",
|
|
17
|
+
"resolved": "https://registry.npmjs.org/@gregiteen/ssss-cli/-/ssss-cli-0.14.5.tgz",
|
|
18
|
+
"integrity": "sha512-qVEYOocnwn97uJ0eDzmuwN06CYsYWr2t3+iKylpisBHX4wlLWk7P8EmFFdBlx7NyKVIZDDeYT164Gd7/T8UGgw==",
|
|
19
19
|
"license": "ISC",
|
|
20
20
|
"bin": {
|
|
21
21
|
"ssss": "scripts/ssss.mjs"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tr-plugin-ssss",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"private": true,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Canonical SSSS distribution, scaffolding and validation for Total Recall installations.",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"check:ssss-conformance": "node cli.mjs conformance"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@gregiteen/ssss-cli": "0.14.
|
|
22
|
+
"@gregiteen/ssss-cli": "0.14.5"
|
|
23
23
|
},
|
|
24
24
|
"license": "MIT"
|
|
25
25
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://github.com/gregiteen/total-recall/blob/main/metadata.plugin.schema.json",
|
|
3
3
|
"id": "ssss",
|
|
4
4
|
"name": "SSSS",
|
|
5
|
-
"version": "0.1.
|
|
5
|
+
"version": "0.1.3",
|
|
6
6
|
"description": "Canonical SSSS distribution, scaffolding and validation for Total Recall installations.",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"use_cases": ["software-development", "state-conformance"],
|
|
@@ -16,7 +16,7 @@ Publication/deployment use the owning push/deploy procedures when authorized. Sh
|
|
|
16
16
|
|
|
17
17
|
Use `brain status` to check the current project and physical global storage. Preview `brain relocate-global <dir>` before adding `--apply`. The destination must be a new private directory outside Git on the same filesystem as home. The home skills path links to the relocated tree. Keep repository brains in their own directories.
|
|
18
18
|
|
|
19
|
-
Run normal preflight from home for global orchestration. Pass a repository working directory when routing repository work through
|
|
19
|
+
Run normal preflight from home for global orchestration. Pass a repository working directory when routing repository work through Metaharness. Use `plugin copies` to audit old project copies of shared defaults. `--apply` deletes verified bundled matches. Add `--archive-stale` to retain differing older copies in the replacement archive and use the shared versions.
|
|
20
20
|
|
|
21
21
|
## Optional developer API
|
|
22
22
|
|
package/src/cli/agent.mjs
CHANGED
|
@@ -31,7 +31,7 @@ Options:
|
|
|
31
31
|
--allow-unknown-auth Explicitly permit a harness without a verified login probe
|
|
32
32
|
|
|
33
33
|
Auth:
|
|
34
|
-
The
|
|
34
|
+
The Metaharness owner probes login and resolves only adapter-declared credentials through auth.
|
|
35
35
|
|
|
36
36
|
Available Harnesses:
|
|
37
37
|
agy, claude, codex, dsh, hermes, openclaw
|
package/src/cli/command.mjs
CHANGED
|
@@ -247,21 +247,59 @@ function existingTag(file, key) {
|
|
|
247
247
|
try { return fs.readFileSync(file, 'utf8').match(new RegExp(`^// @${key} (.+)$`, 'm'))?.[1] || undefined; } catch { return undefined; }
|
|
248
248
|
}
|
|
249
249
|
|
|
250
|
+
/** Where the background recompile records its outcome: <agentDir>/state and <agentDir>/logs. */
|
|
251
|
+
export function compileRecordPaths(isGlobal) {
|
|
252
|
+
const agentDir = path.dirname(resolveTargetDir(isGlobal));
|
|
253
|
+
return {
|
|
254
|
+
status: path.join(agentDir, 'state', 'command-compile.json'),
|
|
255
|
+
log: path.join(agentDir, 'logs', 'command-compile.log'),
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// Runs in the detached child: compile, then record the exit code and output.
|
|
260
|
+
const COMPILE_RECORDER = `
|
|
261
|
+
const { spawnSync } = require('node:child_process');
|
|
262
|
+
const fs = require('node:fs');
|
|
263
|
+
const [cli, layer, statusFile, logFile] = process.argv.slice(1);
|
|
264
|
+
const startedAt = new Date().toISOString();
|
|
265
|
+
const r = spawnSync(process.execPath, [cli, 'compile', layer], { encoding: 'utf8', maxBuffer: 64 * 1024 * 1024 });
|
|
266
|
+
const code = r.status === null ? 1 : r.status;
|
|
267
|
+
fs.writeFileSync(logFile, (r.stdout || '') + (r.stderr || '') + (r.error ? String(r.error) + '\\n' : ''));
|
|
268
|
+
const record = { ok: code === 0, code, signal: r.signal || null, layer, startedAt, finishedAt: new Date().toISOString(), log: logFile };
|
|
269
|
+
fs.writeFileSync(statusFile + '.tmp', JSON.stringify(record, null, 2));
|
|
270
|
+
fs.renameSync(statusFile + '.tmp', statusFile);
|
|
271
|
+
`;
|
|
272
|
+
|
|
250
273
|
/**
|
|
251
274
|
* Composable instructions: the surfaces list every command, so any change to
|
|
252
275
|
* the command set recompiles them (project layer, or every project for global).
|
|
276
|
+
* A global compile takes minutes, so it runs in the background; its exit code and
|
|
277
|
+
* output are recorded, and the next `command` call reports a failure.
|
|
253
278
|
*/
|
|
254
279
|
export function recompileSurfaces(isGlobal) {
|
|
255
280
|
if (process.env.TR_COMMAND_NO_COMPILE === '1' || !process.argv[1]) return;
|
|
256
281
|
try {
|
|
257
|
-
const
|
|
282
|
+
const { status, log } = compileRecordPaths(isGlobal);
|
|
283
|
+
fs.mkdirSync(path.dirname(status), { recursive: true });
|
|
284
|
+
fs.mkdirSync(path.dirname(log), { recursive: true });
|
|
285
|
+
const child = spawn(process.execPath, ['-e', COMPILE_RECORDER, process.argv[1], isGlobal ? '--global' : '--project', status, log], { detached: true, stdio: 'ignore' });
|
|
258
286
|
child.unref();
|
|
259
|
-
console.log(
|
|
287
|
+
console.log(` ⏳ Instruction surfaces recompiling in the background (command list updated). Outcome: ${status}`);
|
|
260
288
|
} catch (error) {
|
|
261
289
|
console.warn(` ⚠️ Command saved, but surface recompile failed to start: ${error.message}`);
|
|
290
|
+
process.exitCode = 1;
|
|
262
291
|
}
|
|
263
292
|
}
|
|
264
293
|
|
|
294
|
+
/** Report a failed background recompile; returns the record when it failed. */
|
|
295
|
+
export function reportFailedCompile(isGlobal, out = console.warn) {
|
|
296
|
+
let record;
|
|
297
|
+
try { record = JSON.parse(fs.readFileSync(compileRecordPaths(isGlobal).status, 'utf8')); } catch { return null; }
|
|
298
|
+
if (record.ok) return null;
|
|
299
|
+
out(` ❌ The last instruction-surface recompile (${record.layer}, ${record.finishedAt}) failed with exit ${record.code}. Surfaces may not list current commands. Log: ${record.log}. Run 'total-recall compile ${record.layer}' to retry.`);
|
|
300
|
+
return record;
|
|
301
|
+
}
|
|
302
|
+
|
|
265
303
|
/**
|
|
266
304
|
* Register every `commands` entry of an installed plugin as a composable command.
|
|
267
305
|
* A command that already exists and was generated from this plugin is refreshed;
|
|
@@ -319,6 +357,7 @@ export default async function commandCmd(rawArgs = []) {
|
|
|
319
357
|
|
|
320
358
|
const action = cleanArgs[0];
|
|
321
359
|
const name = cleanArgs[1];
|
|
360
|
+
if (process.env.TR_COMMAND_NO_COMPILE !== '1') reportFailedCompile(isGlobal);
|
|
322
361
|
|
|
323
362
|
if (!action || action === '--help' || action === '-h') {
|
|
324
363
|
printHelp();
|