Skip to content

Retire the four-item lane ceiling from the lane tooling (owner ruling 2026-10-26) - #2543

Merged
wshallwshall merged 8 commits into
mainfrom
retire-lane-capacity-cap
Oct 27, 2026
Merged

wshallwshall merged 8 commits into
mainfrom
retire-lane-capacity-cap

Conversation

@wshallwshall

@wshallwshall wshallwshall commented Oct 26, 2026 •

Copy link
Copy Markdown
Collaborator

Owner rulings 2026-10-26, in session: the Builder four-item lane ceiling and the burn start-throttle are retired, and there is no WIP limit on briefing. Usage is governed by the Steward's holds and the korus Workflow gate.

  • scripts/coord/lane.ps1: -Capacity (default 4) is removed. The capacity field is written as null rather than dropped, so an older lane.ps1 on another branch can still restate (measured: the old writer exits 1 on a record without the key, 0 with it null). -Free and -InFlight have no upper bound, and -Free counts only held items.
  • scripts/hooks/lane-level.ps1: the AT CAPACITY and SERIAL verdicts and the quiet-when-full exit are gone. A lane reports STATED or IDLE. Also fixes Get-AgeMin, which read UTC stamps as hours in the future west of UTC, so STALE and the 15-minute re-prompt never fired.
  • tests/test_coord_lane_no_ceiling.py (new): 8 tests that fail if a default cap of 4, a count bound or the AT CAPACITY verdict returns. Their controls were measured against origin/main.

Not in this PR:

  • The vault's own copies of both scripts still carry the ceiling, and the installed Stop wrapper prefers the vault hook. A vault PR follows.
  • The dispatcher arm still matches no live seat.
  • The builder nag misses agent-* subagent worktrees.
  • $EXPECTED_LANES = 2 is still hard-coded.

Related: #2534 and MEFORORG/korus#246 carry the same rulings in the playbooks and cards.

Checks: ruff and ruff format on both test files; mypy tests leg on both; pytest, 355 passed across the 11 files that reference these scripts; lane-level.ps1 -SelfTest passes; pre-commit passed. Full suite not run.

QA: code-review at level xhigh, two rounds, round-abf8f84da9 and round-fce919bd8b. Tag for both: xhigh effort -> 10 inline angles -> dedup (no verify) -> sweep -> <=15 findings, read with korus scripts/quality/review_tag.py from origin/main (exit 0). The round-two fixes are covered by tests but have not been reviewed again (repair cap).

RetriggerView in GreptileConfidence Score: 4/5

The PR appears safe to merge, with a non-blocking gap in the timezone regression test.

Fix All in Claude CodeFindings

  1. P2 UTC hides the age regression ▶
Fix with agent prompt
### Issue 1
tests/test_coord_lane_no_ceiling.py:242-250
If Windows uses UTC, these tests pass even with the original broken `Get-AgeMin` conversion. The extra local-to-UTC conversion changes nothing there, so both the 0-minute and 45-minute cases still pass. Add a controlled non-UTC case so a UTC test runner can catch this bug returning.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Summary

Removes the lane tooling's four-item ceiling.

  • Lane statements can record counts without a four-item ceiling.
  • The dispatcher gets lane counts without a capacity verdict.
  • Builder prompts now recognize how old a lane level is.

Acknowledged exclusions from wshallwshall: vault copies and the installed wrapper still use the old ceiling; a vault PR follows. The dispatcher seat match, missing agent-* reminders, and hard-coded $EXPECTED_LANES = 2 are explicitly deferred.

Reviews (1) · Last reviewed commit: "Read a lane level's age in UTC, and keep..." · Reviewed by Greptile

Owner ruling 2026-10-26: the Builder four-item lane ceiling and the
start-throttle by burn are retired, and there is no WIP limit on
briefing. Usage is governed only by the Steward's holds and the korus
Workflow gate.

lane.ps1 drops -Capacity (default 4) and the record's capacity field,
and strips a capacity left on an older record on its next write.
lane-level.ps1 no longer reads a lane as AT CAPACITY or SERIAL, and no
item count buys the dispatcher arm silence: each lane is reported as
STATED with its in-flight and free-by-work counts. New tests in
tests/test_coord_lane_no_ceiling.py fail if a default cap of 4 returns.

Proposed PR title: Retire the four-item lane ceiling from the lane tooling
Against the pre-change scripts the dispatcher-report test failed on its
count-format check before it reached the capacity check. The control is
now the lane's note, which both versions print, and the capacity
assertions come next, so a returning ceiling is what turns it red.
Measured: line 214, the capacity assertion, fails on origin/main's
scripts; all five tests pass on this branch.
Round-one code-review fixes. Dropping the capacity key broke an older
lane.ps1 run from another branch: it assigns $rec.capacity, which
throws under StrictMode when the key is missing. Measured: the old
writer exits 1 on a record without the key and 0 with it as null. So
lane.ps1 now writes capacity as null on every write.

Also: -Free and -InFlight take any non-negative count; the hook reads
a lane with nothing in flight as IDLE; ROSTER DRIFT fires only on a
shortfall of lanes; the builder nag says to count no empty slots; and
the ruling is stated once, in lane.ps1's header.
Round-two code-review fixes. lane-level.ps1's Get-AgeMin passed the
[datetime] ConvertFrom-Json returns back through [datetime]::Parse,
which re-read it as local time and added the offset again, so a level
stated 45 minutes ago read as hours in the future and the STALE check
and the builder re-prompt never fired west of UTC. It now mirrors the
fix lane.ps1 already carries at its statedUtc guard. New tests: a
builder lane is asked again at 45 minutes and not at 0, and the
dispatcher report never prints a negative age.

Also: the hook's CANNOT SEE text again names Steward holds, and says a
hold, not a count, is what stops briefing; ROSTER DRIFT goes back to
firing on any count but the expected one; the UNREADABLE line names a
missing count; and lane.ps1's comments say what actually throws and
which lanes the hook re-prompts.
@wshallwshall wshallwshall added the qa Builder QA record posted; not a merge gate label Oct 26, 2026
Comment on lines +242 to +250
@pytest.mark.parametrize(("minutes_ago", "nags"), [(0, False), (45, True)])
def test_a_builder_lane_is_asked_again_once_its_level_ages(
tmp_path: Path, minutes_ago: int, nags: bool
) -> None:
"""The 0-minute case is the control: the nag below is the age's, not the record's shape's."""
shared = tmp_path / "shared" / "mefor-coord"
(shared / "lanes").mkdir(parents=True)
builder = _git_repo(tmp_path / "builder-lane")
stamp = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(time.time() - minutes_ago * 60))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 UTC hides the age regression

If Windows uses UTC, these tests pass even with the original broken Get-AgeMin conversion. The extra local-to-UTC conversion changes nothing there, so both the 0-minute and 45-minute cases still pass. Add a controlled non-UTC case so a UTC test runner can catch this bug returning.

Prompt To Fix With AI
This is a comment left during a code review.
Path: tests/test_coord_lane_no_ceiling.py
Line: 242-250

Comment:
**UTC hides the age regression**

If Windows uses UTC, these tests pass even with the original broken `Get-AgeMin` conversion. The extra local-to-UTC conversion changes nothing there, so both the 0-minute and 45-minute cases still pass. Add a controlled non-UTC case so a UTC test runner can catch this bug returning.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Fix in Claude Code

@wshallwshall

Copy link
Copy Markdown
Collaborator Author

Merge order: the vault companion is MEFORORG/MessageFoundry-vault#2704. The installed gauge shim runs the vault hook in engine sessions, so merge the vault PR with or before this one, then update the vault primary checkout.

@wshallwshall

Copy link
Copy Markdown
Collaborator Author

Lander: review proof now covers engine 2543 at 0a53e43150 and vault 2704 at 1fe102dbfa.

A Lander-dispatched code-review run (level xhigh, nonce round-a826d611af, korus review_tag.py exit 0, one fork, tag xhigh effort -> 10 inline angles -> dedup (no verify) -> sweep -> <=15 findings) covered the round-two fixes: engine a6b3f2fc63..0a53e43150 and vault b4a2bffae9..1fe102dbfa. Engine test_coord_lane_no_ceiling.py and test_coord_lane_statement.py pass at the head (31 passed); with the old Get-AgeMin restored, two go red on a Central-time host.

  • No finding changes behaviour or weakens a control. Neither PR touches Steward, Workflow-gate or hold code, and round two adds that the hook does not read holds.
  • The two PRs agree with each other and with the 2026-10-26 ruling. Merge order: vault 2704 with or before engine 2543, then update the vault primary checkout (installed-hook drift).
  • Rows before the merge, at least: the age tests pass on a UTC runner either way, so CI cannot catch a revert of the fix; an unreadable statedUtc still reads FRESH (older than this PR); stale header and comment claims in lane.ps1 and the hook (never-asked, SUPERSEDED/STALE/NEVER-STATED, line 145, "both lanes"); ROSTER DRIFT on -ne explains only the too-few case; no engine self-test age case; a fourth inline UTC normalisation (the vault has utc-instant.ps1); the same [datetime]::Parse pattern in claim.ps1:772 and overlap.ps1:945, untraced; vault self-test b9 exercises the string path, not a UTC [datetime]. Six of vault 2704's seven declines are agreed row candidates; the old capacity-4 records decline holds.

@github-actions github-actions Bot added the ci-red A required check went red. Attribute it before retrying. label Oct 26, 2026
tests/test_coord_lane_no_ceiling.py runs scripts/coord/lane.ps1 and
scripts/hooks/lane-level.ps1 as real pwsh children and imports nothing
from messagefoundry, so its subject is the coordination harness. It
joins tests/tooling_manifest.txt beside its sibling
tests/test_coord_lane_statement.py, in that block's alphabetical order.
Without it, test_every_non_engine_test_is_classified reported the file
as UNCLASSIFIED and turned all three test legs red.
@wshallwshall

Copy link
Copy Markdown
Collaborator Author

Fix for the red test legs: commit b6867fa (fast-forward on top of 0a53e43).

What changed. One line in tests/tooling_manifest.txt: tests/test_coord_lane_no_ceiling.py, inserted directly before its sibling tests/test_coord_lane_statement.py, in that block's alphabetical order.

Why the manifest and not _STAYS_WITHOUT_IMPORTING. The test's subject is scripts/coord/lane.ps1 and scripts/hooks/lane-level.ps1, which it runs as real pwsh children. It imports nothing from messagefoundry and reads no file under messagefoundry/** or packaging/messagefoundry-webconsole/** (grep for both is empty), so it is option (a) in the partition test's own message, a HARNESS subject. Its sibling test_coord_lane_statement.py, with the same subject, is already in the manifest. A diff that can break it is a diff under scripts/**, which the tooling job's path gate selects.

Tests run.

  • Control: tests/test_tooling_partition.py against the parent's manifest: 1 failed, 39 passed, failing on UNCLASSIFIED TEST FILE(S) ... ['test_coord_lane_no_ceiling.py'], the reported red.
  • With the fix: tests/test_tooling_partition.py 40 passed.
  • tests/test_tooling_partition.py, tests/test_coord_lane_no_ceiling.py, and every test that reads the manifest (test_ci_tooling_gate.py, test_audit_all_platforms.py, test_connscale_smoke.py, test_cp1252_console_safety.py, test_net_helper_install_scripts.py, test_precompact_reprime_hook.py): 229 passed.
  • ruff not run: no .py file changed. Pre-commit hooks passed.
QA -- korus roles/BUILDER.md step 11
Level: xhigh, from the brief. Tag: xhigh effort -> 10 inline angles -> dedup (no verify) -> sweep -> <=15 findings (fork a9332d69fe66b0cf2 round-067b2a8531; ascii spelling).
Rounds: 1. Findings: 0 on this commit; 11 on the branch's earlier commits, not repaired here (out of this brief's scope), 11 open.

The review ran over the whole branch diff against origin/main, so its 11 findings land on the earlier commits' lane.ps1, lane-level.ps1 and test file, not on the manifest line. Two that may change behaviour, carried for the Manager:

  1. The installed Stop shim resolves the vault copy of lane-level.ps1 first, and that copy still has the AT-CAPACITY verdict. Under the new meaning of -Free (held items only), it would read more lanes as full.
  2. statedFree changes meaning while the record stays v = 1, and the hook stops reading capacity, the one field that tells an old writer's record from a new one's.

The rest: the Get-AgeMin tests cannot fail on a UTC runner; $EXPECTED_LANES = 2 stays hardcoded; the builder arm reads $rec.statedUtc without Test-Has under StrictMode; an unparseable statedUtc reads as FRESH; the dispatcher arm now reports on every Stop; some prose misstates the old behaviour; Get-AgeMin duplicates ConvertTo-UtcDateTime; -SelfTest returns before the dot-sources; and the test file duplicates sibling helpers.

The current lane.ps1 writes capacity as null on every write; an older copy
writes a number there on every statement, and its free count includes the
empty slots under the retired ceiling. lane-level.ps1 now reads a non-null
capacity as that marker, never as a cap: the dispatcher arm shows the lane
as OLD-WRITER with its in-flight count and no free count, and asks for a
restatement; the builder arm asks every turn, naming the lane.ps1 beside the
hook. Null or absent capacity reads as before. No cap or full verdict, and
the record version is unchanged.

Self-test gains an old record (capacity 4, 2 free, 2 in flight) and its
null-capacity control; tests/test_coord_lane_no_ceiling.py gains the same
pair for the dispatcher and builder arms.

Follow-up on PR 2543 (lane ceiling retired, owner ruling 2026-10-26).
… on a level

Review round one on the OLD-WRITER change. The unstated-or-stale nag told
the lane to run its worktree's own lane.ps1, which may be the older copy,
so the two nags could alternate; both now name the lane.ps1 beside the hook.
The OLD-WRITER nag fires only on a record with a stated level, since a
record with none holds no free count; the unstated nag covers it. The hook
header no longer dates the old meaning, and lane.ps1's comment points at the
hook header instead of restating it.

Follow-up on PR 2543 (lane ceiling retired, owner ruling 2026-10-26).
-Asked writes no counts, so nulling capacity there erased the marker of an
older writer's statement and left its slot-inclusive free count reading as
held items. A statement still writes capacity as null; -Asked keeps any
value it finds and adds the key as null only when it is missing, because an
older lane.ps1 assigns it and throws without it. The test that expected
-Asked to null it now expects 4 kept, and a new case covers the missing key.

Also from review round two: the dispatcher OLD-WRITER line no longer says
the lane's own nag will ask it (that arm runs only in builder* worktrees),
and the test docstring no longer calls age the migration path.

Follow-up on PR 2543 (lane ceiling retired, owner ruling 2026-10-26).
@wshallwshall

Copy link
Copy Markdown
Collaborator Author

Follow-up pushed to retire-lane-capacity-cap: head is now a22cf38cf0d33d8ec600e900bfae5eda8927ae77 (fast-forward from b6867fa3d). Three commits:

  • 6c4dafddb: lane-level.ps1 tells an older lane.ps1's level apart. A record whose capacity is non-null was stated by an older writer, whose free count includes empty slots. The dispatcher arm labels it OLD-WRITER, shows its in-flight count, withholds the free count, and asks the lane to restate with a current lane.ps1. The builder arm asks every turn until it restates. Null or absent capacity reads as before. No cap, no full verdict, and record v is unchanged.
  • 8f47f872d (review round one): both builder nags name the lane.ps1 beside the hook, because a worktree's own copy may be the older one and the two nags could alternate. The OLD-WRITER nag fires only on a record with a stated level.
  • a22cf38cf (Manager addition, matching vault ea5c45265): lane.ps1 -Asked keeps any capacity it finds, and only a statement nulls it. -Asked still adds the key as null when it is missing. Review round two: the dispatcher text no longer claims the lane's own nag will ask it.

Tests: self-test now 10 cases, including capacity 4 with 2 free and 2 in flight read as OLD-WRITER with no free count, and the same counts with capacity null read as STATED with 2 free. In tests/test_coord_lane_no_ceiling.py, there is a dispatcher pair and a builder pair, each with the null-capacity control. An unstated old-writer record gets the unstated nag. -Asked keeps 4 and a statement nulls it. -Asked adds a missing key as null. Against the pre-change hook, the two old-writer arms fail and their controls pass.

Checks: pytest tests/test_coord_lane_no_ceiling.py tests/test_coord_lane_statement.py tests/test_tooling_partition.py tests/test_coord_host_box_key.py tests/test_coord_shared_root_seats_mail.py tests/test_coord_cloud_refusal.py gave 190 passed. ruff check and ruff format --check on the test file are clean, and lane-level.ps1 -SelfTest passes. mypy was not run, because there are no Python package changes.

QA: Level: xhigh, from the brief. Tag: xhigh effort -> 10 inline angles -> dedup (no verify) -> sweep -> <=15 findings (forks a0d84a56a3cb8180a round-8ff925ef58, ac538155f15e3fcb2 round-5cc1f8f1fd; ascii spelling). Round one's findings on this change are fixed in 8f47f87. Round two's are fixed in a22cf38, which is the -Asked change. a22cf38 itself had no third review round, because the cap is two.

Open findings on earlier commits, listed and not fixed:

  • statedFree changes meaning in place under the same field and v. An unupdated lane-level.ps1 that falls back to cap 4 reads a current writer's 0 free with 2 or more in flight as full, sooner than before. The reviewer suggested a new field, with statedFree written as null.
  • The timezone regression tests cannot fail on a UTC-clock runner.
  • Get-AgeMin duplicates ConvertTo-UtcDateTime in config-roots.ps1. An unparseable statedUtc reads as FRESH.
  • The builder arm reads $rec.statedUtc with no Test-Has guard under StrictMode, so a {} lane file crashes the hook.
  • SUPERSEDED, and STALE by turns, can never fire, because nothing updates tipNow, claimHashNow or turnsSinceStated.
  • TIMEOUT = 90 in the test file is above the suite's 60 s per-test cap.
  • The fleet-pane mod renders of ${capacity ?? '?'}.
  • The korus fleet-write-a-report-or-handoff skill quotes lane.ps1's old synopsis.
  • lane.ps1's header still dates the old meaning ("before 2026-10-26") rather than tying it to the writer.
  • The dispatcher arm matches only a dispatcher leaf or branch, a seat that has been retired.

Noted from the vault Builder, not fixed here: the vault hook, which the install shim runs in engine sessions, looks up builder records by a path-only key, while the engine writes host-plus-path keys.

@wshallwshall

Copy link
Copy Markdown
Collaborator Author

Lander: review proof now covers head a22cf38cf0d33d8ec600e900bfae5eda8927ae77.

Scope: a Lander-dispatched code-review run over a22cf38cf~1..a22cf38cf, the -Asked change that round two did not cover.

  • Level xhigh, nonce round-9af206694e.
  • Korus review_tag.py exited 0 on 1 fork.
  • Tag, verbatim: xhigh effort → 10 inline angles → dedup (no verify) → sweep → ≤15 findings.
  • The reviewer spot-checked findings 1, 3, 5 and 8 against the tree and origin/main.

No finding ships a behaviour defect or weakens a control. The two copies agree on -Asked (vault 2704 ea5c45265c, scripts/coord/lane.ps1:176-178).

Findings, all filed as rows before merge, with the rows from QA comment 6428262563:

  1. lane.ps1:263, low: the missing-capacity guard runs after earlier property sets, so it covers only a hand-shaped record.
  2. lane.ps1:209, low: the unlocked read-modify-write can now restore an old writer's numeric capacity over a restatement. The race already existed.
  3. lane-level.ps1:21, low: the header dropped the caveat that a null does not prove the current writer stated the counts.
  4. lane.ps1:262, info: capacity is overloaded as a writer marker. Suggest an explicit stamp, such as noCeilingStatedUtc.
  5. lane.ps1:260, low: "An older copy of that hook falls back to 4 whatever this field holds" is false; main's hook line 93 uses any truthy number. The vault copy carries the same sentence.
  6. lane.ps1:253, low: the headline "WRITTEN AS NULL, NEVER DROPPED" half-contradicts the -Asked branch.
  7. lane-level.ps1:16, low: the writer contract is restated in three places (SDS-3.5).
  8. lane-level.ps1:18, low: the header overclaims. An older -Asked on a missing file writes capacity=4 with no counts.
  9. tests/test_coord_lane_no_ceiling.py:145, low: the -Asked control does not assert that statedFree, statedUtc and statedNote are unchanged.
  10. lane.ps1:262, info: the if/elseif collapses to one guarded Add-Member, as the vault copy has it.
  11. lane-level.ps1:436, low: "Its own hook asks only in a builder* worktree". The installed hook comes from a primary checkout, so no lane sees the OLD-WRITER nag until that primary carries this version.

Order stands: vault 2704 merges first, then this PR, then the vault primary is pulled.

@wshallwshall

Copy link
Copy Markdown
Collaborator Author

Lander: one re-run of the failed jobs on head a22cf38cf0d33d8ec600e900bfae5eda8927ae77.

Run 40408302361, job repo harness tests (ubuntu-latest) (https://github.com/MEFORORG/MessageFoundry/actions/runs/40408302361/job/121872200363): 39 failed, 5869 passed. All 39 failures are pwsh exiting -6 with "Unhandled exception. System.ArgumentException: String cannot have zero length". They are spread across the worktree-gate parsing, quote-straddle, install-gate provenance and spawn-lock tests. The same leg passed on main a63e960ef2. CI gate failed along with it.

If the re-run goes red with the same signature, that is a finding: it would point at this PR's lane tooling rather than the runner.

Rows are filed: #4411 to #4430 (vault PR 2713, merged). Order once green: vault PR 2704 merges first, then this PR.

@wshallwshall

Copy link
Copy Markdown
Collaborator Author

Lander: enqueuing at pinned head a22cf38cf0d33d8ec600e900bfae5eda8927ae77. Every required context in branch protection's live list is completed/success on this head (read 2026-10-26 ~22:00Z). Review proof covers this head (see the QA and Lander comments above). Findings left open are filed as ledger rows: #4411 to #4430 (vault PR 2713, merged), with own-grade notes in vault PRs 2717 and 2719. Vault PR 2704, its pair, merged first. The Windows DICOM flake that held the queue is fixed by engine PR 2552 (merged 8bac1f5).

@wshallwshall
wshallwshall added this pull request to the merge queue Oct 27, 2026
Merged via the queue into main with commit 59124ff Oct 27, 2026
70 of 72 checks passed
@wshallwshall
wshallwshall deleted the retire-lane-capacity-cap branch October 27, 2026 04:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci-red A required check went red. Attribute it before retrying. qa Builder QA record posted; not a merge gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant