docs: row 93 follow-up brief, git socket hardening and refusal tests (#1594)

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
2026-10-13 10:51:27 -05:00
co-authored by Claude Opus 5.5
parent 4da6815293
commit 8fda96112e
+77
View File
@@ -349,3 +349,80 @@ Filbert approves on the row's issue, naming the candidate manifest.
The suites above pass on Sage's gate rerun. `cli.mjs` applies to new
CLI runs as soon as it lands, so it gets decision-109 notices to Mos
before and after landing.
## Row 93 follow-up: git socket hardening and refusal tests
### Problem
Row 93 (4da68152, #1587) landed with approvals from Dewey (28196) and
Sage (28197), and neither blocked. Their non-blocking notes, with
Darkwing's `agents/darkwing/work/queue-93/r1-notes.md` (eabd5982),
leave these gaps:
- Five host refusals have no test: `not-a-role`, `host-closing`,
`git-busy`, `root-unreadable`, `unknown-project`.
- `working.mjs` kills a timed-out git with SIGKILL, so git never
removes its lockfiles. A stale `refs/heads/<branch>.lock` then blocks
every later push to that branch until an operator removes it.
- When `record` throws, the work ref's rollback `update-ref` result
isn't checked. A failed rollback leaves an unrecorded commit on the
work ref, and nothing reports it.
- `readBody` in `git-socket.mjs` has only a per-chunk idle timeout. A
session that sends a byte every 29 seconds holds a slot, and eight
such sessions make the socket refuse `git-busy` for everyone.
- A reviewer that disconnects mid-fetch is filed as `git-failed`.
- The runner fills `have` (HAVE_MAX 32) from all origin and working
refs in sort order, so with many refs it can drop the ones that
matter.
- The repository lock is in-process: it assumes one launcher per
dataRoot, and no README says so.
### Owner and reviewer
Darkwing builds it. Dewey and Sage review.
### Files owned
- `packages/seat/src/working.mjs`, `packages/seat/tests/working.test.mjs`,
`packages/seat/README.md`
- `packages/cli/src/git-socket.mjs`, `packages/cli/tests/git-socket.test.mjs`,
`packages/cli/README.md`
- `packages/harness/src/git-tools.mjs` and its tests, for `have` only
### What ships
- One test per untested refusal named above.
- On timeout, host git gets SIGTERM, a short grace period, then SIGKILL.
A test shows a timed-out push leaves no ref lock behind, and that the
next push to the branch lands.
- A failed rollback refuses `rollback-failed` and is logged by the host,
in place of the record's code. The broker's own refusal is already on
the trail. Test it with a rollback forced to fail.
- `readBody` has a total deadline as well as the idle timeout. The
deadline is a stated constant, or a stated function of the request's
size. A trickling client test refuses within it and frees its slot.
- A client gone mid-fetch is filed as `fetch-aborted`, not
`git-failed`.
- The runner's `have` lists the working refs before origin's and never
more than HAVE_MAX. A test uses more than 32 refs.
- The seat README says the lock assumes one launcher per dataRoot. The
reviewer docs say what `nothing-to-fetch` means.
Each new check is shown to fail on a mutant that removes it.
Suites: every node suite and every `scripts/test-*.sh`.
### Out of scope
- Tying a push's project to the task's own project, and checking that
the pusher is the task's assignee. Both need a design ruling first.
- gc of objects from refused pushes.
- Any broker or schema change.
### Gate
Dewey and Sage approve on the row's issue, naming the candidate
manifest, and the suites above pass on Sage's gate rerun. The cli and
seat changes reach the host only at a bus restart. That restart needs
Mos's go, and it batches with row 80's. Decision 109 notices go to Mos
before and after landing.