fix(bin): fold OPEN DECISIONS in one awk pass for a full re-fold - #2836
fix(bin): fold OPEN DECISIONS in one awk pass for a full re-fold#2836armchairo wants to merge 1 commit into
Conversation
status_open_decisions and the cursor-invalidated full-refold branch of status_open_decisions_incremental (bin/fm-classify-lib.sh) rebuilt a task's open-decision set by looping _fm_decision_fold_line per line in bash: several subshells per line plus an O(open-count) drop rescan on every open/close. Incremental cursors (kunchenguid#1737) bound the steady-state cost to new appends, but any cursor miss, fold-version mismatch, or shrink still re-folds the whole file from byte 0 through that same bash loop. On a ~330KB status log this is minutes of CPU-bound shell, stalling every wake-handling turn (kunchenguid#2808). _fm_decision_fold_awk re-derives the exact same rule (both key positions, the drop rules, the reserved-key-prefix namespace check, and the "default" one-open-per-task key) as one awk pass. Both full folds now call it; the incremental steady-state branch keeps the bash loop, where per-call overhead already dwarfs a handful of new lines. tests/fm-classify-decision-fold-awk-equivalence.test.sh drives both engines over the same fixture logs, including a generated multi-KB one, and asserts byte-identical output. The existing tests/fm-classify-decision-key.test.sh and tests/fm-wake-drain-open-decisions(-cursor).test.sh suites now exercise the awk engine through status_open_decisions and status_open_decisions_incremental and still pass unchanged. Fixes kunchenguid#2808
Confidence Score: 5/5The PR appears safe to merge with no concrete changed-code failure identified. The new full-fold implementation matches the existing parsing, key validation, reserved-prefix handling, transition, and ordering behavior for supported configurations, while reachable incremental cursor states preserve correct byte-zero refolding. Reviews (1): Last reviewed commit: "fix(bin): fold OPEN DECISIONS in one awk..." | Re-trigger Greptile |
|
Speaking as Kun's firstmate: Scheduled 3:10pm PT 8/23 pass. VISION.md read in full from current main VISION (inspected Class: corrective (performance rewrite of existing fold semantics, not a default-behavior change of which decisions surface). Security: none. Diff reviewed in full before first-time-fork approval: only Overlap / HOLD: same-file overlap with open #2877 / #2867 / #2801 on CI / NM: HEAD Workflows: first-time fork, approved this pass after diff review. Run IDs: 32624507887 (CI, in_progress), 32624507860 (Require no-mistakes, approved). Land-eligible rec: NO (CI not green yet; no NM attestation; 12 behind; classify-lib overlap with #2877). Captain-flag NOW: no — waiting on CI and on the author for a no-mistakes pipeline that stamps THIS HEAD. Waiting on CI (just approved) and on the author for a HEAD-matching no-mistakes attestation. Not a captain-decision hold. |
Fixes #2808.
Problem
status_open_decisionsand the cursor-invalidated full-refold branch ofstatus_open_decisions_incremental(bin/fm-classify-lib.sh) rebuild a task's open-decision set by looping_fm_decision_fold_lineonce per status line in bash: several subshells per line (status_line_verb,_fm_decision_keyand its helpers,status_line_note) plus anO(open-count)_fm_decision_droprescan on every open/close.Incremental cursors (#1737) bound the steady-state cost to newly appended bytes, but any cursor miss, fold-version mismatch, or shrink still re-folds the whole file from byte 0 through that same bash loop, which is CPU-bound-shell-slow on a large status log.
Fix
_fm_decision_fold_awkre-derives the exact same fold rule as oneawkpass: both key positions ([key=x]before the colon or at the head of the note), the drop-then-append ordering, the reservedpending-reply-key-prefix namespace check, and thedefaultone-open-per-task key.status_open_decisionsand the full-refold branch ofstatus_open_decisions_incremental(identified by the chunk starting at byte 0) now call it instead of looping_fm_decision_fold_line. The incremental steady-state branch is unchanged and keeps the bash loop, where per-call overhead already dwarfs a handful of newly appended lines.#2801's wake-context-packet work is untouched; this PR is fold cost only.Equivalence
tests/fm-classify-decision-fold-awk-equivalence.test.shdrives both a bash reference fold (built from the still-live_fm_decision_fold_line) and the new awk engine over the same fixture logs - an empty file, blank/whitespace-only lines, no-colon legacy lines, multiple[key=...]tags on one line, a file with no trailing newline, and a generated ~20KB fixture exercising every decision-line shape - and asserts byte-identical output. The existingtests/fm-classify-decision-key.test.shandtests/fm-wake-drain-open-decisions(-cursor).test.shsuites now exercise the awk engine throughstatus_open_decisions/status_open_decisions_incrementaland pass unchanged.Benchmark
Generated a ~330KB fixture shaped like the reported scenario (mostly routine
working:lines, an occasionalneeds-decision/resolvedcycle, ~5,200 lines, 104 decisions still open at the end) and timedstatus_open_decisionsbefore and after this change, sourcing each version ofbin/fm-classify-lib.shstandalone:~1,000x faster on this fixture (24.7s -> 0.03s), same output.
Verification