fix(skill): attempt-scoped marker для secondary session-id (round-7 finding)
- Зачем:
- live e2e round 2 нашёл HIGH: review-stable marker `${REVIEW_ID}` позволяет skill'овой ретрай-логике создать несколько rollout'ов с одинаковым marker'ом (первая попытка фэйлит sanity, оставляет rollout; ретрай успешен, оба попадают в grep). "Pick any" → silent intra-review drift на stale session.
- Что:
- Новый placeholder `${ATTEMPT_ID}` — 6-значный random, генерируется заново на каждый launch (initial/retry/resume/fresh-exec).
- Marker перешёл на `${REVIEW_ID}-${ATTEMPT_ID}`. Stale retry rollout содержит ОЛД attempt-id → невидим для grep'a новой попытки.
- Multi-match policy: "pick any" → **fail closed** с диагностикой. Под корректной attempt-scoping multi-match структурно невозможен; если произошло — silent picking только скрывал бы баг.
- SKILL.md: Step 2 preamble (placeholders + per-launch ATTEMPT_ID generation), Step 4 prompts (marker), Step 4 check 4 (grep by attempt-id + fail-closed multi-match), Step 7 resume prompt (fresh ATTEMPT_ID), Step 7 check 4, Step 7 fresh-exec fallback, Rules section.
- docs/DESIGN.md §4.1: decision + alternatives переписаны — добавлен round-7 rejection "review-stable marker alone".
- docs/DESIGN.md §6.8: новый round-7 lesson (scope of identifier must match rollout granularity).
- docs/DESIGN.md §7.1/§7.2 smoke tests: добавлен ATTEMPT_ID generation, grep паттерн обновлён.
- docs/DESIGN.md §8: строка с round-7 переходом.
- README.md troubleshooting обновлён под attempt-scoping.
- Проверка:
- Retry edge case закрыт по построению: ATTEMPT_ID свежий на каждом launch → stale rollout невидим.
- Multi-match визибильный (fail-closed) вместо silent (pick-any).
This commit is contained in:
@@ -229,15 +229,20 @@ In some Claude Code sandbox configurations codex's `--json` event stream is
|
||||
suppressed when stdout is redirected to a file — the `/tmp/codex-stdout-*.jsonl`
|
||||
ends up 0 bytes even though the review itself (`-o /tmp/codex-review-*.md`)
|
||||
completes correctly. The skill handles this automatically via a filesystem
|
||||
fallback: every prompt includes a unique session marker
|
||||
(`<!-- ADVERSARIAL-REVIEW-SESSION: <REVIEW_ID> -->`) that gets written to
|
||||
the rollout JSONL on disk. When the JSONL stream is empty, the skill runs
|
||||
`find ~/.codex/sessions -name 'rollout-*.jsonl' -newer <prompt-file> -exec
|
||||
grep -l <REVIEW_ID> {} +` to positively identify this session's rollout by
|
||||
content match (not by newest-mtime, which would be unsafe against parallel
|
||||
codex invocations) and extracts the UUID from the filename. Resume continues
|
||||
to work normally. The commands used are POSIX (`find -newer`, `-exec grep -l`)
|
||||
and work identically on Linux and macOS.
|
||||
fallback: every prompt includes a **per-launch** session marker
|
||||
(`<!-- ADVERSARIAL-REVIEW-SESSION: <REVIEW_ID>-<ATTEMPT_ID> -->`) where
|
||||
`ATTEMPT_ID` is a fresh random integer regenerated for the initial exec,
|
||||
every retry, every resume, and every fresh-exec fallback. The marker is
|
||||
written to the rollout JSONL on disk. When the JSONL stream is empty, the
|
||||
skill runs `find ~/.codex/sessions -name 'rollout-*.jsonl' -newer
|
||||
<prompt-file> -exec grep -l <REVIEW_ID>-<ATTEMPT_ID> {} +` to positively
|
||||
identify this specific launch's rollout (not by newest-mtime, which would
|
||||
be unsafe against parallel codex; not by review-stable ID alone, which
|
||||
would match stale retry rollouts) and extracts the UUID from the filename.
|
||||
Zero or multiple matches → the skill fails closed with a diagnostic rather
|
||||
than silently picking. Resume continues to work normally. All commands are
|
||||
POSIX (`find -newer`, `-exec grep -l`) and work identically on Linux and
|
||||
macOS.
|
||||
|
||||
**"NOT VERIFIED" result.**
|
||||
The skill applied fixes but the reviewer did not re-verify them (resume
|
||||
|
||||
Reference in New Issue
Block a user