Files
multi-agent-mux/.agents/reports/canary-projects-multi-agent-mux-creator-cline/report-6f18ba0f.md
T
Godopu 14e306be46 feat(layout,test): resolve backlog items I-2, I-3, and C-1 with unanimous peer review
- I-2: add 5.0s upper-bound execution time assertion in test_bug4_headless_unobservable_fast_path to contractually guard SKS_EMPTY_GIVEUP early-exit latency
- I-3: clean up PaneInfo.focused, wire MAM_MAX_PANE_COLS/MAM_MAX_COLS environment variables and CLI --max-cols flag
- C-1: apply max_columns growth guard to headless 0x0 layouts, mirroring GUI behavior
- Promoted Planner consensus plan Rev.2 (plan-fea5f1b2.md) and unanimous PASS reports from Reviewers Claude (report-55d1a1d9.md) and Cline (report-6f18ba0f.md)
- Verified all 333 test cases pass with exit code 0
2026-08-23 21:59:03 +09:00

9.4 KiB

Cross-Code Review — Job 6f18ba0f

  • Reviewer: cline (session: herdr:canary-projects-multi-agent-mux-creator-cline)
  • Subject: Backlog items I-2 (headless fast-path timing contract) and I-3 (PaneInfo.focused cleanup, --max-cols/max_columns_reached coherence, headless anchor comment refinement), plus the C-1 headless max-columns guard.
  • Changeset: git difflib_py/layout.py (69 lines), tests/test_layout.py (75 lines, +3 tests), tests/test_b19_headless_reconcile_fixes.py (25 lines), .mam.env.example (14 lines), IMPROVEMENTS.md (3 lines). lib.sh is not modified (verified: layout block unchanged at :432).
  • Date: 2026-08-23

§0 Executive Summary

The changeset cleanly addresses both backlog items and a related headless max-columns defect (C-1). I-2 adds a contractual wall-clock upper bound to the headless fast-path test, with a precise rationale for why a timing assertion is the only signal that catches that particular regression. I-3 removes the unused/non-deterministic PaneInfo.focused field (with a clear determinism rationale), renames the extractor accordingly, wires MAM_MAX_PANE_COLS/MAM_MAX_COLS through a graceful _env_int helper, and refines the headless anchor comments. The C-1 fix makes headless mode honor max_columns on the column-opening (right) branch while deliberately leaving the column-filling (down) branch uncapped — mirroring the GUI path, and documented as such.

I verified the API rename introduces no orphan importers, ran the directly-affected suites (layout 19/19, b19 6/6, herdr_shim_contract 5/5 — all pass), and confirmed lib.sh's layout invocation is untouched. No lint, behavioral, or missing-coverage defects found.

Verdict: PASS.


§1 I-2 — Headless fast-path timing contract (verified)

tests/test_b19_headless_reconcile_fixes.py::test_bug4_headless_unobservable_fast_path:

  • Adds import time and an elapsed < 5.0 assertion with a failure message that names the exact regression (SKS_EMPTY_GIVEUP early exit removed → full 10s quiescence window consumed). The docstring justifies the bound empirically (1.22s with the optimization vs 10.21s without) and explains why functional assertions alone cannot detect the regression. This is a well-reasoned contractual guard, not a flaky nicety.
  • Strips SKS_QUIESCENT_TRIES/SKS_QUIESCENT_INTERVAL/SKS_EMPTY_GIVEUP from the subprocess env so lib.sh defaults apply cleanly — making the timing assertion reproducible regardless of the caller's shell env.
  • The mock's paste-buffer branch had its early return 0 removed; control now falls through to the final return 0 (line 161) with no intervening branch — functionally identical (both return 0), a harmless no-op cleanup.
  • Result: 6/6 b19 tests pass in 4.43s; the fast-path test itself runs well under the 5.0s bound (no flakiness margin concern).

§2 I-3 — layout.py cleanup & max-cols coherence (verified)

PaneInfo.focused removal

  • The focused: bool = False field is deleted and replaced with a NOTE comment: the engine is deliberately geometry/structure-driven so identical pane sets yield identical decisions; focus is user-interaction state that would make results non-deterministic. This is the correct call for a layout engine and the rationale is documented inline.
  • extract_panes_and_focusextract_panes, now returning List[PaneInfo] only; all focused_id extraction logic removed. Docstring updated to enumerate the three accepted payload shapes.
  • Orphan check: grep for extract_panes_and_focus / PaneInfo / extract_panes importers across .agents and testsNONE. The remaining focused_pane_id occurrences (conftest.py:297/315, test_layout.py:177) are herdr payload data (herdr 0.8 emits that field), which the engine now correctly ignores — not symbol references. No breakage.

--max-cols / max_columns_reached coherence

  • New _env_int(*names) helper reads the first non-empty env var among its arguments, parsing as int and returning None on bad values (a typo won't crash the layout call; lib.sh's || echo "right …" fallback still applies). Used for --min-cols, --min-rows, and --max-cols defaults.
  • --max-cols default changed from None to _env_int("MAM_MAX_COLS", "MAM_MAX_PANE_COLS") — so the column cap is honored without a CLI flag, which is exactly how lib.sh invokes the module (it passes no --max-cols). This is the key behavioral fix.
  • C-1: the headless even-n branch now computes current_cols = n // 2 and returns overflow/max_columns_reached when current_cols >= max_columns. The odd-n down branch deliberately ignores the cap (it fills an existing column, never opens one) — mirroring the GUI fill_singleton_column path, with an inline comment stating this. Coherent and symmetric with the GUI path.

Headless anchor comment refinement

  • The terse alternation comment was replaced with a detailed explanation of why n // 2 is the completed-column count under the alternation invariant, and how an odd-n drift self-corrects at the next even n. Directly satisfies the "refine comments regarding headless anchor fallback" requirement.

lib.sh (I-3 scope)

  • lib.sh is unmodified in this changeset (diff stat confirms; python3 -m lib_py.layout still at :432). The lib.sh-facing concern — that the env-var path works without a --max-cols flag — is covered by test_env_max_cols_applies_without_flag. No lib.sh edit is needed.

§3 Test Coverage & DoD

New layout tests (tests/test_layout.py, +3, total 19, all PASS in 0.21s):

  • test_cli_max_cols_flag_triggers_overflow — CLI --max-cols 2 reaches compute_2xk_layout and yields overflow / max_columns_reached on a 4-pane/2-column payload.
  • test_env_max_cols_applies_without_flagMAM_MAX_PANE_COLS=2 is honoured with no --max-cols flag (the lib.sh invocation shape); asserts max_columns_reached.
  • test_headless_max_columns_growth_guard — C-1: headless n=4/max=2 → overflow; n=2/max=2 → right (grows below cap); n=3/max=2 → down (fill not blocked); n=4 no cap → right (behavior neutrality). Comprehensive.

b19 suite (tests/test_b19_headless_reconcile_fixes.py, 6/6 PASS in 4.43s) — I-2 timing contract holds.

Shim contract (tests/test_herdr_shim_contract.py, 5/5 PASS in 1.77s) — integration intact after the API rename.

Broader suite: the e2e/tier3-4 files are slow (subprocess-heavy, exceed the 30s run-window). I confirmed in the prior review cycle that test_tier1_unit (45), test_sanity + test_deploy_freshness (33), and test_herdr_shim_contract (5) pass, and — critically — a grep for importers of PaneInfo / extract_panes / extract_panes_and_focus across .agents and tests returns NONE, so the API rename cannot regress any other suite. No regression risk from this changeset's surface change.

Total confirmed passing this cycle: 30 tests (19 layout + 6 b19 + 5 shim-contract), 0 failures.


§4 Soundness & Cleanup

  • No orphan references: removed/renamed symbols have zero importers; remaining focused_pane_id strings are payload data, correctly ignored.
  • lib.sh untouched: the prior G-1 fix (python3 -m lib_py.layout at :432) is preserved; no regression to the integration.
  • Env wiring documented: .mam.env.example documents MAM_MIN_PANE_COLS/MAM_MIN_PANE_ROWS/MAM_MAX_PANE_COLS with defaults and the overflow semantics; IMPROVEMENTS.md records I-2/I-3/C-1 completion and updated test counts.
  • Graceful degradation: _env_int returns None on bad values rather than raising; combined with lib.sh's || echo "right $sample_pane" fallback, a malformed env var degrades to a safe default instead of crashing the layout call.
  • Tuple import removed (no longer needed after the return-type simplification). No unused imports remain.

§5 Minor Observations (non-blocking)

  1. _env_int behavior change for min-cols/min-rows on bad env values: previously int(bad_value) would raise (crash → lib.sh fallback to right); now it returns None → falls back to the 60/20 default. This is a robustness improvement and the docstring states the rationale, but it is a subtle behavior change worth being aware of (a typo no longer surfaces as a hard failure). Acceptable and intentional.
  2. b19 mock return 0 removal in the paste-buffer branch is a pure no-op (falls through to the identical final return 0). Harmless, though its presence in the diff adds minor noise with no behavioral effect. Cosmetic.
  3. Broader e2e/tier3-4 suites were not re-run this cycle due to the 30s run-window; the orphan-importer check substantiates that the API rename cannot affect them, but a full pytest tests/ in an unbounded environment would be the strongest DoD signal. Not a blocker.

None of the above warrant a NOT PASS or a planner escalation. They are notes for future polish only.


§6 Verdict

Both backlog items (I-2, I-3) and the related C-1 headless max-columns defect are correctly and coherently addressed. The unused/non-deterministic focused field is removed with documented rationale, the --max-cols/env wiring is clean and tested on both CLI and env paths, headless mode now honors the column cap symmetrically with the GUI path, the fast-path timing is contractually guarded, and 30 directly-relevant tests pass with zero orphan references to the renamed API.

[VERDICT: PASS]