@techgoblin/gobstack 0.4.4-beta.6 → 0.4.4-beta.8

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/bin/goblin-lib.sh CHANGED
@@ -216,6 +216,37 @@ g_installed_scalar() {
216
216
  sed -n "s/^[[:space:]]*\"$2\"[[:space:]]*:[[:space:]]*\"\{0,1\}\([^\",]*\)\"\{0,1\},\{0,1\}$/\1/p" "$1" | head -n 1
217
217
  }
218
218
 
219
+ # g_installed_scalar_options <file> <key> — the value of one key inside the "options" object
220
+ # of an install record (e.g. skills). The installer writes options on ONE line
221
+ # (`"options": {"skills": "yes", ...}`), so the awk reads that line's shape directly; a
222
+ # multi-line variant is read the same way the other installed_* readers read their block.
223
+ g_installed_scalar_options() {
224
+ awk -v k="$2" '
225
+ /^[[:space:]]*"options"[[:space:]]*:[[:space:]]*\{/ && index($0, "\"" k "\"") {
226
+ # single-line form: pull the value out between the key and the next , or }
227
+ line = $0
228
+ sub(/^[^{]*\{/, "", line) # everything up to and including the opening brace
229
+ n = split(line, pair, ",")
230
+ for (i = 1; i <= n; i++) {
231
+ p = pair[i]
232
+ sub(/^[[:space:]]*/, "", p); sub(/[[:space:]]*$/, "", p)
233
+ key = p; sub(/[[:space:]]*:.*/, "", key); gsub(/"/, "", key)
234
+ if (key == k) {
235
+ v = p; sub(/^[^:]*:[[:space:]]*/, "", v); gsub(/"/, "", v); sub(/\}[[:space:]]*$/, "", v)
236
+ print v; exit
237
+ }
238
+ }
239
+ exit
240
+ }
241
+ /^[[:space:]]*"options"[[:space:]]*:[[:space:]]*\{/ { inf = 1; next }
242
+ inf && /^[[:space:]]*\}/ { inf = 0 }
243
+ inf && index($0, "\"" k "\"") {
244
+ v = $0; sub(/^[^:]*:[[:space:]]*/, "", v); sub(/,?[[:space:]]*$/, "", v); gsub(/"/, "", v)
245
+ print v; exit
246
+ }
247
+ ' "$1"
248
+ }
249
+
219
250
  # ------------------------------------------------------------- self-test -----
220
251
  # Proves the parser actually parses. Every assertion is a real comparison against a
221
252
  # value written to a temp file in this function — blank the awk in g_yaml_scalar and
package/bin/goblin-verify CHANGED
@@ -536,6 +536,13 @@ check_in_02() {
536
536
  [ -e "$ROOT/$p" ] || continue ;;
537
537
  esac
538
538
  fi
539
+ # W6 neutral-first: an EXPLICIT --skills no re-install removes the recorded skill files
540
+ # by design (the record follows the switch). Their absence on a record whose options now
541
+ # say skills=no is the documented opt-out, not drift - the same clause W4a wrote for the
542
+ # global tier, scoped to the record's own declared choice.
543
+ case "$p" in
544
+ .hermes/skills/*) [ -e "$ROOT/$p" ] || [ "$(g_installed_scalar_options "$INSTALLED" skills)" = "yes" ] || continue ;;
545
+ esac
539
546
  n=$((n + 1))
540
547
  cur=$(g_sha256_file "$ROOT/$p")
541
548
  if [ "$cur" != "$h" ]; then
@@ -2661,6 +2668,21 @@ while IFS=$'\t' read -r id scope rule enforced_by artifact check why; do
2661
2668
  only_selected "$id" || continue
2662
2669
 
2663
2670
  part=$(row_part "$id")
2671
+ # W6 neutral-first: in global engine mode AU-01's subject is the PRODUCER glob, which
2672
+ # global mode reads from the engine dir — the row must run there even when the repo's
2673
+ # skills opt-out (playbooks) is set, or the W1 control below it is skip-masked. This
2674
+ # clause precedes the opt-out branch on purpose. SK-01/SK-02/SK-04 and AU-02..AU-04 keep
2675
+ # their opt-out semantics.
2676
+ if [ "$id" = "AU-01" ] && [ "$ENGINE_MODE" = "global" ]; then
2677
+ out=$(check_au_01 2>&1); rc=$?
2678
+ case "$rc" in
2679
+ 0) PASS=$((PASS + 1)); emit "$id" PASS "$out" ;;
2680
+ 1) FAIL=$((FAIL + 1)); emit "$id" FAIL "$out" ;;
2681
+ 2) ADV=$((ADV + 1)); emit "$id" ADV "$out" ;;
2682
+ 3) SKIP=$((SKIP + 1)); emit "$id" SKIP "$out" ;;
2683
+ esac
2684
+ continue
2685
+ fi
2664
2686
  if [ -n "$part" ] && g_part_disabled "$CONFIG" "$part"; then
2665
2687
  SKIP=$((SKIP + 1)); emit "$id" SKIP "$rule (opt-out: $part)"; continue
2666
2688
  fi
package/docs/ADOPTION.md CHANGED
@@ -102,13 +102,16 @@ Each step is independently useful and the later ones build on the earlier:
102
102
  Then, in order:
103
103
 
104
104
  git add -A && git commit # the install is a change like any other
105
- .goblin/bin/goblin-verify # 42 passed, 1 failed - HP-05, until HANDOFF names a commit
106
- hermes skills trust <target> # one-time, so the project-tier skills load
105
+ .goblin/bin/goblin-verify # 37 passed, 1 failed - HP-05, until HANDOFF names a commit
106
+ gob emit --platform <p> # optional, per platform: the agent skills are an opt-in
107
107
 
108
- A class-A install is **green** — `43 passed, 0 failed, 11 advisory, 28 skipped`, exit 0 — once
108
+ A default class-A install (no agent skills) is **green** — `38 passed, 0 failed, 11 advisory,
109
+ 33 skipped`, exit 0 — once
109
110
  `HANDOFF.md` names a commit that exists; before that edit the scaffold's `0000000` placeholder is
110
- the one expected red (`42 passed, 1 failed`). Both numbers are measured, not assumed
111
- (`docs/CONTRACTS.md`; step 2 of `docs/GUIDE.md`). Twenty-eight rows skip with a reason: `HS-02` (no
111
+ the one expected red (`37 passed, 1 failed`). Both numbers are measured, not assumed
112
+ (`docs/CONTRACTS.md`; step 2 of `docs/GUIDE.md`). Thirty-three rows skip with a reason: the
113
+ five skill rows (`SK-01`..`SK-04`, `AU-04`) skip on the `playbooks` opt-out a skills-free
114
+ install records, plus the not-yet rows: `HS-02` (no
112
115
  pinned pre-change commit yet), `AU-02`/`AU-03` (no report has been filed, so there is nothing to
113
116
  dedup and no reporter run to audit), `SC-06`/`SC-07`/`SC-08` (no dependency manifest, no lockfile,
114
117
  no audit record), `PF-01` (no measured perf baseline), `BN-01`/`BN-02`/`BN-05` (no `src/` for a ban
@@ -160,7 +163,7 @@ The remedy is a reconciliation. The project's file stays the file of record; not
160
163
  git add -A && git commit
161
164
  .goblin/bin/goblin-verify # HP-02, HP-03, HP-05 go green
162
165
 
163
- Success is the class's full green path (`43 passed, 0 failed, 11 advisory, 28 skipped`, exit 0 for
166
+ Success is the class's full green path (`38 passed, 0 failed, 11 advisory, 33 skipped`, exit 0 for
164
167
  class A) with `git status --short` empty.
165
168
 
166
169
  The edit is additive and small — measured on the model repo (§1's exemplar, 2450 lines): three
package/docs/CONTRACTS.md CHANGED
@@ -14,7 +14,10 @@ same way the fleet's own tool reads it. Everything else is line-oriented shell.
14
14
  --practice <path> the referenced standard (default: $GOBLIN_PRACTICE -> ~/projects/PROJECT-PRACTICE.md)
15
15
  --parts <list> comma list to install; default = every part the class requires
16
16
  --archive mark the project archive: verify requires no HANDOFF and no gates
17
- --skills yes|no install .hermes/skills (default yes; needs the one-time trust step)
17
+ --skills yes|no install agent skills under .hermes/skills (default no — the harness is
18
+ neutral; opt in per platform with: gob emit --platform <p>). On a repo whose
19
+ record already has skills installed, an OMITTED flag keeps them; an explicit
20
+ --skills no removes them.
18
21
  --dry-run print the plan; write nothing
19
22
  --upgrade re-install at the current version; report created/updated/unchanged/skipped
20
23
  --opt-out <part> record the part in disabled: so its required checks are skipped
@@ -37,7 +40,7 @@ files whose hash changed and prints `created C · updated U · unchanged N · sk
37
40
 
38
41
  | kind | recorded as | overwritten? | hash-checked? | removed by `--uninstall`? |
39
42
  |---|---|---|---|---|
40
- | installed artifact (bin, manifest, roles, skills, harness scaffold) | `files` | yes, on upgrade | yes — IN-02, SK-02 | yes |
43
+ | installed artifact (bin, manifest, roles, opt-in skills, harness scaffold) | `files` | yes, on upgrade | yes — IN-02, SK-02 | yes |
41
44
  | 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 |
42
45
  | pre-existing, left alone | `refused` | never | no — IN-04 only proves it was not taken over | no |
43
46
 
@@ -112,9 +115,9 @@ Output is one line per executed row, in manifest order, plus a summary line at t
112
115
  ADV MD-02 code lane and review lane both resolve to the same family
113
116
  SKIP HS-02 no pinned pre-change commit yet - REPLAY not provable
114
117
 
115
- Those four lines are one row of each marking. The summary line of a green class-A run is:
118
+ Those four lines are one row of each marking. The summary line of a green default class-A run is:
116
119
 
117
- 43 passed, 0 failed, 11 advisory, 28 skipped
120
+ 38 passed, 0 failed, 11 advisory, 33 skipped
118
121
 
119
122
  **Exit codes:** `0` every executed check passed (advisories and skips do not fail the run) ·
120
123
  `1` at least one check FAILED · `2` verify could not run (not installed, a missing dependency,
@@ -135,8 +138,10 @@ settings that make a workflow a **gate** are written down.
135
138
 
136
139
  ### A fresh install verifies green
137
140
 
138
- Measured on a fresh class-A install, committed with no hand edit: **`43 passed, 0 failed,
139
- 11 advisory, 28 skipped`, exit 0.** Twenty-eight rows skip with a reason: `HS-02` — no pre-change commit
141
+ Measured on a fresh DEFAULT class-A install (skills opt-in, W6 neutral-first), committed with no
142
+ hand edit: **`38 passed, 0 failed, 11 advisory, 33 skipped`, exit 0.** Thirty-three rows skip with
143
+ a reason — the same not-yet rows as before, plus the five skill rows (`SK-01`..`SK-04`,
144
+ `AU-04`) that skip on the `playbooks` opt-out a skills-free install records: `HS-02` — no pre-change commit
140
145
  is pinned yet, so the REPLAY is not provable (`docs/LIMITS.md` #11) — `AU-02` and `AU-03`, which
141
146
  have no report to audit in a repo where no reporter has run — `SC-06`, `SC-07` and `SC-08`, which
142
147
  have no dependency manifest, no lockfile and no audit record to read yet — `PF-01`, which has
@@ -173,13 +178,20 @@ verifier is reporting FAILs.
173
178
  - **Per part:** `--opt-out <part>` records the part in `disabled:`. `goblin-verify` then reports
174
179
  the part's rows as `SKIP (opt-out)` in the summary, so the opt-out is **visible rather than
175
180
  absent**. The same mechanism is what makes a class's `-` (off) real.
176
- - **The opt-out numbers are pinned (V3-3).** A fresh class-A install with `--skills no` verifies
177
- `39 passed, 0 failed, 11 advisory, 28 skipped`, exit 0, and `tests/t-install-off-switch.sh`
178
- asserts that line: a silent drift in the opt-out path is caught rather than left as a number
179
- nobody wrote down (the `--skills no` count moved from `37/0/9/11` at v0.2 to here when the ban
180
- rows landed, and no file recorded the shift; **the skipped count moved 15 → 18 on 2026-09-25
181
- (G1)** — the three new feature-map rows skip on the same path for the same reason, measured;
182
- **and 18 → 24 on 2026-09-25 (W3)** — the six judge/loop rows skip there too, measured).
181
+ - **The opt-out numbers are pinned (V3-3).** A class-A install with an explicit `--skills no`
182
+ verifies `38 passed, 0 failed, 11 advisory, 33 skipped`, exit 0, and
183
+ `tests/t-install-off-switch.sh` asserts that line: a silent drift in the opt-out path is caught
184
+ rather than left as a number nobody wrote down (the `--skills no` count moved from `37/0/9/11`
185
+ at v0.2 when the ban rows landed, **15 → 18 on 2026-09-25 (G1)** — the feature-map rows,
186
+ **18 → 24 on 2026-09-25 (W3)** — the judge/loop rows, and **to `38/0/11/33` at W6
187
+ (neutral-first)**, when this opt-out shape BECAME the default and the two lines converged:
188
+ the old default install measured `43/0/11/28`).
189
+ - **Skills, W6 neutral-first.** A default install ships no agent skills. A repo whose record has
190
+ `skills: yes` keeps them through every flag-less re-install and `--upgrade` (the installer
191
+ reads the record's choice and says so out loud); an explicit `--skills no` removes exactly the
192
+ recorded skill files; `--uninstall` removes everything recorded, as always.
193
+ `tests/t-install-off-switch.sh` walks that migration: install `--skills yes`, upgrade flag-less,
194
+ the skills survive byte-identical; uninstall, and they are all gone.
183
195
  - **Whole harness:** `--uninstall` deletes the `files` list plus `.goblin/goblin.yaml`, removes
184
196
  every directory that leaves empty (deepest first, after `installed.json` itself is gone — the
185
197
  order that used to leave `.goblin/` and the sixteen `.hermes/skills/*` directories behind),
package/docs/GUIDE.md CHANGED
@@ -106,18 +106,20 @@ or the plain installer this wizard drives, if you prefer the one-shot shape:
106
106
 
107
107
  Expected output (this is a real transcript, trimmed):
108
108
 
109
- created 50 · updated 0 · unchanged 0 · skipped 0
109
+ created 25 · updated 0 · unchanged 0 · skipped 0
110
110
 
111
111
  next:
112
112
  1. cd /tmp/gs-try && git add -A && git commit # the install is a change like any other
113
113
  2. .goblin/bin/goblin-verify # or add .goblin/bin to PATH
114
114
  3. edit .goblin/goblin.yaml: replace the default gate with your real commands (P8 step 3)
115
- 4. hermes skills trust /tmp/gs-try # one-time, so the project-tier skills load
115
+ 4. agent skills are opt-in: gob emit --platform <p> # hermes, claude, copilot, cursor, opencode, codex, gemini
116
116
 
117
- **`created 50`** is the installer's count of the files it **tracks** — the 41 in its `files` map,
118
- the 8 it `owns`, and `.gitignore`. It writes **51**: the 51st is `.goblin/installed.json`, the
119
- record it keeps for itself, which it writes but does not count. It has written nothing outside this
120
- directory.
117
+ **`created 25`** is the installer's count of the files it **tracks** — the 16 in its `files`
118
+ map, the 8 it `owns`, and `.gitignore`. It writes **26**: the 26th is `.goblin/installed.json`,
119
+ the record it keeps for itself, which it writes but does not count. It has written nothing
120
+ outside this directory. The default install ships **no agent skills** — the harness is neutral,
121
+ and `gob emit --platform <p>` is the per-platform opt-in (the old `--skills yes` default is
122
+ still there for repos that want the Hermes project tier vendored).
121
123
 
122
124
  ### Why `git init -b main` matters
123
125
 
@@ -141,14 +143,14 @@ branch** (unless you want to).
141
143
  You will see one line per rule. The shape:
142
144
 
143
145
  PASS IN-01 (test -s .goblin/installed.json && grep -q '"version"' .goblin/installed.json)
144
- PASS IN-02 40 installed files hashed | practice pin ok
146
+ PASS IN-02 16 installed files hashed | practice pin ok
145
147
  FAIL HP-05 HANDOFF.md names no commit that exists in this repo
146
148
  SKIP HS-02 no pinned pre-change commit yet - the REPLAY is not provable
147
149
  ADV HP-04 A stale sentence is corrected in place... (advisory)
148
150
 
149
151
  and a summary line at the bottom:
150
152
 
151
- 42 passed, 1 failed, 11 advisory, 28 skipped # the one FAIL is HP-05, below
153
+ 37 passed, 1 failed, 11 advisory, 33 skipped # the one FAIL is HP-05, below
152
154
 
153
155
  ### How to read that output
154
156
 
@@ -185,7 +187,7 @@ against a declared expectation. That is exactly what you want it to do.
185
187
  `HEAD when this file was written: `0000000``, and `HP-05` **rejects that placeholder on purpose**.
186
188
  A file that names a commit which does not exist is worse than one that names none — it looks like a
187
189
  record. Commit first, then write the real short SHA in. Measured: with the placeholder left in,
188
- verify reports `42 passed, 1 failed`; with the real SHA, `43 passed, 0 failed`.
190
+ verify reports `37 passed, 1 failed`; with the real SHA, `38 passed, 0 failed`.
189
191
 
190
192
  ---
191
193
 
@@ -305,9 +307,9 @@ honest entry, and the harness treats it as one.
305
307
  > **Prove it was broken first.**
306
308
 
307
309
  Before you trust a check, break the thing it checks and watch it go red — then put it back and watch
308
- it go green. Break it on a row this walkthrough can actually break: `IN-02` hashes the **41 files it
310
+ it go green. Break it on a row this walkthrough can actually break: `IN-02` hashes the **16 files it
309
311
  tracks** — not the 8 it `owns` (including `.goblin/goblin.yaml`, which §5 has you editing) and not
310
- `.goblin/installed.json`; edit one of the 41 — the exercise below uses `.goblin/bans/README.md`.
312
+ `.goblin/installed.json`; edit one of the 16 — the exercise below uses `.goblin/bans/README.md`.
311
313
 
312
314
  # REPLAY-BEGIN (this exact block is run by tests/t-doc-guide.sh - keep the two copies identical)
313
315
  .goblin/bin/goblin-verify --only IN-02 # expect PASS
@@ -393,13 +395,13 @@ the next session.
393
395
  A class-A install lands on a specific shape. The scaffold ships one deliberate red — `HP-05`, the
394
396
  `0000000` placeholder in `HANDOFF.md` (§4) — so a literal first run prints:
395
397
 
396
- 42 passed, 1 failed, 11 advisory, 28 skipped (the one FAIL is HP-05)
398
+ 37 passed, 1 failed, 11 advisory, 33 skipped (the one FAIL is HP-05)
397
399
 
398
400
  Name a real commit in `HANDOFF.md` and commit, and it is green:
399
401
 
400
- 43 passed, 0 failed, 11 advisory, 28 skipped (on a real project; your numbers will differ)
402
+ 38 passed, 0 failed, 11 advisory, 33 skipped (on a real project; your numbers will differ)
401
403
 
402
- **Twenty-eight rows skipping is correct**, and each skip prints its reason. In plain terms: the
404
+ **Thirty-three rows skipping is correct**, and each skip prints its reason. In plain terms: the
403
405
  harness is telling you which of its rules have nothing to read yet. It is a checklist, not a
404
406
  scolding.
405
407
 
@@ -579,7 +581,7 @@ with *"prove it was broken first"* — it is the one practice that survives cont
579
581
  # 1. try it somewhere disposable
580
582
  mkdir -p /tmp/gs-try && cd /tmp/gs-try
581
583
  git init -b main
582
- gob install --target . --class A # expect: created 50
584
+ gob install --target . --class A # expect: created 25 (no skills — those are gob emit)
583
585
 
584
586
  # 2. commit and check
585
587
  git add -A && git commit -m "chore: install gobstack"
package/docs/LIMITS.md CHANGED
@@ -111,7 +111,7 @@ deliberate trade or an unfilled gap.
111
111
  drift check — `IN-02`, `SK-02`, and `HS-01`'s hash of the harness dir — reads its expected
112
112
  hash out of that one file, and that file is the one file no check protects. Measured: append a
113
113
  byte to `.goblin/bin/goblin-verify`, rewrite its recorded hash in `installed.json`, commit, and
114
- the run is **fully GREEN** (`43 passed, 0 failed`, exit 0). One edit defeats three rows at
114
+ the run is **fully GREEN** (`38 passed, 0 failed`, exit 0). One edit defeats three rows at
115
115
  once, and it is the cheapest way to fake a green run. Doing better needs an anchor the target
116
116
  cannot edit — a signature, or a hash held outside the repo — and goblin-stack has no such
117
117
  trust root: the source checkout is not guaranteed to exist at verify time, and any value
@@ -0,0 +1,334 @@
1
+ Script started on 2026-10-02 00:53:48+07:00 [COMMAND="bash /home/harvey/projects/goblin-stack/bin/goblin-init --target /tmp/ptyfinal/repo --yes" <not executed on terminal>]
2
+
3
+
4
+
5
+
6
+
7
+
8
+
9
+
10
+ ▄███▄ ▄██▄ ██▄ █ ▄█▄ █ █ ▄██▀ █████ ▄███▄ ▄███ █ █
11
+ █ █ █ █ █▄▀█ █ █ █▄ █ ▀██▄ █ █ █ █ █ █
12
+ █ ▄██ █ █ █▄▀█ █ █ █ ▄█ ▄█▀ █ █████ █ ██
13
+ ▀██▀▀ ▀██▀ ██▀ ▀▀▀▀ ▀█▀ █ █ ██▀▀ ▀ █ █ ▀██▀ █ █
14
+  discipline around whatever executes
15
+ 
16
+  gob init — first-run setup (gobstack v0.4.4)
17
+  6 steps · every step has a flag · nothing is written until the plan is confirmed
18
+ 
19
+  ◆ 1. platforms 
20
+  ○ 2. class 
21
+  ○ 3. branch/email 
22
+  ○ 4. first gate 
23
+  ○ 5. emit 
24
+  ○ 6. done 
25
+ ▄███▄ ▄██▄ ██▄ █ ▄█▄ █ █ ▄██▀ █████ ▄███▄ ▄███ █ █
26
+ █ █ █ █ █▄▀█ █ █ █▄ █ ▀██▄ █ █ █ █ █ █
27
+ █ ▄██ █ █ █▄▀█ █ █ █ ▄█ ▄█▀ █ █████ █ ██
28
+ ▀██▀▀ ▀██▀ ██▀ ▀▀▀▀ ▀█▀ █ █ ██▀▀ ▀ █ █ ▀██▀ █ █
29
+  discipline around whatever executes
30
+ 
31
+  gob init — first-run setup (gobstack v0.4.4)
32
+  6 steps · every step has a flag · nothing is written until the plan is confirmed
33
+ 
34
+  ✔ 1. platforms 
35
+  ◆ 2. class 
36
+  ○ 3. branch/email 
37
+  ○ 4. first gate 
38
+  ○ 5. emit 
39
+  ○ 6. done 
40
+ 
41
+  ✔ 1. platforms 0 detected
42
+  no platform detected here — the wizard will still install the harness; emit later with gob emit
43
+ ▄███▄ ▄██▄ ██▄ █ ▄█▄ █ █ ▄██▀ █████ ▄███▄ ▄███ █ █
44
+ █ █ █ █ █▄▀█ █ █ █▄ █ ▀██▄ █ █ █ █ █ █
45
+ █ ▄██ █ █ █▄▀█ █ █ █ ▄█ ▄█▀ █ █████ █ ██
46
+ ▀██▀▀ ▀██▀ ██▀ ▀▀▀▀ ▀█▀ █ █ ██▀▀ ▀ █ █ ▀██▀ █ █
47
+  discipline around whatever executes
48
+ 
49
+  gob init — first-run setup (gobstack v0.4.4)
50
+  6 steps · every step has a flag · nothing is written until the plan is confirmed
51
+ 
52
+ 
53
+  ✔ 1. platforms 0 detected
54
+  no platform detected here — the wizard will still install the harness; emit later with gob emit
55
+  ✔ 1. platforms 0 detected
56
+  ✔ 2. class 
57
+  ◆ 3. branch/email 
58
+  ○ 4. first gate 
59
+  ○ 5. emit 
60
+  ○ 6. done 
61
+ 
62
+  what kind of work does this repo do?
63
+   1 ▸ app shipped features, PRs, review gates (class A)
64
+   2 service backend jobs, config, unattended runs (class B)
65
+   3 game playable builds, perf budgets (class C)
66
+   4 research specs, replays, reference corpora (class D)
67
+   5 agent fleets, loops, unattended automation (class E)
68
+   6 desktop the shell you live in, perf budget (class F)
69
+  ↑ number + Enter · Enter = app · the class letter works too (A-F)
70
+ 
71
+  ✔ 2. class A — shipped-software
72
+ ▄███▄ ▄██▄ ██▄ █ ▄█▄ █ █ ▄██▀ █████ ▄███▄ ▄███ █ █
73
+ █ █ █ █ █▄▀█ █ █ █▄ █ ▀██▄ █ █ █ █ █ █
74
+ █ ▄██ █ █ █▄▀█ █ █ █ ▄█ ▄█▀ █ █████ █ ██
75
+ ▀██▀▀ ▀██▀ ██▀ ▀▀▀▀ ▀█▀ █ █ ██▀▀ ▀ █ █ ▀██▀ █ █
76
+  discipline around whatever executes
77
+ 
78
+  gob init — first-run setup (gobstack v0.4.4)
79
+  6 steps · every step has a flag · nothing is written until the plan is confirmed
80
+ 
81
+ 
82
+  ✔ 1. platforms 0 detected
83
+  no platform detected here — the wizard will still install the harness; emit later with gob emit
84
+ 
85
+  what kind of work does this repo do?
86
+   1 ▸ app shipped features, PRs, review gates (class A)
87
+   2 service backend jobs, config, unattended runs (class B)
88
+   3 game playable builds, perf budgets (class C)
89
+   4 research specs, replays, reference corpora (class D)
90
+   5 agent fleets, loops, unattended automation (class E)
91
+   6 desktop the shell you live in, perf budget (class F)
92
+  ↑ number + Enter · Enter = app · the class letter works too (A-F)
93
+ 
94
+  ✔ 2. class A — shipped-software
95
+  ✔ 1. platforms 0 detected
96
+  ✔ 2. class A (shipped-software)
97
+  ✔ 3. branch/email 
98
+  ◆ 4. first gate 
99
+  ○ 5. emit 
100
+  ○ 6. done 
101
+ 
102
+  the forge contract — the identity this repo commits with (CM-01)
103
+ default branch ─ main
104
+ owner email ─ t@t.co
105
+  ✔ 3. branch/email main · t@t.co
106
+ ▄███▄ ▄██▄ ██▄ █ ▄█▄ █ █ ▄██▀ █████ ▄███▄ ▄███ █ █
107
+ █ █ █ █ █▄▀█ █ █ █▄ █ ▀██▄ █ █ █ █ █ █
108
+ █ ▄██ █ █ █▄▀█ █ █ █ ▄█ ▄█▀ █ █████ █ ██
109
+ ▀██▀▀ ▀██▀ ██▀ ▀▀▀▀ ▀█▀ █ █ ██▀▀ ▀ █ █ ▀██▀ █ █
110
+  discipline around whatever executes
111
+ 
112
+  gob init — first-run setup (gobstack v0.4.4)
113
+  6 steps · every step has a flag · nothing is written until the plan is confirmed
114
+ 
115
+ 
116
+  ✔ 1. platforms 0 detected
117
+  no platform detected here — the wizard will still install the harness; emit later with gob emit
118
+ 
119
+  what kind of work does this repo do?
120
+   1 ▸ app shipped features, PRs, review gates (class A)
121
+   2 service backend jobs, config, unattended runs (class B)
122
+   3 game playable builds, perf budgets (class C)
123
+   4 research specs, replays, reference corpora (class D)
124
+   5 agent fleets, loops, unattended automation (class E)
125
+   6 desktop the shell you live in, perf budget (class F)
126
+  ↑ number + Enter · Enter = app · the class letter works too (A-F)
127
+ 
128
+  ✔ 2. class A — shipped-software
129
+ 
130
+  the forge contract — the identity this repo commits with (CM-01)
131
+ 
132
+ 
133
+  ✔ 3. branch/email main · t@t.co
134
+  ✔ 1. platforms 0 detected
135
+  ✔ 2. class A (shipped-software)
136
+  ✔ 3. branch/email main · t@t.co
137
+  ✔ 4. first gate 
138
+  ◆ 5. emit 
139
+  ○ 6. done 
140
+ 
141
+  one real command that must stay green — suggested for a bash suite:
142
+  bash tests/run-tests.sh
143
+ gate command ─ bash tests/run-tests.sh
144
+  ✔ 4. first gate bash tests/run-tests.sh
145
+ ▄███▄ ▄██▄ ██▄ █ ▄█▄ █ █ ▄██▀ █████ ▄███▄ ▄███ █ █
146
+ █ █ █ █ █▄▀█ █ █ █▄ █ ▀██▄ █ █ █ █ █ █
147
+ █ ▄██ █ █ █▄▀█ █ █ █ ▄█ ▄█▀ █ █████ █ ██
148
+ ▀██▀▀ ▀██▀ ██▀ ▀▀▀▀ ▀█▀ █ █ ██▀▀ ▀ █ █ ▀██▀ █ █
149
+  discipline around whatever executes
150
+ 
151
+  gob init — first-run setup (gobstack v0.4.4)
152
+  6 steps · every step has a flag · nothing is written until the plan is confirmed
153
+ 
154
+ 
155
+  ✔ 1. platforms 0 detected
156
+  no platform detected here — the wizard will still install the harness; emit later with gob emit
157
+ 
158
+  what kind of work does this repo do?
159
+   1 ▸ app shipped features, PRs, review gates (class A)
160
+   2 service backend jobs, config, unattended runs (class B)
161
+   3 game playable builds, perf budgets (class C)
162
+   4 research specs, replays, reference corpora (class D)
163
+   5 agent fleets, loops, unattended automation (class E)
164
+   6 desktop the shell you live in, perf budget (class F)
165
+  ↑ number + Enter · Enter = app · the class letter works too (A-F)
166
+ 
167
+  ✔ 2. class A — shipped-software
168
+ 
169
+  the forge contract — the identity this repo commits with (CM-01)
170
+ 
171
+ 
172
+  ✔ 3. branch/email main · t@t.co
173
+ 
174
+  one real command that must stay green — suggested for a bash suite:
175
+  bash tests/run-tests.sh
176
+ 
177
+  ✔ 4. first gate bash tests/run-tests.sh
178
+  ✔ 1. platforms 0 detected
179
+  ✔ 2. class A (shipped-software)
180
+  ✔ 3. branch/email main · t@t.co
181
+  ✔ 4. first gate bash tests/run-tests.sh
182
+  ✔ 5. emit 
183
+  ◆ 6. done 
184
+  ✔ 5. emit 0 platform(s) · scope project
185
+
186
+ running: goblin-install --target /tmp/ptyfinal/repo --class A
187
+ created 50 · updated 0 · unchanged 0 · skipped 0
188
+
189
+ next:
190
+ 1. cd /tmp/ptyfinal/repo && git add -A && git commit # the install is a change like any other
191
+ 2. .goblin/bin/goblin-verify # or add .goblin/bin to PATH
192
+ 3. edit .goblin/goblin.yaml: replace the default gate with your real commands (P8 step 3)
193
+ 4. hermes skills trust /tmp/ptyfinal/repo # one-time, so the project-tier skills load
194
+
195
+ automations (optional; neither writes outside this repo, and A-02 has no agent in it):
196
+ bash /tmp/ptyfinal/repo/.goblin/automations/drift-audit.sh --dry-run # read the record first
197
+ cp /tmp/ptyfinal/repo/.goblin/automations/drift-audit.sh ~/.hermes/scripts/
198
+ hermes cron create "0 9 * * 1" --name "Drift audit - weekly" --no-agent \
199
+ --script drift-audit.sh --deliver <channel>
200
+ P13/P14 in docs/FLOWS.md; the whole model in automations/README.md
201
+ PASS IN-01 the install record exists and names its version
202
+ PASS IN-02 41 installed files hashed
203
+ PASS IN-03 the manifest is complete: every rule carries a check or is advisory, inside the enum
204
+ PASS IN-04 0 pre-existing file(s) left untouched
205
+ PASS HP-01 (test -f HANDOFF.md)
206
+ PASS HP-02 (for h in 'START HERE' 'STATE|STATUS' 'GATES?' 'NEXT STEPS|NEXT' 'NOT VERIFIED|UNVERIFIED|NOT PROVEN|UNPROVEN|PENDING[^.]*DEVICE TEST'; do grep -qiE "^#{2,3}[[:space:]]+[^[:alpha:]]*($h)\b" HANDOFF.md || { echo "missing section: $h"; exit 1; }; done)
207
+ PASS HP-03 1 gate line(s) inside the Gates section, each with a measured date (anchored on the declared gate name(s): commit todo_ceiling)
208
+ ADV HP-04 A stale sentence is corrected in place with a dated parenthetical, never deleted. (advisory)
209
+ PASS HP-05 names 3c96403 (ancestor of HEAD 3c96403)
210
+ PASS SP-01 (ls ./*-SPEC.md >/dev/null 2>&1)
211
+ FAIL SP-02 (test -z "$(git ls-files --others --exclude-standard -- '*-SPEC.md')" -> exit 1)
212
+ PASS SP-03 (awk '/^[[:space:]]*[-*][[:space:]]/ && /AC[0-9]*:/ && !/`|==|===|exit|<|>/ {print; bad=1} END{exit bad}' ./*-SPEC.md)
213
+ PASS GT-01 2 declared gate(s), each with a cmd
214
+ PASS GT-02 commit=0 todo_ceiling=0 · client_js_bytes 0 (ceiling 0) · measured 2026-10-02
215
+ PASS GT-03 (test -f .goblin/last-gate-line && [ .goblin/last-gate-line -nt "$(git rev-parse --git-dir)/logs/HEAD" ])
216
+ PASS GT-04 ratchet client_js_bytes ceiling 0
217
+ PASS GT-05 client_js_bytes 0 (ceiling 0)
218
+ PASS HS-01 not an asserting harness (report utility): gate.sh
219
+ 1 asserting harness(es), 1 report utility(ies)
220
+ SKIP HS-02 no pinned pre-change commit yet (replay.commit empty or unknown) - REPLAY not provable
221
+ ADV HS-03 Source probes read text with comments blanked first. (advisory)
222
+ PASS CM-01 (test "$(git log -1 --format='%ae')" = "$(grep '^owner_email:' .goblin/goblin.yaml | cut -d' ' -f2)")
223
+ ADV CM-02 The commit message was written to a file, not passed with -m. (advisory)
224
+ FAIL CM-03 9 dirty entr(y|ies), max_dirty 0
225
+ PASS MD-01 (for d in skills manifest bin templates presets .goblin .hermes; do [ -d "$d" ] || continue; grep -rniE '(d[e]epseek|cl[a]ude|g[p]t-[0-9]|gr[o]k|g[e]mini|g[l]m-[0-9]|k[i]mi)[a-z0-9.:_-]*' "$d" && exit 1; done; exit 0)
226
+ ADV MD-02 no model mapping configured (/tmp/ptyfinal/home/projects/fleet-model.yaml absent) - advisory
227
+ ADV MD-03 Role-pinned fan-out goes through kanban, not a model-less subagent spawn. (advisory)
228
+ PASS PG-01 0 review note(s)
229
+ PASS PG-02 0 review note(s) classified
230
+ PASS PG-03 0 review note(s) patch-id checked
231
+ ADV PG-04 Never bypass what the forge enforces. (advisory)
232
+ PASS PG-05 1 workflow file(s) checked for a self-skipping required check
233
+ PASS PG-06 goblin-gate.yml: runs the verifier, which executes every declared gate
234
+ 1 workflow file(s) compared with the 2 declared gate(s)
235
+ PASS DS-01 unchanged: .goblin/state.json=missing
236
+ PASS DS-02 snapshot .goblin/state.json=missing
237
+ ADV DOC-01 A significant change updates the docs that teach it. (advisory)
238
+ ADV DOC-02 System-level changes are recorded wherever the project's standard says they live. (advisory)
239
+ PASS SK-01 
240
+ PASS SK-02 20 installed skill file(s) hashed
241
+ PASS SK-03 advisory 10 of ceiling 10 (0 free slots: the next advisory row FAILs)
242
+ PASS SK-04 
243
+ PASS PT-01 (for d in skills manifest bin templates presets .goblin .hermes; do [ -d "$d" ] || continue; grep -rniE --exclude=goblin.yaml --exclude=installed.json '(h[a]rvey|tech-g[o]blin|/h[o]me/[a-z]+|g[o]blin-ui|op[e]n-door|sup[r]eme|bb[t]ech|c[l]v)' "$d" && exit 1; done; exit 0)
244
+ PASS PT-02 declared main, actual main
245
+ PASS CL-01 part pr-gate: optional, present
246
+ part review-panel: optional, present
247
+ part tokens: optional, absent
248
+ PASS CL-02 archive: false - the full class requirement applies
249
+ PASS SC-01 0 tracked secret file(s)
250
+ PASS SC-02 the whole secret family is ignored (.env, .env.local, .env.production proved by git)
251
+ PASS SC-03 0 client-visible secret-shaped name(s); no build output to scan for clause 2
252
+ PASS SC-04 0 cookie write(s) checked; a JS-written cookie is readable by any script - reported, not failed
253
+ PASS SC-05 0 write handler(s), 0 waived; 11 dir(s) declared
254
+ SKIP SC-06 no package.json - there is no dependency manifest to lock
255
+ SKIP SC-07 no audit record yet. Run .goblin/bin/goblin-audit once, deliberately, then commit
256
+ .goblin/audit.tsv: SC-07 reads the record and never the network
257
+ SKIP SC-08 no package-lock.json - there is no install-hook surface to enumerate
258
+ ADV SC-09 Auth is applied consistently across sibling routes. (advisory)
259
+ SKIP PF-01 no perf baseline recorded yet: run `find .next/static dist/assets dist -type f -name '*.js' -exec cat {} + 2>/dev/null | wc -c` on a pinned commit, then write
260
+ perf.baseline_commit, perf.baseline_value, perf.measured and the matching ratchet ceiling
261
+ PASS AU-01 2 automation producer(s) scanned, none opens with a network or forge verb
262
+ SKIP AU-02 no reports/*/report.yaml - nothing to dedup
263
+ SKIP AU-03 no reports/ - no reporter run in this repo to audit
264
+ PASS AU-04 
265
+ PASS BN-00 8 ban(s), each with an enforcement row and a named replacement
266
+ SKIP BN-01 No `any` in application TypeScript. (no matching files: src) 
267
+ SKIP BN-02 No `@ts-ignore` / `@ts-expect-error` suppressions. (no matching files: src) 
268
+ SKIP BN-03 No direct network call from a component. (not enabled in bans: - add BN-03 to .goblin/goblin.yaml to turn it on) 
269
+ SKIP BN-05 No import across a declared layer boundary. (no matching files: src) 
270
+ SKIP BN-06 No renderer with Node access (`nodeIntegration: true`). (not enabled in bans: - add BN-06 to .goblin/goblin.yaml to turn it on) 
271
+ SKIP BN-07 No renderer with context isolation or the process sandbox turned off. (not enabled in bans: - add BN-07 to .goblin/goblin.yaml to turn it on) 
272
+ SKIP BN-08 No dangerous webPreferences. (not enabled in bans: - add BN-08 to .goblin/goblin.yaml to turn it on) 
273
+ SKIP BN-09 No synchronous IPC and no `@electron/remote`. (not enabled in bans: - add BN-09 to .goblin/goblin.yaml to turn it on) 
274
+ SKIP FM-01 feature_map: is empty - no map is declared, so there is nothing to index
275
+ SKIP FM-02 feature_map: is empty - no map is declared, so there are no entry paths to resolve
276
+ SKIP VA-01 verify_doctor: is empty - no doctor is declared, so "the generated skill was executed once" is not provable here
277
+ SKIP JG-01 no loop record in this repo - no judge verdict to check
278
+ ADV JG-02 no model mapping configured (/tmp/ptyfinal/home/projects/fleet-model.yaml absent) - advisory
279
+ remedy: add a `judge:` entry beside the code lane in the file declared as models_file: in /tmp/ptyfinal/repo/.goblin/goblin.yaml
280
+ ADV JG-03 A judge lane that has never returned a non-`done` verdict is escalated. (advisory)
281
+ SKIP LP-01 no loop has run in this repo
282
+ SKIP LP-02 no loop has run in this repo
283
+ SKIP LP-03 no loop has run in this repo
284
+ SKIP LP-04 no loop has run in this repo
285
+ SKIP LP-05 no loop has run in this repo
286
+ SKIP RC-01 reference_manifest: is empty - no reference corpus is declared, so there is nothing for a build to match against
287
+ SKIP RC-02 reference_manifest: is empty - there is no manifest to shape-check (RC-01 skips for the same reason)
288
+ SKIP RC-03 no manifests/ directory - this is not a lab repo with a reference corpus, so there are no tracked bytes to check
289
+ SKIP RC-04 no manifests/*.sha256 - no acquisition record is declared, so there is none to read
290
+ 41 passed, 2 failed, 11 advisory, 28 skipped
291
+ of those 11 advisory: the matrix labels 10 row(s) advisory; the difference is the non-advisory row(s) reporting ADV by design (an unresolved lane) and any labelled row skipped by an opt-out
292
+ cannot see: whether a check in the harness dir tests the right path rather than
293
+ merely passing; whether the forge is bound by the workflow CL-01 found; whether a human
294
+ read the diff;
295
+ whether the model mapping names a family that actually differs (MD-02 reports it
296
+ and cannot change it); and whether .goblin/installed.json — the record every drift
297
+ check trusts — was itself rewritten. It is not signed, so one edit to it (with the
298
+ matching edit to the file it protects) defeats IN-02, SK-02 and HS-01 at once
299
+ (docs/LIMITS.md #18). The ban lane carries the same blind spot and two of its own:
300
+ the ban table is a manifest file under the same unsigned record, so a defanged ban
301
+ passes BN-00 (docs/LIMITS.md #28); a ban probe is a TEXT probe with no AST, so a
302
+ `Record<string, any>` is missed and a `: any` inside a string is reported
303
+ (docs/LIMITS.md #27); and no check here can reach a ban IN CONTEXT — the row proves
304
+ the forbidden path fails mechanically, never that the ban reached the agent that
305
+ wrote the line. The judge/loop lane adds its own: every JG-/LP- row reads a RECORD, so
306
+ it proves a handle, a pin, a budget and a pointer exist — never that the loop made
307
+ progress (a changed pointer is a proxy, docs/LIMITS.md #33), never which lane returned
308
+ a verdict, and never that the predicate was the right one or was really run. The CI lane
309
+ adds its own: PG-05 and PG-06 read a workflow's TEXT, so PG-05 sees a job whose gate step is
310
+ conditional and cannot see branch protection, the required-check list, or a forge that never
311
+ ran the job at all, and PG-06 proves a declared gate is INVOKED in a file under
312
+ .github/workflows/ — never that the forge marks that job required, never that it is the job
313
+ the forge waits on, and never that the workflow can fail (that is PG-05). A required check
314
+ that reports Success after skipping its gate is a green light for a commit whose gate never
315
+ ran (docs/CI.md). The reference-corpus lane adds its own: RC-01 matches EXACT sha256 only,
316
+ so a resized, recoloured or re-encoded reference asset, or copied text inside a shipped
317
+ string, passes it unseen; RC-02 proves the manifest is well-shaped, never that its entries
318
+ are the right hashes (as strong as tamper hashing, and installed.json is unsigned); RC-03
319
+ reads the tracked tree and cannot see a payload renamed and re-encoded; and RC-04 proves an
320
+ acquisition record EXISTS, never that the number beside it came from the store (HP-03's
321
+ defect, one artifact over). No row here reaches a reference asset in CONTEXT either.
322
+ engine: mode=vendored cli_sha256=2d37cf1c9f38a582ad60f3f75d2fcd53d10b743905dc3274eab6511c5c5ea008 enforcement_tsv_sha256=fd474c268b0852587c632910c503144fbcfe5e211ed2182902949a79fc5282b1
323
+
324
+ gob verify: 41 passed, 2 failed, 28 skipped · exit 1
325
+
326
+ next:
327
+ 1. the 28 skipped checks ARE your checklist — gob verify names each one
328
+ 2. replace the placeholder gate in .goblin/goblin.yaml with your real commands (P8 step 3)
329
+ 3. not emitted here: gob emit --platform <p> --scope global
330
+ 4. hermes skills trust /tmp/ptyfinal/repo # one-time, so the project-tier skills load
331
+
332
+ ▙ the goblin sees you. the gate is RED — start there.
333
+
334
+ Script done on 2026-10-02 00:53:50+07:00 [COMMAND_EXIT_CODE="0"]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@techgoblin/gobstack",
3
- "version": "0.4.4-beta.6",
3
+ "version": "0.4.4-beta.8",
4
4
  "description": "Agent-discipline toolkit: one verify command, an enforcement matrix, and LIMITS. bash engine, npm shim.",
5
5
  "bin": {
6
6
  "goblin": "bin/goblin.js",