@damian87/omp 0.12.0 → 0.14.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 (94) hide show
  1. package/.github/skills/schedule/SKILL.md +27 -2
  2. package/.github/skills/verify-byok/SKILL.md +50 -0
  3. package/README.md +88 -4
  4. package/catalog/capabilities.json +23 -0
  5. package/catalog/skills-general.json +25 -0
  6. package/dist/src/cli.js +158 -5
  7. package/dist/src/cli.js.map +1 -1
  8. package/dist/src/commands/comms.d.ts +2 -0
  9. package/dist/src/commands/comms.js +110 -0
  10. package/dist/src/commands/comms.js.map +1 -0
  11. package/dist/src/commands/council.d.ts +2 -0
  12. package/dist/src/commands/council.js +77 -0
  13. package/dist/src/commands/council.js.map +1 -0
  14. package/dist/src/commands/env.d.ts +2 -0
  15. package/dist/src/commands/env.js +95 -0
  16. package/dist/src/commands/env.js.map +1 -0
  17. package/dist/src/commands/gateway.d.ts +3 -0
  18. package/dist/src/commands/gateway.js +129 -0
  19. package/dist/src/commands/gateway.js.map +1 -0
  20. package/dist/src/commands/memory.d.ts +7 -0
  21. package/dist/src/commands/memory.js +202 -0
  22. package/dist/src/commands/memory.js.map +1 -0
  23. package/dist/src/commands/mode.d.ts +4 -0
  24. package/dist/src/commands/mode.js +119 -0
  25. package/dist/src/commands/mode.js.map +1 -0
  26. package/dist/src/commands/schedule.d.ts +2 -0
  27. package/dist/src/commands/schedule.js +91 -0
  28. package/dist/src/commands/schedule.js.map +1 -0
  29. package/dist/src/commands/team.d.ts +2 -0
  30. package/dist/src/commands/team.js +146 -0
  31. package/dist/src/commands/team.js.map +1 -0
  32. package/dist/src/commands/utils.d.ts +13 -0
  33. package/dist/src/commands/utils.js +68 -0
  34. package/dist/src/commands/utils.js.map +1 -0
  35. package/dist/src/gateway/desktop-notify.d.ts +56 -0
  36. package/dist/src/gateway/desktop-notify.js +183 -0
  37. package/dist/src/gateway/desktop-notify.js.map +1 -0
  38. package/dist/src/goal.js +6 -8
  39. package/dist/src/goal.js.map +1 -1
  40. package/dist/src/instructions-memory.js +26 -3
  41. package/dist/src/instructions-memory.js.map +1 -1
  42. package/dist/src/memory-review/apply.d.ts +7 -0
  43. package/dist/src/memory-review/apply.js +75 -0
  44. package/dist/src/memory-review/apply.js.map +1 -0
  45. package/dist/src/memory-review/config.d.ts +22 -0
  46. package/dist/src/memory-review/config.js +54 -0
  47. package/dist/src/memory-review/config.js.map +1 -0
  48. package/dist/src/memory-review/guard.d.ts +5 -0
  49. package/dist/src/memory-review/guard.js +37 -0
  50. package/dist/src/memory-review/guard.js.map +1 -0
  51. package/dist/src/memory-review/index.d.ts +17 -0
  52. package/dist/src/memory-review/index.js +87 -0
  53. package/dist/src/memory-review/index.js.map +1 -0
  54. package/dist/src/memory-review/prompt.d.ts +18 -0
  55. package/dist/src/memory-review/prompt.js +89 -0
  56. package/dist/src/memory-review/prompt.js.map +1 -0
  57. package/dist/src/memory-review/spawn.d.ts +2 -0
  58. package/dist/src/memory-review/spawn.js +51 -0
  59. package/dist/src/memory-review/spawn.js.map +1 -0
  60. package/dist/src/memory-review/transcript.d.ts +24 -0
  61. package/dist/src/memory-review/transcript.js +212 -0
  62. package/dist/src/memory-review/transcript.js.map +1 -0
  63. package/dist/src/memory-review/trigger.d.ts +21 -0
  64. package/dist/src/memory-review/trigger.js +27 -0
  65. package/dist/src/memory-review/trigger.js.map +1 -0
  66. package/dist/src/project-memory.d.ts +9 -0
  67. package/dist/src/project-memory.js +72 -1
  68. package/dist/src/project-memory.js.map +1 -1
  69. package/dist/src/schedule/commands.d.ts +13 -0
  70. package/dist/src/schedule/commands.js +24 -1
  71. package/dist/src/schedule/commands.js.map +1 -1
  72. package/dist/src/schedule/deep-link.d.ts +18 -0
  73. package/dist/src/schedule/deep-link.js +41 -0
  74. package/dist/src/schedule/deep-link.js.map +1 -0
  75. package/dist/src/schedule/runner.d.ts +10 -0
  76. package/dist/src/schedule/runner.js +36 -0
  77. package/dist/src/schedule/runner.js.map +1 -1
  78. package/dist/src/schedule/types.d.ts +16 -0
  79. package/dist/src/state.js +25 -37
  80. package/dist/src/state.js.map +1 -1
  81. package/dist/src/utils/fs.d.ts +14 -0
  82. package/dist/src/utils/fs.js +32 -0
  83. package/dist/src/utils/fs.js.map +1 -0
  84. package/dist/src/utils/paths.d.ts +14 -0
  85. package/dist/src/utils/paths.js +21 -0
  86. package/dist/src/utils/paths.js.map +1 -0
  87. package/docs/memory-mode.md +94 -0
  88. package/docs/research/2026-06-22-schedule-desktop-notifications.md +193 -0
  89. package/package.json +4 -2
  90. package/plugin.json +1 -1
  91. package/scripts/lib/memory-review-trigger.mjs +59 -0
  92. package/scripts/lib/pending-directives.mjs +36 -0
  93. package/scripts/session-end.mjs +8 -0
  94. package/scripts/session-start.mjs +4 -0
@@ -0,0 +1,91 @@
1
+ import { flagValue, hasFlag, parsePositiveIntFlag } from "./utils.js";
2
+ export async function handleSchedule(argv) {
3
+ const [, command, value] = argv;
4
+ const json = hasFlag(argv, "--json");
5
+ const cwd = flagValue(argv, "--root") ?? process.cwd();
6
+ // The OS scheduler invokes `omp schedule run --id <id> --root <dir>`, so prefer
7
+ // the --id flag; fall back to the positional form for human-typed commands.
8
+ const targetId = flagValue(argv, "--id") ?? (value && !value.startsWith("--") ? value : undefined);
9
+ const mod = await import("../schedule/commands.js");
10
+ if (command === "add") {
11
+ const id = flagValue(argv, "--id");
12
+ const cron = flagValue(argv, "--cron");
13
+ const prompt = flagValue(argv, "--prompt");
14
+ if (!id || !cron || !prompt) {
15
+ return { ok: false, exitCode: 1, message: 'schedule add requires --id, --cron, and --prompt' };
16
+ }
17
+ let timeoutMs;
18
+ let maxRuns;
19
+ let ttlHours;
20
+ try {
21
+ timeoutMs = parsePositiveIntFlag(flagValue(argv, "--timeout"), "--timeout");
22
+ maxRuns = parsePositiveIntFlag(flagValue(argv, "--max-runs"), "--max-runs");
23
+ ttlHours = parsePositiveIntFlag(flagValue(argv, "--ttl-hours"), "--ttl-hours");
24
+ }
25
+ catch (err) {
26
+ return { ok: false, exitCode: 1, message: String(err instanceof Error ? err.message : err) };
27
+ }
28
+ const notifyTarget = flagValue(argv, "--notify-target");
29
+ if (notifyTarget) {
30
+ const { parseTarget } = await import("../gateway/target-parser.js");
31
+ const parsed = parseTarget(notifyTarget);
32
+ if (!parsed.ok) {
33
+ return { ok: false, exitCode: 1, message: `--notify-target: ${parsed.error}` };
34
+ }
35
+ }
36
+ const result = mod.addScheduleJob(cwd, {
37
+ id,
38
+ cron,
39
+ prompt,
40
+ bin: flagValue(argv, "--bin"),
41
+ model: flagValue(argv, "--model"),
42
+ cwd: flagValue(argv, "--cwd"),
43
+ timeoutMs,
44
+ maxRuns,
45
+ ttlHours,
46
+ allowAllTools: hasFlag(argv, "--allow-all-tools"),
47
+ dryRun: hasFlag(argv, "--dry-run"),
48
+ notifyTarget,
49
+ });
50
+ return json
51
+ ? { ok: result.ok, exitCode: result.ok ? 0 : 1, output: result }
52
+ : { ok: result.ok, exitCode: result.ok ? 0 : 1, message: result.ok ? result.messages.join("\n") : (result.error ?? "schedule add failed") };
53
+ }
54
+ if (command === "list") {
55
+ const jobs = mod.listScheduleJobs(cwd);
56
+ return json
57
+ ? { ok: true, output: jobs }
58
+ : {
59
+ ok: true,
60
+ message: jobs.length
61
+ ? jobs.map((j) => `${j.id}\t${j.cron}\t${j.backend}\tinstalled=${j.osInstalled}\tlast=${j.lastStatus ?? "-"}`).join("\n")
62
+ : "(no scheduled jobs)",
63
+ };
64
+ }
65
+ if (command === "status" && targetId) {
66
+ const st = mod.getScheduleStatus(cwd, targetId);
67
+ if (!st.job)
68
+ return { ok: false, exitCode: 1, output: json ? st : undefined, message: `no schedule job "${targetId}"` };
69
+ return json
70
+ ? { ok: true, output: st }
71
+ : { ok: true, message: `${st.job.id} cron=${st.job.cron} backend=${st.job.backend} installed=${st.osInstalled} runs=${st.job.runCount} last=${st.job.lastStatus ?? "-"}` };
72
+ }
73
+ if (command === "remove" && targetId) {
74
+ const result = mod.removeScheduleJob(cwd, targetId);
75
+ return json
76
+ ? { ok: result.removed, exitCode: result.removed ? 0 : 1, output: result }
77
+ : { ok: result.removed, exitCode: result.removed ? 0 : 1, message: result.removed ? `removed "${targetId}"` : `no schedule job "${targetId}"` };
78
+ }
79
+ if ((command === "run" || command === "run-now") && targetId) {
80
+ const result = await mod.runScheduleById(cwd, targetId);
81
+ return json
82
+ ? { ok: result.ok, exitCode: result.ok ? 0 : 1, output: result }
83
+ : { ok: result.ok, exitCode: result.ok ? 0 : 1, message: result.message };
84
+ }
85
+ return {
86
+ ok: false,
87
+ exitCode: 1,
88
+ message: 'Unknown schedule subcommand. Try: schedule add --id <id> --cron "<expr>" --prompt "<text>" | list | status <id> | remove <id> | run-now <id>',
89
+ };
90
+ }
91
+ //# sourceMappingURL=schedule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schedule.js","sourceRoot":"","sources":["../../../src/commands/schedule.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { CliResult } from "./types.js";
2
+ export declare function handleTeam(argv: string[]): Promise<CliResult>;
@@ -0,0 +1,146 @@
1
+ import { flagValue, hasFlag, parsePositiveIntFlag } from "./utils.js";
2
+ const TEAM_SPEC_RE = /^(\d+):([\w-]+)$/;
3
+ export async function handleTeam(argv) {
4
+ const [, command, value, extra] = argv;
5
+ const json = hasFlag(argv, "--json");
6
+ const cwd = flagValue(argv, "--root") ?? process.cwd();
7
+ if (command && TEAM_SPEC_RE.test(command)) {
8
+ const match = command.match(TEAM_SPEC_RE);
9
+ const workerCount = Number(match[1]);
10
+ const role = match[2];
11
+ if (!value) {
12
+ return { ok: false, exitCode: 1, message: "team <N:role> requires a task description" };
13
+ }
14
+ const name = flagValue(argv, "--name") ?? `${role}-${Date.now().toString(36)}`;
15
+ const { startTeam } = await import("../team/runtime.js");
16
+ try {
17
+ const result = await startTeam({ cwd, name, role, workerCount, task: value });
18
+ return json
19
+ ? { ok: true, output: result }
20
+ : {
21
+ ok: true,
22
+ message: `started team ${name} session=${result.tmuxSession} workers=${result.config.workers
23
+ .map((w) => `${w.name}(${w.paneId ?? "?"})`)
24
+ .join(",")}`,
25
+ };
26
+ }
27
+ catch (error) {
28
+ const message = error instanceof Error ? error.message : String(error);
29
+ return { ok: false, exitCode: 1, output: json ? { ok: false, error: message } : undefined, message };
30
+ }
31
+ }
32
+ if (command === "status" && value) {
33
+ const { statusTeam, formatStatus } = await import("../team/runtime.js");
34
+ const report = statusTeam({ cwd, name: value });
35
+ return json
36
+ ? { ok: report.ok, output: report }
37
+ : { ok: report.ok, message: formatStatus(report) };
38
+ }
39
+ if (command === "shutdown" && value) {
40
+ const { shutdownTeam } = await import("../team/runtime.js");
41
+ const result = await shutdownTeam({ cwd, name: value });
42
+ return json
43
+ ? { ok: result.ok, output: result }
44
+ : {
45
+ ok: result.ok,
46
+ message: `shutdown team ${value} killedPanes=${result.killedPanes} killedSession=${result.killedSession}`,
47
+ };
48
+ }
49
+ if (command === "monitor-panes") {
50
+ const leaderPaneId = flagValue(argv, "--leader-pane");
51
+ const workerPaneIds = argv
52
+ .flatMap((arg, index) => (arg === "--worker-pane" ? [argv[index + 1]] : []))
53
+ .filter((value) => Boolean(value));
54
+ if (!leaderPaneId || workerPaneIds.length === 0) {
55
+ return { ok: false, exitCode: 1, message: "team monitor-panes requires --leader-pane and at least one --worker-pane" };
56
+ }
57
+ let pollIntervalMs;
58
+ let readySamples;
59
+ let minObservationMs;
60
+ let timeoutMs;
61
+ let captureLines;
62
+ try {
63
+ pollIntervalMs = parsePositiveIntFlag(flagValue(argv, "--poll-interval-ms"), "--poll-interval-ms");
64
+ readySamples = parsePositiveIntFlag(flagValue(argv, "--ready-samples"), "--ready-samples");
65
+ minObservationMs = parsePositiveIntFlag(flagValue(argv, "--min-observation-ms"), "--min-observation-ms");
66
+ timeoutMs = parsePositiveIntFlag(flagValue(argv, "--timeout-ms"), "--timeout-ms");
67
+ captureLines = parsePositiveIntFlag(flagValue(argv, "--capture-lines"), "--capture-lines");
68
+ }
69
+ catch (err) {
70
+ return { ok: false, exitCode: 1, message: String(err instanceof Error ? err.message : err) };
71
+ }
72
+ const { monitorPanes } = await import("../team/pane-monitor.js");
73
+ const result = await monitorPanes({
74
+ leaderPaneId,
75
+ workerPaneIds,
76
+ sessionLabel: flagValue(argv, "--session-label"),
77
+ config: {
78
+ pollIntervalMs,
79
+ readySamples,
80
+ minObservationMs,
81
+ timeoutMs,
82
+ captureLines,
83
+ },
84
+ });
85
+ return json
86
+ ? { ok: result.ok, exitCode: result.ok ? 0 : 1, output: result }
87
+ : { ok: result.ok, exitCode: result.ok ? 0 : 1, message: `team monitor-panes ${result.reason} events=${result.events.length}` };
88
+ }
89
+ if (command === "api") {
90
+ const sub = value;
91
+ const inputRaw = flagValue(argv, "--input");
92
+ if (!sub || !inputRaw) {
93
+ return { ok: false, exitCode: 1, message: "team api <sub> --input '<json>' required" };
94
+ }
95
+ let input;
96
+ try {
97
+ input = JSON.parse(inputRaw);
98
+ }
99
+ catch (error) {
100
+ const message = error instanceof Error ? error.message : String(error);
101
+ return { ok: false, exitCode: 1, message: `invalid --input JSON: ${message}` };
102
+ }
103
+ const api = await import("../team/api.js");
104
+ if (sub === "claim-task") {
105
+ const result = api.apiClaimTask(input);
106
+ return json
107
+ ? { ok: result.ok, exitCode: result.ok ? 0 : 1, output: result }
108
+ : { ok: result.ok, exitCode: result.ok ? 0 : 1, message: JSON.stringify(result) };
109
+ }
110
+ if (sub === "transition-task-status") {
111
+ const result = api.apiTransitionTaskStatus(input);
112
+ return json
113
+ ? { ok: result.ok, exitCode: result.ok ? 0 : 1, output: result }
114
+ : { ok: result.ok, exitCode: result.ok ? 0 : 1, message: JSON.stringify(result) };
115
+ }
116
+ if (sub === "send-message") {
117
+ const result = await api.apiSendMessage(input);
118
+ return json
119
+ ? { ok: result.ok, exitCode: result.ok ? 0 : 1, output: result }
120
+ : { ok: result.ok, exitCode: result.ok ? 0 : 1, message: JSON.stringify(result) };
121
+ }
122
+ if (sub === "broadcast") {
123
+ const result = await api.apiBroadcast(input);
124
+ return json
125
+ ? { ok: result.ok, exitCode: result.ok ? 0 : 1, output: result }
126
+ : { ok: result.ok, exitCode: result.ok ? 0 : 1, message: JSON.stringify(result) };
127
+ }
128
+ if (sub === "mailbox-list") {
129
+ const result = api.apiMailboxList(input);
130
+ return json
131
+ ? { ok: result.ok, exitCode: result.ok ? 0 : 1, output: result }
132
+ : { ok: result.ok, exitCode: result.ok ? 0 : 1, message: JSON.stringify(result) };
133
+ }
134
+ if (sub === "mailbox-mark-delivered") {
135
+ const result = api.apiMailboxMarkDelivered(input);
136
+ return json
137
+ ? { ok: result.ok, exitCode: result.ok ? 0 : 1, output: result }
138
+ : { ok: result.ok, exitCode: result.ok ? 0 : 1, message: JSON.stringify(result) };
139
+ }
140
+ return { ok: false, exitCode: 1, message: `Unknown team api command: ${sub}` };
141
+ }
142
+ // tolerate trailing extras (e.g., '--json')
143
+ void extra;
144
+ return { ok: false, exitCode: 1, message: `Unknown team command. Try: omp team <N:role> "<task>" | status <name> | shutdown <name> | api <sub>` };
145
+ }
146
+ //# sourceMappingURL=team.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"team.js","sourceRoot":"","sources":["../../../src/commands/team.ts"],"names":[],"mappings":"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"}
@@ -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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"}
@@ -0,0 +1,56 @@
1
+ export interface DesktopNotifyOptions {
2
+ title: string;
3
+ message: string;
4
+ /** URL or absolute file path to open when the notification is clicked (click-capable transports only). */
5
+ open?: string;
6
+ }
7
+ /** Resolved, non-empty payload handed to a transport. */
8
+ export interface ResolvedPayload {
9
+ title: string;
10
+ message: string;
11
+ open?: string;
12
+ }
13
+ /** Minimal slice of node-notifier we depend on (also a test seam). */
14
+ export interface Notifier {
15
+ notify(opts: Record<string, unknown>, cb?: (err: Error | null) => void): void;
16
+ }
17
+ /** Low-level command runner (test seam). Never throws; returns the structured result. */
18
+ export type ExecFn = (file: string, args: string[], timeoutMs: number) => Promise<DesktopNotifyResult>;
19
+ /** A delivery transport (test seam — bypasses platform selection entirely). */
20
+ export type Transport = (payload: ResolvedPayload, timeoutMs: number) => Promise<DesktopNotifyResult>;
21
+ export interface DesktopNotifyDeps {
22
+ /** Override env (tests). Defaults to process.env. */
23
+ env?: NodeJS.ProcessEnv;
24
+ /** Override platform (tests). Defaults to process.platform. */
25
+ platform?: NodeJS.Platform;
26
+ /** Max wait for delivery before giving up. Default 15s. */
27
+ timeoutMs?: number;
28
+ /** Inject the full transport (tests) — bypasses platform selection. */
29
+ transport?: Transport;
30
+ /** Inject the command runner (tests) for the macOS transports. */
31
+ exec?: ExecFn;
32
+ /** Inject system-terminal-notifier availability (tests). Defaults to a PATH lookup. */
33
+ hasSystemTerminalNotifier?: boolean;
34
+ /** Inject node-notifier (tests) for the non-macOS transport. */
35
+ notifier?: Notifier;
36
+ }
37
+ export type DesktopNotifyResult = {
38
+ ok: true;
39
+ skipped?: boolean;
40
+ } | {
41
+ ok: false;
42
+ reason: string;
43
+ };
44
+ /**
45
+ * Build the argv for `osascript`. The message/title are passed as `argv` items
46
+ * (via `on run argv`), never interpolated into the AppleScript source, so an
47
+ * arbitrary run summary cannot inject AppleScript.
48
+ */
49
+ export declare function buildOsascriptArgs(title: string, message: string): string[];
50
+ /**
51
+ * Fire a desktop notification. Library entry point — never throws.
52
+ * Skips silently (ok:true, skipped) when disabled or on a headless host.
53
+ */
54
+ export declare function notifyDesktop(opts: DesktopNotifyOptions, deps?: DesktopNotifyDeps): Promise<DesktopNotifyResult>;
55
+ /** True only when neither the PATH entry nor its real (symlink-resolved) target is under node_modules. */
56
+ export declare function isSystemNotifierPath(resolved: string, real: string): boolean;
@@ -0,0 +1,183 @@
1
+ /**
2
+ * Native desktop notifier — Hermes-style sibling of gateway/notify.ts. No daemon.
3
+ * Each call is a one-shot, best-effort native OS notification.
4
+ *
5
+ * Platform transports (the bundled node-notifier terminal-notifier does NOT
6
+ * display on modern macOS — it is an unsigned app run from node_modules — so we
7
+ * do not use it there):
8
+ * - macOS: `osascript display notification` by default — the only path that
9
+ * reliably DISPLAYS on macOS Sequoia. It cannot carry a click action. A
10
+ * system `terminal-notifier` (which supports the click `-open` deep-link)
11
+ * is used only when OMP_NOTIFY_USE_TERMINAL_NOTIFIER is set, since it does
12
+ * not display on some Sequoia builds.
13
+ * - Linux/Windows: node-notifier (notify-send / SnoreToast).
14
+ *
15
+ * Contract (mirrors notify.ts): NEVER throws. Returns a structured result so the
16
+ * caller (the schedule runner) can log a dropped notification to stderr without
17
+ * the failure ever propagating into the job result. A bounded timeout means a
18
+ * wedged backend can never hang `omp schedule run`; the osascript/terminal-notifier
19
+ * children are our own and are killed on timeout.
20
+ */
21
+ import { execFile, execFileSync } from "node:child_process";
22
+ import { realpathSync } from "node:fs";
23
+ /**
24
+ * Bound on how long we wait for delivery (a hung backend must not stall cron).
25
+ * Kept comfortably above node-notifier's own ~10s display timeout so a slow but
26
+ * successful delivery is not misclassified as a timeout.
27
+ */
28
+ const DEFAULT_TIMEOUT_MS = 15_000;
29
+ /**
30
+ * Build the argv for `osascript`. The message/title are passed as `argv` items
31
+ * (via `on run argv`), never interpolated into the AppleScript source, so an
32
+ * arbitrary run summary cannot inject AppleScript.
33
+ */
34
+ export function buildOsascriptArgs(title, message) {
35
+ return [
36
+ "-e",
37
+ "on run argv",
38
+ "-e",
39
+ "display notification (item 1 of argv) with title (item 2 of argv)",
40
+ "-e",
41
+ "end run",
42
+ "--",
43
+ message,
44
+ title,
45
+ ];
46
+ }
47
+ /**
48
+ * Fire a desktop notification. Library entry point — never throws.
49
+ * Skips silently (ok:true, skipped) when disabled or on a headless host.
50
+ */
51
+ export async function notifyDesktop(opts, deps = {}) {
52
+ const env = deps.env ?? process.env;
53
+ const platform = deps.platform ?? process.platform;
54
+ // Skips win first — a disabled/headless host produces no artifact and no error.
55
+ if ((env.OMP_DISABLE_DESKTOP_NOTIFY ?? "").trim()) {
56
+ return { ok: true, skipped: true };
57
+ }
58
+ if (platform === "linux" && !env.DISPLAY && !env.WAYLAND_DISPLAY) {
59
+ return { ok: true, skipped: true };
60
+ }
61
+ const title = (opts.title ?? "").trim();
62
+ const message = (opts.message ?? "").trim();
63
+ if (!title && !message) {
64
+ return { ok: false, reason: "title and message are both empty" };
65
+ }
66
+ const payload = { title: title || message, message, open: opts.open };
67
+ const timeoutMs = deps.timeoutMs ?? DEFAULT_TIMEOUT_MS;
68
+ try {
69
+ const transport = deps.transport ?? selectTransport(platform, deps);
70
+ return await withTimeout(() => transport(payload, timeoutMs), timeoutMs);
71
+ }
72
+ catch (err) {
73
+ return { ok: false, reason: errMsg(err) };
74
+ }
75
+ }
76
+ /** Pick the delivery transport for this host. */
77
+ function selectTransport(platform, deps) {
78
+ const exec = deps.exec ?? realExec;
79
+ if (platform === "darwin") {
80
+ // Default to osascript: it is the one path that reliably displays on macOS
81
+ // Sequoia. A system terminal-notifier (which supports the click `-open`
82
+ // deep-link) is used ONLY when explicitly opted in, because it does not
83
+ // display on some Sequoia builds — preferring it would silently break
84
+ // notifications. See OMP_NOTIFY_USE_TERMINAL_NOTIFIER.
85
+ const env = deps.env ?? process.env;
86
+ const optIn = Boolean((env.OMP_NOTIFY_USE_TERMINAL_NOTIFIER ?? "").trim());
87
+ const tnCommand = optIn ? resolveTerminalNotifier(deps) : null;
88
+ return (payload, timeoutMs) => deliverMac(payload, exec, tnCommand, timeoutMs);
89
+ }
90
+ return (payload, timeoutMs) => deliverNodeNotifier(payload, deps, timeoutMs);
91
+ }
92
+ /** The terminal-notifier command to exec (validated absolute path), or null to use osascript. */
93
+ function resolveTerminalNotifier(deps) {
94
+ if (deps.hasSystemTerminalNotifier !== undefined) {
95
+ return deps.hasSystemTerminalNotifier ? "terminal-notifier" : null;
96
+ }
97
+ return detectSystemTerminalNotifier();
98
+ }
99
+ /** macOS: osascript displays reliably (no click); opt-in terminal-notifier adds the click `-open`. */
100
+ function deliverMac(p, exec, tnCommand, timeoutMs) {
101
+ if (tnCommand) {
102
+ const args = ["-title", p.title, "-message", p.message, ...(p.open ? ["-open", p.open] : [])];
103
+ return exec(tnCommand, args, timeoutMs);
104
+ }
105
+ return exec("osascript", buildOsascriptArgs(p.title, p.message), timeoutMs);
106
+ }
107
+ /** Non-macOS: node-notifier (notify-send / SnoreToast), bounded by the outer timeout. */
108
+ async function deliverNodeNotifier(p, deps, _timeoutMs) {
109
+ const notifier = deps.notifier ?? (await loadNotifier());
110
+ const opts = { title: p.title, message: p.message, sound: false };
111
+ if (p.open)
112
+ opts.open = p.open;
113
+ return new Promise((resolve) => {
114
+ try {
115
+ notifier.notify(opts, (err) => resolve(err ? { ok: false, reason: err.message } : { ok: true }));
116
+ }
117
+ catch (err) {
118
+ resolve({ ok: false, reason: errMsg(err) });
119
+ }
120
+ });
121
+ }
122
+ /** Race a delivery against a bounded timeout. The timer stays referenced so it fires. */
123
+ function withTimeout(fn, timeoutMs) {
124
+ return new Promise((resolve) => {
125
+ let settled = false;
126
+ const done = (r) => {
127
+ if (settled)
128
+ return;
129
+ settled = true;
130
+ clearTimeout(timer);
131
+ resolve(r);
132
+ };
133
+ const timer = setTimeout(() => done({ ok: false, reason: `desktop notify timed out after ${timeoutMs}ms` }), timeoutMs);
134
+ Promise.resolve()
135
+ .then(fn)
136
+ .then(done, (err) => done({ ok: false, reason: errMsg(err) }));
137
+ });
138
+ }
139
+ /** Real command runner: execFile with its own kill-on-timeout (our child, we own it). */
140
+ const realExec = (file, args, timeoutMs) => new Promise((resolve) => {
141
+ execFile(file, args, { timeout: Math.max(1_000, timeoutMs) }, (err) => {
142
+ resolve(err ? { ok: false, reason: (err.message || String(err)).slice(0, 200) } : { ok: true });
143
+ });
144
+ });
145
+ /** True only when neither the PATH entry nor its real (symlink-resolved) target is under node_modules. */
146
+ export function isSystemNotifierPath(resolved, real) {
147
+ if (!resolved)
148
+ return false;
149
+ const hasNodeModules = (p) => p.split(/[\\/]/).includes("node_modules");
150
+ return !hasNodeModules(resolved) && !hasNodeModules(real);
151
+ }
152
+ /**
153
+ * Resolve a SYSTEM terminal-notifier to its validated absolute path, or null.
154
+ * Resolves the symlink target too, so a PATH symlink pointing at node-notifier's
155
+ * bundled copy is rejected (it does not display on Sequoia and isn't "system").
156
+ */
157
+ function detectSystemTerminalNotifier() {
158
+ try {
159
+ const resolved = execFileSync("which", ["terminal-notifier"], { encoding: "utf8" }).trim();
160
+ if (!resolved)
161
+ return null;
162
+ let real = resolved;
163
+ try {
164
+ real = realpathSync(resolved);
165
+ }
166
+ catch {
167
+ // keep `resolved` if the realpath lookup fails
168
+ }
169
+ return isSystemNotifierPath(resolved, real) ? real : null;
170
+ }
171
+ catch {
172
+ return null;
173
+ }
174
+ }
175
+ /** Lazy-load node-notifier so non-notifying CLI paths never pay for the dependency. */
176
+ async function loadNotifier() {
177
+ const mod = (await import("node-notifier"));
178
+ return mod.default ?? mod;
179
+ }
180
+ function errMsg(err) {
181
+ return err instanceof Error ? err.message : String(err);
182
+ }
183
+ //# sourceMappingURL=desktop-notify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"desktop-notify.js","sourceRoot":"","sources":["../../../src/gateway/desktop-notify.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