@damian87/omp 0.4.1 → 0.5.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 (56) hide show
  1. package/.github/agents/researcher.md +7 -6
  2. package/.github/copilot-instructions.md +23 -0
  3. package/.github/skills/daily-log/SKILL.md +64 -0
  4. package/.github/skills/goal/SKILL.md +33 -0
  5. package/dist/src/cli.js +190 -9
  6. package/dist/src/cli.js.map +1 -1
  7. package/dist/src/comms/index.d.ts +116 -0
  8. package/dist/src/comms/index.js +258 -0
  9. package/dist/src/comms/index.js.map +1 -0
  10. package/dist/src/comms/resolve-session.d.ts +35 -0
  11. package/dist/src/comms/resolve-session.js +53 -0
  12. package/dist/src/comms/resolve-session.js.map +1 -0
  13. package/dist/src/daily-log.d.ts +18 -0
  14. package/dist/src/daily-log.js +138 -0
  15. package/dist/src/daily-log.js.map +1 -0
  16. package/dist/src/goal.d.ts +4 -0
  17. package/dist/src/goal.js +44 -0
  18. package/dist/src/goal.js.map +1 -0
  19. package/dist/src/instructions-memory.d.ts +9 -0
  20. package/dist/src/instructions-memory.js +72 -0
  21. package/dist/src/instructions-memory.js.map +1 -0
  22. package/dist/src/mcp/tools/daily-log.d.ts +2 -0
  23. package/dist/src/mcp/tools/daily-log.js +148 -0
  24. package/dist/src/mcp/tools/daily-log.js.map +1 -0
  25. package/dist/src/omp-root.d.ts +1 -0
  26. package/dist/src/omp-root.js +19 -0
  27. package/dist/src/omp-root.js.map +1 -0
  28. package/dist/src/project-memory.d.ts +13 -0
  29. package/dist/src/project-memory.js +105 -0
  30. package/dist/src/project-memory.js.map +1 -0
  31. package/dist/src/state.d.ts +17 -0
  32. package/dist/src/state.js +101 -0
  33. package/dist/src/state.js.map +1 -0
  34. package/dist/src/trace.d.ts +19 -0
  35. package/dist/src/trace.js +74 -0
  36. package/dist/src/trace.js.map +1 -0
  37. package/dist/test/catalog.test.d.ts +1 -0
  38. package/dist/test/catalog.test.js +21 -0
  39. package/dist/test/catalog.test.js.map +1 -0
  40. package/dist/test/jira.test.d.ts +1 -0
  41. package/dist/test/jira.test.js +26 -0
  42. package/dist/test/jira.test.js.map +1 -0
  43. package/dist/test/lint.test.d.ts +1 -0
  44. package/dist/test/lint.test.js +9 -0
  45. package/dist/test/lint.test.js.map +1 -0
  46. package/dist/test/sync.test.d.ts +1 -0
  47. package/dist/test/sync.test.js +15 -0
  48. package/dist/test/sync.test.js.map +1 -0
  49. package/package.json +1 -1
  50. package/scripts/lib/daily-log.mjs +155 -0
  51. package/scripts/lib/hook-output.mjs +2 -1
  52. package/scripts/lib/omp-root.mjs +15 -0
  53. package/scripts/lib/project-memory.mjs +21 -0
  54. package/scripts/prompt-submit.mjs +14 -2
  55. package/scripts/session-end.mjs +6 -1
  56. package/scripts/session-start.mjs +52 -2
@@ -0,0 +1,44 @@
1
+ import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { ompRoot } from "./omp-root.js";
4
+ // The repo's durable objective ("what we want to achieve in this repo"), stored
5
+ // once per project at .omp/goal.md — distinct from a daily log's per-day goal.
6
+ // Exposed through the `omp goal` CLI subcommands (NOT MCP), so the project dir
7
+ // is the CLI's cwd and never ambiguous.
8
+ function goalFile(cwd) {
9
+ return join(ompRoot(cwd), ".omp", "goal.md");
10
+ }
11
+ // Strip ONLY our own serialized `# Repo Goal` header (not any heading), so a
12
+ // hand-authored objective — even one that starts with `#` — is never lost.
13
+ function parseGoal(text) {
14
+ const noBom = text.charCodeAt(0) === 0xfeff ? text.slice(1) : text;
15
+ const lines = noBom.split("\n");
16
+ if (/^#\s+Repo Goal\s*$/i.test(lines[0] ?? ""))
17
+ lines.shift();
18
+ return lines.join("\n").trim();
19
+ }
20
+ /** The repo objective, or "" when unset. */
21
+ export function readRepoGoal(cwd) {
22
+ const p = goalFile(cwd);
23
+ if (!existsSync(p))
24
+ return "";
25
+ try {
26
+ return parseGoal(readFileSync(p, "utf8"));
27
+ }
28
+ catch {
29
+ return "";
30
+ }
31
+ }
32
+ /** Set/replace the repo objective (collapsed to one north-star line). */
33
+ export function writeRepoGoal(cwd, goal) {
34
+ const clean = String(goal ?? "")
35
+ .replace(/\s*\n\s*/g, " ")
36
+ .trim();
37
+ const p = goalFile(cwd);
38
+ mkdirSync(dirname(p), { recursive: true });
39
+ const tmp = `${p}.tmp.${process.pid}.${Date.now()}`;
40
+ writeFileSync(tmp, `# Repo Goal\n\n${clean}\n`, "utf8");
41
+ renameSync(tmp, p);
42
+ return clean;
43
+ }
44
+ //# sourceMappingURL=goal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"goal.js","sourceRoot":"","sources":["../../src/goal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACzF,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAExC,gFAAgF;AAChF,+EAA+E;AAC/E,+EAA+E;AAC/E,wCAAwC;AACxC,SAAS,QAAQ,CAAC,GAAW;IAC3B,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC;AAC/C,CAAC;AAED,6EAA6E;AAC7E,2EAA2E;AAC3E,SAAS,SAAS,CAAC,IAAY;IAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACnE,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAChC,IAAI,qBAAqB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAAE,KAAK,CAAC,KAAK,EAAE,CAAC;IAC9D,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;AACjC,CAAC;AAED,4CAA4C;AAC5C,MAAM,UAAU,YAAY,CAAC,GAAW;IACtC,MAAM,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;IACxB,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IAC9B,IAAI,CAAC;QACH,OAAO,SAAS,CAAC,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,aAAa,CAAC,GAAW,EAAE,IAAY;IACrD,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;SAC7B,OAAO,CAAC,WAAW,EAAE,GAAG,CAAC;SACzB,IAAI,EAAE,CAAC;IACV,MAAM,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;IACxB,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3C,MAAM,GAAG,GAAG,GAAG,CAAC,QAAQ,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;IACpD,aAAa,CAAC,GAAG,EAAE,kBAAkB,KAAK,IAAI,EAAE,MAAM,CAAC,CAAC;IACxD,UAAU,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;IACnB,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Write/refresh the managed memory block in .github/copilot-instructions.md so
3
+ * Copilot surfaces it every session. Creates the file if absent. Returns the
4
+ * path and whether a block was written. Best-effort; never throws.
5
+ */
6
+ export declare function syncInstructionsMemory(cwd: string): {
7
+ path: string;
8
+ wrote: boolean;
9
+ };
@@ -0,0 +1,72 @@
1
+ import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { ompRoot } from "./omp-root.js";
4
+ import { readRepoGoal } from "./goal.js";
5
+ import { readDirectives, noteIndex } from "./project-memory.js";
6
+ // Copilot CLI does not execute plugin lifecycle hooks (verified: neither
7
+ // SessionStart nor UserPromptSubmit fire), so we can't inject memory via hooks.
8
+ // Copilot DOES read .github/copilot-instructions.md, so we render the always-on
9
+ // memory (repo goal + directives) into a managed block there. The block is
10
+ // refreshed whenever goal/directives/notes change, so it appears every session.
11
+ const START = "<!-- omp:memory:start -->";
12
+ const END = "<!-- omp:memory:end -->";
13
+ const MAX_DIRECTIVES = 20;
14
+ function instructionsPath(cwd) {
15
+ return join(ompRoot(cwd), ".github", "copilot-instructions.md");
16
+ }
17
+ function renderBlock(cwd) {
18
+ const goal = readRepoGoal(cwd);
19
+ const directives = readDirectives(cwd);
20
+ const notes = noteIndex(cwd);
21
+ const lines = [START, "## Active memory (managed by omp — do not edit between these markers)"];
22
+ if (goal)
23
+ lines.push("", `**Repo goal:** ${goal}`);
24
+ if (directives.length > 0) {
25
+ lines.push("", "**Directives — must follow this session:**");
26
+ for (const d of directives.slice(0, MAX_DIRECTIVES))
27
+ lines.push(`- ${d}`);
28
+ if (directives.length > MAX_DIRECTIVES)
29
+ lines.push(`- (+${directives.length - MAX_DIRECTIVES} more — \`omp project-memory read\`)`);
30
+ }
31
+ lines.push("", `**On demand:** \`omp project-memory index\` (${notes.length} note${notes.length === 1 ? "" : "s"}) · \`omp project-memory read <id>\` · \`omp daily-log read\``, END);
32
+ return lines.join("\n");
33
+ }
34
+ /**
35
+ * Write/refresh the managed memory block in .github/copilot-instructions.md so
36
+ * Copilot surfaces it every session. Creates the file if absent. Returns the
37
+ * path and whether a block was written. Best-effort; never throws.
38
+ */
39
+ export function syncInstructionsMemory(cwd) {
40
+ const p = instructionsPath(cwd);
41
+ const block = renderBlock(cwd);
42
+ try {
43
+ const content = existsSync(p) ? readFileSync(p, "utf8") : "";
44
+ const starts = content.split(START).length - 1;
45
+ const ends = content.split(END).length - 1;
46
+ let next;
47
+ if (starts === 1 && ends === 1) {
48
+ const s = content.indexOf(START);
49
+ const e = content.indexOf(END);
50
+ if (e <= s)
51
+ return { path: p, wrote: false }; // markers out of order — don't risk a clobber
52
+ next = content.slice(0, s) + block + content.slice(e + END.length);
53
+ }
54
+ else if (starts === 0 && ends === 0) {
55
+ next = content.trim() === "" ? `# oh-my-copilot\n\n${block}\n` : `${content.trimEnd()}\n\n${block}\n`;
56
+ }
57
+ else {
58
+ // Orphan or duplicate markers = corrupt managed region. Fail closed rather
59
+ // than risk replacing user content between mismatched markers.
60
+ return { path: p, wrote: false };
61
+ }
62
+ mkdirSync(dirname(p), { recursive: true });
63
+ const tmp = `${p}.tmp.${process.pid}.${Date.now()}`;
64
+ writeFileSync(tmp, next, "utf8");
65
+ renameSync(tmp, p);
66
+ return { path: p, wrote: true };
67
+ }
68
+ catch {
69
+ return { path: p, wrote: false };
70
+ }
71
+ }
72
+ //# sourceMappingURL=instructions-memory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instructions-memory.js","sourceRoot":"","sources":["../../src/instructions-memory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { type ToolDefinition } from "../types.js";
2
+ export declare const dailyLogTools: ToolDefinition[];
@@ -0,0 +1,148 @@
1
+ import { existsSync, mkdirSync, readdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
2
+ import { dirname, join, resolve } from "node:path";
3
+ import { jsonResult, textResult } from "../types.js";
4
+ const DAY_FILE_RE = /^\d{4}-\d{2}-\d{2}\.md$/;
5
+ const READ_CHAR_BUDGET = 4000;
6
+ function pad(n) {
7
+ return String(n).padStart(2, "0");
8
+ }
9
+ function todayStr(d = new Date()) {
10
+ return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
11
+ }
12
+ function timeStr(d = new Date()) {
13
+ return `${pad(d.getHours())}:${pad(d.getMinutes())}`;
14
+ }
15
+ function dailyDir(cwd) {
16
+ return join(resolve(cwd), ".omp", "memory", "daily");
17
+ }
18
+ function dayFile(cwd, date = todayStr()) {
19
+ return join(dailyDir(cwd), `${date}.md`);
20
+ }
21
+ function parseDay(text) {
22
+ let section = null;
23
+ const goalLines = [];
24
+ const log = [];
25
+ for (const line of text.split("\n")) {
26
+ if (/^#\s+/.test(line))
27
+ continue;
28
+ if (/^##\s+Goal\s*$/i.test(line)) {
29
+ section = "goal";
30
+ continue;
31
+ }
32
+ if (/^##\s+Log\s*$/i.test(line)) {
33
+ section = "log";
34
+ continue;
35
+ }
36
+ if (section === "goal")
37
+ goalLines.push(line);
38
+ // Preserve any non-empty line a user may have hand-written, verbatim (bullets,
39
+ // prose, indented sub-notes). Only blank spacer lines are dropped on round-trip.
40
+ else if (section === "log" && line.trim() !== "")
41
+ log.push(line);
42
+ }
43
+ return { goal: goalLines.join("\n").trim(), log };
44
+ }
45
+ function serializeDay(date, doc) {
46
+ const parts = [`# ${date}`, "", "## Goal", doc.goal.trim(), "", "## Log", ...doc.log];
47
+ return `${parts.join("\n").replace(/\n+$/, "")}\n`;
48
+ }
49
+ function readDay(cwd, date = todayStr()) {
50
+ const p = dayFile(cwd, date);
51
+ if (!existsSync(p))
52
+ return { goal: "", log: [] };
53
+ try {
54
+ return parseDay(readFileSync(p, "utf8"));
55
+ }
56
+ catch {
57
+ return { goal: "", log: [] };
58
+ }
59
+ }
60
+ function writeDay(cwd, doc, date = todayStr()) {
61
+ const p = dayFile(cwd, date);
62
+ mkdirSync(dirname(p), { recursive: true });
63
+ const tmp = `${p}.tmp.${process.pid}.${Date.now()}`;
64
+ writeFileSync(tmp, serializeDay(date, doc), "utf8");
65
+ renameSync(tmp, p);
66
+ }
67
+ function readRecent(cwd, days) {
68
+ const dir = dailyDir(cwd);
69
+ if (!existsSync(dir))
70
+ return "";
71
+ const files = readdirSync(dir)
72
+ .filter((f) => DAY_FILE_RE.test(f))
73
+ .sort()
74
+ .reverse()
75
+ .slice(0, Math.max(0, days) + 1);
76
+ let out = "";
77
+ for (const f of files) {
78
+ try {
79
+ out += `${readFileSync(join(dir, f), "utf8").trim()}\n\n`;
80
+ }
81
+ catch {
82
+ // skip unreadable day file
83
+ }
84
+ if (out.length > READ_CHAR_BUDGET) {
85
+ out = `${out.slice(0, READ_CHAR_BUDGET)}\n…(truncated)`;
86
+ break;
87
+ }
88
+ }
89
+ return out.trim();
90
+ }
91
+ export const dailyLogTools = [
92
+ {
93
+ name: "daily_log_set_goal",
94
+ category: "daily_log",
95
+ description: "Set/replace today's Goal in .omp/memory/daily/<today>.md.",
96
+ inputSchema: {
97
+ type: "object",
98
+ properties: { goal: { type: "string" }, cwd: { type: "string" } },
99
+ required: ["goal"],
100
+ },
101
+ handler: (args) => {
102
+ const cwd = args.cwd ?? process.cwd();
103
+ const doc = readDay(cwd);
104
+ doc.goal = String(args.goal ?? "");
105
+ writeDay(cwd, doc);
106
+ return jsonResult({ ok: true, date: todayStr(), goal: doc.goal });
107
+ },
108
+ },
109
+ {
110
+ name: "daily_log_add",
111
+ category: "daily_log",
112
+ description: "Append a timestamped entry to today's Log in .omp/memory/daily/<today>.md.",
113
+ inputSchema: {
114
+ type: "object",
115
+ properties: { text: { type: "string" }, cwd: { type: "string" } },
116
+ required: ["text"],
117
+ },
118
+ handler: (args) => {
119
+ const cwd = args.cwd ?? process.cwd();
120
+ // Collapse to a single line so an entry can never contain a `## Goal`/`## Log`
121
+ // marker that parseDay would later misread as a section boundary.
122
+ const text = String(args.text ?? "")
123
+ .replace(/\s*\n\s*/g, " ")
124
+ .trim();
125
+ if (!text)
126
+ return jsonResult({ ok: false, error: "text is required" });
127
+ const doc = readDay(cwd);
128
+ doc.log.push(`- ${timeStr()} — ${text}`);
129
+ writeDay(cwd, doc);
130
+ return jsonResult({ ok: true, date: todayStr(), count: doc.log.length });
131
+ },
132
+ },
133
+ {
134
+ name: "daily_log_read",
135
+ category: "daily_log",
136
+ description: "Read the daily log for today plus the previous `days` days (default 1). Char-capped to ~4KB.",
137
+ inputSchema: {
138
+ type: "object",
139
+ properties: { days: { type: "number" }, cwd: { type: "string" } },
140
+ },
141
+ handler: (args) => {
142
+ const cwd = args.cwd ?? process.cwd();
143
+ const days = typeof args.days === "number" ? args.days : 1;
144
+ return textResult(readRecent(cwd, days) || "(no daily log entries)");
145
+ },
146
+ },
147
+ ];
148
+ //# sourceMappingURL=daily-log.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daily-log.js","sourceRoot":"","sources":["../../../../src/mcp/tools/daily-log.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function ompRoot(start: string): string;
@@ -0,0 +1,19 @@
1
+ import { existsSync } from "node:fs";
2
+ import { dirname, join, resolve } from "node:path";
3
+ // Resolve the project root for .omp storage: walk up from `start` to the nearest
4
+ // project marker (.git, then package.json), so memory is scoped to the actual
5
+ // project even when omp is run from a nested directory or a parent workspace.
6
+ // Falls back to `start` when no marker is found. Used by every .omp path so the
7
+ // CLI and hooks agree on one location per project.
8
+ export function ompRoot(start) {
9
+ let dir = resolve(start);
10
+ while (true) {
11
+ if (existsSync(join(dir, ".git")) || existsSync(join(dir, "package.json")))
12
+ return dir;
13
+ const parent = dirname(dir);
14
+ if (parent === dir)
15
+ return resolve(start);
16
+ dir = parent;
17
+ }
18
+ }
19
+ //# sourceMappingURL=omp-root.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"omp-root.js","sourceRoot":"","sources":["../../src/omp-root.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEnD,iFAAiF;AACjF,8EAA8E;AAC9E,8EAA8E;AAC9E,gFAAgF;AAChF,mDAAmD;AACnD,MAAM,UAAU,OAAO,CAAC,KAAa;IACnC,IAAI,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;IACzB,OAAO,IAAI,EAAE,CAAC;QACZ,IAAI,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;YAAE,OAAO,GAAG,CAAC;QACvF,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;QAC5B,IAAI,MAAM,KAAK,GAAG;YAAE,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC;QAC1C,GAAG,GAAG,MAAM,CAAC;IACf,CAAC;AACH,CAAC"}
@@ -0,0 +1,13 @@
1
+ export declare function readDirectives(cwd: string): string[];
2
+ /** Append a must-follow directive; returns the new directive count. */
3
+ export declare function addDirective(cwd: string, directive: string): number;
4
+ export interface NoteMeta {
5
+ id: string;
6
+ title: string;
7
+ }
8
+ /** Create a note (title + optional body); returns its id (slug, deduped). */
9
+ export declare function addNote(cwd: string, title: string, body?: string): string;
10
+ /** Cheap index of (id, title) — the only thing surfaced; bodies stay on disk. */
11
+ export declare function noteIndex(cwd: string): NoteMeta[];
12
+ /** Full note body by id, or null when missing. */
13
+ export declare function readNote(cwd: string, id: string): string | null;
@@ -0,0 +1,105 @@
1
+ import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, writeFileSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { ompRoot } from "./omp-root.js";
4
+ function memPath(cwd) {
5
+ return join(ompRoot(cwd), ".omp", "project-memory.json");
6
+ }
7
+ function notesDir(cwd) {
8
+ return join(ompRoot(cwd), ".omp", "memory", "notes");
9
+ }
10
+ // --- directives (rules, injected at session start) ---
11
+ function readMem(cwd) {
12
+ const p = memPath(cwd);
13
+ if (!existsSync(p))
14
+ return { directives: [], updatedAt: new Date(0).toISOString() };
15
+ try {
16
+ const data = JSON.parse(readFileSync(p, "utf8"));
17
+ return {
18
+ directives: Array.isArray(data?.directives) ? data.directives : [],
19
+ updatedAt: typeof data?.updatedAt === "string" ? data.updatedAt : new Date(0).toISOString(),
20
+ };
21
+ }
22
+ catch {
23
+ return { directives: [], updatedAt: new Date(0).toISOString() };
24
+ }
25
+ }
26
+ function writeMem(cwd, mem) {
27
+ const p = memPath(cwd);
28
+ mkdirSync(dirname(p), { recursive: true });
29
+ const tmp = `${p}.tmp.${process.pid}.${Date.now()}`;
30
+ writeFileSync(tmp, JSON.stringify({ directives: mem.directives, updatedAt: new Date().toISOString() }, null, 2), "utf8");
31
+ renameSync(tmp, p);
32
+ }
33
+ export function readDirectives(cwd) {
34
+ return readMem(cwd).directives;
35
+ }
36
+ /** Append a must-follow directive; returns the new directive count. */
37
+ export function addDirective(cwd, directive) {
38
+ const mem = readMem(cwd);
39
+ mem.directives.push(String(directive).trim());
40
+ writeMem(cwd, mem);
41
+ return mem.directives.length;
42
+ }
43
+ function slugify(title) {
44
+ return (String(title)
45
+ .toLowerCase()
46
+ .replace(/[^a-z0-9]+/g, "-")
47
+ .replace(/^-+|-+$/g, "")
48
+ .slice(0, 50) || "note");
49
+ }
50
+ /** Create a note (title + optional body); returns its id (slug, deduped). */
51
+ export function addNote(cwd, title, body) {
52
+ const dir = notesDir(cwd);
53
+ mkdirSync(dir, { recursive: true });
54
+ const base = slugify(title);
55
+ let id = base;
56
+ let n = 1;
57
+ while (existsSync(join(dir, `${id}.md`))) {
58
+ n += 1;
59
+ id = `${base}-${n}`;
60
+ }
61
+ const content = `# ${String(title).trim()}\n${body ? `\n${String(body).trim()}\n` : ""}`;
62
+ const p = join(dir, `${id}.md`);
63
+ const tmp = `${p}.tmp.${process.pid}.${Date.now()}`;
64
+ writeFileSync(tmp, content, "utf8");
65
+ renameSync(tmp, p);
66
+ return id;
67
+ }
68
+ /** Cheap index of (id, title) — the only thing surfaced; bodies stay on disk. */
69
+ export function noteIndex(cwd) {
70
+ const dir = notesDir(cwd);
71
+ if (!existsSync(dir))
72
+ return [];
73
+ return readdirSync(dir)
74
+ .filter((f) => f.endsWith(".md"))
75
+ .map((f) => {
76
+ const id = f.replace(/\.md$/, "");
77
+ let title = id;
78
+ try {
79
+ const first = readFileSync(join(dir, f), "utf8").split("\n")[0] ?? "";
80
+ title = first.replace(/^#\s*/, "").trim() || id;
81
+ }
82
+ catch {
83
+ // keep id as title
84
+ }
85
+ return { id, title };
86
+ })
87
+ .sort((a, b) => a.id.localeCompare(b.id));
88
+ }
89
+ /** Full note body by id, or null when missing. */
90
+ export function readNote(cwd, id) {
91
+ // Ids are slugs ([a-z0-9-]); reject anything else so a crafted id can't
92
+ // escape the notes dir via path traversal (e.g. "../../README").
93
+ if (!/^[a-z0-9-]+$/i.test(id))
94
+ return null;
95
+ const p = join(notesDir(cwd), `${id}.md`);
96
+ if (!existsSync(p))
97
+ return null;
98
+ try {
99
+ return readFileSync(p, "utf8").trim();
100
+ }
101
+ catch {
102
+ return null;
103
+ }
104
+ }
105
+ //# sourceMappingURL=project-memory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-memory.js","sourceRoot":"","sources":["../../src/project-memory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /** Write a value under a key, with an optional TTL in seconds. Returns expiresAt. */
2
+ export declare function stateWrite(cwd: string, key: string, value: unknown, ttlSeconds?: number): string | undefined;
3
+ /** Read a value. Returns { value: null } when missing; auto-deletes if expired. */
4
+ export declare function stateRead(cwd: string, key: string): {
5
+ value: unknown;
6
+ expired?: boolean;
7
+ };
8
+ export declare function stateDelete(cwd: string, key: string): void;
9
+ /** List live (non-expired) keys. */
10
+ export declare function stateList(cwd: string): string[];
11
+ /** Delete all expired entries; returns the count removed. */
12
+ export declare function stateCleanup(cwd: string): number;
13
+ export declare function stateStatus(cwd: string, key: string): {
14
+ exists: boolean;
15
+ mtime?: string;
16
+ bytes?: number;
17
+ };
@@ -0,0 +1,101 @@
1
+ import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, statSync, unlinkSync, writeFileSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { ompRoot } from "./omp-root.js";
4
+ function kvDir(cwd) {
5
+ return join(ompRoot(cwd), ".omp", "state", "kv");
6
+ }
7
+ function kvPath(cwd, key) {
8
+ if (!/^[\w.-]+$/.test(key))
9
+ throw new Error(`invalid key: ${key}`);
10
+ return join(kvDir(cwd), `${key}.json`);
11
+ }
12
+ /** Write a value under a key, with an optional TTL in seconds. Returns expiresAt. */
13
+ export function stateWrite(cwd, key, value, ttlSeconds) {
14
+ const entry = {
15
+ value,
16
+ writtenAt: new Date().toISOString(),
17
+ expiresAt: ttlSeconds != null ? new Date(Date.now() + ttlSeconds * 1000).toISOString() : undefined,
18
+ };
19
+ const path = kvPath(cwd, key);
20
+ mkdirSync(dirname(path), { recursive: true });
21
+ const tmp = `${path}.tmp.${process.pid}.${Date.now()}`;
22
+ writeFileSync(tmp, JSON.stringify(entry, null, 2), "utf8");
23
+ renameSync(tmp, path);
24
+ return entry.expiresAt;
25
+ }
26
+ /** Read a value. Returns { value: null } when missing; auto-deletes if expired. */
27
+ export function stateRead(cwd, key) {
28
+ const path = kvPath(cwd, key);
29
+ if (!existsSync(path))
30
+ return { value: null };
31
+ try {
32
+ const entry = JSON.parse(readFileSync(path, "utf8"));
33
+ if (entry.expiresAt && Date.parse(entry.expiresAt) < Date.now()) {
34
+ unlinkSync(path);
35
+ return { value: null, expired: true };
36
+ }
37
+ return { value: entry.value };
38
+ }
39
+ catch {
40
+ return { value: null };
41
+ }
42
+ }
43
+ export function stateDelete(cwd, key) {
44
+ const path = kvPath(cwd, key);
45
+ if (existsSync(path))
46
+ unlinkSync(path);
47
+ }
48
+ /** List live (non-expired) keys. */
49
+ export function stateList(cwd) {
50
+ const dir = kvDir(cwd);
51
+ if (!existsSync(dir))
52
+ return [];
53
+ const now = Date.now();
54
+ const keys = [];
55
+ for (const f of readdirSync(dir)) {
56
+ if (!f.endsWith(".json"))
57
+ continue;
58
+ try {
59
+ const entry = JSON.parse(readFileSync(join(dir, f), "utf8"));
60
+ if (entry.expiresAt && Date.parse(entry.expiresAt) < now)
61
+ continue;
62
+ keys.push(f.replace(/\.json$/, ""));
63
+ }
64
+ catch {
65
+ // skip unparseable
66
+ }
67
+ }
68
+ return keys.sort();
69
+ }
70
+ /** Delete all expired entries; returns the count removed. */
71
+ export function stateCleanup(cwd) {
72
+ const dir = kvDir(cwd);
73
+ if (!existsSync(dir))
74
+ return 0;
75
+ const now = Date.now();
76
+ let deleted = 0;
77
+ for (const f of readdirSync(dir)) {
78
+ if (!f.endsWith(".json"))
79
+ continue;
80
+ const path = join(dir, f);
81
+ try {
82
+ const entry = JSON.parse(readFileSync(path, "utf8"));
83
+ if (entry.expiresAt && Date.parse(entry.expiresAt) < now) {
84
+ unlinkSync(path);
85
+ deleted++;
86
+ }
87
+ }
88
+ catch {
89
+ // skip
90
+ }
91
+ }
92
+ return deleted;
93
+ }
94
+ export function stateStatus(cwd, key) {
95
+ const path = kvPath(cwd, key);
96
+ if (!existsSync(path))
97
+ return { exists: false };
98
+ const s = statSync(path);
99
+ return { exists: true, mtime: s.mtime.toISOString(), bytes: s.size };
100
+ }
101
+ //# sourceMappingURL=state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.js","sourceRoot":"","sources":["../../src/state.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ interface TraceEntry {
2
+ ts: string;
3
+ sessionId?: string;
4
+ event?: string;
5
+ payload?: unknown;
6
+ }
7
+ export declare function appendTraceEntry(cwd: string, sessionId: string, entry: Omit<TraceEntry, "ts" | "sessionId">): void;
8
+ /** Last `limit` entries of a session (default 50; most recent session if omitted). */
9
+ export declare function traceTimeline(cwd: string, sessionId?: string, limit?: number): {
10
+ sessionId?: string;
11
+ entries: TraceEntry[];
12
+ };
13
+ /** Event-name counts for a session. */
14
+ export declare function traceSummary(cwd: string, sessionId?: string): {
15
+ sessionId?: string;
16
+ total: number;
17
+ counts: Record<string, number>;
18
+ };
19
+ export {};