@techgoblin/gobstack 0.5.0-beta.7 → 0.6.0-alpha.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.
Files changed (54) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/README.md +112 -123
  3. package/VERSION +1 -1
  4. package/automations/drift-audit.sh +4 -4
  5. package/bans/layer-check.sh +10 -8
  6. package/bin/goblin +61 -52
  7. package/bin/goblin-audit +11 -13
  8. package/bin/goblin-bans +11 -11
  9. package/bin/goblin-init +275 -713
  10. package/bin/goblin-install +160 -114
  11. package/bin/goblin-lib.sh +234 -1
  12. package/bin/goblin-map +607 -0
  13. package/bin/goblin-mcp.js +492 -0
  14. package/bin/goblin-model +4 -4
  15. package/bin/goblin-upgrade +1 -1
  16. package/bin/goblin-verify +159 -145
  17. package/bin/goblin.js +33 -49
  18. package/docs/ADOPTION.md +15 -15
  19. package/docs/CONTRACTS.md +16 -15
  20. package/docs/DESIGN.md +1 -1
  21. package/docs/ENFORCEMENT.md +89 -90
  22. package/docs/FLOWS.md +1 -1
  23. package/docs/GLOSSARY.md +3 -3
  24. package/docs/GUARDRAILS.md +5 -5
  25. package/docs/GUIDE.md +178 -169
  26. package/docs/INTEGRATION.md +1 -1
  27. package/docs/LIMITS.md +25 -0
  28. package/docs/LOOP.md +12 -12
  29. package/docs/RE-PLAYBOOK.md +3 -3
  30. package/docs/ROLES.md +5 -5
  31. package/manifest/bans.tsv +8 -8
  32. package/manifest/classes.tsv +3 -3
  33. package/manifest/enforcement.tsv +40 -40
  34. package/manifest/glossary.tsv +3 -3
  35. package/manifest/playbooks.tsv +1 -1
  36. package/package.json +1 -1
  37. package/presets/electron-overlay.yaml +2 -2
  38. package/presets/fleet.yaml +8 -7
  39. package/presets/game.yaml +1 -1
  40. package/presets/research.yaml +1 -1
  41. package/presets/service.yaml +1 -1
  42. package/presets/software.yaml +1 -1
  43. package/skills/goblin-bootstrap/SKILL.md +2 -2
  44. package/templates/AGENTS.md.tmpl +8 -18
  45. package/templates/HANDOFF.md.tmpl +5 -5
  46. package/templates/agents-block.tmpl +45 -0
  47. package/templates/audit-waiver.tsv.tmpl +2 -2
  48. package/templates/boundary-waivers.tmpl +1 -1
  49. package/templates/checks/gate.sh.tmpl +6 -6
  50. package/templates/install-hooks.allowlist.tmpl +1 -1
  51. package/templates/ci/goblin-gate.yml.tmpl +0 -46
  52. package/templates/goblin.yaml.tmpl +0 -146
  53. package/templates/loop/decisions.tsv.tmpl +0 -1
  54. 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.5.0` · Last measured: 2026-10-05 · Every command and every output below was run on a
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 checks the project against
42
- a table of rules and prints `PASS` / `FAIL` / `SKIP` for each one.
43
- - The rules table is a real file (`.goblin/manifest/enforcement.tsv`). Every row either names a
44
- command that can fail, or is labelled `advisory`. **Nothing in between.** That is what stops the
45
- rules turning into decoration.
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** — the one command in the toolbox that reaches the network is `goblin-audit`, which you run
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
- `.goblin/manifest/glossary.tsv`).
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 guided path is `gob init` — one screen per question (health check, class,
97
- identity (branch/email), the health check, the CI opt-in, which platforms to sync), every question also
98
- answerable by flag, `--dry-run` to see the plan first:
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 --target . --class software --branch main --email "you@example.com" \
106
- --gate "bash tests/run-tests.sh" --yes
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
- The wizard's ci step asks whether the gate should also run in CI
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
- or the plain installer this wizard drives, if you prefer the one-shot shape:
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
- gob install --target . --class software
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 24 · updated 0 · unchanged 0 · skipped 0
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. .goblin/bin/goblin-verify # or add .goblin/bin to PATH
127
- 3. edit .goblin/goblin.yaml: replace the default gate with your real commands (P8 step 3)
128
- 4. agent skills are opt-in: gob sync --platform <p> # hermes, claude, copilot, cursor, opencode, codex, gemini
129
-
130
- **`created 24`** is the installer's count of the files it **tracks** — one fewer than the plain
131
- installer's 25, because the wizard's unanswered ci screen defaults to an explicit **no**, which is
132
- recorded as an opt-out and suppresses `.github/workflows/goblin-gate.yml`. It writes **25**: the
133
- 25th is `.goblin/installed.json`, the record it keeps for itself, which it writes but does not
134
- count. It has written nothing outside this directory. The default install ships **no agent
135
- skills** — the harness is neutral, and `gob sync --platform <p>` is the per-platform opt-in
136
- (`gob emit` is the same command under its original name; the old `--skills yes` default is
137
- still there for repos that want the Hermes project tier vendored).
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 step 3, not by renaming your
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
- .goblin/bin/goblin-verify
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
- 35 passed, 2 failed, 11 advisory, 34 skipped # HP-05 and GT-02, below
180
+ 36 passed, 1 failed, 11 advisory, 34 skipped # HP-05, below
170
181
 
171
182
  ### How to read that output
172
183
 
@@ -178,10 +189,29 @@ 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, two dozen rows skip — because there is no `src/` for a
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
 
196
+ ### Feature maps: generate with `gob map`, then opt in
197
+
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
200
+ is:
201
+
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/`
204
+ module dirs as TODO placeholders) and writes `features/README.md` plus one file per detected
205
+ feature. It never clobbers: an existing `features/` refuses until `--force`, which regenerates
206
+ only the index and adds new slugs — your hand-edited feature files are never rewritten.
207
+ 2. **Hand-pass every file.** The generated files say so themselves: a `verified: never-driven
208
+ (generated <date>)` line is not a drive claim. Edit each one into a real feature description
209
+ with concrete entry paths and driving steps.
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.
214
+
185
215
  **Read the failure messages.** They are written to be actionable, not decorative. `HP-05` above is
186
216
  telling you the HANDOFF does not yet name a commit — fix it by naming your HEAD in the `State`
187
217
  section.
@@ -190,17 +220,16 @@ section.
190
220
 
191
221
  | Step | Command | Verify prints | The FAILs |
192
222
  |---|---|---|---|
193
- | 1. the wizard ran | `gob init ... --yes` | `31 passed, 6 failed, 11 advisory, 34 skipped` | the install is uncommitted (`CM-03`), `HP-05`, `GT-02` exit 127, and the identity/branch rows if you skipped the flags |
194
- | 2. the first commit | `git add -A && git commit` | `35 passed, 2 failed, 11 advisory, 34 skipped` | `HP-05` (the placeholder) and `GT-02` |
195
- | 3. name a real HEAD — and **commit that too** | edit `HANDOFF.md`, then `git add -A && git commit` | `36 passed, 1 failed, 11 advisory, 34 skipped` | `GT-02` only |
196
- | 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 |
197
226
 
198
- Two of those deserve their name spelled out:
227
+ One of those deserves its name spelled out:
199
228
 
200
- - **`GT-02` exit 127 is the guide's own teaching point, not a defect.** The default gate is
201
- `bash tests/run-tests.sh`, and a throwaway repo has no `tests/` — the shell's own
202
- *command not found*. It stays red until §5's most valuable edit (your real `gates:`) replaces
203
- it. The failure line tells you this: `gate commit: bash tests/run-tests.sh -> exit 127`.
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`.
204
233
  - **Step 3 is two steps on purpose.** Naming a real HEAD in `HANDOFF.md` without committing it
205
234
  re-reds `CM-03` (`1 dirty entr(y|ies)`) — commit-as-you-go starts on minute one. Edit, commit,
206
235
  then verify.
@@ -211,8 +240,8 @@ If you ran step 1 without `-b main`, or with the wrong git identity, you will se
211
240
 
212
241
  | FAIL | Cause | Fix |
213
242
  |---|---|---|
214
- | `PT-02 declared main, actual master` | branch name mismatch | set `branch:` in `.goblin/goblin.yaml` |
215
- | `CM-01` (commit identity) | the repo's commit email ≠ the declared `owner_email:` | set `owner_email:` in the config |
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 |
216
245
  | `HP-05` | `HANDOFF.md` still names the scaffold placeholder `` `0000000` `` | replace it with your real short HEAD |
217
246
 
218
247
  **All three are configuration, not defects.** The harness is reporting your repo's actual state
@@ -221,33 +250,27 @@ against a declared expectation. That is exactly what you want it to do.
221
250
  `HP-05` deserves one sentence more, because it surprises people: the scaffold ships
222
251
  `HEAD when this file was written: `0000000``, and `HP-05` **rejects that placeholder on purpose**.
223
252
  A file that names a commit which does not exist is worse than one that names none — it looks like a
224
- record. Commit first, then write the real short SHA in. Measured on this walk: with the placeholder
225
- left in, verify reports `35 passed, 2 failed`; with the real SHA (and the edit committed),
226
- `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.
227
254
 
228
255
  ---
229
256
 
230
- ## 5. Step 3 — Make it yours: the one config file
257
+ ## 5. Step 3 — Make it yours: the one config block
231
258
 
232
- Everything you configure lives in **one file**, created once and then never overwritten:
259
+ Everything you configure lives in **one place**, created once and then never overwritten
260
+ by the installer:
233
261
 
234
- .goblin/goblin.yaml
262
+ AGENTS.md — the `<!-- gob:begin --> ... <!-- gob:end -->` block
235
263
 
236
264
  Open it. The keys that matter on day one:
237
265
 
238
- class: software # software|service|game|research|fleet (A-E are aliases) - what kind of project this is (step 6)
266
+ class: software # software|service|game|research|fleet (A-E are aliases)
239
267
  branch: main # DECLARED, never assumed
240
268
  owner_email: you@example.com # the commit identity this repo expects
241
269
  practice: /path/to/your-standard.md # optional: your own house rules, hash-pinned
242
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
243
272
 
244
- gates: # <- replace these with YOUR real commands
245
- - name: commit
246
- cmd: git rev-parse --verify --quiet HEAD
247
- - name: todo_ceiling
248
- cmd: test "$(grep -rniE '\b(TODO|FIXME)\b' --include='*.ts' . | wc -l)" -le 160
249
-
250
- **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
251
274
  actually run to know your project is healthy. `tsc --noEmit`, `npm run build`, your test command —
252
275
  whichever three or four you would run before saying "this is fine."
253
276
 
@@ -259,7 +282,7 @@ without you remembering to. And the gate numbers are recorded with a date, so a
259
282
 
260
283
  If you already have a house standard — a `CONTRIBUTING.md`, a `PROJECT-PRACTICE.md`, anything
261
284
  written down — point `practice:` at it. gobstack does **not** copy its text. It records a
262
- **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.
263
286
 
264
287
  That buys you one specific, valuable thing: **if someone edits your standard, every project that
265
288
  pins it goes red.** You find out immediately instead of discovering six months later that half your
@@ -269,8 +292,8 @@ When *you* legitimately edit your own standard:
269
292
 
270
293
  gob install --target . --re-pin
271
294
 
272
- It re-records the hash and prints the old and new value. Nothing re-pins automatically — an
273
- 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.
274
297
 
275
298
  ---
276
299
 
@@ -294,10 +317,10 @@ gate, not a sixth class. The old `F` letter still resolves there as an install a
294
317
 
295
318
  - A repo that holds *output* while the code lives elsewhere → **research**, not **software**. Gating
296
319
  it like an application gates the wrong artifact.
297
- - A plain input directory that is not a build target → **research** with `--archive`, which tells
320
+ - A plain input directory that is not a build target → **research** with `archive: true`, which tells
298
321
  verify to expect no HANDOFF and no gates, and to say so.
299
322
 
300
- Switch class later by editing `class:` in the config and re-running install. The parts you no longer
323
+ Switch class later by editing `class:` in the gob block and re-running install. The parts you no longer
301
324
  need are recorded as **disabled** and will report `SKIP (opt-out)` rather than failing.
302
325
 
303
326
  ---
@@ -324,7 +347,7 @@ Step by step:
324
347
  # 2. make your change, committing in small steps
325
348
 
326
349
  # 3. run the gate
327
- .goblin/bin/goblin-verify
350
+ .gob/bin/goblin-verify
328
351
 
329
352
  # 4. write the handoff: state / gates / next steps / NOT verified
330
353
 
@@ -345,16 +368,16 @@ honest entry, and the harness treats it as one.
345
368
  > **Prove it was broken first.**
346
369
 
347
370
  Before you trust a check, break the thing it checks and watch it go red — then put it back and watch
348
- it go green. Break it on a row this walkthrough can actually break: `IN-02` hashes the **16 files it
349
- tracks** — not the 8 it `owns` (including `.goblin/goblin.yaml`, which §5 has you editing) and not
350
- `.goblin/installed.json`; edit one of the 16 — the exercise below uses `.goblin/bans/README.md`.
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`.
351
374
 
352
375
  # REPLAY-BEGIN (this exact block is run by tests/t-doc-guide.sh - keep the two copies identical)
353
- .goblin/bin/goblin-verify --only IN-02 # expect PASS
354
- printf '\n<!-- a deliberate edit -->\n' >> .goblin/bans/README.md
355
- .goblin/bin/goblin-verify --only IN-02 # expect FAIL
356
- git stash push -- .goblin/bans/README.md # path-limited: your own edits stay put
357
- .goblin/bin/goblin-verify --only IN-02 # expect PASS
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
358
381
  git stash drop # the break was deliberate: discard it
359
382
  # REPLAY-END
360
383
 
@@ -363,10 +386,10 @@ That is the whole habit — the change you *undo* is a deliberate break, not a f
363
386
  measures the shipped files rather than your work.
364
387
 
365
388
  `GT-02` is the row most readers reach for first, and it will **not** work as a REPLAY demo on the
366
- shipped configuration: it runs the gates you declared (`commit`, `todo_ceiling`), and stashing a
389
+ shipped configuration: it runs the gates you declared, and stashing a
367
390
  local change does not change either command's exit status — so it prints `PASS` before and after,
368
391
  which is exactly the "green on both trees" result this rule exists to kill. REPLAY a gate of your
369
- own the same way, once that gate is real: declare it in `.goblin/goblin.yaml` and stash a change it
392
+ own the same way, once that gate is real: declare it in the gob block and stash a change it
370
393
  can see.
371
394
 
372
395
  A check that is green on **both** the broken and the fixed tree proves nothing — it would have been
@@ -377,7 +400,7 @@ caught every real regression in this repository's own development history.
377
400
 
378
401
  ## 8. Step 6 — The daily loop, once you are settled
379
402
 
380
- Day to day, the harness should fade into four habits:
403
+ Day to day, the harness should fade into three habits:
381
404
 
382
405
  **Starting work** — read `HANDOFF.md` first. It tells you the state, the gates, what is next, and —
383
406
  most importantly — **what is *not* verified**. Never trust a claim in it without running the
@@ -388,15 +411,7 @@ the harness nudges you to land things as they work rather than in one heroic com
388
411
 
389
412
  **Finishing** — update `HANDOFF.md`, then:
390
413
 
391
- .goblin/bin/goblin-verify && git add -A && git commit -m "..."
392
-
393
- **Every so often** — audit your own claims against the artifact:
394
-
395
- .goblin/bin/goblin-audit
396
-
397
- This is the *only* step that touches the network (rule `SC-07`), and it is deliberate: it is how a
398
- recorded claim ("this dependency is fine") gets checked against reality ("this dependency has a
399
- known advisory").
414
+ .gob/bin/goblin-verify && git add -A && git commit -m "..."
400
415
 
401
416
  ### Keeping `HANDOFF.md` honest
402
417
 
@@ -430,18 +445,18 @@ the next session.
430
445
 
431
446
  ## 9. What to expect on day one (so you do not misread it)
432
447
 
433
- A software-class install through the wizard lands on a specific shape. Two of the first reds are
434
- the scaffold teaching on purpose — `HP-05`, the `0000000` placeholder in `HANDOFF.md` (§4), and
435
- `GT-02`, the default gate pointing at a test script a throwaway repo does not have. The walk in §4
436
- 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:
437
451
 
438
- 31 passed, 6 failed, 11 advisory, 34 skipped # straight after the wizard, nothing committed
439
- 35 passed, 2 failed, 11 advisory, 34 skipped # first commit: HP-05 and GT-02 left
440
- 36 passed, 1 failed, 11 advisory, 34 skipped # real HEAD named and committed: GT-02 left
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
441
455
 
442
- Name a real commit in `HANDOFF.md`, commit, and give `gates:` real commands (§5), and it is green:
456
+ Name a real commit in `HANDOFF.md`, commit, and give the gate lines real commands (§5), and it is
457
+ green:
443
458
 
444
- 36 passed, 0 failed, 11 advisory, 34 skipped (on a real project; your numbers will differ)
459
+ 37 passed, 0 failed, 11 advisory, 34 skipped (on a real project; your numbers will differ)
445
460
 
446
461
  **Thirty-four rows skipping is correct**, and each skip prints its reason. In plain terms: the
447
462
  harness is telling you which of its rules have nothing to read yet. It is a checklist, not a
@@ -467,9 +482,9 @@ Two readings that are easy to get wrong:
467
482
  | Symptom | What it means | What to do |
468
483
  |---|---|---|
469
484
  | `refused to overwrite: HANDOFF.md`, exit 1 | your repo already had a HANDOFF | **do not `--force`** — reconcile it (below) |
470
- | `PT-02 declared main, actual master` | branch mismatch | set `branch:` in the config |
485
+ | `PT-02 declared main, actual master` | branch mismatch | set `branch:` in the gob block |
471
486
  | `IN-02 ... practice EDITED` | someone changed the pinned standard | re-pin deliberately: `--re-pin` |
472
- | `gob install: unknown subcommand` (exit 2) | you ran a bare `gob install` without the npm package installed | install the npm package first: `npm i -g @techgoblin/gobstack`, then `gob install` |
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 |
473
488
  | `IN-03` fails, "manifest is broken" | a row has a broken check column | fix the row; this is a source defect, not yours |
474
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 |
475
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 |
@@ -479,37 +494,15 @@ replaces your project's own record with a blank scaffold — the exact act the r
479
494
  prevent. Reconcile instead: keep your file, and add the five sections it is missing. The measured
480
495
  cost of that edit, on a real 2450-line handoff, was **15 lines added, none removed**.
481
496
 
482
- **One engine, many repos:** the rule table does not have to live in every repo. A repo can
483
- point at a shared engine with one line in `.goblin/goblin.yaml`:
484
-
485
- engine_dir: ~/.goblin/engine # absolute or ~/-prefixed; absent = per-repo engine
486
-
487
- Declared but unusable (relative path, missing directory, no manifest inside) is verify **exit 2
488
- with no fallback** — a repo is never judged by an engine it did not declare. A repo whose record
489
- says `mode=global` keeps hashing whatever files it still holds; the engine's own identity prints in
490
- every run's footer (`engine: mode=… cli_sha256=… enforcement_tsv_sha256=…`). The same commands are
491
- available outside any repo through the npm CLI: `gob verify` / `gob bans` / `gob audit` /
492
- `gob doctor` / `gob sync` / `gob upgrade` / `gob --version`.
493
-
494
- **Migrating a repo to the global engine:**
495
-
496
- gob upgrade # 8 steps, two commits, one report
497
-
498
- It refuses on a dirty tree, a detached HEAD, a red repo, or a global engine holding different
499
- bytes — each refusal names the fix. What it does: verifies every recorded hash, lands the engine
500
- at `~/.goblin/engine` (or `--engine-dir <dir>`) from this repo's own verified bytes, commits the
501
- declaration + record rewrite + `checks/gate.sh` + CI re-point (commit A), proves the repo green
502
- with both engines present, then `git rm`s exactly the 18 engine files (commit B) and proves green
503
- again. Nothing is deleted before the engine is safely landed and the tree is green mid-sequence.
504
-
505
- **Rolling back a migration** — the two commits are pure git operations:
506
-
507
- git revert <commit-A-sha> <commit-B-sha>
508
-
509
- reverses byte-for-byte: the vendored payload returns, the record drops its `engine:` block, and
510
- `gob verify` is the 43-green it was before. A second `gob upgrade` on a migrated repo is a
511
- no-op; `goblin-install` onto one refuses with the revert remedy (re-installing would re-shadow the
512
- 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`.
513
506
 
514
507
  **Two exit-code contracts worth knowing:**
515
508
 
@@ -517,8 +510,7 @@ engine and silently de-migrate the record).
517
510
  |---|---|
518
511
  | `goblin-install` | `0` ok · `1` a refusal (with the path and the fix) · `2` bad input |
519
512
  | `goblin-verify` | `0` all checks passed · `1` a check failed · `2` could not run · `3` the manifest itself is broken |
520
- | `goblin` (npm CLI) | propagates the subcommand's codes verbatim — `verify`/`bans`/`audit`/`--version`; `install`/`uninstall`/`re-pin`/`upgrade` route into `goblin-install` (`upgrade` migrates to the global engine: `0` ok · `1` refusal · `2` bad input); `doctor`/`emit` carry the same contract: `doctor` exits `0` every probed platform DETECTED and clean · `1` any DRIFT · `2` nothing to probe, and `emit` exits `0` ok or no-op · `1` refusal (with the path and the fix) · `2` bad input or unknown platform; `sync` is the same verb renamed and propagates identically |
521
- | 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 |
522
514
 
523
515
  `3` is the one to notice: it means gobstack's own rule table is malformed, not your project.
524
516
 
@@ -528,16 +520,34 @@ engine and silently de-migrate the record).
528
520
 
529
521
  ### Commands
530
522
 
531
- gob install --target <dir> --class <software|service|game|research|fleet> [options]
532
- gob install --target <dir> --uninstall
533
- gob install --target <dir> --re-pin
534
- gob install --target <dir> --upgrade
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)
535
527
 
536
- .goblin/bin/goblin-verify [--only <id[,id...]>] [--json] [--list]
537
- .goblin/bin/goblin-audit # the only network step
538
- .goblin/bin/goblin-bans # run the ban list
528
+ .gob/bin/goblin-verify [--only <id[,id...]>] [--json] [--list]
529
+ .gob/bin/goblin-bans # run the ban list
530
+ gob install --target <dir> --uninstall # the uninstall job
531
+ gob install --target <dir> --re-pin # the deliberate re-pin
539
532
  bin/goblin-model <role> # checkout-only; resolve a role to a profile (docs/ROLES.md)
540
533
 
534
+ ### Register the harness with your agent (MCP)
535
+
536
+ Your agent can call the discipline gate itself instead of you pasting verify output into the
537
+ chat. `gob mcp` is a local tool server (JSON-RPC over stdin/stdout — the Model Context
538
+ Protocol shape); it exposes `gob_verify` (the gate, with the remedy line under every FAIL),
539
+ `gob_map_status` (the feature map, read-only) and `gob_init_status` (is this repo under the
540
+ harness). It calls no API and opens no socket.
541
+
542
+ The one-liner, per user account:
543
+
544
+ claude mcp add gob -- npx -y @techgoblin/gobstack mcp
545
+
546
+ or, committed with the repo so every teammate's agent picks it up (Claude Code and Cursor
547
+ auto-detect it):
548
+
549
+ gob init --with-mcp-config # writes .mcp.json; never overwrites one you customized
550
+
541
551
  ### The 15 playbooks
542
552
 
543
553
  Named procedures, installed as project-local skills. Each has a measurable verification step.
@@ -565,7 +575,7 @@ Named procedures, installed as project-local skills. Each has a measurable verif
565
575
  | File | Read it for |
566
576
  |---|---|
567
577
  | `docs/DESIGN.md` | the thesis and every rejected alternative |
568
- | `docs/GLOSSARY.md` | every term of art in one table (rendered from `.goblin/manifest/glossary.tsv`) |
578
+ | `docs/GLOSSARY.md` | every term of art in one table (rendered from `.gob/manifest/glossary.tsv`) |
569
579
  | `docs/RECORD-NOTES.md` | the wave codes the changelog uses, one line each |
570
580
  | `docs/FLOWS.md` | the playbooks in full, with reasons |
571
581
  | `docs/ENFORCEMENT.md` | the rule matrix, rendered for a human |
@@ -573,7 +583,7 @@ Named procedures, installed as project-local skills. Each has a measurable verif
573
583
  | `docs/RISKS.md` | the risk register and non-goals |
574
584
  | `docs/CONTRACTS.md` | exact interface, exit codes, uninstall |
575
585
  | `docs/ADOPTION.md` | classes, presets, adoption order |
576
- | `docs/CI.md`, `docs/LOOP.md`, `docs/GUARDRAILS.md` | the newer lanes |
586
+ | `docs/LOOP.md`, `docs/GUARDRAILS.md` | the newer lanes |
577
587
 
578
588
  ---
579
589
 
@@ -592,64 +602,63 @@ Stated plainly, because a guide that oversells its tool is worse than no guide:
592
602
  - **It is not a product.** It is a repository of files, installed into other repositories.
593
603
  No service, no daemon, no support contract.
594
604
 
595
- The current status, if you want the honest number: a separate review pass verified the artifact at
596
- **9/10** (that was 0.4.2), and the point it withheld was not a missing feature — it was sentences
597
- in the record that a measurement contradicted. `docs/LIMITS.md` is the list of what the harness
598
- cannot see.
599
-
600
605
  ---
601
606
 
602
607
  ## 13. Where to go next
603
608
 
604
- **If you only do one thing:** install into your most active repo today, set your real `gates:`, and
605
- run `goblin-verify` once a day for a week. The habit, not the tool, is what produces the result.
609
+ **If you only do one thing:** install into your most active repo today, set your real gate
610
+ commands, and run `goblin-verify` once a day for a week. The habit, not the tool, is what produces
611
+ the result.
606
612
 
607
613
  **Then, in order:**
608
614
 
609
615
  1. Point `practice:` at your existing house standard and pin it.
610
616
  2. Write one `AC:` item that a script could check, and make it pass.
611
617
  3. Add a ban for the one pattern you are tired of seeing in agent-written code
612
- (`.goblin/manifest/bans.tsv` — a ban without a mechanism is a wish, so give it one).
618
+ (`.gob/manifest/bans.tsv` — a ban without a mechanism is a wish, so give it one).
613
619
  4. When you have a bug that a test could catch, walk P5 (`goblin-tdd-repro`) end to end once.
614
620
 
615
- **If you are sharing this with a team:** the parts that matter are `HANDOFF.md`, the `gates:` you
616
- declare, and the REPLAY habit. The rest is optional machinery you can switch off per class. Lead
617
- with *"prove it was broken first"* — it is the one practice that survives contact with a deadline.
621
+ **If you are sharing this with a team:** the parts that matter are `HANDOFF.md`, the gate commands
622
+ you declare, and the REPLAY habit. The rest is optional machinery you can switch off per class.
623
+ Lead with *"prove it was broken first"* — it is the one practice that survives contact with a
624
+ deadline.
618
625
 
619
626
  ---
620
627
 
621
628
  ## Appendix — a 45-minute first run, on one page
622
629
 
623
630
  # 0. get it
624
- npm i -g @techgoblin/gobstack
631
+ npx @techgoblin/gobstack init # or: npm i -g @techgoblin/gobstack
625
632
 
626
633
  # 1. try it somewhere disposable
627
634
  mkdir -p /tmp/gs-try && cd /tmp/gs-try
628
635
  git init -b main
629
- gob install --target . --class software # expect: created 25 (no skills — those are gob sync)
636
+ gob init --heuristic # the brief + schema; answer it in a proposal file
637
+ gob init --write .gob-init-proposal.md --yes
638
+ # expect: created 23 (no skills — those are opt-in)
630
639
 
631
640
  # 2. commit and check
632
641
  git add -A && git commit -m "chore: install gobstack"
633
- .goblin/bin/goblin-verify # expect: mostly PASS, some SKIP
642
+ .gob/bin/goblin-verify # expect: mostly PASS, some SKIP
634
643
 
635
644
  # 3. make it yours
636
- $EDITOR .goblin/goblin.yaml # branch, owner_email, and YOUR real gates:
645
+ $EDITOR AGENTS.md # branch, owner_email, and YOUR real gate commands (the gob block)
637
646
 
638
647
  # 4. prove a check can fail (the habit that matters) - the same block §7 runs
639
648
  # REPLAY-BEGIN (this exact block is run by tests/t-doc-guide.sh - keep the two copies identical)
640
- .goblin/bin/goblin-verify --only IN-02 # expect PASS
641
- printf '\n<!-- a deliberate edit -->\n' >> .goblin/bans/README.md
642
- .goblin/bin/goblin-verify --only IN-02 # expect FAIL
643
- git stash push -- .goblin/bans/README.md # path-limited: your own edits stay put
644
- .goblin/bin/goblin-verify --only IN-02 # expect PASS
649
+ .gob/bin/goblin-verify --only IN-02 # expect PASS
650
+ printf '\n<!-- a deliberate edit -->\n' >> .gob/bans/README.md
651
+ .gob/bin/goblin-verify --only IN-02 # expect FAIL
652
+ git stash push -- .gob/bans/README.md # path-limited: your own edits stay put
653
+ .gob/bin/goblin-verify --only IN-02 # expect PASS
645
654
  git stash drop # the break was deliberate: discard it
646
655
  # REPLAY-END
647
656
 
648
657
  # 5. do it for real, in a repo you care about
649
658
  cd ~/projects/your-project
650
- gob install --target . --class software
659
+ gob init --write .gob-init-proposal.md --yes
651
660
  git add -A && git commit -m "chore: adopt gobstack"
652
- .goblin/bin/goblin-verify
661
+ .gob/bin/goblin-verify
653
662
  $EDITOR HANDOFF.md # state / gates (dated!) / next / NOT verified
654
663
 
655
664
  ---