@damian87/omp 0.12.0 → 0.13.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 (75) hide show
  1. package/dist/src/cli.js +125 -4
  2. package/dist/src/cli.js.map +1 -1
  3. package/dist/src/commands/comms.d.ts +2 -0
  4. package/dist/src/commands/comms.js +110 -0
  5. package/dist/src/commands/comms.js.map +1 -0
  6. package/dist/src/commands/council.d.ts +2 -0
  7. package/dist/src/commands/council.js +77 -0
  8. package/dist/src/commands/council.js.map +1 -0
  9. package/dist/src/commands/env.d.ts +2 -0
  10. package/dist/src/commands/env.js +95 -0
  11. package/dist/src/commands/env.js.map +1 -0
  12. package/dist/src/commands/gateway.d.ts +3 -0
  13. package/dist/src/commands/gateway.js +129 -0
  14. package/dist/src/commands/gateway.js.map +1 -0
  15. package/dist/src/commands/memory.d.ts +7 -0
  16. package/dist/src/commands/memory.js +202 -0
  17. package/dist/src/commands/memory.js.map +1 -0
  18. package/dist/src/commands/mode.d.ts +4 -0
  19. package/dist/src/commands/mode.js +119 -0
  20. package/dist/src/commands/mode.js.map +1 -0
  21. package/dist/src/commands/schedule.d.ts +2 -0
  22. package/dist/src/commands/schedule.js +91 -0
  23. package/dist/src/commands/schedule.js.map +1 -0
  24. package/dist/src/commands/team.d.ts +2 -0
  25. package/dist/src/commands/team.js +146 -0
  26. package/dist/src/commands/team.js.map +1 -0
  27. package/dist/src/commands/utils.d.ts +13 -0
  28. package/dist/src/commands/utils.js +68 -0
  29. package/dist/src/commands/utils.js.map +1 -0
  30. package/dist/src/goal.js +6 -8
  31. package/dist/src/goal.js.map +1 -1
  32. package/dist/src/instructions-memory.js +26 -3
  33. package/dist/src/instructions-memory.js.map +1 -1
  34. package/dist/src/memory-review/apply.d.ts +7 -0
  35. package/dist/src/memory-review/apply.js +75 -0
  36. package/dist/src/memory-review/apply.js.map +1 -0
  37. package/dist/src/memory-review/config.d.ts +22 -0
  38. package/dist/src/memory-review/config.js +54 -0
  39. package/dist/src/memory-review/config.js.map +1 -0
  40. package/dist/src/memory-review/guard.d.ts +5 -0
  41. package/dist/src/memory-review/guard.js +37 -0
  42. package/dist/src/memory-review/guard.js.map +1 -0
  43. package/dist/src/memory-review/index.d.ts +17 -0
  44. package/dist/src/memory-review/index.js +87 -0
  45. package/dist/src/memory-review/index.js.map +1 -0
  46. package/dist/src/memory-review/prompt.d.ts +18 -0
  47. package/dist/src/memory-review/prompt.js +89 -0
  48. package/dist/src/memory-review/prompt.js.map +1 -0
  49. package/dist/src/memory-review/spawn.d.ts +2 -0
  50. package/dist/src/memory-review/spawn.js +51 -0
  51. package/dist/src/memory-review/spawn.js.map +1 -0
  52. package/dist/src/memory-review/transcript.d.ts +24 -0
  53. package/dist/src/memory-review/transcript.js +212 -0
  54. package/dist/src/memory-review/transcript.js.map +1 -0
  55. package/dist/src/memory-review/trigger.d.ts +21 -0
  56. package/dist/src/memory-review/trigger.js +27 -0
  57. package/dist/src/memory-review/trigger.js.map +1 -0
  58. package/dist/src/project-memory.d.ts +9 -0
  59. package/dist/src/project-memory.js +72 -1
  60. package/dist/src/project-memory.js.map +1 -1
  61. package/dist/src/state.js +25 -37
  62. package/dist/src/state.js.map +1 -1
  63. package/dist/src/utils/fs.d.ts +14 -0
  64. package/dist/src/utils/fs.js +32 -0
  65. package/dist/src/utils/fs.js.map +1 -0
  66. package/dist/src/utils/paths.d.ts +14 -0
  67. package/dist/src/utils/paths.js +21 -0
  68. package/dist/src/utils/paths.js.map +1 -0
  69. package/docs/memory-mode.md +94 -0
  70. package/package.json +1 -1
  71. package/plugin.json +1 -1
  72. package/scripts/lib/memory-review-trigger.mjs +59 -0
  73. package/scripts/lib/pending-directives.mjs +36 -0
  74. package/scripts/session-end.mjs +8 -0
  75. package/scripts/session-start.mjs +4 -0
@@ -0,0 +1,13 @@
1
+ export declare function hasFlag(args: string[], flag: string): boolean;
2
+ export declare function flagValue(args: string[], flag: string): string | undefined;
3
+ export declare function resolveExistingInputPath(value: string): Promise<string>;
4
+ export declare const DEFAULT_COUNCIL_ROLES: string[];
5
+ /** Parse a --models value: comma-separated `model` or `model:role:weight` tokens. */
6
+ export declare function parseModelsFlag(value: string): {
7
+ model: string;
8
+ role: string;
9
+ weight: number;
10
+ }[];
11
+ /** Parse a numeric flag as a finite positive integer; throw on malformed input. */
12
+ export declare function parsePositiveIntFlag(value: string | undefined, flag: string): number | undefined;
13
+ export declare function readFlagOrFile(value: string | undefined): Promise<string | undefined>;
@@ -0,0 +1,68 @@
1
+ export function hasFlag(args, flag) {
2
+ return args.includes(flag);
3
+ }
4
+ export function flagValue(args, flag) {
5
+ const index = args.indexOf(flag);
6
+ if (index === -1)
7
+ return undefined;
8
+ return args[index + 1];
9
+ }
10
+ export async function resolveExistingInputPath(value) {
11
+ const { existsSync } = await import("node:fs");
12
+ const { isAbsolute, resolve } = await import("node:path");
13
+ const direct = isAbsolute(value) ? value : resolve(process.cwd(), value);
14
+ if (existsSync(direct))
15
+ return direct;
16
+ const parentRelative = isAbsolute(value) ? value : resolve(process.cwd(), "..", value);
17
+ if (existsSync(parentRelative))
18
+ return parentRelative;
19
+ return direct;
20
+ }
21
+ export const DEFAULT_COUNCIL_ROLES = ["critic", "architect", "pragmatist"];
22
+ /** Parse a --models value: comma-separated `model` or `model:role:weight` tokens. */
23
+ export function parseModelsFlag(value) {
24
+ const tokens = value
25
+ .split(",")
26
+ .map((t) => t.trim())
27
+ .filter((t) => t.length > 0);
28
+ if (tokens.length === 0) {
29
+ throw new Error("--models was empty");
30
+ }
31
+ return tokens.map((token, i) => {
32
+ const parts = token.split(":");
33
+ const model = parts[0].trim();
34
+ if (!model)
35
+ throw new Error(`--models token "${token}" has no model`);
36
+ const role = parts[1]?.trim() || DEFAULT_COUNCIL_ROLES[i % DEFAULT_COUNCIL_ROLES.length];
37
+ let weight = 1;
38
+ if (parts[2] !== undefined) {
39
+ const w = Number(parts[2]);
40
+ if (!Number.isFinite(w) || w <= 0) {
41
+ throw new Error(`--models token "${token}" has invalid weight`);
42
+ }
43
+ weight = w;
44
+ }
45
+ return { model, role, weight };
46
+ });
47
+ }
48
+ /** Parse a numeric flag as a finite positive integer; throw on malformed input. */
49
+ export function parsePositiveIntFlag(value, flag) {
50
+ if (value === undefined)
51
+ return undefined;
52
+ const n = Number(value);
53
+ if (!Number.isFinite(n) || n <= 0 || !Number.isInteger(n)) {
54
+ throw new Error(`Invalid ${flag}: expected a positive integer, got "${value}"`);
55
+ }
56
+ return n;
57
+ }
58
+ export async function readFlagOrFile(value) {
59
+ if (value === undefined)
60
+ return undefined;
61
+ if (value.startsWith("@")) {
62
+ const { readFileSync } = await import("node:fs");
63
+ const path = await resolveExistingInputPath(value.slice(1));
64
+ return readFileSync(path, "utf8");
65
+ }
66
+ return value;
67
+ }
68
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/commands/utils.ts"],"names":[],"mappings":"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"}
package/dist/src/goal.js CHANGED
@@ -1,12 +1,12 @@
1
- import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
2
- import { dirname, join } from "node:path";
3
- import { ompRoot } from "./omp-root.js";
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import { atomicWrite, ensureDir } from "./utils/fs.js";
3
+ import { ompPath } from "./utils/paths.js";
4
4
  // The repo's durable objective ("what we want to achieve in this repo"), stored
5
5
  // once per project at .omp/goal.md — distinct from a daily log's per-day goal.
6
6
  // Exposed through the `omp goal` CLI subcommands (NOT MCP), so the project dir
7
7
  // is the CLI's cwd and never ambiguous.
8
8
  function goalFile(cwd) {
9
- return join(ompRoot(cwd), ".omp", "goal.md");
9
+ return ompPath(cwd, "goal.md");
10
10
  }
11
11
  // Strip ONLY our own serialized `# Repo Goal` header (not any heading), so a
12
12
  // hand-authored objective — even one that starts with `#` — is never lost.
@@ -35,10 +35,8 @@ export function writeRepoGoal(cwd, goal) {
35
35
  .replace(/\s*\n\s*/g, " ")
36
36
  .trim();
37
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);
38
+ ensureDir(p);
39
+ atomicWrite(p, `# Repo Goal\n\n${clean}\n`);
42
40
  return clean;
43
41
  }
44
42
  //# sourceMappingURL=goal.js.map
@@ -1 +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"}
1
+ {"version":3,"file":"goal.js","sourceRoot":"","sources":["../../src/goal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAE3C,gFAAgF;AAChF,+EAA+E;AAC/E,+EAA+E;AAC/E,wCAAwC;AACxC,SAAS,QAAQ,CAAC,GAAW;IAC3B,OAAO,OAAO,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;AACjC,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,CAAC,CAAC,CAAC;IACb,WAAW,CAAC,CAAC,EAAE,kBAAkB,KAAK,IAAI,CAAC,CAAC;IAC5C,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -2,7 +2,12 @@ import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "
2
2
  import { dirname, join } from "node:path";
3
3
  import { ompRoot } from "./omp-root.js";
4
4
  import { readRepoGoal } from "./goal.js";
5
- import { noteIndex } from "./project-memory.js";
5
+ import { noteIndex, recentNotes } from "./project-memory.js";
6
+ // Cap surfaced note titles so the managed block can't balloon as notes
7
+ // accumulate; overflow is summarized with a pointer (mirrors the directive cap
8
+ // in scripts/session-start.mjs). Newest notes stay visible.
9
+ const MAX_NOTE_TITLES = 12;
10
+ const MAX_NOTE_TITLE_CHARS = 1200;
6
11
  // Copilot CLI can inject memory via the `sessionStart` hook's `additionalContext`
7
12
  // (see hooks/hooks.json + scripts/session-start.mjs, ported to Copilot's hook
8
13
  // schema). This copilot-instructions.md block remains the always-on fallback: it
@@ -16,11 +21,29 @@ function instructionsPath(cwd) {
16
21
  }
17
22
  function renderBlock(cwd) {
18
23
  const goal = readRepoGoal(cwd);
19
- const notes = noteIndex(cwd);
24
+ const total = noteIndex(cwd).length;
20
25
  const lines = [START, "## oh-my-copilot project context"];
21
26
  if (goal)
22
27
  lines.push("", `**Repo goal:** ${goal}`);
23
- lines.push("", "Project memory is available on demand:", "- `omp project-memory read` for project hints and the note index", "- `omp project-memory read <id>` for a specific note body", "- `omp daily-log read --days 7` for recent daily context", "", `Available note index: ${notes.length} note${notes.length === 1 ? "" : "s"}.`, END);
28
+ lines.push("", "Project memory is available on demand:", "- `omp project-memory read` for project hints and the note index", "- `omp project-memory read <id>` for a specific note body", "- `omp daily-log read --days 7` for recent daily context");
29
+ if (total > 0) {
30
+ // Surface the most recent note titles (newest-first, capped) so the next
31
+ // session knows WHAT it remembers, not just that N notes exist. Bodies stay
32
+ // on demand via `omp project-memory read <id>`.
33
+ const shown = [];
34
+ let chars = 0;
35
+ for (const n of recentNotes(cwd, MAX_NOTE_TITLES)) {
36
+ if (chars + n.title.length > MAX_NOTE_TITLE_CHARS)
37
+ break;
38
+ shown.push(`- ${n.title} (\`${n.id}\`)`);
39
+ chars += n.title.length;
40
+ }
41
+ const more = total - shown.length;
42
+ lines.push("", `Project memory notes (${total}):`, ...shown);
43
+ if (more > 0)
44
+ lines.push(`- (+${more} more — \`omp project-memory read\` for the full index)`);
45
+ }
46
+ lines.push(END);
24
47
  return lines.join("\n");
25
48
  }
26
49
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"instructions-memory.js","sourceRoot":"","sources":["../../src/instructions-memory.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"instructions-memory.js","sourceRoot":"","sources":["../../src/instructions-memory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { ReviewResult } from "./prompt.js";
2
+ export interface ApplySummary {
3
+ notesAdded: number;
4
+ draftsWritten: string[];
5
+ directivesQueued: number;
6
+ }
7
+ export declare function applyReview(cwd: string, result: ReviewResult): ApplySummary;
@@ -0,0 +1,75 @@
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 { addNote } from "../project-memory.js";
5
+ function reviewDir(cwd) {
6
+ return join(ompRoot(cwd), ".oh-my-copilot", "memory-review");
7
+ }
8
+ function draftsDir(cwd) {
9
+ return join(ompRoot(cwd), ".oh-my-copilot", "self-evolve", "drafts");
10
+ }
11
+ function writeAtomic(p, content) {
12
+ mkdirSync(dirname(p), { recursive: true });
13
+ const tmp = `${p}.tmp.${process.pid}.${Date.now()}`;
14
+ writeFileSync(tmp, content, "utf8");
15
+ renameSync(tmp, p);
16
+ }
17
+ const GITIGNORE_START = "# omp:memory-review:start";
18
+ const GITIGNORE_END = "# omp:memory-review:end";
19
+ // Memory-mode writes notes/drafts/pending that may contain sensitive tool output,
20
+ // so ensure the project gitignores them before the first write. Idempotent and
21
+ // marker-guarded: append the managed block only if absent; never clobber user
22
+ // content. Best-effort — a gitignore failure must not block the review.
23
+ function ensureGitignored(cwd) {
24
+ try {
25
+ const p = join(ompRoot(cwd), ".gitignore");
26
+ const existing = existsSync(p) ? readFileSync(p, "utf8") : "";
27
+ if (existing.includes(GITIGNORE_START))
28
+ return; // already managed
29
+ const block = [GITIGNORE_START, ".omp/", ".oh-my-copilot/", GITIGNORE_END, ""].join("\n");
30
+ const next = existing.trim() === "" ? `${block}` : `${existing.trimEnd()}\n\n${block}`;
31
+ mkdirSync(dirname(p), { recursive: true });
32
+ const tmp = `${p}.tmp.${process.pid}.${Date.now()}`;
33
+ writeFileSync(tmp, next, "utf8");
34
+ renameSync(tmp, p);
35
+ }
36
+ catch {
37
+ // best-effort
38
+ }
39
+ }
40
+ export function applyReview(cwd, result) {
41
+ ensureGitignored(cwd);
42
+ let notesAdded = 0;
43
+ for (const n of result.notes) {
44
+ addNote(cwd, n.title, n.body);
45
+ notesAdded += 1;
46
+ }
47
+ const draftsWritten = [];
48
+ for (const d of result.skill_drafts) {
49
+ if (!d.slug)
50
+ continue;
51
+ const skillMd = [
52
+ "---",
53
+ `name: learned-${d.slug}`,
54
+ `description: ${JSON.stringify(d.reason || `Learned procedure: ${d.slug}`)}`,
55
+ "status: draft",
56
+ "---",
57
+ "",
58
+ d.body.trim() || `# ${d.slug}\n\n${d.reason}`,
59
+ "",
60
+ ].join("\n");
61
+ writeAtomic(join(draftsDir(cwd), d.slug, "SKILL.md"), skillMd);
62
+ draftsWritten.push(d.slug);
63
+ }
64
+ let directivesQueued = 0;
65
+ if (result.directives.length > 0) {
66
+ const pending = join(reviewDir(cwd), "pending-directives.md");
67
+ const header = "# Pending directives (review before applying)\n";
68
+ const existing = existsSync(pending) ? readFileSync(pending, "utf8") : header;
69
+ const lines = result.directives.map((d) => `- [ ] ${d}`).join("\n");
70
+ writeAtomic(pending, `${existing.trimEnd()}\n${lines}\n`);
71
+ directivesQueued = result.directives.length;
72
+ }
73
+ return { notesAdded, draftsWritten, directivesQueued };
74
+ }
75
+ //# sourceMappingURL=apply.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apply.js","sourceRoot":"","sources":["../../../src/memory-review/apply.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ export type MemoryMode = "off" | "on";
2
+ export declare const DEFAULT_REVIEW_MODEL = "gpt-5-mini";
3
+ export declare const DEFAULT_MIN_MESSAGES = 4;
4
+ export interface MemoryConfig {
5
+ memoryMode: MemoryMode;
6
+ memoryReviewModel: string;
7
+ memoryReviewMinMessages: number;
8
+ }
9
+ export type MemoryConfigKey = "memoryMode" | "memoryReviewModel" | "memoryReviewMinMessages";
10
+ export interface ReadConfigOptions {
11
+ /** Override the home dir (defaults to os.homedir()); used in tests. */
12
+ homeDir?: string;
13
+ }
14
+ export interface SetConfigOptions extends ReadConfigOptions {
15
+ /** "project" (default) writes .omp/config.json under ompRoot(cwd); "global"
16
+ * writes ~/.omp/config.json. */
17
+ scope?: "project" | "global";
18
+ }
19
+ export declare function readMemoryConfig(cwd: string, opts?: ReadConfigOptions): MemoryConfig;
20
+ /** Persist a single memory key, preserving all other keys in that file. Atomic.
21
+ * Writes the project file by default, or the global ~/.omp file with scope. */
22
+ export declare function setMemoryConfigValue(cwd: string, key: MemoryConfigKey, value: string, opts?: SetConfigOptions): void;
@@ -0,0 +1,54 @@
1
+ import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
2
+ import { homedir } from "node:os";
3
+ import { dirname, join } from "node:path";
4
+ import { ompRoot } from "../omp-root.js";
5
+ export const DEFAULT_REVIEW_MODEL = "gpt-5-mini";
6
+ export const DEFAULT_MIN_MESSAGES = 4;
7
+ function projectConfigPath(cwd) {
8
+ return join(ompRoot(cwd), ".omp", "config.json");
9
+ }
10
+ function globalConfigPath(homeDir) {
11
+ // OMP_HOME_OVERRIDE relocates the global ~/.omp dir (custom home; also the
12
+ // test-isolation seam set in test/setup.ts). Explicit homeDir wins over it.
13
+ const home = homeDir ?? (process.env.OMP_HOME_OVERRIDE || homedir());
14
+ return join(home, ".omp", "config.json");
15
+ }
16
+ function readRawAt(p) {
17
+ if (!existsSync(p))
18
+ return {};
19
+ try {
20
+ const data = JSON.parse(readFileSync(p, "utf8"));
21
+ return data && typeof data === "object" ? data : {};
22
+ }
23
+ catch {
24
+ return {};
25
+ }
26
+ }
27
+ export function readMemoryConfig(cwd, opts = {}) {
28
+ // Project overrides global, per key.
29
+ const raw = { ...readRawAt(globalConfigPath(opts.homeDir)), ...readRawAt(projectConfigPath(cwd)) };
30
+ const envMode = process.env.OMP_MEMORY_MODE;
31
+ const memoryMode = envMode === "on" || envMode === "off"
32
+ ? envMode
33
+ : raw.memoryMode === "on"
34
+ ? "on"
35
+ : "off";
36
+ const memoryReviewModel = typeof raw.memoryReviewModel === "string" && raw.memoryReviewModel.trim()
37
+ ? raw.memoryReviewModel.trim()
38
+ : DEFAULT_REVIEW_MODEL;
39
+ const parsedMin = Number(raw.memoryReviewMinMessages);
40
+ const memoryReviewMinMessages = Number.isFinite(parsedMin) && parsedMin >= 0 ? Math.floor(parsedMin) : DEFAULT_MIN_MESSAGES;
41
+ return { memoryMode, memoryReviewModel, memoryReviewMinMessages };
42
+ }
43
+ /** Persist a single memory key, preserving all other keys in that file. Atomic.
44
+ * Writes the project file by default, or the global ~/.omp file with scope. */
45
+ export function setMemoryConfigValue(cwd, key, value, opts = {}) {
46
+ const p = opts.scope === "global" ? globalConfigPath(opts.homeDir) : projectConfigPath(cwd);
47
+ const raw = readRawAt(p);
48
+ raw[key] = value;
49
+ mkdirSync(dirname(p), { recursive: true });
50
+ const tmp = `${p}.tmp.${process.pid}.${Date.now()}`;
51
+ writeFileSync(tmp, `${JSON.stringify(raw, null, 2)}\n`, "utf8");
52
+ renameSync(tmp, p);
53
+ }
54
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/memory-review/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /** Atomically claim a session for review. Returns true only for the winner. */
2
+ export declare function claimSession(cwd: string, uuid: string): boolean;
3
+ /** Release a claim so the session can be retried — used on no-write failure
4
+ * paths (model error, unparseable output) where nothing was persisted. */
5
+ export declare function releaseClaim(cwd: string, uuid: string): void;
@@ -0,0 +1,37 @@
1
+ import { mkdirSync, unlinkSync, writeFileSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { ompRoot } from "../omp-root.js";
4
+ // The review can be triggered from two places — the sessionEnd hook (detached)
5
+ // and the omp wrapper post-exit (headless `-p`). Both may fire for the same
6
+ // session, so the claim must be atomic: an exclusive-create write (`wx`) is the
7
+ // race-free "exactly one winner" primitive. A read-then-write check would race.
8
+ function reviewDir(cwd) {
9
+ return join(ompRoot(cwd), ".oh-my-copilot", "memory-review");
10
+ }
11
+ function claimPath(cwd, uuid) {
12
+ const safe = String(uuid).replace(/[^a-zA-Z0-9._-]+/g, "-") || "unknown";
13
+ return join(reviewDir(cwd), `.claim-${safe}`);
14
+ }
15
+ /** Atomically claim a session for review. Returns true only for the winner. */
16
+ export function claimSession(cwd, uuid) {
17
+ const p = claimPath(cwd, uuid);
18
+ try {
19
+ mkdirSync(dirname(p), { recursive: true });
20
+ writeFileSync(p, new Date().toISOString(), { flag: "wx" }); // EEXIST if already claimed
21
+ return true;
22
+ }
23
+ catch {
24
+ return false;
25
+ }
26
+ }
27
+ /** Release a claim so the session can be retried — used on no-write failure
28
+ * paths (model error, unparseable output) where nothing was persisted. */
29
+ export function releaseClaim(cwd, uuid) {
30
+ try {
31
+ unlinkSync(claimPath(cwd, uuid));
32
+ }
33
+ catch {
34
+ // a missing claim is fine
35
+ }
36
+ }
37
+ //# sourceMappingURL=guard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guard.js","sourceRoot":"","sources":["../../../src/memory-review/guard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAEzC,+EAA+E;AAC/E,4EAA4E;AAC5E,gFAAgF;AAChF,gFAAgF;AAEhF,SAAS,SAAS,CAAC,GAAW;IAC5B,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,gBAAgB,EAAE,eAAe,CAAC,CAAC;AAC/D,CAAC;AAED,SAAS,SAAS,CAAC,GAAW,EAAE,IAAY;IAC1C,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,mBAAmB,EAAE,GAAG,CAAC,IAAI,SAAS,CAAC;IACzE,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,UAAU,IAAI,EAAE,CAAC,CAAC;AAChD,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,YAAY,CAAC,GAAW,EAAE,IAAY;IACpD,MAAM,CAAC,GAAG,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAC/B,IAAI,CAAC;QACH,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3C,aAAa,CAAC,CAAC,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,4BAA4B;QACxF,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;2EAC2E;AAC3E,MAAM,UAAU,YAAY,CAAC,GAAW,EAAE,IAAY;IACpD,IAAI,CAAC;QACH,UAAU,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;IACnC,CAAC;IAAC,MAAM,CAAC;QACP,0BAA0B;IAC5B,CAAC;AACH,CAAC"}
@@ -0,0 +1,17 @@
1
+ import type { CouncilSpawn } from "../council/types.js";
2
+ import { type TranscriptMessage } from "./transcript.js";
3
+ import { type ApplySummary } from "./apply.js";
4
+ export interface RunMemoryReviewOptions {
5
+ cwd: string;
6
+ sessionId: string;
7
+ spawn: CouncilSpawn;
8
+ readTranscript?: (uuid: string) => TranscriptMessage[];
9
+ model?: string;
10
+ timeoutMs?: number;
11
+ }
12
+ export interface RunMemoryReviewResult {
13
+ ran: boolean;
14
+ reason?: string;
15
+ summary?: ApplySummary;
16
+ }
17
+ export declare function runMemoryReview(options: RunMemoryReviewOptions): Promise<RunMemoryReviewResult>;
@@ -0,0 +1,87 @@
1
+ import { appendFileSync, mkdirSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { ompRoot } from "../omp-root.js";
4
+ import { appendCostRecord } from "../cost/ledger.js";
5
+ import { readMemoryConfig } from "./config.js";
6
+ import { claimSession, releaseClaim } from "./guard.js";
7
+ import { isValidSessionId, readSessionTranscript } from "./transcript.js";
8
+ import { buildReviewPrompt, parseReviewOutput } from "./prompt.js";
9
+ import { applyReview } from "./apply.js";
10
+ function logLine(cwd, payload) {
11
+ try {
12
+ const p = join(ompRoot(cwd), ".omp", "state", "memory-review.log");
13
+ mkdirSync(dirname(p), { recursive: true });
14
+ appendFileSync(p, `${JSON.stringify({ ts: new Date().toISOString(), ...payload })}\n`);
15
+ }
16
+ catch {
17
+ // logging is best-effort
18
+ }
19
+ }
20
+ export async function runMemoryReview(options) {
21
+ const { cwd, sessionId } = options;
22
+ const config = readMemoryConfig(cwd);
23
+ if (config.memoryMode !== "on")
24
+ return { ran: false, reason: "memory-mode off" };
25
+ if (!sessionId)
26
+ return { ran: false, reason: "no session id" };
27
+ if (!isValidSessionId(sessionId))
28
+ return { ran: false, reason: "invalid session id" };
29
+ // Read the transcript BEFORE claiming — an empty session never consumes a
30
+ // claim, so a session that later grows can still be reviewed.
31
+ const read = options.readTranscript ?? ((uuid) => readSessionTranscript(uuid));
32
+ const messages = read(sessionId);
33
+ if (messages.length === 0) {
34
+ logLine(cwd, { sessionId, ran: false, reason: "empty transcript" });
35
+ return { ran: false, reason: "empty transcript" };
36
+ }
37
+ // Skip trivial sessions (cost control) — don't spend a model call or consume
38
+ // a claim on a session too short to have produced durable knowledge.
39
+ if (messages.length < config.memoryReviewMinMessages) {
40
+ logLine(cwd, { sessionId, ran: false, reason: "below min-messages threshold" });
41
+ return { ran: false, reason: "below min-messages threshold" };
42
+ }
43
+ // Atomic claim only once we're committed to spending the model call, so a
44
+ // near-simultaneous hook + wrapper run resolves to exactly one execution.
45
+ if (!claimSession(cwd, sessionId))
46
+ return { ran: false, reason: "already claimed" };
47
+ const model = options.model ?? config.memoryReviewModel;
48
+ const prompt = buildReviewPrompt(messages);
49
+ const timeoutMs = options.timeoutMs ?? 90_000;
50
+ const res = await options.spawn({ model, prompt, timeoutMs });
51
+ if (res.exitCode !== 0 || res.timedOut) {
52
+ // Nothing was written — release the claim so the session can be retried.
53
+ releaseClaim(cwd, sessionId);
54
+ const reason = `review model failed (exit=${res.exitCode}, timedOut=${res.timedOut})`;
55
+ logLine(cwd, { sessionId, ran: false, reason });
56
+ return { ran: false, reason };
57
+ }
58
+ const parsed = parseReviewOutput(res.stdout);
59
+ if (!parsed) {
60
+ releaseClaim(cwd, sessionId);
61
+ logLine(cwd, { sessionId, ran: false, reason: "unparseable review output" });
62
+ return { ran: false, reason: "unparseable review output" };
63
+ }
64
+ const summary = applyReview(cwd, parsed);
65
+ // Refresh the injected memory block so newly written notes surface in the
66
+ // NEXT session (closes the loop). Best-effort — never fail the review on it.
67
+ if (summary.notesAdded > 0) {
68
+ try {
69
+ const { syncInstructionsMemory } = await import("../instructions-memory.js");
70
+ syncInstructionsMemory(cwd);
71
+ }
72
+ catch {
73
+ // sync is best-effort
74
+ }
75
+ }
76
+ appendCostRecord(cwd, {
77
+ sessionId,
78
+ event: "memory-review",
79
+ model,
80
+ inTokens: Math.ceil(prompt.length / 4),
81
+ outTokens: Math.ceil(res.stdout.length / 4),
82
+ note: `notes=${summary.notesAdded} drafts=${summary.draftsWritten.length} directivesQueued=${summary.directivesQueued}`,
83
+ });
84
+ logLine(cwd, { sessionId, ran: true, ...summary });
85
+ return { ran: true, summary };
86
+ }
87
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/memory-review/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import type { TranscriptMessage } from "./transcript.js";
2
+ export interface ReviewNote {
3
+ title: string;
4
+ body: string;
5
+ }
6
+ export interface ReviewSkillDraft {
7
+ slug: string;
8
+ reason: string;
9
+ body: string;
10
+ }
11
+ export interface ReviewResult {
12
+ directives: string[];
13
+ notes: ReviewNote[];
14
+ skill_drafts: ReviewSkillDraft[];
15
+ }
16
+ export declare function slugify(input: string): string;
17
+ export declare function buildReviewPrompt(messages: TranscriptMessage[]): string;
18
+ export declare function parseReviewOutput(raw: string): ReviewResult | null;