Skip to content

merge-queue batch q-1785745378 - #741

Closed
matt82198 wants to merge 6 commits into
mainfrom
integrate/q-1785745378
Closed

matt82198 wants to merge 6 commits into
mainfrom
integrate/q-1785745378

Conversation

@matt82198

Copy link
Copy Markdown
Owner

Merge-queue batch built by tools/merge_queue.py.

Members: #719, #725

Members are closed only after git merge-base --is-ancestor proves their content landed on main.

matt82198 and others added 6 commits August 2, 2026 21:27
--check auto-corrected drift: it WROTE tests/CLAUDE.md and exited 0. That made a
check mode mutate the tree, made count drift structurally unable to fail CI
(fail-open gate), and made tests/test_tests_claudemd_drift.py rewrite a tracked
file on every test run.

New contract:
- --check (default) and --strict are READ-ONLY validation, never write. Drift is
  exit 1 with a "run --regenerate" hint. --strict is an alias reserved for future
  main-only CI wiring so the current CI contract stays stable.
- --regenerate (deprecated alias --fix, still used by auto_merge.py) is the only
  writing mode, and now applies the same exactly-one assertion before writing so
  it can no longer launder a duplicated count line into a green tree.

Count-line scanning hardened against the refine-r1 adversarial lens evasions:
line-anchored and tolerant of spacing/colon-placement variants; labels restricted
to exact ASCII Node/Shell/Python so a homoglyph label is MALFORMED instead of
invisible; fenced blocks and HTML comments masked out (offset-preserving) so a
format example is neither a duplicate nor a substitute for the real line;
regeneration rewrites by match span in canonical form. Error text now shows the
canonical format the matcher prefers instead of one it rejected.

Preserved: exactly-one/dup detection (#679), vacuous zero-file exit 2, which now
also guards the writing path.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Folds five more verified defects into the read-only gate fix. Each reproduced as
a failing test before the fix.

Format-variant evasion (refine-r1 lens C/D): the exact-literal regex missed
`**Python (N suites)** :` and `**Python (N suites):**`, so a document could carry
two contradictory counts with the gate green. Matching is now line-anchored and
tolerant of spacing and both colon placements.

Homoglyph evasion (case E): a Cyrillic look-alike in the label was invisible.
Labels are restricted to exact ASCII Node/Shell/Python and any other
count-line-shaped label is reported MALFORMED instead of skipped.

Fence/comment blindness (cases F/G/H): a fenced-only count line satisfied the
exactly-one requirement (and auto-correct then rewrote the number inside the
documentation example), while a legitimate format example or commented-out line
was reported as a duplicate. Fenced blocks and HTML comments are masked out
offset-preservingly, so they are neither duplicates nor substitutes for the real
line, and regeneration never touches them.

Duplicate laundering: the writing path used unbounded re.sub with no exactly-one
assertion, rewriting BOTH duplicates and exiting 0. It now runs the same
structural validation before writing and rewrites by match span.

--repo was accepted and ignored: every git ls-files ran in the process CWD, so
--repo at an empty tree reported "[OK] counts match". cwd is threaded into every
git call, the target must be a git work tree, and a failed ls-files is exit 2
rather than a silent zero.

Vacuous-zero guard was an AND over all three families, so a single-language
wipeout was auto-blessed. It is now per family; a deliberate removal is declared
by hand-editing that line to 0 suites.

Error text now shows the canonical format the matcher prefers instead of one it
rejected.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… exit 2)

bin/cli.js propagated child exit codes with `result.status || 0`. spawnSync
reports `status: null` (and leaves `error` undefined) whenever the child was
terminated by a signal rather than exiting on its own -- SIGTERM/SIGKILL from
an operator, an OOM kill, or a CI job cancellation. `null || 0` collapsed that
to 0, so a signal-killed child reported SUCCESS.

This propagator is shared by every `aesop <namespace> <verb>` dispatch (~50
gate/lint/verify subcommands), so a killed `aesop gate secret-scan` was
indistinguishable from a passing secret gate: a fail-OPEN security gate.

Fix: route all three spawnSync sites (Python namespace dispatch, `init`, and
`init`'s python fallback) through a single `exitCodeFromSpawnResult()` that
fails CLOSED -- real numeric status verbatim, but spawn error or a non-numeric
status (null = signal-killed, undefined = unknown) exits 2. The namespace
dispatch also prints why it failed instead of exiting silently.

`init`'s fallback additionally collapsed a signal-killed child to 0 via
`fallback.status || (fallback.error ? 1 : 0)`; same fix applies.

Requiring bin/cli.js as a module now exports the helper instead of running the
scaffolder, which is the seam the tests use.

TDD: tests/cli-dispatch.test.mjs gains 6 assertions -- real codes propagate
unchanged, {status:null,signal:'SIGTERM',error:undefined} must exit nonzero
(2), SIGKILL/undefined status fail closed, spawn errors exit 2, and the
fixture is cross-checked against a real self-SIGTERM child on POSIX so it is
not an invented shape. Verified RED: the old expression yields 0 for that
fixture, the new one yields 2.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@matt82198 matt82198 added the merge-queue-batch Integration batch PR opened by the merge-queue advancer label Aug 3, 2026
@matt82198

Copy link
Copy Markdown
Owner Author

Dissolving merge-queue batch: required check(s) absent from rollup: windows

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-queue-batch Integration batch PR opened by the merge-queue advancer

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant