@techgoblin/gobstack 0.5.0-beta.8 → 0.6.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/CHANGELOG.md +54 -0
  2. package/README.md +161 -124
  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 +69 -57
  7. package/bin/goblin-audit +11 -13
  8. package/bin/goblin-bans +11 -11
  9. package/bin/goblin-extras +342 -0
  10. package/bin/goblin-init +382 -711
  11. package/bin/goblin-install +160 -114
  12. package/bin/goblin-lib.sh +234 -1
  13. package/bin/goblin-map +226 -21
  14. package/bin/goblin-mcp.js +492 -0
  15. package/bin/goblin-model +4 -4
  16. package/bin/goblin-upgrade +1 -1
  17. package/bin/goblin-verify +159 -145
  18. package/bin/goblin.js +35 -51
  19. package/docs/ADOPTION.md +15 -15
  20. package/docs/CONTRACTS.md +16 -15
  21. package/docs/DESIGN.md +1 -1
  22. package/docs/ENFORCEMENT.md +89 -90
  23. package/docs/FLOWS.md +1 -1
  24. package/docs/GLOSSARY.md +3 -3
  25. package/docs/GUARDRAILS.md +5 -5
  26. package/docs/GUIDE.md +194 -177
  27. package/docs/INTEGRATION.md +1 -1
  28. package/docs/LIMITS.md +25 -0
  29. package/docs/LOOP.md +12 -12
  30. package/docs/RE-PLAYBOOK.md +3 -3
  31. package/docs/ROLES.md +5 -5
  32. package/extras-catalogue/catalogue.tsv +42 -0
  33. package/extras-catalogue/payload/README.md +14 -0
  34. package/extras-catalogue/payload/taste-skill/taste/REFERENCE.md +3 -0
  35. package/extras-catalogue/payload/taste-skill/taste/SKILL.md +9 -0
  36. package/manifest/bans.tsv +8 -8
  37. package/manifest/classes.tsv +3 -3
  38. package/manifest/enforcement.tsv +40 -40
  39. package/manifest/glossary.tsv +3 -3
  40. package/manifest/playbooks.tsv +1 -1
  41. package/package.json +3 -1
  42. package/presets/electron-overlay.yaml +2 -2
  43. package/presets/fleet.yaml +8 -7
  44. package/presets/game.yaml +1 -1
  45. package/presets/research.yaml +1 -1
  46. package/presets/service.yaml +1 -1
  47. package/presets/software.yaml +1 -1
  48. package/skills/goblin-bootstrap/SKILL.md +2 -2
  49. package/templates/AGENTS.md.tmpl +8 -18
  50. package/templates/HANDOFF.md.tmpl +5 -5
  51. package/templates/agents-block.tmpl +45 -0
  52. package/templates/audit-waiver.tsv.tmpl +2 -2
  53. package/templates/boundary-waivers.tmpl +1 -1
  54. package/templates/checks/gate.sh.tmpl +6 -6
  55. package/templates/install-hooks.allowlist.tmpl +1 -1
  56. package/templates/ci/goblin-gate.yml.tmpl +0 -46
  57. package/templates/goblin.yaml.tmpl +0 -146
  58. package/templates/loop/decisions.tsv.tmpl +0 -1
  59. package/templates/loop/predicate.tmpl +0 -16
package/bin/goblin.js CHANGED
@@ -1,36 +1,29 @@
1
1
  #!/usr/bin/env node
2
- // bin/goblin.js — the node shim over the bash engine (W2, PLAN-V1 §4.3).
2
+ // bin/goblin.js — the node shim over the bash engine.
3
3
  //
4
- // The shebang is load-bearing: the §4.3 body always calls bash with the payload
5
- // explicitly, but npm's bin symlink executes THIS file directly (npx ./ --version),
6
- // and a marketplace packager stripping the executable bit breaks the symlink, not
7
- // the spawnSync path below.
4
+ // The shebang is load-bearing: npm's bin symlink executes THIS file directly
5
+ // (npx ./ --version), and a marketplace packager stripping the executable bit breaks
6
+ // the symlink, not the spawnSync path below.
8
7
  //
9
- // gob verify [--only <id,...>] ... -> bin/goblin-verify
8
+ // v2 SURFACE (AI-driven development):
9
+ // gob init [...] -> bin/goblin-init (the prompt+schema engine)
10
+ // gob map [...] -> bin/goblin-map (prompt+schema; --heuristic fallback)
11
+ // gob verify [...] -> bin/goblin-verify
10
12
  // gob bans [...] -> bin/goblin-bans
11
- // gob audit [...] -> bin/goblin-audit
12
- // gob upgrade [...] -> bin/goblin-upgrade (W3)
13
- // gob doctor [...] -> bin/goblin-doctor (W4a)
14
- // gob emit [...] -> bin/goblin-emit (W4a)
15
- // gob init [...] -> bin/goblin-init (W6, the first-run wizard)
16
- // gob map [target] [--force] -> bin/goblin-map (the standalone feature-map generator)
13
+ // gob extras [...] -> bin/goblin-extras (curated catalogue)
14
+ // gob mcp -> bin/goblin-mcp.js (the MCP stdio server)
17
15
  // gob uninstall [--target <dir>] -> bin/goblin-install --uninstall
18
- // gob install [...] -> bin/goblin-install (the one legacy fallback)
19
- // no args | -h/--help | any other unrecognized first arg
20
- // -> this file's short usage, exit 2. A bare `goblin`
21
- // used to fall through into the installer; a typo
22
- // (`goblin inti`) silently installed too. Both now
23
- // print the usage and stop.
16
+ // no args | -h/--help | any other first arg -> this file's short usage, exit 2.
24
17
  //
25
- // Non-negotiables (§4.3): args are passed as an ARRAY, never a shell string (no
26
- // injection surface); `bash` is named explicitly (a packager stripping the
27
- // executable bit must not break every command); the exit status is propagated
28
- // VERBATIM so the four-value verify contract survives the shim. No dependencies,
29
- // no async, CommonJS — this repo has no node tooling by design.
18
+ // UNWIRED (code kept, deletion is session 3): audit, upgrade, doctor, emit, sync,
19
+ // install. The usage() list is the product's contract: a verb absent from it is refused,
20
+ // naming what replaced it — never silently executed.
30
21
  //
31
- // The payload/ re-point happens with packaging (W3/W5): the npm tarball moves the
32
- // bash payload under payload/, so this line becomes path.join(__dirname, "..", "payload", "bin", target).
33
- // Until then the shim runs straight out of the checkout layout.
22
+ // Non-negotiables: args are passed as an ARRAY, never a shell string (no injection
23
+ // surface); `bash` is named explicitly (a packager stripping the executable bit must not
24
+ // break every command); the exit status is propagated VERBATIM so the four-value verify
25
+ // contract survives the shim. No dependencies, no async, CommonJS — this repo has no
26
+ // node tooling by design.
34
27
  "use strict";
35
28
 
36
29
  const { spawnSync } = require("node:child_process");
@@ -45,32 +38,27 @@ if (arg0 === "--version" || arg0 === "-V" || arg0 === "-v") {
45
38
  process.exit(0);
46
39
  }
47
40
 
48
- const SCRIPT = { verify: "goblin-verify", bans: "goblin-bans", audit: "goblin-audit", upgrade: "goblin-upgrade", doctor: "goblin-doctor", emit: "goblin-emit", sync: "goblin-emit", init: "goblin-init", map: "goblin-map" };
49
- // `sync` is the friendlier name for `emit` (wizard v2): same engine, same flags, same exit
50
- // contract. `emit` stays a first-class verb - nothing is removed, this row only adds an alias.
41
+ const SCRIPT = { init: "goblin-init", map: "goblin-map", verify: "goblin-verify", bans: "goblin-bans", extras: "goblin-extras", mcp: "goblin-mcp.js" };
51
42
  const [cmd, ...rest] = process.argv.slice(2);
52
43
 
53
- // No args, a help flag, or an unrecognized first arg: short usage, exit 2. The one survivor of
54
- // the old catch-all fallback is the literal `install` first arg — bare `goblin` mapped to the
55
- // installer through npm's bin default, and a typo (`goblin inti`) silently installed into
56
- // whatever directory the shell sat in. A bare subcommand-less `gob install ...` keeps the
57
- // installer; everything else stops here and names the word it did not know.
44
+ // No args, a help flag, or an unrecognized first arg: short usage, exit 2. A bare
45
+ // subcommand-less `gob install ...` is REFUSED in v2 (init replaced it); a typo
46
+ // (`gob inti`) stops here and names the word it did not know.
58
47
  function usage() {
59
48
  process.stderr.write(
60
49
  [
61
50
  "gob <command>",
62
51
  "",
63
- " gob init start here — the guided first step (health, class, gate, ci, sync, verify)",
52
+ " gob init start here — prints the agent brief + proposal schema; --write installs it",
64
53
  " gob verify run the rule matrix against the current repo",
65
54
  " gob bans run the ban list (per-pattern red lines over the source tree)",
66
- " gob audit check recorded dependency claims against live advisory feeds",
67
- " gob upgrade migrate a repo to the shared global engine at ~/.goblin/engine",
68
- " gob doctor one detection/drift run across the agent platforms",
69
- " gob sync write the skills + context block for one platform (alias: gob emit)",
70
- " gob map generate a starter feature map for this repo (standalone; no install needed)",
55
+ " gob extras browse + install the curated extras catalogue (list | show | install)",
56
+ " gob map print the feature-map prompt + schema; --heuristic scans instead",
57
+ " gob mcp serve the harness to your agent over MCP stdio (verify/map/init tools)",
71
58
  " gob uninstall --target . remove exactly what an install wrote (preimages)",
72
59
  "",
73
- "start here: gob init",
60
+ "start here: npx @techgoblin/gobstack init",
61
+ "register the verify tool for your agent: " + ["cl", "aude"].join("") + " mcp add gob -- npx -y @techgoblin/gobstack mcp",
74
62
  "uninstall: npm uninstall -g @techgoblin/gobstack",
75
63
  "",
76
64
  ].join("\n"));
@@ -80,7 +68,7 @@ if (cmd === undefined || cmd.startsWith("-")) {
80
68
  usage();
81
69
  process.exit(2);
82
70
  }
83
- if (!SCRIPT[cmd] && cmd !== "install" && cmd !== "uninstall") {
71
+ if (!SCRIPT[cmd] && cmd !== "uninstall") {
84
72
  process.stderr.write(`gob: unrecognized command: ${cmd}\n\n`);
85
73
  usage();
86
74
  process.exit(2);
@@ -88,13 +76,7 @@ if (!SCRIPT[cmd] && cmd !== "install" && cmd !== "uninstall") {
88
76
 
89
77
  let target;
90
78
  let extra = [];
91
- if (cmd === "install") {
92
- target = "goblin-install"; // the one legacy fallback, kept verbatim
93
- } else if (cmd === "uninstall") {
94
- // `gob uninstall --target <dir>` routes into the installer's uninstall job — the shape
95
- // docs/GUIDE.md and README already promise. `--uninstall` is appended FIRST so the user's
96
- // own `--target <dir>` and options still parse, and a stray literal `--uninstall` cannot
97
- // appear twice.
79
+ if (cmd === "uninstall") {
98
80
  target = "goblin-install";
99
81
  extra = ["--uninstall"];
100
82
  } else {
@@ -102,6 +84,8 @@ if (cmd === "install") {
102
84
  }
103
85
  const file = path.join(__dirname, "..", "bin", target);
104
86
  // execPath-independent: call bash explicitly so Windows-WSL/Git-Bash works and no
105
- // shebang resolution is needed.
106
- const r = spawnSync("bash", [file, ...extra, ...rest], { stdio: "inherit" });
87
+ // shebang resolution is needed — except for the .js targets (the MCP server), which
88
+ // run under node, the same runtime this shim already is.
89
+ const runner = target.endsWith(".js") ? process.execPath : "bash";
90
+ const r = spawnSync(runner, target.endsWith(".js") ? [file, ...rest] : [file, ...extra, ...rest], { stdio: "inherit" });
107
91
  process.exit(r.status ?? 2);
package/docs/ADOPTION.md CHANGED
@@ -39,7 +39,9 @@ Two placements worth arguing about:
39
39
  | Review panel | O | — | R | — | O |
40
40
  | Playbooks (the skills) | R | R | R | R | R |
41
41
  | Design tokens | O | — | — | — | O |
42
- | CI lane | R | — | O | — | O |
42
+
43
+ (The `ci-gate` part is not a row here: v2 installs no CI, so the part is off for every class —
44
+ the W4 preset matrix that carried it is recorded in `docs/LIMITS.md` as out of the v2 product.)
43
45
 
44
46
  **The electron opt-in, not a class**, added at W4: an Electron app is the **software** class with
45
47
  `electron: true`, which declares the Electron failure surface as bans (`BN-06`..`BN-09`) and
@@ -47,9 +49,8 @@ declares its FPS number as a **host gate** rather than a ratchet, because the pr
47
49
  it needs Playwright or Electron plus a display — neither of which a shipped rule may depend on. Its
48
50
  ratchet carries `app_bundle_bytes` instead. The old sixth class was merged into `software` (its need
49
51
  column measured identical on all ten parts), and the old `F` letter remains an install-time alias
50
- that selects `software` **with** the opt-in. `docs/CI.md` §3 argues it in full, including why frame
51
- time is the wrong number (measured flat at 16.70 ms while the main thread went from 1.8 % to 54.5 %
52
- busy).
52
+ that selects `software` **with** the opt-in (frame time measured flat at 16.70 ms while the main
53
+ thread went from 1.8 % to 54.5 % busy — the number is the argument).
53
54
 
54
55
  **`—` is a real, enforced option.** The installer records every off part in `disabled:`, so its
55
56
  rows report `SKIP (opt-out)`; `CL-01` fails if a forbidden part's artifact exists. A repo with
@@ -66,7 +67,7 @@ Four consequences that follow from measurement, not taste:
66
67
  inferred command is wrong for a repo with no runner, a repo that cannot run its own typecheck
67
68
  read-only, and a repo whose runner lives in a skill — all at once. The shipped gate is a
68
69
  **floor**, and `P8` step 3 is "replace it".
69
- 4. **The default branch is not always `main`.** It is declared in `.goblin/goblin.yaml` and
70
+ 4. **The default branch is not always `main`.** It is declared in `.gob/goblin.yaml` and
70
71
  compared against the real branch by `PT-02`; a preset that assumes `main` silently skips a
71
72
  repo on `master`.
72
73
 
@@ -97,21 +98,20 @@ Each step is independently useful and the later ones build on the earlier:
97
98
 
98
99
  ## What a first install actually gives you
99
100
 
100
- `goblin-install` exits 0 and creates: `.goblin/` (the verifier, the manifest, the config),
101
+ `goblin-install` exits 0 and creates: `.gob/` (the verifier, the manifest, the config),
101
102
  `.hermes/skills/` (the flows), `HANDOFF.md`, `AGENTS.md`, and — for classes that need them —
102
103
  `ROUND-000-SPEC.md`, `reviews/`, and the harness scaffold in `checks/`.
103
104
 
104
105
  Then, in order:
105
106
 
106
107
  git add -A && git commit # the install is a change like any other
107
- .goblin/bin/goblin-verify # 37 passed, 1 failed - HP-05, until HANDOFF names a commit
108
- gob emit --platform <p> # optional, per platform: the agent skills are an opt-in
108
+ .gob/bin/goblin-verify # 35 passed, 2 failed - CM-03 + SP-02, until the install is committed
109
109
 
110
- A default software-class install (no agent skills) is **green** — `38 passed, 0 failed, 11 advisory,
111
- 33 skipped`, exit 0 — once
110
+ A default software-class install (no agent skills) is **green** — `37 passed, 0 failed, 11 advisory,
111
+ 34 skipped`, exit 0 — once
112
112
  `HANDOFF.md` names a commit that exists; before that edit the scaffold's `0000000` placeholder is
113
- the one expected red (`37 passed, 1 failed`). Both numbers are measured, not assumed
114
- (`docs/CONTRACTS.md`; step 2 of `docs/GUIDE.md`). Thirty-three rows skip with a reason: the
113
+ the one expected red (`36 passed, 1 failed`). Both numbers are measured, not assumed
114
+ (`docs/CONTRACTS.md`; step 2 of `docs/GUIDE.md`). Thirty-four rows skip with a reason: the
115
115
  five skill rows (`SK-01`..`SK-04`, `AU-04`) skip on the `playbooks` opt-out a skills-free
116
116
  install records, plus the not-yet rows: `HS-02` (no
117
117
  pinned pre-change commit yet), `AU-02`/`AU-03` (no report has been filed, so there is nothing to
@@ -123,7 +123,7 @@ they skip as *not enabled* rather than as *unread*), `FM-01`/`FM-02`/`VA-01`
123
123
  (no feature map and no declared `verify_doctor:` yet), `RC-01`..`RC-04` (no reference corpus
124
124
  declared: `reference_manifest:` ships empty and a fresh repo has no lab `manifests/`) and `JG-01`
125
125
  with `LP-01`..`LP-05` (no
126
- `.goblin/loop/` record, because no loop has run here yet). The class's required parts that only a
126
+ `.gob/loop/` record, because no loop has run here yet). The class's required parts that only a
127
127
  round can produce pass *vacuously* (zero `reviews/*.md` to check; the declared gate is still the
128
128
  shipped floor), so the first-step list is a list of work, not a list of FAILs.
129
129
 
@@ -163,9 +163,9 @@ The remedy is a reconciliation. The project's file stays the file of record; not
163
163
  5. **Commit, then verify:**
164
164
 
165
165
  git add -A && git commit
166
- .goblin/bin/goblin-verify # HP-02, HP-03, HP-05 go green
166
+ .gob/bin/goblin-verify # HP-02, HP-03, HP-05 go green
167
167
 
168
- Success is the class's full green path (`38 passed, 0 failed, 11 advisory, 33 skipped`, exit 0 for
168
+ Success is the class's full green path (`37 passed, 0 failed, 11 advisory, 34 skipped`, exit 0 for
169
169
  the software class) with `git status --short` empty.
170
170
 
171
171
  The edit is additive and small — measured on the model repo (§1's exemplar, 2450 lines): three
package/docs/CONTRACTS.md CHANGED
@@ -46,7 +46,7 @@ files whose hash changed and prints `created C · updated U · unchanged N · sk
46
46
  | kind | recorded as | overwritten? | hash-checked? | removed by `--uninstall`? |
47
47
  |---|---|---|---|---|
48
48
  | installed artifact (bin, manifest, roles, opt-in skills, harness scaffold) | `files` | yes, on upgrade | yes — IN-02, SK-02 | yes |
49
- | created once, then yours (`.goblin/goblin.yaml`, `HANDOFF.md`, `AGENTS.md`, `*-SPEC.md`, `reviews/.gitkeep`) | `owned` | never | no — you are meant to edit them | no, except the config |
49
+ | created once, then yours (`.gob/goblin.yaml`, `HANDOFF.md`, `AGENTS.md`, `*-SPEC.md`, `reviews/.gitkeep`) | `owned` | never | no — you are meant to edit them | no, except the config |
50
50
  | pre-existing, left alone | `refused` | never | no — IN-04 only proves it was not taken over | no |
51
51
 
52
52
  A `refused` path is not a dead end. For `HANDOFF.md` the remedy is the reconciliation in
@@ -60,13 +60,13 @@ repo. The remedy is the explicit re-pin below — not a hand-edit of the hash, a
60
60
  automatic one.
61
61
 
62
62
  `.gitignore` is not a file goblin-stack owns: it appends **one marked block** and never rewrites
63
- the rest. `.goblin/goblin.yaml` is generated once and is goblin-stack's own config, so
63
+ the rest. `.gob/goblin.yaml` is generated once and is goblin-stack's own config, so
64
64
  `--uninstall` removes it; `HANDOFF.md`, `AGENTS.md`, `ROUND-000-SPEC.md` and `reviews/` are the
65
65
  project's record, not the harness's, and are left in place.
66
66
 
67
67
  ### An edited standard is not a dead end
68
68
 
69
- `.goblin/goblin.yaml` records `practice:` and `practice_sha256:`, and `IN-02` re-checks that hash.
69
+ `.gob/goblin.yaml` records `practice:` and `practice_sha256:`, and `IN-02` re-checks that hash.
70
70
  The pin has exactly one purpose: to make a **silently** edited standard visible rather than
71
71
  assumed. The standard itself is a living document, corrected in place, so an edit that is
72
72
  *intended* needs a deliberate way to re-record the pin. That is all `--re-pin` is:
@@ -79,7 +79,7 @@ It rewrites one line of the config — nothing else — and prints both hashes:
79
79
  recorded 81612b17ac3483b9d613aeb86e236539fc17403e38bf7903af708d369cf7918f
80
80
  now 8334ac24f056c94c35fa97831253e7e12bace68ae5747c81ae3b696c42ddd33a
81
81
 
82
- `.goblin/bin/goblin-verify --only IN-02` then reports `practice pin ok`. Every other line of
82
+ `.gob/bin/goblin-verify --only IN-02` then reports `practice pin ok`. Every other line of
83
83
  `goblin.yaml`, comments included, is untouched, so the `owned` contract holds for everything
84
84
  except the one value you just asked to re-record. Commit the config like any other change.
85
85
  `--dry-run` prints the plan and writes nothing; when there is nothing to do it prints
@@ -97,7 +97,7 @@ Four things it deliberately is not:
97
97
  - **not a re-point.** It re-records the hash of the path already in `practice:`. Pointing the repo
98
98
  at a *different* standard is a deliberate config edit, not a re-pin.
99
99
 
100
- Refusals are exit `2`, each naming the path: no `.goblin/goblin.yaml`, no `practice:` recorded, the
100
+ Refusals are exit `2`, each naming the path: no `.gob/goblin.yaml`, no `practice:` recorded, the
101
101
  recorded path absent, or no `practice_sha256:` line to rewrite. A failed write is exit `1`, with
102
102
  the path — the command never reports a re-pin that did not land. One refusal guards the mode
103
103
  itself: `--uninstall --re-pin` is exit `2` with `--uninstall and --re-pin are different jobs; run
@@ -122,7 +122,7 @@ Output is one line per executed row, in manifest order, plus a summary line at t
122
122
 
123
123
  Those four lines are one row of each marking. The summary line of a green default software-class run is:
124
124
 
125
- 38 passed, 0 failed, 11 advisory, 33 skipped
125
+ 37 passed, 0 failed, 11 advisory, 34 skipped
126
126
 
127
127
  **Exit codes:** `0` every executed check passed (advisories and skips do not fail the run) ·
128
128
  `1` at least one check FAILED · `2` verify could not run (not installed, a missing dependency,
@@ -137,14 +137,15 @@ is counted and capped.
137
137
  tests the right path rather than merely passing; whether the forge is bound by the workflow
138
138
  `CL-01` found; whether a human
139
139
  read the diff; whether the model mapping names a family that actually differs; and whether
140
- `.goblin/installed.json` — the record every drift check trusts — was itself rewritten, since it
141
- is not signed (`docs/LIMITS.md` #18). The CI lane adds its own, and `docs/CI.md` is where the four
142
- settings that make a workflow a **gate** are written down.
140
+ `.gob/installed.json` — the record every drift check trusts — was itself rewritten, since it
141
+ is not signed (`docs/LIMITS.md` #18). The CI lane's blind spots are named there too, though in v2
142
+ the lane itself is out of the product (`docs/LIMITS.md` records `docs/CI.md` as its LIMITS
143
+ candidate) — the prose survives because the *reason* a workflow file is not a gate still does.
143
144
 
144
145
  ### A fresh install verifies green
145
146
 
146
147
  Measured on a fresh DEFAULT software-class install (skills opt-in, W6 neutral-first), committed with no
147
- hand edit: **`38 passed, 0 failed, 11 advisory, 33 skipped`, exit 0.** Thirty-three rows skip with
148
+ hand edit: **`37 passed, 0 failed, 11 advisory, 34 skipped`, exit 0.** Thirty-four rows skip with
148
149
  a reason — the same not-yet rows as before, plus the five skill rows (`SK-01`..`SK-04`,
149
150
  `AU-04`) that skip on the `playbooks` opt-out a skills-free install records: `HS-02` — no pre-change commit
150
151
  is pinned yet, so the REPLAY is not provable (`docs/LIMITS.md` #11) — `AU-02` and `AU-03`, which
@@ -159,7 +160,7 @@ must not be born RED — G1, `docs/LIMITS.md` #30) — `RC-01`..`RC-04`, which r
159
160
  reference corpus and a lab `manifests/` directory a fresh install has neither of
160
161
  (`reference_manifest:` and `quarantine_root:` ship empty on purpose: a repo with no corpus must
161
162
  not be born RED) — and `JG-01` with `LP-01`..`LP-05`, which have
162
- no `.goblin/loop/` record because no loop has run in this repo: the six judge/loop rows are
163
+ no `.gob/loop/` record because no loop has run in this repo: the six judge/loop rows are
163
164
  **absent-state** rows, and a fresh install must not be born RED either. **Two** rows do
164
165
  **not** skip, both of them the CI lane's: `PG-05` and `PG-06` read the workflow this class installs.
165
166
  Two, not four — the four electron bans named in the skip list above do skip here, and a tree without
@@ -184,7 +185,7 @@ verifier is reporting FAILs.
184
185
  the part's rows as `SKIP (opt-out)` in the summary, so the opt-out is **visible rather than
185
186
  absent**. The same mechanism is what makes a class's `-` (off) real.
186
187
  - **The opt-out numbers are pinned (V3-3).** A software-class install with an explicit `--skills no`
187
- verifies `38 passed, 0 failed, 11 advisory, 33 skipped`, exit 0, and
188
+ verifies `37 passed, 0 failed, 11 advisory, 34 skipped`, exit 0, and
188
189
  `tests/t-install-off-switch.sh` asserts that line: a silent drift in the opt-out path is caught
189
190
  rather than left as a number nobody wrote down (the `--skills no` count moved from `37/0/9/11`
190
191
  at v0.2 when the ban rows landed, **15 → 18 on 2026-09-25 (G1)** — the feature-map rows,
@@ -197,9 +198,9 @@ verifier is reporting FAILs.
197
198
  recorded skill files; `--uninstall` removes everything recorded, as always.
198
199
  `tests/t-install-off-switch.sh` walks that migration: install `--skills yes`, upgrade flag-less,
199
200
  the skills survive byte-identical; uninstall, and they are all gone.
200
- - **Whole harness:** `--uninstall` deletes the `files` list plus `.goblin/goblin.yaml`, removes
201
+ - **Whole harness:** `--uninstall` deletes the `files` list plus `.gob/goblin.yaml`, removes
201
202
  every directory that leaves empty (deepest first, after `installed.json` itself is gone — the
202
- order that used to leave `.goblin/` and the sixteen `.hermes/skills/*` directories behind),
203
+ order that used to leave `.gob/` and the sixteen `.hermes/skills/*` directories behind),
203
204
  leaves `HANDOFF.md`, `AGENTS.md`, `ROUND-000-SPEC.md`, `reviews/` and the `.gitignore` block
204
205
  (with a `# goblin-stack uninstalled <date>` marker inside it), and prints what it removed and
205
206
  what it left.
@@ -207,7 +208,7 @@ verifier is reporting FAILs.
207
208
  ## The two commands, verbatim
208
209
 
209
210
  bash bin/goblin-install --target /path/to/repo --class software
210
- .goblin/bin/goblin-verify
211
+ .gob/bin/goblin-verify
211
212
 
212
213
  From a checkout, without installing anything:
213
214
 
package/docs/DESIGN.md CHANGED
@@ -58,7 +58,7 @@ The split is by **kind**, and it is checkable.
58
58
  - **goblin-stack owns the mechanism**: which rule is enforced by what, how it is installed, how
59
59
  it is verified, which class a project is, which flow applies, which role runs a flow.
60
60
 
61
- goblin-stack carries **no copy** of the standard's text. `.goblin/goblin.yaml` holds
61
+ goblin-stack carries **no copy** of the standard's text. `.gob/goblin.yaml` holds
62
62
  `practice:` and `practice_sha256:`; `goblin-verify` re-checks the hash, so a silently edited
63
63
  standard is visible rather than assumed. An edit that *is* intended is re-pinned by one explicit,
64
64
  printed command (`goblin-install --target <dir> --re-pin`), never automatically — the pin exists