@techgoblin/gobstack 0.0.0-stage → 0.4.4-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/CHANGELOG.md +351 -0
  2. package/LICENSE +21 -0
  3. package/README.md +163 -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 +482 -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 +48 -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 +36 -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/CHANGELOG.md ADDED
@@ -0,0 +1,351 @@
1
+ # Changelog
2
+
3
+ One line per released version. `goblin-install --upgrade` prints the delta between the
4
+ version recorded in a target's `.goblin/installed.json` and the source `VERSION`.
5
+
6
+ ## 0.4.4
7
+
8
+ The five findings an independent verification of 0.4.3 left open (AB3). The blocker is the species
9
+ this campaign keeps meeting: a false statement about the artifact's own enforcement, written into the
10
+ guide **while** the wave that fixed five of the same kind was landing. No row was added, moved or
11
+ re-labelled — `advisory` stays at **10 of 10**, and `manifest/enforcement.tsv` and
12
+ `tests/t-verify-red.sh` are untouched, so the census cannot drift.
13
+
14
+ - **`docs/GUIDE.md` §8's rule sentence was false (AB3-1, the BLOCKER).** It said `IN-02` "hashes
15
+ **every file the installer wrote**". Measured on a fresh class-A install: the installer writes
16
+ **50** files and the row's `files` map covers **40** — ten sit outside it, including
17
+ `.goblin/goblin.yaml`, the file §5 step 3 tells the reader to edit. Editing all ten at once still
18
+ printed `PASS IN-02 40 installed files hashed` rc 0, so a reader who followed §5 and then §8 would
19
+ watch REPLAY "confirm" a check that never moved. The sentence now names the 40, the 8 it `owns` and
20
+ `.goblin/installed.json`, and points the exercise at `.goblin/bans/README.md`.
21
+ `tests/t-doc-guide.sh` asserts the count the guide quotes equals the `files`-map length of the
22
+ install it made, and that the universal is gone — both RED at `58a6fe6`.
23
+ - **The 9/10 in `docs/GUIDE.md` §11 was unversioned.** It presented a previous revision's score as
24
+ "the current status" in a file stamped `0.4.3`, so the next pass made it false in silence. The
25
+ sentence now carries the revision it was measured at (`0.4.2`, where AC1 measured 9.0), and
26
+ `t-doc-guide.sh` reads it — RED at `58a6fe6`.
27
+ - **Two more live copies of the stale 9-of-10 advisory arithmetic.** `docs/GUARDRAILS.md`'s third
28
+ design constraint carried the count with no dating at all; `docs/LIMITS.md` #26 said `SK-03`
29
+ "reports that arithmetic **on every run** (`advisory 9 of ceiling 10 (1 free slot)`)" while the run
30
+ prints `advisory 10 of ceiling 10 (0 free slots: the next advisory row FAILs)`. Both now state the
31
+ measured value and date the correction, and `tests/t-doc-sync.sh` reads the two LIVE copies — RED at
32
+ `58a6fe6` — while the dated history (the CHANGELOG entries, `docs/ENFORCEMENT.md`'s chronology,
33
+ `t-verify-red.sh`'s pre-change note) keeps its own tense and is not read.
34
+ - **`CHANGELOG.md`'s 0.4.0 census is annotated, not rewritten.** It claimed "**105** controls and
35
+ **19** `expect_green` — **124**", a figure that matched no tree even when it was written: 0.4.0's
36
+ own tree (`63d62d2`) measures **112** + **22** = **134**, and the tree at 0.4.3 measures **121** +
37
+ **28** = **149**. The released numbers stand and carry a dated correction beside them.
38
+ - **`VERSION` is `0.4.4`** — `VERSION`, the five `bin/` version constants and this entry agree. No
39
+ logic changed in `bin/`, and no id, verdict or matrix cell moved.
40
+
41
+ ## 0.4.3
42
+
43
+ Five defects an independent verification of 0.4.2 measured, and all five are the same species: a
44
+ sentence in a reader-facing artifact that a measurement contradicts. Four are prose, one is a row
45
+ that stayed GREEN under its own violation. No row was added, moved or re-labelled — `advisory` stays
46
+ at **10 of 10**.
47
+
48
+ - **`docs/GUIDE.md`'s only hands-on REPLAY exercise was false as written (D1, the BLOCKER).** §7 and
49
+ the appendix both told the reader `git stash && .goblin/bin/goblin-verify --only GT-02 # expect
50
+ FAIL`, and `GT-02` runs the gates the config declares (`commit`, `todo_ceiling`), whose exit status
51
+ a stash cannot change: measured on the shipped class-A configuration, `PASS` rc 0 before, during
52
+ and after — the guide taught the lesson backwards. The exercise REPLAYs `IN-02` now, the row that
53
+ hashes the files the installer wrote: break one, watch the row go `FAIL` rc 1, put the file back,
54
+ watch it go `PASS` rc 0. The restore is path-limited (`git stash push -- <path>`) so it cannot
55
+ swallow the uncommitted `.goblin/goblin.yaml` edit step 3 leaves behind, and both copies carry the
56
+ same block between sentinels.
57
+ - **`docs/GUIDE.md` had no control at all, which is how four false sentences survived in it (D1's
58
+ cause).** `grep -rn GUIDE tests/*.sh` was **0** hits before this release. `tests/t-doc-guide.sh`
59
+ now extracts the guide's own exercise and RUNS it — every `goblin-verify` line must do what its
60
+ `# expect PASS|FAIL` annotation promises, verdict and exit code — and re-measures the guide's own
61
+ numbers on a fresh class-A install (`created 49` against **50** files on disk; the day-one and
62
+ green-path summary lines). RED on `d5424be`.
63
+ - **`GT-03` was GREEN under its own violation (D2).** Its freshness clause compared the gate line
64
+ with `$(git rev-parse --git-dir)/HEAD`, and `.git/HEAD` is rewritten by **branch operations, never
65
+ by a commit**: measured, its mtime was unchanged across a real commit and `--only GT-03` stayed
66
+ `PASS` rc 0 while the round had moved on. The clause reads HEAD's **reflog** (`.git/logs/HEAD`) now,
67
+ which a commit rewrites in an attached *and* a detached worktree and whatever the refs' packing
68
+ state; the row's `—` why-cell became the two limits that remain (a disabled reflog passes
69
+ vacuously, and any HEAD movement counts as staleness). `tests/t-gt03-freshness.sh` controls it in
70
+ both directions: RED on `d5424be`.
71
+ - **"The four rows that do not skip" is two (D3).** `README.md` and `docs/CONTRACTS.md` both said
72
+ four. Measured on the class-A run the paragraph describes: `PG-05` and `PG-06` PASS, and the four
73
+ electron bans named in the same breath (`BN-06`..`BN-09`) **SKIP**. Both copies say **two** now and
74
+ name them, and `docs/ADOPTION.md` and the shipped `skills/goblin-bootstrap/SKILL.md` no longer give
75
+ the bans' reason as "no `src/`" when five of those eight rows skip as *not enabled in `bans:`*.
76
+ - **"`created 49` means it wrote 49 files" was one file short (D4).** The installer writes **50**
77
+ files into an empty repo: the 49 it counts (40 `files` + 8 `owned` + `.gitignore`) plus
78
+ `.goblin/installed.json`, the record it keeps for itself, which it writes and does not count. The
79
+ guide says exactly that now. The counter is unchanged — moving it would have moved every derived
80
+ number in every document that quotes a `created N` line.
81
+ - **"It adds no network calls" was unscoped, and false (D5).** Every other copy of that claim is
82
+ scoped — `docs/GUARDRAILS.md` says "No network at **verify time**", README and `docs/CONTRACTS.md`
83
+ put it under "**Dependencies**", and `bin/goblin-audit`'s own header calls itself "the ONE command
84
+ in the toolchain that touches the network" — as does the guide itself in §8 and §11. §1, the first
85
+ sentence a new reader meets, now says `no network call at verify time`.
86
+ - **`VERSION` is `0.4.3`** — `VERSION`, the five `bin/` version constants and this entry agree. The
87
+ seven dated `0.4.2` statements (this file's own 0.4.2 entry, `docs/LIMITS.md`'s AA1 note,
88
+ `docs/ENFORCEMENT.md`'s and `manifest/enforcement.tsv`'s SC-08 cells, and
89
+ `tests/t-verify-red.sh`'s two "measured at …" notes) describe a past revision and keep their
90
+ version.
91
+
92
+ ## 0.4.2
93
+
94
+ - **`SC-08` no longer passes vacuously on a minified lockfile (Z2-2).** `check_sc_08` read
95
+ `package-lock.json` with a line-anchored awk, so a **minified** (one-line) lockfile matched
96
+ nothing and the row printed `0 install hook(s), 0 allowlisted` — **exit 0, a PASS** where the
97
+ pnpm/yarn branch's SKIP is the honest shape. Measured on one tree: the same unlisted hook is
98
+ `FAIL` rc 1 pretty-printed and was `PASS` rc 0 on one line. The text is normalised into the
99
+ pretty shape before the reader sees it (a text transform — no npm, no jq, no parser) and the
100
+ anchor accepts `": {` and `":{`; two controls hold it, and the FAIL half is RED against the
101
+ 0.4.1 verifier.
102
+ - **`HS-02` shell-quotes the harness file name it substitutes (Z2-3).** Z1-4 made the row run the
103
+ DECLARED command instead of `node "$f"`, which put a file name from the harness dir into the
104
+ command text `bash -c` parses — the same surface class as the G8-1 injection. Measured with a
105
+ file named `z2;true;#.mjs`: unquoted, two commands ran and the trailing `true` decided the exit
106
+ code (rc 1, "was GREEN on the pre-change tree"); quoted with `printf %q`, `node` receives one
107
+ argument. The control carries that name.
108
+ - **Y1 §7's items 1, 2 and 6 have their direct controls, so the census moves (AA1).** The layer
109
+ probe's `bans_exempt:` path, the engine→probe `GOBLIN_BANS_ID`/`GOBLIN_BANS_EXEMPT` contract,
110
+ and the prefix's segment alignment (including the trailing-slash case) each have one now;
111
+ `grep -c GOBLIN_BANS_EXEMPT tests/` was **0** before, and the five W5-1/W5-2 controls all drive
112
+ `grep-ban.sh`, never `layer-check.sh`. The census is therefore **18 listed · 2 fixed · 2 closed ·
113
+ 3 controlled · 11 recorded**: three mechanisms left `LIMITS.md` #41's recorded set, which is the
114
+ only direction that frees headroom, and no advisory row was spent — **10 of 10**.
115
+ - **`tests/t-verify-red.sh`'s census is re-counted, not carried: 121 `expect_red` + 28
116
+ `expect_green` = 149 calls**, 78 distinct ids, 0 phantom, 0 uncovered. Its W5-1/W5-2 comment no
117
+ longer says that all five of those controls are RED on the pre-fix tree — two of the five are
118
+ (Z2-4). Measured on 7fec08f: the two `expect_green` halves fail there (the escape did nothing),
119
+ the three `expect_red` halves report ok; all five name a row that is RED there.
120
+ - **`VERSION` is `0.4.2`** — `VERSION`, the five `bin/` version constants and this entry agree.
121
+
122
+ ## 0.4.1
123
+
124
+ - **Y1's remaining defects, landed (Z1).** Eight MINOR/STYLE findings from an independent verification
125
+ of 0.4.0, plus the carried W5 items that survived X1. The load-bearing one is `{{GATE2}}`, which
126
+ leaked an unsubstituted token into **all six classes'** installed `.goblin/goblin.yaml` for two
127
+ waves while `grep -rl '{{GATE2}}' tests docs manifest bin` was **0 files**: nothing rendered it and
128
+ nothing saw it. It is deleted, and it now has the control that would have caught it —
129
+ `tests/t-render-tokens.sh` renders all six classes and scans every installed file for a `{{…}}`
130
+ token (RED on the pre-fix template: 6 leaks, 1 per class).
131
+ - **`replay.cmd` now runs.** `presets/*.yaml` declared `replay_cmd: node checks/{name}.mjs` and `HS-02`
132
+ read it only to assert it was non-empty, then ran `node <file>` itself — so the declared command and
133
+ its `{name}` placeholder were decorative and `replay.cmd: false` changed no verdict. The row
134
+ executes the declared command with `{name}` substituted; measured, `false` now FAILs and the PASS
135
+ line names the command it ran.
136
+ - **Also fixed:** `IN-03` now enforces the `enforced_by` enum it documented as closed (a `bogus` cell
137
+ changed nothing before); `FM-02` refuses an entry path that resolves only to a file git does not
138
+ track (the freshness clause used to skip silently); `SC-03` prints a hit count instead of the
139
+ character count of the matching line (W5-11, a half-done fix); the summary prints the advisory
140
+ arithmetic, so `advisory 10 of ceiling 10` beside 11 `ADV` lines is explained on screen (Z1-7);
141
+ `--practice <path>` that does not resolve is now reported instead of silently dropped (W5-3);
142
+ `CHANGELOG.md`'s own ban-lane claim is corrected to its measurement (two of five RED pre-fix, three
143
+ pinning behaviour that was never broken, which is what X1 §5 reports); `docs/ENFORCEMENT.md` cites
144
+ the right `LIMITS` entry; `tests/run-tests.sh`'s header counts five source rows, not four.
145
+ - **`docs/LIMITS.md` #41** records Y1 §7's census, and the arithmetic is stated separably so a
146
+ reader can check it: Y1 listed **18** documented mechanisms with no control of their own; this
147
+ wave **fixed** two (the unrendered token, `replay.cmd` — items 17 and 18, which by definition
148
+ now HAVE controls and so sit **outside** the "carry no control" set), **closed** two more (the
149
+ ban engine's `exit 2` paths and `--list` — items 4 and 5, three assertions in
150
+ `tests/t-verify-red.sh`), and **recorded the remaining 14** with their reason. **18 listed ·
151
+ 2 fixed · 2 closed · 14 recorded.** (This sentence said *sixteen* and counted the two fixed
152
+ mechanisms inside the no-control set, so `2 + 2 + 14` could not be reconciled from it —
153
+ Z2-1; the corrected counts are the ones that add up.) W5-10's exemption (`docs/` is never
154
+ installed) is stated there too. No advisory row was added: **10 of 10**, unchanged.
155
+ - **`VERSION` is `0.4.1`** — `VERSION`, the five `bin/` version constants and this entry agree.
156
+
157
+ ## 0.4.0
158
+
159
+ - **W5's regression is closed: the ban lane's two documented escapes now work (X1).** `bans_exempt:`
160
+ was a **permanent RED** after W1's V3-2 fix — the engine filtered the probe's stdout *after* the
161
+ probe had already chosen its exit code, so the filter was decorative and a violation inside an
162
+ exempted path had no remedy (measured `rc 0` at `72490f0` → `rc 1` at `7fec08f`, and
163
+ `grep -rn bans_exempt tests/` was **0 hits**, which is why nothing caught it). The engine now
164
+ exports `GOBLIN_BANS_ID` and `GOBLIN_BANS_EXEMPT` and the shipped probes filter the **file list
165
+ before judging**; the manifest's `escape` column is now true — `// BAN-OK(<id>): <reason>` on the
166
+ offending line clears that line, and a non-empty reason is required. Five controls, both
167
+ directions — **two of the five RED on the pre-fix tree; the other three pin behaviour that was
168
+ never broken** (Y1 measured the ban-lane half at 2, which is what X1 §5 itself reports);
169
+ the residual (a project's own `detect` that ignores the
170
+ variables keeps the old, closed failure) is `docs/LIMITS.md` #36.
171
+ - **W5's four half-instrumentations: closed where closable, recorded where not (X1).** `FM-02` no
172
+ longer resolves a token that occurs only in the harness — `.goblin/`, `.hermes/`, the declared
173
+ `harness_dir` and the map's own directory are skipped, so a stub map that echoes the template
174
+ FAILs (W5-4, `docs/LIMITS.md` #37). `MD-02` now resolves the **judge** lane and compares its model
175
+ with the code lane's, instead of leaving the judge distinct by profile name only; it stays
176
+ advisory, and the measured state is recorded (#38 — on this box the live mapping names **no
177
+ `judge:` profile at all**, so the judge lane reads unresolved, while every profile it does name
178
+ resolves to one model: map a judge and it is the author's family). `LP-02`
179
+ requires a close-and-reopen to archive the predicate **and** the pin it was closed under and to
180
+ name the archived digest on a `previous:` line, so a silent relaxation FAILs while a real re-scope
181
+ costs one line (#39 — whether the new bar is *weaker* is not decidable from a digest). And
182
+ `PG-06`'s why-cell now says plainly that the CI lane's enforcement is the **target repo's**, not
183
+ goblin-stack's (#34), rather than reading as enforcement.
184
+ - **The control census is counted, not carried.** `tests/t-verify-red.sh` now carries **112**
185
+ `expect_red` and **22** `expect_green` — **134** call sites over all 78 target rows, 78 distinct
186
+ ids, 0 uncovered, 0 phantom (W5-9 measured the header sentence one count behind at 105+19).
187
+ - **`VERSION` is `0.4.0`.** It read `0.3.0` at `7fec08f` while the board and four build passes
188
+ called the wave v0.4 — this section is the entry the wave lacked, and the artifact no longer
189
+ calls itself a version its own build passes did not.
190
+
191
+ The wave proper (W1–W4) built on **0.3.0**'s ban list and added:
192
+
193
+ - **V3's four 9/10 blockers closed (W1).** `GT-01` FAILs when a declared gate carries no `cmd:` —
194
+ deleted, blanked or re-indented — instead of silently counting the survivors (G8-3, the third
195
+ condition of G8's own 9/10 sentence); the ban engine and the `bans:` switch are named in the
196
+ installed `AGENTS.md`, so a ban is discoverable while the code is written and not only in the
197
+ post-mortem (V3-1); `bin/goblin-bans` reads a detect's exit 1 as VIOLATED even when stdout is
198
+ empty, so the code matches the exit contract it documents instead of failing open (V3-2); and
199
+ `PF-01` FAILs when `ratchet.ceiling` and `perf.baseline_value` disagree, so a hand-raised
200
+ ceiling no longer passes while printing the contradiction (G8-6b). The verifier's "cannot see"
201
+ footer now names the ban lane's own blind spots (V3-8), and `docs/ROLES.md`'s "exactly two
202
+ scripts" is corrected to the four an install actually writes (V3-6).
203
+ - **The feature map, the P6↔P12 wiring, and the skills evidence (G1, W2).**
204
+ `skills/goblin-feature-map/SKILL.md` is the map's contract — the README index, the four-H2 entry
205
+ contract, the rot table, the upkeep pass — and three **declared** config keys drive it:
206
+ `feature_map:` (the map's README; **empty means both FM rows SKIP with that reason**, so a fresh
207
+ install is not born RED), `source_root:` and `verify_doctor:`. Three new rows: `FM-01` (every
208
+ feature file indexed and linked, `feature:` equal to the filename stem, at least one
209
+ `entry_paths:`, the four H2s in order), `FM-02` (every declared entry path still resolves under
210
+ `source_root:` and none changed after its `verified:` date — a tripwire, never a proof) and
211
+ `VA-01` (the declared doctor exits 0, the executable half of P6's "never executed is a draft").
212
+ `P6` gains step 5 (seed the map) and step 6 (hand the generated skill to `P12`: `verified:` does
213
+ not advance until an eval record exists); `P12` gains the record format (`evals/<slug>/`), the
214
+ eleven-token ban, the cheap-checks-first ladder, the merge rule and the pass condition. The eval
215
+ **runner is not shipped** and no row reads a lane (`docs/LIMITS.md` #31). `docs/LIMITS.md` #15 is
216
+ corrected: the controlled evidence now exists — SkillsBench 1.1 measures curated Skills at
217
+ **+16.6 points (33.9% → 50.5%, 18 model–harness configurations, 87 tasks)**, and its
218
+ **self-generated condition put all three tested configurations BELOW their no-Skills baseline**
219
+ (`docs/RISKS.md` K15) — a warning about this repo's own agent-authored output, not someone
220
+ else's.
221
+ - **The judge role and the loop contract (G2, W3).** `role-judge` in `roles.yaml` — a capability,
222
+ never a model — plus `skills/goblin-judge` (what a judge is, and what it must refuse) and
223
+ `skills/goblin-loop` (the record it leaves). `docs/LOOP.md` is the contract **and** the measured
224
+ reading of Hermes's own `goal_mode`: the judge is called as `judge_goal(goal_text,
225
+ last_response)`, with **no contract, no subgoals and no quality gates**
226
+ (`hermes_cli/goals.py:1660`); it sees the card's goal (2000 chars) and the worker's own most
227
+ recent response (4000) (`:38`, `:901-905`); and the loop has **no progress detector at all** —
228
+ its whole state is `last_response`, `turns_used`, `nudged_to_finalize` (`:1634-1636`). Eight new
229
+ rows. `JG-01`: a `done` verdict may only cite a **handle the repo can resolve** (`sha:` a commit
230
+ in `git rev-list --all`, `file:` a path under the root, `sha256:` a file under `.goblin/loop/`) —
231
+ a `cmd:` token resolves **nothing**, because the command's output is not in the record.
232
+ `JG-02`: the declared judge lane must be **disjoint** from the author's — a FAIL, not a report;
233
+ an unresolved lane is an `ADV` with a one-line remedy, because a repo cannot choose the fleet's
234
+ routing. `JG-03`: a judge lane with no non-`done` verdict is escalated — **counted, never gated**,
235
+ and the advisory slot W2 left free for G2. `LP-01`..`LP-05`: one predicate command, run and
236
+ recorded (`exit=<n> ts=<ISO8601>`) **before iteration 1**; pinned by digest and never relaxed;
237
+ a budget under the new `loop_max_turns_ceiling` (default **20** — the engine's own
238
+ `DEFAULT_MAX_TURNS`, so the two numbers agree); no three consecutive rows on one evidence
239
+ pointer without reaching `predicate:green`; and a `.goblin/loop/stuck.md` naming the predicate
240
+ when the loop ends red. `templates/loop/` ships a copy-ready predicate and record header, and
241
+ **nothing installs them**: a fresh install must not be born with a loop record. `P10`'s role is
242
+ now `code + judge`, `P7` gains the S3+ foreman (`role-judge`, one decision from N lane verdicts),
243
+ and `docs/INTEGRATION.md`'s claim that the auxiliary judge "is the predicate re-check" is
244
+ corrected in place with the measured calls. `docs/LIMITS.md` #32 and #33 and `docs/RISKS.md` K17
245
+ record what the lane cannot see.
246
+ - **The CI lane and the desktop-shell class (G6, W4).** `PG-05` is **re-declared**, not patched: it
247
+ counted "every step is guarded", which passed the shape G8 measured — a single **job-level**
248
+ `if:`, a job with no step, and one *unguarded* step deciding whether the guarded gate step runs —
249
+ all of which reach the end of the job without running the gate while the required check reports
250
+ Success. It now FAILs all four. **`PG-06` is new**: the gate CI runs must be the gate the project
251
+ declares, read from the same `g_yaml_gates` reader `GT-01` uses so a gate cannot vanish from the
252
+ comparison in silence; a workflow satisfies it by running the verifier with no `--only`, or by
253
+ running every declared gate command verbatim, with comments blanked first. A `ci-gate` **part**
254
+ joins `manifest/classes.tsv` (`R` for A/F, `O` for C/E, `-` for B/D) and the installer renders
255
+ `templates/ci/goblin-gate.yml.tmpl` into `.github/workflows/goblin-gate.yml` — one job, no `if:`
256
+ anywhere, one step that runs the repo's own gate set. `CL-01`'s artifact for the part is that
257
+ exact path, never the `.github/` directory, so a repo that forbids `ci-gate` may still carry CI of
258
+ its own. `bin/goblin-install --uninstall` now walks **every** ancestor directory, because that
259
+ workflow empties two levels. **Class F (desktop shell)** is the new preset: five electron bans
260
+ (`BN-06` `nodeIntegration: true`, `BN-07` context isolation/sandbox off, `BN-08` the dangerous
261
+ `webPreferences`, `BN-09` synchronous IPC / `@electron/remote`) and the FPS number as a **host
262
+ gate** — the instrument needs Playwright or Electron plus a display, which no shipped rule may
263
+ depend on, so the ratchet carries the hermetic `app_bundle_bytes` instead. **A stated deviation
264
+ from G6 §B.3**, recorded in `docs/LIMITS.md` #35; a `ratchet.cmd` that cannot run would make a
265
+ fresh install born RED. `docs/CI.md` is the new contract: what makes a workflow a gate (required
266
+ check, no admin bypass, a push identity that is not the sole admin, never conditional), why frame
267
+ time is the wrong metric (measured p50 flat at 16.70 ms while the main thread went 1.8 % → 54.5 %
268
+ busy), and what is deliberately not mechanised. `docs/LIMITS.md` #13 and #34, `docs/RISKS.md` K7
269
+ and the new K18, `docs/DESIGN.md`'s "no CI workflow" invariant (amended as an architecture change)
270
+ and the verifier's "cannot see" footer all carry it.
271
+ - `manifest/enforcement.tsv` is **83 rules** (78 target, 5 source); the advisory count is **10 of
272
+ ceiling 10 — full**, unchanged (both new rows are real commands, so no slot was spent);
273
+ `tests/t-verify-red.sh` carries **105** controls and **19** `expect_green` — **124** over all 78
274
+ target rows, 0 uncovered and 0 phantom. (Superseded 2026-09-25: this line read 78 rules / 73
275
+ target / 93 controls / 14 green before W4's five rows landed. **Corrected 2026-09-25 (AB3):** the
276
+ census above was wrong when it was written — 0.4.0's own tree (`63d62d2`) carries **112**
277
+ `expect_red` + **22** `expect_green` = **134**, not 105 + 19 = 124, and the tree at 0.4.3 measures
278
+ **121** + **28** = **149**. The released numbers stand as written; this is their correction.)
279
+ - A fresh class-A install verifies **`43 passed, 0 failed, 11 advisory, 24 skipped`**, exit 0
280
+ (twenty-four rows skip with a reason: `HS-02`, `AU-02`, `AU-03`, `SC-06`, `SC-07`, `SC-08`,
281
+ `PF-01`, `BN-01`/`BN-02`/`BN-03`/`BN-05` plus `BN-06`..`BN-09` on a repo with no `src/`,
282
+ `FM-01`/`FM-02`/`VA-01` with no map
283
+ and no doctor declared, and `JG-01` + `LP-01`..`LP-05` with no `.goblin/loop/` record); `PG-05`
284
+ and `PG-06` do **not** skip, because this class installs the workflow they read. A fresh
285
+ class-B install (`bans: []`) verifies `37 passed, 0 failed, 10 advisory, 31 skipped`; class-C
286
+ verifies `43 passed, 0 failed, 11 advisory, 24 skipped`; class-E (`bans: [BN-02]`) verifies
287
+ `42 passed, 0 failed, 11 advisory, 25 skipped`; the new **class-F** verifies
288
+ `43 passed, 0 failed, 11 advisory, 24 skipped`; class-A with `--skills no` verifies
289
+ `39 passed, 0 failed, 11 advisory, 28 skipped`. All measured on fresh installs, committed with no
290
+ hand edit. (Superseded 2026-09-25: these lines read 42/0/9/14, 37/0/8/20, 42/0/9/14, 41/0/9/15
291
+ and 38/0/9/18 before G2's eight rows landed, and 42/0/11/20, 37/0/10/26, 42/0/11/20, 41/0/11/21
292
+ and 38/0/11/24 before W4's five.)
293
+
294
+ ## 0.3.0
295
+
296
+ - **The ban list (G5).** `manifest/bans.tsv`, `bin/goblin-bans` and `bans/` install as
297
+ `.goblin/manifest/bans.tsv`, `.goblin/bin/goblin-bans` and `.goblin/bans/` — Dune rule 2 made
298
+ a gate: **a ban without a mechanism is a wish.** Four bans ship with a real command each
299
+ (`BN-01` no `any`, `BN-02` no `@ts-ignore`/`@ts-expect-error`, `BN-03` no `fetch` from a
300
+ component, `BN-05` no import across a declared layer boundary), plus `BN-00` (the coherence
301
+ row: every ban has an enforcement row, every row names a replacement, the table is not empty).
302
+ The config gains `bans:` (which bans this project turns on — an unlisted ban SKIPs with a
303
+ reason), `bans_exempt:` (narrow, explicit exceptions) and `layers:` (what `BN-05` reads).
304
+ Class A and C turn on `BN-01 BN-02 BN-05`; E turns on `BN-02`.
305
+ - The ban probes are **text probes** (`grep`, no npm, no AST — `docs/CONTRACTS.md`), so G5's
306
+ `BN-04` (the nine named unnecessary-effect patterns) is **not shipped**: it cannot be
307
+ mechanised without a parser, and a ban that cannot go red is worse than advisory. Recorded in
308
+ `docs/LIMITS.md` #27 rather than spent as the last advisory slot. Advisory stays **9 of 10**.
309
+ - `manifest/enforcement.tsv` is **67 rules** (62 target, 5 source); `tests/t-verify-red.sh`
310
+ carries **68** controls over the 62 target rows.
311
+ - A fresh class-A install verifies **`42 passed, 0 failed, 9 advisory, 11 skipped`**, exit 0
312
+ (eleven rows skip with a reason: `HS-02`, `AU-02`, `AU-03`, `SC-06`, `SC-07`, `SC-08`,
313
+ `PF-01`, and `BN-01`/`BN-02`/`BN-03`/`BN-05` on a repo with no `src/`). A fresh class-B install
314
+ (`bans: []`) verifies `37 passed, 0 failed, 8 advisory, 17 skipped` — the four BN rows SKIP with
315
+ "not enabled in `bans:`"; class-C verifies `42 passed, 0 failed, 9 advisory, 11 skipped`; class-E
316
+ (`bans: [BN-02]`) verifies `41 passed, 0 failed, 9 advisory, 12 skipped`. All measured on fresh
317
+ installs, committed with no hand edit.
318
+
319
+ ## 0.2.0
320
+
321
+ - **Automation agents (G3).** `P13 goblin-bugreporter` and `P14 goblin-drift-audit`, plus the
322
+ producer half in `automations/` — `drift-audit.sh` (deterministic, network-free, silent when
323
+ clean, with a kill switch and a run ceiling) and `bugreporter-intake.sh` (the intake gate: a
324
+ missing key is a refusal card with **no assignee**, so it is structurally un-spawnable). The
325
+ files install to `.goblin/automations/`; the fleet steps are printed by `goblin-install` and
326
+ argued in `automations/README.md`. Six new rules: `AU-01`, `AU-02`, `AU-03`, `AU-04`,
327
+ `SK-04` ("every shipped skill says what it cannot see") and the source row `PR-05`
328
+ (`tests/t-automation-silent.sh` — the mutation is the control). Advisory was **8 of 10** after
329
+ G3 and is **9 of 10** once `SC-09` lands with G4.
330
+ - **Guard rails (G4).** `SC-01`..`SC-09` and `PF-01`: secrets and the config surface, input
331
+ boundaries and dependencies, and the performance lane. The perf budget stays `GT-04`/`GT-05`
332
+ (no second mechanism): the class-A preset's metric is now `client_js_bytes` and the TODO count
333
+ moved into a `todo_ceiling` gate. `bin/goblin-audit` installs to `.goblin/bin/` and is the ONE
334
+ tool allowed to touch the network - run deliberately, it writes the record `SC-07` reads
335
+ offline, and it refuses (exit 5) to write an empty record rather than let "nothing parsed" read
336
+ as "clean". A class declares its security surface and perf baseline in `security:` / `perf:`;
337
+ the guard rails are argued in `docs/GUARDRAILS.md`, and `tests/t-audit.sh` exercises the whole
338
+ producer offline against a canned npm-audit report.
339
+ - `manifest/enforcement.tsv` is **62 rules** (57 target, 5 source); playbooks are **14**;
340
+ `tests/t-verify-red.sh` carries **60** controls over the 57 target rows.
341
+ - A fresh class-A install verifies **`41 passed, 0 failed, 9 advisory, 7 skipped`**, exit 0
342
+ (seven rows skip with a reason: `HS-02`, `AU-02`, `AU-03`, `SC-06`, `SC-07`, `SC-08`,
343
+ `PF-01`); a fresh class-E install verifies `40 passed, 0 failed, 9 advisory, 8 skipped`.
344
+ Advisory is **9 of ceiling 10**.
345
+
346
+ ## 0.1.0
347
+
348
+ - First version. Ships `bin/goblin-install`, `bin/goblin-verify`, `bin/goblin-model`,
349
+ `bin/goblin-lib.sh`; `manifest/enforcement.tsv` (46 rules); 12 playbooks + `goblin-mode`
350
+ + `practice` as Hermes project-local skills; 5 class presets; the templates; and
351
+ `tests/run-tests.sh` with the negative control for every target-scope check class.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 goblin-stack contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,164 @@
1
- # Temporary Holding Version
1
+ # gobstack
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ **gobstack** (npm: [`@techgoblin/gobstack`](https://www.npmjs.com/package/@techgoblin/gobstack))
4
+ installs an **executable rule manifest**, a set of **project-local skills**, and an
5
+ **installer/verifier pair** into any project — so that an AI coding session never re-improvises,
6
+ and a rule that cannot be checked is counted rather than asserted.
7
+
8
+ Install it from npm — the one documented install path:
9
+
10
+ npm i -g @techgoblin/gobstack # gives you the `goblin` CLI
11
+
12
+ ## Install
13
+
14
+ npm i -g @techgoblin/gobstack
15
+
16
+ Then, from any project:
17
+
18
+ goblin install --target /path/to/repo --class A
19
+
20
+ The installer writes only paths it records, hash-compares before writing, and prints `no-op` on a
21
+ second run with the same arguments. It never overwrites `HANDOFF.md`, `AGENTS.md`, a `*-SPEC.md`,
22
+ `reviews/`, the `.gitignore` block or `.goblin/goblin.yaml`. Full option list and the three kinds
23
+ of file it manages: `docs/CONTRACTS.md`.
24
+
25
+ A repo that already has its own `HANDOFF.md` exits 1 on the refusal. That is the contract, not a
26
+ failure: reconcile the file rather than forcing over it — `docs/ADOPTION.md`.
27
+
28
+ After installing, in this order:
29
+
30
+ cd <target> && git add -A && git commit # the install is a change like any other
31
+ goblin verify # or .goblin/bin/goblin-verify, inside the target
32
+ hermes skills trust <target> # one-time, Hermes users, so project-tier skills load
33
+ goblin audit # once, deliberately: the ONLY network step (SC-07)
34
+
35
+ **A class-A install verifies green — `43 passed, 0 failed, 11 advisory, 28 skipped`, exit 0 — once
36
+ `HANDOFF.md` names a commit that exists. Before that edit the scaffold's `0000000` placeholder is
37
+ the one expected red: `42 passed, 1 failed`, `HP-05`. Both numbers measured 2026-09-25; the run and
38
+ the fix are step 2 of `docs/GUIDE.md`.**
39
+ Twenty-eight rows skip (`HS-02` has no pinned pre-change commit yet, so the REPLAY is not provable;
40
+ `AU-02` and `AU-03` have no report to audit; `SC-06`, `SC-07` and `SC-08` have no dependency
41
+ manifest, no lockfile and no audit record to read; `PF-01` has no measured perf baseline;
42
+ `BN-01`/`BN-02`/`BN-05` have no `src/` for a ban to read, and `BN-03` plus the four electron bans
43
+ `BN-06`/`BN-07`/`BN-08`/`BN-09` are not in this class's `bans:` list (`bans: [BN-01, BN-02, BN-05]`),
44
+ so they skip as *not enabled* rather than as *unread*; `FM-01`/`FM-02`/`VA-01`
45
+ have no feature map and no declared `verify_doctor:` yet; `RC-01`..`RC-04` have no reference corpus
46
+ declared and no lab `manifests/` to read; and `JG-01` with `LP-01`..`LP-05`
47
+ have no loop record, because no loop has run in this repo yet). **Two** rows do **not** skip: `PG-05`
48
+ and `PG-06`, the CI lane's. This class installs `.github/workflows/goblin-gate.yml`, so the two of
49
+ them read it and pass. Two, not four — the four electron bans named above are among the skips. Two of
50
+ the eleven advisories
51
+ are new with the judge lane: `JG-02` reports that the judge lane resolves to no profile on this
52
+ fleet (it prints the one-line remedy and never fails a repo for a fleet's routing), and `JG-03`
53
+ is the counted row the advisory ceiling had left for it. The parts
54
+ that only a round can produce — a first review note, a gate that is not the shipped floor — pass
55
+ *vacuously* rather than failing, and `P8` (`goblin-bootstrap`) still walks them as work to do.
56
+ The measurement and the vacuous-pass reading are in `docs/CONTRACTS.md`.
57
+
58
+ ## The `goblin` CLI
59
+
60
+ | command | what it does |
61
+ |---|---|
62
+ | `goblin verify` | run the rule matrix against the current repo — `PASS`/`FAIL`/`SKIP` per row, exit 0 pass · 1 a check failed · 2 could not run · 3 the manifest is broken |
63
+ | `goblin bans` | run the ban list (per-pattern red lines over the source tree) |
64
+ | `goblin audit` | check recorded dependency claims against live advisory feeds — the only command that touches the network |
65
+ | `goblin install` | install the manifest, skills and verifier into a target repo |
66
+ | `goblin uninstall` | remove everything an install wrote (npm shim `goblin install --target <dir> --uninstall`) |
67
+ | `goblin upgrade` | migrate a repo to the shared global engine at `~/.goblin/engine` — 8 steps, two commits, one report |
68
+ | `goblin doctor` | one run across the platforms below: DETECTED / NOT-DETECTED / DRIFT per platform |
69
+ | `goblin emit` | write the skills + context block for one platform (`--scope project` or `global`); `--unshadow` removes a hermes project skill whose hash equals the source |
70
+ | `goblin init` | the first-run wizard: detect → class → branch/email → first gate → emit → verify, one screen per question; every question has a flag (`--class app --branch main --email a@b.c --gate 'cmd' --emit hermes`), so CI runs it with zero prompts; `--dry-run` prints the plan and writes nothing |
71
+
72
+ ## Platforms
73
+
74
+ `goblin emit` and `goblin doctor` cover seven agent platforms, each detected via its own anchor:
75
+
76
+ | platform | what emit writes there |
77
+ |---|---|
78
+ | `claude` | skills + context block under `~/.claude` (or `--target`'s project scope) |
79
+ | `hermes` | skills + context block under `~/.hermes` |
80
+ | `copilot` | skills + context block under `~/.copilot` |
81
+ | `cursor` | skills + context block under `~/.cursor` |
82
+ | `opencode` | skills + context block under `~/.config/opencode` |
83
+ | `codex` | skills + context block under `~/.codex` (partial: some commands blocked, `docs/LIMITS.md` #47) |
84
+ | `gemini` | skills + context block under `~/.gemini` (partial: some commands blocked, `docs/LIMITS.md` #47) |
85
+
86
+ One run of `goblin emit --platform <p> --scope project` writes the skills and the context block a
87
+ session of that platform reads; `--scope global` writes to the machine-level anchor. `--dry-run`
88
+ prints the full write plan first.
89
+
90
+ ## What it is not
91
+
92
+ Not a rules document (every rule carries a runnable check or is explicitly counted as
93
+ advisory). Not a Cursor-plugin port (`subagent_type`, `/loop`, `/goal`, cloud agents and
94
+ vendored plugin paths do not exist here). Not a replacement for a project standard — it
95
+ **references** one by path and pins its hash, and carries none of its text.
96
+
97
+ ## Read this on GitHub
98
+
99
+ **New here? Read `docs/GUIDE.md` first.** It is the step-by-step getting-started guide — install,
100
+ the first green run, your first change. This README is the reference you come back to; the table
101
+ below is the reference material the guide points into, so the two do not compete for the first read.
102
+
103
+ | file | what it decides |
104
+ |---|---|
105
+ | `docs/GUIDE.md` | **read this first**: the first week, in order — install, the first verify, the REPLAY habit |
106
+ | `docs/DESIGN.md` | the thesis, the three load-bearing decisions, and every rejected alternative |
107
+ | `docs/FLOWS.md` | the 15 playbooks, with the 11 cuts and a reason for each |
108
+ | `docs/GUARDRAILS.md` | the security and perf rows (`SC-01`..`SC-09`, `PF-01`), the rung ladder, and what they cannot see |
109
+ | `docs/ROLES.md` | roles versus profiles, the model-mapping contract, the fan-out rule |
110
+ | `docs/ENFORCEMENT.md` | the matrix rendered for a human, and how a rule is added |
111
+ | `docs/CONTRACTS.md` | the installer/verifier interface, exit codes, idempotency, uninstall |
112
+ | `docs/INTEGRATION.md` | the board, cron, the skills precedence order, the referenced standard |
113
+ | `docs/RISKS.md` | the risk register, the advisory rows named, the non-goals |
114
+ | `docs/CI.md` | the CI lane: what makes a workflow a gate, the four settings a repository cannot set, and the desktop-shell class |
115
+ | `docs/LOOP.md` | the judge role and the loop contract: what a goal-mode loop actually does, the record, and what neither can see |
116
+ | `docs/ADOPTION.md` | the six classes, the preset matrix, the adoption order |
117
+ | `docs/LIMITS.md` | where this is weaker than its sources, and what is unproven |
118
+
119
+ `manifest/enforcement.tsv` is the source of truth for rules; `manifest/classes.tsv` for what a
120
+ class requires; `manifest/playbooks.tsv` for the flows; `manifest/glossary.tsv` for the
121
+ vocabulary.
122
+
123
+ ## Verify
124
+
125
+ goblin verify [--only <id[,id...]>] [--json] [--list] [--source <path>]
126
+
127
+ Exit codes: `0` pass · `1` a check failed · `2` could not
128
+ run · `3` the manifest is broken. Every run prints what it cannot see.
129
+
130
+ ## Develop
131
+
132
+ bash tests/run-tests.sh
133
+
134
+ Runs the source-scope rules (PR-01..PR-05) and the test scripts, including `t-verify-red.sh` —
135
+ one control per target-scope row (167 over 82 target rows), each required to go RED and then
136
+ restored, plus `t-audit.sh` for the SC-07 producer. **A verifier that only ever prints GREEN is a
137
+ failure**, so that file is the one that matters most.
138
+
139
+ ## Uninstall
140
+
141
+ goblin install --target <dir> --uninstall
142
+
143
+ Removes the installed artifacts, `.goblin/goblin.yaml` and every directory that leaves empty, and
144
+ leaves `HANDOFF.md`, `AGENTS.md`, `ROUND-000-SPEC.md`, `reviews/` and the `.gitignore` block —
145
+ the project's record is not the harness's to delete.
146
+
147
+ ## Re-pin the referenced standard
148
+
149
+ goblin install --target <dir> --re-pin
150
+
151
+ `practice_sha256:` pins the referenced standard and `IN-02` re-checks it, so editing that standard
152
+ — a legitimate, intended edit — reds `IN-02` in every installed repo. `--re-pin` re-records that
153
+ one line and prints the old and new hash; `IN-02` then reports `practice pin ok`. Nothing re-pins
154
+ automatically, not even `--upgrade`, and the `practice EDITED` failure prints this command. The
155
+ whole contract: `docs/CONTRACTS.md`, "An edited standard is not a dead end".
156
+
157
+ ## Dependencies
158
+
159
+ `bash`, `git`, `awk`, `sed`, `grep`, `python3` (the engine); node ≥ 18 for the npm shim only. No
160
+ jq, no yq, no network at verify time.
161
+
162
+ ## License
163
+
164
+ MIT.
package/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.4.4
@@ -0,0 +1,16 @@
1
+ # adapters/_template/adapter.tsv — W4A-SPEC §2. One row per adapter, tab-separated, header first.
2
+ # Columns:
3
+ # 1 id ^[a-z]+$, matches the directory name and --platform spelling
4
+ # 2 display human name in doctor output
5
+ # 3 detect_any ':'-separated paths (~ ok) and bare binary names; ANY hit => DETECTED
6
+ # 4 skills_path_project project-scope skill path pattern, relative to the repo (<name> slot)
7
+ # 5 skills_path_global global-scope skill path pattern (<name> slot)
8
+ # 6 context_path the context-injection file emit manages with a marker block ("-" = none)
9
+ # 7 docs_url the platform doc page the shapes came from
10
+ # 8 docs_read ISO date the URL was last verified (LIMITS #15 practice; an absent
11
+ # or empty cell is an unfilled PROBE-REQUIRED value => doctor DRIFT)
12
+ # 9-13 cap_skills cap_context_injection cap_command_blocking cap_marketplace cap_post_compaction
13
+ # yes|no|partial — the plan §3.3 capability matrix, as data.
14
+ # A malformed row (wrong column count, bad enum, id != directory, missing docs_read) is DRIFT
15
+ # by definition (R3): a capability table that cannot parse cannot be trusted.
16
+ id display detect_any skills_path_project skills_path_global context_path docs_url docs_read cap_skills cap_context_injection cap_command_blocking cap_marketplace cap_post_compaction
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env bash
2
+ # adapters/_template/detect.sh — the W5+ detection stub (W4A-SPEC §1).
3
+ #
4
+ # A template that silently
5
+ # exited 0 would make an unbuilt adapter look installed, so it refuses with 2
6
+ # and names the work — the same posture as the W1 doctor/emit placeholders.
7
+ # W4b built cursor/opencode/codex/gemini from copies of this directory; any
8
+ # future name copied from here must be measured before its row is filled.
9
+ printf 'detect: template adapter - not implemented (copy adapters/_template and fill in the anchors)\n' >&2
10
+ exit 2
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env bash
2
+ # adapters/_template/emit.sh — W5+ stub. Refuses until the adapter is built (the W4a
3
+ # precedent: a template that silently exited 0 would make an unbuilt adapter look real).
4
+ printf 'emit: template adapter - not implemented (copy adapters/_template and fill in the anchors)\n' >&2
5
+ exit 2
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env bash
2
+ # adapters/_template/verify.sh — W5+ stub. Refuses until the adapter is built.
3
+ printf 'verify: template adapter - not implemented (copy adapters/_template and fill in the anchors)\n' >&2
4
+ exit 2
@@ -0,0 +1,8 @@
1
+ # adapters/claude/adapter.tsv - W4A-SPEC SS2/SS8 P1. Shapes from Claude Code's own docs
2
+ # (code.claude.com/docs/en/skills + /memory, read 2026-09-29): skills are <name>/SKILL.md under
3
+ # .claude/skills/ (project) and ~/.claude/skills/ (personal), name+description frontmatter
4
+ # required to index; project memory is repo-root CLAUDE.md (the docs' project-instructions
5
+ # location; .claude/CLAUDE.md is listed as an alternate). settings.json and hooks are
6
+ # deliberately untouched (W4A-SPEC SS10.3).
7
+ id display detect_any skills_path_project skills_path_global context_path docs_url docs_read cap_skills cap_context_injection cap_command_blocking cap_marketplace cap_post_compaction
8
+ claude Claude Code ~/.claude:claude .claude/skills/<name>/SKILL.md ~/.claude/skills/<name>/SKILL.md CLAUDE.md https://code.claude.com/docs/en/skills 2026-09-29 yes full yes no yes
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ # adapters/claude/detect.sh — the detection contract (W4A-SPEC §3).
3
+ # Prints the detected anchor on stdout; exits 0 present / 1 absent.
4
+ # Side-effect-free, offline, read-only. DETECTED iff ~/.claude/ exists or `claude` is on PATH.
5
+ set -u
6
+ [ -d "${HOME:-}/.claude" ] && { printf '%s\n' "${HOME}/.claude"; exit 0; }
7
+ if command -v claude >/dev/null 2>&1; then printf '%s\n' "$(command -v claude)"; exit 0; fi
8
+ exit 1