@damian87/omp 0.4.0 → 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 (59) 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/.github/skills/weighted-consensus/SKILL.md +12 -4
  6. package/README.md +16 -0
  7. package/dist/src/cli.js +198 -10
  8. package/dist/src/cli.js.map +1 -1
  9. package/dist/src/comms/index.d.ts +116 -0
  10. package/dist/src/comms/index.js +258 -0
  11. package/dist/src/comms/index.js.map +1 -0
  12. package/dist/src/comms/resolve-session.d.ts +35 -0
  13. package/dist/src/comms/resolve-session.js +53 -0
  14. package/dist/src/comms/resolve-session.js.map +1 -0
  15. package/dist/src/council/config.d.ts +1 -0
  16. package/dist/src/council/config.js +5 -0
  17. package/dist/src/council/config.js.map +1 -1
  18. package/dist/src/council/engine.d.ts +2 -0
  19. package/dist/src/council/engine.js +26 -3
  20. package/dist/src/council/engine.js.map +1 -1
  21. package/dist/src/council/index.d.ts +1 -1
  22. package/dist/src/council/index.js.map +1 -1
  23. package/dist/src/council/prompts.js +0 -1
  24. package/dist/src/council/prompts.js.map +1 -1
  25. package/dist/src/council/synth.js +1 -1
  26. package/dist/src/council/synth.js.map +1 -1
  27. package/dist/src/council/types.d.ts +2 -0
  28. package/dist/src/daily-log.d.ts +18 -0
  29. package/dist/src/daily-log.js +138 -0
  30. package/dist/src/daily-log.js.map +1 -0
  31. package/dist/src/goal.d.ts +4 -0
  32. package/dist/src/goal.js +44 -0
  33. package/dist/src/goal.js.map +1 -0
  34. package/dist/src/instructions-memory.d.ts +9 -0
  35. package/dist/src/instructions-memory.js +72 -0
  36. package/dist/src/instructions-memory.js.map +1 -0
  37. package/dist/src/mcp/tools/daily-log.d.ts +2 -0
  38. package/dist/src/mcp/tools/daily-log.js +148 -0
  39. package/dist/src/mcp/tools/daily-log.js.map +1 -0
  40. package/dist/src/omp-root.d.ts +1 -0
  41. package/dist/src/omp-root.js +19 -0
  42. package/dist/src/omp-root.js.map +1 -0
  43. package/dist/src/project-memory.d.ts +13 -0
  44. package/dist/src/project-memory.js +105 -0
  45. package/dist/src/project-memory.js.map +1 -0
  46. package/dist/src/state.d.ts +17 -0
  47. package/dist/src/state.js +101 -0
  48. package/dist/src/state.js.map +1 -0
  49. package/dist/src/trace.d.ts +19 -0
  50. package/dist/src/trace.js +74 -0
  51. package/dist/src/trace.js.map +1 -0
  52. package/package.json +3 -1
  53. package/scripts/lib/daily-log.mjs +155 -0
  54. package/scripts/lib/hook-output.mjs +2 -1
  55. package/scripts/lib/omp-root.mjs +15 -0
  56. package/scripts/lib/project-memory.mjs +21 -0
  57. package/scripts/prompt-submit.mjs +14 -2
  58. package/scripts/session-end.mjs +6 -1
  59. package/scripts/session-start.mjs +52 -2
@@ -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":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,QAAQ,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC5H,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAYxC,SAAS,KAAK,CAAC,GAAW;IACxB,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;AACnD,CAAC;AAED,SAAS,MAAM,CAAC,GAAW,EAAE,GAAW;IACtC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,gBAAgB,GAAG,EAAE,CAAC,CAAC;IACnE,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,CAAC;AACzC,CAAC;AAED,qFAAqF;AACrF,MAAM,UAAU,UAAU,CAAC,GAAW,EAAE,GAAW,EAAE,KAAc,EAAE,UAAmB;IACtF,MAAM,KAAK,GAAU;QACnB,KAAK;QACL,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,SAAS,EAAE,UAAU,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,UAAU,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,SAAS;KACnG,CAAC;IACF,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAC9B,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9C,MAAM,GAAG,GAAG,GAAG,IAAI,QAAQ,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;IACvD,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IAC3D,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACtB,OAAO,KAAK,CAAC,SAAS,CAAC;AACzB,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,SAAS,CAAC,GAAW,EAAE,GAAW;IAChD,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAC9B,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IAC9C,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAU,CAAC;QAC9D,IAAI,KAAK,CAAC,SAAS,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;YAChE,UAAU,CAAC,IAAI,CAAC,CAAC;YACjB,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QACxC,CAAC;QACD,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IACzB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,GAAW,EAAE,GAAW;IAClD,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAC9B,IAAI,UAAU,CAAC,IAAI,CAAC;QAAE,UAAU,CAAC,IAAI,CAAC,CAAC;AACzC,CAAC;AAED,oCAAoC;AACpC,MAAM,UAAU,SAAS,CAAC,GAAW;IACnC,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;IACvB,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,CAAC;IAChC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,KAAK,MAAM,CAAC,IAAI,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;QACjC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC;YAAE,SAAS;QACnC,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,CAAU,CAAC;YACtE,IAAI,KAAK,CAAC,SAAS,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,GAAG;gBAAE,SAAS;YACnE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,CAAC;QACtC,CAAC;QAAC,MAAM,CAAC;YACP,mBAAmB;QACrB,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC;AACrB,CAAC;AAED,6DAA6D;AAC7D,MAAM,UAAU,YAAY,CAAC,GAAW;IACtC,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;IACvB,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,CAAC,CAAC;IAC/B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,KAAK,MAAM,CAAC,IAAI,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;QACjC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC;YAAE,SAAS;QACnC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QAC1B,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAU,CAAC;YAC9D,IAAI,KAAK,CAAC,SAAS,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,GAAG,EAAE,CAAC;gBACzD,UAAU,CAAC,IAAI,CAAC,CAAC;gBACjB,OAAO,EAAE,CAAC;YACZ,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,OAAO;QACT,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,GAAW,EAAE,GAAW;IAClD,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAC9B,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IAChD,MAAM,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IACzB,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;AACvE,CAAC"}
@@ -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 {};
@@ -0,0 +1,74 @@
1
+ import { appendFileSync, existsSync, mkdirSync, readFileSync, readdirSync, statSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { ompRoot } from "./omp-root.js";
4
+ function traceDir(cwd) {
5
+ return join(ompRoot(cwd), ".omp", "state", "trace");
6
+ }
7
+ function tracePath(cwd, sessionId) {
8
+ if (!/^[\w.-]+$/.test(sessionId))
9
+ throw new Error(`invalid sessionId: ${sessionId}`);
10
+ return join(traceDir(cwd), `${sessionId}.jsonl`);
11
+ }
12
+ export function appendTraceEntry(cwd, sessionId, entry) {
13
+ const path = tracePath(cwd, sessionId);
14
+ mkdirSync(dirname(path), { recursive: true });
15
+ appendFileSync(path, `${JSON.stringify({ ts: new Date().toISOString(), sessionId, ...entry })}\n`, "utf8");
16
+ }
17
+ function readEntries(path) {
18
+ if (!existsSync(path))
19
+ return [];
20
+ return readFileSync(path, "utf8")
21
+ .split("\n")
22
+ .filter((l) => l.trim().length > 0)
23
+ .map((l) => {
24
+ try {
25
+ return JSON.parse(l);
26
+ }
27
+ catch {
28
+ return undefined;
29
+ }
30
+ })
31
+ .filter((e) => Boolean(e));
32
+ }
33
+ function pickSessionId(cwd, sessionId) {
34
+ if (sessionId)
35
+ return sessionId;
36
+ const dir = traceDir(cwd);
37
+ if (!existsSync(dir))
38
+ return undefined;
39
+ const files = readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
40
+ if (files.length === 0)
41
+ return undefined;
42
+ // pick the most recently modified session
43
+ return files
44
+ .map((f) => ({ name: f.replace(/\.jsonl$/, ""), path: join(dir, f) }))
45
+ .sort((a, b) => {
46
+ try {
47
+ return statSync(b.path).mtimeMs - statSync(a.path).mtimeMs;
48
+ }
49
+ catch {
50
+ return 0;
51
+ }
52
+ })[0]?.name;
53
+ }
54
+ /** Last `limit` entries of a session (default 50; most recent session if omitted). */
55
+ export function traceTimeline(cwd, sessionId, limit = 50) {
56
+ const sid = pickSessionId(cwd, sessionId);
57
+ if (!sid)
58
+ return { entries: [] };
59
+ return { sessionId: sid, entries: readEntries(tracePath(cwd, sid)).slice(-Math.max(1, limit)) };
60
+ }
61
+ /** Event-name counts for a session. */
62
+ export function traceSummary(cwd, sessionId) {
63
+ const sid = pickSessionId(cwd, sessionId);
64
+ if (!sid)
65
+ return { total: 0, counts: {} };
66
+ const entries = readEntries(tracePath(cwd, sid));
67
+ const counts = {};
68
+ for (const e of entries) {
69
+ const key = e.event ?? "unknown";
70
+ counts[key] = (counts[key] ?? 0) + 1;
71
+ }
72
+ return { sessionId: sid, total: entries.length, counts };
73
+ }
74
+ //# sourceMappingURL=trace.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trace.js","sourceRoot":"","sources":["../../src/trace.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@damian87/omp",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "GitHub Copilot project skills catalog and Jira handoff tools.",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -24,6 +24,8 @@
24
24
  ],
25
25
  "scripts": {
26
26
  "build": "tsc -p tsconfig.json",
27
+ "release": "bash tools/release.sh",
28
+ "release:publish-only": "bash tools/release.sh --publish-only",
27
29
  "check:catalog": "npm run build && node dist/src/cli.js catalog validate",
28
30
  "catalog:list": "npm run build && node dist/src/cli.js catalog list",
29
31
  "project:inspect": "npm run build && node dist/src/cli.js project inspect",