[object Object]

← back to Cli Printing Press

fix(skills): require codex completion marker before treating delegation as success (#1523)

996379417bef8df70441a8f180652d6267dbcda4 · 2026-05-16 12:49:20 -0700 · Trevin Chow

* fix(skills): require codex completion marker before treating delegation as success

Codex `exec` can exit non-zero or be killed mid-run (sandbox abort, OOM,
SIGINT, internal toolchain crash) and leave partial work behind that
looks identical to a successful end-of-prompt exit. The existing
post-codex validate step only checks `go build && go vet` and a
non-empty `git diff`, both of which can pass against partial output, so
the parent skill silently treats partial completion as success and
proceeds to the next priority task with the partial files in tree.

Each of the four prompt templates now ends with a COMPLETION MARKER
section instructing Codex to write `_codex-result.json` (with
`{status,files_written,timestamp}`) only after VERIFY succeeds. The
Delegate step removes any stale marker before the codex invocation so a
file from a prior task can't fool the next one, and the Validate step
treats missing-or-not-complete marker as a Codex failure that falls
through to the existing revert + Claude-fallback path and feeds the
circuit breaker.

Closes #1288

* fix(skills): make completion-marker validate snippet self-describing on failure

Per Greptile review on PR #1523: the previous validate snippet chained
the marker check and the build step with `&&`, so a missing/incomplete
marker exited non-zero silently with the same exit code as a build
failure. The surrounding prose told the agent to surface a specific
error message, but the snippet itself never printed it, leaving the
agent to second-guess which arm failed.

Rewrite both Validate snippets (Phase 3 step e, Phase 4 step 5) as an
`if` block that echoes the exact `codex output marker missing` message
to stderr before exiting non-zero. The build/vet branch is unchanged.

---------

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>

Files touched

Diff

commit 996379417bef8df70441a8f180652d6267dbcda4
Author: Trevin Chow <trevin@trevinchow.com>
Date:   Sat May 16 12:49:20 2026 -0700

    fix(skills): require codex completion marker before treating delegation as success (#1523)
    
    * fix(skills): require codex completion marker before treating delegation as success
    
    Codex `exec` can exit non-zero or be killed mid-run (sandbox abort, OOM,
    SIGINT, internal toolchain crash) and leave partial work behind that
    looks identical to a successful end-of-prompt exit. The existing
    post-codex validate step only checks `go build && go vet` and a
    non-empty `git diff`, both of which can pass against partial output, so
    the parent skill silently treats partial completion as success and
    proceeds to the next priority task with the partial files in tree.
    
    Each of the four prompt templates now ends with a COMPLETION MARKER
    section instructing Codex to write `_codex-result.json` (with
    `{status,files_written,timestamp}`) only after VERIFY succeeds. The
    Delegate step removes any stale marker before the codex invocation so a
    file from a prior task can't fool the next one, and the Validate step
    treats missing-or-not-complete marker as a Codex failure that falls
    through to the existing revert + Claude-fallback path and feeds the
    circuit breaker.
    
    Closes #1288
    
    * fix(skills): make completion-marker validate snippet self-describing on failure
    
    Per Greptile review on PR #1523: the previous validate snippet chained
    the marker check and the build step with `&&`, so a missing/incomplete
    marker exited non-zero silently with the same exit code as a build
    failure. The surrounding prose told the agent to surface a specific
    error message, but the snippet itself never printed it, leaving the
    agent to second-guess which arm failed.
    
    Rewrite both Validate snippets (Phase 3 step e, Phase 4 step 5) as an
    `if` block that echoes the exact `codex output marker missing` message
    to stderr before exiting non-zero. The build/vet branch is unchanged.
    
    ---------
    
    Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
---
 .../printing-press/references/codex-delegation.md  | 46 +++++++++++++++++++---
 1 file changed, 40 insertions(+), 6 deletions(-)

diff --git a/skills/printing-press/references/codex-delegation.md b/skills/printing-press/references/codex-delegation.md
index 764e761b..976eabb3 100644
--- a/skills/printing-press/references/codex-delegation.md
+++ b/skills/printing-press/references/codex-delegation.md
@@ -24,20 +24,28 @@ When `CODEX_MODE` is true, delegate code-writing tasks to Codex CLI. Claude stil
 
    c. **Assemble prompt** — Build a CODEX_PROMPT using the appropriate task type template (see below).
 
-   d. **Delegate** — Pipe to Codex:
+   d. **Delegate** — Remove any stale completion marker from a prior task, then pipe to Codex:
    ```bash
    # Model and reasoning effort inherit from ~/.codex/config.toml. Do not pin -m / -c here.
-   cd "$PRESS_LIBRARY/<api>-pp-cli" && echo "$CODEX_PROMPT" | codex exec \
+   cd "$PRESS_LIBRARY/<api>-pp-cli" && rm -f _codex-result.json && echo "$CODEX_PROMPT" | codex exec \
      --yolo \
      -
    ```
 
-   e. **Validate** — Check the result:
+   e. **Validate** — Check the completion marker first (self-describing on failure), then the build:
    ```bash
-   cd "$PRESS_LIBRARY/<api>-pp-cli" && go build ./... && go vet ./...
+   cd "$PRESS_LIBRARY/<api>-pp-cli"
+   if [ ! -f _codex-result.json ] || [ "$(jq -r '.status // empty' _codex-result.json 2>/dev/null)" != "complete" ]; then
+     echo "codex output marker missing — partial work may be present in $PWD; review before continuing" >&2
+     false
+   else
+     go build ./... && go vet ./...
+   fi
    ```
    Also verify `git diff --stat` shows a non-empty diff.
 
+   A missing or non-complete marker means Codex exited before finishing the prompt (sandbox abort, OOM, SIGINT, internal toolchain crash); the `if` branch prints the diagnostic itself so the agent does not have to second-guess which arm failed. Fall through to step (g) as a failure. Do NOT proceed to the next priority task with whatever Codex managed to write before bailing.
+
    f. **On success** — Discard the restore point and reset the failure counter:
    ```bash
    git stash drop 2>/dev/null
@@ -92,6 +100,10 @@ CONSTRAINTS:
 
 VERIFY: After making changes, run:
   cd . && go build ./... && go vet ./...
+
+COMPLETION MARKER: After VERIFY succeeds (build green, vet clean), and only then, write a JSON object to _codex-result.json in the cwd:
+  {"status":"complete","files_written":["internal/store/store.go"],"timestamp":"<ISO 8601 UTC, e.g. 2026-05-16T12:00:00Z>"}
+If you bail, hit a fatal error, or VERIFY fails, do NOT write this file. The parent skill uses its presence and "status":"complete" as the only signal that the prompt ran end-to-end; missing marker is treated as a partial-completion failure regardless of process exit code.
 ```
 
 **Workflow command task:**
@@ -129,6 +141,10 @@ CONSTRAINTS:
 
 VERIFY: After making changes, run:
   cd . && go build ./... && go vet ./...
+
+COMPLETION MARKER: After VERIFY succeeds (build green, vet clean), and only then, write a JSON object to _codex-result.json in the cwd:
+  {"status":"complete","files_written":["internal/cli/<command>.go","internal/cli/root.go"],"timestamp":"<ISO 8601 UTC>"}
+If you bail, hit a fatal error, or VERIFY fails, do NOT write this file. The parent skill uses its presence and "status":"complete" as the only signal that the prompt ran end-to-end; missing marker is treated as a partial-completion failure regardless of process exit code.
 ```
 
 **Transcendence command task:**
@@ -164,6 +180,10 @@ CONSTRAINTS:
 
 VERIFY: After making changes, run:
   cd . && go build ./... && go vet ./...
+
+COMPLETION MARKER: After VERIFY succeeds (build green, vet clean), and only then, write a JSON object to _codex-result.json in the cwd:
+  {"status":"complete","files_written":["internal/cli/<command>.go","internal/cli/root.go"],"timestamp":"<ISO 8601 UTC>"}
+If you bail, hit a fatal error, or VERIFY fails, do NOT write this file. The parent skill uses its presence and "status":"complete" as the only signal that the prompt ran end-to-end; missing marker is treated as a partial-completion failure regardless of process exit code.
 ```
 
 ## Phase 4: Codex Delegation (Fixes)
@@ -208,16 +228,30 @@ When `CODEX_MODE` is true, delegate each bug fix to Codex. The shipcheck tools t
 
    VERIFY: After making changes, run:
      cd . && go build ./... && go vet ./...
+
+   COMPLETION MARKER: After VERIFY succeeds (build green, vet clean), and only then, write a JSON object to _codex-result.json in the cwd:
+     {"status":"complete","files_written":["<exact file path>"],"timestamp":"<ISO 8601 UTC>"}
+   If you bail, hit a fatal error, or VERIFY fails, do NOT write this file. The parent skill uses its presence and "status":"complete" as the only signal that the prompt ran end-to-end; missing marker is treated as a partial-completion failure regardless of process exit code.
    ```
 
    ```bash
    # Model and reasoning effort inherit from ~/.codex/config.toml. Do not pin -m / -c here.
-   cd "$PRESS_LIBRARY/<api>-pp-cli" && echo "$CODEX_PROMPT" | codex exec \
+   cd "$PRESS_LIBRARY/<api>-pp-cli" && rm -f _codex-result.json && echo "$CODEX_PROMPT" | codex exec \
      --yolo \
      -
    ```
 
-5. **Validate** — same as Phase 3: `go build`, `go vet`, non-empty diff.
+5. **Validate** — same as Phase 3: check the completion marker first (self-describing on failure), then build and vet:
+   ```bash
+   cd "$PRESS_LIBRARY/<api>-pp-cli"
+   if [ ! -f _codex-result.json ] || [ "$(jq -r '.status // empty' _codex-result.json 2>/dev/null)" != "complete" ]; then
+     echo "codex output marker missing — partial work may be present in $PWD; review before continuing" >&2
+     false
+   else
+     go build ./... && go vet ./...
+   fi
+   ```
+   Also verify `git diff --stat` shows a non-empty diff. The `if` branch prints the diagnostic itself before exiting non-zero, so the agent does not have to second-guess which arm failed; fall through to step 7.
 
 6. **On success** — `git stash drop`, reset `CODEX_CONSECUTIVE_FAILURES=0`.
 

← 82ad787b fix(cli): cap body-flag recursion depth to prevent compiler  ·  back to Cli Printing Press  ·  fix(cli): move extra_commands SKILL.md block to its own top- c10d0b55 →