You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* feat(config): add plan_tune_hooks setting (prompt|yes|no)
Registers a new gstack-config key controlling whether ./setup installs the
plan-tune Claude Code hooks. Default "prompt". Documented in the config
header and surfaced in `gstack-config defaults` / `list`.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(setup): make plan-tune hook install non-interactive-safe
The plan-tune consent prompt used a blocking `read -r` with no timeout. Under
a forwarded/automated TTY (conductor workspace setup, CI with a pty) it hung
setup forever.
Move the decision into flags + env + saved config with a smart default:
--plan-tune-hooks / --no-plan-tune-hooks / --plan-tune-hooks=yes|no|prompt
> GSTACK_PLAN_TUNE_HOOKS env > plan_tune_hooks config > prompt-on-real-TTY.
Explicit yes/no act non-interactively. The remaining interactive branch is
gated on a real (non-quiet) TTY and uses a time-bounded `read -t 10 </dev/tty`
that defaults to skip, so it can never hang. A timeout no longer persists a
decline marker, so a later hands-on run can still offer the install.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(dev-setup): run setup non-interactively in dev/workspace mode
Conductor runs bin/dev-setup under a forwarded pty, so any setup prompt
(skill-prefix, plan-tune consent) would hang the workspace. Detach stdin
(`setup </dev/null`) so every prompt takes its smart non-interactive default:
flat skill names, skip the global plan-tune hook install without writing a
decline marker. Saved prefix/config preferences are still honored, and a dev
workspace no longer silently mutates ~/.claude/settings.json.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* test(setup): guard plan-tune hooks stay non-interactive
Static + binary-level regression test (free, <1s): asserts the flags are
wired, the plan-tune read is time-bounded (no bare blocking read), explicit
yes/no decisions short-circuit before the prompt, and gstack-config knows the
plan_tune_hooks key.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(setup,config): harden plan-tune decision against bad input
Review follow-ups to the non-interactive plan-tune work:
- setup now lowercases + whitespace-strips the resolved decision before the
case match, so an explicit opt-in via flag/env ("YES", "Yes", " yes") is
honored instead of silently falling through to "prompt"/skip. Also accepts
on/off and 1/0.
- gstack-config rejects out-of-domain plan_tune_hooks values (anything but
prompt|yes|no) with a warning + fallback to prompt, matching the existing
value-whitelist pattern for explain_level / artifacts_sync_mode.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(dev-setup): never mutate global hooks during workspace setup
Closing stdin alone only suppresses the prompt branch; a saved
`plan_tune_hooks: yes` or exported GSTACK_PLAN_TUNE_HOOKS=yes would still
resolve to "install" and rewrite the user's global ~/.claude/settings.json to
point at THIS ephemeral worktree — which breaks once the workspace is deleted.
Pass --plan-tune-hooks=prompt (highest precedence) so dev-setup pins resolution
to prompt-mode; with stdin closed that is a guaranteed no-op skip (no install,
no decline marker). To install the hooks, run ./setup --plan-tune-hooks directly.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* test(setup): isolate config tests from host + cover new guards
- Point gstack-config tests at a temp GSTACK_HOME so `get plan_tune_hooks`
reads the built-in default, not whatever the host machine has in
~/.gstack/config.yaml (the prior test was non-deterministic).
- Add behavioral coverage: yes/no/prompt round-trip, out-of-domain rejection.
- Add a normalization guard (decision input is lowercased/trimmed) and a
dev-setup guard (runs setup with --plan-tune-hooks=prompt + stdin detached).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* test: rebaseline parity-suite v1.44.1 -> v1.53.0.0
The frozen v1.44.1 anchor went stale: five planning skills (plan-ceo-review,
plan-eng-review, plan-design-review, investigate, office-hours) crept past the
1.05x ceiling via legitimate v1.49-v1.53 growth (brain-aware planning + the
v1.53 redaction guard), so `bun test` was red on a clean checkout of main.
Capture a fresh baseline at HEAD (bun run scripts/capture-baseline.ts --tag
v1.53.0.0) and re-point the test at it. The per-skill 1.05 ratio is kept, so
future bloat is still caught; only the anchor moved. Mirrors the earlier
skill-size-budget rebase (v1.44.1 -> v1.47.0.0). Historical v1.44.1 / v1.46.0.0
/ v1.47.0.0 baselines are retained for the v1->v2 audit trail. The captured
skill bytes equal origin/main exactly (this branch left every SKILL.md
untouched). Clears the pre-existing failures noted in the v1.53.0.0 CHANGELOG.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* test(plan-tune): de-flake "derive pushes scope_appetite up"
The test was ~25-50% flaky (worse on main). gstack-question-log fires a
fire-and-forget background `--derive` after every write; the 5 rapid log writes
spawned 5 racing background derives that collided with the test's explicit
--derive — a late one that only saw 3 entries could clobber
developer-profile.json after the explicit one wrote sample_size=5.
Set GSTACK_QUESTION_LOG_NO_DERIVE=1 (the flag the binary documents for exactly
this case) so the writes don't spawn background derives. The explicit --derive
still runs, so real derive behavior is still asserted. 20/20 green after.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* chore: bump version and changelog (v1.53.1.0)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* docs: document non-interactive dev-setup + plan-tune hook flags (v1.53.1.0)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: CHANGELOG.md
+27Lines changed: 27 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,5 +1,32 @@
1
1
# Changelog
2
2
3
+
## [1.53.1.0] - 2026-05-30
4
+
5
+
## **Workspace and scripted setup never hang on a hidden prompt again. Installing the plan-tune hooks is now flag-driven with safe defaults.**
6
+
7
+
`./setup` asked "Install both hooks now? [y/N]" with a blocking read. Run under a Conductor workspace or any forwarded terminal, that prompt had nobody to answer it, so setup hung forever. Now the decision comes from a flag, an env var, or saved config, and when nobody is there to answer it takes a safe default instead of waiting. A real terminal still gets the prompt, but it is time-bounded (auto-skips after 10s) so it can never stall a pipeline.
8
+
9
+
### What this means for you
10
+
11
+
- Spinning up a new workspace just works. `bin/dev-setup` runs fully non-interactively and never rewrites your global Claude settings behind your back.
12
+
- Want the plan-tune hooks installed without a prompt? `./setup --plan-tune-hooks` (or `GSTACK_PLAN_TUNE_HOOKS=yes`, or `gstack-config set plan_tune_hooks yes`). Don't want them? `--no-plan-tune-hooks`. Leave it unset and a real terminal still asks once, then remembers.
13
+
14
+
### Added
15
+
16
+
- `--plan-tune-hooks` / `--no-plan-tune-hooks` / `--plan-tune-hooks=yes|no|prompt` flags on `./setup`, plus the `GSTACK_PLAN_TUNE_HOOKS` env var and a `plan_tune_hooks` config key (default `prompt`). Precedence: flag > env > saved config > prompt on a real terminal.
17
+
18
+
### Fixed
19
+
20
+
- `./setup` no longer hangs in non-interactive or forwarded-TTY contexts (Conductor workspaces, CI). The plan-tune consent prompt is time-bounded and defaults to skip.
21
+
- `bin/dev-setup` runs setup non-interactively and can no longer silently rewrite your global `~/.claude/settings.json` to point at an ephemeral workspace path that breaks when the workspace is deleted.
22
+
- Opt-in values like `YES`, `Yes`, or ` yes` are honored instead of being silently downgraded to skip, and `gstack-config` now rejects out-of-domain `plan_tune_hooks` values.
23
+
24
+
### For contributors
25
+
26
+
- New regression suite `test/setup-plan-tune-hooks-noninteractive.test.ts` (flag wiring, no-blocking-read guard, decision normalization, config round-trip + domain rejection, dev-setup pin) with host-config isolation via a temp `GSTACK_HOME`.
27
+
- Rebaselined `test/parity-suite.test.ts` from the stale v1.44.1 anchor to v1.53.0.0. The 1.05 per-skill ratio is kept (only the anchor moved), absorbing legitimate v1.49–v1.53 planning-skill growth and clearing the 5 pre-existing parity failures noted in the v1.53.0.0 entry. Historical baselines retained for the v1→v2 audit trail.
28
+
- De-flaked `test/plan-tune.test.ts` "derive pushes scope_appetite up" (was ~25–50% flaky, worse on main): it now sets `GSTACK_QUESTION_LOG_NO_DERIVE=1` so gstack-question-log's fire-and-forget background `--derive` can't race the test's explicit one.
29
+
3
30
## [1.53.0.0] - 2026-05-29
4
31
5
32
## **Secrets, PII, and legal landmines get caught before they reach a public sink. One redaction engine now guards /spec, /ship, /cso, and the /document-* skills.**
Copy file name to clipboardExpand all lines: CONTRIBUTING.md
+3-1Lines changed: 3 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -326,11 +326,13 @@ If you're using [Conductor](https://conductor.build) to run multiple Claude Code
326
326
327
327
| Hook | Script | What it does |
328
328
|------|--------|-------------|
329
-
|`setup`|`bin/dev-setup`| Copies `.env` from main worktree, installs deps, symlinks skills |
329
+
|`setup`|`bin/dev-setup`| Copies `.env` from main worktree, installs deps, symlinks skills, runs `./setup` non-interactively|
330
330
|`archive`|`bin/dev-teardown`| Removes skill symlinks, cleans up `.claude/` directory |
331
331
332
332
When Conductor creates a new workspace, `bin/dev-setup` runs automatically. It detects the main worktree (via `git worktree list`), copies your `.env` so API keys carry over, and sets up dev mode — no manual steps needed.
333
333
334
+
`bin/dev-setup` runs `./setup` fully non-interactively (it passes `--plan-tune-hooks=prompt` and closes stdin), so a forwarded Conductor TTY can never hang on a hidden setup prompt. It also never installs the plan-tune Claude Code hooks, which means a throwaway workspace can't rewrite your global `~/.claude/settings.json` to point at an ephemeral worktree path. To install the plan-tune hooks deliberately, run `./setup --plan-tune-hooks` outside dev-setup (or `gstack-config set plan_tune_hooks yes`).
335
+
334
336
**First-time setup:** Put your `ANTHROPIC_API_KEY` in `.env` in the main repo (see `.env.example`). Every Conductor workspace inherits it automatically.
335
337
336
338
**`GSTACK_*` env prefix (Conductor-injected keys).** Conductor explicitly strips `ANTHROPIC_API_KEY` and `OPENAI_API_KEY` from every workspace's process env. The `.env` copy path doesn't restore them either — the strip happens after env inheritance. Users who want paid evals, `/sync-gbrain` embeddings, or `claude-agent-sdk` calls to work in a Conductor workspace must set `GSTACK_ANTHROPIC_API_KEY` and `GSTACK_OPENAI_API_KEY` in Conductor's workspace env config; Conductor passes those through untouched. On the gstack side, TS entry points import `lib/conductor-env-shim.ts` as a side effect, which promotes `GSTACK_FOO_API_KEY` to `FOO_API_KEY` when the canonical name is empty. If you add a new TS entry point that hits a paid API, add `import "../lib/conductor-env-shim";` to the top of the file. Today the shim is imported from `bin/gstack-gbrain-sync.ts`, `bin/gstack-model-benchmark`, `scripts/preflight-agent-sdk.ts`, and `test/helpers/e2e-helpers.ts`.
0 commit comments