diff --git a/TODOS.md b/TODOS.md index 7be847dde..f61b765ed 100644 --- a/TODOS.md +++ b/TODOS.md @@ -2668,6 +2668,18 @@ Shipped as v0.5.0 on main. Includes `/plan-design-review` (report-only design au ## Document-Release +### Spawned-session auto-choices are invisible to /plan-tune + +**What:** Capture auto-chosen decisions from spawned sessions (OPENCLAW_SESSION or GSTACK_SESSION_KIND=spawned) into `gstack-question-log` so `/plan-tune` learning sees them. + +**Why:** In spawned sessions the model never calls AskUserQuestion (it auto-chooses the recommended option per the spawned-session block), so the PostToolUse capture hook never fires and no prose brief is ever logged — every gate decision made inside a /ship Step 18 document-release subagent is missing from the question-tuning corpus. + +**Context:** #2733 made spawned sessions reachable from Claude Code subagents (every Conductor-hosted /ship now produces one). The subagent reports auto-chosen decisions in the JSON contract's `decisions` array (user-visible in the ship console), but nothing writes them to `~/.gstack/` question analytics. Start from the spawned-session instruction block in `bin/gstack-skill-start` — add a "log each auto-chosen decision with bin/gstack-question-log" sentence and a `source` value distinguishing auto-chosen from human-answered so tuning never trains on machine picks as if a human made them. + +**Effort:** S +**Priority:** P3 +**Depends on:** #2733 fix (GSTACK_SESSION_KIND=spawned marker) landing. + ### Auto-invoke /document-release from /ship — SHIPPED Shipped in v0.8.4; redesigned twice since. Current design (v0.18.2.0+, carved in diff --git a/docs/OPENCLAW.md b/docs/OPENCLAW.md index 7df9895a2..9aaf64700 100644 --- a/docs/OPENCLAW.md +++ b/docs/OPENCLAW.md @@ -116,12 +116,42 @@ No gstack infrastructure (no browse, no telemetry, no preamble). When Claude Code runs inside a session spawned by OpenClaw, the `OPENCLAW_SESSION` environment variable should be set. gstack detects this and adjusts: -- Skips interactive prompts (auto-chooses recommended options) -- Skips upgrade checks and telemetry prompts +- Skips interactive prompts (auto-chooses recommended options; destructive or + irreversible options are never auto-chosen — the conservative choice wins + and gets recorded in the completion report) +- Suppresses interactive-onboarding instruction blocks at emission (upgrade + checks, telemetry prompts, feature discovery, routing injection, tips), so + one-time prompts survive intact for the next human session +- Suppresses the Conductor prose signal (`CONDUCTOR_SESSION: true`) — a + spawned session inside a Conductor workspace auto-chooses instead of + rendering prose to nobody - Focuses on task completion and prose reporting Set the env var in sessions_spawn: `env: { OPENCLAW_SESSION: "1" }` +### Explicit override: GSTACK_SESSION_KIND + +`GSTACK_SESSION_KIND=spawned` is the explicit per-command marker for the same +classification, outranking every ambient env marker (including +`OPENCLAW_SESSION` and `GSTACK_HEADLESS`). It exists because Claude Code +subagents inherit the parent session's env byte-for-byte (#2733) — a +dispatching skill marks its subagent by prefixing the preamble invocation on +the same command line: + +```bash +GSTACK_SESSION_KIND=spawned "$_SS" --skill "document-release" ... +``` + +gstack itself uses this: `/ship` Step 18 dispatches the `/document-release` +subagent with this prefix so its interactive gates auto-choose instead of +prose-stopping. Deliberately narrow: only `spawned` is honored — `headless` +already has `GSTACK_HEADLESS`, and letting an env var force `interactive` +over CI markers would be a misclassification footgun. Empty or other values +are reserved and ignored (fall through to ambient detection). Note that hook +processes inherit the harness env, so a per-command prefix never reaches +PreToolUse/PostToolUse hooks — the hook texts carry a spawned escape sentence +for that topology (`hosts/claude/hooks/spawned-directive.ts`). + ## Installation For OpenClaw users: tell your OpenClaw agent "install gstack for openclaw." diff --git a/test/helpers/touchfiles-data.ts b/test/helpers/touchfiles-data.ts index 2a87ed8e5..c9cc674e1 100644 --- a/test/helpers/touchfiles-data.ts +++ b/test/helpers/touchfiles-data.ts @@ -119,12 +119,12 @@ export const E2E_TOUCHFILES: Record = { // written a never-ask preference, AUQ should still auto-decide rather than // surfacing the question. Touches the question-tuning + preference // infrastructure plus the resolvers that own the AUTO_DECIDE preamble. - 'auto-decide-preserved': ['bin/gstack-skill-start', 'bin/gstack-skill-end', 'scripts/resolvers/question-tuning.ts', 'scripts/resolvers/preamble/generate-ask-user-format.ts', 'scripts/resolvers/preamble/generate-preamble-bash.ts', 'scripts/resolvers/preamble/generate-completion-status.ts', 'plan-ceo-review/**', 'bin/gstack-question-preference', 'bin/gstack-config', 'bin/gstack-slug', 'hosts/claude/hooks/question-preference-hook.ts', 'lib/is-conductor.ts', 'test/helpers/claude-pty-runner.ts', 'test/skill-e2e-auto-decide-preserved.test.ts'], + 'auto-decide-preserved': ['bin/gstack-skill-start', 'bin/gstack-skill-end', 'bin/gstack-session-kind', 'scripts/resolvers/question-tuning.ts', 'scripts/resolvers/preamble/generate-ask-user-format.ts', 'scripts/resolvers/preamble/generate-preamble-bash.ts', 'scripts/resolvers/preamble/generate-completion-status.ts', 'plan-ceo-review/**', 'bin/gstack-question-preference', 'bin/gstack-config', 'bin/gstack-slug', 'hosts/claude/hooks/question-preference-hook.ts', 'hosts/claude/hooks/spawned-directive.ts', 'lib/is-conductor.ts', 'test/helpers/claude-pty-runner.ts', 'test/skill-e2e-auto-decide-preserved.test.ts'], // Conductor → prose decision brief (Conductor signal makes prose the default; // the PreToolUse hook denies the flaky tool). Touches the resolver that owns // the Conductor rule, the preamble signal, the hook, and the detection helper. - 'conductor-prose': ['bin/gstack-skill-start', 'bin/gstack-skill-end', 'scripts/resolvers/preamble/generate-ask-user-format.ts', 'scripts/resolvers/preamble/generate-preamble-bash.ts', 'scripts/resolvers/preamble.ts', 'plan-eng-review/**', 'hosts/claude/hooks/question-preference-hook.ts', 'lib/is-conductor.ts', 'test/helpers/claude-pty-runner.ts', 'test/skill-e2e-conductor-prose.test.ts'], + 'conductor-prose': ['bin/gstack-skill-start', 'bin/gstack-skill-end', 'bin/gstack-session-kind', 'scripts/resolvers/preamble/generate-ask-user-format.ts', 'scripts/resolvers/preamble/generate-preamble-bash.ts', 'scripts/resolvers/preamble.ts', 'plan-eng-review/**', 'hosts/claude/hooks/question-preference-hook.ts', 'hosts/claude/hooks/spawned-directive.ts', 'lib/is-conductor.ts', 'test/helpers/claude-pty-runner.ts', 'test/skill-e2e-conductor-prose.test.ts'], // Real-PTY E2E batch (#6 new tests on the harness). // Each one tests behavior the SDK harness can't observe (rendered TTY,