Skip to content

test(ci-flake): M3 — gatelint legibility lint + AC10 egress posture probe - #597

Merged
sunholo-voight-kampff merged 2 commits into
devfrom
sprint/m-ci-flake-m3
Aug 5, 2026
Merged

test(ci-flake): M3 — gatelint legibility lint + AC10 egress posture probe#597
sunholo-voight-kampff merged 2 commits into
devfrom
sprint/m-ci-flake-m3

Conversation

@sunholo-voight-kampff

Copy link
Copy Markdown
Collaborator

Milestone M3 of m-ci-flake-systemic-fix. Closes AC8 and AC10. Pure Go, zero workflow edits — revert is deleting one directory and one file.

What lands

  • internal/testutil/gatelint — a legibility lint for the three known test-gating offenders, run as a plain Go test on every CI leg and every make test. R1 testing.Short( · R2 Getenv("CI")/Getenv("GITHUB_ACTIONS") · R3 httpbin.org/ailang-packages outside a live-network gate or the allowlist.
  • internal/testutil/egress_posture_test.go — AC10 (a)–(d), including (d), the D5=Option-A residual asserted as open.

The allowlist seed was re-measured after M2

The sprint plan's seed predated M2. Re-measured at 78f30e053: R1 empty (M1/M2 removed all 7), R2 one entry reusing the reason M2 authored in provider_script_test.go, R3 five. net_test.go and gitcache_test.go are gated by M2 and deliberately not allowlisted — allowlisting them would make the gate inert for the very files the sprint just fixed.

AC10(d) — the tripwire that retires itself

The plan's M3 section predates Mark's D5 decision and omits (d); the design doc is current and wins. (d) builds a transport the way internal/effects does (Proxy nil), proves it bypasses the poison, and asserts in the same run that a ProxyFromEnvironment transport fails — that second half is the control. When Option B lands, (d) reds, which is the intended signal.

Verification (all outside the sandbox — in-sandbox verdicts here are uninformative by construction)

  • gatelint 941 files, 0 violations; AC10 (a)–(d) pass in the default, poisoned, live, and poisoned+live lanes
  • full suite 108 ok / 0 FAIL; gofmt, go vet, golangci-lint (0 issues), check-file-sizes clean
  • Six mutations, each proven landed and reverted byte-identical (sha256): R1 branch, walker suffix, dot-dir skip (executor); R3 gating check → flags the 2 gated files, allowlist emptied → flags exactly the 5 seeds, AC10(d) poison env stripped → the control catches it (controller)
  • AC8 falsification drill fired: 942 files scanned, scratch file named in the failure, removed, back to green

🤖 Generated with Claude Code

sunholo-voight-kampff and others added 2 commits August 5, 2026 20:00
…robe (incl. D5=A residual)

Closes AC8 and AC10 of m-ci-flake-systemic-fix. Pure Go, zero workflow edits.

internal/testutil/gatelint — a legibility lint for the three known test-gating
offenders, running as a plain Go test on every CI leg and every `make test`:
  R1 `testing.Short(`  R2 `Getenv("CI")`/`Getenv("GITHUB_ACTIONS")`
  R3 `httpbin.org`/`ailang-packages` outside a live-network gate or the allowlist
The walker matches *_test.go only, skips dot-dirs and testdata/, and excludes its
own package — all three are measured-necessary (6 production files carry R3's
tokens; an unscoped R3 would flag gatelint's own source and red CI on the very
commit that introduces it, which was a blocking quorum objection).

internal/testutil/egress_posture_test.go — AC10 (a) poison sentinel denies HTTP
egress, (b) loopback bypasses the lane poison, (c) raw TCP stays open, and
(d) the D5=Option-A residual asserted as OPEN: a nil-Proxy transport built the
way internal/effects builds them bypasses the poison, with a
ProxyFromEnvironment transport failing in the same run as the control that makes
(d) non-vacuous. (d) is the tripwire that reds when Option B lands.

Allowlist seed re-measured at 78f30e0 AFTER M2 (the plan's seed predated it):
R1 empty (M1/M2 removed all 7), R2 one entry using the reason M2 authored in
provider_script_test.go, R3 five entries. net_test.go and gitcache_test.go are
gated by M2 and deliberately NOT allowlisted.

Verified outside the sandbox: gatelint 941 files/0 violations; AC10 (a)-(d) pass
in the default, poisoned, live and poisoned+live lanes; full suite 108 ok/0 FAIL;
gofmt/vet/golangci-lint clean. Six mutations each proven landed and reverted
byte-identical: R1 branch, walker suffix, dot-dir skip (executor); R3 gating
check -> flags the 2 gated files, allowlist emptied -> flags exactly the 5 seeds,
AC10(d) poison env stripped -> control catches it (controller). AC8 falsification
drill fired: 942 files scanned, the scratch file named, removed, back to green.

Co-Authored-By: codex gpt-5.6-sol <noreply@openai.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…s worded it differently

CI caught what no local gate could: `test-windows` and `Build windows-latest`
both failed on the M3 commit because Go reports a refused TCP connect as
`connectex: No connection could be made because the target machine actively
refused it.` on Windows, versus `connect: connection refused` on Unix. The
assertion required the literal `connection refused`, so it could never pass
there — the production behavior was correct; only the assertion was parochial.

Requires `refused` instead. All three tokens must still match, so the check stays
discriminating; verified against four verbatim error strings — Unix refused and
Windows refused (the latter copied from the failing CI log) pass, a DNS failure
and a proxy hang both fail. Mutation-proved by removing the sentinel proxy wiring
(with `go vet` confirming it still compiled, so the run was informative): the
assertion redded with "request through poison proxy unexpectedly succeeded".

This is the second Windows-only defect in this package that local gates cannot
see; M1's was env-var case-insensitivity.

Found by the sprint evaluator (sonnet) and reproduced first-party against the
job log before applying.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@sonarqubecloud

sonarqubecloud Bot commented Aug 5, 2026

Copy link
Copy Markdown

@sunholo-voight-kampff
sunholo-voight-kampff merged commit 13c5700 into dev Aug 5, 2026
20 checks passed
@sunholo-voight-kampff
sunholo-voight-kampff deleted the sprint/m-ci-flake-m3 branch August 5, 2026 18:37
sunholo-voight-kampff added a commit that referenced this pull request Aug 5, 2026
…plan had gone stale against its own design doc

M3 landed as 13c5700 (PR #597): internal/testutil/gatelint (R1/R2/R3, 941
files, 0 violations) + egress_posture_test.go closing AC8 and AC10(a-d).

Find: iteration 145 applied Mark's D5 ruling by editing the design doc — adding
AC10(d) — and nothing updated the sprint plan, whose M3 task list still said
AC10 (a)(b)(c). Routed as written, M3 would have shipped without the tripwire
whose whole purpose is to red when the queued Option-B item lands. The rot runs
both ways: the doc still bundles M3 with workflow edits the newer plan split into
M4, and still says "5 CI legs" in 6 places though its own V34 measured 6.

Skill edit (>=2 instances, both inside this iteration): Gate 2 gains 3b(vii) —
a design doc and its sprint plan are two documents describing one sprint, and
revising either silently rots the other. Diff the plan's milestone section
against the doc's acceptance criteria at pick time, because quorum reviews the
doc, the planner reads it once, and nothing re-diffs them afterwards.

Applying that edit deleted rule 3c's header line — the anchor included it and the
replacement did not restore it, and the script reported success. Caught by
treating the post-edit grep's 0 as a claim (rule 3a) with a control in the same
call; repaired from origin and proven purely additive (29 insertions, 0
deletions; 3c body word count 418 == origin's 418).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant