feat(ledger): Gate F, the ledger's T3 thread source (#1506)

packages/ledger/src/t3.mjs reads ~/.t3/userdata/state.sqlite read-only,
in one transaction. It maps each thread to a seat by title and checks
self-addressed headers. Unmatched threads go in a t3:unmapped row. A
missing or locked database exits 1 and names --no-t3. Gate F is on by
default (lead decision 12). The 6a uppercase-class fix rides here.

Separate item: the Pi session reader splits lines only on \n, so a raw
U+2028 or U+2029 in a string no longer splits a record. Node 26.8.1's
readline split there, and the live ledger refused on HEAD.

Darkwing built to brief R3 (f3c05c1b); manifest ba73a163. Filbert
approved the build (e47ec6da) and the U+2028 fix as its own item; brief
review be1aa414. On an index export: the eight suites
24/90/43/17/14/15/63/18, ledger 47/47. Four nonblocking notes go to a
small follow-up.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
2026-09-26 16:39:56 -05:00
co-authored by Claude Opus 5.5
parent e58783d278
commit 136958c98b
11 changed files with 1764 additions and 31 deletions
+37
View File
@@ -3120,3 +3120,40 @@ names jason and carmen. Receipt (0600):
`restart-row25-approvers-20260926T213021Z.txt`. Jason reruns the approval
check. DEC-009 needs a `record_update` to names, or a new decision, and
then a new approval request.
## 2026-09-26: Gate F build, the ledger's T3 source (#1506, Darkwing, for Filbert's review)
Before: Table 2 read only `.pi/state/<seat>/sessions/*.jsonl`. Seats that run
in T3 never reach a Pi log, so their Human column showed "no source" as zero.
The class pattern in both preambles accepted lowercase only.
After (uncommitted candidate on 1c5f6bc3, per brief R3 f3c05c1b): new
`packages/ledger/src/t3.mjs` reads `~/.t3/userdata/state.sqlite` read-only in
one transaction. It maps threads to seats by title, cross-checks headers
addressed to their own thread, and adds a `t3:unmapped` row. It refuses on a
missing or unreadable database, symlinks, schema drift, no single project for
the root, bad rows or a header conflict. `--no-t3` and `--t3-db PATH` are new.
Classes now match in either case. Pins:
`agents/darkwing/work/ledger-t3-source/build-manifest.sha256`; record `build.md`
in the same directory.
Beyond the brief: the live read refused on HEAD too, at a Filbert Pi log line
holding a raw U+2028. Node 26.8.1's `readline` ends lines there. The Pi reader
now splits on `\n` only, with a test.
Evidence: no suite runs the ledger tests. `node --test
packages/ledger/tests/ledger.test.mjs` passes 44/44 (47/47 with the gitea
helper file). The eight suites passed on a clone of 1c5f6bc3 with the five
files (24/90/43/17/14/15/63/18); the first task run showed one failure I didn't
capture, and three reruns passed. Union 434/434 three times. Live read exit 0,
no conflict, diagnostic 14. Two mutations don't bite (`mode=ro` removed;
snapshot isolation untested), recorded in `build.md`. Not committed or pushed.
## 2026-09-26: Gate F build review (#1506, Filbert)
Filbert approved manifest ba73a163 and, as its own item, the Pi reader's
newline-only splitter. Review: `agents/filbert/work/ledger-t3-build-review-2026-09-26.md`
(e47ec6da). Correction to the entry above: line 611 holds both a U+2028 and a
U+2029, and `readline` splits at each. The splitter covers both. His four
nonblocking notes are listed in `agents/darkwing/work/ledger-t3-source/build.md`
for a follow-up after the commit.