ori-memory 0.2.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.
Files changed (125) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +217 -0
  3. package/adapters/claude-code/hooks/capture.mjs +58 -0
  4. package/adapters/claude-code/hooks/orient.mjs +114 -0
  5. package/adapters/claude-code/hooks/validate.mjs +56 -0
  6. package/dist/agents/lock.d.ts +3 -0
  7. package/dist/agents/lock.d.ts.map +1 -0
  8. package/dist/agents/lock.js +11 -0
  9. package/dist/agents/lock.js.map +1 -0
  10. package/dist/agents/protocol.d.ts +6 -0
  11. package/dist/agents/protocol.d.ts.map +1 -0
  12. package/dist/agents/protocol.js +10 -0
  13. package/dist/agents/protocol.js.map +1 -0
  14. package/dist/cli/add.d.ts +12 -0
  15. package/dist/cli/add.d.ts.map +1 -0
  16. package/dist/cli/add.js +88 -0
  17. package/dist/cli/add.js.map +1 -0
  18. package/dist/cli/archive.d.ts +25 -0
  19. package/dist/cli/archive.d.ts.map +1 -0
  20. package/dist/cli/archive.js +69 -0
  21. package/dist/cli/archive.js.map +1 -0
  22. package/dist/cli/bridge.d.ts +19 -0
  23. package/dist/cli/bridge.d.ts.map +1 -0
  24. package/dist/cli/bridge.js +180 -0
  25. package/dist/cli/bridge.js.map +1 -0
  26. package/dist/cli/health.d.ts +7 -0
  27. package/dist/cli/health.d.ts.map +1 -0
  28. package/dist/cli/health.js +66 -0
  29. package/dist/cli/health.js.map +1 -0
  30. package/dist/cli/init.d.ts +9 -0
  31. package/dist/cli/init.d.ts.map +1 -0
  32. package/dist/cli/init.js +44 -0
  33. package/dist/cli/init.js.map +1 -0
  34. package/dist/cli/promote.d.ts +35 -0
  35. package/dist/cli/promote.d.ts.map +1 -0
  36. package/dist/cli/promote.js +182 -0
  37. package/dist/cli/promote.js.map +1 -0
  38. package/dist/cli/query.d.ts +10 -0
  39. package/dist/cli/query.d.ts.map +1 -0
  40. package/dist/cli/query.js +74 -0
  41. package/dist/cli/query.js.map +1 -0
  42. package/dist/cli/serve.d.ts +27 -0
  43. package/dist/cli/serve.d.ts.map +1 -0
  44. package/dist/cli/serve.js +254 -0
  45. package/dist/cli/serve.js.map +1 -0
  46. package/dist/cli/status.d.ts +7 -0
  47. package/dist/cli/status.d.ts.map +1 -0
  48. package/dist/cli/status.js +34 -0
  49. package/dist/cli/status.js.map +1 -0
  50. package/dist/cli/validate.d.ts +9 -0
  51. package/dist/cli/validate.d.ts.map +1 -0
  52. package/dist/cli/validate.js +37 -0
  53. package/dist/cli/validate.js.map +1 -0
  54. package/dist/core/classify.d.ts +13 -0
  55. package/dist/core/classify.d.ts.map +1 -0
  56. package/dist/core/classify.js +126 -0
  57. package/dist/core/classify.js.map +1 -0
  58. package/dist/core/config.d.ts +82 -0
  59. package/dist/core/config.d.ts.map +1 -0
  60. package/dist/core/config.js +183 -0
  61. package/dist/core/config.js.map +1 -0
  62. package/dist/core/frontmatter.d.ts +11 -0
  63. package/dist/core/frontmatter.d.ts.map +1 -0
  64. package/dist/core/frontmatter.js +61 -0
  65. package/dist/core/frontmatter.js.map +1 -0
  66. package/dist/core/graph.d.ts +9 -0
  67. package/dist/core/graph.d.ts.map +1 -0
  68. package/dist/core/graph.js +56 -0
  69. package/dist/core/graph.js.map +1 -0
  70. package/dist/core/importance.d.ts +49 -0
  71. package/dist/core/importance.d.ts.map +1 -0
  72. package/dist/core/importance.js +230 -0
  73. package/dist/core/importance.js.map +1 -0
  74. package/dist/core/intent.d.ts +36 -0
  75. package/dist/core/intent.d.ts.map +1 -0
  76. package/dist/core/intent.js +108 -0
  77. package/dist/core/intent.js.map +1 -0
  78. package/dist/core/linkdetect.d.ts +34 -0
  79. package/dist/core/linkdetect.d.ts.map +1 -0
  80. package/dist/core/linkdetect.js +181 -0
  81. package/dist/core/linkdetect.js.map +1 -0
  82. package/dist/core/llm.d.ts +41 -0
  83. package/dist/core/llm.d.ts.map +1 -0
  84. package/dist/core/llm.js +36 -0
  85. package/dist/core/llm.js.map +1 -0
  86. package/dist/core/promote.d.ts +40 -0
  87. package/dist/core/promote.d.ts.map +1 -0
  88. package/dist/core/promote.js +246 -0
  89. package/dist/core/promote.js.map +1 -0
  90. package/dist/core/ranking.d.ts +33 -0
  91. package/dist/core/ranking.d.ts.map +1 -0
  92. package/dist/core/ranking.js +45 -0
  93. package/dist/core/ranking.js.map +1 -0
  94. package/dist/core/schema.d.ts +16 -0
  95. package/dist/core/schema.d.ts.map +1 -0
  96. package/dist/core/schema.js +76 -0
  97. package/dist/core/schema.js.map +1 -0
  98. package/dist/core/vault.d.ts +16 -0
  99. package/dist/core/vault.d.ts.map +1 -0
  100. package/dist/core/vault.js +52 -0
  101. package/dist/core/vault.js.map +1 -0
  102. package/dist/core/vitality.d.ts +55 -0
  103. package/dist/core/vitality.d.ts.map +1 -0
  104. package/dist/core/vitality.js +95 -0
  105. package/dist/core/vitality.js.map +1 -0
  106. package/dist/index.d.ts +3 -0
  107. package/dist/index.d.ts.map +1 -0
  108. package/dist/index.js +139 -0
  109. package/dist/index.js.map +1 -0
  110. package/dist/providers/anthropic.d.ts +12 -0
  111. package/dist/providers/anthropic.d.ts.map +1 -0
  112. package/dist/providers/anthropic.js +90 -0
  113. package/dist/providers/anthropic.js.map +1 -0
  114. package/package.json +60 -0
  115. package/scaffold/.ori +1 -0
  116. package/scaffold/inbox/.gitkeep +1 -0
  117. package/scaffold/notes/index.md +19 -0
  118. package/scaffold/ops/observations/.gitkeep +1 -0
  119. package/scaffold/ops/reminders.md +3 -0
  120. package/scaffold/ops/sessions/.gitkeep +1 -0
  121. package/scaffold/ori.config.yaml +79 -0
  122. package/scaffold/templates/map.md +36 -0
  123. package/scaffold/templates/note.md +61 -0
  124. package/scaffold/templates/observation.md +38 -0
  125. package/scaffold/templates/source.md +45 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../src/agents/protocol.ts"],"names":[],"mappings":"AAKA,MAAM,UAAU,kBAAkB,CAChC,KAAa,EACb,SAAkB;IAElB,MAAM,IAAI,GAAG,KAAK;SACf,WAAW,EAAE;SACb,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC;SAC5B,IAAI,EAAE;SACN,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACxB,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,GAAG,SAAS,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IAChD,OAAO,GAAG,MAAM,GAAG,IAAI,KAAK,CAAC;AAC/B,CAAC"}
@@ -0,0 +1,12 @@
1
+ export type AddOptions = {
2
+ startDir: string;
3
+ title: string;
4
+ type?: string;
5
+ };
6
+ export type AddResult = {
7
+ success: boolean;
8
+ data: Record<string, unknown>;
9
+ warnings: string[];
10
+ };
11
+ export declare function runAdd(options: AddOptions): Promise<AddResult>;
12
+ //# sourceMappingURL=add.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../src/cli/add.ts"],"names":[],"mappings":"AAQA,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG;IACtB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB,CAAC;AAUF,wBAAsB,MAAM,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC,CAmFpE"}
@@ -0,0 +1,88 @@
1
+ import path from "node:path";
2
+ import { promises as fs } from "node:fs";
3
+ import { findVaultRoot, getVaultPaths } from "../core/vault.js";
4
+ import { loadConfig, resolveTemplatePath } from "../core/config.js";
5
+ import { parseFrontmatter, stringifyFrontmatter } from "../core/frontmatter.js";
6
+ import { runValidate } from "./validate.js";
7
+ import { runPromote } from "./promote.js";
8
+ function slugify(title) {
9
+ return title
10
+ .toLowerCase()
11
+ .replace(/[^a-z0-9\s-]/g, "")
12
+ .trim()
13
+ .replace(/\s+/g, "-");
14
+ }
15
+ export async function runAdd(options) {
16
+ const vaultRoot = await findVaultRoot(options.startDir);
17
+ const paths = getVaultPaths(vaultRoot);
18
+ const config = await loadConfig(paths.config);
19
+ const type = options.type ?? "insight";
20
+ const templatePath = resolveTemplatePath(config, vaultRoot, type);
21
+ const templateContent = await fs.readFile(templatePath, "utf8");
22
+ const templateParsed = parseFrontmatter(templateContent);
23
+ const templateBody = templateParsed.body;
24
+ const now = new Date();
25
+ const created = now.toISOString().slice(0, 10);
26
+ const frontmatter = {
27
+ description: "",
28
+ type,
29
+ project: [],
30
+ status: "inbox",
31
+ created,
32
+ last_accessed: created,
33
+ access_count: 0,
34
+ };
35
+ const titleLine = `# ${options.title}`;
36
+ const body = templateBody.replace(/# \{[^}]+\}/, titleLine);
37
+ const content = stringifyFrontmatter(frontmatter, body);
38
+ const rawSlug = slugify(options.title);
39
+ const baseSlug = rawSlug || `note-${Date.now()}`;
40
+ let filename = `${baseSlug}.md`;
41
+ let destPath = path.join(paths.inbox, filename);
42
+ let counter = 2;
43
+ while (true) {
44
+ try {
45
+ await fs.access(destPath);
46
+ filename = `${baseSlug}-${counter}.md`;
47
+ destPath = path.join(paths.inbox, filename);
48
+ counter++;
49
+ }
50
+ catch {
51
+ break;
52
+ }
53
+ }
54
+ await fs.writeFile(destPath, content, "utf8");
55
+ const validation = await runValidate({ notePath: destPath });
56
+ const warnings = [...validation.warnings];
57
+ if (!frontmatter.description) {
58
+ warnings.push("Description is empty");
59
+ }
60
+ // Auto-ingest: promote immediately if config.promote.auto is true
61
+ const autoPromote = config.promote?.auto ?? false;
62
+ if (autoPromote) {
63
+ try {
64
+ const promoteResult = await runPromote({
65
+ startDir: options.startDir,
66
+ noteName: filename,
67
+ });
68
+ if (promoteResult.success && promoteResult.data.promoted.length > 0) {
69
+ const promoted = promoteResult.data.promoted[0];
70
+ warnings.push(...promoted.warnings, ...promoted.changes.map((c) => `auto-promote: ${c}`));
71
+ return {
72
+ success: true,
73
+ data: { path: promoted.to, autoPromoted: true },
74
+ warnings,
75
+ };
76
+ }
77
+ }
78
+ catch {
79
+ warnings.push("Auto-promote failed, note remains in inbox");
80
+ }
81
+ }
82
+ return {
83
+ success: true,
84
+ data: { path: destPath },
85
+ warnings,
86
+ };
87
+ }
88
+ //# sourceMappingURL=add.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add.js","sourceRoot":"","sources":["../../src/cli/add.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ export type ArchiveOptions = {
2
+ startDir: string;
3
+ dryRun?: boolean;
4
+ };
5
+ export type ArchivedNote = {
6
+ note: string;
7
+ reason: string;
8
+ daysSinceAccess: number;
9
+ incomingLinks: number;
10
+ };
11
+ export type ArchiveResult = {
12
+ success: boolean;
13
+ data: {
14
+ archived: ArchivedNote[];
15
+ };
16
+ warnings: string[];
17
+ };
18
+ /**
19
+ * Determine if a note should be archived.
20
+ * Old (60d) + isolated (<2 incoming links) = archive candidate.
21
+ * Terminal status (completed/superseded) + 30d grace = archive faster.
22
+ */
23
+ export declare function shouldArchive(frontmatter: Record<string, unknown>, incomingLinkCount: number, now: Date): boolean;
24
+ export declare function runArchive(options: ArchiveOptions): Promise<ArchiveResult>;
25
+ //# sourceMappingURL=archive.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"archive.d.ts","sourceRoot":"","sources":["../../src/cli/archive.ts"],"names":[],"mappings":"AAUA,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE;QACJ,QAAQ,EAAE,YAAY,EAAE,CAAC;KAC1B,CAAC;IACF,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,iBAAiB,EAAE,MAAM,EACzB,GAAG,EAAE,IAAI,GACR,OAAO,CAoBT;AAED,wBAAsB,UAAU,CAC9B,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,aAAa,CAAC,CA+CxB"}
@@ -0,0 +1,69 @@
1
+ import path from "node:path";
2
+ import { findVaultRoot, getVaultPaths, listNoteTitles } from "../core/vault.js";
3
+ import { loadConfig } from "../core/config.js";
4
+ import { readFrontmatterFile, writeFrontmatterFile, } from "../core/frontmatter.js";
5
+ import { buildGraph } from "../core/graph.js";
6
+ import { daysBetween } from "../core/vitality.js";
7
+ /**
8
+ * Determine if a note should be archived.
9
+ * Old (60d) + isolated (<2 incoming links) = archive candidate.
10
+ * Terminal status (completed/superseded) + 30d grace = archive faster.
11
+ */
12
+ export function shouldArchive(frontmatter, incomingLinkCount, now) {
13
+ if (frontmatter.status === "archived")
14
+ return false;
15
+ const lastAccessed = typeof frontmatter.last_accessed === "string"
16
+ ? frontmatter.last_accessed
17
+ : typeof frontmatter.created === "string"
18
+ ? frontmatter.created
19
+ : null;
20
+ if (typeof lastAccessed !== "string")
21
+ return false;
22
+ const accessDate = new Date(lastAccessed);
23
+ if (isNaN(accessDate.getTime()))
24
+ return false;
25
+ const days = daysBetween(accessDate, now);
26
+ const terminal = ["completed", "superseded"].includes(frontmatter.status);
27
+ return (days > 60 && incomingLinkCount < 2) || (terminal && days > 30);
28
+ }
29
+ export async function runArchive(options) {
30
+ const vaultRoot = await findVaultRoot(options.startDir);
31
+ const paths = getVaultPaths(vaultRoot);
32
+ await loadConfig(paths.config); // validate config exists
33
+ const titles = await listNoteTitles(paths.notes);
34
+ const graph = await buildGraph(paths.notes);
35
+ const now = new Date();
36
+ const archived = [];
37
+ for (const title of titles) {
38
+ const filePath = path.join(paths.notes, `${title}.md`);
39
+ const parsed = await readFrontmatterFile(filePath);
40
+ if (!parsed.data)
41
+ continue;
42
+ const incomingLinks = graph.incoming.get(title)?.size ?? 0;
43
+ if (!shouldArchive(parsed.data, incomingLinks, now))
44
+ continue;
45
+ const accessDateStr = typeof parsed.data.last_accessed === "string"
46
+ ? parsed.data.last_accessed
47
+ : parsed.data.created;
48
+ const days = Math.round(daysBetween(new Date(accessDateStr), now));
49
+ const reason = ["completed", "superseded"].includes(parsed.data.status)
50
+ ? `terminal status (${parsed.data.status}) + ${days}d since access`
51
+ : `${days}d since access + ${incomingLinks} incoming link(s)`;
52
+ if (!options.dryRun) {
53
+ parsed.data.status = "archived";
54
+ await writeFrontmatterFile(filePath, parsed.data, parsed.body);
55
+ }
56
+ archived.push({
57
+ note: title,
58
+ reason,
59
+ daysSinceAccess: days,
60
+ incomingLinks,
61
+ });
62
+ }
63
+ return {
64
+ success: true,
65
+ data: { archived },
66
+ warnings: [],
67
+ };
68
+ }
69
+ //# sourceMappingURL=archive.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"archive.js","sourceRoot":"","sources":["../../src/cli/archive.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ export declare function runBridgeClaudeCode(startDir: string): Promise<{
2
+ success: boolean;
3
+ data: {
4
+ claudePath: string;
5
+ hooksDir: string;
6
+ scope: string;
7
+ };
8
+ warnings: never[];
9
+ }>;
10
+ export declare function runBridgeClaudeCodeGlobal(): Promise<{
11
+ success: boolean;
12
+ data: {
13
+ hooksDir: string;
14
+ settingsPath: string;
15
+ scope: string;
16
+ };
17
+ warnings: never[];
18
+ }>;
19
+ //# sourceMappingURL=bridge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../../src/cli/bridge.ts"],"names":[],"mappings":"AAkKA,wBAAsB,mBAAmB,CAAC,QAAQ,EAAE,MAAM;;;;;;;;GA6BzD;AAED,wBAAsB,yBAAyB;;;;;;;;GAe9C"}
@@ -0,0 +1,180 @@
1
+ import path from "node:path";
2
+ import os from "node:os";
3
+ import { promises as fs } from "node:fs";
4
+ import { fileURLToPath } from "node:url";
5
+ const BRIDGE_SENTINEL = "<!-- ori-bridge:claude-code -->";
6
+ const ORI_HOOK_CMD_MARKER = "hooks/ori/";
7
+ const CLAUDE_SNIPPET = `# Ori Mnemos - Claude Code Bridge
8
+
9
+ ## Session Rhythm
10
+ Every session: Orient -> Retrieve -> Work -> Persist
11
+
12
+ ### Orient (always first)
13
+ - Run \`ori status\`
14
+ - Scan vault structure before reading any note
15
+
16
+ ### Retrieve
17
+ - Run \`ori query\` before creating new notes
18
+ - Use progressive disclosure: titles -> descriptions -> full reads
19
+
20
+ ### Capture
21
+ - NEVER write to notes/ directly
22
+ - Use \`ori add\` to write to inbox/
23
+
24
+ ### Verify
25
+ - Run \`ori validate\` on any note you create
26
+
27
+ ### Persist
28
+ - Keep notes atomic and link to maps
29
+ `;
30
+ function localSettings(hooksDir) {
31
+ return {
32
+ hooks: {
33
+ SessionStart: [
34
+ {
35
+ hooks: [
36
+ {
37
+ type: "command",
38
+ command: "node .claude/hooks/orient.mjs",
39
+ timeout: 10,
40
+ },
41
+ ],
42
+ },
43
+ ],
44
+ PostToolUse: [
45
+ {
46
+ matcher: "Write",
47
+ hooks: [
48
+ {
49
+ type: "command",
50
+ command: "node .claude/hooks/validate.mjs",
51
+ timeout: 5,
52
+ },
53
+ ],
54
+ },
55
+ ],
56
+ Stop: [
57
+ {
58
+ hooks: [
59
+ {
60
+ type: "command",
61
+ command: "node .claude/hooks/capture.mjs",
62
+ timeout: 10,
63
+ },
64
+ ],
65
+ },
66
+ ],
67
+ },
68
+ };
69
+ }
70
+ function globalSettings(hooksDir) {
71
+ const orientCmd = `node "${path.join(hooksDir, "orient.mjs")}"`;
72
+ const validateCmd = `node "${path.join(hooksDir, "validate.mjs")}"`;
73
+ const captureCmd = `node "${path.join(hooksDir, "capture.mjs")}"`;
74
+ return {
75
+ hooks: {
76
+ SessionStart: [
77
+ {
78
+ hooks: [{ type: "command", command: orientCmd, timeout: 10 }],
79
+ },
80
+ ],
81
+ PostToolUse: [
82
+ {
83
+ matcher: "Write",
84
+ hooks: [{ type: "command", command: validateCmd, timeout: 5 }],
85
+ },
86
+ ],
87
+ Stop: [
88
+ {
89
+ hooks: [{ type: "command", command: captureCmd, timeout: 10 }],
90
+ },
91
+ ],
92
+ },
93
+ };
94
+ }
95
+ function hookEntryHasOriMarker(entry) {
96
+ if (!entry || typeof entry !== "object")
97
+ return false;
98
+ const hooks = entry.hooks;
99
+ if (!Array.isArray(hooks))
100
+ return false;
101
+ return hooks.some((h) => {
102
+ if (!h || typeof h !== "object")
103
+ return false;
104
+ const cmd = h.command;
105
+ return (typeof cmd === "string" &&
106
+ cmd.replace(/\\/g, "/").includes(ORI_HOOK_CMD_MARKER));
107
+ });
108
+ }
109
+ async function mergeIntoSettingsFile(settingsPath, incoming) {
110
+ let existing = {};
111
+ try {
112
+ const raw = await fs.readFile(settingsPath, "utf8");
113
+ existing = JSON.parse(raw);
114
+ }
115
+ catch {
116
+ // file missing or unparseable - start fresh
117
+ }
118
+ const merged = {
119
+ ...existing,
120
+ hooks: { ...(existing.hooks ?? {}) },
121
+ };
122
+ for (const [event, entries] of Object.entries(incoming.hooks)) {
123
+ const current = (merged.hooks[event] ?? []);
124
+ const alreadyInstalled = current.some(hookEntryHasOriMarker);
125
+ if (!alreadyInstalled) {
126
+ merged.hooks[event] = [...current, ...entries];
127
+ }
128
+ }
129
+ await fs.writeFile(settingsPath, JSON.stringify(merged, null, 2));
130
+ }
131
+ function getAdaptersDir() {
132
+ const __filename = fileURLToPath(import.meta.url);
133
+ const __dirname = path.dirname(__filename);
134
+ return path.resolve(__dirname, "..", "..", "adapters", "claude-code");
135
+ }
136
+ async function copyHooks(adaptersDir, hooksDir) {
137
+ await fs.mkdir(hooksDir, { recursive: true });
138
+ for (const hook of ["orient.mjs", "validate.mjs", "capture.mjs"]) {
139
+ await fs.copyFile(path.join(adaptersDir, "hooks", hook), path.join(hooksDir, hook));
140
+ }
141
+ }
142
+ export async function runBridgeClaudeCode(startDir) {
143
+ const root = path.resolve(startDir);
144
+ const claudeDir = path.join(root, ".claude");
145
+ const hooksDir = path.join(claudeDir, "hooks");
146
+ const adaptersDir = getAdaptersDir();
147
+ await copyHooks(adaptersDir, hooksDir);
148
+ const claudePath = path.join(root, "CLAUDE.md");
149
+ let existing = "";
150
+ try {
151
+ existing = await fs.readFile(claudePath, "utf8");
152
+ }
153
+ catch {
154
+ // file doesn't exist yet
155
+ }
156
+ if (!existing.includes(BRIDGE_SENTINEL)) {
157
+ await fs.appendFile(claudePath, `\n\n${BRIDGE_SENTINEL}\n${CLAUDE_SNIPPET}`);
158
+ }
159
+ await fs.writeFile(path.join(claudeDir, "settings.json"), JSON.stringify(localSettings(hooksDir), null, 2));
160
+ return {
161
+ success: true,
162
+ data: { claudePath, hooksDir, scope: "project" },
163
+ warnings: [],
164
+ };
165
+ }
166
+ export async function runBridgeClaudeCodeGlobal() {
167
+ const homeDir = os.homedir();
168
+ const globalClaudeDir = path.join(homeDir, ".claude");
169
+ const globalHooksDir = path.join(globalClaudeDir, "hooks", "ori");
170
+ const globalSettingsPath = path.join(globalClaudeDir, "settings.json");
171
+ const adaptersDir = getAdaptersDir();
172
+ await copyHooks(adaptersDir, globalHooksDir);
173
+ await mergeIntoSettingsFile(globalSettingsPath, globalSettings(globalHooksDir));
174
+ return {
175
+ success: true,
176
+ data: { hooksDir: globalHooksDir, settingsPath: globalSettingsPath, scope: "global" },
177
+ warnings: [],
178
+ };
179
+ }
180
+ //# sourceMappingURL=bridge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bridge.js","sourceRoot":"","sources":["../../src/cli/bridge.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export type HealthResult = {
2
+ success: boolean;
3
+ data: Record<string, unknown>;
4
+ warnings: string[];
5
+ };
6
+ export declare function runHealth(startDir: string): Promise<HealthResult>;
7
+ //# sourceMappingURL=health.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.d.ts","sourceRoot":"","sources":["../../src/cli/health.ts"],"names":[],"mappings":"AASA,MAAM,MAAM,YAAY,GAAG;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB,CAAC;AAEF,wBAAsB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CA0EvE"}
@@ -0,0 +1,66 @@
1
+ import path from "node:path";
2
+ import { promises as fs } from "node:fs";
3
+ import { findVaultRoot, getVaultPaths, listNoteTitles } from "../core/vault.js";
4
+ import { buildGraph, findDanglingLinks, findOrphans } from "../core/graph.js";
5
+ import { loadConfig, resolveTemplatePath } from "../core/config.js";
6
+ import { validateNoteAgainstSchema } from "../core/schema.js";
7
+ import { parseFrontmatter } from "../core/frontmatter.js";
8
+ import { computeVitality } from "../core/vitality.js";
9
+ export async function runHealth(startDir) {
10
+ const vaultRoot = await findVaultRoot(startDir);
11
+ const paths = getVaultPaths(vaultRoot);
12
+ const config = await loadConfig(paths.config);
13
+ const allNotes = await listNoteTitles(paths.notes);
14
+ const graph = await buildGraph(paths.notes);
15
+ const orphans = findOrphans(graph, allNotes);
16
+ const dangling = findDanglingLinks(graph, allNotes);
17
+ const schemaViolations = [];
18
+ const fading = [];
19
+ for (const note of allNotes) {
20
+ const filePath = path.join(paths.notes, `${note}.md`);
21
+ const content = await fs.readFile(filePath, "utf8");
22
+ const parsed = parseFrontmatter(content);
23
+ const type = parsed.data && typeof parsed.data === "object"
24
+ ? parsed.data["type"]
25
+ : null;
26
+ const templatePath = resolveTemplatePath(config, vaultRoot, typeof type === "string" ? type : null);
27
+ const validation = await validateNoteAgainstSchema(filePath, templatePath);
28
+ if (!validation.valid) {
29
+ schemaViolations.push({ note, errors: validation.errors });
30
+ }
31
+ const dataObj = parsed.data && typeof parsed.data === "object"
32
+ ? parsed.data
33
+ : null;
34
+ const lastAccessedRaw = typeof dataObj?.["last_accessed"] === "string"
35
+ ? dataObj["last_accessed"]
36
+ : typeof dataObj?.["created"] === "string"
37
+ ? dataObj["created"]
38
+ : null;
39
+ if (typeof lastAccessedRaw === "string") {
40
+ const last = new Date(lastAccessedRaw);
41
+ if (!isNaN(last.getTime())) {
42
+ const decayDays = typeof type === "string" && config.vitality.decay[type]
43
+ ? config.vitality.decay[type]
44
+ : 30;
45
+ const vitality = computeVitality({ base: config.vitality.base, decayDays }, last, new Date());
46
+ if (vitality < 0.2) {
47
+ fading.push({ note, vitality });
48
+ }
49
+ }
50
+ }
51
+ }
52
+ return {
53
+ success: true,
54
+ data: {
55
+ noteCount: allNotes.length,
56
+ orphanCount: orphans.length,
57
+ danglingCount: dangling.length,
58
+ orphans,
59
+ dangling,
60
+ schemaViolations,
61
+ fading,
62
+ },
63
+ warnings: [],
64
+ };
65
+ }
66
+ //# sourceMappingURL=health.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.js","sourceRoot":"","sources":["../../src/cli/health.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export type InitOptions = {
2
+ targetDir: string;
3
+ };
4
+ export type InitResult = {
5
+ created: string[];
6
+ skipped: string[];
7
+ };
8
+ export declare function runInit(options: InitOptions): Promise<InitResult>;
9
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,WAAW,GAAG;IACxB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB,CAAC;AAsBF,wBAAsB,OAAO,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAmBvE"}
@@ -0,0 +1,44 @@
1
+ import { promises as fs } from "node:fs";
2
+ import path from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { getVaultPaths } from "../core/vault.js";
5
+ async function copyDir(src, dest, result) {
6
+ await fs.mkdir(dest, { recursive: true });
7
+ const entries = await fs.readdir(src, { withFileTypes: true });
8
+ for (const entry of entries) {
9
+ const srcPath = path.join(src, entry.name);
10
+ const destPath = path.join(dest, entry.name);
11
+ if (entry.isDirectory()) {
12
+ await copyDir(srcPath, destPath, result);
13
+ }
14
+ else {
15
+ try {
16
+ await fs.access(destPath);
17
+ result.skipped.push(destPath);
18
+ }
19
+ catch {
20
+ await fs.copyFile(srcPath, destPath);
21
+ result.created.push(destPath);
22
+ }
23
+ }
24
+ }
25
+ }
26
+ export async function runInit(options) {
27
+ const target = path.resolve(options.targetDir);
28
+ const __filename = fileURLToPath(import.meta.url);
29
+ const __dirname = path.dirname(__filename);
30
+ const scaffoldRoot = path.resolve(__dirname, "..", "..", "scaffold");
31
+ const result = { created: [], skipped: [] };
32
+ await copyDir(scaffoldRoot, target, result);
33
+ // Ensure top-level marker exists
34
+ const paths = getVaultPaths(target);
35
+ try {
36
+ await fs.access(paths.marker);
37
+ }
38
+ catch {
39
+ await fs.writeFile(paths.marker, "");
40
+ result.created.push(paths.marker);
41
+ }
42
+ return result;
43
+ }
44
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAWjD,KAAK,UAAU,OAAO,CAAC,GAAW,EAAE,IAAY,EAAE,MAAkB;IAClE,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1C,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/D,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAC3C,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAC7C,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,MAAM,OAAO,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;QAC3C,CAAC;aAAM,CAAC;YACN,IAAI,CAAC;gBACH,MAAM,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;gBAC1B,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAChC,CAAC;YAAC,MAAM,CAAC;gBACP,MAAM,EAAE,CAAC,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;gBACrC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAChC,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,OAAoB;IAChD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAC/C,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAClD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAC3C,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;IACrE,MAAM,MAAM,GAAe,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IAExD,MAAM,OAAO,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAE5C,iCAAiC;IACjC,MAAM,KAAK,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IACpC,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QACrC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACpC,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,35 @@
1
+ export type PromoteOptions = {
2
+ startDir: string;
3
+ noteName?: string;
4
+ all?: boolean;
5
+ dryRun?: boolean;
6
+ noAuto?: boolean;
7
+ type?: string;
8
+ description?: string;
9
+ links?: string[];
10
+ project?: string[];
11
+ };
12
+ export type PromotedNote = {
13
+ from: string;
14
+ to: string;
15
+ changes: string[];
16
+ warnings: string[];
17
+ validation: {
18
+ valid: boolean;
19
+ errors: string[];
20
+ warnings: string[];
21
+ };
22
+ };
23
+ export type PromoteCommandResult = {
24
+ success: boolean;
25
+ data: {
26
+ promoted: PromotedNote[];
27
+ skipped: Array<{
28
+ path: string;
29
+ reason: string;
30
+ }>;
31
+ };
32
+ warnings: string[];
33
+ };
34
+ export declare function runPromote(options: PromoteOptions): Promise<PromoteCommandResult>;
35
+ //# sourceMappingURL=promote.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"promote.d.ts","sourceRoot":"","sources":["../../src/cli/promote.ts"],"names":[],"mappings":"AAUA,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,UAAU,EAAE;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAC;QAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;CACtE,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE;QACJ,QAAQ,EAAE,YAAY,EAAE,CAAC;QACzB,OAAO,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KAClD,CAAC;IACF,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB,CAAC;AA4DF,wBAAsB,UAAU,CAC9B,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,oBAAoB,CAAC,CAkJ/B"}