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

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/README.md CHANGED
@@ -7,7 +7,7 @@ and a rule that cannot be checked is counted rather than asserted.
7
7
 
8
8
  Install it from npm — globally; it is a CLI, not a library:
9
9
 
10
- npm install -g @techgoblin/gobstack@beta # gives you the `goblin` CLI (and `gob`)
10
+ npm install -g @techgoblin/gobstack@beta # gives you the `gob` CLI (`goblin` remains as a legacy alias)
11
11
  npx @techgoblin/gobstack@beta init # or the one-shot: run the wizard, install nothing globally
12
12
 
13
13
  ## Install
@@ -27,8 +27,8 @@ never imports, and can fail resolution outright with `ERESOLVE` when the app's o
27
27
  dependencies disagree with npm's. If you see `ERESOLVE` after a local install, remove the
28
28
  dependency from `package.json` and install globally instead.
29
29
 
30
- **The two-layer model.** The global install gives you the CLI only. `goblin init` (or
31
- `goblin install --target <dir> --class A`) then vendors a self-contained engine into the target
30
+ **The two-layer model.** The global install gives you the CLI only. `gob init` (or
31
+ `gob install --target <dir> --class A`) then vendors a self-contained engine into the target
32
32
  repo under `.goblin/` — verifier, manifest, ban probes, skills, all of it. That second layer is
33
33
  why an initialized repo keeps working on machines with **no gobstack installed at all**: the
34
34
  engine lives in the repo, not in your `node_modules`, and `bash .goblin/bin/goblin-verify` (or a
@@ -36,7 +36,7 @@ plain `git` + `bash` box) is the only runtime the repo's gate needs.
36
36
 
37
37
  Then, from any project:
38
38
 
39
- goblin install --target /path/to/repo --class A
39
+ gob install --target /path/to/repo --class A
40
40
 
41
41
  The installer writes only paths it records, hash-compares before writing, and prints `no-op` on a
42
42
  second run with the same arguments. It never overwrites `HANDOFF.md`, `AGENTS.md`, a `*-SPEC.md`,
@@ -49,9 +49,9 @@ failure: reconcile the file rather than forcing over it — `docs/ADOPTION.md`.
49
49
  After installing, in this order:
50
50
 
51
51
  cd <target> && git add -A && git commit # the install is a change like any other
52
- goblin verify # or .goblin/bin/goblin-verify, inside the target
52
+ gob verify # or .goblin/bin/goblin-verify, inside the target
53
53
  hermes skills trust <target> # one-time, Hermes users, so project-tier skills load
54
- goblin audit # once, deliberately: the ONLY network step (SC-07)
54
+ gob audit # once, deliberately: the ONLY network step (SC-07)
55
55
 
56
56
  **A class-A install verifies green — `43 passed, 0 failed, 11 advisory, 28 skipped`, exit 0 — once
57
57
  `HANDOFF.md` names a commit that exists. Before that edit the scaffold's `0000000` placeholder is
@@ -76,23 +76,26 @@ that only a round can produce — a first review note, a gate that is not the sh
76
76
  *vacuously* rather than failing, and `P8` (`goblin-bootstrap`) still walks them as work to do.
77
77
  The measurement and the vacuous-pass reading are in `docs/CONTRACTS.md`.
78
78
 
79
- ## The `goblin` CLI
79
+ ## The `gob` CLI
80
80
 
81
81
  | command | what it does |
82
82
  |---|---|
83
- | `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 |
84
- | `goblin bans` | run the ban list (per-pattern red lines over the source tree) |
85
- | `goblin audit` | check recorded dependency claims against live advisory feeds — the only command that touches the network |
86
- | `goblin install` | install the manifest, skills and verifier into a target repo |
87
- | `goblin uninstall` | remove everything an install wrote, byte-exactly (`goblin install --target <dir> --uninstall` is the same job) |
88
- | `goblin upgrade` | migrate a repo to the shared global engine at `~/.goblin/engine` — 8 steps, two commits, one report |
89
- | `goblin doctor` | one run across the platforms below: DETECTED / NOT-DETECTED / DRIFT per platform |
90
- | `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 |
91
- | `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 |
83
+ | `gob 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 |
84
+ | `gob bans` | run the ban list (per-pattern red lines over the source tree) |
85
+ | `gob audit` | check recorded dependency claims against live advisory feeds — the only command that touches the network |
86
+ | `gob install` | install the manifest, skills and verifier into a target repo |
87
+ | `gob uninstall` | remove everything an install wrote, byte-exactly (`gob install --target <dir> --uninstall` is the same job) |
88
+ | `gob upgrade` | migrate a repo to the shared global engine at `~/.goblin/engine` — 8 steps, two commits, one report |
89
+ | `gob doctor` | one run across the platforms below: DETECTED / NOT-DETECTED / DRIFT per platform |
90
+ | `gob emit` | write the skills + context block for one platform (`--scope project` or `global`); `--unshadow` removes a hermes project skill whose hash equals the source |
91
+ | `gob 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 |
92
+
93
+ `goblin` remains as a legacy alias for every command above — existing scripts keep working, but
94
+ new commands and docs use `gob`.
92
95
 
93
96
  ## Platforms
94
97
 
95
- `goblin emit` and `goblin doctor` cover seven agent platforms, each detected via its own anchor:
98
+ `gob emit` and `gob doctor` cover seven agent platforms, each detected via its own anchor:
96
99
 
97
100
  | platform | what emit writes there |
98
101
  |---|---|
@@ -104,7 +107,7 @@ The measurement and the vacuous-pass reading are in `docs/CONTRACTS.md`.
104
107
  | `codex` | skills + context block under `~/.codex` (partial: some commands blocked, `docs/LIMITS.md` #47) |
105
108
  | `gemini` | skills + context block under `~/.gemini` (partial: some commands blocked, `docs/LIMITS.md` #47) |
106
109
 
107
- One run of `goblin emit --platform <p> --scope project` writes the skills and the context block a
110
+ One run of `gob emit --platform <p> --scope project` writes the skills and the context block a
108
111
  session of that platform reads; `--scope global` writes to the machine-level anchor. `--dry-run`
109
112
  prints the full write plan first.
110
113
 
@@ -143,7 +146,7 @@ vocabulary.
143
146
 
144
147
  ## Verify
145
148
 
146
- goblin verify [--only <id[,id...]>] [--json] [--list] [--source <path>]
149
+ gob verify [--only <id[,id...]>] [--json] [--list] [--source <path>]
147
150
 
148
151
  Exit codes: `0` pass · `1` a check failed · `2` could not
149
152
  run · `3` the manifest is broken. Every run prints what it cannot see.
@@ -166,7 +169,7 @@ touches the others.
166
169
 
167
170
  npm uninstall -g @techgoblin/gobstack
168
171
 
169
- This removes the `goblin` and `gob` commands from the machine and nothing else: no project, no
172
+ This removes the `gob` (and legacy `goblin`) commands from the machine and nothing else: no project, no
170
173
  repo, no `.goblin/` directory anywhere is touched. Repos you already initialized keep working
171
174
  fully — the engine is vendored into each repo's `.goblin/`, so the CLI's absence removes no
172
175
  capability (you lose the installer/upgrade/emit entry points, not the gate; see layer (c) for
@@ -174,10 +177,10 @@ the machine-level skills the CLI wrote).
174
177
 
175
178
  **(b) A project's harness** — the `.goblin/` tree an install created in one repo:
176
179
 
177
- goblin uninstall --target .
180
+ gob uninstall --target .
178
181
 
179
- (equivalently `goblin install --target . --uninstall`; through the short alias:
180
- `gob uninstall --target .`). The uninstall is **byte-exact**: it removes exactly the files
182
+ (equivalently `gob install --target . --uninstall` — through the legacy alias, spell it `goblin`
183
+ instead of `gob`). The uninstall is **byte-exact**: it removes exactly the files
181
184
  `installed.json` records — hash-compared preimages, so a file you edited after install is
182
185
  reported and kept, never clobbered — then every directory that leaves empty. After it, the repo
183
186
  has zero goblin files; only the project's own record (`HANDOFF.md`, `AGENTS.md`, `reviews/`, the
@@ -188,19 +191,19 @@ self-contained until the moment you remove it.
188
191
  **(c) Global agent skills** — the machine-level skills an `emit --scope global` wrote outside any
189
192
  repo:
190
193
 
191
- goblin emit --undo --platform <p> --scope global
194
+ gob emit --undo --platform <p> --scope global
192
195
 
193
196
  (`--undo` is the same byte-exact reversal as `--uninstall`, under its friendlier name). By hand,
194
197
  the same job is deleting the platform's anchor entries: `~/.claude/skills/goblin-*` (and the
195
198
  equivalents under `~/.hermes`, `~/.copilot`, `~/.cursor`, `~/.config/opencode`, `~/.codex`,
196
- `~/.gemini` — `goblin doctor` lists which platforms were detected).
199
+ `~/.gemini` — `gob doctor` lists which platforms were detected).
197
200
 
198
201
  The short version, for a full removal from a machine and its repos: (c) first, then (b) in each
199
202
  initialized repo, then (a).
200
203
 
201
204
  ## Re-pin the referenced standard
202
205
 
203
- goblin install --target <dir> --re-pin
206
+ gob install --target <dir> --re-pin
204
207
 
205
208
  `practice_sha256:` pins the referenced standard and `IN-02` re-checks it, so editing that standard
206
209
  — a legitimate, intended edit — reds `IN-02` in every installed repo. `--re-pin` re-records that
package/bin/goblin CHANGED
@@ -1,16 +1,17 @@
1
1
  #!/usr/bin/env bash
2
2
  # goblin — the global CLI dispatcher (W1, PLAN-V1 §2.3 / W1-SPEC §3).
3
3
  #
4
- # goblin verify [--only <id[,id...]>] [--json] [--list] [--source <path>]
5
- # goblin bans [--only <id[,id...]>] [--list]
6
- # goblin audit [--target <dir>] [--print]
7
- # goblin doctor [--platform <p>] # W4a
8
- # goblin emit --platform <p> [...] # W4a/W4b
9
- # goblin init [...] # W6: the first-run wizard
10
- # goblin upgrade [--target .] [...] # W3
11
- # goblin --version
4
+ # gob verify [--only <id[,id...]>] [--json] [--list] [--source <path>]
5
+ # gob bans [--only <id[,id...]>] [--list]
6
+ # gob audit [--target <dir>] [--print]
7
+ # gob doctor [--platform <p>] # W4a
8
+ # gob emit --platform <p> [...] # W4a/W4b
9
+ # gob init [...] # W6: the first-run wizard
10
+ # gob upgrade [--target .] [...] # W3
11
+ # gob --version
12
12
  #
13
- # Identity: the package is goblin-stack, the command is `goblin`. W1 ships the DISPATCH
13
+ # Identity: the package is gobstack (npm @techgoblin/gobstack), the command is `gob`
14
+ # (`goblin` remains as a legacy alias). W1 ships the DISPATCH
14
15
  # SHELL only — the node shim and npm packaging are W2, doctor/emit are W4a (exit-2
15
16
  # placeholders naming their workstream), upgrade is W3 (same). G3 forbids a runtime
16
17
  # rewrite: the engine stays bash, this file only routes and propagates.
@@ -39,16 +40,16 @@ g_err() { printf 'error: %s\n' "$*" >&2; }
39
40
 
40
41
  usage() {
41
42
  cat <<'USAGE'
42
- goblin — the goblin-stack command line.
43
+ gob — the gobstack command line.
43
44
 
44
- goblin verify [--only <id[,id...]>] [--json] [--list] [--source <path>]
45
- goblin bans [--only <id[,id...]>] [--list]
46
- goblin audit [--target <dir>] [--print]
47
- goblin doctor [--platform <p>] [--target <dir>]
48
- goblin emit --platform <p> --scope project|global [...]
49
- goblin init [--target <dir>] [--class app|A-F] [--dry-run]
50
- goblin upgrade [--target .] [--dry-run] [--yes] [--engine-dir <path>]
51
- goblin --version
45
+ gob verify [--only <id[,id...]>] [--json] [--list] [--source <path>]
46
+ gob bans [--only <id[,id...]>] [--list]
47
+ gob audit [--target <dir>] [--print]
48
+ gob doctor [--platform <p>] [--target <dir>]
49
+ gob emit --platform <p> --scope project|global [...]
50
+ gob init [--target <dir>] [--class app|A-F] [--dry-run]
51
+ gob upgrade [--target .] [--dry-run] [--yes] [--engine-dir <path>]
52
+ gob --version
52
53
 
53
54
  Exit codes (verify): 0 pass | 1 a check failed | 2 could not run | 3 the manifest is
54
55
  broken. Every subcommand propagates the engine's exit code verbatim.
package/bin/goblin-doctor CHANGED
@@ -40,9 +40,9 @@ ADAPTERS_DIR="$SRC/adapters"
40
40
 
41
41
  usage() {
42
42
  cat <<USAGE
43
- goblin doctor — one run, seven platforms (W4a, the seven since W4b).
43
+ gob doctor — one run, seven platforms (W4a, the seven since W4b).
44
44
 
45
- goblin doctor [--platform <$_PLA|hermes|copilot|cursor|opencode|codex|$_G1$_G2>]
45
+ gob doctor [--platform <$_PLA|hermes|copilot|cursor|opencode|codex|$_G1$_G2>]
46
46
  [--target <dir>] [--source <path>]
47
47
 
48
48
  Prints, per platform: the verdict (DETECTED / NOT-DETECTED / DRIFT), the detected
@@ -71,7 +71,7 @@ PLATFORMS="$_PLA hermes copilot cursor opencode codex $_G1$_G2"
71
71
  if [ -n "$ONLY" ]; then
72
72
  case "$ONLY" in
73
73
  $_PLA|hermes|copilot|cursor|opencode|codex|$_G1$_G2) PLATFORMS="$ONLY" ;;
74
- *) die "unknown platform '$ONLY' - goblin doctor ships $_PLA, hermes, copilot, cursor, opencode, codex, $_G1$_G2" 2 ;;
74
+ *) die "unknown platform '$ONLY' - gob doctor ships $_PLA, hermes, copilot, cursor, opencode, codex, $_G1$_G2" 2 ;;
75
75
  esac
76
76
  fi
77
77
 
package/bin/goblin-emit CHANGED
@@ -68,9 +68,9 @@ PREIMG="${GOBLIN_PREIMAGES:-$HOME/.goblin-stack/preimages}"
68
68
 
69
69
  usage() {
70
70
  cat <<USAGE
71
- goblin emit — per-platform emission (W4a, the seven platforms since W4b).
71
+ gob emit — per-platform emission (W4a, the seven platforms since W4b).
72
72
 
73
- goblin emit --platform <$_PLA|hermes|copilot|cursor|opencode|codex|$_G1$_G2>
73
+ gob emit --platform <$_PLA|hermes|copilot|cursor|opencode|codex|$_G1$_G2>
74
74
  --scope project|global
75
75
  [--skills core|all|none] [--target <dir>] [--source <path>]
76
76
  [--uninstall] [--unshadow] [--dry-run] [--strict]
@@ -143,7 +143,7 @@ case "$PLATFORM" in
143
143
  "") printf 'error: emit: --platform is required\n' >&2; usage >&2; exit 2 ;;
144
144
  $_PLA|hermes|copilot|cursor|opencode|codex|$_G1$_G2) ;;
145
145
  *)
146
- die "unknown platform '$PLATFORM' - goblin emit ships $_PLA, hermes, copilot, cursor, opencode, codex, $_G1$_G2" 2
146
+ die "unknown platform '$PLATFORM' - gob emit ships $_PLA, hermes, copilot, cursor, opencode, codex, $_G1$_G2" 2
147
147
  ;;
148
148
  esac
149
149
  TSV="$ADAPTERS_DIR/$PLATFORM/adapter.tsv"
package/bin/goblin-init CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env bash
2
2
  # goblin-init — the W6 first-run wizard (`gob init`).
3
3
  #
4
- # goblin init [--target <dir>] [--class <app|service|game|research|agent|desktop|A..F>]
4
+ # gob init [--target <dir>] [--class <app|service|game|research|agent|desktop|A..F>]
5
5
  # [--branch <name>] [--email <addr>] [--gate <cmd>]
6
6
  # [--emit <p[,p..]>] [--scope project|global] [--yes] [--dry-run]
7
7
  #
@@ -137,7 +137,7 @@ done
137
137
  for dep in git awk sed grep; do
138
138
  command -v "$dep" >/dev/null 2>&1 || { g_err "missing dependency: $dep"; exit 2; }
139
139
  done
140
- [ -f "$SRC/VERSION" ] || { g_err "no VERSION at $SRC — is this a goblin-stack checkout?"; exit 2; }
140
+ [ -f "$SRC/VERSION" ] || { g_err "no VERSION at $SRC — is this a gobstack checkout?"; exit 2; }
141
141
  [ -n "$SCOPE" ] || SCOPE="project"
142
142
  case "$SCOPE" in project|global) ;; *) g_err "--scope must be project or global, got '$SCOPE'"; exit 2 ;; esac
143
143
  TARGET="${TARGET:-$PWD}"
@@ -146,17 +146,18 @@ TARGET=$(g_expand_tilde "$TARGET")
146
146
  TARGET=$(cd "$TARGET" && pwd)
147
147
 
148
148
  # ------------------------------------------------------------ screen 1: welcome
149
- printf '%s\n' "${C_ACCENT} ▄▄ ▄▄▄ ▄ ▄ ▄▄▄ ▄▄▄ ▄▄▄ ▄ ▄ ▄▄▄ ▄▄${C_RESET}"
150
- printf '%s\n' "${C_ACCENT} ▀▄▀ ▄▄▀ ▄ ▀ ▄▄▀ █ █ █▄▄ ▀▄█ █ █ █▄▄${C_RESET}"
151
- printf '%s\n' "${C_ACCENT} ▄▄█ █▄▄ █ ▄ █▄▄ █▄█ █▄▄ ██ █▄█ █ █${C_RESET}"
149
+ printf '%s\n' "${C_ACCENT}▄███▄ ▄██▄ ██▄ █ ▄█▄ █ █ ▄██▀ █████ ▄███▄ ▄███ █ █${C_RESET}"
150
+ printf '%s\n' "${C_ACCENT}█ █ █ █ █▄▀█ █ █ █▄ █ ▀██▄ █ █ █ █ █ █${C_RESET}"
151
+ printf '%s\n' "${C_ACCENT}█ ▄██ █ █ █▄▀█ █ █ █ ▄█ ▄█▀ █ █████ █ ██${C_RESET}"
152
+ printf '%s\n' "${C_ACCENT}▀██▀▀ ▀██▀ ██▀ ▀▀▀▀ ▀█▀ █ █ ██▀▀ ▀ █ █ ▀██▀ █ █${C_RESET}"
152
153
  printf '%s\n' "${C_DIM} discipline around whatever executes${C_RESET}"
153
154
  printf '\n'
154
- printf '%s\n' "${C_TEXT} gob init${C_RESET} ${C_MUTED}— first-run setup (goblin-stack v$VERSION)${C_RESET}"
155
+ printf '%s\n' "${C_TEXT} gob init${C_RESET} ${C_MUTED}— first-run setup (gobstack v$VERSION)${C_RESET}"
155
156
  printf '%s\n' " ${C_MUTED}6 steps · every step has a flag · nothing is written until the plan is confirmed${C_RESET}"
156
157
  printf '\n'
157
158
  CURRENT=1
158
159
  if [ "$TTY_OUT" -eq 1 ]; then rail_print
159
- else cascade "welcome: goblin-stack v$VERSION — the guided first run"; fi
160
+ else cascade "welcome: gobstack v$VERSION — the guided first run"; fi
160
161
 
161
162
  # Platform enum assembled from fragments (the MD_SLUG precedent): a literal tool name in
162
163
  # bin/ trips MD-01's model-name pattern, and run-tests.sh greps this directory.
@@ -227,7 +228,7 @@ if [ -z "$CLASS" ]; then
227
228
  q " $C_TEXT 4 research specs, replays, reference corpora ${C_DIM}(class D)$C_RESET"
228
229
  q " $C_TEXT 5 agent fleets, loops, unattended automation ${C_DIM}(class E)$C_RESET"
229
230
  q " $C_TEXT 6 desktop the shell you live in, perf budget ${C_DIM}(class F)$C_RESET"
230
- q " $C_MUTED↑ number + Enter · Enter = app · the class letter works too (A-F)$C_RESET"
231
+ q " ${C_MUTED}↑ number + Enter · Enter = app · the class letter works too (A-F)$C_RESET"
231
232
  printf ' '
232
233
  read -r REPLY_CLASS
233
234
  ASKED_ANY=1
@@ -360,7 +361,7 @@ if [ "$TTY_IN" -eq 1 ] && [ -z "$EMIT" ] && [ "$YES" -eq 0 ]; then
360
361
  hit=""
361
362
  while IFS=$' ' read -r dp _a _b _c; do [ "$dp" = "$p" ] && hit=1; done <<< "$DET_ROWS"
362
363
  [ -n "$hit" ] || continue
363
- q " $C_GREEN✔$C_RESET $C_TEXT$p$C_RESET"
364
+ q " ${C_GREEN}✔$C_RESET $C_TEXT$p$C_RESET"
364
365
  done
365
366
  q " ${C_DIM}Enter = these; or type platform names to override$C_RESET"
366
367
  printf ' '
@@ -388,7 +389,7 @@ add() { BOX="$BOX$1
388
389
  "; }
389
390
  add " ${C_DIM}╭──────────────────────────────────────────────────────╮${C_RESET}"
390
391
  add " ${C_DIM}│${C_RESET} ${C_GREEN}✔${C_RESET} ${C_TEXT}install${C_RESET} $C_DIM.goblin/ + the payload into$C_RESET $C_TEXT$TARGET$C_RESET"
391
- add " ${C_DIM}│${C_RESET} ${C_GREEN}✔${C_RESET} ${C_TEXT}class${C_RESET} $C_TEXT$CLASS$C_RESET $C_DIM· branch $C_TEXT$BRANCH$C_RESET $C_DIM· email$C_RESET $C_TEXT$EMAIL$C_RESET"
392
+ add " ${C_DIM}│${C_RESET} ${C_GREEN}✔${C_RESET} ${C_TEXT}class${C_RESET} $C_TEXT$CLASS$C_RESET ${C_DIM}· branch $C_TEXT$BRANCH$C_RESET ${C_DIM}· email$C_RESET $C_TEXT$EMAIL$C_RESET"
392
393
  add " ${C_DIM}│${C_RESET} ${C_GREEN}✔${C_RESET} ${C_TEXT}gate${C_RESET} $C_TEXT$GATE$C_RESET"
393
394
  add " ${C_DIM}│${C_RESET} ${C_GREEN}✔${C_RESET} ${C_TEXT}emit${C_RESET} $C_TEXT$EMIT_N platform(s), scope $SCOPE$C_RESET$([ "$EMIT_N" -gt 0 ] && printf '%s' " $C_DIM($(printf '%s' "$EMIT_SELECTED" | awk '{$1=$1};1'))$C_RESET")"
394
395
  add " ${C_DIM}╰──────────────────────────────────────────────────────╯${C_RESET}"
@@ -456,7 +457,7 @@ for p in $EMIT_SELECTED; do
456
457
  bash "$SRC/bin/goblin-emit" --platform "$p" --scope "$SCOPE" --target "$TARGET"
457
458
  EXIT_EMIT=$?
458
459
  if [ "$EXIT_EMIT" -ne 0 ]; then
459
- g_err "emit $p failed (exit $EXIT_EMIT) — run 'goblin emit --platform $p --scope $SCOPE' to see the refusal again"
460
+ g_err "emit $p failed (exit $EXIT_EMIT) — run 'gob emit --platform $p --scope $SCOPE' to see the refusal again"
460
461
  exit "$EXIT_EMIT"
461
462
  fi
462
463
  EMITTED=$((EMITTED + 1))
@@ -489,9 +490,9 @@ if [ "$DRYRUN" -eq 0 ]; then
489
490
  done
490
491
  printf '\n'
491
492
  if [ "$VERIFY_RC" -eq 0 ]; then
492
- printf ' %sgoblin verify: %s passed, %s failed, %s skipped · exit 0%s\n' "$C_GREEN" "$PASSED" "$FAILED" "$SKIPPED" "$C_RESET"
493
+ printf ' %sgob verify: %s passed, %s failed, %s skipped · exit 0%s\n' "$C_GREEN" "$PASSED" "$FAILED" "$SKIPPED" "$C_RESET"
493
494
  else
494
- printf ' %sgoblin verify: %s passed, %s failed, %s skipped · exit %s%s\n' "$C_RED" "$PASSED" "$FAILED" "$SKIPPED" "$VERIFY_RC" "$C_RESET"
495
+ printf ' %sgob verify: %s passed, %s failed, %s skipped · exit %s%s\n' "$C_RED" "$PASSED" "$FAILED" "$SKIPPED" "$VERIFY_RC" "$C_RESET"
495
496
  fi
496
497
  printf '\n'
497
498
  else
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env bash
2
2
  # goblin-install — drop the harness into a target repo, idempotently.
3
3
  #
4
- # Usage: goblin-install --target <dir> [options]
4
+ # Usage: gob install --target <dir> [options] (script: bin/goblin-install)
5
5
  # --target <dir> required; the repo root to install into
6
6
  # --class A|B|C|D|E|F required unless --uninstall or --re-pin; anything else needs an explicit class
7
7
  # --models <path> model mapping file (default: $GOBLIN_MODELS -> ~/projects/fleet-model.yaml)
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env bash
2
- # goblin-upgrade — the 0.4.4 per-repo → global migration (W3, W3-SPEC §2).
2
+ # goblin-upgrade — the 0.4.4 per-repo → global engine migration (W3).
3
3
  #
4
- # goblin upgrade [--target <dir>] [--dry-run] [--yes] [--engine-dir <path>]
4
+ # gob upgrade [--target <dir>] [--dry-run] [--yes] [--engine-dir <path>]
5
5
  #
6
6
  # What it does (the corrected 7-step sequence, W3-SPEC §2 — the record is rewritten
7
7
  # BEFORE the deletion, and every verify runs against a committed tree, CM-03):
@@ -230,7 +230,7 @@ if [ "${RECORD_OK:-0}" -eq 1 ] && [ -z "${MODE:-}" ]; then
230
230
  R8_MSG="upgrade: partial migration detected - the record says global but $PAYLOAD_N engine files are still here. fix: resume by removing them (the engine lives at ${BLOCK_DIR:-$ED}), or roll back: git revert <commit A>"
231
231
  elif [ "$BLOCK_MODE" != "global" ] && [ "$RECORD_ENGINE_N" -lt 18 ]; then
232
232
  MODE="refuse-R9" # hand-migration: entries PARTIALLY or fully dropped, no block
233
- R9_MSG="upgrade: $REPO's record is missing its engine: block and carries only $RECORD_ENGINE_N of the 18 engine entries - dropped $((18 - RECORD_ENGINE_N)) by hand, a state goblin upgrade did not produce. fix: restore the record (git checkout .goblin/installed.json) and re-run"
233
+ R9_MSG="upgrade: $REPO's record is missing its engine: block and carries only $RECORD_ENGINE_N of the 18 engine entries - dropped $((18 - RECORD_ENGINE_N)) by hand, a state gob upgrade did not produce. fix: restore the record (git checkout .goblin/installed.json) and re-run"
234
234
  elif [ "$PAYLOAD_N" -eq 0 ]; then
235
235
  MODE="refuse-R5" # fresh-shape record but no payload to lift
236
236
  R5_MSG="upgrade: no engine at $ED and no vendored payload to lift it from - install the engine first (goblin-install a fresh repo, or set --engine-dir)"
@@ -244,7 +244,7 @@ fi
244
244
 
245
245
  # ---- dry-run report -------------------------------------------------------------
246
246
  if [ "$DRY_RUN" -eq 1 ]; then
247
- printf 'goblin upgrade --dry-run — target %s\n' "$REPO"
247
+ printf 'gob upgrade --dry-run — target %s\n' "$REPO"
248
248
  printf ' engine-dir: %s\n' "$ED"
249
249
  case "$MODE" in
250
250
  migrate)
@@ -447,7 +447,7 @@ if [ -f "$GATE" ] && grep -q '\.goblin/bin/goblin-lib.sh' "$GATE"; then
447
447
  awk '
448
448
  /^# shellcheck source=\/dev\/null$/ && !done {
449
449
  print "# shellcheck source=/dev/null"
450
- print "# The engine went global (goblin upgrade): resolve it exactly as"
450
+ print "# The engine went global (gob upgrade): resolve it exactly as"
451
451
  print "# goblin-verify does - engine_dir:, then the machine default."
452
452
  print "CONFIG=\"$ROOT/.goblin/goblin.yaml\""
453
453
  print "ENGINE_DIR=$(sed -n \"s/^engine_dir:[[:space:]]*//p\" \"$CONFIG\" | head -n 1)"
package/bin/goblin-verify CHANGED
@@ -1363,7 +1363,7 @@ check_sc_07() {
1363
1363
  local rec="$ROOT/.goblin/audit.tsv" wfile="$ROOT/.goblin/audit-waiver.tsv"
1364
1364
  if [ ! -f "$rec" ]; then
1365
1365
  if [ "$ENGINE_MODE" = "global" ]; then
1366
- printf 'no audit record yet. Run `goblin audit` once, deliberately, then commit\n.goblin/audit.tsv: SC-07 reads the record and never the network\n'
1366
+ printf 'no audit record yet. Run `gob audit` once, deliberately, then commit\n.goblin/audit.tsv: SC-07 reads the record and never the network\n'
1367
1367
  else
1368
1368
  printf 'no audit record yet. Run .goblin/bin/goblin-audit once, deliberately, then commit\n.goblin/audit.tsv: SC-07 reads the record and never the network\n'
1369
1369
  fi
package/bin/goblin.js CHANGED
@@ -6,15 +6,15 @@
6
6
  // and a marketplace packager stripping the executable bit breaks the symlink, not
7
7
  // the spawnSync path below.
8
8
  //
9
- // goblin verify [--only <id,...>] ... -> bin/goblin-verify
10
- // goblin bans [...] -> bin/goblin-bans
11
- // goblin audit [...] -> bin/goblin-audit
12
- // goblin upgrade [...] -> bin/goblin-upgrade (W3)
13
- // goblin doctor [...] -> bin/goblin-doctor (W4a)
14
- // goblin emit [...] -> bin/goblin-emit (W4a)
15
- // goblin init [...] -> bin/goblin-init (W6, the first-run wizard)
16
- // goblin uninstall [--target <dir>] -> bin/goblin-install --uninstall
17
- // goblin install [...] -> bin/goblin-install (the one legacy fallback)
9
+ // gob verify [--only <id,...>] ... -> bin/goblin-verify
10
+ // 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 uninstall [--target <dir>] -> bin/goblin-install --uninstall
17
+ // gob install [...] -> bin/goblin-install (the one legacy fallback)
18
18
  // no args | -h/--help | any other unrecognized first arg
19
19
  // -> this file's short usage, exit 2. A bare `goblin`
20
20
  // used to fall through into the installer; a typo
@@ -50,23 +50,23 @@ const [cmd, ...rest] = process.argv.slice(2);
50
50
  // No args, a help flag, or an unrecognized first arg: short usage, exit 2. The one survivor of
51
51
  // the old catch-all fallback is the literal `install` first arg — bare `goblin` mapped to the
52
52
  // installer through npm's bin default, and a typo (`goblin inti`) silently installed into
53
- // whatever directory the shell sat in. A bare subcommand-less `goblin install ...` keeps the
53
+ // whatever directory the shell sat in. A bare subcommand-less `gob install ...` keeps the
54
54
  // installer; everything else stops here and names the word it did not know.
55
55
  function usage() {
56
56
  process.stderr.write(
57
57
  [
58
- "goblin <command>",
58
+ "gob <command>",
59
59
  "",
60
- " goblin init start here — the guided first step (detect, class, emit, first verify)",
61
- " goblin verify run the rule matrix against the current repo",
62
- " goblin bans run the ban list (per-pattern red lines over the source tree)",
63
- " goblin audit check recorded dependency claims against live advisory feeds",
64
- " goblin upgrade migrate a repo to the shared global engine at ~/.goblin/engine",
65
- " goblin doctor one detection/drift run across the agent platforms",
66
- " goblin emit write the skills + context block for one platform",
67
- " goblin uninstall --target . remove exactly what an install wrote (preimages)",
60
+ " gob init start here — the guided first step (detect, class, emit, first verify)",
61
+ " gob verify run the rule matrix against the current repo",
62
+ " gob bans run the ban list (per-pattern red lines over the source tree)",
63
+ " gob audit check recorded dependency claims against live advisory feeds",
64
+ " gob upgrade migrate a repo to the shared global engine at ~/.goblin/engine",
65
+ " gob doctor one detection/drift run across the agent platforms",
66
+ " gob emit write the skills + context block for one platform",
67
+ " gob uninstall --target . remove exactly what an install wrote (preimages)",
68
68
  "",
69
- "start here: goblin init",
69
+ "start here: gob init",
70
70
  "uninstall: npm uninstall -g @techgoblin/gobstack",
71
71
  "",
72
72
  ].join("\n"));
@@ -77,7 +77,7 @@ if (cmd === undefined || cmd.startsWith("-")) {
77
77
  process.exit(2);
78
78
  }
79
79
  if (!SCRIPT[cmd] && cmd !== "install" && cmd !== "uninstall") {
80
- process.stderr.write(`goblin: unrecognized command: ${cmd}\n\n`);
80
+ process.stderr.write(`gob: unrecognized command: ${cmd}\n\n`);
81
81
  usage();
82
82
  process.exit(2);
83
83
  }
@@ -87,7 +87,7 @@ let extra = [];
87
87
  if (cmd === "install") {
88
88
  target = "goblin-install"; // the one legacy fallback, kept verbatim
89
89
  } else if (cmd === "uninstall") {
90
- // `goblin uninstall --target <dir>` routes into the installer's uninstall job — the shape
90
+ // `gob uninstall --target <dir>` routes into the installer's uninstall job — the shape
91
91
  // docs/GUIDE.md and README already promise. `--uninstall` is appended FIRST so the user's
92
92
  // own `--target <dir>` and options still parse, and a stray literal `--uninstall` cannot
93
93
  // appear twice.
package/docs/GUIDE.md CHANGED
@@ -31,7 +31,8 @@ design on day one.
31
31
 
32
32
  ## 1. What this actually is, in plain language
33
33
 
34
- goblin-stack (published as the npm package **`@techgoblin/gobstack`**, product name **gobstack**)
34
+ gobstack (published on npm as **`@techgoblin/gobstack`**) — this guide, the README and the CLI
35
+ all call it **gobstack**
35
36
  is **a folder of files you install into a project** from npm. Once
36
37
  installed, three things change:
37
38
 
@@ -53,7 +54,7 @@ deliberately, and §8 and §11 say why.
53
54
  > **A rule that cannot fail is worse than no rule**, because it takes credit for verification it
54
55
  > does not perform.
55
56
 
56
- Everything else in goblin-stack follows from that sentence. If you remember one thing from this
57
+ Everything else in gobstack follows from that sentence. If you remember one thing from this
57
58
  guide, remember that one — it is also the standard the harness holds itself to, and the reason it
58
59
  ships a file of things it *cannot* check (`docs/LIMITS.md`).
59
60
 
@@ -87,7 +88,7 @@ one way this guide installs it.
87
88
  **Do not install into a real project yet.** You want to see what it does before it touches
88
89
  something you care about.
89
90
 
90
- The guided path is `goblin init` — one screen per question (class, branch/email, first
91
+ The guided path is `gob init` — one screen per question (class, branch/email, first
91
92
  gate, which platforms to emit), every question also answerable by flag, `--dry-run` to
92
93
  see the plan first:
93
94
 
@@ -96,12 +97,12 @@ see the plan first:
96
97
  git config user.email "you@example.com"
97
98
  git config user.name "you"
98
99
 
99
- goblin init --target . --class app --branch main --email "you@example.com" \
100
+ gob init --target . --class app --branch main --email "you@example.com" \
100
101
  --gate "bash tests/run-tests.sh" --yes
101
102
 
102
103
  or the plain installer this wizard drives, if you prefer the one-shot shape:
103
104
 
104
- goblin install --target . --class A
105
+ gob install --target . --class A
105
106
 
106
107
  Expected output (this is a real transcript, trimmed):
107
108
 
@@ -134,7 +135,7 @@ branch** (unless you want to).
134
135
  ## 4. Step 2 — Commit, then verify (the moment it earns its keep)
135
136
 
136
137
  cd /tmp/gs-try
137
- git add -A && git commit -m "chore: install goblin-stack"
138
+ git add -A && git commit -m "chore: install gobstack"
138
139
  .goblin/bin/goblin-verify
139
140
 
140
141
  You will see one line per rule. The shape:
@@ -219,7 +220,7 @@ without you remembering to. And the gate numbers are recorded with a date, so a
219
220
  ### The `practice:` key — the part that makes it yours
220
221
 
221
222
  If you already have a house standard — a `CONTRIBUTING.md`, a `PROJECT-PRACTICE.md`, anything
222
- written down — point `practice:` at it. goblin-stack does **not** copy its text. It records a
223
+ written down — point `practice:` at it. gobstack does **not** copy its text. It records a
223
224
  **hash** of the file and re-checks that hash on every verify.
224
225
 
225
226
  That buys you one specific, valuable thing: **if someone edits your standard, every project that
@@ -228,7 +229,7 @@ repos follow an old version.
228
229
 
229
230
  When *you* legitimately edit your own standard:
230
231
 
231
- goblin install --target . --re-pin
232
+ gob install --target . --re-pin
232
233
 
233
234
  It re-records the hash and prints the old and new value. Nothing re-pins automatically — an
234
235
  edited standard is never a silent no-op.
@@ -329,7 +330,7 @@ own the same way, once that gate is real: declare it in `.goblin/goblin.yaml` an
329
330
  can see.
330
331
 
331
332
  A check that is green on **both** the broken and the fixed tree proves nothing — it would have been
332
- green anyway. goblin-stack calls this the **REPLAY** rule, and it is the single practice that has
333
+ green anyway. gobstack calls this the **REPLAY** rule, and it is the single practice that has
333
334
  caught every real regression in this repository's own development history.
334
335
 
335
336
  ---
@@ -424,7 +425,7 @@ Two readings that are easy to get wrong:
424
425
  | `refused to overwrite: HANDOFF.md`, exit 1 | your repo already had a HANDOFF | **do not `--force`** — reconcile it (below) |
425
426
  | `PT-02 declared main, actual master` | branch mismatch | set `branch:` in the config |
426
427
  | `IN-02 ... practice EDITED` | someone changed the pinned standard | re-pin deliberately: `--re-pin` |
427
- | `goblin install: unknown subcommand` (exit 2) | you ran a bare `goblin install` without the npm package installed | install the npm package first: `npm i -g @techgoblin/gobstack`, then `goblin install` |
428
+ | `gob install: unknown subcommand` (exit 2) | you ran a bare `gob install` without the npm package installed | install the npm package first: `npm i -g @techgoblin/gobstack`, then `gob install` |
428
429
  | `IN-03` fails, "manifest is broken" | a row has a broken check column | fix the row; this is a source defect, not yours |
429
430
  | a `FAIL` you believe is wrong | the check may be weak, or your belief may be | run `--only <id>` and read the command it prints |
430
431
 
@@ -442,12 +443,12 @@ Declared but unusable (relative path, missing directory, no manifest inside) is
442
443
  with no fallback** — a repo is never judged by an engine it did not declare. A repo whose record
443
444
  says `mode=global` keeps hashing whatever files it still holds; the engine's own identity prints in
444
445
  every run's footer (`engine: mode=… cli_sha256=… enforcement_tsv_sha256=…`). The same commands are
445
- available outside any repo through the npm CLI: `goblin verify` / `goblin bans` / `goblin audit` /
446
- `goblin doctor` / `goblin emit` / `goblin upgrade` / `goblin --version`.
446
+ available outside any repo through the npm CLI: `gob verify` / `gob bans` / `gob audit` /
447
+ `gob doctor` / `gob emit` / `gob upgrade` / `gob --version`.
447
448
 
448
449
  **Migrating a repo to the global engine (W3):**
449
450
 
450
- goblin upgrade # 8 steps, two commits, one report
451
+ gob upgrade # 8 steps, two commits, one report
451
452
 
452
453
  It refuses on a dirty tree, a detached HEAD, a red repo, or a global engine holding different
453
454
  bytes — each refusal names the fix. What it does: verifies every recorded hash, lands the engine
@@ -461,7 +462,7 @@ again. Nothing is deleted before the engine is safely landed and the tree is gre
461
462
  git revert <commit-A-sha> <commit-B-sha>
462
463
 
463
464
  reverses byte-for-byte: the vendored payload returns, the record drops its `engine:` block, and
464
- `goblin verify` is the 43-green it was before. A second `goblin upgrade` on a migrated repo is a
465
+ `gob verify` is the 43-green it was before. A second `gob upgrade` on a migrated repo is a
465
466
  no-op; `goblin-install` onto one refuses with the revert remedy (re-installing would re-shadow the
466
467
  engine and silently de-migrate the record).
467
468
 
@@ -474,7 +475,7 @@ engine and silently de-migrate the record).
474
475
  | `goblin` (npm CLI) | propagates the subcommand's codes verbatim — `verify`/`bans`/`audit`/`--version`; `install`/`uninstall`/`re-pin`/`upgrade` route into `goblin-install` (`upgrade` migrates to the global engine: `0` ok · `1` refusal · `2` bad input); `doctor`/`emit` carry the same contract: `doctor` exits `0` every probed platform DETECTED and clean · `1` any DRIFT · `2` nothing to probe, and `emit` exits `0` ok or no-op · `1` refusal (with the path and the fix) · `2` bad input or unknown platform |
475
476
  | platforms (W4b) | `emit`/`doctor` cover seven: `claude`, `hermes`, `copilot`, `cursor`, `opencode`, `codex`, `gemini` — each detected via its own anchor (`~/.claude`, `~/.hermes`, `~/.copilot`, `~/.cursor`, `~/.config/opencode`, `~/.codex`, `~/.gemini`); codex and gemini carry `partial` command-blocking (see LIMITS #47) |
476
477
 
477
- `3` is the one to notice: it means goblin-stack's own rule table is malformed, not your project.
478
+ `3` is the one to notice: it means gobstack's own rule table is malformed, not your project.
478
479
 
479
480
  ---
480
481
 
@@ -482,10 +483,10 @@ engine and silently de-migrate the record).
482
483
 
483
484
  ### Commands
484
485
 
485
- goblin install --target <dir> --class A|B|C|D|E|F [options]
486
- goblin install --target <dir> --uninstall
487
- goblin install --target <dir> --re-pin
488
- goblin install --target <dir> --upgrade
486
+ gob install --target <dir> --class A|B|C|D|E|F [options]
487
+ gob install --target <dir> --uninstall
488
+ gob install --target <dir> --re-pin
489
+ gob install --target <dir> --upgrade
489
490
 
490
491
  .goblin/bin/goblin-verify [--only <id[,id...]>] [--json] [--list]
491
492
  .goblin/bin/goblin-audit # the only network step
@@ -505,7 +506,7 @@ Named procedures, installed as project-local skills. Each has a measurable verif
505
506
  | P5 | `goblin-tdd-repro` | a defect where a regression test is cheap |
506
507
  | P6 | `goblin-verify-author` | a project has no live check lane, or its gates drift |
507
508
  | P7 | `goblin-pr-gate` | anything that should be reviewed before landing |
508
- | P8 | `goblin-bootstrap` | adopting goblin-stack, or starting a project |
509
+ | P8 | `goblin-bootstrap` | adopting gobstack, or starting a project |
509
510
  | P9 | `goblin-handoff` | ending a session, or picking up another's |
510
511
  | P10 | `goblin-overnight` | an unattended run over a predicate |
511
512
  | P11 | `goblin-sweep` | the same change across many projects |
@@ -578,10 +579,10 @@ with *"prove it was broken first"* — it is the one practice that survives cont
578
579
  # 1. try it somewhere disposable
579
580
  mkdir -p /tmp/gs-try && cd /tmp/gs-try
580
581
  git init -b main
581
- goblin install --target . --class A # expect: created 50
582
+ gob install --target . --class A # expect: created 50
582
583
 
583
584
  # 2. commit and check
584
- git add -A && git commit -m "chore: install goblin-stack"
585
+ git add -A && git commit -m "chore: install gobstack"
585
586
  .goblin/bin/goblin-verify # expect: mostly PASS, some SKIP
586
587
 
587
588
  # 3. make it yours
@@ -599,12 +600,12 @@ with *"prove it was broken first"* — it is the one practice that survives cont
599
600
 
600
601
  # 5. do it for real, in a repo you care about
601
602
  cd ~/projects/your-project
602
- goblin install --target . --class A
603
- git add -A && git commit -m "chore: adopt goblin-stack"
603
+ gob install --target . --class A
604
+ git add -A && git commit -m "chore: adopt gobstack"
604
605
  .goblin/bin/goblin-verify
605
606
  $EDITOR HANDOFF.md # state / gates (dated!) / next / NOT verified
606
607
 
607
608
  ---
608
609
 
609
- *This guide is part of goblin-stack. If you find a step that does not work as written, that is a
610
+ *This guide is part of gobstack. If you find a step that does not work as written, that is a
610
611
  defect in the guide — report it the same way you would report one in the code.*
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@techgoblin/gobstack",
3
- "version": "0.4.4-beta.3",
3
+ "version": "0.4.4-beta.6",
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",