Skip to content

fix(bin): recover corr-tagged decision verbs so open keys resolve - #6

Merged
jokim1 merged 1 commit into
lila-mainfrom
fm/fm-send-resolve-key-fold-regression
Aug 18, 2026
Merged

fix(bin): recover corr-tagged decision verbs so open keys resolve#6
jokim1 merged 1 commit into
lila-mainfrom
fm/fm-send-resolve-key-fold-regression

Conversation

@jokim1

@jokim1 jokim1 commented Aug 17, 2026

Copy link
Copy Markdown
Owner

Intent

Fix the adopted-stack regression where bin/fm-send.sh --resolve-key refuses a plainly OPEN decision key.

Defect: a greppable needs-decision/blocked key (reproduced as project-registration-path as the last line of a status file) was OPEN, yet fm-send --resolve-key refused it. Refusal persisted after deleting the task's open-decisions-cursor to force a full re-fold, so the bug is in fold/verb parsing, not stale cursor state. Introduced or exposed by the 2026-08-14 overlay adoption (fm-send / upstream-kunchenguid#2041 revision). Operational impact: firstmate cannot close open decision keys at answer time; every decision reply currently uses the workaround of plain steer plus the worker self-appending its resolved line.

Root cause (implemented fix already committed at 14e7db6): status_line_verb only peeled [key=...], so complete non-key tags such as secondmate [corr=hex] glued onto the verb and the open-decisions fold missed greppable needs-decision/blocked lines. The fix strips a before-colon suffix only when it is a whitespace-separated run of complete [name=value] tags (body rejects space/[, locale-independent ASCII slug names), falls back to the historical [key= peel otherwise, and bumps the open-decisions fold version to 4 so cursors re-fold under the corrected verb recovery.

Deliberately OUT of scope: the key-position grammar ([key=x] at line END is prose, opening the DEFAULT slot) is documented, understood behavior — do NOT change it. Minimal fix only for the refusal-of-a-plainly-open-key defect.

Constraints already accepted: PR target = origin fork (jokim1/firstmate) ONLY; never push/PR/comment against upstream kunchenguid/firstmate. Regression tests colocated under tests/ covering corr-tagged open/close, shape I, key-led preserve, malformed-body and punctuated/unicode name refusal (including stock bash 3.2 + en_US.UTF-8), shared classifiers, cursor migration, and end-to-end fm-send false-send guards. Fork-queue adversarial plan panel already passed 3/3 on the v6 plan; implement/verify that committed fix, do not re-open the design. If CI is red only on pre-existing main failures unrelated to this change, report that and hold rather than chasing them.

What Changed

  • Rewrote status_line_verb in bin/fm-classify-lib.sh to strip a before-colon suffix only when it is a whitespace-separated run of complete [name=value] tags (fail-closed on whitespace/[ in a token body, locale-independent ASCII slug names), falling back to the historical [key= peel otherwise, via a new _fm_is_wholly_complete_metadata_tags helper. This stops complete non-key tags such as secondmate [corr=hex] from gluing onto the leading verb, so the open-decisions fold once again matches greppable needs-decision/blocked lines and fm-send --resolve-key no longer refuses a plainly OPEN key.
  • Bumped FM_OPEN_DECISIONS_FOLD_VERSION from 3 to 4 so existing cursors re-fold under the corrected verb recovery.
  • Added regression tests covering corr-tagged open/close, key-led preserve, malformed-body and punctuated/unicode name refusal, cursor migration, and end-to-end fm-send false-send guards (tests/fm-classify-decision-key.test.sh, tests/fm-send-resolve-key.test.sh, tests/fm-wake-drain-open-decisions-cursor.test.sh).

Risk Assessment

✅ Low: A well-bounded, thoroughly-tested classifier fix that structurally preserves the "no false opens" guarantee, correctly migrates cursors via the fold-version bump, preserves the documented key-position grammar, and matches the authoritative intent exactly.

Testing

Ran the three shipped test files (classifier, fm-send --resolve-key e2e, cursor migration) on the target commit — all pass. Reproduced the regression two ways: the real open-decisions fold shows the corr-tagged key invisible on base but OPEN on target, and the shipped fm-send e2e test fails its "corr-tagged decision should list as open" precondition (the actual --resolve-key refusal) when run against the base classifier, while passing all 15 checks on target. Verified fail-closed handling of unicode/whitespace/malformed tag names and the unchanged out-of-scope trailing-[key=x] grammar under stock bash 3.2 + en_US.UTF-8. No visual artifact applies (Bash CLI/status-fold change, no rendered UI); a CLI transcript is the product-level evidence. Base worktree and temp files removed; working tree clean.

Evidence: Regression + fix CLI transcript (fold, fm-send e2e, grammar guardrails)
fm-send --resolve-key: corr-tagged OPEN decision refusal regression
====================================================================
Defect: bin/fm-send.sh --resolve-key <key> refused a plainly OPEN decision key
because status_line_verb glued a complete non-key tag (e.g. [corr=hex]) onto the
verb, so the open-decisions fold never recognized the needs-decision/blocked line.

Reproduction status file line:
  needs-decision [corr=9f3a1c] [key=project-registration-path]: which path do we register under?

REAL OPEN-DECISIONS FOLD (status_open_decisions), base 3188946 vs target 25ee5d6
-------------------------------------------------------------------------------
BASE  (3188946): verb recovered = 'needs-decision [corr=9f3a1c]'
                 OPEN DECISIONS = <empty>            <-- key invisible => --resolve-key REFUSES
TARGET(25ee5d6): verb recovered = 'needs-decision'
                 OPEN DECISIONS = project-registration-path  needs-decision  which path do we register under?
                                                     <-- key OPEN => --resolve-key CLOSES

END-TO-END fm-send --resolve-key surface (shipped tests/fm-send-resolve-key.test.sh)
------------------------------------------------------------------------------------
With BASE classifier swapped in:
  not ok - precondition: corr-tagged decision should list as open      <-- refusal reproduced
With TARGET classifier (shipped): all 15 checks pass, including
  ok - fm-send --resolve-key: a corr-tagged open key is answerable end to end

FAIL-CLOSED / OUT-OF-SCOPE grammar (status_line_verb, bash 3.2 + en_US.UTF-8)
----------------------------------------------------------------------------
complete corr+key tags       needs-decision [corr=9f3a1c] [key=project-registration-path]: q?  -> verb=needs-decision   (stripped, folds)
unicode tag name (fail-closed)  needs-decision [café=1] [key=k]: q?    -> verb=needs-decision [café=1]  (inert, no phantom key)
whitespace tag body (fail-closed) needs-decision [a b=1] [key=k]: q?   -> verb=needs-decision [a b=1]   (inert)
unclosed bracket (historical peel) needs-decision [corr=9f3a1c [key=k]: q? -> verb=needs-decision [corr=9f3a1c
trailing [key=x] at line END (OUT OF SCOPE, unchanged)  resolved: went with option A [key=api-shape] -> verb=resolved
Evidence: Base-vs-target open-decisions fold on corr-tagged line
TARGET(25ee5d6): verb='needs-decision' OPEN DECISIONS => project-registration-path needs-decision which path do we register under?
BASE (3188946): verb='needs-decision [corr=9f3a1c]' OPEN DECISIONS => <empty> (key invisible -> --resolve-key refuses)
Evidence: fm-send e2e against base classifier (refusal reproduced)
swapped in BASE classifier; running shipped e2e test:
not ok - precondition: corr-tagged decision should list as open
(restored TARGET classifier; worktree clean)

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

✅ **Review** - passed

✅ No issues found.

✅ **Test** - passed

✅ No issues found.

  • fm-classify-decision-key.test.sh
  • fm-send-resolve-key.test.sh
  • fm-wake-drain-open-decisions-cursor.test.sh
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

status_line_verb only peeled [key=...], so complete non-key tags such as
secondmate [corr=hex] glued onto the verb and the open-decisions fold
missed greppable needs-decision/blocked lines - fm-send --resolve-key then
refused a plainly open key. Strip a before-colon suffix only when it is a
whitespace-separated run of complete [name=value] tags (body rejects
space/[, locale-independent ASCII slug names), fall back to the historical
[key= peel otherwise, and bump the open-decisions fold version to 4.

Regression coverage: corr-tagged open/close, shape I, key-led preserve,
malformed-body and punctuated/unicode name refusal (including stock bash
3.2 + en_US.UTF-8), shared classifiers, cursor migration, and end-to-end
fm-send false-send guards.
@cursor

cursor Bot commented Aug 17, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@jokim1
jokim1 merged commit e653a9f into lila-main Aug 18, 2026
24 of 25 checks passed
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