# Row 168: the ledger counts only stack issue numbers Sage, 2026-10-19. Brief: `docs/plans/2026-10-19_ledger-stack-refs.md` at blob 52ac1975 (amended in 03586947a before the build). Issue #1665, Vikunja P19 372. Reviewer: Dewey. Base e2ad3aa10. Candidate f3a966ea4, one commit, built in the detached worktree `/mnt/storage/scratch/sage-r168`. The commit is in the canonical object store, so `git show f3a966ea4` works from the canonical checkout. `candidate.diff` is that output. `candidate-manifest.sha256` lists the four changed paths. ## What changed - `issueNumbers` (`ledger.mjs`) skips a `#N` when the word right before it is `Vikunja`, `P19`, `SetSpark` or `Launchpad`, any case, one space between. It's a lookbehind in the existing regex, so all three callers (commit subjects, pi sessions, T3) get it. - `stackRefs(commits, sessions, first = FIRST_ISSUE)` (`ledger.mjs`) drops numbers below `first` from each commit's issues and from the session mentions. A commit left with none drops out, as an untagged commit does. `FIRST_ISSUE` is 1495 and its comment cites the conversion issue. - `cli.mjs` calls `stackRefs` once, between `mergeSources` and `summarize`. The new option `--first-issue N` takes a positive integer and refuses anything else with `--first-issue requires a positive integer`. Without it the floor is 1495. Gitea's closed issues aren't filtered, so a close-only row below the floor still shows, with no seats. - README: the "no attempt to remap" sentence in Counting rules is replaced with what the ledger counts, and the examples list `--first-issue 1`. ## Why the floor is an option and not inside `issueNumbers` The first brief put the floor in `issueNumbers`. About fifteen CLI tests build their repo with `#1`, `#2` and `#3`, so that would have meant renumbering every fixture. The fixture `run` helper now passes `--first-issue 1` by default, and a test that wants the real floor passes `{ floor: [] }`. Every existing test runs unchanged apart from that helper. ## Tests (`packages/ledger/tests/ledger.test.mjs`) | Test | Covers | |---|---| | tracker names skip their numbers; the floor drops the rest of the foreign refs | each brief form as an exact `issueNumbers` array, case and spacing, then `stackRefs` on commits and mentions at the default floor and at 1 | | the default floor counts only stack issues in the table, commit total and seats | CLI on the fixture repo with no `--first-issue`: table rows `[1, 0, []]`, `[1600, 1, [bob]]`, `[1601, 1, []]`, 2 commits; the same repo at `--first-issue 1` shows the bare `#222` again and 5 commits | | --first-issue refuses a missing, zero or non-integer value | missing, `0`, `1.5`, `abc`, `-3`, `--json` and an unsafe integer each exit 1 with the message; `7` runs | The existing `issueNumbers` test at the old :235 is untouched and passes. ## Mutants `/mnt/storage/scratch/sage-r168-out/mut.sh`, on `ledger.test.mjs`, file restored and compared after: - floor removed (`keep = () => true`): exit 1, 2 failing, both new tests. - tracker-name skip removed (the lookbehind deleted): exit 1, 2 failing, both new tests. ## The 10-11 week through the candidate `preview.mjs` runs the candidate's `readCommits` and `stackRefs` on the canonical `refactor` log for 2026-10-11..10-17: 557 commits, 94 issues with commits, 513 follow-ups. That matches the read-only recompute behind 29089 (557 commits; 94 + 3 close-only = 97 rows; 513 / 97 = 5.3). The full CLI rerun and the post on #1508 happen after landing. ## Gate `/mnt/storage/scratch/sage-r168-out/gate.sh`, from the 2026-10-14 template, on f3a966ea4 with a clean tree: every package suite except queue, then every `scripts/test-*.sh`. GATE_PASSED. 25 steps, each rc=0. 2476 node tests (2320 package, 156 in test-queue) and 422 script selftests, 0 failed, summed with awk over `gate.out`. pkg-ledger is 89/89. Compose project `sage-r168`; its network was removed on exit and no container was left.