@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.
- package/CHANGELOG.md +38 -0
- package/README.md +112 -123
- package/VERSION +1 -1
- package/automations/drift-audit.sh +4 -4
- package/bans/layer-check.sh +10 -8
- package/bin/goblin +61 -52
- package/bin/goblin-audit +11 -13
- package/bin/goblin-bans +11 -11
- package/bin/goblin-init +275 -713
- package/bin/goblin-install +160 -114
- package/bin/goblin-lib.sh +234 -1
- package/bin/goblin-map +607 -0
- 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 +33 -49
- 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 +178 -169
- 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/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 +1 -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,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,
|
|
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
|
|
194
|
-
| 2. the first commit | `git add -A && git commit` | `
|
|
195
|
-
| 3. name a real HEAD — and **commit that too** | edit `HANDOFF.md`, then `git add -A && git commit` | `
|
|
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
|
-
|
|
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
|
|
201
|
-
`bash tests/run-tests.sh
|
|
202
|
-
*command not found*.
|
|
203
|
-
|
|
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
|
|
215
|
-
| `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 |
|
|
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.
|
|
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
|
|
257
|
+
## 5. Step 3 — Make it yours: the one config block
|
|
231
258
|
|
|
232
|
-
Everything you configure lives in **one
|
|
259
|
+
Everything you configure lives in **one place**, created once and then never overwritten
|
|
260
|
+
by the installer:
|
|
233
261
|
|
|
234
|
-
.
|
|
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)
|
|
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
|
-
|
|
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 —
|
|
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
|
|
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
|
|
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
|
-
.
|
|
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
|
|
349
|
-
tracks
|
|
350
|
-
`.
|
|
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
|
-
.
|
|
354
|
-
printf '\n<!-- a deliberate edit -->\n' >> .
|
|
355
|
-
.
|
|
356
|
-
git stash push -- .
|
|
357
|
-
.
|
|
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
|
|
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
|
|
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
|
|
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
|
-
.
|
|
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
|
|
434
|
-
the scaffold teaching on purpose — `HP-05`, the `0000000` placeholder in `HANDOFF.md` (§4)
|
|
435
|
-
|
|
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
|
-
|
|
439
|
-
|
|
440
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
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
|
-
| `
|
|
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
|
|
532
|
-
|
|
533
|
-
gob
|
|
534
|
-
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)
|
|
535
527
|
|
|
536
|
-
.
|
|
537
|
-
.
|
|
538
|
-
|
|
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 `.
|
|
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/
|
|
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
|
|
605
|
-
run `goblin-verify` once a day for a week. The habit, not the tool, is what produces
|
|
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
|
-
(`.
|
|
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
|
|
616
|
-
declare, and the REPLAY habit. The rest is optional machinery you can switch off per class.
|
|
617
|
-
with *"prove it was broken first"* — it is the one practice that survives contact with a
|
|
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
|
|
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
|
-
.
|
|
642
|
+
.gob/bin/goblin-verify # expect: mostly PASS, some SKIP
|
|
634
643
|
|
|
635
644
|
# 3. make it yours
|
|
636
|
-
$EDITOR .
|
|
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
|
-
.
|
|
641
|
-
printf '\n<!-- a deliberate edit -->\n' >> .
|
|
642
|
-
.
|
|
643
|
-
git stash push -- .
|
|
644
|
-
.
|
|
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
|
|
659
|
+
gob init --write .gob-init-proposal.md --yes
|
|
651
660
|
git add -A && git commit -m "chore: adopt gobstack"
|
|
652
|
-
.
|
|
661
|
+
.gob/bin/goblin-verify
|
|
653
662
|
$EDITOR HANDOFF.md # state / gates (dated!) / next / NOT verified
|
|
654
663
|
|
|
655
664
|
---
|