imprnt 0.1.4-edge.88 → 0.1.4-edge.89
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.md +14 -1
- package/dist/cli.js +137 -67
- package/dist/imp.js +137 -67
- package/package.json +1 -1
package/CLAUDE.md
CHANGED
|
@@ -94,7 +94,20 @@ vault/
|
|
|
94
94
|
|
|
95
95
|
**holdings/ vs reference: the cut is CHANGING STATE, not the word "tool."** Anything you follow over time is a holding: a premium, a dose, a balance, a status, a renewal. A paid subscription with a cost/renewal (a transit pass) is a holding even if you'd call it a "service." Static stuff with no state to track is **not** a holding: a free CLI, your dotfiles, tech-stack preferences are pure reference → file them in their domain (`work/`, `health/`). This cut is what keeps `holdings/` a real tracked-entity type instead of drifting back into a `things/` junk drawer.
|
|
96
96
|
|
|
97
|
-
**Domains are user-defined.** One person's set is `identity/ health/ finances/ work/ life/`. A consultant's would add `clients/`, a researcher's `topics/`. imprnt ships the mechanism + sensible defaults, not a fixed domain set
|
|
97
|
+
**Domains are user-defined, and the vault declares them.** One person's set is `identity/ health/ finances/ work/ life/`. A consultant's would add `clients/`, a researcher's `topics/`. imprnt ships the mechanism + sensible defaults, not a fixed domain set — `vault/_folders.md` is where a vault says which of its folders hold **entities**, which hold **domains**, which hold **forms**, and which hold a **mount**. No file means the shipped defaults, so nothing changes until you want it to.
|
|
98
|
+
|
|
99
|
+
```markdown
|
|
100
|
+
## Entities
|
|
101
|
+
people, orgs, holdings
|
|
102
|
+
|
|
103
|
+
## Domains
|
|
104
|
+
identity, health, finances, work, life, clients
|
|
105
|
+
|
|
106
|
+
## Mounts
|
|
107
|
+
household
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
A **mount** is the fourth role and the one the defaults have no name for: a folder holding a tree that is complete on its own and maintained elsewhere — a shared repo checked out inside `vault/`, an imported corpus. Its notes are not part of this vault's entity graph, so `check` does not ask them to link one. Without that, every note under a folder the defaults never heard of is reported disconnected forever with nothing the owner can do, and permanent noise in `_needs-review.md` is worse than no check at all. An absent section keeps its default; an empty one is a deliberate "none". `type:` in frontmatter (below) records *what each note is* even when it sits in a domain folder, so nothing is lost by filing topically.
|
|
98
111
|
|
|
99
112
|
## Frontmatter contract
|
|
100
113
|
|
package/dist/cli.js
CHANGED
|
@@ -2454,11 +2454,72 @@ var init_snapshot = __esm(() => {
|
|
|
2454
2454
|
console.log(` next: the LLM reads raw/${dest}/ and fans sources out into vault notes (source: raw/${dest}/...).`);
|
|
2455
2455
|
});
|
|
2456
2456
|
|
|
2457
|
+
// scripts/lib/folders.ts
|
|
2458
|
+
import { existsSync as existsSync12, readFileSync as readFileSync13 } from "node:fs";
|
|
2459
|
+
import { join as join14 } from "node:path";
|
|
2460
|
+
function section2(text2, name) {
|
|
2461
|
+
return text2.match(new RegExp(`##\\s*${name}\\s*\\n([\\s\\S]*?)(?:\\n##\\s|\\s*$)`, "i"))?.[1] ?? "";
|
|
2462
|
+
}
|
|
2463
|
+
function folderTokens(line) {
|
|
2464
|
+
const t = line.trim();
|
|
2465
|
+
if (t === "" || t.startsWith("#") || t.startsWith("<!--") || t.startsWith(">"))
|
|
2466
|
+
return [];
|
|
2467
|
+
return t.replace(/^[-*]\s+/, "").split(",").map((s) => s.trim().normalize("NFC").toLowerCase()).filter((s) => FOLDER_TOKEN.test(s));
|
|
2468
|
+
}
|
|
2469
|
+
function read(text2, name, fallback) {
|
|
2470
|
+
const found = [];
|
|
2471
|
+
for (const line of section2(text2, name).split(/\r?\n/))
|
|
2472
|
+
found.push(...folderTokens(line));
|
|
2473
|
+
return new RegExp(`##\\s*${name}\\s*\\n`, "i").test(text2) ? new Set(found) : new Set(fallback);
|
|
2474
|
+
}
|
|
2475
|
+
function loadFolders(vault4) {
|
|
2476
|
+
const p = join14(vault4, "_folders.md");
|
|
2477
|
+
if (!existsSync12(p)) {
|
|
2478
|
+
return {
|
|
2479
|
+
entities: new Set(DEFAULT_ENTITIES),
|
|
2480
|
+
domains: new Set(DEFAULT_DOMAINS),
|
|
2481
|
+
forms: new Set(DEFAULT_FORMS),
|
|
2482
|
+
mounts: new Set,
|
|
2483
|
+
declared: false
|
|
2484
|
+
};
|
|
2485
|
+
}
|
|
2486
|
+
let text2 = "";
|
|
2487
|
+
try {
|
|
2488
|
+
text2 = readFileSync13(p, "utf8");
|
|
2489
|
+
} catch {
|
|
2490
|
+
return { entities: new Set(DEFAULT_ENTITIES), domains: new Set(DEFAULT_DOMAINS), forms: new Set(DEFAULT_FORMS), mounts: new Set, declared: false };
|
|
2491
|
+
}
|
|
2492
|
+
const roles = {
|
|
2493
|
+
entities: read(text2, "Entities", DEFAULT_ENTITIES),
|
|
2494
|
+
domains: read(text2, "Domains", DEFAULT_DOMAINS),
|
|
2495
|
+
forms: read(text2, "Forms", DEFAULT_FORMS),
|
|
2496
|
+
mounts: read(text2, "Mounts", []),
|
|
2497
|
+
declared: true
|
|
2498
|
+
};
|
|
2499
|
+
for (const f of roles.entities) {
|
|
2500
|
+
roles.domains.delete(f);
|
|
2501
|
+
roles.forms.delete(f);
|
|
2502
|
+
roles.mounts.delete(f);
|
|
2503
|
+
}
|
|
2504
|
+
for (const f of roles.mounts) {
|
|
2505
|
+
roles.domains.delete(f);
|
|
2506
|
+
roles.forms.delete(f);
|
|
2507
|
+
}
|
|
2508
|
+
return roles;
|
|
2509
|
+
}
|
|
2510
|
+
var DEFAULT_ENTITIES, DEFAULT_DOMAINS, DEFAULT_FORMS, FOLDER_TOKEN;
|
|
2511
|
+
var init_folders = __esm(() => {
|
|
2512
|
+
DEFAULT_ENTITIES = ["people", "orgs", "holdings"];
|
|
2513
|
+
DEFAULT_DOMAINS = ["identity", "health", "finances", "work", "life"];
|
|
2514
|
+
DEFAULT_FORMS = ["events", "mistakes", "projects"];
|
|
2515
|
+
FOLDER_TOKEN = /^[\p{L}\p{N}_-]+$/u;
|
|
2516
|
+
});
|
|
2517
|
+
|
|
2457
2518
|
// scripts/check.ts
|
|
2458
2519
|
var exports_check = {};
|
|
2459
|
-
import { readdirSync as readdirSync8, readFileSync as
|
|
2520
|
+
import { readdirSync as readdirSync8, readFileSync as readFileSync14, statSync as statSync8, existsSync as existsSync13, writeFileSync as writeFileSync10 } from "node:fs";
|
|
2460
2521
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
2461
|
-
import { join as
|
|
2522
|
+
import { join as join15, relative as relative6, dirname as dirname3 } from "node:path";
|
|
2462
2523
|
import { homedir as homedir3 } from "node:os";
|
|
2463
2524
|
function resolves(target) {
|
|
2464
2525
|
const t = target.trim().replace(/^\.\//, "").replace(/\.md$/, "");
|
|
@@ -2485,9 +2546,9 @@ function hostMemoryStores() {
|
|
|
2485
2546
|
const override = process.env.IMPRNT_HOST_MEMORY_DIR;
|
|
2486
2547
|
if (override)
|
|
2487
2548
|
return [override];
|
|
2488
|
-
const configDir = process.env.CLAUDE_CONFIG_DIR ||
|
|
2489
|
-
const projectsDir =
|
|
2490
|
-
if (!
|
|
2549
|
+
const configDir = process.env.CLAUDE_CONFIG_DIR || join15(homedir3(), ".claude");
|
|
2550
|
+
const projectsDir = join15(configDir, "projects");
|
|
2551
|
+
if (!existsSync13(projectsDir))
|
|
2491
2552
|
return [];
|
|
2492
2553
|
let entries;
|
|
2493
2554
|
try {
|
|
@@ -2495,7 +2556,7 @@ function hostMemoryStores() {
|
|
|
2495
2556
|
} catch {
|
|
2496
2557
|
return [];
|
|
2497
2558
|
}
|
|
2498
|
-
return entries.map((p) =>
|
|
2559
|
+
return entries.map((p) => join15(projectsDir, p, "memory")).filter((d) => {
|
|
2499
2560
|
try {
|
|
2500
2561
|
return statSync8(d).isDirectory();
|
|
2501
2562
|
} catch {
|
|
@@ -2505,17 +2566,17 @@ function hostMemoryStores() {
|
|
|
2505
2566
|
}
|
|
2506
2567
|
function memoryIndexHasContent(dir2) {
|
|
2507
2568
|
try {
|
|
2508
|
-
return
|
|
2569
|
+
return readFileSync14(join15(dir2, "MEMORY.md"), "utf8").split(/\r?\n/).some((l) => l.trim() !== "" && l.trim() !== "# Memory index");
|
|
2509
2570
|
} catch {
|
|
2510
2571
|
return false;
|
|
2511
2572
|
}
|
|
2512
2573
|
}
|
|
2513
2574
|
function syncNeedsReview(lines2) {
|
|
2514
|
-
const p =
|
|
2515
|
-
const exists =
|
|
2575
|
+
const p = join15(vault4, "_needs-review.md");
|
|
2576
|
+
const exists = existsSync13(p);
|
|
2516
2577
|
if (!exists && lines2.length === 0)
|
|
2517
2578
|
return "none";
|
|
2518
|
-
const prev = exists ?
|
|
2579
|
+
const prev = exists ? readFileSync14(p, "utf8") : `---
|
|
2519
2580
|
type: needs-review
|
|
2520
2581
|
---
|
|
2521
2582
|
|
|
@@ -2524,7 +2585,7 @@ type: needs-review
|
|
|
2524
2585
|
`;
|
|
2525
2586
|
const b = prev.indexOf(REVIEW_BEGIN);
|
|
2526
2587
|
const e = b !== -1 ? prev.indexOf(REVIEW_END, b + REVIEW_BEGIN.length) : -1;
|
|
2527
|
-
const
|
|
2588
|
+
const section3 = `${REVIEW_BEGIN}
|
|
2528
2589
|
${lines2.join(`
|
|
2529
2590
|
`)}
|
|
2530
2591
|
${REVIEW_END}
|
|
@@ -2538,22 +2599,23 @@ ${REVIEW_END}
|
|
|
2538
2599
|
} else {
|
|
2539
2600
|
after = prev.slice(b + REVIEW_BEGIN.length).replace(/^\n/, "");
|
|
2540
2601
|
}
|
|
2541
|
-
next = before + (lines2.length ?
|
|
2602
|
+
next = before + (lines2.length ? section3 : "") + after;
|
|
2542
2603
|
} else {
|
|
2543
2604
|
if (lines2.length === 0)
|
|
2544
2605
|
return "none";
|
|
2545
2606
|
next = (prev.endsWith(`
|
|
2546
2607
|
`) ? prev : prev + `
|
|
2547
|
-
`) +
|
|
2608
|
+
`) + section3;
|
|
2548
2609
|
}
|
|
2549
2610
|
if (next !== prev || !exists)
|
|
2550
2611
|
writeFileSync10(p, next);
|
|
2551
2612
|
return lines2.length ? "written" : "cleared";
|
|
2552
2613
|
}
|
|
2553
|
-
var args4, vault4, all = false, ENTITY_FOLDERS, DOMAIN_FOLDERS2, LINK, notes, allSlugs, folderOf, byBasename, orphans, disconnected, domainIssues, untagged, review, referencedRaw, tagVocab, hasRealTag = (tags) => tags.some((t) => /[\p{L}\p{N}]/u.test(normalize(tagVocab, t))), hasTagsFile, addedTags, dupPairs, manifest3, rawEntries, norm = (p) => p.replace(/^\.\//, "").replace(/^.*\/raw\//, "raw/").replace(/\.md$/, ""), refNorm, uncovered, memoryStores, strayStores, strayCount, REVIEW_BEGIN = "<!-- imprnt-check:begin (regenerated by `imprnt check` - do not edit between the markers) -->", REVIEW_END = "<!-- imprnt-check:end -->", cap = (xs, n = 25) => xs.slice(0, n).concat(xs.length > n ? [` … +${xs.length - n} more`] : []), count, folders, synced, issues;
|
|
2614
|
+
var args4, vault4, all = false, roles, ENTITY_FOLDERS, DOMAIN_FOLDERS2, MOUNT_FOLDERS, LINK, notes, allSlugs, folderOf, byBasename, orphans, disconnected, domainIssues, untagged, review, referencedRaw, tagVocab, hasRealTag = (tags) => tags.some((t) => /[\p{L}\p{N}]/u.test(normalize(tagVocab, t))), hasTagsFile, addedTags, dupPairs, manifest3, rawEntries, norm = (p) => p.replace(/^\.\//, "").replace(/^.*\/raw\//, "raw/").replace(/\.md$/, ""), refNorm, uncovered, memoryStores, strayStores, strayCount, REVIEW_BEGIN = "<!-- imprnt-check:begin (regenerated by `imprnt check` - do not edit between the markers) -->", REVIEW_END = "<!-- imprnt-check:end -->", cap = (xs, n = 25) => xs.slice(0, n).concat(xs.length > n ? [` … +${xs.length - n} more`] : []), count, folders, synced, issues;
|
|
2554
2615
|
var init_check = __esm(() => {
|
|
2555
2616
|
init_roots();
|
|
2556
2617
|
init_moc();
|
|
2618
|
+
init_folders();
|
|
2557
2619
|
init_tags();
|
|
2558
2620
|
init_manifest();
|
|
2559
2621
|
args4 = process.argv.slice(2);
|
|
@@ -2569,12 +2631,14 @@ var init_check = __esm(() => {
|
|
|
2569
2631
|
} else if (args4[i] === "--all")
|
|
2570
2632
|
all = true;
|
|
2571
2633
|
}
|
|
2572
|
-
if (!
|
|
2634
|
+
if (!existsSync13(vault4)) {
|
|
2573
2635
|
console.error(`no vault at ${vault4} — run \`imprnt init\` first`);
|
|
2574
2636
|
process.exit(1);
|
|
2575
2637
|
}
|
|
2576
|
-
|
|
2577
|
-
|
|
2638
|
+
roles = loadFolders(vault4);
|
|
2639
|
+
ENTITY_FOLDERS = roles.entities;
|
|
2640
|
+
DOMAIN_FOLDERS2 = roles.domains;
|
|
2641
|
+
MOUNT_FOLDERS = roles.mounts;
|
|
2578
2642
|
LINK = /\[\[([^\]|#]+)(?:#[^\]|]+)?(?:\|[^\]]+)?\]\]/g;
|
|
2579
2643
|
notes = collectNotes(vault4);
|
|
2580
2644
|
allSlugs = new Set(notes.map((n) => n.slug));
|
|
@@ -2592,7 +2656,7 @@ var init_check = __esm(() => {
|
|
|
2592
2656
|
referencedRaw = new Set;
|
|
2593
2657
|
tagVocab = loadTags(vault4);
|
|
2594
2658
|
for (const n of notes) {
|
|
2595
|
-
const raw =
|
|
2659
|
+
const raw = readFileSync14(n.path, "utf8");
|
|
2596
2660
|
const fm2 = frontmatter(raw);
|
|
2597
2661
|
const links = [...stripCode(raw).matchAll(LINK)].map((m) => m[1].trim()).filter((l) => !l.startsWith("raw/"));
|
|
2598
2662
|
for (const l of links)
|
|
@@ -2600,7 +2664,7 @@ var init_check = __esm(() => {
|
|
|
2600
2664
|
orphans.push(` ${n.slug} → [[${l}]]`);
|
|
2601
2665
|
review.push(`- [ ] orphan link [[${l}]] — from [[${n.slug}]], target note missing`);
|
|
2602
2666
|
}
|
|
2603
|
-
if (!ENTITY_FOLDERS.has(n.folder) && !links.some(linksEntity)) {
|
|
2667
|
+
if (!ENTITY_FOLDERS.has(n.folder) && !MOUNT_FOLDERS.has(n.folder) && !links.some(linksEntity)) {
|
|
2604
2668
|
disconnected.push(` ${n.slug}`);
|
|
2605
2669
|
review.push(`- [ ] disconnected note [[${n.slug}]] — links no entity`);
|
|
2606
2670
|
}
|
|
@@ -2620,7 +2684,7 @@ var init_check = __esm(() => {
|
|
|
2620
2684
|
for (const s of fmList(fm2, "sources"))
|
|
2621
2685
|
referencedRaw.add(s.replace(/^\[\[/, "").replace(/\]\]$/, "").replace(/^\.\//, ""));
|
|
2622
2686
|
}
|
|
2623
|
-
hasTagsFile =
|
|
2687
|
+
hasTagsFile = existsSync13(join15(vault4, "_tags.md"));
|
|
2624
2688
|
addedTags = [];
|
|
2625
2689
|
dupPairs = [];
|
|
2626
2690
|
if (hasTagsFile) {
|
|
@@ -2692,7 +2756,7 @@ var init_check = __esm(() => {
|
|
|
2692
2756
|
strayStores = memoryStores.map((dir2) => {
|
|
2693
2757
|
let files3 = [];
|
|
2694
2758
|
try {
|
|
2695
|
-
if (
|
|
2759
|
+
if (existsSync13(dir2))
|
|
2696
2760
|
files3 = readdirSync8(dir2).filter((f) => f.endsWith(".md") && f !== "MEMORY.md").sort();
|
|
2697
2761
|
} catch (e) {
|
|
2698
2762
|
console.error(`⚠ host auto-memory sweep: could not read ${dir2} (${e instanceof Error ? e.message : String(e)}) - skipping it`);
|
|
@@ -2704,8 +2768,14 @@ var init_check = __esm(() => {
|
|
|
2704
2768
|
strayCount = strayStores.reduce((n, s) => n + s.files.length, 0);
|
|
2705
2769
|
for (const s of strayStores)
|
|
2706
2770
|
review.push(`- [ ] host auto-memory not empty — ${s.files.length} note(s) in ${s.dir}; migrate knowledge → vault notes, behavior → a CLAUDE.local.md fragment, then empty it`);
|
|
2707
|
-
console.log(`imprnt check — ${notes.length} notes in ${vault4}
|
|
2708
|
-
|
|
2771
|
+
console.log(`imprnt check — ${notes.length} notes in ${vault4}`);
|
|
2772
|
+
if (roles.declared) {
|
|
2773
|
+
const parts = [`entities: ${[...ENTITY_FOLDERS].join(" ") || "(none)"}`, `domains: ${[...DOMAIN_FOLDERS2].join(" ") || "(none)"}`];
|
|
2774
|
+
if (MOUNT_FOLDERS.size)
|
|
2775
|
+
parts.push(`mounts: ${[...MOUNT_FOLDERS].join(" ")}`);
|
|
2776
|
+
console.log(`folder roles from _folders.md — ${parts.join(", ")}`);
|
|
2777
|
+
}
|
|
2778
|
+
console.log("");
|
|
2709
2779
|
if (orphans.length) {
|
|
2710
2780
|
console.log(`⚠ orphan links (${orphans.length}) — target note missing:`);
|
|
2711
2781
|
console.log(cap(orphans).join(`
|
|
@@ -2778,18 +2848,18 @@ var init_check = __esm(() => {
|
|
|
2778
2848
|
${issues} thing(s) to look at above.` : `
|
|
2779
2849
|
clean.`);
|
|
2780
2850
|
if (all) {
|
|
2781
|
-
const pluginsDir =
|
|
2851
|
+
const pluginsDir = join15(projectRoot(), "plugins");
|
|
2782
2852
|
const checks = [];
|
|
2783
|
-
if (
|
|
2853
|
+
if (existsSync13(pluginsDir)) {
|
|
2784
2854
|
for (const entry of readdirSync8(pluginsDir)) {
|
|
2785
2855
|
let isDir2 = false;
|
|
2786
2856
|
try {
|
|
2787
|
-
isDir2 = statSync8(
|
|
2857
|
+
isDir2 = statSync8(join15(pluginsDir, entry)).isDirectory();
|
|
2788
2858
|
} catch {
|
|
2789
2859
|
continue;
|
|
2790
2860
|
}
|
|
2791
|
-
const p =
|
|
2792
|
-
if (isDir2 &&
|
|
2861
|
+
const p = join15(pluginsDir, entry, "check.js");
|
|
2862
|
+
if (isDir2 && existsSync13(p))
|
|
2793
2863
|
checks.push(p);
|
|
2794
2864
|
}
|
|
2795
2865
|
}
|
|
@@ -2824,12 +2894,12 @@ all plugin checks passed.`);
|
|
|
2824
2894
|
// scripts/vault.ts
|
|
2825
2895
|
var exports_vault = {};
|
|
2826
2896
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
2827
|
-
import { existsSync as
|
|
2897
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync5, readdirSync as readdirSync9, statSync as statSync9 } from "node:fs";
|
|
2828
2898
|
import { homedir as homedir4 } from "node:os";
|
|
2829
|
-
import { basename as basename6, dirname as dirname4, join as
|
|
2899
|
+
import { basename as basename6, dirname as dirname4, join as join16, resolve as resolve6 } from "node:path";
|
|
2830
2900
|
function noteCount(project) {
|
|
2831
|
-
const root =
|
|
2832
|
-
if (!
|
|
2901
|
+
const root = join16(project, "vault");
|
|
2902
|
+
if (!existsSync14(root))
|
|
2833
2903
|
return 0;
|
|
2834
2904
|
let n = 0;
|
|
2835
2905
|
const walk3 = (dir2, atRoot) => {
|
|
@@ -2841,7 +2911,7 @@ function noteCount(project) {
|
|
|
2841
2911
|
if (atRoot && CONTROL3.has(e.name))
|
|
2842
2912
|
continue;
|
|
2843
2913
|
if (e.isDirectory())
|
|
2844
|
-
walk3(
|
|
2914
|
+
walk3(join16(dir2, e.name), false);
|
|
2845
2915
|
else if (e.name.endsWith(".md"))
|
|
2846
2916
|
n++;
|
|
2847
2917
|
}
|
|
@@ -2884,7 +2954,7 @@ function tar(...a) {
|
|
|
2884
2954
|
var args5, sub, flag = (name) => {
|
|
2885
2955
|
const i = args5.indexOf(name);
|
|
2886
2956
|
return i >= 0 ? args5[i + 1] : undefined;
|
|
2887
|
-
}, positionals, expand = (p) => resolve6(p.startsWith("~/") ?
|
|
2957
|
+
}, positionals, expand = (p) => resolve6(p.startsWith("~/") ? join16(homedir4(), p.slice(2)) : p), CONTROL3;
|
|
2888
2958
|
var init_vault = __esm(() => {
|
|
2889
2959
|
init_registry();
|
|
2890
2960
|
args5 = process.argv.slice(2);
|
|
@@ -2919,7 +2989,7 @@ var init_vault = __esm(() => {
|
|
|
2919
2989
|
const outDir = expand(flag("--out") ?? ".");
|
|
2920
2990
|
mkdirSync5(outDir, { recursive: true });
|
|
2921
2991
|
const stamp = new Date().toISOString().slice(0, 10);
|
|
2922
|
-
const out =
|
|
2992
|
+
const out = join16(outDir, `${name}-${stamp}.tar.gz`);
|
|
2923
2993
|
if (tar("czf", out, "-C", dirname4(path), basename6(path)) !== 0) {
|
|
2924
2994
|
console.error("archive failed");
|
|
2925
2995
|
process.exit(1);
|
|
@@ -2940,11 +3010,11 @@ var init_vault = __esm(() => {
|
|
|
2940
3010
|
console.error("usage: imprnt vault restore <archive.tar.gz> <dir>");
|
|
2941
3011
|
process.exit(1);
|
|
2942
3012
|
}
|
|
2943
|
-
if (!
|
|
3013
|
+
if (!existsSync14(src3)) {
|
|
2944
3014
|
console.error(`no archive at ${src3}`);
|
|
2945
3015
|
process.exit(1);
|
|
2946
3016
|
}
|
|
2947
|
-
if (
|
|
3017
|
+
if (existsSync14(dest2) && readdirSync9(dest2).length) {
|
|
2948
3018
|
console.error(`${dest2} is not empty — restore into a new directory, then move it`);
|
|
2949
3019
|
process.exit(1);
|
|
2950
3020
|
}
|
|
@@ -2953,7 +3023,7 @@ var init_vault = __esm(() => {
|
|
|
2953
3023
|
console.error("restore failed");
|
|
2954
3024
|
process.exit(1);
|
|
2955
3025
|
}
|
|
2956
|
-
const inner = readdirSync9(dest2).map((e) =>
|
|
3026
|
+
const inner = readdirSync9(dest2).map((e) => join16(dest2, e)).filter((p) => statSync9(p).isDirectory());
|
|
2957
3027
|
const project = inner.find((p) => isVaultProject(p)) ?? (isVaultProject(dest2) ? dest2 : undefined);
|
|
2958
3028
|
if (!project) {
|
|
2959
3029
|
console.error(`extracted, but ${dest2} holds no vault project — check the archive`);
|
|
@@ -2981,9 +3051,9 @@ pointed at nothing — so the vault outlives whatever reads it.`);
|
|
|
2981
3051
|
|
|
2982
3052
|
// scripts/cli.ts
|
|
2983
3053
|
var exports_cli = {};
|
|
2984
|
-
import { cpSync as cpSync3, mkdirSync as mkdirSync6, chmodSync, existsSync as
|
|
3054
|
+
import { cpSync as cpSync3, mkdirSync as mkdirSync6, chmodSync, existsSync as existsSync15, readFileSync as readFileSync15, lstatSync as lstatSync4, statSync as statSync10, realpathSync as realpathSync2 } from "node:fs";
|
|
2985
3055
|
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
2986
|
-
import { join as
|
|
3056
|
+
import { join as join17, dirname as dirname5, resolve as resolve7, basename as basename7 } from "node:path";
|
|
2987
3057
|
import { homedir as homedir5 } from "node:os";
|
|
2988
3058
|
import { fileURLToPath } from "node:url";
|
|
2989
3059
|
import { createInterface as createInterface2 } from "node:readline/promises";
|
|
@@ -2991,7 +3061,7 @@ function pluginRoot() {
|
|
|
2991
3061
|
const local = projectRoot();
|
|
2992
3062
|
if (process.env.IMPRNT_ROOT || process.env.IMPRINT_ROOT)
|
|
2993
3063
|
return local;
|
|
2994
|
-
if (
|
|
3064
|
+
if (existsSync15(join17(local, "vault")) || existsSync15(join17(local, "CLAUDE.local.md")))
|
|
2995
3065
|
return local;
|
|
2996
3066
|
return registeredRoot() ?? local;
|
|
2997
3067
|
}
|
|
@@ -3020,7 +3090,7 @@ function resolvePath(input, base = process.cwd(), home = homedir5()) {
|
|
|
3020
3090
|
if (p === "~")
|
|
3021
3091
|
p = home;
|
|
3022
3092
|
else if (p.startsWith("~/"))
|
|
3023
|
-
p =
|
|
3093
|
+
p = join17(home, p.slice(2));
|
|
3024
3094
|
return resolve7(base, p);
|
|
3025
3095
|
}
|
|
3026
3096
|
function initPositional(args6) {
|
|
@@ -3029,7 +3099,7 @@ function initPositional(args6) {
|
|
|
3029
3099
|
function physicalTarget(target) {
|
|
3030
3100
|
let existing = target;
|
|
3031
3101
|
const tail = [];
|
|
3032
|
-
while (!
|
|
3102
|
+
while (!existsSync15(existing)) {
|
|
3033
3103
|
const parent = dirname5(existing);
|
|
3034
3104
|
if (parent === existing)
|
|
3035
3105
|
return target;
|
|
@@ -3037,7 +3107,7 @@ function physicalTarget(target) {
|
|
|
3037
3107
|
existing = parent;
|
|
3038
3108
|
}
|
|
3039
3109
|
try {
|
|
3040
|
-
return tail.length ?
|
|
3110
|
+
return tail.length ? join17(realpathSync2(existing), ...tail) : realpathSync2(existing);
|
|
3041
3111
|
} catch {
|
|
3042
3112
|
return target;
|
|
3043
3113
|
}
|
|
@@ -3073,7 +3143,7 @@ var init_cli = __esm(async () => {
|
|
|
3073
3143
|
init_registry();
|
|
3074
3144
|
init_launch();
|
|
3075
3145
|
here = dirname5(fileURLToPath(import.meta.url));
|
|
3076
|
-
pkgRoot =
|
|
3146
|
+
pkgRoot = join17(here, "..");
|
|
3077
3147
|
[cmd, ...rest] = process.argv.slice(2);
|
|
3078
3148
|
asImp = globalThis.__IMPRNT_IMP__ === true;
|
|
3079
3149
|
if (["ingest", "recall", "snapshot", "check", "vault"].includes(cmd))
|
|
@@ -3103,12 +3173,12 @@ var init_cli = __esm(async () => {
|
|
|
3103
3173
|
console.log(r);
|
|
3104
3174
|
console.log("");
|
|
3105
3175
|
}
|
|
3106
|
-
const p =
|
|
3107
|
-
if (!
|
|
3176
|
+
const p = join17(vault5, "hot.md");
|
|
3177
|
+
if (!existsSync15(p)) {
|
|
3108
3178
|
console.error(`no hot.md at ${p} — run \`imprnt init\``);
|
|
3109
3179
|
process.exit(1);
|
|
3110
3180
|
}
|
|
3111
|
-
console.log(
|
|
3181
|
+
console.log(readFileSync15(p, "utf8"));
|
|
3112
3182
|
break;
|
|
3113
3183
|
}
|
|
3114
3184
|
case "lair": {
|
|
@@ -3120,12 +3190,12 @@ var init_cli = __esm(async () => {
|
|
|
3120
3190
|
}
|
|
3121
3191
|
case "context": {
|
|
3122
3192
|
const home = requireVaultHome();
|
|
3123
|
-
const contract =
|
|
3124
|
-
if (!
|
|
3193
|
+
const contract = join17(home, "CLAUDE.md");
|
|
3194
|
+
if (!existsSync15(contract)) {
|
|
3125
3195
|
console.error(`no CLAUDE.md at ${home} — run \`imprnt init\` there to drop the contract`);
|
|
3126
3196
|
process.exit(1);
|
|
3127
3197
|
}
|
|
3128
|
-
process.stdout.write(
|
|
3198
|
+
process.stdout.write(readFileSync15(contract, "utf8"));
|
|
3129
3199
|
break;
|
|
3130
3200
|
}
|
|
3131
3201
|
case "agent": {
|
|
@@ -3324,7 +3394,7 @@ enable: imprnt plugin add <name> disable: imprnt plugin rm <name> [--purge]`);
|
|
|
3324
3394
|
process.exit(1);
|
|
3325
3395
|
}
|
|
3326
3396
|
case "global": {
|
|
3327
|
-
const globalDir = process.env.CLAUDE_CONFIG_DIR ||
|
|
3397
|
+
const globalDir = process.env.CLAUDE_CONFIG_DIR || join17(homedir5(), ".claude");
|
|
3328
3398
|
const [sub2, ...gargs] = rest;
|
|
3329
3399
|
if (sub2 === "list") {
|
|
3330
3400
|
const enabled = listGlobalModules(globalDir);
|
|
@@ -3359,8 +3429,8 @@ enable: imprnt plugin add <name> disable: imprnt plugin rm <name> [--purge]`);
|
|
|
3359
3429
|
}
|
|
3360
3430
|
const name = names[0];
|
|
3361
3431
|
const proj = pluginRoot();
|
|
3362
|
-
const srcDir = from ? resolve7(from) :
|
|
3363
|
-
if (!
|
|
3432
|
+
const srcDir = from ? resolve7(from) : join17(proj, "plugins", name);
|
|
3433
|
+
if (!existsSync15(srcDir)) {
|
|
3364
3434
|
console.error(`global add ${name}: no source - ${from ? `--from path not found: ${srcDir}` : `no plugins/${name}/ to promote; pass --from <dir>`}`);
|
|
3365
3435
|
process.exit(1);
|
|
3366
3436
|
}
|
|
@@ -3404,7 +3474,7 @@ enable: imprnt plugin add <name> disable: imprnt plugin rm <name> [--purge]`);
|
|
|
3404
3474
|
} else if (process.stdin.isTTY && process.stdout.isTTY) {
|
|
3405
3475
|
const inPlace = isVaultProject(process.cwd());
|
|
3406
3476
|
const display = inPlace ? process.cwd() : "~/imprnt";
|
|
3407
|
-
const fallback = inPlace ? process.cwd() :
|
|
3477
|
+
const fallback = inPlace ? process.cwd() : join17(homedir5(), "imprnt");
|
|
3408
3478
|
const rl = createInterface2({ input: process.stdin, output: process.stdout });
|
|
3409
3479
|
const answer = (await rl.question(`vault location [${display}]: `)).trim();
|
|
3410
3480
|
rl.close();
|
|
@@ -3413,7 +3483,7 @@ enable: imprnt plugin add <name> disable: imprnt plugin rm <name> [--purge]`);
|
|
|
3413
3483
|
target = process.cwd();
|
|
3414
3484
|
}
|
|
3415
3485
|
const toCwd = target === process.cwd();
|
|
3416
|
-
const rel = (sub2) => toCwd ? `./${sub2}` :
|
|
3486
|
+
const rel = (sub2) => toCwd ? `./${sub2}` : join17(target, sub2);
|
|
3417
3487
|
const lexicalEnclosing = projectRoot(target);
|
|
3418
3488
|
const physical = physicalTarget(target);
|
|
3419
3489
|
const physicalEnclosing = projectRoot(physical);
|
|
@@ -3426,12 +3496,12 @@ enable: imprnt plugin add <name> disable: imprnt plugin rm <name> [--purge]`);
|
|
|
3426
3496
|
const domains = ["identity", "health", "finances", "work", "life", "projects"];
|
|
3427
3497
|
const forms = ["events", "mistakes"];
|
|
3428
3498
|
const vaultDirs = [...entities, ...domains, ...forms];
|
|
3429
|
-
const vaultPath =
|
|
3430
|
-
const vaultExisted =
|
|
3499
|
+
const vaultPath = join17(target, "vault");
|
|
3500
|
+
const vaultExisted = existsSync15(vaultPath);
|
|
3431
3501
|
let createdDirs = 0;
|
|
3432
3502
|
for (const d of ["", "vault", ...vaultDirs.map((t) => `vault/${t}`), "raw"]) {
|
|
3433
|
-
const abs = d ?
|
|
3434
|
-
if (!
|
|
3503
|
+
const abs = d ? join17(target, d) : target;
|
|
3504
|
+
if (!existsSync15(abs))
|
|
3435
3505
|
createdDirs++;
|
|
3436
3506
|
try {
|
|
3437
3507
|
mkdirSync6(abs, { recursive: true });
|
|
@@ -3446,25 +3516,25 @@ enable: imprnt plugin add <name> disable: imprnt plugin rm <name> [--purge]`);
|
|
|
3446
3516
|
};
|
|
3447
3517
|
const added = [];
|
|
3448
3518
|
for (const f of ["index.md", "hot.md", "log.md", "_tags.md"]) {
|
|
3449
|
-
const dst =
|
|
3519
|
+
const dst = join17(vaultPath, f);
|
|
3450
3520
|
const slot = controlSlot(dst);
|
|
3451
3521
|
if (slot.startsWith("blocked")) {
|
|
3452
3522
|
console.error(blockedMsg(`vault/${f}`, slot));
|
|
3453
3523
|
process.exit(1);
|
|
3454
3524
|
}
|
|
3455
3525
|
if (slot === "create") {
|
|
3456
|
-
cpSync3(
|
|
3526
|
+
cpSync3(join17(pkgRoot, "templates", f), dst);
|
|
3457
3527
|
added.push(`vault/${f}`);
|
|
3458
3528
|
}
|
|
3459
3529
|
}
|
|
3460
|
-
const claudeMd =
|
|
3530
|
+
const claudeMd = join17(target, "CLAUDE.md");
|
|
3461
3531
|
const cmSlot = controlSlot(claudeMd);
|
|
3462
3532
|
if (cmSlot.startsWith("blocked")) {
|
|
3463
3533
|
console.error(blockedMsg("CLAUDE.md", cmSlot));
|
|
3464
3534
|
process.exit(1);
|
|
3465
3535
|
}
|
|
3466
|
-
if (cmSlot === "create" &&
|
|
3467
|
-
cpSync3(
|
|
3536
|
+
if (cmSlot === "create" && existsSync15(join17(pkgRoot, "CLAUDE.md"))) {
|
|
3537
|
+
cpSync3(join17(pkgRoot, "CLAUDE.md"), claudeMd);
|
|
3468
3538
|
added.push("CLAUDE.md");
|
|
3469
3539
|
}
|
|
3470
3540
|
try {
|
|
@@ -3506,8 +3576,8 @@ enable: imprnt plugin add <name> disable: imprnt plugin rm <name> [--purge]`);
|
|
|
3506
3576
|
const isHelp = cmd === "help" || cmd === "--help" || cmd === "-h";
|
|
3507
3577
|
const bare = cmd === undefined;
|
|
3508
3578
|
if (cmd && !isHelp && !bare && !cmd.startsWith("-")) {
|
|
3509
|
-
const modScript =
|
|
3510
|
-
if (
|
|
3579
|
+
const modScript = join17(pluginRoot(), "plugins", cmd, `${cmd}.js`);
|
|
3580
|
+
if (existsSync15(modScript)) {
|
|
3511
3581
|
const proc = spawnSync5(process.execPath, [modScript, ...rest], { stdio: "inherit" });
|
|
3512
3582
|
process.exit(proc.status ?? 1);
|
|
3513
3583
|
}
|
package/dist/imp.js
CHANGED
|
@@ -2454,11 +2454,72 @@ var init_snapshot = __esm(() => {
|
|
|
2454
2454
|
console.log(` next: the LLM reads raw/${dest}/ and fans sources out into vault notes (source: raw/${dest}/...).`);
|
|
2455
2455
|
});
|
|
2456
2456
|
|
|
2457
|
+
// scripts/lib/folders.ts
|
|
2458
|
+
import { existsSync as existsSync12, readFileSync as readFileSync13 } from "node:fs";
|
|
2459
|
+
import { join as join14 } from "node:path";
|
|
2460
|
+
function section2(text2, name) {
|
|
2461
|
+
return text2.match(new RegExp(`##\\s*${name}\\s*\\n([\\s\\S]*?)(?:\\n##\\s|\\s*$)`, "i"))?.[1] ?? "";
|
|
2462
|
+
}
|
|
2463
|
+
function folderTokens(line) {
|
|
2464
|
+
const t = line.trim();
|
|
2465
|
+
if (t === "" || t.startsWith("#") || t.startsWith("<!--") || t.startsWith(">"))
|
|
2466
|
+
return [];
|
|
2467
|
+
return t.replace(/^[-*]\s+/, "").split(",").map((s) => s.trim().normalize("NFC").toLowerCase()).filter((s) => FOLDER_TOKEN.test(s));
|
|
2468
|
+
}
|
|
2469
|
+
function read(text2, name, fallback) {
|
|
2470
|
+
const found = [];
|
|
2471
|
+
for (const line of section2(text2, name).split(/\r?\n/))
|
|
2472
|
+
found.push(...folderTokens(line));
|
|
2473
|
+
return new RegExp(`##\\s*${name}\\s*\\n`, "i").test(text2) ? new Set(found) : new Set(fallback);
|
|
2474
|
+
}
|
|
2475
|
+
function loadFolders(vault4) {
|
|
2476
|
+
const p = join14(vault4, "_folders.md");
|
|
2477
|
+
if (!existsSync12(p)) {
|
|
2478
|
+
return {
|
|
2479
|
+
entities: new Set(DEFAULT_ENTITIES),
|
|
2480
|
+
domains: new Set(DEFAULT_DOMAINS),
|
|
2481
|
+
forms: new Set(DEFAULT_FORMS),
|
|
2482
|
+
mounts: new Set,
|
|
2483
|
+
declared: false
|
|
2484
|
+
};
|
|
2485
|
+
}
|
|
2486
|
+
let text2 = "";
|
|
2487
|
+
try {
|
|
2488
|
+
text2 = readFileSync13(p, "utf8");
|
|
2489
|
+
} catch {
|
|
2490
|
+
return { entities: new Set(DEFAULT_ENTITIES), domains: new Set(DEFAULT_DOMAINS), forms: new Set(DEFAULT_FORMS), mounts: new Set, declared: false };
|
|
2491
|
+
}
|
|
2492
|
+
const roles = {
|
|
2493
|
+
entities: read(text2, "Entities", DEFAULT_ENTITIES),
|
|
2494
|
+
domains: read(text2, "Domains", DEFAULT_DOMAINS),
|
|
2495
|
+
forms: read(text2, "Forms", DEFAULT_FORMS),
|
|
2496
|
+
mounts: read(text2, "Mounts", []),
|
|
2497
|
+
declared: true
|
|
2498
|
+
};
|
|
2499
|
+
for (const f of roles.entities) {
|
|
2500
|
+
roles.domains.delete(f);
|
|
2501
|
+
roles.forms.delete(f);
|
|
2502
|
+
roles.mounts.delete(f);
|
|
2503
|
+
}
|
|
2504
|
+
for (const f of roles.mounts) {
|
|
2505
|
+
roles.domains.delete(f);
|
|
2506
|
+
roles.forms.delete(f);
|
|
2507
|
+
}
|
|
2508
|
+
return roles;
|
|
2509
|
+
}
|
|
2510
|
+
var DEFAULT_ENTITIES, DEFAULT_DOMAINS, DEFAULT_FORMS, FOLDER_TOKEN;
|
|
2511
|
+
var init_folders = __esm(() => {
|
|
2512
|
+
DEFAULT_ENTITIES = ["people", "orgs", "holdings"];
|
|
2513
|
+
DEFAULT_DOMAINS = ["identity", "health", "finances", "work", "life"];
|
|
2514
|
+
DEFAULT_FORMS = ["events", "mistakes", "projects"];
|
|
2515
|
+
FOLDER_TOKEN = /^[\p{L}\p{N}_-]+$/u;
|
|
2516
|
+
});
|
|
2517
|
+
|
|
2457
2518
|
// scripts/check.ts
|
|
2458
2519
|
var exports_check = {};
|
|
2459
|
-
import { readdirSync as readdirSync8, readFileSync as
|
|
2520
|
+
import { readdirSync as readdirSync8, readFileSync as readFileSync14, statSync as statSync8, existsSync as existsSync13, writeFileSync as writeFileSync10 } from "node:fs";
|
|
2460
2521
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
2461
|
-
import { join as
|
|
2522
|
+
import { join as join15, relative as relative6, dirname as dirname3 } from "node:path";
|
|
2462
2523
|
import { homedir as homedir3 } from "node:os";
|
|
2463
2524
|
function resolves(target) {
|
|
2464
2525
|
const t = target.trim().replace(/^\.\//, "").replace(/\.md$/, "");
|
|
@@ -2485,9 +2546,9 @@ function hostMemoryStores() {
|
|
|
2485
2546
|
const override = process.env.IMPRNT_HOST_MEMORY_DIR;
|
|
2486
2547
|
if (override)
|
|
2487
2548
|
return [override];
|
|
2488
|
-
const configDir = process.env.CLAUDE_CONFIG_DIR ||
|
|
2489
|
-
const projectsDir =
|
|
2490
|
-
if (!
|
|
2549
|
+
const configDir = process.env.CLAUDE_CONFIG_DIR || join15(homedir3(), ".claude");
|
|
2550
|
+
const projectsDir = join15(configDir, "projects");
|
|
2551
|
+
if (!existsSync13(projectsDir))
|
|
2491
2552
|
return [];
|
|
2492
2553
|
let entries;
|
|
2493
2554
|
try {
|
|
@@ -2495,7 +2556,7 @@ function hostMemoryStores() {
|
|
|
2495
2556
|
} catch {
|
|
2496
2557
|
return [];
|
|
2497
2558
|
}
|
|
2498
|
-
return entries.map((p) =>
|
|
2559
|
+
return entries.map((p) => join15(projectsDir, p, "memory")).filter((d) => {
|
|
2499
2560
|
try {
|
|
2500
2561
|
return statSync8(d).isDirectory();
|
|
2501
2562
|
} catch {
|
|
@@ -2505,17 +2566,17 @@ function hostMemoryStores() {
|
|
|
2505
2566
|
}
|
|
2506
2567
|
function memoryIndexHasContent(dir2) {
|
|
2507
2568
|
try {
|
|
2508
|
-
return
|
|
2569
|
+
return readFileSync14(join15(dir2, "MEMORY.md"), "utf8").split(/\r?\n/).some((l) => l.trim() !== "" && l.trim() !== "# Memory index");
|
|
2509
2570
|
} catch {
|
|
2510
2571
|
return false;
|
|
2511
2572
|
}
|
|
2512
2573
|
}
|
|
2513
2574
|
function syncNeedsReview(lines2) {
|
|
2514
|
-
const p =
|
|
2515
|
-
const exists =
|
|
2575
|
+
const p = join15(vault4, "_needs-review.md");
|
|
2576
|
+
const exists = existsSync13(p);
|
|
2516
2577
|
if (!exists && lines2.length === 0)
|
|
2517
2578
|
return "none";
|
|
2518
|
-
const prev = exists ?
|
|
2579
|
+
const prev = exists ? readFileSync14(p, "utf8") : `---
|
|
2519
2580
|
type: needs-review
|
|
2520
2581
|
---
|
|
2521
2582
|
|
|
@@ -2524,7 +2585,7 @@ type: needs-review
|
|
|
2524
2585
|
`;
|
|
2525
2586
|
const b = prev.indexOf(REVIEW_BEGIN);
|
|
2526
2587
|
const e = b !== -1 ? prev.indexOf(REVIEW_END, b + REVIEW_BEGIN.length) : -1;
|
|
2527
|
-
const
|
|
2588
|
+
const section3 = `${REVIEW_BEGIN}
|
|
2528
2589
|
${lines2.join(`
|
|
2529
2590
|
`)}
|
|
2530
2591
|
${REVIEW_END}
|
|
@@ -2538,22 +2599,23 @@ ${REVIEW_END}
|
|
|
2538
2599
|
} else {
|
|
2539
2600
|
after = prev.slice(b + REVIEW_BEGIN.length).replace(/^\n/, "");
|
|
2540
2601
|
}
|
|
2541
|
-
next = before + (lines2.length ?
|
|
2602
|
+
next = before + (lines2.length ? section3 : "") + after;
|
|
2542
2603
|
} else {
|
|
2543
2604
|
if (lines2.length === 0)
|
|
2544
2605
|
return "none";
|
|
2545
2606
|
next = (prev.endsWith(`
|
|
2546
2607
|
`) ? prev : prev + `
|
|
2547
|
-
`) +
|
|
2608
|
+
`) + section3;
|
|
2548
2609
|
}
|
|
2549
2610
|
if (next !== prev || !exists)
|
|
2550
2611
|
writeFileSync10(p, next);
|
|
2551
2612
|
return lines2.length ? "written" : "cleared";
|
|
2552
2613
|
}
|
|
2553
|
-
var args4, vault4, all = false, ENTITY_FOLDERS, DOMAIN_FOLDERS2, LINK, notes, allSlugs, folderOf, byBasename, orphans, disconnected, domainIssues, untagged, review, referencedRaw, tagVocab, hasRealTag = (tags) => tags.some((t) => /[\p{L}\p{N}]/u.test(normalize(tagVocab, t))), hasTagsFile, addedTags, dupPairs, manifest3, rawEntries, norm = (p) => p.replace(/^\.\//, "").replace(/^.*\/raw\//, "raw/").replace(/\.md$/, ""), refNorm, uncovered, memoryStores, strayStores, strayCount, REVIEW_BEGIN = "<!-- imprnt-check:begin (regenerated by `imprnt check` - do not edit between the markers) -->", REVIEW_END = "<!-- imprnt-check:end -->", cap = (xs, n = 25) => xs.slice(0, n).concat(xs.length > n ? [` … +${xs.length - n} more`] : []), count, folders, synced, issues;
|
|
2614
|
+
var args4, vault4, all = false, roles, ENTITY_FOLDERS, DOMAIN_FOLDERS2, MOUNT_FOLDERS, LINK, notes, allSlugs, folderOf, byBasename, orphans, disconnected, domainIssues, untagged, review, referencedRaw, tagVocab, hasRealTag = (tags) => tags.some((t) => /[\p{L}\p{N}]/u.test(normalize(tagVocab, t))), hasTagsFile, addedTags, dupPairs, manifest3, rawEntries, norm = (p) => p.replace(/^\.\//, "").replace(/^.*\/raw\//, "raw/").replace(/\.md$/, ""), refNorm, uncovered, memoryStores, strayStores, strayCount, REVIEW_BEGIN = "<!-- imprnt-check:begin (regenerated by `imprnt check` - do not edit between the markers) -->", REVIEW_END = "<!-- imprnt-check:end -->", cap = (xs, n = 25) => xs.slice(0, n).concat(xs.length > n ? [` … +${xs.length - n} more`] : []), count, folders, synced, issues;
|
|
2554
2615
|
var init_check = __esm(() => {
|
|
2555
2616
|
init_roots();
|
|
2556
2617
|
init_moc();
|
|
2618
|
+
init_folders();
|
|
2557
2619
|
init_tags();
|
|
2558
2620
|
init_manifest();
|
|
2559
2621
|
args4 = process.argv.slice(2);
|
|
@@ -2569,12 +2631,14 @@ var init_check = __esm(() => {
|
|
|
2569
2631
|
} else if (args4[i] === "--all")
|
|
2570
2632
|
all = true;
|
|
2571
2633
|
}
|
|
2572
|
-
if (!
|
|
2634
|
+
if (!existsSync13(vault4)) {
|
|
2573
2635
|
console.error(`no vault at ${vault4} — run \`imprnt init\` first`);
|
|
2574
2636
|
process.exit(1);
|
|
2575
2637
|
}
|
|
2576
|
-
|
|
2577
|
-
|
|
2638
|
+
roles = loadFolders(vault4);
|
|
2639
|
+
ENTITY_FOLDERS = roles.entities;
|
|
2640
|
+
DOMAIN_FOLDERS2 = roles.domains;
|
|
2641
|
+
MOUNT_FOLDERS = roles.mounts;
|
|
2578
2642
|
LINK = /\[\[([^\]|#]+)(?:#[^\]|]+)?(?:\|[^\]]+)?\]\]/g;
|
|
2579
2643
|
notes = collectNotes(vault4);
|
|
2580
2644
|
allSlugs = new Set(notes.map((n) => n.slug));
|
|
@@ -2592,7 +2656,7 @@ var init_check = __esm(() => {
|
|
|
2592
2656
|
referencedRaw = new Set;
|
|
2593
2657
|
tagVocab = loadTags(vault4);
|
|
2594
2658
|
for (const n of notes) {
|
|
2595
|
-
const raw =
|
|
2659
|
+
const raw = readFileSync14(n.path, "utf8");
|
|
2596
2660
|
const fm2 = frontmatter(raw);
|
|
2597
2661
|
const links = [...stripCode(raw).matchAll(LINK)].map((m) => m[1].trim()).filter((l) => !l.startsWith("raw/"));
|
|
2598
2662
|
for (const l of links)
|
|
@@ -2600,7 +2664,7 @@ var init_check = __esm(() => {
|
|
|
2600
2664
|
orphans.push(` ${n.slug} → [[${l}]]`);
|
|
2601
2665
|
review.push(`- [ ] orphan link [[${l}]] — from [[${n.slug}]], target note missing`);
|
|
2602
2666
|
}
|
|
2603
|
-
if (!ENTITY_FOLDERS.has(n.folder) && !links.some(linksEntity)) {
|
|
2667
|
+
if (!ENTITY_FOLDERS.has(n.folder) && !MOUNT_FOLDERS.has(n.folder) && !links.some(linksEntity)) {
|
|
2604
2668
|
disconnected.push(` ${n.slug}`);
|
|
2605
2669
|
review.push(`- [ ] disconnected note [[${n.slug}]] — links no entity`);
|
|
2606
2670
|
}
|
|
@@ -2620,7 +2684,7 @@ var init_check = __esm(() => {
|
|
|
2620
2684
|
for (const s of fmList(fm2, "sources"))
|
|
2621
2685
|
referencedRaw.add(s.replace(/^\[\[/, "").replace(/\]\]$/, "").replace(/^\.\//, ""));
|
|
2622
2686
|
}
|
|
2623
|
-
hasTagsFile =
|
|
2687
|
+
hasTagsFile = existsSync13(join15(vault4, "_tags.md"));
|
|
2624
2688
|
addedTags = [];
|
|
2625
2689
|
dupPairs = [];
|
|
2626
2690
|
if (hasTagsFile) {
|
|
@@ -2692,7 +2756,7 @@ var init_check = __esm(() => {
|
|
|
2692
2756
|
strayStores = memoryStores.map((dir2) => {
|
|
2693
2757
|
let files3 = [];
|
|
2694
2758
|
try {
|
|
2695
|
-
if (
|
|
2759
|
+
if (existsSync13(dir2))
|
|
2696
2760
|
files3 = readdirSync8(dir2).filter((f) => f.endsWith(".md") && f !== "MEMORY.md").sort();
|
|
2697
2761
|
} catch (e) {
|
|
2698
2762
|
console.error(`⚠ host auto-memory sweep: could not read ${dir2} (${e instanceof Error ? e.message : String(e)}) - skipping it`);
|
|
@@ -2704,8 +2768,14 @@ var init_check = __esm(() => {
|
|
|
2704
2768
|
strayCount = strayStores.reduce((n, s) => n + s.files.length, 0);
|
|
2705
2769
|
for (const s of strayStores)
|
|
2706
2770
|
review.push(`- [ ] host auto-memory not empty — ${s.files.length} note(s) in ${s.dir}; migrate knowledge → vault notes, behavior → a CLAUDE.local.md fragment, then empty it`);
|
|
2707
|
-
console.log(`imprnt check — ${notes.length} notes in ${vault4}
|
|
2708
|
-
|
|
2771
|
+
console.log(`imprnt check — ${notes.length} notes in ${vault4}`);
|
|
2772
|
+
if (roles.declared) {
|
|
2773
|
+
const parts = [`entities: ${[...ENTITY_FOLDERS].join(" ") || "(none)"}`, `domains: ${[...DOMAIN_FOLDERS2].join(" ") || "(none)"}`];
|
|
2774
|
+
if (MOUNT_FOLDERS.size)
|
|
2775
|
+
parts.push(`mounts: ${[...MOUNT_FOLDERS].join(" ")}`);
|
|
2776
|
+
console.log(`folder roles from _folders.md — ${parts.join(", ")}`);
|
|
2777
|
+
}
|
|
2778
|
+
console.log("");
|
|
2709
2779
|
if (orphans.length) {
|
|
2710
2780
|
console.log(`⚠ orphan links (${orphans.length}) — target note missing:`);
|
|
2711
2781
|
console.log(cap(orphans).join(`
|
|
@@ -2778,18 +2848,18 @@ var init_check = __esm(() => {
|
|
|
2778
2848
|
${issues} thing(s) to look at above.` : `
|
|
2779
2849
|
clean.`);
|
|
2780
2850
|
if (all) {
|
|
2781
|
-
const pluginsDir =
|
|
2851
|
+
const pluginsDir = join15(projectRoot(), "plugins");
|
|
2782
2852
|
const checks = [];
|
|
2783
|
-
if (
|
|
2853
|
+
if (existsSync13(pluginsDir)) {
|
|
2784
2854
|
for (const entry of readdirSync8(pluginsDir)) {
|
|
2785
2855
|
let isDir2 = false;
|
|
2786
2856
|
try {
|
|
2787
|
-
isDir2 = statSync8(
|
|
2857
|
+
isDir2 = statSync8(join15(pluginsDir, entry)).isDirectory();
|
|
2788
2858
|
} catch {
|
|
2789
2859
|
continue;
|
|
2790
2860
|
}
|
|
2791
|
-
const p =
|
|
2792
|
-
if (isDir2 &&
|
|
2861
|
+
const p = join15(pluginsDir, entry, "check.js");
|
|
2862
|
+
if (isDir2 && existsSync13(p))
|
|
2793
2863
|
checks.push(p);
|
|
2794
2864
|
}
|
|
2795
2865
|
}
|
|
@@ -2824,12 +2894,12 @@ all plugin checks passed.`);
|
|
|
2824
2894
|
// scripts/vault.ts
|
|
2825
2895
|
var exports_vault = {};
|
|
2826
2896
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
2827
|
-
import { existsSync as
|
|
2897
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync5, readdirSync as readdirSync9, statSync as statSync9 } from "node:fs";
|
|
2828
2898
|
import { homedir as homedir4 } from "node:os";
|
|
2829
|
-
import { basename as basename6, dirname as dirname4, join as
|
|
2899
|
+
import { basename as basename6, dirname as dirname4, join as join16, resolve as resolve6 } from "node:path";
|
|
2830
2900
|
function noteCount(project) {
|
|
2831
|
-
const root =
|
|
2832
|
-
if (!
|
|
2901
|
+
const root = join16(project, "vault");
|
|
2902
|
+
if (!existsSync14(root))
|
|
2833
2903
|
return 0;
|
|
2834
2904
|
let n = 0;
|
|
2835
2905
|
const walk3 = (dir2, atRoot) => {
|
|
@@ -2841,7 +2911,7 @@ function noteCount(project) {
|
|
|
2841
2911
|
if (atRoot && CONTROL3.has(e.name))
|
|
2842
2912
|
continue;
|
|
2843
2913
|
if (e.isDirectory())
|
|
2844
|
-
walk3(
|
|
2914
|
+
walk3(join16(dir2, e.name), false);
|
|
2845
2915
|
else if (e.name.endsWith(".md"))
|
|
2846
2916
|
n++;
|
|
2847
2917
|
}
|
|
@@ -2884,7 +2954,7 @@ function tar(...a) {
|
|
|
2884
2954
|
var args5, sub, flag = (name) => {
|
|
2885
2955
|
const i = args5.indexOf(name);
|
|
2886
2956
|
return i >= 0 ? args5[i + 1] : undefined;
|
|
2887
|
-
}, positionals, expand = (p) => resolve6(p.startsWith("~/") ?
|
|
2957
|
+
}, positionals, expand = (p) => resolve6(p.startsWith("~/") ? join16(homedir4(), p.slice(2)) : p), CONTROL3;
|
|
2888
2958
|
var init_vault = __esm(() => {
|
|
2889
2959
|
init_registry();
|
|
2890
2960
|
args5 = process.argv.slice(2);
|
|
@@ -2919,7 +2989,7 @@ var init_vault = __esm(() => {
|
|
|
2919
2989
|
const outDir = expand(flag("--out") ?? ".");
|
|
2920
2990
|
mkdirSync5(outDir, { recursive: true });
|
|
2921
2991
|
const stamp = new Date().toISOString().slice(0, 10);
|
|
2922
|
-
const out =
|
|
2992
|
+
const out = join16(outDir, `${name}-${stamp}.tar.gz`);
|
|
2923
2993
|
if (tar("czf", out, "-C", dirname4(path), basename6(path)) !== 0) {
|
|
2924
2994
|
console.error("archive failed");
|
|
2925
2995
|
process.exit(1);
|
|
@@ -2940,11 +3010,11 @@ var init_vault = __esm(() => {
|
|
|
2940
3010
|
console.error("usage: imprnt vault restore <archive.tar.gz> <dir>");
|
|
2941
3011
|
process.exit(1);
|
|
2942
3012
|
}
|
|
2943
|
-
if (!
|
|
3013
|
+
if (!existsSync14(src3)) {
|
|
2944
3014
|
console.error(`no archive at ${src3}`);
|
|
2945
3015
|
process.exit(1);
|
|
2946
3016
|
}
|
|
2947
|
-
if (
|
|
3017
|
+
if (existsSync14(dest2) && readdirSync9(dest2).length) {
|
|
2948
3018
|
console.error(`${dest2} is not empty — restore into a new directory, then move it`);
|
|
2949
3019
|
process.exit(1);
|
|
2950
3020
|
}
|
|
@@ -2953,7 +3023,7 @@ var init_vault = __esm(() => {
|
|
|
2953
3023
|
console.error("restore failed");
|
|
2954
3024
|
process.exit(1);
|
|
2955
3025
|
}
|
|
2956
|
-
const inner = readdirSync9(dest2).map((e) =>
|
|
3026
|
+
const inner = readdirSync9(dest2).map((e) => join16(dest2, e)).filter((p) => statSync9(p).isDirectory());
|
|
2957
3027
|
const project = inner.find((p) => isVaultProject(p)) ?? (isVaultProject(dest2) ? dest2 : undefined);
|
|
2958
3028
|
if (!project) {
|
|
2959
3029
|
console.error(`extracted, but ${dest2} holds no vault project — check the archive`);
|
|
@@ -2981,9 +3051,9 @@ pointed at nothing — so the vault outlives whatever reads it.`);
|
|
|
2981
3051
|
|
|
2982
3052
|
// scripts/cli.ts
|
|
2983
3053
|
var exports_cli = {};
|
|
2984
|
-
import { cpSync as cpSync3, mkdirSync as mkdirSync6, chmodSync, existsSync as
|
|
3054
|
+
import { cpSync as cpSync3, mkdirSync as mkdirSync6, chmodSync, existsSync as existsSync15, readFileSync as readFileSync15, lstatSync as lstatSync4, statSync as statSync10, realpathSync as realpathSync2 } from "node:fs";
|
|
2985
3055
|
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
2986
|
-
import { join as
|
|
3056
|
+
import { join as join17, dirname as dirname5, resolve as resolve7, basename as basename7 } from "node:path";
|
|
2987
3057
|
import { homedir as homedir5 } from "node:os";
|
|
2988
3058
|
import { fileURLToPath } from "node:url";
|
|
2989
3059
|
import { createInterface as createInterface2 } from "node:readline/promises";
|
|
@@ -2991,7 +3061,7 @@ function pluginRoot() {
|
|
|
2991
3061
|
const local = projectRoot();
|
|
2992
3062
|
if (process.env.IMPRNT_ROOT || process.env.IMPRINT_ROOT)
|
|
2993
3063
|
return local;
|
|
2994
|
-
if (
|
|
3064
|
+
if (existsSync15(join17(local, "vault")) || existsSync15(join17(local, "CLAUDE.local.md")))
|
|
2995
3065
|
return local;
|
|
2996
3066
|
return registeredRoot() ?? local;
|
|
2997
3067
|
}
|
|
@@ -3020,7 +3090,7 @@ function resolvePath(input, base = process.cwd(), home = homedir5()) {
|
|
|
3020
3090
|
if (p === "~")
|
|
3021
3091
|
p = home;
|
|
3022
3092
|
else if (p.startsWith("~/"))
|
|
3023
|
-
p =
|
|
3093
|
+
p = join17(home, p.slice(2));
|
|
3024
3094
|
return resolve7(base, p);
|
|
3025
3095
|
}
|
|
3026
3096
|
function initPositional(args6) {
|
|
@@ -3029,7 +3099,7 @@ function initPositional(args6) {
|
|
|
3029
3099
|
function physicalTarget(target) {
|
|
3030
3100
|
let existing = target;
|
|
3031
3101
|
const tail = [];
|
|
3032
|
-
while (!
|
|
3102
|
+
while (!existsSync15(existing)) {
|
|
3033
3103
|
const parent = dirname5(existing);
|
|
3034
3104
|
if (parent === existing)
|
|
3035
3105
|
return target;
|
|
@@ -3037,7 +3107,7 @@ function physicalTarget(target) {
|
|
|
3037
3107
|
existing = parent;
|
|
3038
3108
|
}
|
|
3039
3109
|
try {
|
|
3040
|
-
return tail.length ?
|
|
3110
|
+
return tail.length ? join17(realpathSync2(existing), ...tail) : realpathSync2(existing);
|
|
3041
3111
|
} catch {
|
|
3042
3112
|
return target;
|
|
3043
3113
|
}
|
|
@@ -3073,7 +3143,7 @@ var init_cli = __esm(async () => {
|
|
|
3073
3143
|
init_registry();
|
|
3074
3144
|
init_launch();
|
|
3075
3145
|
here = dirname5(fileURLToPath(import.meta.url));
|
|
3076
|
-
pkgRoot =
|
|
3146
|
+
pkgRoot = join17(here, "..");
|
|
3077
3147
|
[cmd, ...rest] = process.argv.slice(2);
|
|
3078
3148
|
asImp = globalThis.__IMPRNT_IMP__ === true;
|
|
3079
3149
|
if (["ingest", "recall", "snapshot", "check", "vault"].includes(cmd))
|
|
@@ -3103,12 +3173,12 @@ var init_cli = __esm(async () => {
|
|
|
3103
3173
|
console.log(r);
|
|
3104
3174
|
console.log("");
|
|
3105
3175
|
}
|
|
3106
|
-
const p =
|
|
3107
|
-
if (!
|
|
3176
|
+
const p = join17(vault5, "hot.md");
|
|
3177
|
+
if (!existsSync15(p)) {
|
|
3108
3178
|
console.error(`no hot.md at ${p} — run \`imprnt init\``);
|
|
3109
3179
|
process.exit(1);
|
|
3110
3180
|
}
|
|
3111
|
-
console.log(
|
|
3181
|
+
console.log(readFileSync15(p, "utf8"));
|
|
3112
3182
|
break;
|
|
3113
3183
|
}
|
|
3114
3184
|
case "lair": {
|
|
@@ -3120,12 +3190,12 @@ var init_cli = __esm(async () => {
|
|
|
3120
3190
|
}
|
|
3121
3191
|
case "context": {
|
|
3122
3192
|
const home = requireVaultHome();
|
|
3123
|
-
const contract =
|
|
3124
|
-
if (!
|
|
3193
|
+
const contract = join17(home, "CLAUDE.md");
|
|
3194
|
+
if (!existsSync15(contract)) {
|
|
3125
3195
|
console.error(`no CLAUDE.md at ${home} — run \`imprnt init\` there to drop the contract`);
|
|
3126
3196
|
process.exit(1);
|
|
3127
3197
|
}
|
|
3128
|
-
process.stdout.write(
|
|
3198
|
+
process.stdout.write(readFileSync15(contract, "utf8"));
|
|
3129
3199
|
break;
|
|
3130
3200
|
}
|
|
3131
3201
|
case "agent": {
|
|
@@ -3324,7 +3394,7 @@ enable: imprnt plugin add <name> disable: imprnt plugin rm <name> [--purge]`);
|
|
|
3324
3394
|
process.exit(1);
|
|
3325
3395
|
}
|
|
3326
3396
|
case "global": {
|
|
3327
|
-
const globalDir = process.env.CLAUDE_CONFIG_DIR ||
|
|
3397
|
+
const globalDir = process.env.CLAUDE_CONFIG_DIR || join17(homedir5(), ".claude");
|
|
3328
3398
|
const [sub2, ...gargs] = rest;
|
|
3329
3399
|
if (sub2 === "list") {
|
|
3330
3400
|
const enabled = listGlobalModules(globalDir);
|
|
@@ -3359,8 +3429,8 @@ enable: imprnt plugin add <name> disable: imprnt plugin rm <name> [--purge]`);
|
|
|
3359
3429
|
}
|
|
3360
3430
|
const name = names[0];
|
|
3361
3431
|
const proj = pluginRoot();
|
|
3362
|
-
const srcDir = from ? resolve7(from) :
|
|
3363
|
-
if (!
|
|
3432
|
+
const srcDir = from ? resolve7(from) : join17(proj, "plugins", name);
|
|
3433
|
+
if (!existsSync15(srcDir)) {
|
|
3364
3434
|
console.error(`global add ${name}: no source - ${from ? `--from path not found: ${srcDir}` : `no plugins/${name}/ to promote; pass --from <dir>`}`);
|
|
3365
3435
|
process.exit(1);
|
|
3366
3436
|
}
|
|
@@ -3404,7 +3474,7 @@ enable: imprnt plugin add <name> disable: imprnt plugin rm <name> [--purge]`);
|
|
|
3404
3474
|
} else if (process.stdin.isTTY && process.stdout.isTTY) {
|
|
3405
3475
|
const inPlace = isVaultProject(process.cwd());
|
|
3406
3476
|
const display = inPlace ? process.cwd() : "~/imprnt";
|
|
3407
|
-
const fallback = inPlace ? process.cwd() :
|
|
3477
|
+
const fallback = inPlace ? process.cwd() : join17(homedir5(), "imprnt");
|
|
3408
3478
|
const rl = createInterface2({ input: process.stdin, output: process.stdout });
|
|
3409
3479
|
const answer = (await rl.question(`vault location [${display}]: `)).trim();
|
|
3410
3480
|
rl.close();
|
|
@@ -3413,7 +3483,7 @@ enable: imprnt plugin add <name> disable: imprnt plugin rm <name> [--purge]`);
|
|
|
3413
3483
|
target = process.cwd();
|
|
3414
3484
|
}
|
|
3415
3485
|
const toCwd = target === process.cwd();
|
|
3416
|
-
const rel = (sub2) => toCwd ? `./${sub2}` :
|
|
3486
|
+
const rel = (sub2) => toCwd ? `./${sub2}` : join17(target, sub2);
|
|
3417
3487
|
const lexicalEnclosing = projectRoot(target);
|
|
3418
3488
|
const physical = physicalTarget(target);
|
|
3419
3489
|
const physicalEnclosing = projectRoot(physical);
|
|
@@ -3426,12 +3496,12 @@ enable: imprnt plugin add <name> disable: imprnt plugin rm <name> [--purge]`);
|
|
|
3426
3496
|
const domains = ["identity", "health", "finances", "work", "life", "projects"];
|
|
3427
3497
|
const forms = ["events", "mistakes"];
|
|
3428
3498
|
const vaultDirs = [...entities, ...domains, ...forms];
|
|
3429
|
-
const vaultPath =
|
|
3430
|
-
const vaultExisted =
|
|
3499
|
+
const vaultPath = join17(target, "vault");
|
|
3500
|
+
const vaultExisted = existsSync15(vaultPath);
|
|
3431
3501
|
let createdDirs = 0;
|
|
3432
3502
|
for (const d of ["", "vault", ...vaultDirs.map((t) => `vault/${t}`), "raw"]) {
|
|
3433
|
-
const abs = d ?
|
|
3434
|
-
if (!
|
|
3503
|
+
const abs = d ? join17(target, d) : target;
|
|
3504
|
+
if (!existsSync15(abs))
|
|
3435
3505
|
createdDirs++;
|
|
3436
3506
|
try {
|
|
3437
3507
|
mkdirSync6(abs, { recursive: true });
|
|
@@ -3446,25 +3516,25 @@ enable: imprnt plugin add <name> disable: imprnt plugin rm <name> [--purge]`);
|
|
|
3446
3516
|
};
|
|
3447
3517
|
const added = [];
|
|
3448
3518
|
for (const f of ["index.md", "hot.md", "log.md", "_tags.md"]) {
|
|
3449
|
-
const dst =
|
|
3519
|
+
const dst = join17(vaultPath, f);
|
|
3450
3520
|
const slot = controlSlot(dst);
|
|
3451
3521
|
if (slot.startsWith("blocked")) {
|
|
3452
3522
|
console.error(blockedMsg(`vault/${f}`, slot));
|
|
3453
3523
|
process.exit(1);
|
|
3454
3524
|
}
|
|
3455
3525
|
if (slot === "create") {
|
|
3456
|
-
cpSync3(
|
|
3526
|
+
cpSync3(join17(pkgRoot, "templates", f), dst);
|
|
3457
3527
|
added.push(`vault/${f}`);
|
|
3458
3528
|
}
|
|
3459
3529
|
}
|
|
3460
|
-
const claudeMd =
|
|
3530
|
+
const claudeMd = join17(target, "CLAUDE.md");
|
|
3461
3531
|
const cmSlot = controlSlot(claudeMd);
|
|
3462
3532
|
if (cmSlot.startsWith("blocked")) {
|
|
3463
3533
|
console.error(blockedMsg("CLAUDE.md", cmSlot));
|
|
3464
3534
|
process.exit(1);
|
|
3465
3535
|
}
|
|
3466
|
-
if (cmSlot === "create" &&
|
|
3467
|
-
cpSync3(
|
|
3536
|
+
if (cmSlot === "create" && existsSync15(join17(pkgRoot, "CLAUDE.md"))) {
|
|
3537
|
+
cpSync3(join17(pkgRoot, "CLAUDE.md"), claudeMd);
|
|
3468
3538
|
added.push("CLAUDE.md");
|
|
3469
3539
|
}
|
|
3470
3540
|
try {
|
|
@@ -3506,8 +3576,8 @@ enable: imprnt plugin add <name> disable: imprnt plugin rm <name> [--purge]`);
|
|
|
3506
3576
|
const isHelp = cmd === "help" || cmd === "--help" || cmd === "-h";
|
|
3507
3577
|
const bare = cmd === undefined;
|
|
3508
3578
|
if (cmd && !isHelp && !bare && !cmd.startsWith("-")) {
|
|
3509
|
-
const modScript =
|
|
3510
|
-
if (
|
|
3579
|
+
const modScript = join17(pluginRoot(), "plugins", cmd, `${cmd}.js`);
|
|
3580
|
+
if (existsSync15(modScript)) {
|
|
3511
3581
|
const proc = spawnSync5(process.execPath, [modScript, ...rest], { stdio: "inherit" });
|
|
3512
3582
|
process.exit(proc.status ?? 1);
|
|
3513
3583
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "imprnt",
|
|
3
|
-
"version": "0.1.4-edge.
|
|
3
|
+
"version": "0.1.4-edge.89",
|
|
4
4
|
"stable": true,
|
|
5
5
|
"description": "Deterministic-first, plain-markdown knowledge vault. Code does the bulk transform. The LLM only touches the irreducibly-semantic 20%. Native grep plus BM25 retrieval, zero MCP on the vault.",
|
|
6
6
|
"type": "module",
|