@naswerks/engineering-loop 0.6.0 → 0.7.1
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.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +59 -0
- package/package.json +1 -1
- package/references/docs-workflow.md +1 -1
- package/references/engineering-loop.md +32 -25
- package/skills/spec-coordinator/SKILL.md +48 -22
- package/skills/spec-retro/SKILL.md +4 -6
- package/skills/spec-seat/SKILL.md +42 -12
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "naswerks",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.1",
|
|
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,65 @@ version is the one in `package.json` and `.claude-plugin/plugin.json`, which mus
|
|
|
5
5
|
|
|
6
6
|
## [Unreleased]
|
|
7
7
|
|
|
8
|
+
## [0.7.1] - 2026-10-04
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- `spec-coordinator` learns the control plane's verbs of 2026-10-04: `seat_spawn` defaults its host to the one
|
|
13
|
+
carrying the coordinator's own session and takes `model` and `effort` overrides; `accept_plan` and `accept`
|
|
14
|
+
take `answeringActId`, so one act rules and closes a question — and an act that names no question closes
|
|
15
|
+
none; the coordinator reads for itself what the owner used to check (`seat_timeline`, `needs_you`, argless
|
|
16
|
+
`seat_usage`, `seat_parks` with a charge's `seatId` or `all: true`, the roster's host and `re-raises`); it
|
|
17
|
+
commits its tracker itself, after each reap and never in a seat's commit call; and, hosted, `finish` is its
|
|
18
|
+
last call — the pipeline moves to `reviewing` and the PR's merge closes it.
|
|
19
|
+
|
|
20
|
+
### Upgrading from 0.7.0
|
|
21
|
+
|
|
22
|
+
Take the release (`claude plugin marketplace update engineering-loop`, then
|
|
23
|
+
`claude plugin update naswerks@engineering-loop --scope <scope>`, and a new session). A patch: no loop text
|
|
24
|
+
changed, nothing is restamped, and a hand-cranked repository's coordinator acts as before — every change but
|
|
25
|
+
the tracker's commit discipline is the hosted plane's. A control plane older than 2026-10-04 refuses the new
|
|
26
|
+
arguments and verbs by name.
|
|
27
|
+
|
|
28
|
+
## [0.7.0] - 2026-10-01
|
|
29
|
+
|
|
30
|
+
### Changed
|
|
31
|
+
|
|
32
|
+
- **The hosted plane runs the hand-cranked ceremony: one file, two voices, a poke each way.** A seat writes
|
|
33
|
+
its `plan.md` and `tldr.md` with its own tools and posts each by `path` the first time — the control plane
|
|
34
|
+
reads the file from the seat's runner (periscope 1.4.0's `workspace_read`) — then with nothing. The
|
|
35
|
+
coordinator appends its ruling to the seat's `tldr.md` under its coordinator-voice heading and calls
|
|
36
|
+
`accept_plan`, `accept` or `callout` with a one-line summary; the control plane mirrors the file before it
|
|
37
|
+
records the act, and the seat is pointed at the section added. The act still decides. A runner older than
|
|
38
|
+
periscope 1.4.0 keeps the old form: the seat posts `content`, and the verb carries the coordinator's words.
|
|
39
|
+
`spec-seat`, `spec-coordinator` and `engineering-loop.md` § The blackboard say so.
|
|
40
|
+
- `spec-coordinator`: `seat_acts` is the coordinator's census (its mint carries `acts:read`, and
|
|
41
|
+
`spec-retro` says so too); `read_blackboard` returns a window of a file or only the sections new since a
|
|
42
|
+
revision; `accept` carries the commit call, and an acceptance written into the seat's file binds to that
|
|
43
|
+
revision.
|
|
44
|
+
- `spec-seat`: a search is data only as a quoted literal given to a read-only search tool, with no `$`, no
|
|
45
|
+
backtick, no interpreter and no `xargs` in the pipeline. On a periscope 1.4.0 runner the native reads
|
|
46
|
+
reach outside the workspace, credential material excepted; on an older one a file outside it is read with
|
|
47
|
+
a shell command.
|
|
48
|
+
|
|
49
|
+
### Added
|
|
50
|
+
|
|
51
|
+
- **`## [seat·…] ABOUT TO PARK`, the seat's third anchor:** the next call waits on a human, and here it is —
|
|
52
|
+
the verbatim command and what it waits on, posted before the call runs. Non-staling, like `HOLDING`.
|
|
53
|
+
- Both skills: a control-plane verb that fails with a transport error (`ECONNRESET`) is called once more,
|
|
54
|
+
then disclosed; a refusal has a name and a dropped connection does not.
|
|
55
|
+
|
|
56
|
+
### Upgrading from 0.6
|
|
57
|
+
|
|
58
|
+
1. Take the release: `claude plugin marketplace update engineering-loop`, then
|
|
59
|
+
`claude plugin update naswerks@engineering-loop --scope <scope>`, and a new session.
|
|
60
|
+
2. Re-copy the loop text of `references/engineering-loop.md` into `docs/_meta/engineering-loop.md` — § The
|
|
61
|
+
blackboard changed — keeping your repository-owned sections. Then `init refresh` restamps both copies; it
|
|
62
|
+
never touches loop text.
|
|
63
|
+
3. A control plane that reads the seat anchors treats `## [seat·…] ABOUT TO PARK` as it treats
|
|
64
|
+
`## [seat·…] HOLDING` — a post-acceptance append that does not stale the acceptance. Until it does, the
|
|
65
|
+
append stales one.
|
|
66
|
+
|
|
8
67
|
## [0.6.0] - 2026-09-29
|
|
9
68
|
|
|
10
69
|
### Changed
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@naswerks/engineering-loop",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.1",
|
|
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.
|
|
1
|
+
<!-- naswerks-loop: version=0.7.1 -->
|
|
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-*`
|
|
@@ -253,26 +253,31 @@ repo files, staged at close-out; the coordinator appends rulings with its own fi
|
|
|
253
253
|
human's relay is a one-line nudge each way).
|
|
254
254
|
|
|
255
255
|
<!-- control-plane-specific -->
|
|
256
|
-
**Hosted —
|
|
257
|
-
`post_plan` / `post_tldr`
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
256
|
+
**Hosted — the same files, read by the controller.** A seat edits its two files with its own tools and
|
|
257
|
+
**pokes**: `post_plan` / `post_tldr` with the file's `path` inside its workspace the first time, then with
|
|
258
|
+
nothing — the control plane reads the file from the seat's runner and mirrors it (verbs under `acts:write`,
|
|
259
|
+
so a witness ticket structurally cannot post). A runner older than periscope 1.4.0 cannot be read; there the
|
|
260
|
+
seat carries its bytes as `content`. Everything identifying is **server-derived** — pipeline and seat from
|
|
261
|
+
the verified ticket, and **the rev** (newest + 1). *A rev nobody can misstate cannot regress by accident.*
|
|
262
|
+
The append-only guard is what survives the transport: the ladder only climbs, a revision that drops a section
|
|
263
|
+
is refused, and the same rev with different bytes is refused — so the mirror **cannot be clobbered or rewound
|
|
264
|
+
by a caller that lies, even though it can be fed.**
|
|
265
|
+
|
|
266
|
+
**The coordinator's voice is in the seat's file in both modes.** The coordinator appends its ruling to the
|
|
267
|
+
seat's `tldr.md` under its coordinator-voice heading, then calls its verb (`accept_plan` · `accept` ·
|
|
268
|
+
`callout`) with a one-line summary: the control plane mirrors the file as a revision in the coordinator's
|
|
269
|
+
voice BEFORE it records the act, and the seat is pointed at the section added. **The file says what was
|
|
270
|
+
said; the ledger says what was decided** — a question closes only on the coordinator's act, so a seat typing
|
|
271
|
+
a coordinator-voice heading into its own TLDR closes nothing, and a revision in the coordinator's voice never
|
|
272
|
+
counts as the seat asking. `callout` **refuses when the charge has no live session** — a coordinator must
|
|
269
273
|
`seat_spawn` before it can rule — and reports **"RULING RECORDED, NOT DELIVERED"** in those words if the
|
|
270
|
-
transport drops it.
|
|
274
|
+
transport drops it. Where the coordinator cannot write the seat's file (a runner older than 1.4.0, a seat in
|
|
275
|
+
its own workspace), the verb carries the words, as before.
|
|
271
276
|
|
|
272
|
-
The coordinator-voice block (
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
277
|
+
The coordinator-voice block (the coordinator writes it in both modes; hand-cranked there is no rev counter,
|
|
278
|
+
so the heading is `## COORDINATOR RULING (plan — {verdict})`; the stable grep prefix
|
|
279
|
+
`## COORDINATOR RULING` is the contract in both modes, and an older board's `## PARENT RULING` is read as
|
|
280
|
+
the same heading):
|
|
276
281
|
|
|
277
282
|
```
|
|
278
283
|
## COORDINATOR RULING (plan rev N — {accept | accept-with-riders | blocking-precondition})
|
|
@@ -286,19 +291,21 @@ Go build. Fold the riders in — no re-approval round-trip.
|
|
|
286
291
|
|
|
287
292
|
Callouts and nudges append as `## COORDINATOR NOTE` (actor-suffixed when known, e.g. `(operator)`).
|
|
288
293
|
|
|
289
|
-
**The seat's own
|
|
294
|
+
**The seat's own three anchors:**
|
|
290
295
|
|
|
291
296
|
```
|
|
292
297
|
## [seat·{slug} · run {id}] CLOSE-OUT RECEIPT <- after the push
|
|
293
298
|
## [seat·{slug} · run {id}] HOLDING <- "I have pushed and I am waiting"
|
|
299
|
+
## [seat·{slug} · run {id}] ABOUT TO PARK <- "the next call waits on a human, and here it is"
|
|
294
300
|
```
|
|
295
301
|
|
|
296
|
-
**A question heading, a HOLDING and a close-out receipt are ALL non-staling** — the gates
|
|
297
|
-
acceptance to the accepted CONTENT, not to the revision number, so appending your own *state* leaves
|
|
298
|
-
intact. Only **new content** stales. A seat that has pushed and is waiting is otherwise indistinguishable
|
|
302
|
+
**A question heading, a HOLDING, an ABOUT TO PARK and a close-out receipt are ALL non-staling** — the gates
|
|
303
|
+
bind an acceptance to the accepted CONTENT, not to the revision number, so appending your own *state* leaves
|
|
304
|
+
it intact. Only **new content** stales. A seat that has pushed and is waiting is otherwise indistinguishable
|
|
299
305
|
from a seat that has done nothing, and a coordinator reading a wake led by its own acceptance concludes
|
|
300
|
-
there is nothing to rule — the HOLDING anchor is what prevents that
|
|
301
|
-
whatever seat you are — it is a protocol anchor,
|
|
306
|
+
there is nothing to rule — the HOLDING anchor is what prevents that, and ABOUT TO PARK does the same for a
|
|
307
|
+
seat the gate is holding. The token is the literal `seat·` whatever seat you are — it is a protocol anchor,
|
|
308
|
+
not a description of you.
|
|
302
309
|
|
|
303
310
|
### Questions ride the same blackboard
|
|
304
311
|
|
|
@@ -73,36 +73,56 @@ the tracker exists and cut Prompt #1. **Step 0 still applies.**
|
|
|
73
73
|
## Your hands
|
|
74
74
|
|
|
75
75
|
**`read_blackboard` first, always** — argless it is your DAY-ONE SWEEP and your roster: every seat you
|
|
76
|
-
decide for, its state, and its newest tldr rev. With a seat id it returns that seat's
|
|
77
|
-
|
|
76
|
+
decide for, its state, and its newest tldr rev. With a seat id it returns that seat's tldr (or
|
|
77
|
+
`kind: plan`): whole, a window of it (`offset`), or only the sections new since a revision (`sinceRev`) —
|
|
78
|
+
read what changed, not the whole conversation again. In a shared workspace the seat's `tldr.md` is also a
|
|
79
|
+
file you read with your own tools. Hand-cranked, your tools are normal file tools on the blackboard files
|
|
80
|
+
plus the human relay.
|
|
78
81
|
|
|
79
82
|
<!-- control-plane-specific -->
|
|
80
83
|
**The five that reach a seat, and what each one actually is:**
|
|
81
84
|
|
|
82
85
|
| Verb | What it does | The part that bites |
|
|
83
86
|
|---|---|---|
|
|
84
|
-
| `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` |
|
|
85
|
-
| `accept_plan` | The verdict act: `accept` · `accept-with-riders` · `blocking-precondition`, **and NOTHING ELSE carries a go** — and
|
|
86
|
-
| `accept` | The rev-bound FINAL receipt | It binds to the seat's CURRENT tldr revision, so if the seat posts 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 |
|
|
87
|
+
| `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 |
|
|
88
|
+
| `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 |
|
|
89
|
+
| `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` |
|
|
87
90
|
| `complete` | The reap, and it is HONEST | It re-reads the seat and reports ok only after the terminal state is OBSERVED |
|
|
88
|
-
| `callout` | **THE ONLY WAY YOU REACH A CHARGE** (besides the
|
|
91
|
+
| `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 |
|
|
89
92
|
|
|
90
|
-
**A QUESTION IS CLOSED BY AN ACT, NOT BY A FILE.** Answer a charge's question with a `callout`
|
|
91
|
-
|
|
92
|
-
the
|
|
93
|
+
**A QUESTION IS CLOSED BY AN ACT, NOT BY A FILE.** Answer a charge's question with a `callout` — or an
|
|
94
|
+
`accept_plan` / `accept` that rules at the same time — carrying that post's act id as `answeringActId`:
|
|
95
|
+
**that act IS the answer**, and it is the only thing that stops the re-raise. An act without one steers or
|
|
96
|
+
rules and closes nothing — a forgotten id costs one re-raise — and **nothing you write into a file
|
|
93
97
|
closes anything**: the latch reads the ledger, so a ruling you never sent is a question still open no
|
|
94
98
|
matter what any blackboard says.
|
|
95
99
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
100
|
+
**THE COORDINATOR'S APPEND, HOSTED.** In a shared workspace a seat that posts its `tldr.md` by `path` shares
|
|
101
|
+
the file with you: append your ruling with your own file tools under a coordinator-voice heading, then call
|
|
102
|
+
the verb. The control plane reads the file, mirrors it as the next revision in YOUR voice before it records
|
|
103
|
+
your act, and points the seat at the section you added; the reply's `file:` line says what was mirrored. A
|
|
104
|
+
seat that posts bytes (a runner older than periscope 1.4.0) or works in its own workspace keeps the old form:
|
|
105
|
+
the verb carries your words. **The act still decides** — a section closes nothing on its own.
|
|
106
|
+
|
|
107
|
+
**`seat_acts` IS YOUR CENSUS.** Your mint carries `acts:read`: take counts, human touches and receipts from
|
|
108
|
+
the ledger, never from a seat's report about itself, and name the lane any count you publish came from.
|
|
109
|
+
Beside it, read for yourself what the owner used to check for you: `seat_timeline` (a seat's two lanes —
|
|
110
|
+
*the reap ended the process* is the runner's `ended` row, cause `stop_requested`, after your reap act),
|
|
111
|
+
`needs_you` (the owner's Needs-you tab, Active and History), argless `seat_usage` (every seat's spend and
|
|
112
|
+
the pipeline's total), `seat_parks` with a charge's `seatId` or `all: true` (its parks, and the rows that
|
|
113
|
+
ADMITTED a push), and the argless roster's host and `re-raises` per seat.
|
|
101
114
|
|
|
102
115
|
**WAKES:** you are woken when a charge posts its plan or its tldr, and a one-line pointer rides the wake —
|
|
103
|
-
|
|
116
|
+
the revision and the sections it added. Read what is new (`read_blackboard` with `sinceRev`, or the file) and
|
|
117
|
+
answer on first receipt rather than spending a round-trip.
|
|
104
118
|
|
|
105
|
-
**
|
|
119
|
+
**A verb that fails with a transport error** (`ECONNRESET`, a socket closed under the call) is the transport,
|
|
120
|
+
not a refusal: call it once more, and journal it if it fails again. A refusal has a name; a dropped
|
|
121
|
+
connection does not.
|
|
122
|
+
|
|
123
|
+
**THE TRACKER IS YOURS ALONE.** Advance it at every seat boundary and **commit it yourself — after each
|
|
124
|
+
reap, before the next spawn — never in a seat's commit call**, so it is never frozen between an acceptance
|
|
125
|
+
and a seat's close-out. Never reconstruct it at the close.
|
|
106
126
|
|
|
107
127
|
## The loop (per seat)
|
|
108
128
|
|
|
@@ -329,6 +349,12 @@ read the board and answer on first receipt rather than spending a round-trip.
|
|
|
329
349
|
is not reversible by the seat that does it, and a check the human runs afterwards confirms the damage
|
|
330
350
|
instead of preventing it. **A live-check row is confirmation; this is prevention.** Never hold the
|
|
331
351
|
run waiting for a human to verify this first — you have the list, so you are the gate.
|
|
352
|
+
8. **Hosted, `finish` is your last call** — once every other seat, P included, is reaped. Pass the PR's
|
|
353
|
+
URL: it records the pipeline done with evidence it reads from the ledger, moves it to `reviewing`,
|
|
354
|
+
closes your own session and ends your process, and the PR's merge closes the pipeline. **Nothing you
|
|
355
|
+
send after it is admitted** — commit your tracker and report first. It refuses, recording nothing,
|
|
356
|
+
while any seat is still live or when none shipped. Hand-cranked there is no `finish`; the human closes
|
|
357
|
+
the effort.
|
|
332
358
|
|
|
333
359
|
**The human hand-tests.** Live verification is the human's role, not a seat's claim — when a slice
|
|
334
360
|
ships something clickable, tell the human concretely what to drive (the 2-3 highest-value clicks), and
|
|
@@ -342,10 +368,9 @@ so read them as run-time obligations, not close-out ones:
|
|
|
342
368
|
|
|
343
369
|
- **Your zero-touch / ceremony claims must cite an ARGLESS sweep**, never a verb list you picked
|
|
344
370
|
yourself. **Check on day one that the sweep is runnable at your run's scale — and that it is runnable
|
|
345
|
-
BY SOMEONE.** Hosted,
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
suspected.
|
|
371
|
+
BY SOMEONE.** Hosted, `seat_acts` is that sweep and your ticket carries it; hand-cranked, check that the
|
|
372
|
+
retro seat, a witness or an operator can produce it. If none can, that is a day-one escalation, not a
|
|
373
|
+
close-out discovery — a verb-filtered audit can only confirm what you suspected.
|
|
349
374
|
- **A rev-bound acceptance goes stale on a post-acceptance append of NEW CONTENT — from either actor.**
|
|
350
375
|
The receipt covers the tldr rev + HEAD it was written against; a later content post invalidates it and
|
|
351
376
|
the cheap repair is an **argless re-accept sent WITH the retry order in the same act**. A re-accept with
|
|
@@ -541,8 +566,9 @@ still open, however good the prose; the seat is still holding and the re-raise i
|
|
|
541
566
|
**The blackboard append.** Hand-cranked, the seat's `plan.md` and `tldr.md` are live FILES at
|
|
542
567
|
`docs/research/{topic}/sessions/{spec-slug}/` — read the TLDR there with normal file tools instead of
|
|
543
568
|
asking for a paste (`read-full-plan` = read `plan.md`, a pull, never force-fed). Deliver every ruling by
|
|
544
|
-
**APPENDING it verbatim to the seat's `tldr.md`**, right under the questions it answers. Hosted,
|
|
545
|
-
|
|
569
|
+
**APPENDING it verbatim to the seat's `tldr.md`**, right under the questions it answers. Hosted, the same
|
|
570
|
+
append, then the verb: the control plane mirrors the file before your act and points the seat at the
|
|
571
|
+
section (§ Your hands, the coordinator's append).
|
|
546
572
|
|
|
547
573
|
**Anchor grammar (canonical — the witness greps these):** rulings land under
|
|
548
574
|
`## COORDINATOR RULING (plan — {verdict})` hand-cranked, `## COORDINATOR RULING (plan rev N — {verdict})`
|
|
@@ -45,12 +45,10 @@ human and exception rows included. **Start every audit with it: "what happened t
|
|
|
45
45
|
not ask about."** A verb-filtered read can only confirm suspicions, never surface surprises — a run can
|
|
46
46
|
certify itself "zero-touch" while `approved_by_human` rows sit one unqueried verb away.
|
|
47
47
|
|
|
48
|
-
**Who holds the instrument, on the hosted plane:** a `retro` seat's ticket
|
|
49
|
-
`seat_acts` argless IS your sweep
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
effort's witness, or a credentialed operator. **Say which instrument produced every count in this
|
|
53
|
-
document** — a number whose lane you cannot name is testimony, not an audit.
|
|
48
|
+
**Who holds the instrument, on the hosted plane:** a `retro` seat's ticket and a `coordinator` ticket both
|
|
49
|
+
carry `acts:read`, so `seat_acts` argless IS your sweep whichever of the two writes this retro. **Say which
|
|
50
|
+
instrument produced every count in this document** — a number whose lane you cannot name is testimony, not
|
|
51
|
+
an audit.
|
|
54
52
|
|
|
55
53
|
**If the argless sweep is not runnable at your run's scale, that is a day-one escalation, not a
|
|
56
54
|
close-out discovery.** A few thousand rows can exceed the lane's page budget; you cannot retroactively
|
|
@@ -98,16 +98,26 @@ that is your scope — do not widen it on the theory that more reading is safer.
|
|
|
98
98
|
`plan.md` (the full plan document) and `tldr.md` (the chat: your PLAN TLDR, any mid-build updates, the
|
|
99
99
|
FINAL TLDR — **append, never overwrite**) are FILES, not just chat text.
|
|
100
100
|
|
|
101
|
+
**ONE CEREMONY IN BOTH MODES: you write your file, then you poke; your coordinator appends its ruling to the
|
|
102
|
+
SAME file, then pokes you. Nobody pastes a document into a message.**
|
|
103
|
+
|
|
101
104
|
- **Hand-cranked:** create them under `docs/research/{topic}/sessions/{slug}/` at plan time and end your
|
|
102
105
|
turn announcing the path. The coordinator reads `tldr.md` with normal file tools and APPENDS its ruling
|
|
103
106
|
under `## COORDINATOR RULING`, so read the answer in your own file and proceed. The full plan is PULL — it is
|
|
104
107
|
read only on a read-full-plan verdict; never paste it into chat. (If your harness has a plan-approval
|
|
105
108
|
mode that forbids writes: give the chat summary, get the human's approve, THEN post and stop.)
|
|
106
|
-
- **Hosted (a seat inside a pipeline):** the same two files are yours to edit with normal file tools,
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
109
|
+
- **Hosted (a seat inside a pipeline):** the same two files are yours to edit with normal file tools. **Write,
|
|
110
|
+
then poke:** the first time, call `post_tldr` with `path` — the file's path inside your workspace, relative
|
|
111
|
+
to its root — and the control plane reads the file from your runner; after that, call `post_tldr` with
|
|
112
|
+
NOTHING and it reads the same path again (`post_plan` the same way). It records a revision and wakes your
|
|
113
|
+
coordinator with ONE LINE naming the rev and the sections you added. **Your coordinator's ruling arrives
|
|
114
|
+
IN YOUR FILE** — it appends under its coordinator-voice heading, and you are poked with one line naming
|
|
115
|
+
the section (*"Your tldr.md rev 5 adds `## COORDINATOR RULING (plan rev 1 — accept)`"*). Read it with
|
|
116
|
+
your own file tools; it is never pasted to you.
|
|
117
|
+
**If the post answers `host-lacks-workspace-read`** (a runner older than periscope 1.4.0) **or asks for
|
|
118
|
+
`content`** (a control plane that predates reading files), it cannot read your workspace: pass the whole
|
|
119
|
+
file as `content` instead, and read rulings from your board (`seat_content(kind: "ruling")`) as well as
|
|
120
|
+
your file.
|
|
111
121
|
**THE FILE IS THE RECORD AND THE ROW MIRRORS IT** — one artifact row per rev carrying the whole file
|
|
112
122
|
verbatim, so the two voices stay interleaved because nothing splits them. The control plane refuses
|
|
113
123
|
`blackboard-rev-regressed` · `blackboard-shrank` · `blackboard-rev-content-mismatch` at the door: **an
|
|
@@ -194,9 +204,10 @@ question tool — the relay cannot copy it.
|
|
|
194
204
|
**An unanswered question re-raises to your coordinator on a cooldown** until a ruling lands. Asking costs
|
|
195
205
|
the pipeline a round-trip and nothing else.
|
|
196
206
|
|
|
197
|
-
**WHAT ACTUALLY CLOSES A QUESTION.** On the hosted plane **nothing
|
|
198
|
-
The latch reads the ACTS LEDGER: a ruling closes your
|
|
199
|
-
|
|
207
|
+
**WHAT ACTUALLY CLOSES A QUESTION.** On the hosted plane **nothing written into a FILE closes anything** —
|
|
208
|
+
not yours, and not your coordinator's section in it. The latch reads the ACTS LEDGER: a ruling closes your
|
|
209
|
+
question only when the coordinator's act carries your post's act id as `answeringActId`. The words arrive in
|
|
210
|
+
your file; the act is what decides. A `callout` without one steers you and closes nothing.
|
|
200
211
|
**The reason is a security property, not tidiness:** `tldr.md` is written BY YOU, so a file-side close
|
|
201
212
|
predicate is a string the audited party can type — a seat could write `## COORDINATOR RULING` into its own file
|
|
202
213
|
and switch off the very re-raise that exists to stop it waiting forever. The question is therefore split
|
|
@@ -250,6 +261,9 @@ Ask what the park is protecting:
|
|
|
250
261
|
the platform's turn, not your failure; routing around it hides the defect the park is surfacing.
|
|
251
262
|
- **A park on a boundary command** (push to the base branch, force-push, branch delete — or a command
|
|
252
263
|
whose *text* merely tripped the scanner) — **never re-request; reshape the command.**
|
|
264
|
+
**A search is data only in one shape:** a quoted literal pattern given to a read-only search tool (`rg`,
|
|
265
|
+
`grep`, `git grep`, `Select-String`, `findstr`), with no `$`, no backtick, no interpreter and no `xargs`
|
|
266
|
+
in the pipeline. Any other command carrying boundary words parks — search for the symbol, not the verb.
|
|
253
267
|
**THE SCANNER MATCHES TEXT, NOT PARSED VERBS, AND THIS IS THE MOST-PAID FENCE IN THE CEREMONY.** It
|
|
254
268
|
fires on read-only commands a careful seat runs to PROVE its work: an `echo` label reading
|
|
255
269
|
`=== remote tip ===` on a `git status`/`git log` block, or `git branch -r --contains <sha>` — a branch
|
|
@@ -266,6 +280,16 @@ Ask what the park is protecting:
|
|
|
266
280
|
The test: is the park **blocking your work** (re-request + disclose), **guarding the boundary** (reshape),
|
|
267
281
|
or **a wall** (reshape or escalate — never a click)?
|
|
268
282
|
|
|
283
|
+
**BEFORE A CALL YOU KNOW WILL PARK, SAY SO.** When your work needs a boundary command — a lane that tests the
|
|
284
|
+
park, a push your coordinator called for from a state the push bar cannot see — append
|
|
285
|
+
|
|
286
|
+
```
|
|
287
|
+
## [seat·{slug} · run {id}] ABOUT TO PARK
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
with the verbatim command and what it waits on, post, then run it. A seat held by the gate without saying so
|
|
291
|
+
looks idle to everyone watching. Like `HOLDING`, it is a state report, and it does not stale your acceptance.
|
|
292
|
+
|
|
269
293
|
**EVERY park is DISCLOSED in your next TLDR — including one you resolved yourself in seconds:** the
|
|
270
294
|
verbatim command AND the verbatim park text. A self-resolved park looks like nothing happened and leaves
|
|
271
295
|
the coordinator no signal, so the gate's false-park rate is only ever knowable from the seat that paid it.
|
|
@@ -379,7 +403,9 @@ doorbell with no follow-through**; if you receive one bare, retry anyway and say
|
|
|
379
403
|
parks where the same three commands, sent one at a time, flow unattended. Keep the word "push" out of
|
|
380
404
|
echo text — the deny layer matches text, not parsed verbs.
|
|
381
405
|
- Prefer native read/glob/grep tools for reads; a shell read flows with its row like any other
|
|
382
|
-
non-boundary call.
|
|
406
|
+
non-boundary call. On a periscope 1.4.0 runner they reach anything outside your workspace except
|
|
407
|
+
credential material; on an older runner Read is jailed to your workspace, so read a file outside it —
|
|
408
|
+
the runner's installed package, say — with a shell command.
|
|
383
409
|
- **Codegen only through the command `patterns/codegen.md` § Running codegen names** (when the repo has
|
|
384
410
|
one) — never hand-write a generated folder.
|
|
385
411
|
- **Never improvise a qualifying path in.** If a push parks and the remedy you can think of is touching a
|
|
@@ -449,9 +475,10 @@ ANCHOR, not a description of you.** A descriptive tail after the marker IS
|
|
|
449
475
|
blessed (`… CLOSE-OUT RECEIPT — addendum: the six staged, tree clean`) — an end-anchored pattern on the
|
|
450
476
|
one heading seats are told to write would be a trap that fires on ordinary prose.
|
|
451
477
|
|
|
452
|
-
**Any post-accept append that is NOT one of these
|
|
453
|
-
your coordinator's own voice — needs the argless re-accept.** The bar is content, not
|
|
454
|
-
what you are publishing still what I approved?*, and a state report is not a change of
|
|
478
|
+
**Any post-accept append that is NOT one of these five — close-out receipt, HOLDING, ABOUT TO PARK, a
|
|
479
|
+
question heading, or your coordinator's own voice — needs the argless re-accept.** The bar is content, not
|
|
480
|
+
revision: it asks *is what you are publishing still what I approved?*, and a state report is not a change of
|
|
481
|
+
work.
|
|
455
482
|
|
|
456
483
|
**FILE YOUR SESSION ARTIFACTS:** copy your final `plan.md` and `tldr.md` into
|
|
457
484
|
`docs/research/{topic}/sessions/{slug}/`. **Two files — that is the whole filing step.** Questions ride the
|
|
@@ -524,5 +551,8 @@ plane. The publish receipt is written at your turn's STOP and is structurally un
|
|
|
524
551
|
with a clean rerun builds trust, an undisclosed one destroys it.
|
|
525
552
|
- **A rule recalled from context needs re-reading at the source before it is used to refuse work.** A
|
|
526
553
|
rule already corrected on disk is the commonest thing a seat blocks itself on.
|
|
554
|
+
- **A control-plane verb that fails with a transport error** (`ECONNRESET`, a socket closed under the call)
|
|
555
|
+
is the transport, not a refusal: call it once more. If it fails again, say so in your next TLDR and carry
|
|
556
|
+
on with work that does not need it. A refusal has a name; a dropped connection does not.
|
|
527
557
|
- Your job skill is next: `spec-build` (build/fixit) · `spec-review` (the outside look) ·
|
|
528
558
|
`docs-process` (compile the living docs). Counterpart: `spec-coordinator` (the seat that arms you).
|