lazycodex-ai 5.0.0-beta.53 → 5.0.0-beta.55

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 (80) hide show
  1. package/dist/cli/index.js +53 -19
  2. package/dist/cli-node/index.js +53 -19
  3. package/package.json +1 -1
  4. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
  5. package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
  6. package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
  7. package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
  8. package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
  9. package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
  10. package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
  11. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
  12. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
  13. package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +2 -2
  14. package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
  15. package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
  16. package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
  17. package/packages/omo-codex/plugin/components/rules/package.json +1 -1
  18. package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
  19. package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
  20. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  21. package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
  22. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  23. package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
  24. package/packages/omo-codex/plugin/components/ulw-execute-continuation/hooks/hooks.json +1 -1
  25. package/packages/omo-codex/plugin/components/ulw-execute-continuation/package.json +1 -1
  26. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-codex-validation.d.ts +5 -1
  27. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-codex-validation.js +14 -34
  28. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-continuation.js +1 -4
  29. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-reconciliation.d.ts +0 -18
  30. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-reconciliation.js +1 -88
  31. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint.d.ts +2 -0
  32. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint.js +10 -3
  33. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-arg-parser.js +2 -2
  34. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-subcommands.js +2 -0
  35. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.js +86 -174
  36. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-snapshot.d.ts +2 -18
  37. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-snapshot.js +23 -33
  38. package/packages/omo-codex/plugin/components/ulw-loop/dist/review-blockers.d.ts +2 -0
  39. package/packages/omo-codex/plugin/components/ulw-loop/dist/review-blockers.js +16 -9
  40. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +5 -5
  41. package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
  42. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-codex-validation.ts +18 -59
  43. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-continuation.ts +1 -6
  44. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-reconciliation.ts +1 -124
  45. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint.ts +11 -3
  46. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-arg-parser.ts +10 -4
  47. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-subcommands.ts +2 -0
  48. package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-snapshot.ts +31 -50
  49. package/packages/omo-codex/plugin/components/ulw-loop/src/review-blockers.ts +29 -10
  50. package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint-final.test.ts +0 -82
  51. package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint.test.ts +16 -22
  52. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-checkpoint.test.ts +27 -0
  53. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-json-errors.test.ts +25 -0
  54. package/packages/omo-codex/plugin/components/ulw-loop/test/codex-goal-snapshot.test.ts +34 -11
  55. package/packages/omo-codex/plugin/components/ulw-loop/test/guided-recovery.test.ts +9 -47
  56. package/packages/omo-codex/plugin/components/ulw-loop/test/review-blockers.test.ts +9 -7
  57. package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
  58. package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
  59. package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
  60. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
  61. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
  62. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
  63. package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
  64. package/packages/omo-codex/plugin/hooks/post-tool-use-recording-spawn-admission.json +1 -1
  65. package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
  66. package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
  67. package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
  68. package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
  69. package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
  70. package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
  71. package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
  72. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-execute-continuation.json +1 -1
  73. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
  74. package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
  75. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
  76. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
  77. package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
  78. package/packages/omo-codex/plugin/package-lock.json +12 -12
  79. package/packages/omo-codex/plugin/package.json +1 -1
  80. package/packages/omo-codex/scripts/install-dist/install-local.mjs +2 -2
@@ -1,42 +1,22 @@
1
- import { canReconcileActiveFinalTaskScopedAggregateSnapshot, canReconcileCompletedTaskScopedAggregateSnapshot, codexSnapshotMismatchError, } from "./checkpoint-reconciliation.js";
2
- import { readCodexGoalSnapshotInput, reconcileCodexGoalSnapshot } from "./codex-goal-snapshot.js";
3
- import { codexGoalMode, compatibleCodexObjectives, expectedCodexObjective, isFinalRunCompletionCandidate, } from "./goal-status.js";
1
+ import { CodexGoalSnapshotError, formatCodexGoalReconciliation, readCodexGoalSnapshotInput, reconcileCodexGoalSnapshot, } from "./codex-goal-snapshot.js";
2
+ import { codexGoalMode, compatibleCodexObjectives, expectedCodexObjective } from "./goal-status.js";
4
3
  import { UlwLoopError } from "./types.js";
5
- function normalizeObjective(value) {
6
- return value.replace(/\s+/g, " ").trim();
7
- }
8
4
  export async function validateCheckpointCodexGoal(input) {
9
- const aggregate = codexGoalMode(input.plan) === "aggregate";
10
- const final = isFinalRunCompletionCandidate(input.plan, input.goal);
11
5
  const snapshot = await readCodexGoalSnapshotInput(input.raw, input.repoRoot);
12
- const expectedObjective = expectedCodexObjective(input.plan, input.goal);
6
+ const expected = expectedCodexObjective(input.plan, input.goal);
13
7
  const reconciliation = reconcileCodexGoalSnapshot(snapshot, {
14
- expectedObjective,
15
- ...(aggregate ? { acceptedObjectives: compatibleCodexObjectives(input.plan) } : {}),
16
- allowedStatuses: aggregate ? (final ? ["complete"] : ["active"]) : ["complete"],
17
- requireSnapshot: true,
18
- requireComplete: !aggregate || final,
19
- });
20
- if (reconciliation.ok)
21
- return reconciliation.snapshot.raw;
22
- const objective = snapshot?.objective;
23
- const mismatchedTaskObjective = snapshot?.available === true &&
24
- objective !== undefined &&
25
- normalizeObjective(objective) !== normalizeObjective(expectedObjective);
26
- const completedTaskScoped = mismatchedTaskObjective &&
27
- snapshot.status === "complete" &&
28
- (await canReconcileCompletedTaskScopedAggregateSnapshot(input.repoRoot, input.plan, input.goal, objective, input.evidence, input.scope));
29
- const activeFinalTaskScoped = mismatchedTaskObjective &&
30
- snapshot.status === "active" &&
31
- (await canReconcileActiveFinalTaskScopedAggregateSnapshot(input.repoRoot, input.plan, input.goal, objective, input.evidence, input.scope));
32
- if (completedTaskScoped || activeFinalTaskScoped)
33
- return reconciliation.snapshot.raw;
34
- throw codexSnapshotMismatchError({
35
- reconciliation,
36
- snapshot,
37
- expectedObjective,
38
- taskScopedHint: { goal: input.goal, aggregate, final },
8
+ expectedObjective: expected,
9
+ ...(codexGoalMode(input.plan) === "aggregate"
10
+ ? { acceptedObjectives: compatibleCodexObjectives(input.plan) }
11
+ : {}),
39
12
  });
13
+ if (!reconciliation.ok)
14
+ throw new CodexGoalSnapshotError(formatCodexGoalReconciliation(reconciliation));
15
+ return {
16
+ raw: snapshot?.raw,
17
+ nextActions: reconciliation.warnings,
18
+ warnings: reconciliation.warnings.filter((warning) => warning.startsWith("driver_objective_differs")),
19
+ };
40
20
  }
41
21
  export function combineCheckpointValidationErrors(codexError, gateError) {
42
22
  return new UlwLoopError(`${codexError.message}\n${gateError.message}`, "ULW_LOOP_QUALITY_GATE_INVALID", {
@@ -27,10 +27,7 @@ export async function checkpoint(repoRoot, argv, json, scope) {
27
27
  const goalId = required(argv, "--goal-id");
28
28
  const statusValue = checkpointStatus(required(argv, "--status"));
29
29
  const evidence = required(argv, "--evidence");
30
- const codexGoalJson = await parseCodexGoalJson(statusValue === "complete" ? required(argv, "--codex-goal-json") : readValue(argv, "--codex-goal-json"));
31
- if (statusValue === "complete" && codexGoalJson === undefined) {
32
- throw new UlwLoopError("Missing --codex-goal-json.", "ULW_LOOP_CODEX_GOAL_JSON_REQUIRED");
33
- }
30
+ const codexGoalJson = await parseCodexGoalJson(readValue(argv, "--codex-goal-json"));
34
31
  const qualityGateJson = readValue(argv, "--quality-gate-json");
35
32
  const args = {
36
33
  goalId,
@@ -1,20 +1,2 @@
1
- import type { CodexGoalReconciliation, CodexGoalSnapshot } from "./codex-goal-snapshot.js";
2
- import { type UlwLoopScope } from "./paths.js";
3
- import type { UlwLoopItem, UlwLoopPlan } from "./types.js";
4
1
  import { UlwLoopError } from "./types.js";
5
- export interface CodexSnapshotMismatchInput {
6
- readonly reconciliation: CodexGoalReconciliation;
7
- readonly snapshot: CodexGoalSnapshot | null | undefined;
8
- readonly expectedObjective: string;
9
- /** Only the checkpoint path can fall back to task-scoped aggregate reconciliation, so only it asks for that hint. */
10
- readonly taskScopedHint?: {
11
- readonly goal: UlwLoopItem;
12
- readonly aggregate: boolean;
13
- readonly final: boolean;
14
- };
15
- }
16
2
  export declare function combineCheckpointValidationErrors(codexError: UlwLoopError, gateError: UlwLoopError): UlwLoopError;
17
- export declare function codexSnapshotMismatchError(input: CodexSnapshotMismatchInput): UlwLoopError;
18
- export declare function canReconcileCompletedTaskScopedAggregateSnapshot(repoRoot: string, plan: UlwLoopPlan, goal: UlwLoopItem, snapshotObjective: string, evidence: string, scope?: UlwLoopScope): Promise<boolean>;
19
- export declare function canReconcileActiveFinalTaskScopedAggregateSnapshot(repoRoot: string, plan: UlwLoopPlan, goal: UlwLoopItem, snapshotObjective: string, evidence: string, scope?: UlwLoopScope): Promise<boolean>;
20
- export declare function buildTaskScopedAggregateReconciliationHint(goal: UlwLoopItem, final: boolean): string;
@@ -1,93 +1,6 @@
1
- import { existsSync } from "node:fs";
2
- import { readFile } from "node:fs/promises";
3
- import { codexGoalMismatchRecovery, formatCodexGoalReconciliation } from "./codex-goal-snapshot.js";
4
- import { codexGoalMode, isFinalRunCompletionCandidate } from "./goal-status.js";
5
- import { ulwLoopBriefPath } from "./paths.js";
6
- import { ULW_LOOP_DIR, ULW_LOOP_GOALS, ULW_LOOP_LEDGER, UlwLoopError } from "./types.js";
1
+ import { UlwLoopError } from "./types.js";
7
2
  export function combineCheckpointValidationErrors(codexError, gateError) {
8
3
  return new UlwLoopError(`${codexError.message}\n${gateError.message}`, "ULW_LOOP_QUALITY_GATE_INVALID", {
9
4
  details: { ...(codexError.details ?? {}), ...(gateError.details ?? {}) },
10
5
  });
11
6
  }
12
- export function codexSnapshotMismatchError(input) {
13
- const { reconciliation, snapshot, taskScopedHint } = input;
14
- const hint = taskScopedHint?.aggregate === true && snapshot?.status === "complete" && snapshot.objective !== undefined
15
- ? buildTaskScopedAggregateReconciliationHint(taskScopedHint.goal, taskScopedHint.final)
16
- : "";
17
- const recovery = codexGoalMismatchRecovery(input.expectedObjective, snapshot);
18
- return new UlwLoopError(`${formatCodexGoalReconciliation(reconciliation)}${hint}\n${recovery.message}`, "ulw_loop_codex_snapshot_mismatch", { details: recovery.details });
19
- }
20
- function normalizeObjective(value) {
21
- return value.replace(/\s+/g, " ").trim();
22
- }
23
- function textMentionsUlwLoopPlanArtifact(value) {
24
- const normalized = (value ?? "").toLowerCase();
25
- return (normalized.includes(ULW_LOOP_DIR.toLowerCase()) ||
26
- normalized.includes(ULW_LOOP_GOALS.toLowerCase()) ||
27
- normalized.includes(ULW_LOOP_LEDGER.toLowerCase()));
28
- }
29
- function textMentionsGoalId(value, goalId) {
30
- return (value ?? "").toLowerCase().includes(goalId.toLowerCase());
31
- }
32
- function textHasCompletionValidationEvidence(value) {
33
- const normalized = (value ?? "").toLowerCase();
34
- const done = /\b(?:planned work|implementation|deliverables?|scope|task|work)\b/.test(normalized) &&
35
- /\b(?:done|complete|completed|finished|shipped)\b/.test(normalized);
36
- const verified = /\b(?:validation|verification|tests?|build|lint|review|quality gate|code-review)\b/.test(normalized) &&
37
- /\b(?:passed|complete|completed|clean|green|approve|approved|clear)\b/.test(normalized);
38
- return done && verified;
39
- }
40
- async function snapshotObjectiveMapsToUlwLoopPlan(repoRoot, snapshotObjective, scope) {
41
- const actual = normalizeObjective(snapshotObjective).toLowerCase();
42
- if (textMentionsUlwLoopPlanArtifact(actual))
43
- return true;
44
- if (actual.length < 24 || !existsSync(ulwLoopBriefPath(repoRoot, scope)))
45
- return false;
46
- try {
47
- const brief = normalizeObjective(await readFile(ulwLoopBriefPath(repoRoot, scope), "utf8")).toLowerCase();
48
- return brief.length >= 24 && (brief.includes(actual) || actual.includes(brief));
49
- }
50
- catch (error) {
51
- if (error instanceof Error)
52
- return false;
53
- throw error;
54
- }
55
- }
56
- export async function canReconcileCompletedTaskScopedAggregateSnapshot(repoRoot, plan, goal, snapshotObjective, evidence, scope) {
57
- if (codexGoalMode(plan) !== "aggregate")
58
- return false;
59
- if (goal.status !== "in_progress" || plan.activeGoalId !== goal.id)
60
- return false;
61
- if (isFinalRunCompletionCandidate(plan, goal)) {
62
- return snapshotObjectiveMapsToUlwLoopPlan(repoRoot, snapshotObjective, scope);
63
- }
64
- if (!textMentionsUlwLoopPlanArtifact(evidence) || !textMentionsGoalId(evidence, goal.id))
65
- return false;
66
- if (!textHasCompletionValidationEvidence(evidence))
67
- return false;
68
- return snapshotObjectiveMapsToUlwLoopPlan(repoRoot, snapshotObjective, scope);
69
- }
70
- export async function canReconcileActiveFinalTaskScopedAggregateSnapshot(repoRoot, plan, goal, snapshotObjective, evidence, scope) {
71
- if (codexGoalMode(plan) !== "aggregate")
72
- return false;
73
- if (goal.status !== "in_progress" || plan.activeGoalId !== goal.id)
74
- return false;
75
- if (!isFinalRunCompletionCandidate(plan, goal))
76
- return false;
77
- if (!textHasCompletionValidationEvidence(evidence))
78
- return false;
79
- return snapshotObjectiveMapsToUlwLoopPlan(repoRoot, snapshotObjective, scope);
80
- }
81
- function buildCompletedLegacyGoalRemediation(goal) {
82
- return [
83
- "If get_goal returns a different completed legacy/thread objective, do not repeat --status complete in this thread.",
84
- `Record a non-terminal blocker with: omo-agent-toolkit ulw-loop checkpoint --goal-id ${goal.id} --status blocked --evidence "<completed legacy Codex goal blocks create_goal in this thread>" --codex-goal-json "<different completed get_goal JSON or path>".`,
85
- "Then continue only from a Codex goal context with no active/completed conflicting goal, in the same repo/worktree, and create the intended goal there.",
86
- ].join(" ");
87
- }
88
- export function buildTaskScopedAggregateReconciliationHint(goal, final) {
89
- if (final) {
90
- return ` Final task-scoped aggregate reconciliation requires the checkpoint goal to be the active in-progress final OMO goal and the completed get_goal objective to map to the ulw-loop brief or artifact. ${buildCompletedLegacyGoalRemediation(goal)}`;
91
- }
92
- return ` Completed task-scoped aggregate reconciliation requires the checkpoint goal to be the active in-progress OMO goal, evidence that names that active OMO goal id, names .omo/ulw-loop/goals.json or ledger.jsonl, includes completed implementation plus validation/review evidence, and a get_goal objective that maps to the ulw-loop brief/artifact. ${buildCompletedLegacyGoalRemediation(goal)}`;
93
- }
@@ -12,5 +12,7 @@ export interface CheckpointUlwLoopResult {
12
12
  readonly goal: UlwLoopItem;
13
13
  readonly ledgerEntry: UlwLoopLedgerEntry;
14
14
  readonly aggregateCompletion?: UlwLoopAggregateCompletion;
15
+ readonly nextActions: readonly string[];
16
+ readonly warnings: readonly string[];
15
17
  }
16
18
  export declare function checkpointUlwLoop(repoRoot: string, args: CheckpointUlwLoopArgs, scope?: UlwLoopScope): Promise<CheckpointUlwLoopResult>;
@@ -110,6 +110,8 @@ export async function checkpointUlwLoop(repoRoot, args, scope) {
110
110
  let aggregateCompletion;
111
111
  let qualityGate;
112
112
  let codexGoal;
113
+ let nextActions = [];
114
+ let warnings = [];
113
115
  if (args.status === "complete") {
114
116
  const aggregate = codexGoalMode(plan) === "aggregate";
115
117
  const final = isFinalRunCompletionCandidate(plan, goal);
@@ -125,7 +127,7 @@ export async function checkpointUlwLoop(repoRoot, args, scope) {
125
127
  requireAllCriteriaPass(goal);
126
128
  let codexValidationError;
127
129
  try {
128
- codexGoal = await validateCheckpointCodexGoal({
130
+ const validation = await validateCheckpointCodexGoal({
129
131
  repoRoot,
130
132
  plan,
131
133
  goal,
@@ -133,6 +135,9 @@ export async function checkpointUlwLoop(repoRoot, args, scope) {
133
135
  evidence,
134
136
  ...(scope === undefined ? {} : { scope }),
135
137
  });
138
+ codexGoal = validation.raw;
139
+ nextActions = validation.nextActions;
140
+ warnings = validation.warnings;
136
141
  }
137
142
  catch (error) {
138
143
  if (!(error instanceof UlwLoopError))
@@ -179,6 +184,8 @@ export async function checkpointUlwLoop(repoRoot, args, scope) {
179
184
  goal.updatedAt = now;
180
185
  if (aggregateCompletion !== undefined)
181
186
  plan.aggregateCompletion = aggregateCompletion;
187
+ if (aggregateCompletion !== undefined)
188
+ nextActions = [...nextActions, 'aggregate complete — now update_goal({status:"complete"})'];
182
189
  plan.updatedAt = now;
183
190
  await writePlan(repoRoot, plan, scope);
184
191
  const ledgerEntry = buildLedger(now, args, goal, qualityGate, codexGoal, aggregateCompletion);
@@ -187,7 +194,7 @@ export async function checkpointUlwLoop(repoRoot, args, scope) {
187
194
  if (closedBatch !== undefined)
188
195
  await appendLedger(repoRoot, { at: now, kind: "batch_closed", goalId: goal.id, message: closedBatch.batchId }, scope);
189
196
  return aggregateCompletion === undefined
190
- ? { plan, goal, ledgerEntry }
191
- : { plan, goal, ledgerEntry, aggregateCompletion };
197
+ ? { plan, goal, ledgerEntry, nextActions, warnings }
198
+ : { plan, goal, ledgerEntry, aggregateCompletion, nextActions, warnings };
192
199
  });
193
200
  }
@@ -66,14 +66,14 @@ export async function readJsonInput(value) {
66
66
  export async function parseCodexGoalJson(value) {
67
67
  if (value === undefined)
68
68
  return undefined;
69
- const raw = looksLikeJson(value) ? value : await readFile(value, "utf8");
70
69
  try {
70
+ const raw = looksLikeJson(value) ? value : await readFile(value, "utf8");
71
71
  JSON.parse(raw);
72
72
  return raw;
73
73
  }
74
74
  catch (error) {
75
75
  const message = error instanceof Error ? error.message : "unknown error";
76
- throw new UlwLoopError(`Invalid --codex-goal-json: ${message}`, "ULW_LOOP_CODEX_GOAL_JSON_INVALID", { cause: error });
76
+ throw new UlwLoopError(`Invalid --codex-goal-json: ${looksLikeJson(value) ? message : "neither valid JSON nor a readable path"}`, "ULW_LOOP_CODEX_GOAL_JSON_INVALID", { cause: error });
77
77
  }
78
78
  }
79
79
  function required(argv, flag, code) {
@@ -140,6 +140,8 @@ export async function reviewBlockers(repoRoot, argv, json, scope) {
140
140
  blockedGoal: result.blockedGoal,
141
141
  goal: result.newGoal,
142
142
  ledgerEntries: result.ledgerEntries,
143
+ nextActions: result.nextActions,
144
+ warnings: result.warnings,
143
145
  summary: summarizeUlwLoopPlan(result.plan),
144
146
  });
145
147
  }