@naswerks/engineering-loop 0.8.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -10,7 +10,7 @@
10
10
  {
11
11
  "name": "naswerks",
12
12
  "description": "The engineering loop: docs-* knowledge loop, spec-* execution loop, and init for a fresh repository.",
13
- "version": "0.8.0",
13
+ "version": "0.9.0",
14
14
  "source": "./"
15
15
  }
16
16
  ]
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "naswerks",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "description": "The engineering loop: a knowledge loop (docs-*) and an execution loop (spec-*) for repositories driven by hosted agent sessions, plus init to make a repository ready for both.",
5
5
  "author": { "name": "naswerks" },
6
6
  "license": "MIT",
package/CHANGELOG.md CHANGED
@@ -5,6 +5,100 @@ version is the one in `package.json` and `.claude-plugin/plugin.json`, which mus
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
+ ## [0.9.0] - 2026-11-14
9
+
10
+ A minor: the skills act differently, the doctor can newly fail a brief, and a repository's copy of the loop text
11
+ takes one paragraph (§ Upgrading from 0.8). A pipeline that writes one repository runs as it did.
12
+
13
+ ### Added
14
+
15
+ - **A seat may also write a second repository: the `Repository` column.** A sequence row names the repositories its
16
+ seat also writes in, in an optional `Repository` column: one or more names, as the runner serves them. The column
17
+ never moves a seat: its home is the pipeline's own repository, where its spec, its board and the tracker are, and
18
+ one pull request still closes the pipeline. `spec-pipeline` states the column. `init doctor` reads it the way a
19
+ launcher does, and fails a cell holding a kind word, `step`, a name that is not one path segment of at most 200
20
+ characters, a ninth name, or a name twice. **A pipeline that writes one repository has no such column and is
21
+ unchanged.**
22
+ - **What a seat does in a second repository** (`spec-seat` § Git shapes, `spec-build`). Its home stays this
23
+ repository and nothing of the pipeline's record is written in the other one. Its code goes in its own tree of
24
+ that repository, never the owner's checkout: hosted, at the path the variable its seed names holds; by hand, at
25
+ the path its prompt names. Then a staging list, a `verify-staged` receipt, a commit and a push per repository;
26
+ that repository's whole gate, run in its tree; its own rules for commit and pull-request text; a draft pull
27
+ request where it checks them, its checks read after every push; no merge, tag or publish. Its commit there goes
28
+ on an `ALSO WRITING` line beneath BELIEFS, and its FINAL gives a list and a receipt per repository. A pin holds
29
+ every clause, because a launcher that knows this version says only where the tree is.
30
+ - **The push in a second repository has its own form:** `cd` into the tree, then the push, and nothing else on the
31
+ line. `spec-seat` said a leading `cd` disqualifies every push; that is the rule for the home repository, and it
32
+ now says so.
33
+ - **The coordinator's and the review's side of a second repository.** `spec-coordinator` tells such a seat where
34
+ its tree is and nothing else (by hand; hosted, the seed says where), diffs its `ALSO WRITING` line, checks two
35
+ receipts at the FINAL, reads a pull request's checks at every seat report in whichever repository the branch is,
36
+ and hands the review one diff range per repository (by release tags when the run released it mid-run).
37
+ `spec-review` reads each range and the seam between them. A pin holds every template line for a further
38
+ repository under a line saying when it applies.
39
+ - **A conditional fixit that must write a further repository is listed as a row, directly after the review row**
40
+ (`spec-pipeline`). Listed anywhere else, a launcher reads a second fixit beside the one the review implies, and
41
+ the doctor names it.
42
+ - **The model and the effort a run starts on are named in the brief and read back.** `spec-pipeline`'s `## Birth`
43
+ names both, each in backticks, because the launcher reads them from that section; a brief that names neither
44
+ leaves both to the launcher's default. A seat's BELIEFS line states the model and effort its session is running
45
+ on, as it can read them, and `spec-coordinator` settles a seat on a pair the brief does not name before it rules
46
+ that seat's plan.
47
+
48
+ ### Changed
49
+
50
+ - **Pipelines never intertwine** replaces "one pipeline at a time", in `spec-coordinator`'s hard rules and in
51
+ `references/engineering-loop.md`. A brief's GATE still checks only that its predecessor merged, and no seat waits
52
+ on another pipeline; independent pipelines may run at the same time, each on its own branch. The coordinator takes
53
+ a moved base branch in between seats, by a merge. A repository's `docs/_meta/` copy takes the paragraph by hand.
54
+ - **A review's diff range reads the remote's copy of the base branch** (`origin/{base}...{branch}`), in
55
+ `spec-coordinator`'s REVIEW manifest, `spec-review` and `spec-pipeline`: a local base branch can sit behind it and
56
+ pull another effort's commits into the range.
57
+ - **`spec-coordinator`'s Step 0 is two numbered reads:** the seven floor docs, then every doc the repository's role
58
+ reading lists carry a path for. The second read was a trailing clause, and coordinators read the floor and stopped.
59
+ The status readback opens with how many docs each read took.
60
+ - **The coordinator edits its tracker and a seat's board with file tools, never a shell heredoc or an interpreter
61
+ one-liner** (`spec-coordinator`): one collapses backslashes, and one whose text quotes a publish is held.
62
+
63
+ ### Fixed
64
+
65
+ - `spec-coordinator` said a backticked sha is fine for the plan verdict's workspace HEAD. The verb takes only the
66
+ bare 40-hex sha and refuses a backticked or quoted one, recording nothing, so a coordinator that followed the skill
67
+ spent a refused call on every plan ruling. It now says the bare sha; a seat's board may still fence its own.
68
+ - `spec-coordinator` wrote an amount as a dollar sign before a digit, which a harness that substitutes a skill's
69
+ arguments by position rewrote at load: the line about uncosted turns read with the invocation's first argument in
70
+ the amount's place. The amount is spelled out, and a pin holds every skill's text free of a dollar sign before a
71
+ digit and of the arguments token.
72
+ - `spec-seat`, `spec-coordinator` and `spec-retro` said the gate matches text and told a seat to keep git words out
73
+ of echo labels, section headers and searches. The gate reads the command the shell would run: what parks is the
74
+ operation, at any depth, and an echo label, a branch listing and a quoted search are data unless something on the
75
+ line could run them. Six passages say so now, in fewer lines, and a pin keeps the old rule out.
76
+ - `spec-seat` said the HEAD check takes the first `HEAD <sha>` it meets. It reads the newest line that carries
77
+ `BELIEFS`, so a seat whose HEAD moved appends a new BELIEFS line and never edits the old one.
78
+
79
+ ### Upgrading from 0.8
80
+
81
+ In this order:
82
+
83
+ 1. **Take the release where every session loads it:** `claude plugin marketplace update engineering-loop`, then
84
+ `claude plugin update naswerks@engineering-loop --scope <scope>` for each scope that runs sessions, and a new
85
+ session. A runner takes `@naswerks/engineering-loop@0.9.0` in the folder its plugin directories name, and is
86
+ restarted by its owner with no seat live.
87
+ 2. **Replace one paragraph of loop text.** In `docs/_meta/engineering-loop.md`, the paragraph that opens
88
+ **One pipeline at a time.** becomes:
89
+
90
+ > **Pipelines never intertwine.** A pipeline's GATE is that its predecessor merged — never a seat of another
91
+ > pipeline — and no seat waits on another pipeline. Independent pipelines may run at the same time, each on
92
+ > its own branch, merged one after the other.
93
+
94
+ It is the only loop text that changed. `docs/_meta/docs-workflow.md` takes nothing but its stamp, and the four
95
+ repository-owned sections are yours and are not touched.
96
+ 3. **Restamp and check:** `init refresh` (with `--write`) restamps both copies and leaves every other line as it
97
+ is; then `init doctor`. A repository that read clean on 0.8.0 reads clean, unless a brief lists a `fixit` row
98
+ away from its `review` row or holds a `Repository` cell that is not a list of names.
99
+
100
+ No pipeline folder changes shape, and a sequence with no `Repository` column reads as it always has.
101
+
8
102
  ## [0.8.0] - 2026-10-21
9
103
 
10
104
  A minor: the skills act differently, and a repository must act — its method docs take new text, and every
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@naswerks/engineering-loop",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "description": "The engineering loop as a Claude Code plugin: a knowledge loop (docs-*), an execution loop (spec-*), and init for a fresh repository. The package root is the plugin root.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -1,4 +1,4 @@
1
- <!-- naswerks-loop: version=0.8.0 -->
1
+ <!-- naswerks-loop: version=0.9.0 -->
2
2
  # Docs Workflow
3
3
 
4
4
  > How knowledge flows through `docs/`: the loop, the folder rules, the templates, and the `docs-*` skills.
@@ -1,4 +1,4 @@
1
- <!-- naswerks-loop: version=0.8.0 -->
1
+ <!-- naswerks-loop: version=0.9.0 -->
2
2
  # The Engineering Loop — flow, seats, skills, and the ceremony
3
3
 
4
4
  > The quick intro to how work gets built with this loop: the two loops (`docs-*` knowledge, `spec-*`
@@ -74,8 +74,9 @@ owner's — never a seat's job and never a doc's row: the coordinator offers a s
74
74
  the chat, and `live-checks.md` holds only the rows the owner dictates. Everything between `idea` and
75
75
  `archived` a pipeline can do for itself.
76
76
 
77
- **One pipeline at a time.** A pipeline's GATE is that its predecessor merged — never a seat of another
78
- pipeline — and the next one starts after it.
77
+ **Pipelines never intertwine.** A pipeline's GATE is that its predecessor merged — never a seat of another
78
+ pipeline — and no seat waits on another pipeline. Independent pipelines may run at the same time, each on
79
+ its own branch, merged one after the other.
79
80
 
80
81
  **`docs-audit-*` is never a pipeline row.** It runs off-hours and scheduled, over the whole doc tree — not
81
82
  inside an effort, and not at an effort's close. A stale living doc is not something a pipeline must stop for.
@@ -197,6 +197,11 @@ for (const name of ['CLAUDE.md', 'AGENTS.md']) {
197
197
  // The kick is sent verbatim as the coordinator's task, so a skill it names that this pack does not carry
198
198
  // (a renamed one, most often) tells the coordinator to invoke nothing.
199
199
  const packSkills = new Set(existsSync(join(packRoot, 'skills')) ? readdirSync(join(packRoot, 'skills')) : []);
200
+ // A repository's name as a sequence row may write it: one path segment, no separators, no spaces, of at most
201
+ // MAX_REPOSITORY_NAME characters; a row names at most MAX_REPOSITORIES, none twice.
202
+ const REPOSITORY_NAME = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
203
+ const MAX_REPOSITORY_NAME = 200;
204
+ const MAX_REPOSITORIES = 8;
200
205
  const researchDir = join(repo, 'docs', 'research');
201
206
  if (existsSync(researchDir)) {
202
207
  for (const topic of readdirSync(researchDir)) {
@@ -217,17 +222,38 @@ if (existsSync(researchDir)) {
217
222
  const cellsOf = (line) => line.trim().replace(/^\|/, '').replace(/\|$/, '').split('|').map((c) => c.trim().replace(/^`|`$/g, '').trim());
218
223
  // The optional Role column, found by its header; a row's cell there is a role or empty.
219
224
  const roleAt = tableRows.length ? cellsOf(tableRows[0]).findIndex((c) => c.toLowerCase() === 'role') : -1;
225
+ // The optional Repository column, found by its header; a row's cell there names the repositories the
226
+ // seat also writes in, or is empty. The table is read by kind value, so a kind word or `step` in that
227
+ // cell would be read as the row's kind: it fails by name, before either is looked for.
228
+ const repositoryAt = tableRows.length ? cellsOf(tableRows[0]).findIndex((c) => c.toLowerCase() === 'repository') : -1;
229
+ // The seat rows' kinds, in order: where a listed fixit sits is read from them.
230
+ const seatKinds = [];
220
231
  for (const line of tableRows.slice(1)) {
221
232
  const cells = cellsOf(line);
222
233
  if (cells.every((c) => /^[-: ]*$/.test(c))) continue;
223
234
  const spec = cells.map((c) => SPEC_FILE.exec(c)).find(Boolean);
224
235
  if (spec) named.add(spec[1]);
236
+ const repositories = repositoryAt >= 0 ? (cells[repositoryAt] ?? '') : '';
237
+ const names = !repositories || /^[-—]$/.test(repositories) ? [] : repositories.split(/\s*[·,]\s*/).map((n) => n.replace(/`/g, '').trim()).filter((n) => n !== '');
238
+ const notNames = names.filter((n) => KINDS.includes(n) || n === STEP || !REPOSITORY_NAME.test(n) || n.length > MAX_REPOSITORY_NAME);
239
+ if (notNames.length) {
240
+ for (const n of notNames) problems.push(`a sequence row's repository \`${n.length > 60 ? `${n.slice(0, 60)}…` : n}\` is not a repository's name (one path segment of at most ${MAX_REPOSITORY_NAME} characters; a kind word or \`${STEP}\` there is read as the row's kind): \`${line.trim().slice(0, 200)}\``);
241
+ continue;
242
+ }
243
+ if (names.length > MAX_REPOSITORIES) problems.push(`a sequence row names ${names.length} repositories and a seat writes at most ${MAX_REPOSITORIES}: \`${line.trim()}\``);
244
+ for (const n of new Set(names.filter((name, i) => names.indexOf(name) !== i))) problems.push(`a sequence row names the repository \`${n}\` twice: \`${line.trim()}\``);
225
245
  if (cells.includes(STEP)) continue;
226
246
  if (!cells.some((c) => KINDS.includes(c))) { problems.push(`a sequence row names no seat kind and composes nothing (a row that is not a seat says \`${STEP}\`): \`${line.trim()}\``); continue; }
247
+ seatKinds.push(cells.find((c) => KINDS.includes(c)));
227
248
  const role = roleAt >= 0 ? (cells[roleAt] ?? '') : '';
228
249
  if (role && !/^[-—]$/.test(role) && !ROLES.includes(role)) problems.push(`a sequence row's role \`${role}\` is not one of ${ROLES.map((r) => `\`${r}\``).join(' · ')}: \`${line.trim()}\``);
229
250
  if (spec && !existsSync(join(researchDir, topic, spec[1]))) problems.push(`the sequence names \`${spec[1]}\` and it is missing from disk`);
230
251
  }
252
+ // A listed fixit is the one its review implies only when it is the next seat row after that review. Listed
253
+ // anywhere else, a launcher reads a second fixit beside the implied one, and that one names no repository.
254
+ const reviewAt = seatKinds.indexOf('review');
255
+ const fixitAt = seatKinds.indexOf('fixit');
256
+ if (reviewAt >= 0 && fixitAt >= 0 && fixitAt !== reviewAt + 1) problems.push('the sequence lists a `fixit` row that is not the next seat row after its `review` row, so a launcher reads two fixits and the extra one names no repository: move the row directly after the review');
231
257
  }
232
258
  // An old-shape folder carries an umbrella: a `01-` file no sequence row names. It still runs on an older
233
259
  // pack; carry it over before it runs on this one.
@@ -93,6 +93,10 @@ signal that a VERDICT changed, not that the test is stale.
93
93
  Run the suite lanes **SERIALLY** — the lanes and their exact invocations are `patterns/testing.md`
94
94
  § Running tests; concurrent runs flake.
95
95
 
96
+ **A seat that wrote a further repository runs THAT repository's gate too, inside its tree of it** — the
97
+ lanes its own contributing rules name, serially, never beside this repository's — and reports each
98
+ repository's summaries under its own name. This repository's lanes do not run the code you wrote there.
99
+
96
100
  **Capture FULL runner output to a UTF-8 file and search failures by name** — redirect to a file, then
97
101
  search `^failed ` / `Failed!`. Piping through a "last N lines" filter destroys failure names.
98
102
 
@@ -35,14 +35,15 @@ hand-testing what shipped. Everything else that a human does hand-cranked, you d
35
35
 
36
36
  ## Read first
37
37
 
38
- **Step 0 — the same floor every seat reads, all seven, plus every standard doc this repository has.**
39
- You verify every seat's work, so you start from the context they build in. A coordinator that has not
40
- read `testing.md` cannot judge a receipt; one that has not read `codegen.md` (when the repo has one)
41
- cannot spot a hand-written generated file.
38
+ **Step 0 — two reads, and neither is optional.** You verify every seat's work, so you start from the
39
+ context they build in. A coordinator that has not read `testing.md` cannot judge a receipt; one that has
40
+ not read `codegen.md` (when the repo has one) cannot spot a hand-written generated file.
42
41
 
43
- `_meta/doc-index.md` · `_meta/docs-workflow.md` · `_meta/engineering-loop.md` ·
44
- `patterns/code-organization.md` · `patterns/backend-patterns.md` · `patterns/frontend-patterns.md` ·
45
- `patterns/testing.md` — then every doc `doc-index.md` § Role reading lists carries a path for.
42
+ 1. **The floor every seat reads, all seven:** `_meta/doc-index.md` · `_meta/docs-workflow.md` ·
43
+ `_meta/engineering-loop.md` · `patterns/code-organization.md` · `patterns/backend-patterns.md` ·
44
+ `patterns/frontend-patterns.md` · `patterns/testing.md`.
45
+ 2. **Then every doc `doc-index.md` § Role reading lists carries a path for.** Open that section and read
46
+ each one. The floor alone is not Step 0.
46
47
 
47
48
  **Step 1 — the effort**, in order:
48
49
 
@@ -67,8 +68,9 @@ now, and again before you cut the retro. **A disagreement is a finding, not a ty
67
68
  changed in one place and not the other. Say which is right, fix the other, and journal it.
68
69
 
69
70
  Then produce a **5-line status readback** — shipped / in flight / next action / next prompt you expect to
70
- cut. Hand-cranked that goes to the human so they can confirm the seat transferred; hosted it is your
71
- opening journal entry in `project-status.md`, which is how anyone watching the cockpit catches up.
71
+ cut — opening with how many docs each of Step 0's two reads took. Hand-cranked that goes to the human so
72
+ they can confirm the seat transferred; hosted it is your opening journal entry in `project-status.md`,
73
+ which is how anyone watching the cockpit catches up.
72
74
 
73
75
  **Same-session graduation:** you just ran `spec-pipeline`, so you already hold most of Step 1 — confirm
74
76
  the tracker exists and cut Prompt #1. **Step 0 still applies.**
@@ -88,7 +90,7 @@ plus the human relay.
88
90
  | Verb | What it does | The part that bites |
89
91
  |---|---|---|
90
92
  | `seat_spawn` | Opens a DECLARED sibling's session | **It can never CREATE a seat** — the topology is the create door's, decided by a human — and you may only drive seats you `supervises`/`reviews`. With no `hostId` it opens on the host carrying your own session; `model` and `effort` override the seat's own for this session, judged against what the runner offers |
91
- | `accept_plan` | The verdict act: `accept` · `accept-with-riders` · `blocking-precondition`, **and NOTHING ELSE carries a go** — and it DELIVERS ITSELF: the seat's live session receives a one-line pointer to the ruling, for an accepting verdict and for any verdict that filed a ruling in the seat's file | Write the ruling into the seat's `tldr.md` FIRST (`## COORDINATOR RULING (plan rev N — {verdict})`), then call with a one-line `ruling`: the file is mirrored before your act and the pointer names your section. Pass the workspace HEAD you observed (a backticked sha is fine); an accepting verdict whose seat planned against a different tree is REFUSED, naming both shas. READ THE REPLY'S `delivery:` and `file:` LINES — `NOT DELIVERED` means the seat is idle and only a `callout` reaches it. When the verdict also answers the seat's question, pass `answeringActId` — one act rules and closes it |
93
+ | `accept_plan` | The verdict act: `accept` · `accept-with-riders` · `blocking-precondition`, **and NOTHING ELSE carries a go** — and it DELIVERS ITSELF: the seat's live session receives a one-line pointer to the ruling, for an accepting verdict and for any verdict that filed a ruling in the seat's file | Write the ruling into the seat's `tldr.md` FIRST (`## COORDINATOR RULING (plan rev N — {verdict})`), then call with a one-line `ruling`: the file is mirrored before your act and the pointer names your section. Pass the workspace HEAD you observed as the bare 40-hex sha `git rev-parse HEAD` prints — a backticked or quoted one is refused and records nothing, though a seat's board may fence its own; an accepting verdict whose seat planned against a different tree is REFUSED, naming both shas. READ THE REPLY'S `delivery:` and `file:` LINES — `NOT DELIVERED` means the seat is idle and only a `callout` reaches it. When the verdict also answers the seat's question, pass `answeringActId` — one act rules and closes it |
92
94
  | `accept` | The rev-bound FINAL receipt — and it TELLS the seat, so it carries your commit call | Put the next instruction (commit, push, close-out) in `ruling`, or write it under `## COORDINATOR ACCEPT` in the seat's `tldr.md` first — the receipt then binds to that mirrored revision. It binds to the seat's CURRENT tldr revision, so if the seat posts NEW CONTENT again your acceptance no longer covers what it publishes. **Re-accept — it is idempotent and cheap.** This receipt is what the push bar reads; prose is not a receipt. `answeringActId` closes the question it answers, as on `accept_plan` |
93
95
  | `complete` | The reap, and it is HONEST | It re-reads the seat and reports ok only after the terminal state is OBSERVED |
94
96
  | `callout` | **THE ONLY WAY YOU REACH A CHARGE** (besides the pointers `accept_plan` and `accept` send) | A charge that posted and ended its turn cannot resume any other way — without this verb it waits for a human. Your ruling must carry a DETERMINATE NEXT ACTION it can execute without inference. **Write it into the seat's `tldr.md` first and pass a one-line `ruling`:** the file is mirrored before your act and the seat is pointed at your section. Without a file, KEEP IT TO A LINE: over 600 chars the body is stored as a `ruling` artifact on the board and the seat receives a POINTER — the seat reads the body once, never twice |
@@ -171,6 +173,8 @@ and a seat's close-out. Never reconstruct it at the close.
171
173
  call out / hand the human both sides when the call is genuinely theirs.
172
174
  **The accepting verdict carries the workspace HEAD you observed, and a seat that planned against a
173
175
  different tree is REFUSED with both shas named.** So read the BELIEFS sha before you rule, not after.
176
+ **A seat whose row names a further repository states that tree too,** on an `ALSO WRITING` line beneath
177
+ its BELIEFS: diff its commit and branch against that repository's branch, with your own `git` read of it.
174
178
  **AND GRADE THE `CONTROLS` LINE — it is a required PLAN TLDR field and you are its only reader.** For
175
179
  every probe or pin the seat plans, it must name the positive control and what would make it FAIL. A
176
180
  missing or hand-wavy `CONTROLS` line is a rider, not a nit: a control that cannot fail is a green light
@@ -188,6 +192,8 @@ and a seat's close-out. Never reconstruct it at the close.
188
192
  But spot-check the riskiest claim yourself (never trust self-reported "N green"), and **verify your own
189
193
  rulings were APPLIED** — a ruling can silently drop, and a seat can rebuild the exact problem
190
194
  the ruling solved. Diff the shipped behavior against your ruling list before accepting.
195
+ **A seat that wrote two repositories returns two of everything:** a staging list and its receipt per
196
+ repository, and each repository's gate under its own name. A green in one says nothing about the other.
191
197
  **VERIFY THE CLAIM WHOSE FAILURE WOULD BE SILENT; MACHINE-COMPARE THE REST.** That is the rule that
192
198
  keeps your own share of the spend honest — a seat producing receipts that reconcile arithmetically has
193
199
  already done the work you would be repeating.
@@ -202,6 +208,10 @@ and a seat's close-out. Never reconstruct it at the close.
202
208
  **Advance the tracker AT EVERY CHECKPOINT.** Plan accepted: the row says so; final TLDR accepted: the
203
209
  row says so; push confirmed: SHIPPED with the hash. A stale tracker is your omission.
204
210
 
211
+ **WHEN A BRANCH A SEAT PUSHES HAS A PULL REQUEST OPEN, READ ITS CHECKS AT EVERY SEAT REPORT,** in
212
+ whichever repository it is, with your own read and not the seat's sentence about it: a check read at
213
+ the first commit says nothing about the tenth.
214
+
205
215
  **CLOSING A HUMAN STEP: TAKE THE RECEIPT, DO NOT WRITE IT.** A `step` row has no seat to post a TLDR,
206
216
  so the temptation is to transcribe the sitting into your tracker and call the step recorded. **That
207
217
  leaves it with ONE voice — yours — and it is the only row in the effort with one.** Ask the human
@@ -330,9 +340,7 @@ and a seat's close-out. Never reconstruct it at the close.
330
340
  `docs/_meta/engineering-loop.md` § This repository's rails (repository-owned) says (when it names no
331
341
  route, ask the human once and suggest recording the answer there); if one is already open the push is
332
342
  enough. These are your own git — gated and receipted like any other publish. **The
333
- push command must be the ENTIRE command** (a leading `cd` disqualifies it), and keep git-verb words
334
- out of any echo label around it — the deny layer matches TEXT, not parsed verbs, and a decorative
335
- `=== remote tip ===` header over a read-only block will park.
343
+ push command must be the ENTIRE command** (a leading `cd` disqualifies it).
336
344
  6. **Report the close:** commits, receipts, total cost with its uncosted-turn count, the findings ledger,
337
345
  and the explicit list of what the human still owns. **The merge is theirs, never yours.**
338
346
  7. **If the effort has a DOCS-PROCESS row, it runs last** — after the PR exists, as its own session,
@@ -397,7 +405,7 @@ so read them as run-time obligations, not close-out ones:
397
405
  - **Verify a query FIRES on a known-positive before you trust a clean result.** A silently-empty result
398
406
  is usually a broken query, not an empty table — and a false all-clear on an audit query is worse than
399
407
  no query.
400
- - **Costs: uncosted turns count $0**, so any total is a FLOOR while the uncosted-turn count is above zero.
408
+ - **Costs: an uncosted turn counts as nothing**, so any total is a FLOOR while the uncosted-turn count is above zero.
401
409
  Report it with the count. **Never sum across instruments** — session footers ride the seats' wakes and
402
410
  omit your own spend.
403
411
 
@@ -409,8 +417,10 @@ so read them as run-time obligations, not close-out ones:
409
417
  approved seat commits and pushes its branch itself (the relay, below); hosted, the commit call rides your
410
418
  acceptance. The PR is yours at the close. The merge is the human's, always. Explicit staging only —
411
419
  never `git add -A` — and never a push to the base branch.
412
- - **One pipeline at a time.** A brief's GATE checks only that its predecessor merged; never gate a run on
413
- another pipeline's seats, and never run two pipelines over one another.
420
+ - **Pipelines never intertwine.** A brief's GATE checks only that its predecessor merged; never gate a run
421
+ on another pipeline's seats, and never make a seat wait on one. Independent pipelines may run at the same
422
+ time, each on its own branch; never two over the same files or on one branch. When the base branch moves
423
+ under your run, take it in between seats, by a merge, never under a live seat and never as a rebase.
414
424
  - **Never advise or run a runner restart while a seat is live.** A restart ends every live session on that
415
425
  runner, and the plane may not notice. "Restarting it is fine" said to the human in that state is how a
416
426
  run loses every seat at once; say instead which seats are live and that the restart waits.
@@ -426,9 +436,9 @@ so read them as run-time obligations, not close-out ones:
426
436
  - **The unattended git form, and it binds YOU as much as the seats: one git command per call, no shell
427
437
  metacharacters.** The FORM check reads the whole command string, so chaining, redirects or substitution
428
438
  disqualify it — `git add … && git commit … && git push …` parks, while the same three sent separately
429
- flow. Pushes always name the refspec; a push without one parks by design. Keep git-verb words out of
430
- echo text and section labels — **including `branch`**, which parks a read-only branch LISTING on the
431
- branch-deletion backstop. The fence fires on the commands a careful seat runs to PROVE its work.
439
+ flow. Pushes always name the refspec; a push without one parks by design. The gate reads the command
440
+ the shell would run, not its words: an echo label or a quoted search naming a git verb is data, unless
441
+ a shell or an interpreter is on the same line.
432
442
  - Seats never edit `project-status.md`, `live-checks.md` or memory files; never run `docs-write` unprompted;
433
443
  respect the brief's § What this effort does NOT do; codegen only through the command `patterns/codegen.md` § Running codegen
434
444
  names (when the repo has one); component files laid out as `patterns/frontend-patterns.md` § Component files states. Run the
@@ -438,9 +448,11 @@ so read them as run-time obligations, not close-out ones:
438
448
  - **Cite symbols, not bare `file:line`.** In a seed, a ruling, or the tracker, name the symbol and use the
439
449
  line as a hint — a line number is a comment, not an address, and the seat documenting why a line matters
440
450
  is what moves it.
441
- - Model policy: seats run **the effort's declared default model** (allowlist-exact, set at creation);
442
- investigation-heavy sessions may warrant a reasoning-heavier one. Parallel sessions only when
443
- the specs share no files — and sequence the *commits* regardless.
451
+ - Model policy: seats run **the effort's declared default model and effort** — the pair the brief's
452
+ `## Birth` names (allowlist-exact, set at creation); investigation-heavy sessions may warrant a
453
+ reasoning-heavier one. **A seat's BELIEFS line states the pair it started on, and one the brief does not
454
+ name is settled before you rule its plan:** re-open the seat on the named pair, or rule the difference in
455
+ by name. Parallel sessions only when the specs share no files — and sequence the *commits* regardless.
444
456
  - **The gate is inverted (means are free, protocol is law):** benign tools/methods flow with audit rows;
445
457
  only the ceremony's boundaries park — in EVERY tier, recon included. Reads, execs, suites, pipes,
446
458
  redirects and in-worktree writes all flow pre-accept. **Do not seed tool-avoidance rules the platform
@@ -507,6 +519,9 @@ role={backend | frontend | mixed} before anything else, and ALWAYS after `spec-s
507
519
  names `spec-seat` first, the job skill second. <- hand-cranked only; hosted, start at the spec
508
520
 
509
521
  Your spec: {absolute path to the spec}
522
+ {only when the seat's row names a further repository, one line each; hand-cranked only — hosted, the
523
+ seed says where:}
524
+ You also write: {repository} — your tree of it is {absolute path}, on branch {branch}. Never its owner's checkout.
510
525
  Pipeline context: {brief path} — the charter: its sections down to § Platform state bind you, and the owner's
511
526
  rulings in it are settled (don't relitigate) + {project-status.md path}
512
527
  (READ-ONLY, coordinator-owned — prior rows, deferred findings, and process incidents are your contract).
@@ -529,6 +544,10 @@ Baselines (cite, don't re-measure): {per lane, from the brief's § Baselines: N
529
544
  THE TASK: {compressed spec restatement with the load-bearing specifics inline.}
530
545
  ```
531
546
 
547
+ **A seat that also writes a further repository is told WHERE, and nothing else about it:** what it does
548
+ there is `spec-seat` § Git shapes, and a prompt that restates it is a second copy of the contract. A seat
549
+ whose row names none gets no such line, and a prompt exactly as it would have been.
550
+
532
551
  For investigation-first work, add **STEP 0 — INVESTIGATE, REPORT, STOP** before the task, or use
533
552
  `role={...} fixit` for no-spec defect sessions (the skill carries the fix-it ceremony). Fallback: if the
534
553
  seat can't invoke skills, paste the ceremony from the `spec-build` skill inline.
@@ -546,7 +565,10 @@ second** — this is the whole point of the row.
546
565
  ```
547
566
  REVIEW row (R):
548
567
  You are the REVIEW SEAT: invoke the spec-review skill before anything else.
549
- Topic: {topic} · branch: {branch} · diff range: {base}...{branch}
568
+ Topic: {topic} · branch: {branch} · diff range: origin/{base}...{branch}
569
+ {when the run wrote a further repository, one more line each:}
570
+ Also: {repository}, at {its path} · diff range: origin/{its base}...{its branch}, or by its release
571
+ tags ({the release before}...{this run's release}) when the run released it mid-run
550
572
  The brief, down to § Platform state and never past it (read as claims, not facts):
551
573
  docs/research/{topic}/00-ignition-brief.md
552
574
  Specs (read as claims, not facts): {every numbered spec path}
@@ -687,7 +709,9 @@ post-merge.
687
709
  - **The tracker is the seat — ONE ledger, and you write it live.** `project-status.md` is your journal: you
688
710
  own it, you advance it at every boundary, and the human never edits it. That file, not the chat, is the
689
711
  product of this skill. **The mechanism is ordinary file tools** — edit it exactly as a seat edits
690
- `tldr.md`/`plan.md`; the gate permits the path. Git commits are the receipt: timestamped, attributed,
712
+ `tldr.md`/`plan.md`; the gate permits the path. **Never a shell heredoc or an interpreter one-liner,
713
+ for the tracker or for a seat's board:** one collapses backslashes in what it writes, and one whose
714
+ text quotes a publish is held as if it ran it. Git commits are the receipt: timestamped, attributed,
691
715
  carrying the diff.
692
716
  - **The session entry is a JOURNAL entry, not a status cell.** The ruling *and its reasoning*, recon
693
717
  corrections, what you verified yourself, mid-build directives, and anything you don't want to forget —
@@ -141,15 +141,27 @@ sessions/ WHO PUTS IT THERE
141
141
  reading list of a build seat should not be left to the default. Leave the column out when no row needs
142
142
  it.
143
143
 
144
+ **A seat row may name the repositories it ALSO writes in** — in a `Repository` column, when the seat
145
+ builds something that lives in another repository: a package this repository consumes, say. The cell
146
+ holds one or more names, as the runner that carries the seat serves them, separated by ` · ` or `,`;
147
+ an empty cell, `-` or `—` means none. **The column never moves a seat:** its home is always the
148
+ pipeline's own repository, where the specs, the boards and the tracker are. The pipeline still closes
149
+ on ONE pull request, its own repository's; a release of the other repository is a `step` row. Leave
150
+ the column out when no row needs it — most pipelines write one repository, and nothing about them
151
+ changes.
152
+
144
153
  Then write the rows into the brief's sequence, in this order:
145
154
 
146
155
  ```
147
156
  0 the coordinator, with the brief as its spec
148
157
  01..NN the build seats, with any `step` rows in their places
149
- {R} REVIEW — spec-review, if chosen. Runs on `git diff {base}...<branch>` (the rails' base branch); no PR yet
158
+ {R} REVIEW — spec-review, if chosen. Runs on `git diff origin/{base}...<branch>` (the rails' base branch); no PR yet
150
159
  {F} FIXIT — MAY materialise, one maximum, only if the review classifies an (a)+(b)
151
160
  finding AND the coordinator rules it in. Not authored up front; the
152
- coordinator charters it from the review's named list
161
+ coordinator charters it from the review's named list. Listed as a row
162
+ only when it must write a further repository: then directly after the
163
+ review row, with its `Repository` cell — anywhere else a launcher reads
164
+ a second fixit beside the one the review implies
153
165
  — the coordinator's retro + PR (its own close-out, not a row)
154
166
  {P} DOCS-PROCESS — if chosen
155
167
  ```
@@ -272,9 +284,15 @@ corrects drift; it does not re-author it.
272
284
  What is wrong today and what the effort makes true — the vision a seat builds toward.
273
285
 
274
286
  ## Birth
275
- Topic · spec path · receipt prefix · mode (hosted, or by hand) · shape · the effort's branch · the rows
276
- chosen at authoring (review? docs-process?) and why · **the GATE**: only that the predecessor merged, then
277
- re-verify this brief's § Reference and re-measure § Baselines.
287
+ Topic · spec path · receipt prefix · mode (hosted, or by hand) · shape · the effort's branch · **the model
288
+ and the effort every seat starts on** · the rows chosen at authoring (review? docs-process?) and why ·
289
+ **the GATE**: only that the predecessor merged, then re-verify this brief's § Reference and re-measure
290
+ § Baselines.
291
+
292
+ **Name the model and the effort, each in backticks** — the word model then the id, the word effort then the
293
+ level (*every seat starts on model `{id}` at effort `{level}`*) — because the launcher reads both from this
294
+ section. Write the id as the runner's catalog offers it. A brief that names neither leaves both to the
295
+ launcher's default; hand-cranked, the same line tells the human which model to open each seat's session on.
278
296
 
279
297
  ## The sequence
280
298
  | Seat | Spec | Kind | Why it sits here |
@@ -285,7 +303,10 @@ prose role.** This table is READ, not just read by people: ignition derives the
285
303
  (`spec-ignite` § the stage card is derived), the create door validates the kind against a closed set and
286
304
  refuses an unknown by name, and the doctor fails a row whose kind is none of these. A cell saying "the one
287
305
  that reviews" composes nothing. An optional `Role` column carries `backend` · `frontend` · `mixed` for a
288
- seat whose reading list should not be left to the default.
306
+ seat whose reading list should not be left to the default. An optional `Repository` column names the
307
+ repositories a seat also writes in, by the runner's names; a seat's home is always this repository. Neither
308
+ column's cell may hold a kind word or `step`: the table is read by kind value, and a kind word anywhere in
309
+ a row is read as that row's kind.
289
310
 
290
311
  **This is the only copy of the sequence.** The tracker's status lines name these rows by id and copy
291
312
  nothing else.
@@ -73,9 +73,10 @@ population or only its failures.
73
73
  silently-empty result is usually a broken query, not an empty table.
74
74
  - **A search that times out is not a search that found nothing.** If a sweep backs an ABSENCE claim,
75
75
  re-run it on the tool that completes before you report the absence.
76
- - **A gate scanner matches TEXT.** A query or command whose text contains `git` and `push`, or
77
- `git` + `branch` + a `-d` flag, parks by design. **Reshape the command — never re-request it.** (The
78
- boundary half of `spec-seat`'s discriminator.)
76
+ - **The gate reads the command the shell would run, not its words.** A quoted search pattern naming a
77
+ boundary operation is data; the same words handed to an interpreter, or carrying a substitution, are read
78
+ as something that could run, and park. **Reshape the command — never re-request it.** (The boundary half
79
+ of `spec-seat`'s discriminator.)
79
80
 
80
81
  **READS ONLY. Never write to the platform's store.**
81
82
 
@@ -393,8 +394,7 @@ is the look of a record with none of a record's properties.
393
394
  § This repository's rails (repository-owned) says (when it names no route, ask the human once and suggest
394
395
  recording the answer there); one branch, one PR from any seat. **If one is already open, the push is enough.** These three git commands are your own close-out
395
396
  lane and they are gated and receipted like any other publish. **The push command must be the ENTIRE
396
- command** — a leading `cd` disqualifies it — and keep git-verb words out of any echo label you write
397
- around it; the deny layer matches TEXT, not parsed verbs.
397
+ command** — a leading `cd` disqualifies it.
398
398
  6. **Sweep for stale beliefs BY MEANING, NEVER BY PHRASE — and sweep the SIBLINGS that restate a rule, not
399
399
  just the rule's own home.** A sweep keyed on wording only finds the wording it thought of. Ask what each
400
400
  instruction *depends on being true* — which file it names, which lane it assumes exists, who it thinks
@@ -35,9 +35,12 @@ else's job.
35
35
  Your seed carries **no beliefs about the pipeline, and that is deliberate** — but it should carry an
36
36
  **inventory**, because you cannot review what you cannot find:
37
37
 
38
- - the **topic**, the **branch**, and the **diff range** (`{base}...<branch>` — `{base}` is the base branch
39
- `docs/_meta/engineering-loop.md` § This repository's rails (repository-owned) names, or the remote's
40
- default when it names none);
38
+ - the **topic**, the **branch**, and the **diff range** (`origin/{base}...<branch>` — `{base}` is the base
39
+ branch `docs/_meta/engineering-loop.md` § This repository's rails (repository-owned) names, or the
40
+ remote's default when it names none; it is read from the remote's copy, because a local base branch can
41
+ sit behind it and pull another effort's commits into the range);
42
+ - **one more range per further repository the run wrote**, with that repository's path — by its release
43
+ tags when the run released it mid-run, since its branch is merged by then;
41
44
  - **the brief** (`00-ignition-brief.md`) — its sections down to § Platform state, read as claims like the
42
45
  specs, and **never the coordinator's sections after it** (its beliefs, its close-out, its kick);
43
46
  - **every numbered spec path** — you read them as claims, not facts;
@@ -67,7 +70,10 @@ instrument, and a reader who takes it for a cold one over-trusts its independenc
67
70
  3. **The working docs** in `docs/working/` — the narrative: what was tried, what failed, what changed.
68
71
  4. **The tracker** — `project-status.md`, the coordinator's journal: rulings and their reasoning, recon
69
72
  corrections, incidents.
70
- 5. **THEN the diff** — `git diff {base}...<pipeline-branch>`, plus `git log --oneline {base}..<pipeline-branch>`.
73
+ 5. **THEN the diff** — `git diff origin/{base}...<pipeline-branch>`, plus `git log --oneline
74
+ origin/{base}..<pipeline-branch>`; and the same pair for each further range your seed names, run inside
75
+ that repository. Read the two sides of a seam together: what one repository ships and what the other
76
+ consumes are one claim.
71
77
 
72
78
  **Read the artifacts before the code, and the code before you conclude.** Reading the diff first makes
73
79
  you review a patch; reading the claims first makes you review whether the pipeline did what it said.
@@ -278,24 +278,19 @@ Ask what the park is protecting:
278
278
  - **A park on your own legitimate in-worktree work** — **re-request it** (no self-imposed cap, no
279
279
  workaround, no silent giving-up) AND disclose ("blocked on X, re-requested N times"). A parked call is
280
280
  the platform's turn, not your failure; routing around it hides the defect the park is surfacing.
281
- - **A park on a boundary command** (push to the base branch, force-push, branch delete — or a command
282
- whose *text* merely tripped the scanner) — **never re-request; reshape the command.**
283
- **A search is data only in one shape:** a quoted literal pattern given to a read-only search tool (`rg`,
284
- `grep`, `git grep`, `Select-String`, `findstr`), with no `$`, no backtick, no interpreter and no `xargs`
285
- in the pipeline. Any other command carrying boundary words parks — search for the symbol, not the verb.
286
- **THE SCANNER MATCHES TEXT, NOT PARSED VERBS, AND THIS IS THE MOST-PAID FENCE IN THE CEREMONY.** It
287
- fires on read-only commands a careful seat runs to PROVE its work: an `echo` label reading
288
- `=== remote tip ===` on a `git status`/`git log` block, or `git branch -r --contains <sha>` — a branch
289
- **listing** — tripping the *"branch deletion is human-only"* backstop. **So the discipline belongs in
290
- the prose you write around a command, not only in the command:** no git-verb vocabulary (push, remote,
291
- force, reset, branch delete) in any `echo`, comment, `--description` or section label. For upstream
292
- verification use `git log origin/<branch>..HEAD | wc -l` and `git status -sb`, which carry no colliding
293
- noun.
281
+ - **A park on a boundary command** (push to the base branch, force-push, branch delete — or a command the
282
+ gate read as one) — **never re-request; reshape the command.**
283
+ **THE GATE READS THE COMMAND THE SHELL WOULD RUN, NOT ITS WORDS.** What parks is the operation — a
284
+ publish, a remote change, a branch deletion, a merge — at any depth: wrapped, chained, or named inside
285
+ another program's words. An `echo` label naming a git verb, a branch listing and a quoted search pattern
286
+ are data to it. **They stop being data when something on the line could run them:** a shell or an
287
+ interpreter anywhere on the line, or a `$`, a backtick or an `xargs` in the pipeline. So keep a proof
288
+ command plain — one program, quoted literals — and give a search to a read-only search tool (`rg`,
289
+ `grep`, `git grep`, `Select-String`, `findstr`).
294
290
  **RESHAPE MEANS A DIFFERENT COMMAND, NEVER A DISGUISED ONE — NEVER ROUTE AROUND A REFUSAL.** Rewriting a
295
- path with a glob or a quote so the scanner no longer sees the word it matched (a `?` in place of one
296
- letter of a folder name) defeats every text-scanned rule at once, and the same disguise passes a real
297
- boundary command. When the only way through is to hide the word, the park is a false one: disclose it,
298
- with the verbatim command and park text, and ask.
291
+ path with a glob or a quote so a word is no longer seen (a `?` in place of one letter of a folder name)
292
+ is a disguise, and the same disguise passes a real boundary command. When the only way through is to
293
+ hide the word, the park is a false one: disclose it, with the verbatim command and park text, and ask.
299
294
  - **A POLICY WALL is none of the three.** If the refusal says `walled-by-policy`, **an approval cannot
300
295
  grant it** and re-requesting is walking through a known fail-open. The two routes are **reshape the work**
301
296
  (do it by a path the policy allows — often: hand the text to a seat whose scope covers it) or
@@ -325,9 +320,11 @@ Plain text, BEFORE any plan-approval presentation:
325
320
 
326
321
  ```
327
322
  PLAN TLDR ({your assignment}), recon done against HEAD {sha}, anchors {verified fresh / drift: …}:
328
- BELIEFS: HEAD {sha}; dirty files I see: {list, whose}; tool versions: {the harness, the runtimes};
329
- baseline suites: {cited from the brief's § Baselines, per lane: N (+known pre-existing reds); a lane it
330
- does not name, measured before you edit}.
323
+ BELIEFS: HEAD {sha}; dirty files I see: {list, whose}; tool versions: {the harness, the runtimes, and the
324
+ model and effort this session is running on}; baseline suites: {cited from the brief's § Baselines, per
325
+ lane: N (+known pre-existing reds); a lane it does not name, measured before you edit}.
326
+ {when your row names a further repository, one line each:}
327
+ ALSO WRITING {repository}: commit {sha} on {branch}; dirty files there: {list, whose}.
331
328
  CONTROLS: for each probe or pin I will build — its positive control, and what would make it FAIL.
332
329
  {one line each: "probe X — control: {the case that must go red}; fails when: {…}"}
333
330
  {5-10 lines: what you will do, anchored to real files; the surfaces you will touch; departures flagged.}
@@ -343,9 +340,18 @@ coordinator with your question text and what the re-raise keys on (the two-headi
343
340
  **BELIEFS sha — ONE line.** The build-go HEAD check scans for `HEAD` + a 40-hex token **on the same line**
344
341
  (fenced or quoted is fine); a markdown break between them reads as a malformed sha and **refuses the
345
342
  flip** (fail-closed by design). Paste the verbatim `git rev-parse HEAD` output, never hand-transcribe, no
346
- wrapping. **Put the BELIEFS line near the top of BOTH `plan.md` and `tldr.md`**, and keep it current on
347
- every revision: a checker that takes the first `HEAD <sha>` it meets reads an old line before a new one, and
348
- quoted command output carrying another sha above it is read as your belief.
343
+ wrapping. **Put the BELIEFS line near the top of BOTH `plan.md` and `tldr.md`. When your HEAD moves,
344
+ restate it by appending a new `BELIEFS:` line, never by editing the old one:** the check reads the newest
345
+ line that carries `BELIEFS`, and with none it takes the first `HEAD <sha>` it meets, so quoted command
346
+ output carrying another sha is then read as your belief.
347
+
348
+ **A further repository's commit goes on its own `ALSO WRITING` line, beneath the BELIEFS line and never
349
+ beside the word `HEAD`:** the BELIEFS line carries one sha, this repository's, and your coordinator diffs
350
+ the other line against that repository's branch.
351
+
352
+ **The model and effort in that line are the ones you can read, never the brief's copied back.** The brief's
353
+ `## Birth` names the pair every seat starts on, and a seat that finds itself on another says so here, before
354
+ its plan. Write *not visible from here* for a part your session cannot see.
349
355
 
350
356
  **Cite symbols, not line numbers.** In anything that outlives a commit — a TLDR, a working doc, a handover
351
357
  — **name the symbol and use the line as a hint.** A line number is a comment, not an address; an anchor
@@ -424,15 +430,34 @@ doorbell with no follow-through**; if you receive one bare, retry anyway and say
424
430
  disqualifier is **anything else on the line**, and a leading `cd` — harmless on every OTHER git call you
425
431
  make — disqualifies a push (the FORM check reads the whole command string). Qualifying forms, exactly:
426
432
  first `git push -u origin <your-branch>`, later `git push origin <your-branch>` (`--set-upstream` also
427
- qualifies). A push without a refspec parks by design.
433
+ qualifies). A push without a refspec parks by design. This is your push in THIS repository; a further
434
+ repository's push has its own form, below.
428
435
  - **EVERY GIT COMMAND GOES ALONE — no shell metacharacters.** The FORM check reads the whole command
429
436
  string, so chaining, redirects or substitution disqualify it: `git add … && git commit … && git push …`
430
- parks where the same three commands, sent one at a time, flow unattended. Keep the word "push" out of
431
- echo text — the deny layer matches text, not parsed verbs.
437
+ parks where the same three commands, sent one at a time, flow unattended.
432
438
  - Prefer native read/glob/grep tools for reads; a shell read flows with its row like any other
433
439
  non-boundary call. On a periscope 1.4.0 runner they reach anything outside your workspace except
434
440
  credential material; on an older runner Read is jailed to your workspace, so read a file outside it —
435
441
  the runner's installed package, say — with a shell command.
442
+ - **WHEN YOUR ROW NAMES A FURTHER REPOSITORY, YOU WORK IN TWO TREES, AND EACH KEEPS ITS OWN RULES.** Most
443
+ rows name none, and nothing in this bullet applies to them.
444
+ - **Your home is this repository:** your spec, board, plan and working doc stay here, and nothing of
445
+ the pipeline's record is ever written in the other repository.
446
+ - **The other repository takes your code, in your own tree of it — never its owner's checkout.**
447
+ Hosted, your seed names the environment variable holding that tree's path: read it, never build the
448
+ path. Hand-cranked, your prompt names the path. Read the branch in the tree itself; it need not carry
449
+ this repository's branch name.
450
+ - **This section applies once per repository:** an explicit staging list and its `verify-staged`
451
+ receipt, run inside that tree; its own commit; and before its push, the whole of ITS gate — the suite
452
+ and checks its own contributing rules name, which this repository's lanes never run.
453
+ - **Its commit and pull-request text follow ITS rules:** no effort ids, no board or seat words. Where it
454
+ checks pull requests, open a DRAFT one at your first push and read its checks after every push.
455
+ - **Push from inside that tree — `cd "$TREE" && git push origin <branch>`, and nothing else on the
456
+ line,** with the variable your seed names in `$TREE`'s place (hand-cranked, the path your prompt
457
+ names). It is the one push that takes a leading `cd`. Keep the variable out of the push itself:
458
+ `git -C "$TREE" push` cannot be read, and waits for a person. Your push may wait for one anyway: wait,
459
+ never reshape it, and report a refusal.
460
+ - **You never merge, tag or publish there.** A release is a person's act, at the pipeline's `step`.
436
461
  - **Codegen only through the command `patterns/codegen.md` § Running codegen names** (when the repo has
437
462
  one) — never hand-write a generated folder.
438
463
  - **Never improvise a qualifying path in.** If a push parks and the remedy you can think of is touching a
@@ -462,7 +487,9 @@ FINAL TLDR — {your assignment}. Built on HEAD {sha}; {hand-cranked: committed
462
487
  (f) EXPLICIT STAGING LIST — the exact list `verify-staged` was (hand-cranked) or will be (hosted)
463
488
  run over; a path not on this list is a path nobody will notice missing — + the STAGING
464
489
  VERIFIED receipt, or hosted "commit HELD awaiting the commit call" + which dirty files are NOT
465
- mine. SESSION ID + NAME.
490
+ mine. A seat that wrote a further repository gives a list and a receipt PER REPOSITORY, each
491
+ under its repository's name, and in (b) each repository's summaries under its own name.
492
+ SESSION ID + NAME.
466
493
  ```
467
494
 
468
495
  ## Close-out — the order is law