oh-my-codex 0.19.0 → 0.19.1
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.
- package/Cargo.lock +6 -6
- package/Cargo.toml +1 -1
- package/README.md +5 -0
- package/dist/cli/__tests__/mission.test.d.ts +2 -0
- package/dist/cli/__tests__/mission.test.d.ts.map +1 -0
- package/dist/cli/__tests__/mission.test.js +239 -0
- package/dist/cli/__tests__/mission.test.js.map +1 -0
- package/dist/cli/__tests__/session-scoped-runtime.test.js +67 -0
- package/dist/cli/__tests__/session-scoped-runtime.test.js.map +1 -1
- package/dist/cli/__tests__/ultragoal.test.js +1 -1
- package/dist/cli/index.d.ts +2 -2
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +30 -4
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/mission.d.ts +36 -0
- package/dist/cli/mission.d.ts.map +1 -0
- package/dist/cli/mission.js +443 -0
- package/dist/cli/mission.js.map +1 -0
- package/dist/hud/__tests__/state.test.js +31 -6
- package/dist/hud/__tests__/state.test.js.map +1 -1
- package/dist/hud/state.d.ts.map +1 -1
- package/dist/hud/state.js +7 -3
- package/dist/hud/state.js.map +1 -1
- package/dist/mcp/__tests__/state-paths.test.js +32 -1
- package/dist/mcp/__tests__/state-paths.test.js.map +1 -1
- package/dist/mcp/state-paths.d.ts +4 -0
- package/dist/mcp/state-paths.d.ts.map +1 -1
- package/dist/mcp/state-paths.js +6 -15
- package/dist/mcp/state-paths.js.map +1 -1
- package/dist/ralplan/__tests__/consensus-gate.test.js +193 -0
- package/dist/ralplan/__tests__/consensus-gate.test.js.map +1 -1
- package/dist/ralplan/consensus-gate.js +24 -3
- package/dist/ralplan/consensus-gate.js.map +1 -1
- package/dist/scripts/__tests__/codex-native-hook.test.js +330 -0
- package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -1
- package/dist/scripts/codex-native-hook.d.ts.map +1 -1
- package/dist/scripts/codex-native-hook.js +68 -10
- package/dist/scripts/codex-native-hook.js.map +1 -1
- package/dist/scripts/generate-catalog-docs.js +1 -0
- package/dist/scripts/generate-catalog-docs.js.map +1 -1
- package/dist/state/__tests__/operations.test.js +287 -0
- package/dist/state/__tests__/operations.test.js.map +1 -1
- package/dist/state/__tests__/skill-active.test.js +59 -0
- package/dist/state/__tests__/skill-active.test.js.map +1 -1
- package/dist/state/operations.d.ts.map +1 -1
- package/dist/state/operations.js +8 -6
- package/dist/state/operations.js.map +1 -1
- package/dist/state/skill-active.js +3 -3
- package/dist/state/skill-active.js.map +1 -1
- package/dist/ultragoal/__tests__/artifacts.test.js +14 -4
- package/dist/ultragoal/__tests__/artifacts.test.js.map +1 -1
- package/dist/ultragoal/artifacts.d.ts.map +1 -1
- package/dist/ultragoal/artifacts.js +70 -5
- package/dist/ultragoal/artifacts.js.map +1 -1
- package/package.json +1 -1
- package/plugins/oh-my-codex/.codex-plugin/plugin.json +1 -1
- package/src/scripts/__tests__/codex-native-hook.test.ts +340 -0
- package/src/scripts/codex-native-hook.ts +75 -9
- package/src/scripts/generate-catalog-docs.ts +1 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export declare const MISSION_HELP = "omx mission - Run a prompt checklist sequentially through omx exec\n\nUsage:\n omx mission <file> [--dry-run] [--continue-on-error] [--summary <path>] [--slug <name>] [--json] [-- <codex exec args...>]\n omx mission run <file> [options]\n omx mission plan <file> [--json]\n omx mission status <file|slug> [--json] [--summary <path>]\n omx mission mark <file|slug> --task <id> --status <blocked|needs-human-review> [--json] [--summary <path>]\n omx mission resume <file> [--continue-on-error] [--summary <path>] [--json] [-- <codex exec args...>]\n omx mission rerun <file> --task <id> [--summary <path>] [--json] [-- <codex exec args...>]\n\nInput format:\n - One task per non-empty line\n - Markdown bullets, numbered lists, and checkboxes are accepted\n - Markdown headings and HTML comments are ignored\n\nArtifacts:\n .omx/missions/<slug>/summary.json\n .omx/missions/<slug>/ledger.jsonl\n\nExamples:\n omx mission ./mission.md --dry-run\n omx mission status ./mission.md\n omx mission resume ./mission.md -- --model gpt-5\n omx mission mark ./mission.md --task task-002 --status needs-human-review\n omx mission rerun ./mission.md --task task-002\n";
|
|
2
|
+
type MissionTaskStatus = "pending" | "planned" | "running" | "passed" | "failed" | "skipped" | "blocked" | "needs-human-review";
|
|
3
|
+
export interface MissionTask {
|
|
4
|
+
id: string;
|
|
5
|
+
index: number;
|
|
6
|
+
prompt: string;
|
|
7
|
+
source_line: number;
|
|
8
|
+
status: MissionTaskStatus;
|
|
9
|
+
started_at?: string;
|
|
10
|
+
completed_at?: string;
|
|
11
|
+
exit_code?: number;
|
|
12
|
+
}
|
|
13
|
+
export interface MissionSummary {
|
|
14
|
+
version: 1;
|
|
15
|
+
slug: string;
|
|
16
|
+
input_path: string;
|
|
17
|
+
dry_run: boolean;
|
|
18
|
+
continue_on_error: boolean;
|
|
19
|
+
started_at: string;
|
|
20
|
+
completed_at?: string;
|
|
21
|
+
status: "planned" | "running" | "passed" | "failed" | "blocked" | "needs-human-review";
|
|
22
|
+
counts: Record<"total" | "planned" | "passed" | "failed" | "skipped" | "blocked" | "needs-human-review", number>;
|
|
23
|
+
codex_args: string[];
|
|
24
|
+
tasks: MissionTask[];
|
|
25
|
+
}
|
|
26
|
+
export interface MissionCommandOptions {
|
|
27
|
+
cwd?: string;
|
|
28
|
+
now?: () => Date;
|
|
29
|
+
stdout?: (line: string) => void;
|
|
30
|
+
stderr?: (line: string) => void;
|
|
31
|
+
runTask?: (prompt: string, codexArgs: string[]) => Promise<number>;
|
|
32
|
+
}
|
|
33
|
+
export declare function parseMissionTasks(input: string): MissionTask[];
|
|
34
|
+
export declare function missionCommand(args: string[], options?: MissionCommandOptions): Promise<void>;
|
|
35
|
+
export {};
|
|
36
|
+
//# sourceMappingURL=mission.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mission.d.ts","sourceRoot":"","sources":["../../src/cli/mission.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,YAAY,upCA0BxB,CAAC;AAEF,KAAK,iBAAiB,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,oBAAoB,CAAC;AAGhI,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,CAAC,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,oBAAoB,CAAC;IACvF,MAAM,EAAE,MAAM,CAAC,OAAO,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,oBAAoB,EAAE,MAAM,CAAC,CAAC;IACjH,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,KAAK,EAAE,WAAW,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,qBAAqB;IACpC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;IACjB,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CACpE;AAiCD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,EAAE,CAqB9D;AAgPD,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,GAAE,qBAA0B,GAAG,OAAO,CAAC,IAAI,CAAC,CA2IvG"}
|
|
@@ -0,0 +1,443 @@
|
|
|
1
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import { basename, dirname, extname, isAbsolute, join, resolve } from "node:path";
|
|
3
|
+
import { omxRoot } from "../utils/paths.js";
|
|
4
|
+
export const MISSION_HELP = `omx mission - Run a prompt checklist sequentially through omx exec
|
|
5
|
+
|
|
6
|
+
Usage:
|
|
7
|
+
omx mission <file> [--dry-run] [--continue-on-error] [--summary <path>] [--slug <name>] [--json] [-- <codex exec args...>]
|
|
8
|
+
omx mission run <file> [options]
|
|
9
|
+
omx mission plan <file> [--json]
|
|
10
|
+
omx mission status <file|slug> [--json] [--summary <path>]
|
|
11
|
+
omx mission mark <file|slug> --task <id> --status <blocked|needs-human-review> [--json] [--summary <path>]
|
|
12
|
+
omx mission resume <file> [--continue-on-error] [--summary <path>] [--json] [-- <codex exec args...>]
|
|
13
|
+
omx mission rerun <file> --task <id> [--summary <path>] [--json] [-- <codex exec args...>]
|
|
14
|
+
|
|
15
|
+
Input format:
|
|
16
|
+
- One task per non-empty line
|
|
17
|
+
- Markdown bullets, numbered lists, and checkboxes are accepted
|
|
18
|
+
- Markdown headings and HTML comments are ignored
|
|
19
|
+
|
|
20
|
+
Artifacts:
|
|
21
|
+
.omx/missions/<slug>/summary.json
|
|
22
|
+
.omx/missions/<slug>/ledger.jsonl
|
|
23
|
+
|
|
24
|
+
Examples:
|
|
25
|
+
omx mission ./mission.md --dry-run
|
|
26
|
+
omx mission status ./mission.md
|
|
27
|
+
omx mission resume ./mission.md -- --model gpt-5
|
|
28
|
+
omx mission mark ./mission.md --task task-002 --status needs-human-review
|
|
29
|
+
omx mission rerun ./mission.md --task task-002
|
|
30
|
+
`;
|
|
31
|
+
class MissionCommandError extends Error {
|
|
32
|
+
}
|
|
33
|
+
function stripTaskMarker(line) {
|
|
34
|
+
return line
|
|
35
|
+
.replace(/^\s*(?:[-*+]\s+)?\[(?: |x|X)\]\s+/, "")
|
|
36
|
+
.replace(/^\s*[-*+]\s+/, "")
|
|
37
|
+
.replace(/^\s*\d+[.)]\s+/, "")
|
|
38
|
+
.trim();
|
|
39
|
+
}
|
|
40
|
+
export function parseMissionTasks(input) {
|
|
41
|
+
const tasks = [];
|
|
42
|
+
const lines = input.split(/\r?\n/);
|
|
43
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
44
|
+
const raw = lines[index] ?? "";
|
|
45
|
+
const trimmed = raw.trim();
|
|
46
|
+
if (!trimmed)
|
|
47
|
+
continue;
|
|
48
|
+
if (trimmed.startsWith("#"))
|
|
49
|
+
continue;
|
|
50
|
+
if (/^<!--.*-->$/.test(trimmed))
|
|
51
|
+
continue;
|
|
52
|
+
const prompt = stripTaskMarker(raw);
|
|
53
|
+
if (!prompt)
|
|
54
|
+
continue;
|
|
55
|
+
tasks.push({
|
|
56
|
+
id: `task-${String(tasks.length + 1).padStart(3, "0")}`,
|
|
57
|
+
index: tasks.length + 1,
|
|
58
|
+
prompt,
|
|
59
|
+
source_line: index + 1,
|
|
60
|
+
status: "pending",
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
return tasks;
|
|
64
|
+
}
|
|
65
|
+
function slugify(value) {
|
|
66
|
+
const slug = value
|
|
67
|
+
.toLowerCase()
|
|
68
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
69
|
+
.replace(/^-+|-+$/g, "")
|
|
70
|
+
.slice(0, 80);
|
|
71
|
+
return slug || "mission";
|
|
72
|
+
}
|
|
73
|
+
function readValue(args, index, flag) {
|
|
74
|
+
const value = args[index + 1];
|
|
75
|
+
if (!value || value.startsWith("--"))
|
|
76
|
+
throw new MissionCommandError(`Missing value for ${flag}.`);
|
|
77
|
+
return value;
|
|
78
|
+
}
|
|
79
|
+
function parseMissionArgs(args) {
|
|
80
|
+
let rest = [...args];
|
|
81
|
+
const command = rest[0];
|
|
82
|
+
if (command === "help" || command === "--help" || command === "-h") {
|
|
83
|
+
throw new MissionCommandError(MISSION_HELP);
|
|
84
|
+
}
|
|
85
|
+
let action = "run";
|
|
86
|
+
if (command === "run")
|
|
87
|
+
rest = rest.slice(1);
|
|
88
|
+
else if (command === "plan") {
|
|
89
|
+
action = "plan";
|
|
90
|
+
rest = rest.slice(1);
|
|
91
|
+
}
|
|
92
|
+
else if (command === "status" || command === "mark" || command === "resume" || command === "rerun") {
|
|
93
|
+
action = command;
|
|
94
|
+
rest = rest.slice(1);
|
|
95
|
+
}
|
|
96
|
+
const separator = rest.indexOf("--");
|
|
97
|
+
const commandArgs = separator >= 0 ? rest.slice(0, separator) : rest;
|
|
98
|
+
const codexArgs = separator >= 0 ? rest.slice(separator + 1) : [];
|
|
99
|
+
let file;
|
|
100
|
+
let dryRun = action === "plan";
|
|
101
|
+
let continueOnError = false;
|
|
102
|
+
let json = false;
|
|
103
|
+
let slug;
|
|
104
|
+
let summaryPath;
|
|
105
|
+
let taskId;
|
|
106
|
+
let markStatus;
|
|
107
|
+
for (let index = 0; index < commandArgs.length; index += 1) {
|
|
108
|
+
const arg = commandArgs[index] ?? "";
|
|
109
|
+
if (arg === "--dry-run") {
|
|
110
|
+
if (action !== "run")
|
|
111
|
+
throw new MissionCommandError(`--dry-run is only supported for mission run/plan.`);
|
|
112
|
+
dryRun = true;
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
if (arg === "--continue-on-error") {
|
|
116
|
+
if (action === "status")
|
|
117
|
+
throw new MissionCommandError(`--continue-on-error is not supported for mission status.`);
|
|
118
|
+
continueOnError = true;
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
if (arg === "--json") {
|
|
122
|
+
json = true;
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
if (arg.startsWith("--summary=")) {
|
|
126
|
+
summaryPath = arg.slice("--summary=".length);
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
if (arg === "--summary") {
|
|
130
|
+
summaryPath = readValue(commandArgs, index, arg);
|
|
131
|
+
index += 1;
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
if (arg.startsWith("--slug=")) {
|
|
135
|
+
slug = arg.slice("--slug=".length);
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
if (arg === "--slug") {
|
|
139
|
+
slug = readValue(commandArgs, index, arg);
|
|
140
|
+
index += 1;
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
if (arg.startsWith("--task=")) {
|
|
144
|
+
taskId = arg.slice("--task=".length);
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
if (arg === "--task") {
|
|
148
|
+
taskId = readValue(commandArgs, index, arg);
|
|
149
|
+
index += 1;
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
if (arg.startsWith("--status=")) {
|
|
153
|
+
const value = arg.slice("--status=".length);
|
|
154
|
+
if (value !== "blocked" && value !== "needs-human-review")
|
|
155
|
+
throw new MissionCommandError(`Unsupported mission mark status: ${value}`);
|
|
156
|
+
markStatus = value;
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
if (arg === "--status") {
|
|
160
|
+
const value = readValue(commandArgs, index, arg);
|
|
161
|
+
if (value !== "blocked" && value !== "needs-human-review")
|
|
162
|
+
throw new MissionCommandError(`Unsupported mission mark status: ${value}`);
|
|
163
|
+
markStatus = value;
|
|
164
|
+
index += 1;
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
if (arg.startsWith("--"))
|
|
168
|
+
throw new MissionCommandError(`Unknown mission option: ${arg}`);
|
|
169
|
+
if (!file) {
|
|
170
|
+
file = arg;
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
throw new MissionCommandError(`Unexpected mission argument: ${arg}`);
|
|
174
|
+
}
|
|
175
|
+
if (!file)
|
|
176
|
+
throw new MissionCommandError(`Missing mission input file.\n\n${MISSION_HELP}`);
|
|
177
|
+
if (action !== "rerun" && action !== "mark" && taskId)
|
|
178
|
+
throw new MissionCommandError(`--task is only supported for mission mark/rerun.`);
|
|
179
|
+
if (action === "rerun" && !taskId)
|
|
180
|
+
throw new MissionCommandError(`mission rerun requires --task <id>.`);
|
|
181
|
+
if (action !== "mark" && markStatus)
|
|
182
|
+
throw new MissionCommandError(`--status is only supported for mission mark.`);
|
|
183
|
+
if (action === "mark" && (!taskId || !markStatus))
|
|
184
|
+
throw new MissionCommandError(`mission mark requires --task <id> --status <blocked|needs-human-review>.`);
|
|
185
|
+
return { action, file, dryRun, continueOnError, json, slug, summaryPath, taskId, markStatus, codexArgs };
|
|
186
|
+
}
|
|
187
|
+
function missionCounts(tasks) {
|
|
188
|
+
return {
|
|
189
|
+
total: tasks.length,
|
|
190
|
+
planned: tasks.filter((task) => task.status === "planned").length,
|
|
191
|
+
passed: tasks.filter((task) => task.status === "passed").length,
|
|
192
|
+
failed: tasks.filter((task) => task.status === "failed").length,
|
|
193
|
+
skipped: tasks.filter((task) => task.status === "skipped").length,
|
|
194
|
+
blocked: tasks.filter((task) => task.status === "blocked").length,
|
|
195
|
+
"needs-human-review": tasks.filter((task) => task.status === "needs-human-review").length,
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
function missionStatus(tasks) {
|
|
199
|
+
if (tasks.some((task) => task.status === "running"))
|
|
200
|
+
return "running";
|
|
201
|
+
if (tasks.some((task) => task.status === "blocked"))
|
|
202
|
+
return "blocked";
|
|
203
|
+
if (tasks.some((task) => task.status === "needs-human-review"))
|
|
204
|
+
return "needs-human-review";
|
|
205
|
+
if (tasks.some((task) => task.status === "failed"))
|
|
206
|
+
return "failed";
|
|
207
|
+
if (tasks.length > 0 && tasks.every((task) => task.status === "passed"))
|
|
208
|
+
return "passed";
|
|
209
|
+
return "planned";
|
|
210
|
+
}
|
|
211
|
+
async function persistSummary(summaryPath, summary) {
|
|
212
|
+
await mkdir(dirname(summaryPath), { recursive: true });
|
|
213
|
+
await writeFile(summaryPath, `${JSON.stringify(summary, null, 2)}\n`, "utf-8");
|
|
214
|
+
}
|
|
215
|
+
async function appendLedger(ledgerPath, event) {
|
|
216
|
+
await mkdir(dirname(ledgerPath), { recursive: true });
|
|
217
|
+
const existing = await readFile(ledgerPath, "utf-8").catch(() => "");
|
|
218
|
+
await writeFile(ledgerPath, `${existing}${JSON.stringify(event)}\n`, "utf-8");
|
|
219
|
+
}
|
|
220
|
+
function resolveMissionPaths(cwd, parsed) {
|
|
221
|
+
const looksLikePath = parsed.file.includes("/") || parsed.file.includes("\\") || parsed.file.endsWith(".md") || parsed.file.endsWith(".txt");
|
|
222
|
+
const inputPath = isAbsolute(parsed.file) ? parsed.file : resolve(cwd, parsed.file);
|
|
223
|
+
const baseSlug = parsed.slug ?? ((parsed.action === "status" || parsed.action === "mark") && !looksLikePath ? parsed.file : slugify(basename(inputPath, extname(inputPath))));
|
|
224
|
+
const slug = slugify(baseSlug);
|
|
225
|
+
const missionRoot = join(omxRoot(cwd), "missions", slug);
|
|
226
|
+
const summaryPath = parsed.summaryPath
|
|
227
|
+
? (isAbsolute(parsed.summaryPath) ? parsed.summaryPath : resolve(cwd, parsed.summaryPath))
|
|
228
|
+
: join(missionRoot, "summary.json");
|
|
229
|
+
const ledgerPath = join(missionRoot, "ledger.jsonl");
|
|
230
|
+
return { inputPath, slug, missionRoot, summaryPath, ledgerPath };
|
|
231
|
+
}
|
|
232
|
+
async function readSummary(summaryPath) {
|
|
233
|
+
let raw;
|
|
234
|
+
try {
|
|
235
|
+
raw = await readFile(summaryPath, "utf-8");
|
|
236
|
+
}
|
|
237
|
+
catch {
|
|
238
|
+
throw new MissionCommandError(`No mission summary found at ${summaryPath}.`);
|
|
239
|
+
}
|
|
240
|
+
let summary;
|
|
241
|
+
try {
|
|
242
|
+
summary = JSON.parse(raw);
|
|
243
|
+
}
|
|
244
|
+
catch {
|
|
245
|
+
throw new MissionCommandError(`Invalid mission summary at ${summaryPath}.`);
|
|
246
|
+
}
|
|
247
|
+
if (summary.version !== 1 || !Array.isArray(summary.tasks)) {
|
|
248
|
+
throw new MissionCommandError(`Invalid mission summary at ${summaryPath}.`);
|
|
249
|
+
}
|
|
250
|
+
return summary;
|
|
251
|
+
}
|
|
252
|
+
function syncSummary(summary, updates) {
|
|
253
|
+
Object.assign(summary, updates);
|
|
254
|
+
summary.counts = missionCounts(summary.tasks);
|
|
255
|
+
}
|
|
256
|
+
async function runSelectedTasks(summary, paths, parsed, now, stdout, runTask, shouldRun) {
|
|
257
|
+
let failed = false;
|
|
258
|
+
for (const task of summary.tasks) {
|
|
259
|
+
if (!shouldRun(task))
|
|
260
|
+
continue;
|
|
261
|
+
if (failed && !parsed.continueOnError) {
|
|
262
|
+
task.status = "skipped";
|
|
263
|
+
delete task.started_at;
|
|
264
|
+
delete task.completed_at;
|
|
265
|
+
delete task.exit_code;
|
|
266
|
+
continue;
|
|
267
|
+
}
|
|
268
|
+
task.status = "running";
|
|
269
|
+
task.started_at = now().toISOString();
|
|
270
|
+
delete task.completed_at;
|
|
271
|
+
delete task.exit_code;
|
|
272
|
+
syncSummary(summary, { status: "running" });
|
|
273
|
+
await persistSummary(paths.summaryPath, summary);
|
|
274
|
+
await appendLedger(paths.ledgerPath, { event: "task_started", at: task.started_at, slug: summary.slug, task_id: task.id, index: task.index, prompt: task.prompt });
|
|
275
|
+
stdout(`[running] ${task.id}/${summary.tasks.length}: ${task.prompt}`);
|
|
276
|
+
const exitCode = await runTask(task.prompt, parsed.codexArgs);
|
|
277
|
+
task.exit_code = exitCode;
|
|
278
|
+
task.completed_at = now().toISOString();
|
|
279
|
+
task.status = exitCode === 0 ? "passed" : "failed";
|
|
280
|
+
if (exitCode !== 0)
|
|
281
|
+
failed = true;
|
|
282
|
+
syncSummary(summary, { status: missionStatus(summary.tasks) });
|
|
283
|
+
await persistSummary(paths.summaryPath, summary);
|
|
284
|
+
await appendLedger(paths.ledgerPath, { event: "task_completed", at: task.completed_at, slug: summary.slug, task_id: task.id, status: task.status, exit_code: exitCode });
|
|
285
|
+
stdout(`[${task.status}] ${task.id}/${summary.tasks.length}: exit ${exitCode}`);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
function printStatus(summary, summaryPath, json, stdout) {
|
|
289
|
+
if (json) {
|
|
290
|
+
stdout(JSON.stringify({ ok: summary.status === "passed", summary_path: summaryPath, summary }, null, 2));
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
stdout(`mission status: ${summary.slug} [${summary.status}]`);
|
|
294
|
+
stdout(`tasks: ${summary.counts.passed}/${summary.counts.total} passed, ${summary.counts.failed} failed, ${summary.counts.skipped} skipped, ${summary.counts.blocked} blocked, ${summary.counts["needs-human-review"]} needs-human-review, ${summary.counts.planned} planned`);
|
|
295
|
+
for (const task of summary.tasks)
|
|
296
|
+
stdout(`[${task.status}] ${task.id} line ${task.source_line}: ${task.prompt}`);
|
|
297
|
+
stdout(`summary: ${summaryPath}`);
|
|
298
|
+
}
|
|
299
|
+
export async function missionCommand(args, options = {}) {
|
|
300
|
+
const cwd = options.cwd ?? process.cwd();
|
|
301
|
+
const now = options.now ?? (() => new Date());
|
|
302
|
+
const stdout = options.stdout ?? ((line) => console.log(line));
|
|
303
|
+
const stderr = options.stderr ?? ((line) => console.error(line));
|
|
304
|
+
try {
|
|
305
|
+
const parsed = parseMissionArgs(args);
|
|
306
|
+
const paths = resolveMissionPaths(cwd, parsed);
|
|
307
|
+
if (parsed.action === "status") {
|
|
308
|
+
const summary = await readSummary(paths.summaryPath);
|
|
309
|
+
syncSummary(summary, { status: missionStatus(summary.tasks) });
|
|
310
|
+
printStatus(summary, paths.summaryPath, parsed.json, stdout);
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
if (parsed.action === "mark") {
|
|
314
|
+
const summary = await readSummary(paths.summaryPath);
|
|
315
|
+
const task = summary.tasks.find((candidate) => candidate.id === parsed.taskId);
|
|
316
|
+
if (!task)
|
|
317
|
+
throw new MissionCommandError(`No mission task found for --task ${parsed.taskId}.`);
|
|
318
|
+
task.status = parsed.markStatus ?? task.status;
|
|
319
|
+
task.completed_at = now().toISOString();
|
|
320
|
+
delete task.exit_code;
|
|
321
|
+
syncSummary(summary, { status: missionStatus(summary.tasks) });
|
|
322
|
+
await persistSummary(paths.summaryPath, summary);
|
|
323
|
+
await appendLedger(paths.ledgerPath, { event: "task_marked", at: task.completed_at, slug: summary.slug, task_id: task.id, status: task.status });
|
|
324
|
+
if (parsed.json)
|
|
325
|
+
stdout(JSON.stringify({ ok: true, summary_path: paths.summaryPath, ledger_path: paths.ledgerPath, summary }, null, 2));
|
|
326
|
+
else {
|
|
327
|
+
stdout(`mission task marked ${task.status}: ${summary.slug} ${task.id}`);
|
|
328
|
+
stdout(`summary: ${paths.summaryPath}`);
|
|
329
|
+
stdout(`ledger: ${paths.ledgerPath}`);
|
|
330
|
+
}
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
if (parsed.action === "resume" || parsed.action === "rerun") {
|
|
334
|
+
const summary = await readSummary(paths.summaryPath);
|
|
335
|
+
const runTask = options.runTask;
|
|
336
|
+
if (!runTask)
|
|
337
|
+
throw new MissionCommandError("Mission execution requires a task runner; use status for read-only inspection.");
|
|
338
|
+
if (parsed.action === "rerun" && !summary.tasks.some((task) => task.id === parsed.taskId)) {
|
|
339
|
+
throw new MissionCommandError(`No mission task found for --task ${parsed.taskId}.`);
|
|
340
|
+
}
|
|
341
|
+
summary.input_path = paths.inputPath;
|
|
342
|
+
summary.dry_run = false;
|
|
343
|
+
summary.continue_on_error = parsed.continueOnError;
|
|
344
|
+
summary.codex_args = parsed.codexArgs;
|
|
345
|
+
summary.status = "running";
|
|
346
|
+
delete summary.completed_at;
|
|
347
|
+
for (const task of summary.tasks) {
|
|
348
|
+
if (task.status === "running")
|
|
349
|
+
task.status = "pending";
|
|
350
|
+
}
|
|
351
|
+
syncSummary(summary, { status: "running" });
|
|
352
|
+
await persistSummary(paths.summaryPath, summary);
|
|
353
|
+
await appendLedger(paths.ledgerPath, { event: parsed.action === "resume" ? "mission_resumed" : "mission_rerun_started", at: now().toISOString(), slug: summary.slug, summary_path: paths.summaryPath, task_id: parsed.taskId });
|
|
354
|
+
const shouldRun = parsed.action === "resume"
|
|
355
|
+
? (task) => task.status !== "passed" && task.status !== "blocked" && task.status !== "needs-human-review"
|
|
356
|
+
: (task) => task.id === parsed.taskId;
|
|
357
|
+
await runSelectedTasks(summary, paths, parsed, now, stdout, runTask, shouldRun);
|
|
358
|
+
summary.status = missionStatus(summary.tasks);
|
|
359
|
+
summary.completed_at = now().toISOString();
|
|
360
|
+
summary.counts = missionCounts(summary.tasks);
|
|
361
|
+
await persistSummary(paths.summaryPath, summary);
|
|
362
|
+
await appendLedger(paths.ledgerPath, { event: "mission_completed", at: summary.completed_at, slug: summary.slug, status: summary.status, counts: summary.counts });
|
|
363
|
+
if (parsed.json)
|
|
364
|
+
stdout(JSON.stringify({ ok: summary.status === "passed", summary_path: paths.summaryPath, ledger_path: paths.ledgerPath, summary }, null, 2));
|
|
365
|
+
else {
|
|
366
|
+
stdout(`mission ${parsed.action} ${summary.status}: ${summary.slug}`);
|
|
367
|
+
stdout(`summary: ${paths.summaryPath}`);
|
|
368
|
+
stdout(`ledger: ${paths.ledgerPath}`);
|
|
369
|
+
}
|
|
370
|
+
if (summary.status !== "passed")
|
|
371
|
+
process.exitCode = 1;
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
374
|
+
const input = await readFile(paths.inputPath, "utf-8");
|
|
375
|
+
const tasks = parseMissionTasks(input);
|
|
376
|
+
if (tasks.length === 0)
|
|
377
|
+
throw new MissionCommandError(`No runnable mission tasks found in ${parsed.file}.`);
|
|
378
|
+
const startedAt = now().toISOString();
|
|
379
|
+
const summary = {
|
|
380
|
+
version: 1,
|
|
381
|
+
slug: paths.slug,
|
|
382
|
+
input_path: paths.inputPath,
|
|
383
|
+
dry_run: parsed.dryRun,
|
|
384
|
+
continue_on_error: parsed.continueOnError,
|
|
385
|
+
started_at: startedAt,
|
|
386
|
+
status: parsed.dryRun ? "planned" : "running",
|
|
387
|
+
counts: missionCounts(tasks),
|
|
388
|
+
codex_args: parsed.codexArgs,
|
|
389
|
+
tasks,
|
|
390
|
+
};
|
|
391
|
+
if (parsed.dryRun) {
|
|
392
|
+
for (const task of summary.tasks)
|
|
393
|
+
task.status = "planned";
|
|
394
|
+
summary.counts = missionCounts(summary.tasks);
|
|
395
|
+
summary.completed_at = now().toISOString();
|
|
396
|
+
await persistSummary(paths.summaryPath, summary);
|
|
397
|
+
await appendLedger(paths.ledgerPath, { event: "mission_planned", at: summary.completed_at, slug: paths.slug, total: tasks.length, summary_path: paths.summaryPath });
|
|
398
|
+
if (parsed.json)
|
|
399
|
+
stdout(JSON.stringify({ ok: true, summary_path: paths.summaryPath, ledger_path: paths.ledgerPath, summary }, null, 2));
|
|
400
|
+
else {
|
|
401
|
+
stdout(`mission planned: ${paths.slug} (${tasks.length} tasks)`);
|
|
402
|
+
for (const task of summary.tasks)
|
|
403
|
+
stdout(`[planned] ${task.id} line ${task.source_line}: ${task.prompt}`);
|
|
404
|
+
stdout(`summary: ${paths.summaryPath}`);
|
|
405
|
+
stdout(`ledger: ${paths.ledgerPath}`);
|
|
406
|
+
}
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
409
|
+
const runTask = options.runTask;
|
|
410
|
+
if (!runTask)
|
|
411
|
+
throw new MissionCommandError("Mission execution requires a task runner; use --dry-run for parser/plan validation.");
|
|
412
|
+
await persistSummary(paths.summaryPath, summary);
|
|
413
|
+
await appendLedger(paths.ledgerPath, { event: "mission_started", at: startedAt, slug: paths.slug, total: tasks.length, summary_path: paths.summaryPath });
|
|
414
|
+
await runSelectedTasks(summary, paths, parsed, now, stdout, runTask, () => true);
|
|
415
|
+
summary.status = missionStatus(summary.tasks);
|
|
416
|
+
summary.completed_at = now().toISOString();
|
|
417
|
+
summary.counts = missionCounts(summary.tasks);
|
|
418
|
+
await persistSummary(paths.summaryPath, summary);
|
|
419
|
+
await appendLedger(paths.ledgerPath, { event: "mission_completed", at: summary.completed_at, slug: paths.slug, status: summary.status, counts: summary.counts });
|
|
420
|
+
if (parsed.json)
|
|
421
|
+
stdout(JSON.stringify({ ok: summary.status === "passed", summary_path: paths.summaryPath, ledger_path: paths.ledgerPath, summary }, null, 2));
|
|
422
|
+
else {
|
|
423
|
+
stdout(`mission ${summary.status}: ${paths.slug}`);
|
|
424
|
+
stdout(`summary: ${paths.summaryPath}`);
|
|
425
|
+
stdout(`ledger: ${paths.ledgerPath}`);
|
|
426
|
+
}
|
|
427
|
+
if (summary.status === "failed")
|
|
428
|
+
process.exitCode = 1;
|
|
429
|
+
}
|
|
430
|
+
catch (error) {
|
|
431
|
+
if (error instanceof MissionCommandError) {
|
|
432
|
+
if (error.message === MISSION_HELP)
|
|
433
|
+
stdout(MISSION_HELP);
|
|
434
|
+
else
|
|
435
|
+
stderr(`[mission] ${error.message}`);
|
|
436
|
+
if (error.message !== MISSION_HELP)
|
|
437
|
+
process.exitCode = 1;
|
|
438
|
+
return;
|
|
439
|
+
}
|
|
440
|
+
throw error;
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
//# sourceMappingURL=mission.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mission.js","sourceRoot":"","sources":["../../src/cli/mission.ts"],"names":[],"mappings":"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"}
|
|
@@ -266,7 +266,7 @@ describe('readUltragoalState', { concurrency: false }, () => {
|
|
|
266
266
|
});
|
|
267
267
|
});
|
|
268
268
|
});
|
|
269
|
-
it('
|
|
269
|
+
it('treats aggregate completion as terminal for HUD while preserving microgoal bookkeeping counts', async () => {
|
|
270
270
|
await withTempRepo('omx-hud-ultragoal-aggregate-active-', async (cwd) => {
|
|
271
271
|
const ultragoalDir = join(cwd, '.omx', 'ultragoal');
|
|
272
272
|
await mkdir(ultragoalDir, { recursive: true });
|
|
@@ -276,7 +276,7 @@ describe('readUltragoalState', { concurrency: false }, () => {
|
|
|
276
276
|
aggregateCompletion: {
|
|
277
277
|
status: 'complete',
|
|
278
278
|
completedAt: '2026-06-01T12:00:00.000Z',
|
|
279
|
-
evidence: 'task-scoped Codex aggregate completed
|
|
279
|
+
evidence: 'task-scoped Codex aggregate completed after strict reconciliation',
|
|
280
280
|
},
|
|
281
281
|
goals: [
|
|
282
282
|
{ id: 'G001-done', title: 'Done', objective: 'Completed prior work', status: 'complete' },
|
|
@@ -285,13 +285,38 @@ describe('readUltragoalState', { concurrency: false }, () => {
|
|
|
285
285
|
],
|
|
286
286
|
}));
|
|
287
287
|
const state = await readUltragoalState(cwd);
|
|
288
|
-
assert.equal(state?.active,
|
|
289
|
-
assert.equal(state?.status, '
|
|
290
|
-
assert.equal(state?.activeGoal
|
|
288
|
+
assert.equal(state?.active, false);
|
|
289
|
+
assert.equal(state?.status, 'complete');
|
|
290
|
+
assert.equal(state?.activeGoal, undefined);
|
|
291
291
|
assert.equal(state?.complete, 1);
|
|
292
292
|
assert.equal(state?.inProgress, 1);
|
|
293
293
|
assert.equal(state?.pending, 1);
|
|
294
|
-
assert.deepEqual(state?.ongoingGoals
|
|
294
|
+
assert.deepEqual(state?.ongoingGoals, []);
|
|
295
|
+
});
|
|
296
|
+
});
|
|
297
|
+
it('treats reconciled task-scoped aggregate completion as inactive in HUD state', async () => {
|
|
298
|
+
await withTempRepo('omx-hud-ultragoal-aggregate-reconciled-', async (cwd) => {
|
|
299
|
+
const ultragoalDir = join(cwd, '.omx', 'ultragoal');
|
|
300
|
+
await mkdir(ultragoalDir, { recursive: true });
|
|
301
|
+
await writeFile(join(ultragoalDir, 'goals.json'), JSON.stringify({
|
|
302
|
+
version: 1,
|
|
303
|
+
aggregateCompletion: {
|
|
304
|
+
status: 'complete',
|
|
305
|
+
completedAt: '2026-06-01T12:00:00.000Z',
|
|
306
|
+
evidence: 'task-scoped Codex aggregate completed and active microgoal row was reconciled',
|
|
307
|
+
},
|
|
308
|
+
goals: [
|
|
309
|
+
{ id: 'G001-reconciled', title: 'Reconciled', objective: 'Finish active repo-native work', status: 'complete', completedAt: '2026-06-01T12:00:00.000Z' },
|
|
310
|
+
],
|
|
311
|
+
}));
|
|
312
|
+
const state = await readUltragoalState(cwd);
|
|
313
|
+
assert.equal(state?.active, false);
|
|
314
|
+
assert.equal(state?.status, 'complete');
|
|
315
|
+
assert.equal(state?.activeGoal, undefined);
|
|
316
|
+
assert.equal(state?.complete, 1);
|
|
317
|
+
assert.equal(state?.inProgress, 0);
|
|
318
|
+
assert.equal(state?.pending, 0);
|
|
319
|
+
assert.deepEqual(state?.ongoingGoals, []);
|
|
295
320
|
});
|
|
296
321
|
});
|
|
297
322
|
it('treats superseded pending ultragoal goals as terminal for HUD activity', async () => {
|