Files
stack/agents/darkwing/work/ledger-t3-source/followup.md
T
jason.woltjeandClaude Opus 5.5 3a209eeafe fix(ledger): Gate F follow-up, Filbert's notes 1 to 3 (#1506)
Darkwing's follow-up to the T3 thread source: manifest 382f5bb0 pins
t3.mjs, ledger.test.mjs and README.md. Filbert approved it (review
6fd693b6). Ledger 51/51; the eight suites pass on the index.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-26 16:57:51 -05:00

3.6 KiB

Gate F follow-up: Filbert's notes 1 to 3 (#1506), candidate for review

Darkwing, 2026-09-26. Filbert's build review (agents/filbert/work/ledger-t3-build-review-2026-09-26.md, e47ec6da) left four nonblocking notes on Gate F (136958c9). Sage asked for 1 to 3 as one small change that Filbert reviews and Sage commits. Note 4, snapshot isolation, went to DEFERRED (a68dc174). Base is HEAD a4d38a3d, which changes nothing under packages/ledger since 136958c9. Nothing is committed or pushed.

followup-manifest.sha256 pins the three files. followup.patch is the diff against a4d38a3d.

Changes

  1. U+2029. The splitter test now writes a Pi entry holding a raw U+2028 and a raw U+2029, with CRLF endings, and asserts that the file contains both. The README line names both characters. ledger.mjs is unchanged, because the splitter already ends lines at \n only.
  2. Diagnostic. Three new tests:
    • A human message with no thread.message-sent event gives humanWithoutEvent: 1.
    • A thread.message-sent event whose payload doesn't parse makes both diagnostic fields unknown and leaves seats unchanged.
    • The same for an event whose messageId isn't a string. Filbert didn't list this one, but it's the third return null in origins() and had no test either.
  3. Rethrow. readT3's catch now rethrows anything that is not a SourceError and carries no numeric errcode. The CLI prints such an error as Ledger failed: cannot read source evidence, exit 1. That's the CLI's existing message for a non-source error, and it no longer points at SQLite or --no-t3. With only numeric errcodes left, the message's ?? 'error' fallback could no longer fire, so I removed it. The new test calls readT3 in process with an explicit fixture path and a null range, so inRange throws a TypeError inside the read transaction. It asserts the TypeError comes out. It never touches the real ~/.t3, and the fixture comment says so.

Evidence

  • Ledger tests: 51/51, the Gate F 47 plus 4 new.

  • Mutations on a scratch copy of the package. The three gitea-helper tests fail in every scratch copy, as before, so the counts leave them out:

    Mutation Result
    humanWithoutEvent hardcoded to 0 1 fails (no-event test)
    unparseable event skipped (continue) 1 fails (unparseable test)
    non-string messageId skipped 1 fails (messageId test)
    rethrow removed (Gate F catch) 1 fails (rethrow test)
    splitter also splits at U+2028 1 fails (splitter test)
    splitter also splits at U+2029 1 fails (splitter test)

    My first try at the last two put a raw U+2028 or U+2029 in the regex source. That ends a JS regex literal, so the whole test file failed to load, which doesn't count as a kill. I reran with the escape written out literally, and the rows above come from that rerun.

  • Eight suites on a local clone of a4d38a3d with the three files: config 24, task 90, foundation 43, conductor 17, release 14, auth 15, discord 63, extension-package 18. I ran them twice, and the second run was on the final files after the errcode edit.

  • Union on the same clone. Control-board, webui, seat, mosaic, ledger and discord, plus conversation, which CHAT-02 committed: 474/474 twice before the errcode edit and once after. No ledger-* temp directories remained.

  • Live read, --since 2026-09-01 --until 2026-09-26 --no-issues --json, at 2026-09-26T21:47Z: exit 0, no header conflict, diagnostic {humanSentThroughApi: 15, humanWithoutEvent: 0}, two imported threads excluded. The Gate F build read 14; messages have been sent since then.