Files
stack/agents/filbert/work/queue-67/build.md
T
jason.woltjeandClaude Opus 5.5 7d032da5b4 filbert: row 67 round 2 packet, rebase onto f38b7f46 (#1560)
Manifest 4387c8d5. Rebase only: same added and removed lines, three files
re-digested after rows 58, 60 and 59. Gate green, round 1 mutants all killed.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-11 20:53:36 -05:00

214 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Row 67 (#1560): decisions read follow-up, round 2
Filbert, 2026-10-12. Brief: `docs/plans/2026-10-11_decisions-read-follow-up.md`,
"Decisions read follow-up: seen-then-resolve, list-before-503 and full-row
tests" (blob 7674ff40, unchanged). Darkwing and Dewey review. Sage commits
after the gate. Nothing in the candidate is committed, staged or pushed.
Base f38b7f46, origin/refactor's tip when I rebased. `build.patch` applies
there with `git apply --index`, and `candidate-manifest.sha256` pins all 4
files after the patch. Round 1 was manifest `8959e615…7369` on 970ef729,
approved by Dewey (27452) and Darkwing (27627).
## Round 2: rebase only
Sage set the scope: a rebase onto the current tip, the merged hunks named
here, a fresh manifest, and a digest re-approval. Nothing new goes in, so the
round 1 description, mutants and questions below still apply. Dewey's N1 (an
assertion that test 4's new decisions are listed) is not folded in; it stays
a follow-up.
### What landed on the manifest paths
Since 970ef729, three rows changed 3 of the 4 files.
`packages/bus/tests/decisions.test.mjs` is untouched.
- Row 58 (aaf87213): the bus README, `broker.mjs` and webui `bus.test.mjs`.
- Row 60 (1771bf98): the bus README, `broker.mjs` and webui `bus.test.mjs`.
- Row 59 (a8512007): the bus README and `broker.mjs`.
### Digest check
Round 1's patch no longer applies plain (README line 205), as Darkwing found.
It applies to f38b7f46 with `git apply --index --3way` with no conflicts.
I compared the round 1 and round 2 patches:
- The added and removed lines are byte-identical (106 lines each).
- The hunk headers moved: README 205 to 235, `broker.mjs` 837 to 861, webui
`bus.test.mjs` 163 to 191. The `decisions.test.mjs` hunks are unchanged.
- One context line differs, below.
`decisions.test.mjs` keeps its digest (`9477cfa7…`). The other three have new
digests because their bases changed.
### Merged hunks
Line numbers are in the round 2 tree.
- `packages/bus/README.md`, lines 235–243: the "Every row is…" sentence is
rewritten as in round 1. In round 1 the hunk's last context line was the
`## Shared reads and adapter boundary` heading. Row 60 has since put its
`credentials` paragraph between the two, so that paragraph's first line
is the context now. The sentence and the paragraph share no lines.
- `packages/bus/src/broker.mjs`, lines 864–867: the comment above
`case 'decisions'` (line 868). Row 59's `agents` block ends above it
(line 852 on), and row 60's `case 'credentials'` follows it (line 889).
Neither touches the comment or the case.
- `packages/webui/tests/bus.test.mjs`, lines 194–198: the three no-bus
requests still follow the `/api/bus/agents` not-configured check, inside
"bus refusals map to statuses…". Row 58 and row 60's additions sit above.
### Gate (round 2)
Run in a worktree of f38b7f46 with the round 2 patch staged and
`node_modules` linked, in sequence, with `TMPDIR` in my scratch and
`DOCKER_HOST` pointed at a missing socket, 2026-10-12T01:47:57Z to 01:52:03Z.
- Packages: webui 62/0, bus 95/0, cli 114/0, control-board 124/0.
- All nine `scripts/test-*.sh` exit 0: auth 15, conductor 17, config 24,
discord 66, extension-package 18, foundation 44, queue 27, release 4,
task 26. `test-queue` skipped `verify` and `render --check`, because the
worktree isn't the queue's canonical root. `test-release` skipped its
Docker cases without a daemon.
- Afterwards `git status` showed only the four staged paths and the
`node_modules` link, and the tree checked 4/4 against the manifest.
### Mutants (round 2)
I reran round 1's nine mutants (`mut/run.mjs`) on the round 2 tree,
2026-10-12T01:52Z to 01:53Z. All nine are killed, each by the same test as in
round 1. The bus suite now has 95 tests and the webui file 9, so the counts
read 94/1, 92/3 for `view-blocking-raw` and 8/1 for `web-503-first`, where
round 1 read 80/1, 78/3 and 7/1. One edit changed: row 59 added a second
`blocking: !!d.blocking,` in the `agents` read (`broker.mjs` line 930), and
the runner refuses a target that isn't unique. So `view-blocking-raw` ran
from a copy of the runner that anchors on its whole line (line 297, inside
the decisions view), and the edit is the same. After each run `git diff` was
unchanged, and the tree checked 4/4 against the manifest afterwards.
---
The round 1 packet follows unchanged: the description, files, round 1
mutants, round 1 gate and questions. Its base and line numbers are round 1's.
# Row 67 (#1560): decisions read follow-up, round 1
Filbert, 2026-10-11. Brief: `docs/plans/2026-10-11_decisions-read-follow-up.md`,
"Decisions read follow-up: seen-then-resolve, list-before-503 and full-row
tests" (blob 7674ff40). Darkwing and Dewey review. Sage commits after the
gate; nothing is committed, staged or pushed yet.
Base 970ef729. `build.patch` applies there with `git apply --index`;
`candidate-manifest.sha256` pins all 4 files after the patch.
No behaviour changes. No new test found a defect; the only non-test edits
are the broker comment and the README sentence that repeats it.
## What ships
- **Seen, then closed** (`decisions.test.mjs`, new test after `recent`). The
human marks the human-routed decision seen and resolves it; `cto` does the
same for its decision; `pm` marks its decision seen and the raiser
withdraws it. For each, the store holds exactly `seen` then the closing
op, and the `recent` row's `closed` has that op, the closing event's `seq`
and its `by`. The test also pins the `recent` order by close. Mutant
`recent-closed-first-event` fails it.
- **List before 503** (`webui/tests/bus.test.mjs`, the no-bus server in
"bus refusals map to statuses…"). With no bus configured,
`/api/bus/decisions?list=bad` answers 400 `invalid-request`, and
`?list=roles` answers 503 `not-configured`, so a good list still reaches
the bus check. Trail checks `subject` the same way, so the same loop pins
`/api/bus/trail?subject=%3C` at 400. Mutant `web-503-first` fails it.
- **The whole row** (test 4, "every row is what trail already gives…"). For
every `roles` and `recent` row, for human and reader sessions, the row
minus `authorization` and `closed` deep-equals trail's `decisions` row for
that id minus `table`, with `blocking` as a boolean. `authorization`
deep-equals `{action, target, approvalChoice}` from trail's one
`action.allowed` `decision.raise` event for the id. `closed` is present on
`recent` rows only, and equals trail's `decision_events` row as before.
The seed left `project`, `requirement_ref` and `supersedes` null and every
approval choice at the default `yes`, so a test of them would pass on a
mutant that nulled them. Test 4 now raises two more decisions: one with a
project and a requirement ref, then one that supersedes it, blocking, on a
task, with approval choice `no`. The first closes as `withdrawn` by the
supersede, so it lands in `recent`; the second is in `roles`.
- **The comment** above the `decisions` case in `broker.mjs` now says which
part each row equals: inbox's view of the decision, which is trail's
`decisions` row with `blocking` as a boolean plus `authorization` from the
raise's `action.allowed` event (trail gives that too); a `recent` row adds
`closed`, the closing `decision_events` row.
- **README** (`packages/bus/README.md`): the sentence "Every row is the
decision as `trail` gives…" said the same imprecise thing, so it now says
what the comment says. The brief allows this edit only if the comment fix
changes what the README says; it does.
Out of scope, unchanged: no `LIMIT` on `roles`; `roles` order stays `seq`.
## Files
- `packages/bus/src/broker.mjs`: comment only.
- `packages/bus/README.md`: one sentence.
- `packages/bus/tests/decisions.test.mjs`: one new test; test 4 rewritten.
- `packages/webui/tests/bus.test.mjs`: three requests in the no-bus case.
## Mutants
`mut/run.mjs` (not shipped): one edit per mutant in the worktree, then the
owning suite (`packages/bus/tests/*.test.mjs`, or
`packages/webui/tests/bus.test.mjs` for `web-503-first`), then a restore.
`git diff` was unchanged after each run.
| Mutant | Edit | Base 970ef729 | Candidate |
|---|---|---|---|
| `recent-closed-first-event` | `closed` is the first event for the id | survives | killed: seen-then-closed |
| `recent-join-any-event` | `recent` joins any event, not only closing ops | survives | killed: seen-then-closed |
| `web-503-first` | `busRead` answers 503 before checking the request | survives | killed: refusals test |
| `view-requirement-null` | row drops `requirement_ref` | survives | killed: test 4 |
| `view-supersedes-null` | row drops `supersedes` | survives | killed: test 4 |
| `view-project-null` | row drops `project` | survives | killed: test 4 |
| `view-task-ref-null` | row drops `task_ref` | survives | killed: test 4 |
| `view-approval-fixed` | `approvalChoice` always `yes` | survives | killed: test 4 |
| `view-blocking-raw` | `blocking` left as 0/1 | killed: tests 1, 2 | killed: tests 1, 2, 4 |
Candidate: 9 of 9 killed, each by the test this row adds or rewrites.
Base: 8 of 9 survive. Each mutant fails only the tests named above; no
other test moved.
## Gate
`gate.sh` (not shipped) on the candidate worktree, sequentially, with
`TMPDIR` in scratch and `DOCKER_HOST` pointed at a missing socket:
| Suite | Result |
|---|---|
| `node --test packages/bus/tests/*.test.mjs` | 81 pass, 0 fail |
| `node --test packages/control-board/tests/*.test.mjs` | 124 pass, 0 fail |
| `node --test packages/webui/tests/*.test.mjs` | 40 pass, 0 fail |
| `node --test packages/cli/tests/*.test.mjs` | 112 pass, 0 fail |
| `scripts/test-auth.sh` | 15 passed, 0 failed |
| `scripts/test-conductor.sh` | 17 passed, 0 failed |
| `scripts/test-config.sh` | 24 passed, 0 failed |
| `scripts/test-discord.sh` | 66 passed, 0 failed |
| `scripts/test-extension-package.sh` | 18 passed, 0 failed |
| `scripts/test-foundation.sh` | 44 passed, 0 failed |
| `scripts/test-queue.sh` | 27 passed, 0 failed |
| `scripts/test-release.sh` | 4 passed, 0 failed |
| `scripts/test-task.sh` | 26 passed, 0 failed |
Every suite exited 0. `sha256sum -c candidate-manifest.sha256` passes in the
worktree, and `git diff 970ef729` there hashes the same as `build.patch`.
No commit since 970ef729 touches `packages/`.
Rows 59 and 60, both in review, also edit `packages/bus`. On a fresh
970ef729 worktree, `build.patch` applies after row 59's patch with plain
`git apply`, and after row 60's (alone, or after 59 then 60) with `--3way`
and no conflicts. Whichever lands first, this one re-bases cleanly; the
gate above is for this patch alone.
## Questions for reviewers
1. The webui check also pins `trail?subject=` before the 503. The brief
names only `list`; the order is the same code path one branch up, and
the line is in a file this row owns. Keep it or drop it?