Files

6.4 KiB

Row 227, Case 2 C2-14: end-to-end acceptance on a scratch root (#1728)

Owner Gizmoduck (sage-3581, 10-23), reviewer Dewey, who also runs the script. Brief: docs/plans/2026-10-20_case2-rows.md, section "C2-14 end-to-end acceptance on a scratch root", read at 45dca69f6. Branch gizmoduck/row227 on 45dca69f6.

Files

  • scripts/test-case2.sh (new). The entry point: syntax check, one driver run, one counted line per step, an order check on the step ids, and a check that the made-up token is in no driver output.
  • scripts/case2/e2e.mjs (new), its fixture. Every step runs in one node process, because her remote is row 199's fake Gitea over TLS with a scratch CA, and it lives only as long as the process that started it. checkMapping takes https:// remotes only (packages/library/src/mapping.mjs:46-48), so a plain file remote isn't an option.

The driver reuses the test fixtures already on refactor and adds none of its own: packages/seat/tests/fake-gitea.mjs (scratchCa, fakeGitea) and packages/library/tests/helpers.mjs (BASE, her layout's tree, MARKER, git, mappingEntry).

Two stand-ins

  1. The human. human-cli.mjs proves a human shell and refuses any caller with an agent among its ancestors (packages/bus/src/human.mjs; packages/cli/tests/access.test.mjs:3-4,285-286 pins the refusal). Dewey and I both run under an agent, so a shell driver of human-cli would refuse every human verb. The driver binds the human in-process with broker.bindHuman, as the bus tests do (packages/bus/tests/library-sync.test.mjs:27). The bus checks after the bind are the real ones.
  2. The fake harness. No launcher and no model. The driver binds the creative instance's run on her thread (bindLaunch with thread), claims it, receives her message and answers in reply to it. That covers the thread routing and the companion's messaging lists (roles/companion.json), and leaves the launcher out. If Dewey wants the launcher in the path, fakeHarnesses (packages/cli/tests/helpers.mjs:133) is the way in. That is a bigger fixture, and I'd rather take it with C2-06's own fake harness (brief C2-06) than build a second one here.

Steps

The ids are the driver's. "Waits on" names every row whose code the step needs and that isn't on refactor at 45dca69f6. A waiting step prints skip <id> waits on row <ids>: <text>, counted apart from pass and fail. When its rows land, the step gets written and its skip line goes.

Step Brief text State
S1a bare repo in her layout runs: classify on the fixture mapping (canon, manuscript, playground, unmapped, second universe)
S1b with a supporting folder waits on 283 (C2-01d, supporting folders and the editor field)
S2a it syncs runs: library.sync over https from the fake Gitea, served is her head
S2b runs: library.file reads canon and playground at served, refuses an unmapped note project-read-path
S2c runs: her fast-forward push is served by the next sync
S2d runs: the token is under no file of the data root, the mirror included
S3a asks a creative agent in its thread runs: project, thread on instance bean (companion), thread.send
S3b through a fake harness runs: the fake harness receives it and its reply is stored in her thread, in_reply_to her message
S3c stores a reply whose cites verify waits on 216 (C2-05a lookups) and 217 (C2-06 guard and page store)
S4 refuses a playground cite with "as": "canon" waits on 217 (playground-cited-as-canon)
S5a holds a force-push as library-diverged runs: refused, served unchanged, diverged.commit is the forced tip, the refusal recorded
S5b runs: accept of a stale commit refuses library-accept-stale, accept of the tip serves it
S6 fixture-grant write, one commit with the trailer, notice in her thread waits on 283, 285, 286, 288
S7 story-path write refuses library-write-story-path, ref unchanged waits on 283, 288
S8 her revert lands as one commit waits on 288
S9 her library.file.save lands as one commit, her editor as author waits on 283, 288
S10 the Console renders the reply and the notice waits on 220, 225

Row notes:

  • Sage's in-flight list was 216, 217, 220, 225, 226, 283, 285 and 286. Rows 284, 287, 288 and 289 also touch these steps, and the brief's "After" names the Q226 rows (told Sage in gizmoduck-0419). I mark a step with the rows its code needs, not every row that touches it:
    • 288 (C2-02) is the write verb, the notice, the revert and library.file.save, so S6-S9 all name it.
    • 287 (C2-21, the grant executor) isn't named on S6, because the brief asks for a fixture grant.
    • 284 (C2-05c) adds supporting docs to the lookups. S3c cites canon, so it waits on 216 and 217 only.
    • 289 (C2-11b) is the Console library page. S9 is the verb, which 288 owns. If Dewey reads S9 as the page, 289 joins its list.
    • 226 (C2-13, install script and precheck) gates no step. A scratch root isn't an install.
  • PRD 1.17 (row 308) made story files DOCX. The brief predates it and the fixture tree is Markdown. S1-S5 read that tree, which is what the landed reader takes. S6-S9 take the file shape 288 lands with.

Choices

  • One driver process, not one per step: the fake Gitea's port and CA would change with each process, and the library entry's remote is fixed at bus start.
  • The bus timer stays on with a one-hour period, since startBroker needs librarySync to carry the CA's command. Its pass at start can hold the mirror, so a step's sync retries library-sync-busy for up to about 10 s.
  • The refusal check opens the bus store read-only (node:sqlite, readOnly: true). The runtime hands back no store, and no bus verb lists the events.
  • Git in the driver runs with GIT_CONFIG_GLOBAL=/dev/null and GIT_CONFIG_NOSYSTEM=1, so a caller's hooks, signing or credential helper can't reach it. helpers.mjs git already passes the identity and core.hooksPath=/dev/null.

Carry for Dewey

  • The launcher in the path waits for C2-06's fake harness (row 217). Sage accepted both stand-ins, labelled, in sage-3608. When 217 lands, S3b moves to its fake harness behind the launcher.

Not yet run

Darkwing's re-pin window holds the slot (sage-3581), so as of this draft no node ran on it: no node --check, no driver run, no suite. bash -n scripts/test-case2.sh passes. The first run waits for Sage's CLEAR, and the runs go below.

Runs