From 9c36fbdd22d6def084626e49fb7aadc9b61f35fe Mon Sep 17 00:00:00 2001 From: katlun-lgtm <264247399+katlun-lgtm@users.noreply.github.com> Date: Tue, 9 Jun 2026 13:47:31 -0400 Subject: [PATCH 1/2] fix: tool rewrites catch all 'Agent tool' phrasings across agent-runtime hosts The Agent->host-tool rewrite only keyed on the exact literal 'use the Agent tool', which never appears in generated content. Real phrasings ('using the Agent tool', 'via the Agent tool', 'Use the Agent tool', and bare 'Agent tool') slipped through, so the host's subagent tool never rendered and the Claude-ism 'Agent tool' leaked into generated docs (16x in hermes alone, delegate_task 0x). Add article-first + bare-sweep rules to hermes (delegate_task), gbrain and openclaw (sessions_spawn), and factory. Factory uses the plain noun 'delegation' since its rewrites are prose, not tool names, which avoids echoing the surrounding 'subagent' wording; a possessive-first rule handles "Claude Code's Agent tool". Regenerated all four trees: 0 'Agent tool' leaks. Update the factory ship golden baseline to match. --- hosts/factory.ts | 6 ++++++ hosts/gbrain.ts | 4 ++++ hosts/hermes.ts | 5 +++++ hosts/openclaw.ts | 4 ++++ test/fixtures/golden/factory-ship-SKILL.md | 16 ++++++++-------- 5 files changed, 27 insertions(+), 8 deletions(-) diff --git a/hosts/factory.ts b/hosts/factory.ts index 08ac2f9a1..11cfd4e8d 100644 --- a/hosts/factory.ts +++ b/hosts/factory.ts @@ -41,6 +41,12 @@ const factory: HostConfig = { 'use the Agent tool': 'dispatch a subagent', 'use the Grep tool': 'search for', 'use the Glob tool': 'find files matching', + // Agent tool: catch every phrasing, not just 'use the Agent tool'. Factory uses the plain + // noun 'delegation' (reads clean mid-sentence without echoing the surrounding 'subagent' + // prose); possessive form first, then article form, then a bare sweep. + "Claude Code's Agent tool": 'delegation', + 'the Agent tool': 'delegation', + 'Agent tool': 'delegation', }, suppressedResolvers: ['GBRAIN_CONTEXT_LOAD', 'GBRAIN_SAVE_RESULTS'], diff --git a/hosts/gbrain.ts b/hosts/gbrain.ts index ae777f2f1..962437845 100644 --- a/hosts/gbrain.ts +++ b/hosts/gbrain.ts @@ -46,6 +46,10 @@ const gbrain: HostConfig = { 'the Read tool': 'the read tool', 'the Write tool': 'the write tool', 'the Edit tool': 'the edit tool', + // Agent tool: catch every phrasing (using/via/Use/bare), not just 'use the Agent tool'. + // Article form first (drops 'the'), then a bare sweep for the article-less forms. + 'the Agent tool': 'sessions_spawn', + 'Agent tool': 'sessions_spawn', }, // GBrain gets brain-aware resolvers. All other hosts suppress these. diff --git a/hosts/hermes.ts b/hosts/hermes.ts index 43598989d..505c01a73 100644 --- a/hosts/hermes.ts +++ b/hosts/hermes.ts @@ -41,6 +41,11 @@ const hermes: HostConfig = { 'the Read tool': 'the read_file tool', 'the Write tool': 'the patch tool', 'the Edit tool': 'the patch tool', + // Agent tool: catch every phrasing (using/via/Use/bare), not just 'use the Agent tool'. + // Article form first (drops 'the' -> no dangling article), then a bare sweep for the + // article-less forms ('via Agent tool', '(Agent tool', "Claude Code's Agent tool"). + 'the Agent tool': 'delegate_task', + 'Agent tool': 'delegate_task', }, suppressedResolvers: [ diff --git a/hosts/openclaw.ts b/hosts/openclaw.ts index f8268b5c7..9c9082617 100644 --- a/hosts/openclaw.ts +++ b/hosts/openclaw.ts @@ -44,6 +44,10 @@ const openclaw: HostConfig = { 'the Read tool': 'the read tool', 'the Write tool': 'the write tool', 'the Edit tool': 'the edit tool', + // Agent tool: catch every phrasing (using/via/Use/bare), not just 'use the Agent tool'. + // Article form first (drops 'the'), then a bare sweep for the article-less forms. + 'the Agent tool': 'sessions_spawn', + 'Agent tool': 'sessions_spawn', }, // Suppress Claude-specific preamble sections that don't apply to OpenClaw diff --git a/test/fixtures/golden/factory-ship-SKILL.md b/test/fixtures/golden/factory-ship-SKILL.md index 9a5e09b6a..f5345787a 100644 --- a/test/fixtures/golden/factory-ship-SKILL.md +++ b/test/fixtures/golden/factory-ship-SKILL.md @@ -1581,7 +1581,7 @@ If multiple suites need to run, run them sequentially (each needs a test lane). ## Step 7: Test Coverage Audit -**Dispatch this step as a subagent** using the Agent tool with `subagent_type: "general-purpose"`. The subagent runs the coverage audit in a fresh context window — the parent only sees the conclusion, not intermediate file reads. This is context-rot defense. +**Dispatch this step as a subagent** using delegation with `subagent_type: "general-purpose"`. The subagent runs the coverage audit in a fresh context window — the parent only sees the conclusion, not intermediate file reads. This is context-rot defense. **Subagent prompt:** Pass the following instructions to the subagent, with `` substituted with the base branch: @@ -1839,7 +1839,7 @@ Repo: {owner/repo} ## Step 8: Plan Completion Audit -**Dispatch this step as a subagent** using the Agent tool with `subagent_type: "general-purpose"`. The subagent reads the plan file and every referenced code file in its own fresh context. Parent gets only the conclusion. +**Dispatch this step as a subagent** using delegation with `subagent_type: "general-purpose"`. The subagent reads the plan file and every referenced code file in its own fresh context. Parent gets only the conclusion. **Subagent prompt:** Pass these instructions to the subagent: @@ -2272,8 +2272,8 @@ Note which specialists were selected, gated, and skipped. Print the selection: ### Dispatch specialists in parallel -For each selected specialist, launch an independent subagent via the Agent tool. -**Launch ALL selected specialists in a single message** (multiple Agent tool calls) +For each selected specialist, launch an independent subagent via delegation. +**Launch ALL selected specialists in a single message** (multiple delegation calls) so they run in parallel. Each subagent has fresh context — no prior review bias. **Each specialist subagent prompt:** @@ -2387,7 +2387,7 @@ Remember these stats — you will need them for the review-log entry in Step 5.8 **Activation:** Only if DIFF_LINES > 200 OR any specialist produced a CRITICAL finding. -If activated, dispatch one more subagent via the Agent tool (foreground, not background). +If activated, dispatch one more subagent via delegation (foreground, not background). The Red Team subagent receives: 1. The red-team checklist from `$GSTACK_ROOT/review/specialists/red-team.md` @@ -2477,7 +2477,7 @@ Save the review output — it goes into the PR body in Step 19. ## Step 10: Address Greptile review comments (if PR exists) -**Dispatch the fetch + classification as a subagent** using the Agent tool with `subagent_type: "general-purpose"`. The subagent pulls every Greptile comment, runs the escalation detection algorithm, and classifies each comment. Parent receives a structured list and handles user interaction + file edits. +**Dispatch the fetch + classification as a subagent** using delegation with `subagent_type: "general-purpose"`. The subagent pulls every Greptile comment, runs the escalation detection algorithm, and classifies each comment. Parent receives a structured list and handles user interaction + file edits. **Subagent prompt:** @@ -2550,7 +2550,7 @@ If `OLD_CFG` is `disabled`: skip Codex passes only. Claude adversarial subagent ### Claude adversarial subagent (always runs) -Dispatch via the Agent tool. The subagent has fresh context — no checklist bias from the structured review. This genuine independence catches things the primary reviewer is blind to. +Dispatch via delegation. The subagent has fresh context — no checklist bias from the structured review. This genuine independence catches things the primary reviewer is blind to. Subagent prompt: "Read the diff for this branch with `git diff origin/`. Think like an attacker and a chaos engineer. Your job is to find ways this code will fail in production. Look for: edge cases, race conditions, security holes, resource leaks, failure modes, silent data corruption, logic errors that produce wrong results silently, error handling that swallows failures, and trust boundary violations. Be adversarial. Be thorough. No compliments — just the problems. For each finding, classify as FIXABLE (you know how to fix it) or INVESTIGATE (needs human judgment)." @@ -3069,7 +3069,7 @@ git push -u origin ## Step 18: Documentation sync (via subagent, before PR creation) -**Dispatch /document-release as a subagent** using the Agent tool with `subagent_type: "general-purpose"`. The subagent gets a fresh context window — zero rot from the preceding 17 steps. It also runs the **full** `/document-release` workflow (with CHANGELOG clobber protection, doc exclusions, risky-change gates, named staging, race-safe PR body editing) rather than a weaker reimplementation. +**Dispatch /document-release as a subagent** using delegation with `subagent_type: "general-purpose"`. The subagent gets a fresh context window — zero rot from the preceding 17 steps. It also runs the **full** `/document-release` workflow (with CHANGELOG clobber protection, doc exclusions, risky-change gates, named staging, race-safe PR body editing) rather than a weaker reimplementation. **Sequencing:** This step runs AFTER Step 17 (Push) and BEFORE Step 19 (Create PR). The PR is created once from final HEAD with the `## Documentation` section baked into the initial body. No create-then-re-edit dance. From b4361480968d192aeb3d46f21413a8e67979a3b9 Mon Sep 17 00:00:00 2001 From: katlun-lgtm <264247399+katlun-lgtm@users.noreply.github.com> Date: Tue, 9 Jun 2026 14:11:06 -0400 Subject: [PATCH 2/2] test: golden regression fixtures for hermes/gbrain/openclaw ship skill Only claude/codex/factory had golden baselines, so a host-specific rewrite regression (such as the Agent-tool rewrite gap) on the agent-runtime hosts would go uncaught. Add ship-skill golden fixtures plus a parametrized test for the three regular ./skills/gstack-ship hosts, locking their tool/path rewrites (Bash->terminal/exec, Agent->delegate_task/sessions_spawn, .claude->.host, CLAUDE.md->AGENTS.md). --- test/fixtures/golden/gbrain-ship-SKILL.md | 2974 +++++++++++++++++++ test/fixtures/golden/hermes-ship-SKILL.md | 2969 ++++++++++++++++++ test/fixtures/golden/openclaw-ship-SKILL.md | 2919 ++++++++++++++++++ test/host-config.test.ts | 11 + 4 files changed, 8873 insertions(+) create mode 100644 test/fixtures/golden/gbrain-ship-SKILL.md create mode 100644 test/fixtures/golden/hermes-ship-SKILL.md create mode 100644 test/fixtures/golden/openclaw-ship-SKILL.md diff --git a/test/fixtures/golden/gbrain-ship-SKILL.md b/test/fixtures/golden/gbrain-ship-SKILL.md new file mode 100644 index 000000000..a93ba694e --- /dev/null +++ b/test/fixtures/golden/gbrain-ship-SKILL.md @@ -0,0 +1,2974 @@ +--- +name: ship +description: | + Ship workflow: detect + merge base branch, run tests, review diff, bump VERSION, + update CHANGELOG, commit, push, create PR. Use when asked to "ship", "deploy", + "push to main", "create a PR", "merge and push", or "get it deployed". + Proactively invoke this skill (do NOT push/PR directly) when the user says code + is ready, asks about deploying, wants to push code up, or asks to create a PR. (gstack) +triggers: + - ship it + - create a pr + - push to main + - deploy this +--- + + + +## Preamble (run first) + +```bash +_ROOT=$(git rev-parse --show-toplevel 2>/dev/null) +GSTACK_ROOT="$HOME/.gbrain/skills/gstack" +[ -n "$_ROOT" ] && [ -d "$_ROOT/.gbrain/skills/gstack" ] && GSTACK_ROOT="$_ROOT/.gbrain/skills/gstack" +GSTACK_BIN="$GSTACK_ROOT/bin" +GSTACK_BROWSE="$GSTACK_ROOT/browse/dist" +GSTACK_DESIGN="$GSTACK_ROOT/design/dist" +_UPD=$($GSTACK_BIN/gstack-update-check 2>/dev/null || .gbrain/skills/gstack/bin/gstack-update-check 2>/dev/null || true) +[ -n "$_UPD" ] && echo "$_UPD" || true +mkdir -p ~/.gstack/sessions +touch ~/.gstack/sessions/"$PPID" +_SESSIONS=$(find ~/.gstack/sessions -mmin -120 -type f 2>/dev/null | wc -l | tr -d ' ') +find ~/.gstack/sessions -mmin +120 -type f -exec rm {} + 2>/dev/null || true +_PROACTIVE=$($GSTACK_BIN/gstack-config get proactive 2>/dev/null || echo "true") +_PROACTIVE_PROMPTED=$([ -f ~/.gstack/.proactive-prompted ] && echo "yes" || echo "no") +_BRANCH=$(git branch --show-current 2>/dev/null || echo "unknown") +echo "BRANCH: $_BRANCH" +_SKILL_PREFIX=$($GSTACK_BIN/gstack-config get skill_prefix 2>/dev/null || echo "false") +echo "PROACTIVE: $_PROACTIVE" +echo "PROACTIVE_PROMPTED: $_PROACTIVE_PROMPTED" +echo "SKILL_PREFIX: $_SKILL_PREFIX" +source <($GSTACK_BIN/gstack-repo-mode 2>/dev/null) || true +REPO_MODE=${REPO_MODE:-unknown} +echo "REPO_MODE: $REPO_MODE" +_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no") +echo "LAKE_INTRO: $_LAKE_SEEN" +_TEL=$($GSTACK_BIN/gstack-config get telemetry 2>/dev/null || true) +_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no") +_TEL_START=$(date +%s) +_SESSION_ID="$$-$(date +%s)" +echo "TELEMETRY: ${_TEL:-off}" +echo "TEL_PROMPTED: $_TEL_PROMPTED" +# Writing style verbosity (V1: default = ELI10, terse = tighter V0 prose. +# Read on every skill run so terse mode takes effect without a restart.) +_EXPLAIN_LEVEL=$($GSTACK_BIN/gstack-config get explain_level 2>/dev/null || echo "default") +if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi +echo "EXPLAIN_LEVEL: $_EXPLAIN_LEVEL" +# Question tuning (see /plan-tune). Observational only in V1. +_QUESTION_TUNING=$($GSTACK_BIN/gstack-config get question_tuning 2>/dev/null || echo "false") +echo "QUESTION_TUNING: $_QUESTION_TUNING" +mkdir -p ~/.gstack/analytics +if [ "$_TEL" != "off" ]; then +echo '{"skill":"ship","ts":"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'","repo":"'$(basename "$(git rev-parse --show-toplevel 2>/dev/null)" 2>/dev/null || echo "unknown")'"}' >> ~/.gstack/analytics/skill-usage.jsonl 2>/dev/null || true +fi +# zsh-compatible: use find instead of glob to avoid NOMATCH error +for _PF in $(find ~/.gstack/analytics -maxdepth 1 -name '.pending-*' 2>/dev/null); do + if [ -f "$_PF" ]; then + if [ "$_TEL" != "off" ] && [ -x "$GSTACK_BIN/gstack-telemetry-log" ]; then + $GSTACK_BIN/gstack-telemetry-log --event-type skill_run --skill _pending_finalize --outcome unknown --session-id "$_SESSION_ID" 2>/dev/null || true + fi + rm -f "$_PF" 2>/dev/null || true + fi + break +done +# Learnings count +eval "$($GSTACK_BIN/gstack-slug 2>/dev/null)" 2>/dev/null || true +_LEARN_FILE="${GSTACK_HOME:-$HOME/.gstack}/projects/${SLUG:-unknown}/learnings.jsonl" +if [ -f "$_LEARN_FILE" ]; then + _LEARN_COUNT=$(wc -l < "$_LEARN_FILE" 2>/dev/null | tr -d ' ') + echo "LEARNINGS: $_LEARN_COUNT entries loaded" + if [ "$_LEARN_COUNT" -gt 5 ] 2>/dev/null; then + $GSTACK_BIN/gstack-learnings-search --limit 3 2>/dev/null || true + fi +else + echo "LEARNINGS: 0" +fi +# Session timeline: record skill start (local-only, never sent anywhere) +$GSTACK_BIN/gstack-timeline-log '{"skill":"ship","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & +# Check if AGENTS.md has routing rules +_HAS_ROUTING="no" +if [ -f AGENTS.md ] && grep -q "## Skill routing" AGENTS.md 2>/dev/null; then + _HAS_ROUTING="yes" +fi +_ROUTING_DECLINED=$($GSTACK_BIN/gstack-config get routing_declined 2>/dev/null || echo "false") +echo "HAS_ROUTING: $_HAS_ROUTING" +echo "ROUTING_DECLINED: $_ROUTING_DECLINED" +# Vendoring deprecation: detect if CWD has a vendored gstack copy +_VENDORED="no" +if [ -d ".gbrain/skills/gstack" ] && [ ! -L ".gbrain/skills/gstack" ]; then + if [ -f ".gbrain/skills/gstack/VERSION" ] || [ -d ".gbrain/skills/gstack/.git" ]; then + _VENDORED="yes" + fi +fi +echo "VENDORED_GSTACK: $_VENDORED" +echo "MODEL_OVERLAY: claude" +# Checkpoint mode (explicit = no auto-commit, continuous = WIP commits as you go) +_CHECKPOINT_MODE=$($GSTACK_BIN/gstack-config get checkpoint_mode 2>/dev/null || echo "explicit") +_CHECKPOINT_PUSH=$($GSTACK_BIN/gstack-config get checkpoint_push 2>/dev/null || echo "false") +echo "CHECKPOINT_MODE: $_CHECKPOINT_MODE" +echo "CHECKPOINT_PUSH: $_CHECKPOINT_PUSH" +# Detect spawned session (OpenClaw or other orchestrator) +[ -n "$OPENCLAW_SESSION" ] && echo "SPAWNED_SESSION: true" || true +# GBrain health check (gbrain/hermes host only) +if command -v gbrain &>/dev/null; then + _BRAIN_JSON=$(gbrain doctor --fast --json 2>/dev/null || echo '{}') + _BRAIN_SCORE=$(echo "$_BRAIN_JSON" | grep -o '"health_score":[0-9]*' | cut -d: -f2) + _BRAIN_FAILS=$(echo "$_BRAIN_JSON" | grep -o '"status":"fail"' | wc -l | tr -d ' ') + _BRAIN_WARNS=$(echo "$_BRAIN_JSON" | grep -o '"status":"warn"' | wc -l | tr -d ' ') + echo "BRAIN_HEALTH: ${_BRAIN_SCORE:-unknown} (${_BRAIN_FAILS:-0} failures, ${_BRAIN_WARNS:-0} warnings)" + if [ "${_BRAIN_SCORE:-100}" -lt 50 ] 2>/dev/null; then + echo "$_BRAIN_JSON" | grep -o '"name":"[^"]*","status":"[^"]*","message":"[^"]*"' || true + fi +fi +``` + +## Plan Mode Safe Operations + +In plan mode, these are always allowed (they inform the plan, don't modify source): +`$B` (browse), `$D` (design), `codex exec`/`codex review`, writes to `~/.gstack/`, +writes to the plan file, `open` for generated artifacts. + +## Skill Invocation During Plan Mode + +If the user invokes a skill in plan mode, that skill takes precedence over generic plan mode behavior. Treat it as executable instructions, not reference. Follow step +by step. AskUserQuestion calls satisfy plan mode's end-of-turn requirement. At a STOP +point, stop immediately. Do not continue the workflow past a STOP point and do not call ExitPlanMode there. Commands marked "PLAN +MODE EXCEPTION — ALWAYS RUN" execute. Other writes need to be already permitted +above or explicitly exception-marked. Call ExitPlanMode only after the skill +workflow completes — only then call ExitPlanMode (or if the user tells you to cancel the skill or leave plan mode). + +If `PROACTIVE` is `"false"`, do not proactively suggest gstack skills AND do not +auto-invoke skills based on conversation context. Only run skills the user explicitly +types (e.g., /qa, /ship). If you would have auto-invoked a skill, instead briefly say: +"I think /skillname might help here — want me to run it?" and wait for confirmation. +The user opted out of proactive behavior. + +If `SKILL_PREFIX` is `"true"`, the user has namespaced skill names. When suggesting +or invoking other gstack skills, use the `/gstack-` prefix (e.g., `/gstack-qa` instead +of `/qa`, `/gstack-ship` instead of `/ship`). Disk paths are unaffected — always use +`$GSTACK_ROOT/[skill-name]/SKILL.md` for reading skill files. + +If output shows `UPGRADE_AVAILABLE `: read `$GSTACK_ROOT/gstack-upgrade/SKILL.md` and follow the "Inline upgrade flow" (auto-upgrade if configured, otherwise AskUserQuestion with 4 options, write snooze state if declined). + +If output shows `JUST_UPGRADED ` AND `SPAWNED_SESSION` is NOT set: tell +the user "Running gstack v{to} (just updated!)" and then check for new features to +surface. For each per-feature marker below, if the marker file is missing AND the +feature is plausibly useful for this user, use AskUserQuestion to let them try it. +Fire once per feature per user, NOT once per upgrade. + +**In spawned sessions (`SPAWNED_SESSION` = "true"): SKIP feature discovery entirely.** +Just print "Running gstack v{to}" and continue. Orchestrators do not want interactive +prompts from sub-sessions. + +**Feature discovery markers and prompts** (one at a time, max one per session): + +1. `$GSTACK_ROOT/.feature-prompted-continuous-checkpoint` → + Prompt: "Continuous checkpoint auto-commits your work as you go with `WIP:` prefix + so you never lose progress to a crash. Local-only by default — doesn't push + anywhere unless you turn that on. Want to try it?" + Options: A) Enable continuous mode, B) Show me first (print the section from + the preamble Continuous Checkpoint Mode), C) Skip. + If A: run `$GSTACK_BIN/gstack-config set checkpoint_mode continuous`. + Always: `touch $GSTACK_ROOT/.feature-prompted-continuous-checkpoint` + +2. `$GSTACK_ROOT/.feature-prompted-model-overlay` → + Inform only (no prompt): "Model overlays are active. `MODEL_OVERLAY: {model}` + shown in the preamble output tells you which behavioral patch is applied. + Override with `--model` when regenerating skills (e.g., `bun run gen:skill-docs + --model gpt-5.4`). Default is claude." + Always: `touch $GSTACK_ROOT/.feature-prompted-model-overlay` + +After handling JUST_UPGRADED (prompts done or skipped), continue with the skill +workflow. + +If `WRITING_STYLE_PENDING` is `yes`: You're on the first skill run after upgrading +to gstack v1. Ask the user once about the new default writing style. Use AskUserQuestion: + +> v1 prompts = simpler. Technical terms get a one-sentence gloss on first use, +> questions are framed in outcome terms, sentences are shorter. +> +> Keep the new default, or prefer the older tighter prose? + +Options: +- A) Keep the new default (recommended — good writing helps everyone) +- B) Restore V0 prose — set `explain_level: terse` + +If A: leave `explain_level` unset (defaults to `default`). +If B: run `$GSTACK_BIN/gstack-config set explain_level terse`. + +Always run (regardless of choice): +```bash +rm -f ~/.gstack/.writing-style-prompt-pending +touch ~/.gstack/.writing-style-prompted +``` + +This only happens once. If `WRITING_STYLE_PENDING` is `no`, skip this entirely. + +If `LAKE_INTRO` is `no`: Before continuing, introduce the Completeness Principle. +Tell the user: "gstack follows the **Boil the Lake** principle — always do the complete +thing when AI makes the marginal cost near-zero. Read more: https://garryslist.org/posts/boil-the-ocean" +Then offer to open the essay in their default browser: + +```bash +open https://garryslist.org/posts/boil-the-ocean +touch ~/.gstack/.completeness-intro-seen +``` + +Only run `open` if the user says yes. Always run `touch` to mark as seen. This only happens once. + +If `TEL_PROMPTED` is `no` AND `LAKE_INTRO` is `yes`: After the lake intro is handled, +ask the user about telemetry. Use AskUserQuestion: + +> Help gstack get better! Community mode shares usage data (which skills you use, how long +> they take, crash info) with a stable device ID so we can track trends and fix bugs faster. +> No code, file paths, or repo names are ever sent. +> Change anytime with `gstack-config set telemetry off`. + +Options: +- A) Help gstack get better! (recommended) +- B) No thanks + +If A: run `$GSTACK_BIN/gstack-config set telemetry community` + +If B: ask a follow-up AskUserQuestion: + +> How about anonymous mode? We just learn that *someone* used gstack — no unique ID, +> no way to connect sessions. Just a counter that helps us know if anyone's out there. + +Options: +- A) Sure, anonymous is fine +- B) No thanks, fully off + +If B→A: run `$GSTACK_BIN/gstack-config set telemetry anonymous` +If B→B: run `$GSTACK_BIN/gstack-config set telemetry off` + +Always run: +```bash +touch ~/.gstack/.telemetry-prompted +``` + +This only happens once. If `TEL_PROMPTED` is `yes`, skip this entirely. + +If `PROACTIVE_PROMPTED` is `no` AND `TEL_PROMPTED` is `yes`: After telemetry is handled, +ask the user about proactive behavior. Use AskUserQuestion: + +> gstack can proactively figure out when you might need a skill while you work — +> like suggesting /qa when you say "does this work?" or /investigate when you hit +> a bug. We recommend keeping this on — it speeds up every part of your workflow. + +Options: +- A) Keep it on (recommended) +- B) Turn it off — I'll type /commands myself + +If A: run `$GSTACK_BIN/gstack-config set proactive true` +If B: run `$GSTACK_BIN/gstack-config set proactive false` + +Always run: +```bash +touch ~/.gstack/.proactive-prompted +``` + +This only happens once. If `PROACTIVE_PROMPTED` is `yes`, skip this entirely. + +If `HAS_ROUTING` is `no` AND `ROUTING_DECLINED` is `false` AND `PROACTIVE_PROMPTED` is `yes`: +Check if a AGENTS.md file exists in the project root. If it does not exist, create it. + +Use AskUserQuestion: + +> gstack works best when your project's AGENTS.md includes skill routing rules. +> This tells Claude to use specialized workflows (like /ship, /investigate, /qa) +> instead of answering directly. It's a one-time addition, about 15 lines. + +Options: +- A) Add routing rules to AGENTS.md (recommended) +- B) No thanks, I'll invoke skills manually + +If A: Append this section to the end of AGENTS.md: + +```markdown + +## Skill routing + +When the user's request matches an available skill, invoke it via the Skill tool. The +skill has multi-step workflows, checklists, and quality gates that produce better +results than an ad-hoc answer. When in doubt, invoke the skill. A false positive is +cheaper than a false negative. + +Key routing rules: +- Product ideas, "is this worth building", brainstorming → invoke /office-hours +- Strategy, scope, "think bigger", "what should we build" → invoke /plan-ceo-review +- Architecture, "does this design make sense" → invoke /plan-eng-review +- Design system, brand, "how should this look" → invoke /design-consultation +- Design review of a plan → invoke /plan-design-review +- Developer experience of a plan → invoke /plan-devex-review +- "Review everything", full review pipeline → invoke /autoplan +- Bugs, errors, "why is this broken", "wtf", "this doesn't work" → invoke /investigate +- Test the site, find bugs, "does this work" → invoke /qa (or /qa-only for report only) +- Code review, check the diff, "look at my changes" → invoke /review +- Visual polish, design audit, "this looks off" → invoke /design-review +- Developer experience audit, try onboarding → invoke /devex-review +- Ship, deploy, create a PR, "send it" → invoke /ship +- Merge + deploy + verify → invoke /land-and-deploy +- Configure deployment → invoke /setup-deploy +- Post-deploy monitoring → invoke /canary +- Update docs after shipping → invoke /document-release +- Weekly retro, "how'd we do" → invoke /retro +- Second opinion, codex review → invoke /codex +- Safety mode, careful mode, lock it down → invoke /careful or /guard +- Restrict edits to a directory → invoke /freeze or /unfreeze +- Upgrade gstack → invoke /gstack-upgrade +- Save progress, "save my work" → invoke /context-save +- Resume, restore, "where was I" → invoke /context-restore +- Security audit, OWASP, "is this secure" → invoke /cso +- Make a PDF, document, publication → invoke /make-pdf +- Launch real browser for QA → invoke /open-gstack-browser +- Import cookies for authenticated testing → invoke /setup-browser-cookies +- Performance regression, page speed, benchmarks → invoke /benchmark +- Review what gstack has learned → invoke /learn +- Tune question sensitivity → invoke /plan-tune +- Code quality dashboard → invoke /health +``` + +Then commit the change: `git add AGENTS.md && git commit -m "chore: add gstack skill routing rules to AGENTS.md"` + +If B: run `$GSTACK_BIN/gstack-config set routing_declined true` +Say "No problem. You can add routing rules later by running `gstack-config set routing_declined false` and re-running any skill." + +This only happens once per project. If `HAS_ROUTING` is `yes` or `ROUTING_DECLINED` is `true`, skip this entirely. + +If `VENDORED_GSTACK` is `yes`: This project has a vendored copy of gstack at +`.gbrain/skills/gstack/`. Vendoring is deprecated. We will not keep vendored copies +up to date, so this project's gstack will fall behind. + +Use AskUserQuestion (one-time per project, check for `~/.gstack/.vendoring-warned-$SLUG` marker): + +> This project has gstack vendored in `.gbrain/skills/gstack/`. Vendoring is deprecated. +> We won't keep this copy up to date, so you'll fall behind on new features and fixes. +> +> Want to migrate to team mode? It takes about 30 seconds. + +Options: +- A) Yes, migrate to team mode now +- B) No, I'll handle it myself + +If A: +1. Run `git rm -r .gbrain/skills/gstack/` +2. Run `echo '.gbrain/skills/gstack/' >> .gitignore` +3. Run `$GSTACK_BIN/gstack-team-init required` (or `optional`) +4. Run `git add .claude/ .gitignore AGENTS.md && git commit -m "chore: migrate gstack from vendored to team mode"` +5. Tell the user: "Done. Each developer now runs: `cd ~/.gbrain/skills/gstack && ./setup --team`" + +If B: say "OK, you're on your own to keep the vendored copy up to date." + +Always run (regardless of choice): +```bash +eval "$($GSTACK_BIN/gstack-slug 2>/dev/null)" 2>/dev/null || true +touch ~/.gstack/.vendoring-warned-${SLUG:-unknown} +``` + +This only happens once per project. If the marker file exists, skip entirely. + +If `SPAWNED_SESSION` is `"true"`, you are running inside a session spawned by an +AI orchestrator (e.g., OpenClaw). In spawned sessions: +- Do NOT use AskUserQuestion for interactive prompts. Auto-choose the recommended option. +- Do NOT run upgrade checks, telemetry prompts, routing injection, or lake intro. +- Focus on completing the task and reporting results via prose output. +- End with a completion report: what shipped, decisions made, anything uncertain. + +If `BRAIN_HEALTH` is shown and the score is below 50, tell the user which checks +failed (shown in the output) and suggest: "Run \`gbrain doctor\` for full diagnostics." +If the output is not valid JSON or health_score is missing, treat GBrain as unavailable +and proceed without brain features this session. + +## AskUserQuestion Format + +**ALWAYS follow this structure for every AskUserQuestion call. Every element is non-skippable. If you find yourself about to skip any of them, stop and back up.** + +### Required shape + +Every AskUserQuestion reads like a decision brief, not a bullet list: + +``` +D + +ELI10: + +Stakes if we pick wrong: + +Recommendation: because + +Completeness: A=X/10, B=Y/10 (or: Note: options differ in kind, not coverage — no completeness score) + +Pros / cons: + +A)