fix(scripts): handle duplicate ARCHON_STATE_JSON_BEGIN blocks in persist#1676
fix(scripts): handle duplicate ARCHON_STATE_JSON_BEGIN blocks in persist#1676kagura-agent wants to merge 1 commit into
Conversation
…ist (coleam00#1674) When the synthesize node emits a truncated state block followed by a complete one (e.g. after a mid-emission restart), the persist script paired the first BEGIN with the first END — slicing across both blocks and producing invalid JSON. Fix: use lastIndexOf(BEGIN) to find the last (complete) block, then search for END only after that position. Brief text uses the first BEGIN as its boundary so preamble prose (including truncated earlier emission) is captured and cleaned by the existing heading filter. Adds integration tests covering single-block, duplicate-block (coleam00#1674 repro), JSON-wrapper fallback, and invalid-input paths.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughThis PR fixes a robustness issue in the ChangesDelimiter Extraction and Persistence Robustness
Possibly related PRs
Poem
Estimated code review effort🎯 2 (Simple) | ⏱️ ~15 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…rkers (#1695) * Fix: extract ARCHON_STATE_JSON markers as standalone lines (#1674) The persist script extracted Claude's state-JSON block by substring-matching the BEGIN/END markers, which gave a false match whenever the marker string appeared inside the brief's prose or inside a JSON string value (e.g. a PR title narrating this very bug). PR #1676's switch to lastIndexOf made the self-referential case worse, since the last substring occurrence may now sit inside a JSON value. Match the markers only when they occupy an entire line (line-anchored ^...$ regex with the m flag) and pick the last END plus the last BEGIN before it, so duplicate-emission and substring-in-content both resolve correctly. Changes: - Replace indexOf/lastIndexOf substring matching in Tier 1 with line-anchored matchAll regex over BEGIN/END markers - Add tests for marker substring in brief prose, marker substring inside state JSON value, and combined duplicate-BEGIN + marker-in-prose case - Keep PR #1676's existing test cases (single block, duplicate BEGINs, JSON-wrapper fallback, no-valid-format exit 1) Fixes #1674 * fix(scripts): address review findings in maintainer-standup-persist - Add WARN diagnostic when all BEGIN markers appear after last END (previously silent fallthrough produced misleading terminal error) - Include 200-char candidate preview in JSON parse error message (error was unactionable in headless workflow without raw output) - Wrap mkdirSync/writeFileSync in try-catch with structured PERSIST FAILED message instead of raw Bun stack trace on disk errors - Fix brief assignment comment to explain WHY [0] vs last-pair asymmetry - Add test: BEGIN present but END absent (truncated output) exits 1 - Add test: prose preamble before first heading is stripped from brief - Add clarifying comment to Test 6 noting it is defence-in-depth, not a case that failed under the old indexOf approach * simplify: collapse multi-line comment blocks to single lines
|
@kagura-agent — closing this in favor of #1695, which has just merged with a more complete fix. Genuine credit owed: #1695 builds directly on your test design. Your four tests (`single BEGIN/END block succeeds`, `duplicate BEGIN blocks — takes last complete block (fixes #1674)`, `JSON-wrapper fallback works`, `no valid format exits 1`) are preserved byte-for-byte in #1695's test file — the scaffolding (`runPersist` helper, temp-dir-per-test isolation, exit-code assertions) is yours. #1695 added five more tests on top to cover the secondary bug class (marker substring inside brief prose / JSON string values) that surfaced after your fix attempt landed. Why #1695 over this PR: your approach used `lastIndexOf` for substring matching, which fixes the duplicate-emission case but doesn't handle markers appearing as substrings inside content (e.g. a PR title containing `ARCHON_STATE_JSON_BEGIN`). #1695 switches to line-anchored regex (`^ARCHON_STATE_JSON_BEGIN$/gm`), which solves both classes at once. This wasn't wasted work — your fast turnaround on issue #1674 (3 hours from filing to PR) set the test framework that #1695 extended. Thank you. |
…rkers (coleam00#1695) * Fix: extract ARCHON_STATE_JSON markers as standalone lines (coleam00#1674) The persist script extracted Claude's state-JSON block by substring-matching the BEGIN/END markers, which gave a false match whenever the marker string appeared inside the brief's prose or inside a JSON string value (e.g. a PR title narrating this very bug). PR coleam00#1676's switch to lastIndexOf made the self-referential case worse, since the last substring occurrence may now sit inside a JSON value. Match the markers only when they occupy an entire line (line-anchored ^...$ regex with the m flag) and pick the last END plus the last BEGIN before it, so duplicate-emission and substring-in-content both resolve correctly. Changes: - Replace indexOf/lastIndexOf substring matching in Tier 1 with line-anchored matchAll regex over BEGIN/END markers - Add tests for marker substring in brief prose, marker substring inside state JSON value, and combined duplicate-BEGIN + marker-in-prose case - Keep PR coleam00#1676's existing test cases (single block, duplicate BEGINs, JSON-wrapper fallback, no-valid-format exit 1) Fixes coleam00#1674 * fix(scripts): address review findings in maintainer-standup-persist - Add WARN diagnostic when all BEGIN markers appear after last END (previously silent fallthrough produced misleading terminal error) - Include 200-char candidate preview in JSON parse error message (error was unactionable in headless workflow without raw output) - Wrap mkdirSync/writeFileSync in try-catch with structured PERSIST FAILED message instead of raw Bun stack trace on disk errors - Fix brief assignment comment to explain WHY [0] vs last-pair asymmetry - Add test: BEGIN present but END absent (truncated output) exits 1 - Add test: prose preamble before first heading is stripped from brief - Add clarifying comment to Test 6 noting it is defence-in-depth, not a case that failed under the old indexOf approach * simplify: collapse multi-line comment blocks to single lines
Summary
maintainer-standup-persist.tsfails when the synthesize node emits duplicateARCHON_STATE_JSON_BEGINblocks (e.g. a truncated emission followed by a complete one after mid-output restart).indexOf(BEGIN)pairs the first (partial) BEGIN with the first END, slicing across both blocks →JSON.parsefails → exit 1, no brief/state written.lastIndexOf(BEGIN)to find the last (complete) block, then searches forENDonly after that position. Brief boundary usesindexOf(BEGIN)(first occurrence) so preamble including truncated content is captured and cleaned by the existing heading filter.UX Journey
Before
After
Architecture Diagram
Before & After
Only the persist script is modified. No new modules, no changed connections.
Connection inventory:
Label Snapshot
.archon/scripts/Change Metadata
Linked Issue
Closes #1674
Validation Evidence
Lint-staged (eslint + prettier) passed on commit.
Security Impact
None — no auth, no network, no user input beyond stdin from a trusted workflow node.
Compatibility/Migration
Fully backward compatible. Single-block inputs behave identically (
lastIndexOf==indexOfwhen there is only one occurrence).Human Verification
indexOf→lastIndexOflogic manually with duplicate-block inputRisks and Mitigations
indexOf(END, beginIdx)finds first END after last BEGIN — correct pairinglines.findIndex(l => l.startsWith("# "))) strips preamble proseSide Effects/Blast Radius
None. The persist script is standalone — no imports from packages/, no runtime callers beyond the bash node in the standup workflow.
Rollback Plan
Revert this commit. Previous behavior (crash on duplicate blocks) is restored.
Summary by CodeRabbit
Tests
Bug Fixes