@theglitchking/semantic-memory 1.2.2 → 1.5.1
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/.claude-plugin/marketplace.json +4 -4
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +154 -0
- package/ROADMAP.md +5 -2
- package/commands/healthcheck.md +13 -11
- package/dist/{chunk-UQSASB7Q.js → chunk-2EELGTLX.js} +32 -3
- package/dist/chunk-2EELGTLX.js.map +1 -0
- package/dist/chunk-5ZKNO6ZD.js +96 -0
- package/dist/chunk-5ZKNO6ZD.js.map +1 -0
- package/dist/chunk-7M3JZOYH.js +105 -0
- package/dist/chunk-7M3JZOYH.js.map +1 -0
- package/dist/chunk-A3KYHKB5.js +176 -0
- package/dist/chunk-A3KYHKB5.js.map +1 -0
- package/dist/{chunk-CYWPDFNI.js → chunk-CSXZ7QUU.js} +4 -203
- package/dist/chunk-CSXZ7QUU.js.map +1 -0
- package/dist/chunk-FM26NFTR.js +272 -0
- package/dist/chunk-FM26NFTR.js.map +1 -0
- package/dist/chunk-NTYYS53O.js +91 -0
- package/dist/chunk-NTYYS53O.js.map +1 -0
- package/dist/{chunk-E2Z4J4MK.js → chunk-OWZWMB4P.js} +70 -2
- package/dist/chunk-OWZWMB4P.js.map +1 -0
- package/dist/chunk-S4KW7VH4.js +203 -0
- package/dist/chunk-S4KW7VH4.js.map +1 -0
- package/dist/{chunk-HODDRXJK.js → chunk-V45NJIHI.js} +4 -2
- package/dist/chunk-V45NJIHI.js.map +1 -0
- package/dist/chunk-WSU4QIPB.js +311 -0
- package/dist/chunk-WSU4QIPB.js.map +1 -0
- package/dist/cli/index.js +265 -65
- package/dist/cli/index.js.map +1 -1
- package/dist/core/index.d.ts +39 -2
- package/dist/core/index.js +17 -11
- package/dist/decay-ELJUKVQG.js +14 -0
- package/dist/dossier-2UG724LB.js +39 -0
- package/dist/healthcheck-IMB47LZE.js +19 -0
- package/dist/indexer-YW4O3VVM.js +8 -0
- package/dist/lexicon-5PXQEMUF.js +26 -0
- package/dist/lexicon-5PXQEMUF.js.map +1 -0
- package/dist/lint-XUQ7JDYX.js +16 -0
- package/dist/lint-XUQ7JDYX.js.map +1 -0
- package/dist/mcp/server.js +478 -40
- package/dist/mcp/server.js.map +1 -1
- package/dist/profile-LXUEF7TX.js +20 -0
- package/dist/profile-LXUEF7TX.js.map +1 -0
- package/dist/{schema-F3RTY6SQ.js → schema-ATFCLC6Y.js} +2 -2
- package/dist/schema-ATFCLC6Y.js.map +1 -0
- package/dist/{search-27WYAI24.js → search-AHKEFI2B.js} +2 -2
- package/dist/telemetry-GB2TEHVE.js +21 -0
- package/dist/telemetry-GB2TEHVE.js.map +1 -0
- package/hooks/vault-context.js +270 -11
- package/package.json +16 -1
- package/skills/vault-first/SKILL.md +18 -0
- package/dist/chunk-CAN2GWUG.js +0 -88
- package/dist/chunk-CAN2GWUG.js.map +0 -1
- package/dist/chunk-CYWPDFNI.js.map +0 -1
- package/dist/chunk-E2Z4J4MK.js.map +0 -1
- package/dist/chunk-HODDRXJK.js.map +0 -1
- package/dist/chunk-UQSASB7Q.js.map +0 -1
- package/dist/healthcheck-E4GI5RMZ.js +0 -14
- package/dist/indexer-KD6UTXZB.js +0 -8
- package/dist/lint-GMXQF4RW.js +0 -11
- /package/dist/{healthcheck-E4GI5RMZ.js.map → decay-ELJUKVQG.js.map} +0 -0
- /package/dist/{indexer-KD6UTXZB.js.map → dossier-2UG724LB.js.map} +0 -0
- /package/dist/{lint-GMXQF4RW.js.map → healthcheck-IMB47LZE.js.map} +0 -0
- /package/dist/{schema-F3RTY6SQ.js.map → indexer-YW4O3VVM.js.map} +0 -0
- /package/dist/{search-27WYAI24.js.map → search-AHKEFI2B.js.map} +0 -0
package/dist/cli/index.js
CHANGED
|
@@ -7,6 +7,46 @@ import { resolve as resolve2, join as join3, dirname, relative } from "path";
|
|
|
7
7
|
import { existsSync as existsSync3, readFileSync, writeFileSync, rmSync } from "fs";
|
|
8
8
|
import { createRequire } from "module";
|
|
9
9
|
import { spawnSync } from "child_process";
|
|
10
|
+
import { pathToFileURL } from "url";
|
|
11
|
+
|
|
12
|
+
// src/core/healthcheck-fix.ts
|
|
13
|
+
var MANUAL_REASON = {
|
|
14
|
+
"regenerate-contract": "AGENTS.md needs a human decision \u2014 run `/contract` (regenerate_contract), or move custom content into a Local Notes section outside the managed block.",
|
|
15
|
+
lint_vault: "Vault lint findings (stale notes, broken wikilinks, schema violations) require human review \u2014 run `lint_vault` for the full report.",
|
|
16
|
+
session_staleness: "Resume the session (session_run / session_finish) or remove .claude/.semantic-memory/session.json to abandon it."
|
|
17
|
+
};
|
|
18
|
+
function planFixes(findings) {
|
|
19
|
+
const fixes = [];
|
|
20
|
+
const skipped = [];
|
|
21
|
+
for (const f of findings) {
|
|
22
|
+
if (f.severity === "ok") continue;
|
|
23
|
+
switch (f.fixable_via) {
|
|
24
|
+
case "skill-link":
|
|
25
|
+
fixes.push({ check: f.check, action: "skill-link", summary: f.summary });
|
|
26
|
+
break;
|
|
27
|
+
case "mcp-reconcile":
|
|
28
|
+
fixes.push({ check: f.check, action: "mcp-reconcile", summary: f.summary });
|
|
29
|
+
break;
|
|
30
|
+
case "reindex":
|
|
31
|
+
fixes.push({ check: f.check, action: "reindex", summary: f.summary });
|
|
32
|
+
break;
|
|
33
|
+
case "state-migrate":
|
|
34
|
+
fixes.push({ check: f.check, action: "state-migrate", summary: f.summary });
|
|
35
|
+
break;
|
|
36
|
+
case "regenerate-contract":
|
|
37
|
+
skipped.push({ check: f.check, reason: MANUAL_REASON["regenerate-contract"] });
|
|
38
|
+
break;
|
|
39
|
+
default:
|
|
40
|
+
skipped.push({
|
|
41
|
+
check: f.check,
|
|
42
|
+
reason: MANUAL_REASON[f.check] ?? "No automatic fix available \u2014 needs human review."
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return { fixes, skipped };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// src/cli/index.ts
|
|
10
50
|
import { registerUpdateCommands } from "@theglitchking/claude-plugin-runtime";
|
|
11
51
|
|
|
12
52
|
// src/cli/skills.ts
|
|
@@ -287,6 +327,61 @@ function runRelink(cwd) {
|
|
|
287
327
|
stdio: "inherit"
|
|
288
328
|
});
|
|
289
329
|
}
|
|
330
|
+
async function executeFixes(cwd, fixes) {
|
|
331
|
+
const outcomes = [];
|
|
332
|
+
const actions = [...new Set(fixes.map((f) => f.action))];
|
|
333
|
+
for (const action of actions) {
|
|
334
|
+
const checks = fixes.filter((f) => f.action === action).map((f) => f.check).join(", ");
|
|
335
|
+
try {
|
|
336
|
+
switch (action) {
|
|
337
|
+
case "skill-link": {
|
|
338
|
+
runRelink(cwd);
|
|
339
|
+
outcomes.push({ check: checks, action, status: "fixed", detail: "re-linked skills" });
|
|
340
|
+
break;
|
|
341
|
+
}
|
|
342
|
+
case "state-migrate": {
|
|
343
|
+
const r = migrateState({ projectRoot: cwd, force: true });
|
|
344
|
+
outcomes.push({
|
|
345
|
+
check: checks,
|
|
346
|
+
action,
|
|
347
|
+
status: "fixed",
|
|
348
|
+
detail: `migrated ${r.migrated.length} file(s), resolved ${r.conflicts.length} conflict(s)`
|
|
349
|
+
});
|
|
350
|
+
break;
|
|
351
|
+
}
|
|
352
|
+
case "mcp-reconcile": {
|
|
353
|
+
const reconcilePath = join3(findSourceRoot(), "hooks", "reconcile.js");
|
|
354
|
+
if (!existsSync3(reconcilePath)) {
|
|
355
|
+
outcomes.push({ check: checks, action, status: "failed", detail: "reconcile.js not found" });
|
|
356
|
+
break;
|
|
357
|
+
}
|
|
358
|
+
const mod = await import(pathToFileURL(reconcilePath).href);
|
|
359
|
+
mod.reconcile(cwd);
|
|
360
|
+
outcomes.push({ check: checks, action, status: "fixed", detail: "reconciled .mcp.json" });
|
|
361
|
+
break;
|
|
362
|
+
}
|
|
363
|
+
case "reindex": {
|
|
364
|
+
const bin = findLocalBin(cwd);
|
|
365
|
+
if (!bin) {
|
|
366
|
+
outcomes.push({ check: checks, action, status: "failed", detail: "no local bin to run reindex" });
|
|
367
|
+
break;
|
|
368
|
+
}
|
|
369
|
+
const vault = join3(cwd, ".claude", ".vault");
|
|
370
|
+
const r = spawnSync("node", [bin, "--notes", vault, "--reindex"], { cwd, stdio: "pipe", timeout: 12e4 });
|
|
371
|
+
if (r.status === 0) {
|
|
372
|
+
outcomes.push({ check: checks, action, status: "fixed", detail: "reindexed vault" });
|
|
373
|
+
} else {
|
|
374
|
+
outcomes.push({ check: checks, action, status: "failed", detail: (r.stderr?.toString() || "reindex failed").slice(0, 200) });
|
|
375
|
+
}
|
|
376
|
+
break;
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
} catch (err) {
|
|
380
|
+
outcomes.push({ check: checks, action, status: "failed", detail: err?.message ?? String(err) });
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
return outcomes;
|
|
384
|
+
}
|
|
290
385
|
function findLocalBin(cwd) {
|
|
291
386
|
const candidates = [
|
|
292
387
|
join3(cwd, "node_modules", "@theglitchking", "semantic-memory", "bin", "semantic-memory"),
|
|
@@ -526,7 +621,7 @@ program.name("semantic-memory").description(
|
|
|
526
621
|
"Unified memory-layer MCP server for Claude Code (rebrand of semantic-sidekick at v1.0.0).\nThe `semantic-sidekick` command is preserved as an alias.\n\n Start MCP server: semantic-memory --notes ./vault\n Show vault stats: semantic-memory --notes ./vault --stats\n Force reindex: semantic-memory --notes ./vault --reindex\n List MCP tools: semantic-memory tools\n Tool details: semantic-memory tools search_semantic"
|
|
527
622
|
).version(version);
|
|
528
623
|
program.command("search <query>").description("Run a vault search and print top hits as JSON (used by activation hooks)").requiredOption("--notes <path>", "Path to markdown notes directory").option("--limit <n>", "Max results", (v) => parseInt(v, 10), 8).option("--text-only", "Skip embedder \u2014 keyword-only search (fast path, no model init)").option("--json", "Emit raw JSON (default)", true).action(async (query, opts) => {
|
|
529
|
-
const { runSearch } = await import("../search-
|
|
624
|
+
const { runSearch } = await import("../search-AHKEFI2B.js");
|
|
530
625
|
try {
|
|
531
626
|
const hits = await runSearch({
|
|
532
627
|
notes: opts.notes,
|
|
@@ -542,7 +637,7 @@ program.command("search <query>").description("Run a vault search and print top
|
|
|
542
637
|
}
|
|
543
638
|
});
|
|
544
639
|
program.command("lint").description("Lint the vault against vault.schema.yml (schema violations + missing provenance + stale)").requiredOption("--notes <path>", "Path to markdown notes directory").option("--rule <name>", "Limit output to one rule: schema_violations | missing_provenance | stale").option("--json", "Emit JSON instead of the human-readable report").option("--strict", "Exit non-zero on warnings too (default: exit non-zero only on errors)").action(async (opts) => {
|
|
545
|
-
const { lintVault, formatLintReport } = await import("../lint-
|
|
640
|
+
const { lintVault, formatLintReport } = await import("../lint-XUQ7JDYX.js");
|
|
546
641
|
const report = await lintVault(resolve2(opts.notes));
|
|
547
642
|
if (opts.json) {
|
|
548
643
|
const out = opts.rule ? report.byRule[opts.rule] : report;
|
|
@@ -593,7 +688,7 @@ program.command("log-query").description("Read structured log entries from log.m
|
|
|
593
688
|
}
|
|
594
689
|
});
|
|
595
690
|
program.command("install-schema").description("Bootstrap vault.schema.yml in the vault root with the default schema").requiredOption("--notes <path>", "Path to markdown notes directory").option("--force", "Overwrite existing schema file").action(async (opts) => {
|
|
596
|
-
const { installDefaultSchema } = await import("../schema-
|
|
691
|
+
const { installDefaultSchema } = await import("../schema-ATFCLC6Y.js");
|
|
597
692
|
const r = await installDefaultSchema(resolve2(opts.notes), opts.force);
|
|
598
693
|
console.log(r.written ? `Installed default schema: ${r.path}` : `Schema already exists: ${r.path} (use --force to overwrite)`);
|
|
599
694
|
process.exit(0);
|
|
@@ -613,7 +708,7 @@ program.command("serve", { isDefault: true }).description("Start the MCP server
|
|
|
613
708
|
process.exit(1);
|
|
614
709
|
}
|
|
615
710
|
if (opts.stats) {
|
|
616
|
-
const { Indexer } = await import("../indexer-
|
|
711
|
+
const { Indexer } = await import("../indexer-YW4O3VVM.js");
|
|
617
712
|
const indexer = new Indexer(notesPath);
|
|
618
713
|
const docs = await indexer.indexAll();
|
|
619
714
|
console.log(`Notes: ${docs.length}`);
|
|
@@ -722,8 +817,8 @@ ${verify.stderr?.toString() || ""}`);
|
|
|
722
817
|
process.exit(0);
|
|
723
818
|
});
|
|
724
819
|
program.command("healthcheck").description(
|
|
725
|
-
"Verify the local install starts cleanly + run drift detection. Self-heals common npx-cache corruption (ERR_MODULE_NOT_FOUND). With --fast, skips the slow tier (full vault lint)."
|
|
726
|
-
).option("--fast", "Run only the fast-tier drift checks (file-system probes). Skips the slow tier (full vault lint).", false).option("--json", "Emit structured JSON output instead of human-readable text.", false).action(async (opts) => {
|
|
820
|
+
"Verify the local install starts cleanly + run drift detection. Self-heals common npx-cache corruption (ERR_MODULE_NOT_FOUND). With --fast, skips the slow tier (full vault lint). With --fix, auto-applies safe fixes for fixable findings."
|
|
821
|
+
).option("--fast", "Run only the fast-tier drift checks (file-system probes). Skips the slow tier (full vault lint).", false).option("--json", "Emit structured JSON output instead of human-readable text.", false).option("--fix", "Auto-apply safe fixes for fixable drift findings (re-link skills, reconcile .mcp.json, reindex, migrate state). Findings that need human review are reported, not touched.", false).action(async (opts) => {
|
|
727
822
|
const cwd = process.cwd();
|
|
728
823
|
const bin = findLocalBin(cwd);
|
|
729
824
|
if (!bin) {
|
|
@@ -732,85 +827,86 @@ program.command("healthcheck").description(
|
|
|
732
827
|
process.exit(1);
|
|
733
828
|
}
|
|
734
829
|
const mcpPath = join3(cwd, ".mcp.json");
|
|
735
|
-
if (existsSync3(mcpPath)) {
|
|
830
|
+
if (existsSync3(mcpPath) && !opts.json) {
|
|
736
831
|
const data = readJsonSafe(mcpPath);
|
|
737
832
|
const entries = data?.mcpServers && typeof data.mcpServers === "object" ? Object.entries(data.mcpServers) : [];
|
|
738
833
|
const fragile = entries.filter(([, e]) => isNpxForm(e)).map(([k]) => k);
|
|
739
834
|
if (fragile.length > 0) {
|
|
740
|
-
console.warn(
|
|
741
|
-
`\u26A0\uFE0F .mcp.json uses the fragile npx-@latest form for: ${fragile.join(", ")}`
|
|
742
|
-
);
|
|
835
|
+
console.warn(`\u26A0\uFE0F .mcp.json uses the fragile npx-@latest form for: ${fragile.join(", ")}`);
|
|
743
836
|
console.warn(` Rewrite to the stable form:`);
|
|
744
837
|
console.warn(` npx --no @theglitchking/semantic-memory normalize-config`);
|
|
745
838
|
}
|
|
746
839
|
}
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
const match = stderr.match(/([\/~][^'"\s]*\/_npx\/[^\/'"\s]+)/);
|
|
755
|
-
if (match) {
|
|
756
|
-
const bad = match[1];
|
|
757
|
-
console.warn(`detected broken npx cache at ${bad} \u2014 clearing and retrying...`);
|
|
758
|
-
try {
|
|
759
|
-
rmSync(bad, { recursive: true, force: true });
|
|
760
|
-
} catch {
|
|
761
|
-
}
|
|
762
|
-
const r2 = spawnSync("node", [bin, "--version"], { cwd, stdio: "pipe", timeout: 15e3 });
|
|
763
|
-
if (r2.status === 0) {
|
|
764
|
-
console.log(`\u2713 cleared npx cache and verified (v${r2.stdout?.toString().trim()})`);
|
|
765
|
-
process.exit(0);
|
|
766
|
-
}
|
|
767
|
-
console.error(`retry still failed:
|
|
768
|
-
${r2.stderr?.toString() || ""}`);
|
|
840
|
+
let smokeOk = false;
|
|
841
|
+
let smokeVersion = "";
|
|
842
|
+
{
|
|
843
|
+
const r = spawnSync("node", [bin, "--version"], { cwd, stdio: "pipe", timeout: 15e3 });
|
|
844
|
+
if (r.status === 0) {
|
|
845
|
+
smokeOk = true;
|
|
846
|
+
smokeVersion = r.stdout?.toString().trim() ?? "";
|
|
769
847
|
} else {
|
|
770
|
-
|
|
848
|
+
const stderr = r.stderr?.toString() ?? "";
|
|
849
|
+
if (stderr.includes("ERR_MODULE_NOT_FOUND")) {
|
|
850
|
+
const match = stderr.match(/([\/~][^'"\s]*\/_npx\/[^\/'"\s]+)/);
|
|
851
|
+
if (match) {
|
|
852
|
+
const bad = match[1];
|
|
853
|
+
if (!opts.json) console.warn(`detected broken npx cache at ${bad} \u2014 clearing and retrying...`);
|
|
854
|
+
try {
|
|
855
|
+
rmSync(bad, { recursive: true, force: true });
|
|
856
|
+
} catch {
|
|
857
|
+
}
|
|
858
|
+
const r2 = spawnSync("node", [bin, "--version"], { cwd, stdio: "pipe", timeout: 15e3 });
|
|
859
|
+
if (r2.status === 0) {
|
|
860
|
+
smokeOk = true;
|
|
861
|
+
smokeVersion = r2.stdout?.toString().trim() ?? "";
|
|
862
|
+
} else if (!opts.json) {
|
|
863
|
+
console.error(`retry still failed:
|
|
864
|
+
${r2.stderr?.toString() || ""}`);
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
if (!smokeOk && !opts.json && stderr) console.error(stderr);
|
|
771
869
|
}
|
|
772
870
|
}
|
|
773
|
-
if (
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
871
|
+
if (smokeOk && !opts.json) console.log(`\u2713 local install starts cleanly (v${smokeVersion})`);
|
|
872
|
+
const { runHealthcheck, formatDriftBanner, filterToDrift } = await import("../healthcheck-IMB47LZE.js");
|
|
873
|
+
const vaultCandidate = join3(cwd, ".claude", ".vault");
|
|
874
|
+
const vaultPath = existsSync3(vaultCandidate) ? vaultCandidate : void 0;
|
|
875
|
+
let result = await runHealthcheck({ projectRoot: cwd, vaultPath, tier: opts.fast ? "fast" : "all", force: true });
|
|
876
|
+
let fixOutcomes = [];
|
|
877
|
+
let plan = { fixes: [], skipped: [] };
|
|
878
|
+
if (opts.fix) {
|
|
879
|
+
plan = planFixes(filterToDrift(result));
|
|
880
|
+
if (plan.fixes.length > 0) {
|
|
881
|
+
fixOutcomes = await executeFixes(cwd, plan.fixes);
|
|
882
|
+
result = await runHealthcheck({ projectRoot: cwd, vaultPath, tier: opts.fast ? "fast" : "all", force: true });
|
|
883
|
+
}
|
|
777
884
|
}
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
if (opts.json) {
|
|
792
|
-
console.log(JSON.stringify(result, null, 2));
|
|
793
|
-
return;
|
|
885
|
+
if (opts.json) {
|
|
886
|
+
console.log(JSON.stringify({ smoke: { ok: smokeOk, version: smokeVersion }, result, fix: opts.fix ? { plan, outcomes: fixOutcomes } : void 0 }, null, 2));
|
|
887
|
+
} else {
|
|
888
|
+
if (opts.fix) {
|
|
889
|
+
if (fixOutcomes.length === 0 && plan.skipped.length === 0) {
|
|
890
|
+
console.log(`
|
|
891
|
+
\u2713 nothing to fix`);
|
|
892
|
+
} else {
|
|
893
|
+
console.log(`
|
|
894
|
+
--fix applied ${fixOutcomes.filter((o) => o.status === "fixed").length}/${fixOutcomes.length} action(s):`);
|
|
895
|
+
for (const o of fixOutcomes) console.log(` ${o.status === "fixed" ? "\u2713" : "\u2717"} ${o.action} (${o.check}) \u2014 ${o.detail}`);
|
|
896
|
+
for (const s of plan.skipped) console.log(` \u2022 skipped ${s.check} \u2014 ${s.reason}`);
|
|
897
|
+
}
|
|
794
898
|
}
|
|
795
899
|
const banner = formatDriftBanner(result);
|
|
796
900
|
if (banner) {
|
|
797
901
|
console.log("");
|
|
798
902
|
console.log(banner);
|
|
799
903
|
} else {
|
|
800
|
-
console.log(
|
|
801
|
-
|
|
904
|
+
console.log(`
|
|
905
|
+
\u2713 no drift detected (${result.findings.length} checks ran in ${result.duration_ms}ms)`);
|
|
802
906
|
}
|
|
803
|
-
} catch (err) {
|
|
804
|
-
console.error(`drift check threw: ${err?.message ?? err}`);
|
|
805
907
|
}
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
if (healthcheckCmd) {
|
|
809
|
-
healthcheckCmd.hook("postAction", async (thisCmd) => {
|
|
810
|
-
const opts = thisCmd.opts();
|
|
811
|
-
await driftHealthcheckActionPostprocess({ fast: !!opts.fast, json: !!opts.json });
|
|
812
|
-
});
|
|
813
|
-
}
|
|
908
|
+
process.exit(smokeOk ? 0 : 1);
|
|
909
|
+
});
|
|
814
910
|
function parseAgent(input) {
|
|
815
911
|
const a = input.toLowerCase();
|
|
816
912
|
if (!SKILL_BUNDLER_AGENTS.includes(a)) {
|
|
@@ -899,5 +995,109 @@ ${result.conflicts.length} conflict${result.conflicts.length === 1 ? "" : "s"} d
|
|
|
899
995
|
process.exit(1);
|
|
900
996
|
}
|
|
901
997
|
});
|
|
998
|
+
program.command("decay-config").description("Print the active confidence-decay config (shipped defaults + any vault.schema.yml override).").requiredOption("--notes <path>", "Path to markdown notes directory").action(async (opts) => {
|
|
999
|
+
const { loadDecayConfig, DEFAULT_DECAY_CONFIG } = await import("../decay-ELJUKVQG.js");
|
|
1000
|
+
const cfg = loadDecayConfig(resolve2(opts.notes));
|
|
1001
|
+
const source = JSON.stringify(cfg) === JSON.stringify(DEFAULT_DECAY_CONFIG) ? "defaults" : "vault.schema.yml (overridden)";
|
|
1002
|
+
console.log(JSON.stringify({ source, config: cfg }, null, 2));
|
|
1003
|
+
process.exit(0);
|
|
1004
|
+
});
|
|
1005
|
+
program.command("decay-trace <notePath>").description("Show the decay calculation for one note: type, last_verified, age, half-life, evergreen, multiplier.").requiredOption("--notes <path>", "Path to markdown notes directory").action(async (notePath, opts) => {
|
|
1006
|
+
const { loadDecayConfig, computeDecay, normalizeVerifiedDate } = await import("../decay-ELJUKVQG.js");
|
|
1007
|
+
const matter = (await import("gray-matter")).default;
|
|
1008
|
+
const abs = resolve2(opts.notes, notePath);
|
|
1009
|
+
if (!existsSync3(abs)) {
|
|
1010
|
+
console.error(`note not found: ${abs}`);
|
|
1011
|
+
process.exit(1);
|
|
1012
|
+
}
|
|
1013
|
+
const { data: fm } = matter(readFileSync(abs, "utf8"));
|
|
1014
|
+
const lastVerified = normalizeVerifiedDate(fm.last_verified);
|
|
1015
|
+
const d = computeDecay({
|
|
1016
|
+
type: typeof fm.type === "string" ? fm.type : void 0,
|
|
1017
|
+
last_verified: lastVerified,
|
|
1018
|
+
evergreen: fm.evergreen === true,
|
|
1019
|
+
config: loadDecayConfig(resolve2(opts.notes))
|
|
1020
|
+
});
|
|
1021
|
+
console.log(
|
|
1022
|
+
JSON.stringify(
|
|
1023
|
+
{
|
|
1024
|
+
path: notePath,
|
|
1025
|
+
type: fm.type ?? null,
|
|
1026
|
+
last_verified: lastVerified ?? null,
|
|
1027
|
+
evergreen: fm.evergreen === true,
|
|
1028
|
+
multiplier: d.multiplier,
|
|
1029
|
+
age_days: Math.round(d.age_days),
|
|
1030
|
+
effective_half_life: d.effective_half_life,
|
|
1031
|
+
reason: d.reason
|
|
1032
|
+
},
|
|
1033
|
+
null,
|
|
1034
|
+
2
|
|
1035
|
+
)
|
|
1036
|
+
);
|
|
1037
|
+
process.exit(0);
|
|
1038
|
+
});
|
|
1039
|
+
var lexiconCmd = program.command("lexicon").description("Manage the learned human\u2192artifact lexicon (aliases).");
|
|
1040
|
+
lexiconCmd.command("list").description("List all aliases in the lexicon.").requiredOption("--notes <path>", "Path to markdown notes directory").action(async (opts) => {
|
|
1041
|
+
const { loadLexiconCache } = await import("../lexicon-5PXQEMUF.js");
|
|
1042
|
+
console.log(JSON.stringify(await loadLexiconCache(resolve2(opts.notes)), null, 2));
|
|
1043
|
+
process.exit(0);
|
|
1044
|
+
});
|
|
1045
|
+
lexiconCmd.command("compile").description("Rebuild the derived lexicon cache from the lexicon/ notes.").requiredOption("--notes <path>", "Path to markdown notes directory").action(async (opts) => {
|
|
1046
|
+
const { compileLexicon } = await import("../lexicon-5PXQEMUF.js");
|
|
1047
|
+
const entries = await compileLexicon(resolve2(opts.notes));
|
|
1048
|
+
console.log(`compiled ${entries.length} alias(es)`);
|
|
1049
|
+
process.exit(0);
|
|
1050
|
+
});
|
|
1051
|
+
lexiconCmd.command("add <canonical> <phrases...>").description("Upsert an alias: a canonical target and the human phrases that refer to it.").requiredOption("--notes <path>", "Path to markdown notes directory").option("--authored", "Mark as human-authored (default: learned)").action(async (canonical, phrases, opts) => {
|
|
1052
|
+
const { addAlias } = await import("../lexicon-5PXQEMUF.js");
|
|
1053
|
+
const r = await addAlias(resolve2(opts.notes), { canonical, phrases, source: opts.authored ? "authored" : "learned" });
|
|
1054
|
+
console.log(JSON.stringify(r, null, 2));
|
|
1055
|
+
process.exit(0);
|
|
1056
|
+
});
|
|
1057
|
+
var dossierCmd = program.command("dossier").description("Manage entity dossiers \u2014 per-component living notes (purpose / failure modes / knobs / incident log / current state).");
|
|
1058
|
+
dossierCmd.command("init <entity>").description("Scaffold a dossier for an entity (no-op if one already exists). Optionally seed aliases and provenance.").requiredOption("--notes <path>", "Path to markdown notes directory").option("--alias <phrase...>", "Human phrase(s) for this entity \u2014 fed to the lexicon compiler").option("--seeded-from <ref>", "Provenance of the scaffold (e.g. a babel-fish project-map entry)").action(async (entity, opts) => {
|
|
1059
|
+
const { initDossier } = await import("../dossier-2UG724LB.js");
|
|
1060
|
+
const r = await initDossier(resolve2(opts.notes), entity, { aliases: opts.alias, seeded_from: opts.seededFrom });
|
|
1061
|
+
console.log(JSON.stringify(r, null, 2));
|
|
1062
|
+
process.exit(0);
|
|
1063
|
+
});
|
|
1064
|
+
dossierCmd.command("list").description("List all dossiers with their entity, aliases, and current state.").requiredOption("--notes <path>", "Path to markdown notes directory").action(async (opts) => {
|
|
1065
|
+
const { listDossiers } = await import("../dossier-2UG724LB.js");
|
|
1066
|
+
console.log(JSON.stringify(await listDossiers(resolve2(opts.notes)), null, 2));
|
|
1067
|
+
process.exit(0);
|
|
1068
|
+
});
|
|
1069
|
+
var profileCmd = program.command("profile").description("Manage the speaker profile \u2014 how THIS human communicates (severity calibration, chronic omissions, verbosity, shorthand).");
|
|
1070
|
+
profileCmd.command("init").description("Scaffold profile/speaker.md with the fixed sections (no-op if it exists).").requiredOption("--notes <path>", "Path to markdown notes directory").action(async (opts) => {
|
|
1071
|
+
const { initSpeakerProfile } = await import("../profile-LXUEF7TX.js");
|
|
1072
|
+
const r = await initSpeakerProfile(resolve2(opts.notes));
|
|
1073
|
+
console.log(JSON.stringify(r, null, 2));
|
|
1074
|
+
process.exit(0);
|
|
1075
|
+
});
|
|
1076
|
+
profileCmd.command("show").description("Print the speaker profile's injection head (the capped, placeholder-stripped view).").requiredOption("--notes <path>", "Path to markdown notes directory").action(async (opts) => {
|
|
1077
|
+
const { readSpeakerProfile } = await import("../profile-LXUEF7TX.js");
|
|
1078
|
+
const p = await readSpeakerProfile(resolve2(opts.notes));
|
|
1079
|
+
console.log(p ? p.head || "(profile is empty \u2014 only placeholders)" : "(no speaker profile \u2014 run `profile init`)");
|
|
1080
|
+
process.exit(0);
|
|
1081
|
+
});
|
|
1082
|
+
program.command("selection-stats").description("Summarize the local selection log: searches, selections, most-cited notes, and retrieved-but-never-cited notes.").requiredOption("--notes <path>", "Path to markdown notes directory").option("--json", "Emit raw JSON instead of a human summary").action(async (opts) => {
|
|
1083
|
+
const { computeSelectionStats, selectionLogPath } = await import("../telemetry-GB2TEHVE.js");
|
|
1084
|
+
const stats = await computeSelectionStats(resolve2(opts.notes));
|
|
1085
|
+
if (opts.json) {
|
|
1086
|
+
console.log(JSON.stringify(stats, null, 2));
|
|
1087
|
+
process.exit(0);
|
|
1088
|
+
}
|
|
1089
|
+
console.log(`Selection log: ${selectionLogPath(resolve2(opts.notes))}`);
|
|
1090
|
+
console.log(` searches: ${stats.searches}`);
|
|
1091
|
+
console.log(` selections: ${stats.selections}`);
|
|
1092
|
+
const topCited = Object.entries(stats.citedPaths).sort((a, b) => b[1] - a[1]).slice(0, 10);
|
|
1093
|
+
if (topCited.length) {
|
|
1094
|
+
console.log(` most cited:`);
|
|
1095
|
+
for (const [p, n] of topCited) console.log(` ${n}\xD7 ${p}`);
|
|
1096
|
+
}
|
|
1097
|
+
if (stats.retrievedNeverCited.length) {
|
|
1098
|
+
console.log(` retrieved but never cited (${stats.retrievedNeverCited.length}): ${stats.retrievedNeverCited.slice(0, 10).join(", ")}${stats.retrievedNeverCited.length > 10 ? " \u2026" : ""}`);
|
|
1099
|
+
}
|
|
1100
|
+
process.exit(0);
|
|
1101
|
+
});
|
|
902
1102
|
program.parse();
|
|
903
1103
|
//# sourceMappingURL=index.js.map
|