Conversation
Co-Authored-By: mecatl <noreply@mecatl.dev>
Co-authored-by: mecatl <noreply@mecatl.dev>
Co-authored-by: mecatl <noreply@mecatl.dev>
Co-authored-by: mecatl <noreply@mecatl.dev>
Co-authored-by: mecatl <noreply@mecatl.dev>
Co-authored-by: mecatl <noreply@mecatl.dev>
Co-authored-by: mecatl <noreply@mecatl.dev>
Co-Authored-By: mecatl <noreply@mecatl.dev>
Co-Authored-By: mecatl <noreply@mecatl.dev>
Co-Authored-By: mecatl <noreply@mecatl.dev>
ba77a17 to
caed7fd
Compare
jhrozek
left a comment
There was a problem hiding this comment.
Automated panel review (Spec, Standards, Test-adequacy, and a 5-agent Domain panel) against docs/acceptance/mecatui-bounded-scroll-selection.md. Full result: 1 blocker, 4 important, 8 advisory findings across the axes. Posting the actionable subset (1 blocker + 4 important) as inline comments below.
PANEL: ship_blockers=1 important=4 advisory=8 reviewer_failures=0
| s.rowBudget = modelsRowBudgetFor(height, modelsPanelFixedRows(*s, s.provenance, s.deps.marks)) | ||
| return renderModelsPanel(s.deps.theme, s.catalog, *s, s.deps.caps, s.provenance, s.deps.marks, s.rowBudget, width), nil | ||
| prefix, suffix := modelsFixedLines(*s, s.provenance) | ||
| s.rowBudget = max(0, height-len(prefix)-len(suffix)) |
There was a problem hiding this comment.
[blocker · test-adequacy] testdata/models_scrolled.golden was regenerated into a degenerate, near-empty ~4-cell box at 100×14 after pressing End on a 30-item list — the pre-diff golden correctly showed a populated "28–30 of 30" window (confirmed via git diff origin/main...HEAD -- cmd/mecatui/ui/testdata/models_scrolled.golden). This looks like the rendered height collapses to near-zero for a frame and the outer modal box gets sized to that collapsed content instead of the offered 100×14 — the opposite failure from what AC2.3 guards against ("no minimum-row rule that can force output beyond offered geometry"; here nothing floors it back up when it transiently collapses). compareGolden only diffs bytes against a self-generated fixture, so this shipped silently under a green gate. Worth tracing rowBudget here plus whatever sizes the outer box against it, and adding a content assertion ("at least one model row visible when width/height are ample") alongside the golden.
| topID, topLine, haveTop = oldLayout.rows[oldOffset].id, oldLayout.rows[oldOffset].itemLine, true | ||
| } | ||
|
|
||
| l.items = append(l.items[:0], items...) |
There was a problem hiding this comment.
[important · go-architect] boundedList is copied by value throughout agents_overlay.go (e.g. agentsSelectableList.control). l.items = append(l.items[:0], items...) mutates the shared backing array in place, so a copy's items slice aliases the original's. Call paths that build a copy and discard it — render/boundedView via indicatorAdjustedControl, and agentsNormalBodyFits — silently rewrite persisted roster state (m.subagents.roster, etc.) they never intended to touch. It's masked today because the next real setItems overwrites it again — exactly why it'll be a nasty one to chase down later. Suggest l.items = slices.Clone(items) (or append(l.items[:0:0], items...)).
| return list.cursor, list.control, false | ||
| } | ||
| th, _, _, height := m.agentsListGeometry() | ||
| control, _, _ := list.configuredControl(th, height) |
There was a problem hiding this comment.
[important · go-architect] This calls configuredControl and then control.move(move) directly. configuredControl sets viewport.height to the full capacity, but boundedListViewWithIndicators (used by the wheel path via scrollList, and by modelsState since it holds a *boundedList) shrinks height by 1–2 rows to reserve the "N lines above/below" indicators. So keyboard PgUp/PgDn here pages by a taller window than what's actually on screen — it skips 1–2 rows of content right at the indicator boundary that the wheel path doesn't skip. Suggest routing this through indicatorAdjustedControl like scrollList does, so all three paths agree on one height.
| above, below int | ||
| } | ||
|
|
||
| type boundedList struct { |
There was a problem hiding this comment.
[important · software-architect] cursorID, viewport.valid(), and reveal are read directly as struct fields at two independent call sites (models_surface.go:216,223,236 and agents_overlay.go:1070,1077), each reimplementing the same hadCursor := X.cursorID != "" check. boundedList already has a clean method surface (setGeometry, setItems, setCursor, move, scroll, view…) — worth adding hasCursor() bool / ready() bool accessors and switching both sites to them, so the field layout stays genuinely private and the duplicated one-liner can't drift if the empty-string sentinel convention ever changes.
| } | ||
| if layout.bounded { | ||
| layout.bodyCapacity = height - layout.frameRows - lipgloss.Height(layout.tabStrip) | ||
| layout.bodyCapacity = height - layout.frameRows - lipgloss.Height(layout.tabStrip) - 2 |
There was a problem hiding this comment.
[important · spec] layout.bodyCapacity = height - layout.frameRows - lipgloss.Height(layout.tabStrip) - 2 — this bare -2 sits alongside boundedListViewWithIndicators's own dynamic reservation for the above/below indicator rows: a static offset next to a dynamic one computing roughly the same thing. The plan's "Deferred decisions" section calls this out as a risk ("a second geometry calculation risks pointer disagreement and style leakage"). Could this derive from the same reservation logic boundedListViewWithIndicators uses, or at least get a comment naming exactly what two rows it reserves?
|
Thanks for the review! This was a first pass from the agent and I'm going to make sure I give it a careful review :) |
Stage
Implementation
Contract
297817d86ef8173452877d42bc4132d73da4efd5Implementation
boundedViewportand composedboundedList; no exported Go interface or protocol surface/models/modelsclick-to-cursor while Enter remains activationAcceptance
All 15 ACs in
docs/acceptance/mecatui-bounded-scroll-selection.mdare implemented and resolve under the targeted strict trace.Verification
task lint— passedtask test— passedtask test:golden— passedtask docs— passedtask site:build— passedtask api:check— passedgo run ./cmd/mecademo— passedac-trace --strict --plan docs/acceptance/mecatui-bounded-scroll-selection.md— 15 ACs, 0 failuresPANEL: ship_blockers=0 important=0 advisory=0 reviewer_failures=0The branch was intentionally not rebased in the large-context implementation session. Repository-wide
task ac-trace-strictfailed against this older baseline on unrelated acceptance-plan state; currentorigin/mainincludes0fe7b4739 fix(acceptance): resolve stale ac-trace proofs (#1600). Rebase and rerun the aggregate gates before merge.Deviations
No implementation deviation from the approved, operator-amended contract.
Relates to #1589