@techgoblin/gobstack 0.5.0-beta.8 → 0.6.0-alpha.2
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/CHANGELOG.md +54 -0
- package/README.md +161 -124
- package/VERSION +1 -1
- package/automations/drift-audit.sh +4 -4
- package/bans/layer-check.sh +10 -8
- package/bin/goblin +69 -57
- package/bin/goblin-audit +11 -13
- package/bin/goblin-bans +11 -11
- package/bin/goblin-extras +342 -0
- package/bin/goblin-init +382 -711
- package/bin/goblin-install +160 -114
- package/bin/goblin-lib.sh +234 -1
- package/bin/goblin-map +226 -21
- package/bin/goblin-mcp.js +492 -0
- package/bin/goblin-model +4 -4
- package/bin/goblin-upgrade +1 -1
- package/bin/goblin-verify +159 -145
- package/bin/goblin.js +35 -51
- package/docs/ADOPTION.md +15 -15
- package/docs/CONTRACTS.md +16 -15
- package/docs/DESIGN.md +1 -1
- package/docs/ENFORCEMENT.md +89 -90
- package/docs/FLOWS.md +1 -1
- package/docs/GLOSSARY.md +3 -3
- package/docs/GUARDRAILS.md +5 -5
- package/docs/GUIDE.md +194 -177
- package/docs/INTEGRATION.md +1 -1
- package/docs/LIMITS.md +25 -0
- package/docs/LOOP.md +12 -12
- package/docs/RE-PLAYBOOK.md +3 -3
- package/docs/ROLES.md +5 -5
- package/extras-catalogue/catalogue.tsv +42 -0
- package/extras-catalogue/payload/README.md +14 -0
- package/extras-catalogue/payload/taste-skill/taste/REFERENCE.md +3 -0
- package/extras-catalogue/payload/taste-skill/taste/SKILL.md +9 -0
- package/manifest/bans.tsv +8 -8
- package/manifest/classes.tsv +3 -3
- package/manifest/enforcement.tsv +40 -40
- package/manifest/glossary.tsv +3 -3
- package/manifest/playbooks.tsv +1 -1
- package/package.json +3 -1
- package/presets/electron-overlay.yaml +2 -2
- package/presets/fleet.yaml +8 -7
- package/presets/game.yaml +1 -1
- package/presets/research.yaml +1 -1
- package/presets/service.yaml +1 -1
- package/presets/software.yaml +1 -1
- package/skills/goblin-bootstrap/SKILL.md +2 -2
- package/templates/AGENTS.md.tmpl +8 -18
- package/templates/HANDOFF.md.tmpl +5 -5
- package/templates/agents-block.tmpl +45 -0
- package/templates/audit-waiver.tsv.tmpl +2 -2
- package/templates/boundary-waivers.tmpl +1 -1
- package/templates/checks/gate.sh.tmpl +6 -6
- package/templates/install-hooks.allowlist.tmpl +1 -1
- package/templates/ci/goblin-gate.yml.tmpl +0 -46
- package/templates/goblin.yaml.tmpl +0 -146
- package/templates/loop/decisions.tsv.tmpl +0 -1
- package/templates/loop/predicate.tmpl +0 -16
package/docs/GUIDE.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
A step-by-step guide for your first week. **Read this before the README.** The README tells you
|
|
4
4
|
what the pieces are; this tells you what to *do*, in order, and what you should see when it works.
|
|
5
5
|
|
|
6
|
-
Version: `0.
|
|
6
|
+
Version: `0.6.0-alpha.1` · Last measured: 2026-10-09 · Every command and every output below was run on a
|
|
7
7
|
real repository while writing this guide.
|
|
8
8
|
|
|
9
9
|
---
|
|
@@ -38,16 +38,16 @@ installed, three things change:
|
|
|
38
38
|
|
|
39
39
|
- A file called `HANDOFF.md` sits at the root. It is the note from the last session to the next one.
|
|
40
40
|
Any agent — or you, a month later — reads it first.
|
|
41
|
-
- A command called `goblin-verify` exists in that project. Run it and it
|
|
42
|
-
a table of rules and prints `PASS` / `FAIL` / `SKIP` for each one.
|
|
43
|
-
- The rules table
|
|
44
|
-
|
|
45
|
-
|
|
41
|
+
- A command called `goblin-verify` exists in that project (vendored at `.gob/bin/`). Run it and it
|
|
42
|
+
checks the project against a table of rules and prints `PASS` / `FAIL` / `SKIP` for each one.
|
|
43
|
+
- The config and the rules table are real files: the config is the `<!-- gob:begin --> …
|
|
44
|
+
<!-- gob:end -->` block at the top of `AGENTS.md`, and the rules table is
|
|
45
|
+
`.gob/manifest/enforcement.tsv`. Every row either names a command that can fail, or is labelled
|
|
46
|
+
`advisory`. **Nothing in between.** That is what stops the rules turning into decoration.
|
|
46
47
|
|
|
47
48
|
It is not a framework, not a service, and not a runtime. It has no server and no dependencies
|
|
48
49
|
beyond `bash`, `git`, `awk`, `sed`, `grep` and `python3`. It makes **no network call at verify
|
|
49
|
-
time** —
|
|
50
|
-
deliberately, and §8 and §11 say why.
|
|
50
|
+
time** — nothing in the v2 surface touches the network at all.
|
|
51
51
|
|
|
52
52
|
### The one idea worth holding onto
|
|
53
53
|
|
|
@@ -60,7 +60,7 @@ ships a file of things it *cannot* check (`docs/LIMITS.md`).
|
|
|
60
60
|
|
|
61
61
|
**Words this guide uses** — gate, ratchet, class, part, replay and the rest are defined in one
|
|
62
62
|
sentence each in `docs/GLOSSARY.md` (rendered from the glossary table the install ships:
|
|
63
|
-
`.
|
|
63
|
+
`.gob/manifest/glossary.tsv`).
|
|
64
64
|
|
|
65
65
|
---
|
|
66
66
|
|
|
@@ -76,10 +76,15 @@ sentence each in `docs/GLOSSARY.md` (rendered from the glossary table the instal
|
|
|
76
76
|
|
|
77
77
|
You need node ≥ 18 (for the npm shim only), beyond the row above.
|
|
78
78
|
|
|
79
|
-
**You do *not* need:** network access at verify time, or an agent running
|
|
79
|
+
**You do *not* need:** network access at verify time, or an agent running — though the `init`
|
|
80
|
+
brief is written for an agent to answer, you can fill the proposal in by hand.
|
|
80
81
|
|
|
81
82
|
**Get gobstack:**
|
|
82
83
|
|
|
84
|
+
npx @techgoblin/gobstack init # the one-shot path; installs nothing globally
|
|
85
|
+
|
|
86
|
+
or, if you want the CLI on your PATH:
|
|
87
|
+
|
|
83
88
|
npm i -g @techgoblin/gobstack
|
|
84
89
|
|
|
85
90
|
This puts **two** commands on your PATH — `gob` and `goblin`, both the same node shim over the
|
|
@@ -93,48 +98,55 @@ scripts.
|
|
|
93
98
|
**Do not install into a real project yet.** You want to see what it does before it touches
|
|
94
99
|
something you care about.
|
|
95
100
|
|
|
96
|
-
The
|
|
97
|
-
|
|
98
|
-
|
|
101
|
+
The v2 flow is **`init`**: it prints an AGENT BRIEF (what to scan, what to decide) plus the
|
|
102
|
+
schema of the proposal file, the agent (or you) writes the proposal, and `--write` validates it
|
|
103
|
+
and installs:
|
|
99
104
|
|
|
100
105
|
mkdir -p /tmp/gs-try && cd /tmp/gs-try
|
|
101
106
|
git init -b main
|
|
102
107
|
git config user.email "you@example.com"
|
|
103
108
|
git config user.name "you"
|
|
104
109
|
|
|
105
|
-
gob init --
|
|
106
|
-
|
|
110
|
+
gob init --heuristic # the brief + schema; --heuristic adds scanned hints
|
|
111
|
+
|
|
112
|
+
The brief asks for exactly four decisions — class, branch, owner email, and ONE gate command
|
|
113
|
+
that proves the repo is healthy. Write them into the proposal file (the brief names the schema;
|
|
114
|
+
a hand-written one works fine):
|
|
115
|
+
|
|
116
|
+
<!-- gob:begin (gobstack config — edit in place; the parser reads only this block) -->
|
|
117
|
+
class: software
|
|
118
|
+
branch: main
|
|
119
|
+
owner_email: you@example.com
|
|
120
|
+
gate_check_cmd: bash tests/run-tests.sh
|
|
121
|
+
<!-- gob:end -->
|
|
107
122
|
|
|
108
|
-
|
|
109
|
-
(`.github/workflows/goblin-gate.yml`). The wizard's default is **no** — nothing lands under `.github/` unless you opt in. (Outside the wizard, `gob install`'s own default is the class decides: a class whose
|
|
110
|
-
contract requires or permits the ci-gate part gets the workflow, one that forbids it never does.)
|
|
111
|
-
`--ci-gate yes|no` overrides: an explicit `no` is recorded as an opt-out (so verify reports the
|
|
112
|
-
opt-out, never a silent absence), and an explicit `yes` is refused for a class that forbids the
|
|
113
|
-
part.
|
|
123
|
+
## gob init summary
|
|
114
124
|
|
|
115
|
-
|
|
125
|
+
- scan: bare repo, no package.json — the brief was answered by hand
|
|
126
|
+
- chose: class software, branch main, gate `bash tests/run-tests.sh`
|
|
116
127
|
|
|
117
|
-
|
|
128
|
+
then install it:
|
|
129
|
+
|
|
130
|
+
gob init --write .gob-init-proposal.md --yes
|
|
118
131
|
|
|
119
132
|
Expected output (this is a real transcript, trimmed):
|
|
120
133
|
|
|
121
|
-
created
|
|
122
|
-
recorded opt-out: ci-gate
|
|
134
|
+
created 23 · updated 0 · unchanged 0 · skipped 0
|
|
123
135
|
|
|
124
136
|
next:
|
|
125
137
|
1. cd /tmp/gs-try && git add -A && git commit # the install is a change like any other
|
|
126
|
-
2. .
|
|
127
|
-
3. edit .
|
|
128
|
-
4. agent skills are opt-in
|
|
129
|
-
|
|
130
|
-
**`created
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
+
2. .gob/bin/goblin-verify # or add .gob/bin to PATH
|
|
139
|
+
3. edit AGENTS.md: replace the default gate with your real commands (P8 step 3)
|
|
140
|
+
4. agent skills are opt-in (the per-platform emit surface returns in a later alpha)
|
|
141
|
+
|
|
142
|
+
**`created 23`** is the installer's count of the files it **tracks**. It writes **24**: the 24th
|
|
143
|
+
is `.gob/installed.json`, the record it keeps for itself, which it writes but does not count. It
|
|
144
|
+
has written nothing outside this directory — and nothing under `.github/`: **v2 installs no
|
|
145
|
+
CI, ever.** The default install ships **no agent skills** — the harness is neutral.
|
|
146
|
+
|
|
147
|
+
**The config is the AGENTS.md frontmatter.** There is no separate config file: every key the
|
|
148
|
+
harness reads lives in the `<!-- gob:begin --> … <!-- gob:end -->` marker block at the top of
|
|
149
|
+
`AGENTS.md`. Edit it in place; the parser reads only that block.
|
|
138
150
|
|
|
139
151
|
### Why `git init -b main` matters
|
|
140
152
|
|
|
@@ -144,8 +156,8 @@ branch is `master` and the config says `main`, verify fails on the very first ru
|
|
|
144
156
|
FAIL PT-02 declared main, actual master
|
|
145
157
|
|
|
146
158
|
That is not a bug — it is the harness refusing to guess, which is the same reason it fails instead
|
|
147
|
-
of silently skipping a repo whose branch it got wrong. **Fix it in
|
|
148
|
-
branch** (unless you want to).
|
|
159
|
+
of silently skipping a repo whose branch it got wrong. **Fix it in the AGENTS.md block, not by
|
|
160
|
+
renaming your branch** (unless you want to).
|
|
149
161
|
|
|
150
162
|
---
|
|
151
163
|
|
|
@@ -153,20 +165,19 @@ branch** (unless you want to).
|
|
|
153
165
|
|
|
154
166
|
cd /tmp/gs-try
|
|
155
167
|
git add -A && git commit -m "chore: install gobstack"
|
|
156
|
-
.
|
|
168
|
+
.gob/bin/goblin-verify
|
|
157
169
|
|
|
158
170
|
You will see one line per rule. The shape:
|
|
159
171
|
|
|
160
172
|
PASS IN-01 the install record exists and names its version
|
|
161
173
|
PASS IN-02 15 installed files hashed
|
|
162
174
|
FAIL HP-05 HANDOFF.md names no commit that exists in this repo
|
|
163
|
-
FAIL GT-02 gate commit: bash tests/run-tests.sh -> exit 127
|
|
164
175
|
SKIP HS-02 no pinned pre-change commit yet - the REPLAY is not provable
|
|
165
176
|
ADV HP-04 A stale sentence is corrected in place... (advisory)
|
|
166
177
|
|
|
167
178
|
and a summary line at the bottom:
|
|
168
179
|
|
|
169
|
-
|
|
180
|
+
36 passed, 1 failed, 11 advisory, 34 skipped # HP-05, below
|
|
170
181
|
|
|
171
182
|
### How to read that output
|
|
172
183
|
|
|
@@ -178,28 +189,28 @@ and a summary line at the bottom:
|
|
|
178
189
|
| `ADV` | advisory — a rule with no runnable check, **counted** | nothing, but know it is not enforced |
|
|
179
190
|
|
|
180
191
|
**`SKIP` is not success and not failure.** It is the harness telling you the truth: "this rule has
|
|
181
|
-
nothing to read yet." On a brand-new install,
|
|
192
|
+
nothing to read yet." On a brand-new install, three dozen rows skip — because there is no `src/` for a
|
|
182
193
|
ban to scan, no feature map, no loop record, no pinned pre-change commit. That is correct on day
|
|
183
194
|
one. The list of what is still skipping *is* your onboarding checklist.
|
|
184
195
|
|
|
185
196
|
### Feature maps: generate with `gob map`, then opt in
|
|
186
197
|
|
|
187
|
-
The feature-map rows (`FM-01`, `FM-02`) are opt-in by declaration: while `feature_map:` in
|
|
188
|
-
|
|
198
|
+
The feature-map rows (`FM-01`, `FM-02`) are opt-in by declaration: while `feature_map:` in the
|
|
199
|
+
AGENTS.md gob block is empty, both rows SKIP. When you are ready to keep a map honest, the flow
|
|
189
200
|
is:
|
|
190
201
|
|
|
191
|
-
1. **Generate a starter.** `gob map` works in any git repo — no
|
|
192
|
-
|
|
202
|
+
1. **Generate a starter.** `gob map --heuristic` works in any git repo — no install needed. It
|
|
203
|
+
scans the repo (Next.js app/pages router, Nuxt, route files, or top-level `src/`/`lib/`
|
|
193
204
|
module dirs as TODO placeholders) and writes `features/README.md` plus one file per detected
|
|
194
205
|
feature. It never clobbers: an existing `features/` refuses until `--force`, which regenerates
|
|
195
206
|
only the index and adds new slugs — your hand-edited feature files are never rewritten.
|
|
196
207
|
2. **Hand-pass every file.** The generated files say so themselves: a `verified: never-driven
|
|
197
208
|
(generated <date>)` line is not a drive claim. Edit each one into a real feature description
|
|
198
209
|
with concrete entry paths and driving steps.
|
|
199
|
-
3. **Then, optionally, declare it.** Set `feature_map: features/README.md` in
|
|
200
|
-
and `FM-01`/`FM-02` start reading it on every verify — that declaration is the
|
|
201
|
-
never forced. A repo that wants the generator but not the rows can run
|
|
202
|
-
declare anything.
|
|
210
|
+
3. **Then, optionally, declare it.** Set `feature_map: features/README.md` in the AGENTS.md gob
|
|
211
|
+
block and `FM-01`/`FM-02` start reading it on every verify — that declaration is the
|
|
212
|
+
verify opt-in, never forced. A repo that wants the generator but not the rows can run
|
|
213
|
+
`gob map` and never declare anything.
|
|
203
214
|
|
|
204
215
|
**Read the failure messages.** They are written to be actionable, not decorative. `HP-05` above is
|
|
205
216
|
telling you the HANDOFF does not yet name a commit — fix it by naming your HEAD in the `State`
|
|
@@ -209,17 +220,16 @@ section.
|
|
|
209
220
|
|
|
210
221
|
| Step | Command | Verify prints | The FAILs |
|
|
211
222
|
|---|---|---|---|
|
|
212
|
-
| 1. the
|
|
213
|
-
| 2. the first commit | `git add -A && git commit` | `
|
|
214
|
-
| 3. name a real HEAD — and **commit that too** | edit `HANDOFF.md`, then `git add -A && git commit` | `
|
|
215
|
-
| 4. your real gate | edit `gates:` in `.goblin/goblin.yaml` (§5) | `36 passed, 0 failed, ...` | none — green |
|
|
223
|
+
| 1. the install ran | `gob init --write ... --yes` | `35 passed, 2 failed, 11 advisory, 34 skipped` | the install is uncommitted (`CM-03`) and the shipped SPEC is untracked (`SP-02`) |
|
|
224
|
+
| 2. the first commit | `git add -A && git commit` | `36 passed, 1 failed, 11 advisory, 34 skipped` | `HP-05` (the placeholder) — plus `GT-02` if your gate names a script the repo does not have |
|
|
225
|
+
| 3. name a real HEAD — and **commit that too** | edit `HANDOFF.md`, then `git add -A && git commit` | `37 passed, 0 failed, 11 advisory, 34 skipped` | none — green |
|
|
216
226
|
|
|
217
|
-
|
|
227
|
+
One of those deserves its name spelled out:
|
|
218
228
|
|
|
219
|
-
- **`GT-02` exit 127 is the guide's own teaching point, not a defect.** The
|
|
220
|
-
`bash tests/run-tests.sh
|
|
221
|
-
*command not found*.
|
|
222
|
-
|
|
229
|
+
- **`GT-02` exit 127 is the guide's own teaching point, not a defect.** The gate you wrote in the
|
|
230
|
+
proposal (`bash tests/run-tests.sh`) does not exist in a throwaway repo — the shell's own
|
|
231
|
+
*command not found*. Replace it with a command that can run (or create the script). The failure
|
|
232
|
+
line tells you this: `gate check: bash tests/run-tests.sh -> exit 127`.
|
|
223
233
|
- **Step 3 is two steps on purpose.** Naming a real HEAD in `HANDOFF.md` without committing it
|
|
224
234
|
re-reds `CM-03` (`1 dirty entr(y|ies)`) — commit-as-you-go starts on minute one. Edit, commit,
|
|
225
235
|
then verify.
|
|
@@ -230,8 +240,8 @@ If you ran step 1 without `-b main`, or with the wrong git identity, you will se
|
|
|
230
240
|
|
|
231
241
|
| FAIL | Cause | Fix |
|
|
232
242
|
|---|---|---|
|
|
233
|
-
| `PT-02 declared main, actual master` | branch name mismatch | set `branch:` in
|
|
234
|
-
| `CM-01` (commit identity) | the repo's commit email ≠ the declared `owner_email:` | set `owner_email:` in the
|
|
243
|
+
| `PT-02 declared main, actual master` | branch name mismatch | set `branch:` in the AGENTS.md gob block |
|
|
244
|
+
| `CM-01` (commit identity) | the repo's commit email ≠ the declared `owner_email:` | set `owner_email:` in the gob block |
|
|
235
245
|
| `HP-05` | `HANDOFF.md` still names the scaffold placeholder `` `0000000` `` | replace it with your real short HEAD |
|
|
236
246
|
|
|
237
247
|
**All three are configuration, not defects.** The harness is reporting your repo's actual state
|
|
@@ -240,33 +250,27 @@ against a declared expectation. That is exactly what you want it to do.
|
|
|
240
250
|
`HP-05` deserves one sentence more, because it surprises people: the scaffold ships
|
|
241
251
|
`HEAD when this file was written: `0000000``, and `HP-05` **rejects that placeholder on purpose**.
|
|
242
252
|
A file that names a commit which does not exist is worse than one that names none — it looks like a
|
|
243
|
-
record. Commit first, then write the real short SHA in.
|
|
244
|
-
left in, verify reports `35 passed, 2 failed`; with the real SHA (and the edit committed),
|
|
245
|
-
`36 passed, 1 failed` — the one FAIL being the `GT-02` exit 127 above.
|
|
253
|
+
record. Commit first, then write the real short SHA in.
|
|
246
254
|
|
|
247
255
|
---
|
|
248
256
|
|
|
249
|
-
## 5. Step 3 — Make it yours: the one config
|
|
257
|
+
## 5. Step 3 — Make it yours: the one config block
|
|
250
258
|
|
|
251
|
-
Everything you configure lives in **one
|
|
259
|
+
Everything you configure lives in **one place**, created once and then never overwritten
|
|
260
|
+
by the installer:
|
|
252
261
|
|
|
253
|
-
.
|
|
262
|
+
AGENTS.md — the `<!-- gob:begin --> ... <!-- gob:end -->` block
|
|
254
263
|
|
|
255
264
|
Open it. The keys that matter on day one:
|
|
256
265
|
|
|
257
|
-
class: software # software|service|game|research|fleet (A-E are aliases)
|
|
266
|
+
class: software # software|service|game|research|fleet (A-E are aliases)
|
|
258
267
|
branch: main # DECLARED, never assumed
|
|
259
268
|
owner_email: you@example.com # the commit identity this repo expects
|
|
260
269
|
practice: /path/to/your-standard.md # optional: your own house rules, hash-pinned
|
|
261
270
|
models_file: /path/to/fleet-model.yaml # the ONE machine-specific input
|
|
271
|
+
gate_<name>_cmd: <one command> # YOUR real commands, one line each
|
|
262
272
|
|
|
263
|
-
|
|
264
|
-
- name: commit
|
|
265
|
-
cmd: git rev-parse --verify --quiet HEAD
|
|
266
|
-
- name: todo_ceiling
|
|
267
|
-
cmd: test "$(grep -rniE '\b(TODO|FIXME)\b' --include='*.ts' . | wc -l)" -le 160
|
|
268
|
-
|
|
269
|
-
**The single most valuable edit you will make:** replace the default `gates:` with the commands you
|
|
273
|
+
**The single most valuable edit you will make:** replace the gate line(s) with the commands you
|
|
270
274
|
actually run to know your project is healthy. `tsc --noEmit`, `npm run build`, your test command —
|
|
271
275
|
whichever three or four you would run before saying "this is fine."
|
|
272
276
|
|
|
@@ -278,7 +282,7 @@ without you remembering to. And the gate numbers are recorded with a date, so a
|
|
|
278
282
|
|
|
279
283
|
If you already have a house standard — a `CONTRIBUTING.md`, a `PROJECT-PRACTICE.md`, anything
|
|
280
284
|
written down — point `practice:` at it. gobstack does **not** copy its text. It records a
|
|
281
|
-
**hash** of the file and re-checks that hash on every verify.
|
|
285
|
+
**hash** of the file (`practice_sha256:`) and re-checks that hash on every verify.
|
|
282
286
|
|
|
283
287
|
That buys you one specific, valuable thing: **if someone edits your standard, every project that
|
|
284
288
|
pins it goes red.** You find out immediately instead of discovering six months later that half your
|
|
@@ -288,8 +292,8 @@ When *you* legitimately edit your own standard:
|
|
|
288
292
|
|
|
289
293
|
gob install --target . --re-pin
|
|
290
294
|
|
|
291
|
-
It re-records the hash and prints the old and new value. Nothing re-pins automatically —
|
|
292
|
-
edited standard is never a silent no-op.
|
|
295
|
+
It re-records the hash and prints the old and new value. Nothing re-pins automatically — not even
|
|
296
|
+
a re-install — an edited standard is never a silent no-op.
|
|
293
297
|
|
|
294
298
|
---
|
|
295
299
|
|
|
@@ -313,10 +317,10 @@ gate, not a sixth class. The old `F` letter still resolves there as an install a
|
|
|
313
317
|
|
|
314
318
|
- A repo that holds *output* while the code lives elsewhere → **research**, not **software**. Gating
|
|
315
319
|
it like an application gates the wrong artifact.
|
|
316
|
-
- A plain input directory that is not a build target → **research** with
|
|
320
|
+
- A plain input directory that is not a build target → **research** with `archive: true`, which tells
|
|
317
321
|
verify to expect no HANDOFF and no gates, and to say so.
|
|
318
322
|
|
|
319
|
-
Switch class later by editing `class:` in the
|
|
323
|
+
Switch class later by editing `class:` in the gob block and re-running install. The parts you no longer
|
|
320
324
|
need are recorded as **disabled** and will report `SKIP (opt-out)` rather than failing.
|
|
321
325
|
|
|
322
326
|
---
|
|
@@ -343,7 +347,7 @@ Step by step:
|
|
|
343
347
|
# 2. make your change, committing in small steps
|
|
344
348
|
|
|
345
349
|
# 3. run the gate
|
|
346
|
-
.
|
|
350
|
+
.gob/bin/goblin-verify
|
|
347
351
|
|
|
348
352
|
# 4. write the handoff: state / gates / next steps / NOT verified
|
|
349
353
|
|
|
@@ -364,16 +368,16 @@ honest entry, and the harness treats it as one.
|
|
|
364
368
|
> **Prove it was broken first.**
|
|
365
369
|
|
|
366
370
|
Before you trust a check, break the thing it checks and watch it go red — then put it back and watch
|
|
367
|
-
it go green. Break it on a row this walkthrough can actually break: `IN-02` hashes the
|
|
368
|
-
tracks
|
|
369
|
-
`.
|
|
371
|
+
it go green. Break it on a row this walkthrough can actually break: `IN-02` hashes the 15 files it
|
|
372
|
+
tracks — not the ones it `owns` (including `AGENTS.md`, whose gob block §5 has you editing) and not
|
|
373
|
+
`.gob/installed.json`; edit one of the tracked — the exercise below uses `.gob/bans/README.md`.
|
|
370
374
|
|
|
371
375
|
# REPLAY-BEGIN (this exact block is run by tests/t-doc-guide.sh - keep the two copies identical)
|
|
372
|
-
.
|
|
373
|
-
printf '\n<!-- a deliberate edit -->\n' >> .
|
|
374
|
-
.
|
|
375
|
-
git stash push -- .
|
|
376
|
-
.
|
|
376
|
+
.gob/bin/goblin-verify --only IN-02 # expect PASS
|
|
377
|
+
printf '\n<!-- a deliberate edit -->\n' >> .gob/bans/README.md
|
|
378
|
+
.gob/bin/goblin-verify --only IN-02 # expect FAIL
|
|
379
|
+
git stash push -- .gob/bans/README.md # path-limited: your own edits stay put
|
|
380
|
+
.gob/bin/goblin-verify --only IN-02 # expect PASS
|
|
377
381
|
git stash drop # the break was deliberate: discard it
|
|
378
382
|
# REPLAY-END
|
|
379
383
|
|
|
@@ -382,10 +386,10 @@ That is the whole habit — the change you *undo* is a deliberate break, not a f
|
|
|
382
386
|
measures the shipped files rather than your work.
|
|
383
387
|
|
|
384
388
|
`GT-02` is the row most readers reach for first, and it will **not** work as a REPLAY demo on the
|
|
385
|
-
shipped configuration: it runs the gates you declared
|
|
389
|
+
shipped configuration: it runs the gates you declared, and stashing a
|
|
386
390
|
local change does not change either command's exit status — so it prints `PASS` before and after,
|
|
387
391
|
which is exactly the "green on both trees" result this rule exists to kill. REPLAY a gate of your
|
|
388
|
-
own the same way, once that gate is real: declare it in
|
|
392
|
+
own the same way, once that gate is real: declare it in the gob block and stash a change it
|
|
389
393
|
can see.
|
|
390
394
|
|
|
391
395
|
A check that is green on **both** the broken and the fixed tree proves nothing — it would have been
|
|
@@ -396,7 +400,7 @@ caught every real regression in this repository's own development history.
|
|
|
396
400
|
|
|
397
401
|
## 8. Step 6 — The daily loop, once you are settled
|
|
398
402
|
|
|
399
|
-
Day to day, the harness should fade into
|
|
403
|
+
Day to day, the harness should fade into three habits:
|
|
400
404
|
|
|
401
405
|
**Starting work** — read `HANDOFF.md` first. It tells you the state, the gates, what is next, and —
|
|
402
406
|
most importantly — **what is *not* verified**. Never trust a claim in it without running the
|
|
@@ -407,15 +411,7 @@ the harness nudges you to land things as they work rather than in one heroic com
|
|
|
407
411
|
|
|
408
412
|
**Finishing** — update `HANDOFF.md`, then:
|
|
409
413
|
|
|
410
|
-
.
|
|
411
|
-
|
|
412
|
-
**Every so often** — audit your own claims against the artifact:
|
|
413
|
-
|
|
414
|
-
.goblin/bin/goblin-audit
|
|
415
|
-
|
|
416
|
-
This is the *only* step that touches the network (rule `SC-07`), and it is deliberate: it is how a
|
|
417
|
-
recorded claim ("this dependency is fine") gets checked against reality ("this dependency has a
|
|
418
|
-
known advisory").
|
|
414
|
+
.gob/bin/goblin-verify && git add -A && git commit -m "..."
|
|
419
415
|
|
|
420
416
|
### Keeping `HANDOFF.md` honest
|
|
421
417
|
|
|
@@ -449,18 +445,18 @@ the next session.
|
|
|
449
445
|
|
|
450
446
|
## 9. What to expect on day one (so you do not misread it)
|
|
451
447
|
|
|
452
|
-
A software-class install
|
|
453
|
-
the scaffold teaching on purpose — `HP-05`, the `0000000` placeholder in `HANDOFF.md` (§4)
|
|
454
|
-
|
|
455
|
-
measured, step by step:
|
|
448
|
+
A software-class install lands on a specific shape. The first reds are
|
|
449
|
+
the scaffold teaching on purpose — `HP-05`, the `0000000` placeholder in `HANDOFF.md` (§4). The
|
|
450
|
+
walk in §4 measured, step by step:
|
|
456
451
|
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
452
|
+
35 passed, 2 failed, 11 advisory, 34 skipped # straight after the install (CM-03 + SP-02)
|
|
453
|
+
36 passed, 1 failed, 11 advisory, 34 skipped # first commit: HP-05 left (and GT-02 too if the gate cannot run)
|
|
454
|
+
37 passed, 0 failed, 11 advisory, 34 skipped # real HEAD named and committed: green
|
|
460
455
|
|
|
461
|
-
Name a real commit in `HANDOFF.md`, commit, and give
|
|
456
|
+
Name a real commit in `HANDOFF.md`, commit, and give the gate lines real commands (§5), and it is
|
|
457
|
+
green:
|
|
462
458
|
|
|
463
|
-
|
|
459
|
+
37 passed, 0 failed, 11 advisory, 34 skipped (on a real project; your numbers will differ)
|
|
464
460
|
|
|
465
461
|
**Thirty-four rows skipping is correct**, and each skip prints its reason. In plain terms: the
|
|
466
462
|
harness is telling you which of its rules have nothing to read yet. It is a checklist, not a
|
|
@@ -486,9 +482,9 @@ Two readings that are easy to get wrong:
|
|
|
486
482
|
| Symptom | What it means | What to do |
|
|
487
483
|
|---|---|---|
|
|
488
484
|
| `refused to overwrite: HANDOFF.md`, exit 1 | your repo already had a HANDOFF | **do not `--force`** — reconcile it (below) |
|
|
489
|
-
| `PT-02 declared main, actual master` | branch mismatch | set `branch:` in the
|
|
485
|
+
| `PT-02 declared main, actual master` | branch mismatch | set `branch:` in the gob block |
|
|
490
486
|
| `IN-02 ... practice EDITED` | someone changed the pinned standard | re-pin deliberately: `--re-pin` |
|
|
491
|
-
| `gob
|
|
487
|
+
| `gob: unrecognized command: <verb>` (exit 2) | you ran a verb outside the v2 surface (`audit`, `doctor`, `emit`, `sync`, `upgrade`, `install`) | use the five wired verbs: `init`, `map`, `verify`, `bans`, `uninstall` — the unwired surface returns in a later alpha |
|
|
492
488
|
| `IN-03` fails, "manifest is broken" | a row has a broken check column | fix the row; this is a source defect, not yours |
|
|
493
489
|
| a `FAIL` you believe is wrong | the check may be weak, or your belief may be | run `--only <id>` and read the command it prints |
|
|
494
490
|
| a changelog or matrix note says `W6` or `Z1-4` | that is a revision wave code | `docs/RECORD-NOTES.md` is the legend, one line per code |
|
|
@@ -498,37 +494,15 @@ replaces your project's own record with a blank scaffold — the exact act the r
|
|
|
498
494
|
prevent. Reconcile instead: keep your file, and add the five sections it is missing. The measured
|
|
499
495
|
cost of that edit, on a real 2450-line handoff, was **15 lines added, none removed**.
|
|
500
496
|
|
|
501
|
-
**One engine, many repos
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
available outside any repo through the npm CLI: `gob verify` / `gob bans` / `gob audit` /
|
|
511
|
-
`gob doctor` / `gob sync` / `gob upgrade` / `gob --version`.
|
|
512
|
-
|
|
513
|
-
**Migrating a repo to the global engine:**
|
|
514
|
-
|
|
515
|
-
gob upgrade # 8 steps, two commits, one report
|
|
516
|
-
|
|
517
|
-
It refuses on a dirty tree, a detached HEAD, a red repo, or a global engine holding different
|
|
518
|
-
bytes — each refusal names the fix. What it does: verifies every recorded hash, lands the engine
|
|
519
|
-
at `~/.goblin/engine` (or `--engine-dir <dir>`) from this repo's own verified bytes, commits the
|
|
520
|
-
declaration + record rewrite + `checks/gate.sh` + CI re-point (commit A), proves the repo green
|
|
521
|
-
with both engines present, then `git rm`s exactly the 18 engine files (commit B) and proves green
|
|
522
|
-
again. Nothing is deleted before the engine is safely landed and the tree is green mid-sequence.
|
|
523
|
-
|
|
524
|
-
**Rolling back a migration** — the two commits are pure git operations:
|
|
525
|
-
|
|
526
|
-
git revert <commit-A-sha> <commit-B-sha>
|
|
527
|
-
|
|
528
|
-
reverses byte-for-byte: the vendored payload returns, the record drops its `engine:` block, and
|
|
529
|
-
`gob verify` is the 43-green it was before. A second `gob upgrade` on a migrated repo is a
|
|
530
|
-
no-op; `goblin-install` onto one refuses with the revert remedy (re-installing would re-shadow the
|
|
531
|
-
engine and silently de-migrate the record).
|
|
497
|
+
**One engine, many repos (declared, not wired in this alpha):** the rule table can live outside
|
|
498
|
+
the repo — a declared `engine_dir:` line in the gob block names a shared engine. In v2 the
|
|
499
|
+
**vendored engine wins by design**: a repo carrying both `.gob/` and an `engine_dir:` judges
|
|
500
|
+
itself with the vendored manifest, because that is the manifest its install record hashes
|
|
501
|
+
(`docs/LIMITS.md` #54). A declared but unusable `engine_dir:` is verify **exit 2 with no
|
|
502
|
+
fallback** — a repo is never judged by an engine it did not declare. The engine's own identity
|
|
503
|
+
prints in every run's footer (`engine: mode=vendored cli_sha256=… enforcement_tsv_sha256=…`). The
|
|
504
|
+
same commands are available outside any repo through the npm CLI: `gob init` / `gob map` /
|
|
505
|
+
`gob verify` / `gob bans` / `gob --version`.
|
|
532
506
|
|
|
533
507
|
**Two exit-code contracts worth knowing:**
|
|
534
508
|
|
|
@@ -536,8 +510,7 @@ engine and silently de-migrate the record).
|
|
|
536
510
|
|---|---|
|
|
537
511
|
| `goblin-install` | `0` ok · `1` a refusal (with the path and the fix) · `2` bad input |
|
|
538
512
|
| `goblin-verify` | `0` all checks passed · `1` a check failed · `2` could not run · `3` the manifest itself is broken |
|
|
539
|
-
| `
|
|
540
|
-
| platforms (W4b) | `emit`/`doctor` cover seven: `claude`, `hermes`, `copilot`, `cursor`, `opencode`, `codex`, `gemini` — each detected via its own anchor (`~/.claude`, `~/.hermes`, `~/.copilot`, `~/.cursor`, `~/.config/opencode`, `~/.codex`, `~/.gemini`); codex and gemini carry `partial` command-blocking (see LIMITS #47) |
|
|
513
|
+
| `gob` (npm CLI) | propagates the subcommand's codes verbatim; a verb outside the surface (`audit`/`doctor`/`emit`/`sync`/`upgrade`/`install`) is refused with exit 2 and the usage |
|
|
541
514
|
|
|
542
515
|
`3` is the one to notice: it means gobstack's own rule table is malformed, not your project.
|
|
543
516
|
|
|
@@ -547,16 +520,35 @@ engine and silently de-migrate the record).
|
|
|
547
520
|
|
|
548
521
|
### Commands
|
|
549
522
|
|
|
550
|
-
gob
|
|
551
|
-
|
|
552
|
-
gob
|
|
553
|
-
gob
|
|
523
|
+
gob init [--heuristic] [--write <proposal>] [--target <dir>] [--dry-run] [--yes]
|
|
524
|
+
[--with-mcp-config]
|
|
525
|
+
gob map [--heuristic [target]] [--write <dir>] [--force]
|
|
526
|
+
gob mcp # the MCP stdio server (three tools, local only)
|
|
527
|
+
gob extras list | show <id> | install <id...> # the curated extras catalogue
|
|
554
528
|
|
|
555
|
-
.
|
|
556
|
-
.
|
|
557
|
-
|
|
529
|
+
.gob/bin/goblin-verify [--only <id[,id...]>] [--json] [--list]
|
|
530
|
+
.gob/bin/goblin-bans # run the ban list
|
|
531
|
+
gob install --target <dir> --uninstall # the uninstall job
|
|
532
|
+
gob install --target <dir> --re-pin # the deliberate re-pin
|
|
558
533
|
bin/goblin-model <role> # checkout-only; resolve a role to a profile (docs/ROLES.md)
|
|
559
534
|
|
|
535
|
+
### Register the harness with your agent (MCP)
|
|
536
|
+
|
|
537
|
+
Your agent can call the discipline gate itself instead of you pasting verify output into the
|
|
538
|
+
chat. `gob mcp` is a local tool server (JSON-RPC over stdin/stdout — the Model Context
|
|
539
|
+
Protocol shape); it exposes `gob_verify` (the gate, with the remedy line under every FAIL),
|
|
540
|
+
`gob_map_status` (the feature map, read-only) and `gob_init_status` (is this repo under the
|
|
541
|
+
harness). It calls no API and opens no socket.
|
|
542
|
+
|
|
543
|
+
The one-liner, per user account:
|
|
544
|
+
|
|
545
|
+
claude mcp add gob -- npx -y @techgoblin/gobstack mcp
|
|
546
|
+
|
|
547
|
+
or, committed with the repo so every teammate's agent picks it up (Claude Code and Cursor
|
|
548
|
+
auto-detect it):
|
|
549
|
+
|
|
550
|
+
gob init --with-mcp-config # writes .mcp.json; never overwrites one you customized
|
|
551
|
+
|
|
560
552
|
### The 15 playbooks
|
|
561
553
|
|
|
562
554
|
Named procedures, installed as project-local skills. Each has a measurable verification step.
|
|
@@ -579,12 +571,38 @@ Named procedures, installed as project-local skills. Each has a measurable verif
|
|
|
579
571
|
| P14 | `goblin-drift-audit` | a recorded claim disagrees with the artifact |
|
|
580
572
|
| P15 | `goblin-re-mobile` | one shipped Android build must be understood as facts for study |
|
|
581
573
|
|
|
574
|
+
### The extras catalogue (suggestions, not installs)
|
|
575
|
+
|
|
576
|
+
`gob extras` browses and installs the curated extras catalogue — third-party agent skills,
|
|
577
|
+
MCP servers and workflows the curator reviewed and carried in `extras-catalogue/catalogue.tsv`.
|
|
578
|
+
The one rule to hold onto: **init suggests, the catalogue allows, you install.**
|
|
579
|
+
|
|
580
|
+
gob extras list # the whole catalogue, grouped by category
|
|
581
|
+
gob extras list testing # one category: frontend | testing | game | node
|
|
582
|
+
gob extras show playwright-mcp # one row, every field
|
|
583
|
+
gob extras install playwright-mcp --target . # mcp: prints the mcp.json snippet
|
|
584
|
+
gob extras install taste-skill --target . --platform claude # skill: .claude/skills/taste/
|
|
585
|
+
gob extras install taste-skill --target . # no platform: .gob/extras/taste/
|
|
586
|
+
|
|
587
|
+
Verdicts: a `RECOMMEND` row is pre-ticked when `gob init` suggests; a `MAYBE` row is listed
|
|
588
|
+
but never pre-ticked; a `SKIP` row refuses install (visible history, declined candidate).
|
|
589
|
+
Nothing installs at init — `gob init --write` honours only the rows your proposal ticks, and
|
|
590
|
+
it installs them by calling `gob extras install`, so the allowlist is one code path. An id
|
|
591
|
+
that is not in the catalogue is refused; installs copy from the vendored payload in the
|
|
592
|
+
package (no network), and an mcp row merges into `.mcp.json` only with `--with-mcp-config`,
|
|
593
|
+
never overwriting an entry you customized.
|
|
594
|
+
|
|
595
|
+
The brief also asks your agent to propose discoveries (`discover_extras:`): web-found skills
|
|
596
|
+
that match the stack but are not in the catalogue, each with a live URL, a license and a
|
|
597
|
+
rationale. Proposals are inert; the curator promotes accepted ones into `catalogue.tsv` by PR
|
|
598
|
+
or edit, and only then can `gob extras install` name them.
|
|
599
|
+
|
|
582
600
|
### Where the real documentation lives
|
|
583
601
|
|
|
584
602
|
| File | Read it for |
|
|
585
603
|
|---|---|
|
|
586
604
|
| `docs/DESIGN.md` | the thesis and every rejected alternative |
|
|
587
|
-
| `docs/GLOSSARY.md` | every term of art in one table (rendered from `.
|
|
605
|
+
| `docs/GLOSSARY.md` | every term of art in one table (rendered from `.gob/manifest/glossary.tsv`) |
|
|
588
606
|
| `docs/RECORD-NOTES.md` | the wave codes the changelog uses, one line each |
|
|
589
607
|
| `docs/FLOWS.md` | the playbooks in full, with reasons |
|
|
590
608
|
| `docs/ENFORCEMENT.md` | the rule matrix, rendered for a human |
|
|
@@ -592,7 +610,7 @@ Named procedures, installed as project-local skills. Each has a measurable verif
|
|
|
592
610
|
| `docs/RISKS.md` | the risk register and non-goals |
|
|
593
611
|
| `docs/CONTRACTS.md` | exact interface, exit codes, uninstall |
|
|
594
612
|
| `docs/ADOPTION.md` | classes, presets, adoption order |
|
|
595
|
-
| `docs/
|
|
613
|
+
| `docs/LOOP.md`, `docs/GUARDRAILS.md` | the newer lanes |
|
|
596
614
|
|
|
597
615
|
---
|
|
598
616
|
|
|
@@ -611,64 +629,63 @@ Stated plainly, because a guide that oversells its tool is worse than no guide:
|
|
|
611
629
|
- **It is not a product.** It is a repository of files, installed into other repositories.
|
|
612
630
|
No service, no daemon, no support contract.
|
|
613
631
|
|
|
614
|
-
The current status, if you want the honest number: a separate review pass verified the artifact at
|
|
615
|
-
**9/10** (that was 0.4.2), and the point it withheld was not a missing feature — it was sentences
|
|
616
|
-
in the record that a measurement contradicted. `docs/LIMITS.md` is the list of what the harness
|
|
617
|
-
cannot see.
|
|
618
|
-
|
|
619
632
|
---
|
|
620
633
|
|
|
621
634
|
## 13. Where to go next
|
|
622
635
|
|
|
623
|
-
**If you only do one thing:** install into your most active repo today, set your real
|
|
624
|
-
run `goblin-verify` once a day for a week. The habit, not the tool, is what produces
|
|
636
|
+
**If you only do one thing:** install into your most active repo today, set your real gate
|
|
637
|
+
commands, and run `goblin-verify` once a day for a week. The habit, not the tool, is what produces
|
|
638
|
+
the result.
|
|
625
639
|
|
|
626
640
|
**Then, in order:**
|
|
627
641
|
|
|
628
642
|
1. Point `practice:` at your existing house standard and pin it.
|
|
629
643
|
2. Write one `AC:` item that a script could check, and make it pass.
|
|
630
644
|
3. Add a ban for the one pattern you are tired of seeing in agent-written code
|
|
631
|
-
(`.
|
|
645
|
+
(`.gob/manifest/bans.tsv` — a ban without a mechanism is a wish, so give it one).
|
|
632
646
|
4. When you have a bug that a test could catch, walk P5 (`goblin-tdd-repro`) end to end once.
|
|
633
647
|
|
|
634
|
-
**If you are sharing this with a team:** the parts that matter are `HANDOFF.md`, the
|
|
635
|
-
declare, and the REPLAY habit. The rest is optional machinery you can switch off per class.
|
|
636
|
-
with *"prove it was broken first"* — it is the one practice that survives contact with a
|
|
648
|
+
**If you are sharing this with a team:** the parts that matter are `HANDOFF.md`, the gate commands
|
|
649
|
+
you declare, and the REPLAY habit. The rest is optional machinery you can switch off per class.
|
|
650
|
+
Lead with *"prove it was broken first"* — it is the one practice that survives contact with a
|
|
651
|
+
deadline.
|
|
637
652
|
|
|
638
653
|
---
|
|
639
654
|
|
|
640
655
|
## Appendix — a 45-minute first run, on one page
|
|
641
656
|
|
|
642
657
|
# 0. get it
|
|
643
|
-
npm i -g @techgoblin/gobstack
|
|
658
|
+
npx @techgoblin/gobstack init # or: npm i -g @techgoblin/gobstack
|
|
644
659
|
|
|
645
660
|
# 1. try it somewhere disposable
|
|
646
661
|
mkdir -p /tmp/gs-try && cd /tmp/gs-try
|
|
647
662
|
git init -b main
|
|
648
|
-
gob
|
|
663
|
+
gob init --heuristic # the brief + schema; answer it in a proposal file
|
|
664
|
+
gob init --write .gob-init-proposal.md --yes
|
|
665
|
+
# expect: created 23 (no skills — those are opt-in)
|
|
649
666
|
|
|
650
667
|
# 2. commit and check
|
|
651
668
|
git add -A && git commit -m "chore: install gobstack"
|
|
652
|
-
.
|
|
669
|
+
.gob/bin/goblin-verify # expect: mostly PASS, some SKIP
|
|
653
670
|
|
|
654
671
|
# 3. make it yours
|
|
655
|
-
$EDITOR .
|
|
672
|
+
$EDITOR AGENTS.md # branch, owner_email, and YOUR real gate commands (the gob block)
|
|
656
673
|
|
|
657
674
|
# 4. prove a check can fail (the habit that matters) - the same block §7 runs
|
|
658
675
|
# REPLAY-BEGIN (this exact block is run by tests/t-doc-guide.sh - keep the two copies identical)
|
|
659
|
-
.
|
|
660
|
-
printf '\n<!-- a deliberate edit -->\n' >> .
|
|
661
|
-
.
|
|
662
|
-
git stash push -- .
|
|
663
|
-
.
|
|
676
|
+
.gob/bin/goblin-verify --only IN-02 # expect PASS
|
|
677
|
+
printf '\n<!-- a deliberate edit -->\n' >> .gob/bans/README.md
|
|
678
|
+
.gob/bin/goblin-verify --only IN-02 # expect FAIL
|
|
679
|
+
git stash push -- .gob/bans/README.md # path-limited: your own edits stay put
|
|
680
|
+
.gob/bin/goblin-verify --only IN-02 # expect PASS
|
|
664
681
|
git stash drop # the break was deliberate: discard it
|
|
665
682
|
# REPLAY-END
|
|
666
683
|
|
|
667
684
|
# 5. do it for real, in a repo you care about
|
|
668
685
|
cd ~/projects/your-project
|
|
669
|
-
gob
|
|
686
|
+
gob init --write .gob-init-proposal.md --yes
|
|
670
687
|
git add -A && git commit -m "chore: adopt gobstack"
|
|
671
|
-
.
|
|
688
|
+
.gob/bin/goblin-verify
|
|
672
689
|
$EDITOR HANDOFF.md # state / gates (dated!) / next / NOT verified
|
|
673
690
|
|
|
674
691
|
---
|