@techgoblin/gobstack 0.0.0-stage → 0.4.4-beta.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.
Files changed (108) hide show
  1. package/CHANGELOG.md +351 -0
  2. package/LICENSE +21 -0
  3. package/README.md +217 -2
  4. package/VERSION +1 -0
  5. package/adapters/_template/adapter.tsv +16 -0
  6. package/adapters/_template/detect.sh +10 -0
  7. package/adapters/_template/emit.sh +5 -0
  8. package/adapters/_template/verify.sh +4 -0
  9. package/adapters/claude/adapter.tsv +8 -0
  10. package/adapters/claude/detect.sh +8 -0
  11. package/adapters/claude/verify.sh +47 -0
  12. package/adapters/codex/adapter.tsv +12 -0
  13. package/adapters/codex/detect.sh +9 -0
  14. package/adapters/codex/verify.sh +45 -0
  15. package/adapters/copilot/adapter.tsv +10 -0
  16. package/adapters/copilot/detect.sh +8 -0
  17. package/adapters/copilot/verify.sh +45 -0
  18. package/adapters/cursor/adapter.tsv +11 -0
  19. package/adapters/cursor/detect.sh +10 -0
  20. package/adapters/cursor/verify.sh +45 -0
  21. package/adapters/gemini/adapter.tsv +15 -0
  22. package/adapters/gemini/detect.sh +11 -0
  23. package/adapters/gemini/verify.sh +49 -0
  24. package/adapters/hermes/adapter.tsv +9 -0
  25. package/adapters/hermes/detect.sh +8 -0
  26. package/adapters/hermes/verify.sh +27 -0
  27. package/adapters/opencode/adapter.tsv +14 -0
  28. package/adapters/opencode/detect.sh +9 -0
  29. package/adapters/opencode/verify.sh +45 -0
  30. package/automations/README.md +53 -0
  31. package/automations/bugreporter-intake.sh +145 -0
  32. package/automations/drift-audit.sh +139 -0
  33. package/automations/report.schema.tsv +10 -0
  34. package/bans/README.md +82 -0
  35. package/bans/grep-ban.sh +84 -0
  36. package/bans/layer-check.sh +57 -0
  37. package/bin/goblin +119 -0
  38. package/bin/goblin-audit +145 -0
  39. package/bin/goblin-bans +178 -0
  40. package/bin/goblin-doctor +233 -0
  41. package/bin/goblin-emit +484 -0
  42. package/bin/goblin-init +519 -0
  43. package/bin/goblin-install +720 -0
  44. package/bin/goblin-lib.sh +289 -0
  45. package/bin/goblin-model +105 -0
  46. package/bin/goblin-upgrade +572 -0
  47. package/bin/goblin-verify +2798 -0
  48. package/bin/goblin.js +103 -0
  49. package/docs/ADOPTION.md +168 -0
  50. package/docs/CI.md +187 -0
  51. package/docs/CONTRACTS.md +197 -0
  52. package/docs/DESIGN.md +92 -0
  53. package/docs/ENFORCEMENT.md +225 -0
  54. package/docs/FLOWS.md +164 -0
  55. package/docs/GUARDRAILS.md +126 -0
  56. package/docs/GUIDE.md +610 -0
  57. package/docs/INTEGRATION.md +92 -0
  58. package/docs/LIMITS.md +591 -0
  59. package/docs/LOOP.md +165 -0
  60. package/docs/RE-PLAYBOOK.md +183 -0
  61. package/docs/RISKS.md +70 -0
  62. package/docs/ROLES.md +105 -0
  63. package/manifest/bans.tsv +9 -0
  64. package/manifest/classes.tsv +61 -0
  65. package/manifest/enforcement.tsv +88 -0
  66. package/manifest/glossary.tsv +25 -0
  67. package/manifest/playbooks.tsv +16 -0
  68. package/package.json +37 -4
  69. package/presets/A-shipped-software.yaml +48 -0
  70. package/presets/B-service-config.yaml +40 -0
  71. package/presets/C-game.yaml +38 -0
  72. package/presets/D-knowledge.yaml +41 -0
  73. package/presets/E-fleet-config.yaml +42 -0
  74. package/presets/F-electron.yaml +67 -0
  75. package/roles.yaml +54 -0
  76. package/skills/goblin-bootstrap/SKILL.md +51 -0
  77. package/skills/goblin-bugfix/SKILL.md +26 -0
  78. package/skills/goblin-bugreporter/SKILL.md +52 -0
  79. package/skills/goblin-drift-audit/SKILL.md +43 -0
  80. package/skills/goblin-eval/SKILL.md +68 -0
  81. package/skills/goblin-feature/SKILL.md +26 -0
  82. package/skills/goblin-feature-map/SKILL.md +140 -0
  83. package/skills/goblin-handoff/SKILL.md +28 -0
  84. package/skills/goblin-investigation/SKILL.md +26 -0
  85. package/skills/goblin-judge/SKILL.md +74 -0
  86. package/skills/goblin-loop/SKILL.md +88 -0
  87. package/skills/goblin-mode/SKILL.md +70 -0
  88. package/skills/goblin-overnight/SKILL.md +42 -0
  89. package/skills/goblin-pr-gate/SKILL.md +42 -0
  90. package/skills/goblin-re-mobile/SKILL.md +51 -0
  91. package/skills/goblin-refactor/SKILL.md +23 -0
  92. package/skills/goblin-sweep/SKILL.md +23 -0
  93. package/skills/goblin-tdd-repro/SKILL.md +27 -0
  94. package/skills/goblin-verify-author/SKILL.md +50 -0
  95. package/skills/practice/SKILL.md +37 -0
  96. package/templates/AGENTS.md.tmpl +23 -0
  97. package/templates/HANDOFF.md.tmpl +43 -0
  98. package/templates/SPEC.md.tmpl +34 -0
  99. package/templates/audit-waiver.tsv.tmpl +10 -0
  100. package/templates/boundary-waivers.tmpl +8 -0
  101. package/templates/checks/assert.mjs.tmpl +60 -0
  102. package/templates/checks/gate.sh.tmpl +29 -0
  103. package/templates/ci/goblin-gate.yml.tmpl +46 -0
  104. package/templates/goblin.yaml.tmpl +138 -0
  105. package/templates/install-hooks.allowlist.tmpl +9 -0
  106. package/templates/loop/decisions.tsv.tmpl +1 -0
  107. package/templates/loop/predicate.tmpl +16 -0
  108. package/templates/report.yaml.tmpl +16 -0
package/docs/GUIDE.md ADDED
@@ -0,0 +1,610 @@
1
+ # Getting started with gobstack
2
+
3
+ A step-by-step guide for your first week. **Read this before the README.** The README tells you
4
+ what the pieces are; this tells you what to *do*, in order, and what you should see when it works.
5
+
6
+ Version: `0.4.4` · Last measured: 2026-09-25 · Every command and every output below was run on a
7
+ real repository while writing this guide.
8
+
9
+ ---
10
+
11
+ ## 0. Who this is for, and what you will have at the end
12
+
13
+ This guide assumes you are a developer who uses an AI coding agent and has noticed the same three
14
+ problems everyone notices:
15
+
16
+ 1. **A new session re-improvises.** The agent forgets how you work, what you decided last week,
17
+ which commands matter. Every session starts from zero.
18
+ 2. **"It works" is a claim, not a measurement.** The agent says it fixed something. You have no
19
+ cheap way to know whether that is true.
20
+ 3. **Rules live in prose.** You write them down, the agent reads them, and nothing enforces them —
21
+ so they rot silently, and you find out months later.
22
+
23
+ By the end of this guide you will have a repository that fixes those three things *mechanically*:
24
+ one file a new session reads first, a checker that proves a change is a change, and a rule table
25
+ where every rule either runs a command or is explicitly counted as unenforceable.
26
+
27
+ **Time budget:** about 45 minutes to work through it once. You do not need to understand the whole
28
+ design on day one.
29
+
30
+ ---
31
+
32
+ ## 1. What this actually is, in plain language
33
+
34
+ goblin-stack (published as the npm package **`@techgoblin/gobstack`**, product name **gobstack**)
35
+ is **a folder of files you install into a project** from npm. Once
36
+ installed, three things change:
37
+
38
+ - A file called `HANDOFF.md` sits at the root. It is the note from the last session to the next one.
39
+ Any agent — or you, a month later — reads it first.
40
+ - A command called `goblin-verify` exists in that project. Run it and it checks the project against
41
+ a table of rules and prints `PASS` / `FAIL` / `SKIP` for each one.
42
+ - The rules table is a real file (`.goblin/manifest/enforcement.tsv`). Every row either names a
43
+ command that can fail, or is labelled `advisory`. **Nothing in between.** That is what stops the
44
+ rules turning into decoration.
45
+
46
+ It is not a framework, not a service, and not a runtime. It has no server and no dependencies
47
+ beyond `bash`, `git`, `awk`, `sed`, `grep` and `python3`. It makes **no network call at verify
48
+ time** — the one command in the toolbox that reaches the network is `goblin-audit`, which you run
49
+ deliberately, and §8 and §11 say why.
50
+
51
+ ### The one idea worth holding onto
52
+
53
+ > **A rule that cannot fail is worse than no rule**, because it takes credit for verification it
54
+ > does not perform.
55
+
56
+ Everything else in goblin-stack follows from that sentence. If you remember one thing from this
57
+ guide, remember that one — it is also the standard the harness holds itself to, and the reason it
58
+ ships a file of things it *cannot* check (`docs/LIMITS.md`).
59
+
60
+ ---
61
+
62
+ ## 2. Before you begin
63
+
64
+ **You need:**
65
+
66
+ | | |
67
+ |---|---|
68
+ | `bash`, `git`, `awk`, `sed`, `grep`, `python3` | already on any Linux/macOS box |
69
+ | a project that is a **git repository** | `git status` must work; the harness reads commit identity |
70
+ | a branch named the same as the one you declare | see step 3 — a `master`/`main` mismatch is the most common first failure |
71
+
72
+ You need node ≥ 18 (for the npm shim only), beyond the row above.
73
+
74
+ **You do *not* need:** network access at verify time, or an agent running.
75
+
76
+ **Get gobstack:**
77
+
78
+ npm i -g @techgoblin/gobstack
79
+
80
+ This puts a single command, `goblin`, on your PATH — the node shim over the bash engine, and the
81
+ one way this guide installs it.
82
+
83
+ ---
84
+
85
+ ## 3. Step 1 — Try it on a throwaway repo first (5 minutes)
86
+
87
+ **Do not install into a real project yet.** You want to see what it does before it touches
88
+ something you care about.
89
+
90
+ The guided path is `goblin init` — one screen per question (class, branch/email, first
91
+ gate, which platforms to emit), every question also answerable by flag, `--dry-run` to
92
+ see the plan first:
93
+
94
+ mkdir -p /tmp/gs-try && cd /tmp/gs-try
95
+ git init -b main
96
+ git config user.email "you@example.com"
97
+ git config user.name "you"
98
+
99
+ goblin init --target . --class app --branch main --email "you@example.com" \
100
+ --gate "bash tests/run-tests.sh" --yes
101
+
102
+ or the plain installer this wizard drives, if you prefer the one-shot shape:
103
+
104
+ goblin install --target . --class A
105
+
106
+ Expected output (this is a real transcript, trimmed):
107
+
108
+ created 50 · updated 0 · unchanged 0 · skipped 0
109
+
110
+ next:
111
+ 1. cd /tmp/gs-try && git add -A && git commit # the install is a change like any other
112
+ 2. .goblin/bin/goblin-verify # or add .goblin/bin to PATH
113
+ 3. edit .goblin/goblin.yaml: replace the default gate with your real commands (P8 step 3)
114
+ 4. hermes skills trust /tmp/gs-try # one-time, so the project-tier skills load
115
+
116
+ **`created 50`** is the installer's count of the files it **tracks** — the 41 in its `files` map,
117
+ the 8 it `owns`, and `.gitignore`. It writes **51**: the 51st is `.goblin/installed.json`, the
118
+ record it keeps for itself, which it writes but does not count. It has written nothing outside this
119
+ directory.
120
+
121
+ ### Why `git init -b main` matters
122
+
123
+ The harness **declares** your default branch rather than assuming it (rule `PT-02`). If your repo's
124
+ branch is `master` and the config says `main`, verify fails on the very first run:
125
+
126
+ FAIL PT-02 declared main, actual master
127
+
128
+ That is not a bug — it is the harness refusing to guess, which is the same reason it fails instead
129
+ of silently skipping a repo whose branch it got wrong. **Fix it in step 3, not by renaming your
130
+ branch** (unless you want to).
131
+
132
+ ---
133
+
134
+ ## 4. Step 2 — Commit, then verify (the moment it earns its keep)
135
+
136
+ cd /tmp/gs-try
137
+ git add -A && git commit -m "chore: install goblin-stack"
138
+ .goblin/bin/goblin-verify
139
+
140
+ You will see one line per rule. The shape:
141
+
142
+ PASS IN-01 (test -s .goblin/installed.json && grep -q '"version"' .goblin/installed.json)
143
+ PASS IN-02 40 installed files hashed | practice pin ok
144
+ FAIL HP-05 HANDOFF.md names no commit that exists in this repo
145
+ SKIP HS-02 no pinned pre-change commit yet - the REPLAY is not provable
146
+ ADV HP-04 A stale sentence is corrected in place... (advisory)
147
+
148
+ and a summary line at the bottom:
149
+
150
+ 42 passed, 1 failed, 11 advisory, 28 skipped # the one FAIL is HP-05, below
151
+
152
+ ### How to read that output
153
+
154
+ | Marking | Meaning | What you do |
155
+ |---|---|---|
156
+ | `PASS` | the rule's command succeeded | nothing |
157
+ | `FAIL` | the rule's command failed, and the message says why | fix it — this is the whole point |
158
+ | `SKIP` | the rule cannot run **yet**, and it says why | usually expected on day one |
159
+ | `ADV` | advisory — a rule with no runnable check, **counted** | nothing, but know it is not enforced |
160
+
161
+ **`SKIP` is not success and not failure.** It is the harness telling you the truth: "this rule has
162
+ nothing to read yet." On a brand-new install, two dozen rows skip — because there is no `src/` for a
163
+ ban to scan, no feature map, no loop record, no pinned pre-change commit. That is correct on day
164
+ one. The list of what is still skipping *is* your onboarding checklist.
165
+
166
+ **Read the failure messages.** They are written to be actionable, not decorative. `HP-05` above is
167
+ telling you the HANDOFF does not yet name a commit — fix it by naming your HEAD in the `State`
168
+ section.
169
+
170
+ ### The three-day-one failures, and why they are not a broken harness
171
+
172
+ If you ran step 1 without `-b main`, or with the wrong git identity, you will see:
173
+
174
+ | FAIL | Cause | Fix |
175
+ |---|---|---|
176
+ | `PT-02 declared main, actual master` | branch name mismatch | set `branch:` in `.goblin/goblin.yaml` |
177
+ | `CM-01` (commit identity) | the repo's commit email ≠ the declared `owner_email:` | set `owner_email:` in the config |
178
+ | `HP-05` | `HANDOFF.md` still names the scaffold placeholder `` `0000000` `` | replace it with your real short HEAD |
179
+
180
+ **All three are configuration, not defects.** The harness is reporting your repo's actual state
181
+ against a declared expectation. That is exactly what you want it to do.
182
+
183
+ `HP-05` deserves one sentence more, because it surprises people: the scaffold ships
184
+ `HEAD when this file was written: `0000000``, and `HP-05` **rejects that placeholder on purpose**.
185
+ A file that names a commit which does not exist is worse than one that names none — it looks like a
186
+ record. Commit first, then write the real short SHA in. Measured: with the placeholder left in,
187
+ verify reports `42 passed, 1 failed`; with the real SHA, `43 passed, 0 failed`.
188
+
189
+ ---
190
+
191
+ ## 5. Step 3 — Make it yours: the one config file
192
+
193
+ Everything you configure lives in **one file**, created once and then never overwritten:
194
+
195
+ .goblin/goblin.yaml
196
+
197
+ Open it. The keys that matter on day one:
198
+
199
+ class: A # A|B|C|D|E|F - what kind of project this is (step 6)
200
+ branch: main # DECLARED, never assumed
201
+ owner_email: you@example.com # the commit identity this repo expects
202
+ practice: /path/to/your-standard.md # optional: your own house rules, hash-pinned
203
+ models_file: /path/to/fleet-model.yaml # the ONE machine-specific input
204
+
205
+ gates: # <- replace these with YOUR real commands
206
+ - name: commit
207
+ cmd: git rev-parse --verify --quiet HEAD
208
+ - name: todo_ceiling
209
+ cmd: test "$(grep -rniE '\b(TODO|FIXME)\b' --include='*.ts' . | wc -l)" -le 160
210
+
211
+ **The single most valuable edit you will make:** replace the default `gates:` with the commands you
212
+ actually run to know your project is healthy. `tsc --noEmit`, `npm run build`, your test command —
213
+ whichever three or four you would run before saying "this is fine."
214
+
215
+ Why it matters: from then on, `goblin-verify` runs *your* definition of healthy, every time,
216
+ without you remembering to. And the gate numbers are recorded with a date, so a number in
217
+ `HANDOFF.md` can never quietly go stale.
218
+
219
+ ### The `practice:` key — the part that makes it yours
220
+
221
+ If you already have a house standard — a `CONTRIBUTING.md`, a `PROJECT-PRACTICE.md`, anything
222
+ written down — point `practice:` at it. goblin-stack does **not** copy its text. It records a
223
+ **hash** of the file and re-checks that hash on every verify.
224
+
225
+ That buys you one specific, valuable thing: **if someone edits your standard, every project that
226
+ pins it goes red.** You find out immediately instead of discovering six months later that half your
227
+ repos follow an old version.
228
+
229
+ When *you* legitimately edit your own standard:
230
+
231
+ goblin install --target . --re-pin
232
+
233
+ It re-records the hash and prints the old and new value. Nothing re-pins automatically — an
234
+ edited standard is never a silent no-op.
235
+
236
+ ---
237
+
238
+ ## 6. Step 4 — Pick the right class (this decides what you get)
239
+
240
+ A class is **not** a strictness level. It selects which parts are required, optional, or off, and it
241
+ supplies the default gate shape. Choose by asking *what does "done" mean here?*
242
+
243
+ | Class | Choose it when | "Done" means |
244
+ |---|---|---|
245
+ | **A · Shipped software** | an app, library, or tool users run | a gate set reports measured numbers and a round lands |
246
+ | **B · Service / config** | an API, schema, route, or deployment config | the contract is unchanged, or the change is deliberate and migrated |
247
+ | **C · Game** | a game | a suite is green **and** a human feel verdict exists |
248
+ | **D · Knowledge / research** | notes, a vault, a research directory | a question is answered with sources and is findable |
249
+ | **E · Agent-fleet config** | your agent's own config (`~/.hermes`) | the change is applied, verified against the artifact, versioned |
250
+ | **F · Desktop shell** | an Electron / desktop app | renderer isolated from Node, main process not busy, no dev dependency shipped |
251
+
252
+ **Two placements people get wrong:**
253
+
254
+ - A repo that holds *output* while the code lives elsewhere → **D**, not A. Gating it like an
255
+ application gates the wrong artifact.
256
+ - A plain input directory that is not a build target → **D** with `--archive`, which tells verify to
257
+ expect no HANDOFF and no gates, and to say so.
258
+
259
+ Switch class later by editing `class:` in the config and re-running install. The parts you no longer
260
+ need are recorded as **disabled** and will report `SKIP (opt-out)` rather than failing.
261
+
262
+ ---
263
+
264
+ ## 7. Step 5 — Your first real change, end to end
265
+
266
+ Now do the thing the harness exists for. Pick a small real task in a real repo.
267
+
268
+ **The loop you are going to follow:**
269
+
270
+ 1. Write the intent down -> ROUND-001-SPEC.md
271
+ 2. Make the change
272
+ 3. Run the gate -> goblin-verify
273
+ 4. Record what you proved -> HANDOFF.md
274
+ 5. Commit as you go
275
+
276
+ Step by step:
277
+
278
+ # 1. Say what you are about to do, and how you will know it worked
279
+ cp ROUND-000-SPEC.md ROUND-001-SPEC.md
280
+ # edit it: state the measured problem, then a list of AC: items
281
+ # each AC: must be checkable by a machine - see below
282
+
283
+ # 2. make your change, committing in small steps
284
+
285
+ # 3. run the gate
286
+ .goblin/bin/goblin-verify
287
+
288
+ # 4. write the handoff: state / gates / next steps / NOT verified
289
+
290
+ ### Writing an `AC:` item that is worth writing
291
+
292
+ A spec item is only useful if a script could evaluate it. Compare:
293
+
294
+ - AC1: the export button feels responsive after the fix <- worthless, no machine can check it
295
+ - AC2: export completes in < 200ms for 1000 rows <- checkable
296
+ - AC3: `goblin-verify --only SP-03` exits 0 <- checkable, today
297
+
298
+ Rule `SP-03` actually fails a spec line that tries to pass prose off as a criterion. If the only
299
+ test is your own judgement, say so in the spec, in an explicit *device-test* item — that is an
300
+ honest entry, and the harness treats it as one.
301
+
302
+ ### The habit that makes the whole thing work
303
+
304
+ > **Prove it was broken first.**
305
+
306
+ Before you trust a check, break the thing it checks and watch it go red — then put it back and watch
307
+ it go green. Break it on a row this walkthrough can actually break: `IN-02` hashes the **41 files it
308
+ tracks** — not the 8 it `owns` (including `.goblin/goblin.yaml`, which §5 has you editing) and not
309
+ `.goblin/installed.json`; edit one of the 41 — the exercise below uses `.goblin/bans/README.md`.
310
+
311
+ # REPLAY-BEGIN (this exact block is run by tests/t-doc-guide.sh - keep the two copies identical)
312
+ .goblin/bin/goblin-verify --only IN-02 # expect PASS
313
+ printf '\n<!-- a deliberate edit -->\n' >> .goblin/bans/README.md
314
+ .goblin/bin/goblin-verify --only IN-02 # expect FAIL
315
+ git stash push -- .goblin/bans/README.md # path-limited: your own edits stay put
316
+ .goblin/bin/goblin-verify --only IN-02 # expect PASS
317
+ git stash drop # the break was deliberate: discard it
318
+ # REPLAY-END
319
+
320
+ Read the direction: the edit makes the check go **red**, and putting the file back makes it green.
321
+ That is the whole habit — the change you *undo* is a deliberate break, not a fix, because `IN-02`
322
+ measures the shipped files rather than your work.
323
+
324
+ `GT-02` is the row most readers reach for first, and it will **not** work as a REPLAY demo on the
325
+ shipped configuration: it runs the gates you declared (`commit`, `todo_ceiling`), and stashing a
326
+ local change does not change either command's exit status — so it prints `PASS` before and after,
327
+ which is exactly the "green on both trees" result this rule exists to kill. REPLAY a gate of your
328
+ own the same way, once that gate is real: declare it in `.goblin/goblin.yaml` and stash a change it
329
+ can see.
330
+
331
+ A check that is green on **both** the broken and the fixed tree proves nothing — it would have been
332
+ green anyway. goblin-stack calls this the **REPLAY** rule, and it is the single practice that has
333
+ caught every real regression in this repository's own development history.
334
+
335
+ ---
336
+
337
+ ## 8. Step 6 — The daily loop, once you are settled
338
+
339
+ Day to day, the harness should fade into four habits:
340
+
341
+ **Starting work** — read `HANDOFF.md` first. It tells you the state, the gates, what is next, and —
342
+ most importantly — **what is *not* verified**. Never trust a claim in it without running the
343
+ command it names.
344
+
345
+ **While working** — commit small. `CM-03` fails verify when the tree carries a dead run's work, so
346
+ the harness nudges you to land things as they work rather than in one heroic commit at the end.
347
+
348
+ **Finishing** — update `HANDOFF.md`, then:
349
+
350
+ .goblin/bin/goblin-verify && git add -A && git commit -m "..."
351
+
352
+ **Every so often** — audit your own claims against the artifact:
353
+
354
+ .goblin/bin/goblin-audit
355
+
356
+ This is the *only* step that touches the network (rule `SC-07`), and it is deliberate: it is how a
357
+ recorded claim ("this dependency is fine") gets checked against reality ("this dependency has a
358
+ known advisory").
359
+
360
+ ### Keeping `HANDOFF.md` honest
361
+
362
+ `HANDOFF.md` needs five sections, and rule `HP-02` checks the headings exist:
363
+
364
+ | Section | First word of the heading |
365
+ |---|---|
366
+ | orientation | `START HERE` |
367
+ | current state | `State` or `Status` |
368
+ | gates | `Gate` or `Gates` |
369
+ | next steps | `Next steps` or `Next` |
370
+ | what is not verified | `Not verified` / `Unverified` / `Not proven` |
371
+
372
+ Inside `Gates`, every number must carry a date:
373
+
374
+ - `tsc`=0 · `build`=0 · hex **144** (ceiling 160) · 38/38 harnesses green · measured 2026-09-24
375
+
376
+ **A number without a date is a rumour.** `HP-03` will fail it, and the reason is that a
377
+ measurement copied from last round is worse than no measurement — it *looks* verified.
378
+
379
+ **When a sentence in `HANDOFF.md` goes stale:** correct it in place with the date, and keep the
380
+ original:
381
+
382
+ > it used to say X. X was paid on 2026-09-20 (commit abc1234). The stale sentence is kept,
383
+ > dated, rather than deleted.
384
+
385
+ Deleting it erases the fact that it was once believed true; leaving it undated re-arms the trap for
386
+ the next session.
387
+
388
+ ---
389
+
390
+ ## 9. What to expect on day one (so you do not misread it)
391
+
392
+ A class-A install lands on a specific shape. The scaffold ships one deliberate red — `HP-05`, the
393
+ `0000000` placeholder in `HANDOFF.md` (§4) — so a literal first run prints:
394
+
395
+ 42 passed, 1 failed, 11 advisory, 28 skipped (the one FAIL is HP-05)
396
+
397
+ Name a real commit in `HANDOFF.md` and commit, and it is green:
398
+
399
+ 43 passed, 0 failed, 11 advisory, 28 skipped (on a real project; your numbers will differ)
400
+
401
+ **Twenty-eight rows skipping is correct**, and each skip prints its reason. In plain terms: the
402
+ harness is telling you which of its rules have nothing to read yet. It is a checklist, not a
403
+ scolding.
404
+
405
+ Two readings that are easy to get wrong:
406
+
407
+ - **Advisory rows are not passes.** Ten rules are labelled `advisory` — counted, not enforced, and
408
+ nine of them carry no executable check at all. The count is capped by `advisory_ceiling: 10`, and
409
+ a class-A install already sits at 10 of 10: adding another unenforceable rule fails verify until
410
+ one is removed. That is intentional. (The summary line can print `11 advisory`: the eleventh ADV
411
+ line is `JG-02`, a row with a real command of its own that reports ADV here because your model
412
+ file declares no `judge:` lane — it prints the remedy rather than failing a repo for a fleet's
413
+ routing.)
414
+ - **Vacuously-passing rows are not proven.** A rule about "the first review note" passes when there
415
+ is no review note yet. It is not lying — it is passing on an empty set. `docs/CONTRACTS.md`
416
+ names which rows do this.
417
+
418
+ ---
419
+
420
+ ## 10. When something goes wrong
421
+
422
+ | Symptom | What it means | What to do |
423
+ |---|---|---|
424
+ | `refused to overwrite: HANDOFF.md`, exit 1 | your repo already had a HANDOFF | **do not `--force`** — reconcile it (below) |
425
+ | `PT-02 declared main, actual master` | branch mismatch | set `branch:` in the config |
426
+ | `IN-02 ... practice EDITED` | someone changed the pinned standard | re-pin deliberately: `--re-pin` |
427
+ | `goblin install: unknown subcommand` (exit 2) | you ran a bare `goblin install` without the npm package installed | install the npm package first: `npm i -g @techgoblin/gobstack`, then `goblin install` |
428
+ | `IN-03` fails, "manifest is broken" | a row has a broken check column | fix the row; this is a source defect, not yours |
429
+ | 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 |
430
+
431
+ **The `HANDOFF.md` refusal is the most common one, and `--force` is never the answer.** `--force`
432
+ replaces your project's own record with a blank scaffold — the exact act the refusal exists to
433
+ prevent. Reconcile instead: keep your file, and add the five sections it is missing. The measured
434
+ cost of that edit, on a real 2450-line handoff, was **15 lines added, none removed**.
435
+
436
+ **One engine, many repos (W1):** the rule table does not have to live in every repo. A repo can
437
+ point at a shared engine with one line in `.goblin/goblin.yaml`:
438
+
439
+ engine_dir: ~/.goblin/engine # absolute or ~/-prefixed; absent = per-repo engine
440
+
441
+ Declared but unusable (relative path, missing directory, no manifest inside) is verify **exit 2
442
+ with no fallback** — a repo is never judged by an engine it did not declare. A repo whose record
443
+ says `mode=global` keeps hashing whatever files it still holds; the engine's own identity prints in
444
+ every run's footer (`engine: mode=… cli_sha256=… enforcement_tsv_sha256=…`). The same commands are
445
+ available outside any repo through the npm CLI: `goblin verify` / `goblin bans` / `goblin audit` /
446
+ `goblin doctor` / `goblin emit` / `goblin upgrade` / `goblin --version`.
447
+
448
+ **Migrating a repo to the global engine (W3):**
449
+
450
+ goblin upgrade # 8 steps, two commits, one report
451
+
452
+ It refuses on a dirty tree, a detached HEAD, a red repo, or a global engine holding different
453
+ bytes — each refusal names the fix. What it does: verifies every recorded hash, lands the engine
454
+ at `~/.goblin/engine` (or `--engine-dir <dir>`) from this repo's own verified bytes, commits the
455
+ declaration + record rewrite + `checks/gate.sh` + CI re-point (commit A), proves the repo green
456
+ with both engines present, then `git rm`s exactly the 18 engine files (commit B) and proves green
457
+ again. Nothing is deleted before the engine is safely landed and the tree is green mid-sequence.
458
+
459
+ **Rolling back a migration** — the two commits are pure git operations:
460
+
461
+ git revert <commit-A-sha> <commit-B-sha>
462
+
463
+ reverses byte-for-byte: the vendored payload returns, the record drops its `engine:` block, and
464
+ `goblin verify` is the 43-green it was before. A second `goblin upgrade` on a migrated repo is a
465
+ no-op; `goblin-install` onto one refuses with the revert remedy (re-installing would re-shadow the
466
+ engine and silently de-migrate the record).
467
+
468
+ **Two exit-code contracts worth knowing:**
469
+
470
+ | Command | Exit codes |
471
+ |---|---|
472
+ | `goblin-install` | `0` ok · `1` a refusal (with the path and the fix) · `2` bad input |
473
+ | `goblin-verify` | `0` all checks passed · `1` a check failed · `2` could not run · `3` the manifest itself is broken |
474
+ | `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 |
475
+ | 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) |
476
+
477
+ `3` is the one to notice: it means goblin-stack's own rule table is malformed, not your project.
478
+
479
+ ---
480
+
481
+ ## 11. Reference
482
+
483
+ ### Commands
484
+
485
+ goblin install --target <dir> --class A|B|C|D|E|F [options]
486
+ goblin install --target <dir> --uninstall
487
+ goblin install --target <dir> --re-pin
488
+ goblin install --target <dir> --upgrade
489
+
490
+ .goblin/bin/goblin-verify [--only <id[,id...]>] [--json] [--list]
491
+ .goblin/bin/goblin-audit # the only network step
492
+ .goblin/bin/goblin-bans # run the ban list
493
+ bin/goblin-model <role> # checkout-only; resolve a role to a profile (docs/ROLES.md)
494
+
495
+ ### The 15 playbooks
496
+
497
+ Named procedures, installed as project-local skills. Each has a measurable verification step.
498
+
499
+ | | Playbook | Use it when |
500
+ |---|---|---|
501
+ | P1 | `goblin-investigation` | a read-only question, or "why is this happening" |
502
+ | P2 | `goblin-bugfix` | a reported defect |
503
+ | P3 | `goblin-feature` | new behaviour |
504
+ | P4 | `goblin-refactor` | a behaviour-preserving reshape |
505
+ | P5 | `goblin-tdd-repro` | a defect where a regression test is cheap |
506
+ | P6 | `goblin-verify-author` | a project has no live check lane, or its gates drift |
507
+ | P7 | `goblin-pr-gate` | anything that should be reviewed before landing |
508
+ | P8 | `goblin-bootstrap` | adopting goblin-stack, or starting a project |
509
+ | P9 | `goblin-handoff` | ending a session, or picking up another's |
510
+ | P10 | `goblin-overnight` | an unattended run over a predicate |
511
+ | P11 | `goblin-sweep` | the same change across many projects |
512
+ | P12 | `goblin-eval` | a skill or prompt changed — did it do anything? |
513
+ | P13 | `goblin-bugreporter` | an event delivered a report |
514
+ | P14 | `goblin-drift-audit` | a recorded claim disagrees with the artifact |
515
+ | P15 | `goblin-re-mobile` | one shipped Android build must be understood as facts for study |
516
+
517
+ ### Where the real documentation lives
518
+
519
+ | File | Read it for |
520
+ |---|---|
521
+ | `docs/DESIGN.md` | the thesis and every rejected alternative |
522
+ | `docs/FLOWS.md` | the playbooks in full, with reasons |
523
+ | `docs/ENFORCEMENT.md` | the rule matrix, rendered for a human |
524
+ | `docs/LIMITS.md` | **what this cannot check** — read this one early |
525
+ | `docs/RISKS.md` | the risk register and non-goals |
526
+ | `docs/CONTRACTS.md` | exact interface, exit codes, uninstall |
527
+ | `docs/ADOPTION.md` | classes, presets, adoption order |
528
+ | `docs/CI.md`, `docs/LOOP.md`, `docs/GUARDRAILS.md` | the newer lanes |
529
+
530
+ ---
531
+
532
+ ## 12. What this will not do for you
533
+
534
+ Stated plainly, because a guide that oversells its tool is worse than no guide:
535
+
536
+ - **It cannot force an agent that never reads `HANDOFF.md`.** It can only make the file exist,
537
+ structured and dated, so the reading is cheap.
538
+ - **It cannot prove your checks test the right thing.** A green suite that asserts the wrong
539
+ behaviour passes. Only the REPLAY habit (prove it goes red) catches that, and only if you do it.
540
+ - **It cannot see a real user's device.** A performance number measured on your machine is not a
541
+ user's experience, and the harness says so in its own output.
542
+ - **Ten of its rules are labelled `advisory`** — counted, not enforced, and capped at 10 of 10. They
543
+ are listed by name.
544
+ - **It is not a product.** It is a repository of files, installed into other repositories.
545
+ No service, no daemon, no support contract.
546
+
547
+ The current status, if you want the honest number: a separate review pass verified the artifact at
548
+ **9/10** (that was 0.4.2), and the point it withheld was not a missing feature — it was sentences
549
+ in the record that a measurement contradicted. `docs/LIMITS.md` is the list of what the harness
550
+ cannot see.
551
+
552
+ ---
553
+
554
+ ## 13. Where to go next
555
+
556
+ **If you only do one thing:** install into your most active repo today, set your real `gates:`, and
557
+ run `goblin-verify` once a day for a week. The habit, not the tool, is what produces the result.
558
+
559
+ **Then, in order:**
560
+
561
+ 1. Point `practice:` at your existing house standard and pin it.
562
+ 2. Write one `AC:` item that a script could check, and make it pass.
563
+ 3. Add a ban for the one pattern you are tired of seeing in agent-written code
564
+ (`.goblin/manifest/bans.tsv` — a ban without a mechanism is a wish, so give it one).
565
+ 4. When you have a bug that a test could catch, walk P5 (`goblin-tdd-repro`) end to end once.
566
+
567
+ **If you are sharing this with a team:** the parts that matter are `HANDOFF.md`, the `gates:` you
568
+ declare, and the REPLAY habit. The rest is optional machinery you can switch off per class. Lead
569
+ with *"prove it was broken first"* — it is the one practice that survives contact with a deadline.
570
+
571
+ ---
572
+
573
+ ## Appendix — a 45-minute first run, on one page
574
+
575
+ # 0. get it
576
+ npm i -g @techgoblin/gobstack
577
+
578
+ # 1. try it somewhere disposable
579
+ mkdir -p /tmp/gs-try && cd /tmp/gs-try
580
+ git init -b main
581
+ goblin install --target . --class A # expect: created 50
582
+
583
+ # 2. commit and check
584
+ git add -A && git commit -m "chore: install goblin-stack"
585
+ .goblin/bin/goblin-verify # expect: mostly PASS, some SKIP
586
+
587
+ # 3. make it yours
588
+ $EDITOR .goblin/goblin.yaml # branch, owner_email, and YOUR real gates:
589
+
590
+ # 4. prove a check can fail (the habit that matters) - the same block §7 runs
591
+ # REPLAY-BEGIN (this exact block is run by tests/t-doc-guide.sh - keep the two copies identical)
592
+ .goblin/bin/goblin-verify --only IN-02 # expect PASS
593
+ printf '\n<!-- a deliberate edit -->\n' >> .goblin/bans/README.md
594
+ .goblin/bin/goblin-verify --only IN-02 # expect FAIL
595
+ git stash push -- .goblin/bans/README.md # path-limited: your own edits stay put
596
+ .goblin/bin/goblin-verify --only IN-02 # expect PASS
597
+ git stash drop # the break was deliberate: discard it
598
+ # REPLAY-END
599
+
600
+ # 5. do it for real, in a repo you care about
601
+ cd ~/projects/your-project
602
+ goblin install --target . --class A
603
+ git add -A && git commit -m "chore: adopt goblin-stack"
604
+ .goblin/bin/goblin-verify
605
+ $EDITOR HANDOFF.md # state / gates (dated!) / next / NOT verified
606
+
607
+ ---
608
+
609
+ *This guide is part of goblin-stack. If you find a step that does not work as written, that is a
610
+ defect in the guide — report it the same way you would report one in the code.*