Skip to content

fix(composer): require corroboration before empty-classifying left-bar idle hints - #4480

Open
pablontiv wants to merge 1 commit into
kunchenguid:mainfrom
pablontiv:fm/fix-4477-leftbar-swallow
Open

pablontiv wants to merge 1 commit into
kunchenguid:mainfrom
pablontiv:fm/fix-4477-leftbar-swallow

Conversation

@pablontiv

Copy link
Copy Markdown
Contributor

Intent

Captain's intent: dispatch now. Fix GitHub issue #4477 in this fork and open a PR through the normal contribution flow, with exact issue linkage (the PR must close #4477). This is a reproduced dangerous-direction false-empty defect in a distinct composer path from the recently-shipped bordered-box hardening (#2483/PR #4452).

Issue #4477 substance: _fm_composer_classify_leftbar (bin/fm-composer-lib.sh:1104) skips a row as furniture using an unanchored/prefix match against FM_COMPOSER_IDLE_RE/FM_COMPOSER_IDLE_RE_DEFAULT, gated only by placeholder_position (the first non-blank content row after a leading blank left-bar row), with NO independent-empty corroboration - pending_seen=0 unconditionally yields empty. A real, genuinely-unsent draft that begins with a placeholder phrase (e.g. the default Ask anything...) is misclassified empty instead of pending. Confirmed live using the OpenCode 1.18.30 capture shape already in tests/fm-composer-lib.test.sh:411: Ask anything... please reply at placeholder_position=1 -> wrongly empty; Reply with OK. at the same shape -> correctly pending. This path (OpenCode/Grok/Kimi's left-bar composer) is MORE exposed than the bordered-box path because it has no empty_seen-style corroboration gate at all - a single swallowed row is sufficient to misclassify. The sibling bordered-box hardening requires an exact full-row furniture match rather than a prefix or substring and requires at least one independent row to prove empty before returning empty.

What Changed

  • _fm_composer_classify_leftbar (bin/fm-composer-lib.sh) no longer treats a placeholder-position idle-hint match alone as proof of an empty composer: it now tracks empty_seen, set only by an independently blank/ghost-stripped row, and returns unknown instead of empty when no such corroboration exists.
  • FM_COMPOSER_IDLE_RE_DEFAULT is tightened so the Ask anything... idle pattern only matches an optional single trailing quoted suggestion (([[:space:]]+"[^"]*")?$) instead of an unanchored prefix, so a real draft that starts with the placeholder phrase (e.g. Ask anything... please reply) is no longer swallowed as furniture; both _fm_composer_classify_leftbar and fm_composer_extract_selected_content build and use this anchored furniture_re instead of matching the raw idle regex.
  • Adds coverage in tests/fm-composer-lib.test.sh for a placeholder-prefixed draft (classified pending), a furniture-only left-bar row with no corroborating blank (classified unknown), and selected-content extraction preserving placeholder-prefixed input.

Risk Assessment

✅ Low: The fix directly addresses the issue's root cause (unanchored idle-placeholder regex + missing independent-empty corroboration in the leftbar path), mirrors the sibling bordered-box hardening as required, is covered by new tests that reproduce the exact reported failure and pass/fail appropriately, and I traced the row-loop logic against both new and pre-existing test screens without finding a silent misclassification.

Testing

Ran the actual bash composer-classifier library through its existing test suite at the target commit (all pass, including two new regression assertions for the exact issue-#4477 shape), then live-reproduced the reported defect by temporarily substituting the pre-fix library file and observing the same test fail exactly as described, confirming this is a genuine fix; worktree was restored clean afterward.

  • Live validation: ✅ go - 5 of 6 scenarios driven live against the product
Scenario Result Live Evidence
Placeholder-prefixed real draft is no longer swallowed as empty ✅ pass live bash tests/fm-composer-lib.test.sh at target commit dd91570: ok - matrix: opencode's left-bar composer reads empty everywhere and scans the full active run (includes the 'opencode 1.18.30 placeho…
Regression reproduction: same scenario misclassified as empty on pre-fix code ✅ pass live Swapped bin/fm-composer-lib.sh to the base commit (a6618dd) version in place while keeping the fixed test file, reran suite: `not ok - opencode 1.18.30 placeholder-prefixed draft on tmux: expected pe…
Furniture-only single row (no corroboration) now reads unknown, not empty ✅ pass live Same test function assertion 'opencode furniture-only left-bar lacks empty proof' expects unknown; part of the passing ok - matrix: opencode's left-bar composer... line in the target-commit run.
Genuine idle placeholder (uncorroborated-but-blank-backed) still reads empty; genuine typed text still reads pending ✅ pass live Pre-existing assertions in the same test function ('opencode idle on tmux', 'opencode 1.18.30 completed-turn idle hint on tmux', 'opencode 1.18.30 completed-turn typed composer on tmux') all passed in…
Selected-content extraction preserves placeholder-prefixed user text instead of dropping it as furniture ✅ pass live ok - fm_composer_extract_selected_content: scopes user content and excludes furniture in target-commit run includes the new assertion that 'Ask anything... please reply' extracts verbatim rather tha…
PR opened with exact 'Closes #4477' linkage ⏸️ untested no Out of scope for this test phase per the gate-step phase boundary: PR creation/push is owned exclusively by the outer executor's other phase(s), not by this assigned test phase.

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

⚠️ **Review** - 1 info
  • ℹ️ bin/fm-composer-lib.sh:1077 - furniture_re="^(${idle_re})$" is built identically in two places (_fm_composer_classify_leftbar and fm_composer_extract_selected_content). Could be a shared one-line helper, purely mechanical dedup.
✅ **Test** - passed

✅ No issues found.

  • Live validation: ✅ go - 5 of 6 scenarios driven live against the product
Scenario Result Live Evidence
Placeholder-prefixed real draft is no longer swallowed as empty ✅ pass live bash tests/fm-composer-lib.test.sh at target commit dd91570: ok - matrix: opencode's left-bar composer reads empty everywhere and scans the full active run (includes the 'opencode 1.18.30 placeho…
Regression reproduction: same scenario misclassified as empty on pre-fix code ✅ pass live Swapped bin/fm-composer-lib.sh to the base commit (a6618dd) version in place while keeping the fixed test file, reran suite: `not ok - opencode 1.18.30 placeholder-prefixed draft on tmux: expected pe…
Furniture-only single row (no corroboration) now reads unknown, not empty ✅ pass live Same test function assertion 'opencode furniture-only left-bar lacks empty proof' expects unknown; part of the passing ok - matrix: opencode's left-bar composer... line in the target-commit run.
Genuine idle placeholder (uncorroborated-but-blank-backed) still reads empty; genuine typed text still reads pending ✅ pass live Pre-existing assertions in the same test function ('opencode idle on tmux', 'opencode 1.18.30 completed-turn idle hint on tmux', 'opencode 1.18.30 completed-turn typed composer on tmux') all passed in…
Selected-content extraction preserves placeholder-prefixed user text instead of dropping it as furniture ✅ pass live ok - fm_composer_extract_selected_content: scopes user content and excludes furniture in target-commit run includes the new assertion that 'Ask anything... please reply' extracts verbatim rather tha…
PR opened with exact 'Closes #4477' linkage ⏸️ untested no Out of scope for this test phase per the gate-step phase boundary: PR creation/push is owned exclusively by the outer executor's other phase(s), not by this assigned test phase.
  • bash tests/fm-composer-lib.test.sh (target commit dd915706, bin/fm-composer-lib.sh as shipped) — 34/34 ok, exit 0
  • bash tests/fm-composer-lib.test.sh (base commit a6618ddc bin/fm-composer-lib.sh swapped in, fixed test file retained) — reproduces the reported defect: 'expected pending, got empty' for the placeholder-prefixed draft, exit 1
  • bash tests/fm-composer-lib.test.sh (restored target file) — re-verified clean pass, worktree confirmed clean via git status --short
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

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.

OpenCode/Grok/Kimi left-bar composer classifier swallows a real draft beginning with a placeholder phrase as furniture, misreading empty

1 participant