From 713f27d1d2fdee0f2b2dd76283693ac33e8c41a8 Mon Sep 17 00:00:00 2001 From: dnth Date: Sat, 5 Sep 2026 01:40:46 +0800 Subject: [PATCH 1/2] fix(decisions): close keyed answers at answer time through one intake Port upstream kunchenguid/firstmate #2490 (keyed-answer path), adapted to this fork, together with the two smaller upstream pieces it depends on for the incident it is meant to fix: the #2202 colon-first decision-key parser and the unrouted-close mechanics from #2330 that `answer` shares. On 2026-08-30 a worker wrote `needs-decision: [key=X] ...` with the tag after the verb colon. The status fold collapsed that stated key into the shared `default` bucket, so `fm-send --resolve-key X` was refused three times while the captain's answer sat on disk. bin/fm-classify-lib.sh now honors a complete `[key=]` token at the head of the note as an equivalent position to the documented before-colon one, strips the consumed token from the note so both positions fold to byte-identical records, keeps a mid-note mention as prose, rejects a malformed stated key instead of rewriting it to `default`, and bumps the persisted fold version so stale cursors are rebuilt from byte 0. bin/fm-decision-hold.sh owns "a keyed answer closes its matching hold" as one channel-agnostic capability: `answer` closes a single actively held hold that routes no work through a shared unrouted close that keeps every guard (captain decision file, active-hold requirement, digest-based retry identity, refusal while routed work is still blocked); `answers` is the stdin intake that maps `\t\t