Skip to content

backlog: file #1096, the windows-2025 Tests (pytest) cap is exceeded on main - #278

Merged
wshallwshall merged 3 commits into
mainfrom
claude/coordinator-role-handoff-88d83e
Aug 7, 2026
Merged

backlog: file #1096, the windows-2025 Tests (pytest) cap is exceeded on main#278
wshallwshall merged 3 commits into
mainfrom
claude/coordinator-role-handoff-88d83e

Conversation

@wshallwshall

Copy link
Copy Markdown
Collaborator

Files one item. No code, no workflow change -- the fix itself is deliberately not in this PR.

What was measured

ci.yml sets step_timeout: 36 for both Windows legs and, in the same comment block, names its own
re-derivation trigger: "RE-DERIVE IF a windows-2025 Tests (pytest) step is ever seen above 28:00 --
that is the trigger, not a calendar reminder."

Pool: every ci.yml run created 2026-08-07 UTC -- 80 runs, enumerated via gh api --paginate
on the workflow's runs?created= query. Jobs fetched with ?filter=all, so an attempt killed at
the cap is not hidden behind its passing re-run. Rows are each leg's Tests (pytest) STEP, kept
when that step concluded; executions under 60s dropped (a docs-only PR skips the leg).

measure value
windows-2025 step executions / concluding success 65 / 43
max passing step 35:13 against the 36:00 cap -- 47s, 1.022x
passing steps above the 28:00 trigger 43 of 43
killed at 36:0x 5, two of them push runs on main (7ecff8ae, b78214f5)

The trigger is not merely fired, it is universally exceeded, and the cap is failing green suites --
including on main.

The step was measured, not the job, on purpose. ci.yml records at least three sessions
substituting job durations while triaging this same cap; a job-duration reading of this pool gives
33-40 minutes and invites the wrong conclusion that the cap is comfortable.

Two failures on this leg today are DIFFERENT causes

Kept separate in the item rather than merged into one story: #253 is a genuine timeout with no test
failing, while #256 is an assertion failure in test_connscale_cpu_probe.py / test_connscale_smoke.py
whose own comment already records this leg failing twice in one job on 2026-07-30. Only the first belongs
to #1096.

Ledger mechanics

  • Number from scripts/coord/alloc.ps1, not grepped. Row added in the same commit at rank 6; ranks
    6..108 renumbered to 7..109.
  • Renumber bounded to the live table (lines 180..287). The file also holds a superseded 134-row
    2026-07-10 table; an assertion checks it comes out byte-identical, and it does.
  • Four Distribution census lines re-derived: Value 7 -> 8, Difficulty 3 -> 40, P1 -> 9, quick win -> 34,
    sum 108 -> 109.
  • The "Every one of the 102 open items" sentence was left alone deliberately -- it is a dated claim
    about the 2026-08-03 re-scoring pass, not a live census, and bumping it would assert that pass scored
    items that did not exist yet. Prior passes appear to have bumped it, which looks like the source of the
    drift it is known for.

This PR does not fix the census, and says so

Verified in both directions with parse_items imported from backlog_status_check.py rather than a
hand-rolled scan. That surfaces pre-existing drift this PR does not touch: 52 open items carry no
row
, 11 rows name an item that is not open, and parse_items counts 150 open items against a
census asserting 109. Those two sets cancel on a total, which is why a matching sum never caught it.
That reconcile is its own pass and needs 52 items scored.

Verification

A docs-only PR is the blind mode here, not the cheap one: the doc-drift guards live in pytest gated on
code == 'true' and .md is in the noncode allowlist, so they skip pre-merge and fire on the push to
main afterwards. Run locally instead, against the worktree venv:

  • pytest tests/test_asvs_file_surface_doc_drift.py ... tests/test_backlog_status_check.py -- 152 passed,
    89 skipped
    (all skips are docs/security/THREAT-MODEL.md, vault-only)
  • backlog_status_check.py --min-items 150 -- OK, 366 items each declaring exactly one status
  • ledger_check.py --ci -- OK

Auto-merge deliberately NOT armed. docs/BACKLOG.md is the one writer the coordinator playbook says
to serialise, and this renumbers 103 row lines -- landing it ahead of merge trains #274/#275 risks turning
them DIRTY. It gets armed once those land.

…on main

ci.yml sets step_timeout 36 for both Windows legs and, in the same comment
block, names its own re-derivation trigger: re-derive if a windows-2025
Tests (pytest) step is ever seen above 28:00.

Measured 2026-08-07 over all 80 ci.yml runs created that day, jobs fetched
with filter=all so an attempt killed at the cap is not hidden behind its
passing re-run, timing the STEP and filtering on step conclusion:

  windows-2025 Tests (pytest)   max passing 35:13   n=65 steps / 43 success
  cap 36:00 -> 47 seconds of margin, 1.022x
  passing steps above the 28:00 trigger: 43 of 43
  killed at 36:0x: 5, two of them push runs on main (7ecff8a, b78214f)

So the trigger is not merely fired, it is universally exceeded, and the cap
is failing green suites. ci.yml already records this shape once at 26:00
(PR #119, killed at 26:07 with zero tests failing, diagnosed there as
coin-flipping against the cap) and already admits 36:00 failed its own
spread rule when it was chosen, needing roughly 37:00 to hold.

Measured the step rather than the job deliberately: ci.yml records at least
three sessions substituting job durations while triaging this same cap, and
a job-duration reading of this pool gives 33-40 minutes, which invites the
wrong conclusion that the cap is comfortable.

job_timeout must be re-derived in the same act. The job carries two
step_timeout-gated pytest steps and its 46 is sized against the observed
sum, not 2 x step_timeout, so raising step_timeout alone moves the kill to
the job cap, where no step conclusion is reported and the instrument used
to measure this is lost.

Ledger mechanics, stated separately because they are independent claims:

  - Number allocated with scripts/coord/alloc.ps1, not grepped. Row added
    in this same commit at rank 6, ranks 6..108 renumbered to 7..109.
  - The renumber was bounded to the live table (lines 180..287). The file
    also holds a superseded 134-row 2026-07-10 table; an assertion checks
    it comes out byte-identical, and it does.
  - The four Distribution census lines were re-derived, not carried
    forward: Value 7 -> 8, Difficulty 3 -> 40, P1 -> 9, quick win -> 34,
    sum 108 -> 109.
  - The "Every one of the 102 open items" sentence was left ALONE on
    purpose. It is a dated claim about the 2026-08-03 re-scoring pass, not
    a live census, and bumping it would assert that pass scored items that
    did not exist yet. Prior passes appear to have bumped it; that looks
    like the actual source of its drift.

MY FILING IS CORRECT AND THE CENSUS IS STILL WRONG -- these are separate
claims and this commit only makes the first. Verified in both directions
with parse_items imported from backlog_status_check.py rather than a
hand-rolled scan, which surfaces PRE-EXISTING drift this commit does not
touch: 52 open items carry no row, 11 rows name an item that is not open,
and parse_items counts 150 open items against a census asserting 109. Those
two sets cancel on a total, which is why a matching sum never caught it.
That reconcile is its own pass and needs 52 items scored.

Gates run locally: backlog_status_check.py --min-items 150 OK (366 items,
each declaring exactly one status), ledger_check.py --ci OK.
… wrong instrument

#1084 was filed the same day, for the same leg and the same cap, and neither
item referenced the other. It is not a harmless duplicate: the two CONTRADICT
each other on the central action. #1084 says "Do NOT simply raise the cap";
#1096 says the cap must be re-derived. Left alone, whichever is worked first
leaves the survivor standing as an open item asserting the work was wrong.

The collision was invisible from this worktree. #1084 is not on main -- it
lives only on origin/claude/gate-3d-remedy-1057 (PR #261, open) -- so reading
docs/BACKLOG.md here shows no conflict, and backlog_status_check cannot see
one either. The cross-reference is therefore labelled FORWARD-LOOKING in the
item, per the rule that a citation which does not resolve yet must say so.

The contradiction resolves, and #1084 is not wrong in spirit -- its premise is
wrong. Its "~92% of step_timeout, about 17% headroom" comes from comparing JOB
wall time across three PRs (33m09s / 37m06s / 38m20s) against a STEP cap. On
the step the figure is 35:13 against 36:00 = 97.8% of budget, 2.2% headroom.
That is the same job-for-step substitution ci.yml already records at least
three earlier sessions making while triaging this very cap.

That changes what "protect the diagnostic" implies, which is the whole
disagreement. #1084 is right that step_timeout sits under job_timeout so a
deadlock below pytest surfaces as a step failure, and right that raising a cap
to buy a green tick would trade that away. But at 2.2% headroom, against a
distribution where EVERY passing run exceeds the file's own 28:00 re-derive
trigger, the cap fires on a healthy suite as readily as on a deadlock -- so
re-deriving it RESTORES the diagnostic rather than surrendering it.

Also absorbed from #1084 so closing it loses nothing: its three-wrong-answers
triage, the step-under-job rationale, its fix directions (margin reporting is
the cheapest and should likely happen regardless; splitting the Windows leg;
the measured 51% cut on tests/test_worktree_gate_remedy_families.py from
removing 30 of 36 git spawns), and its #1000 negative-control requirement.

Added stronger evidence than either item had alone: a SAME-COMMIT flip. Run
31192717684 (fix-1006-absence-mutation, head 27d7746) failed at 36:07 on
attempt 1 and passed at 33:14 on attempt 2. #1084 inferred a flip from three
DIFFERENT PRs, which is not identical content; this is.

The 43-of-43 figure is NOT rewritten to 45. An independent re-derivation later
the same day reproduced 35:13 to the second and the same five kills, with the
pool grown to n=68 and 45 of 45 above the trigger. It is recorded as a second
measurement with its own pool rather than folded in, because a number edited
away from the pool that produced it is exactly the rot ci.yml warns about.

Recommended disposition stated in the item: keep #1096, close #1084 as merged
into it, correct #1084's numbers rather than carrying them forward. There is
no allocation collision -- 1084 and 1096 are different numbers, only the
subject collided.

Gates: backlog_status_check.py --min-items 150 OK (366 items, each declaring
exactly one status), ledger_check.py --ci OK. Live table still 109 rows with
contiguous ranks; #1096 still parses open via parse_items.
Plain APPEND conflict in docs/BACKLOG.md: my side adds ## 1096., main's side
adds ## 1097. (landed via PR #282). Neither touches the other's text and the
overlapping-heading-number count between the sides is ZERO, measured. Kept
both, ascending: 1096 then 1097.

THIS CONFLICT WAS ENGINEERED TO LAND HERE RATHER THAN ON #282. Both PRs append
to the same file tail, so whichever merged second was always going to conflict.
#282 was armed FIRST and deliberately: the ledger gate keys on which worktree
ALLOCATED a number, #1097 belongs to nice-payne-4dcee0, and that session has
now stopped -- so a conflict landing on #282 would have been unresolvable by
anyone still running. #1096 is allocated to THIS worktree, so the conflict is
resolvable here. Ordering was the whole point; it was not luck.

Verified after resolution: ## 1094. x1, ## 1095. x1, ## 1096. x1, ## 1097. x1,
conflict markers 0, CRLF preserved. My #1084 reconciliation section survived
intact, as did #1096's table row and the census line reading 109. Live table
still 109 rows with contiguous ranks. backlog_status_check.py --min-items 150
OK at 368 items, each declaring exactly one status.

LEDGER DRIFT NOTE, stated rather than quietly absorbed: #1097 arrived with no
table row, so the gap between parse_items' open count and the census table
grows by one. That is the pre-existing drift already recorded in #1096's own
commit (52 open items with no row, 11 rows naming a closed item, the two sets
cancelling on a total). This merge does not fix it and does not make it worse
by any mechanism of mine -- it simply carries it forward, which is what a
correct filing does. The reconcile pass remains outstanding and needs 52 items
scored.
@wshallwshall
wshallwshall enabled auto-merge (squash) August 7, 2026 20:52
@wshallwshall
wshallwshall merged commit 3b2d9e9 into main Aug 7, 2026
32 checks passed
@wshallwshall
wshallwshall deleted the claude/coordinator-role-handoff-88d83e branch August 7, 2026 20:54
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