feat(ledger): Piece E, queue section in the weekly ledger (row 13, #1508)
The ledger prints a queue section above the weekly table. It checks four things: - open issues named by done rows; - owner registrations for active rows; - closed issues for done rows; - the age of required rows. The result is fail, incomplete or reduced pass. It uses its own Gitea budget of the open list plus at most 10 lookups. A full open page counts only while an issue in some row's closes has no known state (lead decision 40). T3 seats are exempt per run with --unsupported-runtime. The weekly routine is in packages/ledger/README.md. Built by Darkwing (build.patch ab1f12ca, manifest 0b20bbca). Filbert reviewed it: round 1 81f26f2e asked for changes (C1, ISO requiredSince never aged); round 2 ce8ce150 approved. Also carries Filbert's plan amendment for decision 40 (68a25ffe). Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
+114
-10
@@ -2,7 +2,9 @@
|
||||
|
||||
Read-only counts from local `refactor` commit subjects, one Gitea issue-list
|
||||
request through `scripts/gitea-api.sh`, repo seats' Pi session logs, and T3's
|
||||
thread messages in `~/.t3/userdata/state.sqlite`.
|
||||
thread messages in `~/.t3/userdata/state.sqlite`. Above the counts, a queue
|
||||
section checks `docs/plans/queue.json` against Gitea and the seat
|
||||
registrations (see "Queue section").
|
||||
No board changes, data-root writes, fleet reads, transcript output, or scheduler.
|
||||
|
||||
```sh
|
||||
@@ -11,6 +13,8 @@ node packages/ledger/src/cli.mjs --since 2026-09-06 --until 2026-09-12 --json
|
||||
node packages/ledger/src/cli.mjs --since 2026-09-06 --no-issues
|
||||
node packages/ledger/src/cli.mjs --since 2026-09-06 --no-t3
|
||||
node packages/ledger/src/cli.mjs --since 2026-09-06 --t3-db /tmp/fixture.sqlite
|
||||
node packages/ledger/src/cli.mjs --since 2026-09-06 --no-queue
|
||||
node packages/ledger/src/cli.mjs --since 2026-09-06 --unsupported-runtime dewey
|
||||
node --test packages/ledger/tests/
|
||||
```
|
||||
|
||||
@@ -125,27 +129,127 @@ directory means no Pi seats ran here; a missing T3 database means the path or
|
||||
T3 changed, so it refuses instead of counting zero. Error messages name ids
|
||||
and paths, never message text.
|
||||
|
||||
## One Gitea call and missing evidence
|
||||
## Queue section
|
||||
|
||||
The client requests issues updated since the start date, all states, first page,
|
||||
limit 50. This includes issues closed in range, even if later updated. Gitea caps
|
||||
The rules come from plan 8.10 in
|
||||
`agents/filbert/work/queue-as-data-plan-2026-09-26.md` (Piece E, #1508). The
|
||||
section is on by default and prints above the weekly table; `--json` puts it
|
||||
under `queue`. `--no-queue` skips it and prints `Queue: not checked
|
||||
(--no-queue)`. The ledger reads `docs/plans/queue.json` through the queue's own
|
||||
validator before any Gitea call, so a missing, symlinked or hand-edited file
|
||||
exits 1 and costs no call. It writes nothing, takes no queue lock and never
|
||||
changes a row.
|
||||
|
||||
Four checks, each finding named by (check, row, issue):
|
||||
|
||||
- **Issues.** An issue is expected closed once every row whose `closes`
|
||||
includes it is done (J6). Then an open issue is `issue-open` on each of
|
||||
those rows. A row that names an issue in `issues` but not in `closes` is
|
||||
never checked against it, so rows 9 to 12 can be done while #1508 is open.
|
||||
A closed issue with a row that closes it still pending is printed as a
|
||||
`disposition` for the lead. It is not a violation.
|
||||
- **Owners.** Each owner of an `in-progress` or `in-review` row gets one
|
||||
liveness class from its `repo` registration in `<dataRoot>/seats`:
|
||||
- `exempt`: declared on this run with `--unsupported-runtime SEAT`.
|
||||
- `missing`: no registration, or one written for another checkout.
|
||||
- `invalid`: the registration fails validation, or the config that names
|
||||
the data root can't be read. A malformed or absent pid fails validation,
|
||||
so it lands here, not in `pid-unknown`.
|
||||
- `pid-unknown`: a valid registration with a null pid.
|
||||
- `pid-gone`: the recorded pid is not running.
|
||||
- `pid-present`: the pid is running. A registration holds no process-start
|
||||
identity and a reused pid looks the same, so this reads "pid present
|
||||
(identity not verified)".
|
||||
The coverage line counts them: `liveness: N pid-present (unverified), N
|
||||
exempt, N pid-unknown, N missing, N invalid, N pid-gone`.
|
||||
- **Age.** A required row that is not done and whose `requiredSince` is more
|
||||
than 14 whole days before the run is listed by name. `requiredSince` is a
|
||||
date at genesis and an ISO time once `set required` or `add --required`
|
||||
writes it; both count from 00:00Z of their UTC day. A value that doesn't
|
||||
parse as a date is an `age-invalid` violation. A legacy row with
|
||||
`requiredSince: "unknown"` was required no later than genesis, so once
|
||||
genesis is more than 14 days old it is listed as `age ≥ N days (legacy lower
|
||||
bound)`. Before that its age is undecided. Age runs to the time of the run,
|
||||
not to `--until`.
|
||||
- **Protected changes.** Every log entry dated inside the report range that
|
||||
changes a required or parked row is listed with its revision, verb, claimed
|
||||
actor and rows. The queue trusts `--by` (its README, "Trust boundary"), so
|
||||
this list is how a wrong claim gets seen. It is not a check and never
|
||||
changes the result. Jason confirms the actors weekly.
|
||||
|
||||
Every run ends with `queue: N violations; result R`, where R is one of three:
|
||||
|
||||
- `fail`: any violation. That is an open issue, a `missing`, `invalid` or
|
||||
`pid-gone` owner, or an age.
|
||||
- `incomplete`: no violation, but something undecided. That is an issue
|
||||
whose state is unknown, a full open-issue page with some issue left
|
||||
unknown, issue checks not run, a
|
||||
`pid-unknown` owner, or a legacy age before genesis is 14 days old.
|
||||
- `reduced pass`: nothing known and nothing undecided. There is no full pass,
|
||||
because no owner's process identity is ever verified.
|
||||
|
||||
The exit code stays 0 whenever a report was computed; the result is in the
|
||||
text and the JSON.
|
||||
|
||||
### Queue issue calls
|
||||
|
||||
The metric call can't answer "is this issue closed", because an issue nobody
|
||||
touched this week isn't in it. So the queue checks have their own budget, per
|
||||
plan 8.10:
|
||||
|
||||
| Calls | Purpose |
|
||||
|---|---|
|
||||
| 1 | `state=open`, issues only, limit 50, one page. A full page may be short. Issues missing from it are looked up, so it makes the run `incomplete` only while some issue a row closes has no known state (lead decision 40). |
|
||||
| up to 10 | `GET issues/N` for each issue in some row's `closes` that is neither on the open list nor closed on the metric page. Beyond 10, the issue's state is unknown, "over the lookup budget". |
|
||||
|
||||
With the metric call that is at most 12 calls. `--no-issues` makes none and
|
||||
prints `queue issue checks: not run`. Closed needs positive evidence: an
|
||||
entry on the metric page with state `closed` and a `closed_at`, or a lookup
|
||||
returning a closed issue that isn't a pull request. A failed lookup, a 404, a
|
||||
pull request or a mismatched number leaves the issue unknown. A failed or
|
||||
malformed open-list call exits 2, like the metric call. Each queue call runs
|
||||
under `timeout -s KILL 60`, which kills the helper and its curl together.
|
||||
|
||||
### Weekly routine
|
||||
|
||||
Run the ledger each Monday for the week that ended on Saturday, Sunday
|
||||
through Saturday as row 7 counts it, with the queue section on and no
|
||||
`--no-issues`:
|
||||
|
||||
```sh
|
||||
node packages/ledger/src/cli.mjs --since 2026-09-20 --until 2026-09-26
|
||||
```
|
||||
|
||||
Post the dated run on #1508 with its coverage line and result. Any seat
|
||||
whose runtime writes no registration (T3 seats today) is passed with
|
||||
`--unsupported-runtime SEAT`, which the output prints. A violation is
|
||||
remediated when a second dated run on the same UTC day no longer reports its
|
||||
(check, row, issue), and both runs are posted on #1508. A row edit alone is
|
||||
not remediation, and a `note` can't clear an owner finding, because that
|
||||
check reads registrations. Row 13's gate is one Monday run with zero
|
||||
violations, or every violation remediated that day.
|
||||
|
||||
## Gitea calls and missing evidence
|
||||
|
||||
The metric client requests issues updated since the start date, all states,
|
||||
first page, limit 50. This includes issues closed in range, even if later updated. Gitea caps
|
||||
responses at 50; a full page fails rather than silently reporting partial totals.
|
||||
Use a narrower range or `--no-issues`, not hidden pagination. A commit-linked
|
||||
issue not returned by the updated-since query still has a row, with unknown
|
||||
metadata. This is the cost of the brief's one-call boundary.
|
||||
|
||||
Exit 0 means a report was computed. Exit 1 means bad arguments or unreadable git,
|
||||
session or T3 evidence. Malformed JSONL, including a partially written last line,
|
||||
Exit 0 means a report was computed. Exit 1 means bad arguments, a queue.json
|
||||
the validator refuses, or unreadable git, session or T3 evidence. Malformed JSONL, including a partially written last line,
|
||||
refuses the report; rerun after the seat finishes writing. Exit 2 means issue
|
||||
credentials, API, payload, or completeness failure. The CLI never prints API
|
||||
error bodies or reads authentication files itself. `--no-issues` makes no API
|
||||
call, keeps commit-derived rows, and shows unknown issue metadata, closed counts,
|
||||
error bodies or reads authentication files itself. The queue's open-list call
|
||||
fails with exit 2 the same way. `--no-issues` makes no API call, keeps commit-derived rows, and shows unknown issue metadata, closed counts,
|
||||
median duration, and human-per-closed ratio. It cannot invent close-only rows.
|
||||
|
||||
For fixtures, a fake `gitea-api.sh` can be placed first on PATH. Otherwise the
|
||||
repository scripts directory is appended to PATH for the issue request.
|
||||
Tests use only temporary repositories, logs, T3 databases and fake API tools,
|
||||
with no real credentials or network. Every CLI run in the tests sets `HOME` to
|
||||
Tests use only temporary repositories, logs, T3 databases, queue files, seat
|
||||
registrations, configs and fake API tools, with no real credentials or network. Every CLI run in the tests sets `HOME` to
|
||||
a temporary directory, so no test opens the real `~/.t3`. The helper regression stubs Node before any credential
|
||||
read and checks successful GET, successful POST, and failed HTTP status.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user