Scoped adaptation of PR #2716: keep compact rendering as the default and require ECC_STATUSLINE_USAGE=1. Installer registration, managed aliases and the Codex background bar remain outside this slice.
Reproduced issue #3485 on installed Codex CLI 0.162.0. Keep user legacy choices for explicit migration and verify disposable install, repair, reinstall and removal.
8a7d6129 added the external-contract question for every code change that
handles data and updated the pinned tests to match, including the legacy
test "code condensed Edit hint for an unknown profile is unchanged". Its own
evaluation then found the gated arm did not improve (25 to 23 of 48), so the
question has no evidence behind it as a default.
- Restore the test expectations 8a7d6129 changed: questionIdsFor, the
byte-identical code text for src/a.py, the condensed hints, and the hook
question lists default to data-schema without external-contract.
- Add questionIdsFor/condensedHintFor cases with { externalContract: true }.
- Add hook cases: GATEGUARD_EXTERNAL_CONTRACT_QUESTION=1/true/ON asks it
beside data-schema and in the unknown-profile set, never without data;
unset, 0, false and off keep the original four.
Against main: target-class 5 failures, fact-force 10 failures.
Each of these is credited on main, reproduced against upstream 2d515e4f:
- rg -t py / -T js / --type-not js, fd -e py, and the Grep tool's
type: "py" credit an Edit of tokenizer.js. Type and extension values
are skipped as plain value flags, so they never filter.
- Glob **/tokenizer.py, rg tokenizer src/*.py, and
git grep tokenizer -- '*.py' credit tokenizer.js. The Glob pattern is
never a filter, and a glob operand scopes as its literal directory.
- Glob **/tokenizer.js, find -name tokenizer.js, rg -g tokenizer.js and
Grep glob: "tokenizer.js" credit tokenizer.js, although each search
could only find the target itself.
- An Edit of "// note<U+2028>foo(1);" to "// note<U+2028>foo(2);" passes
as comment-only, although JavaScript ends the comment at U+2028 and
foo(2) runs.
Scenario 21-bypass-filter-forms adds ten must-deny steps and four
controls. Four hook controls that asserted exact-name lookups still
credit (find -name widget.py, Grep glob widget.py, Get-ChildItem
-Filter widget.py) now assert the lookup is denied; each keeps its
original purpose, that the exclusion parser leaves a positive include
alone, through a wildcard include (widget.*).
Isolate spawned Stop hooks through TMPDIR/TMP/TEMP, open transcript fixtures exclusively with private modes, and derive intentional stale-race fixture identity from its opened descriptor.
Preserve main OpenCode lease and activation gates and native Claude namespace receipts. Detect same-size in-place edits using bigint modification and change times during hashing and before deletion; verify both races and actual public CLI reinstall lifecycles.
Port the evidence floor from PR #3480 onto the canonical generation-bound index; preserve policy-v5 anchors and the source PR attribution. Harden PR #3453 receipt metadata and pointer byte bounds.
Co-authored-by: montjeffrey <montjeffrey@gmail.com>
Isolate deadline fixtures from inherited dry-run/disabled hook flags. Remove an unapproved emoji from the new routing regression to satisfy Unicode validation.
Each writer performs 30 write rounds to widen the race window. Drop the vacuous exitCode liveness assert and the swallowing mid-flight read; instead every wait-loop poll reads and validates the state, so torn reads fail loudly.
Assert dry-run install writes nothing under projectRoot too (cursor target writes there, not home). Rewrite the concurrent writeInstallState test with genuinely overlapping writers via async spawn plus done-file rendezvous, including a mid-flight read; sanitize rendezvous filenames for Windows.
Honor ECC_DRY_RUN=1 in install and repair arg parsing (previously only --dry-run flag worked, so ecc --dry-run install/repair silently performed real writes). Make writeInstallState atomic via writeFileAtomic (O_EXCL staging, fsync, cleanup on failure, atomic rename preserving previous state). Add writeInstallState failure/concurrency/symlink regression tests and disposable-home CLI dry-run regression tests for both global and subcommand forms.
Track illustrative scopes and retain their connectors so a contrastive
request or rejection for the current task ends the preceding example.
Preserve complete skill aliases, outer discussion guards, quoted task
qualifiers, and indirect citation protection for scored admission.
Invalidate older routing receipts and add resolver/launcher regressions
for request ordering, scope boundaries, aliases, and the reported P1.