From 513c9660fab091d5613c16d52937681bad050807 Mon Sep 17 00:00:00 2001 From: Garry Tan Date: Mon, 11 May 2026 18:58:33 -0700 Subject: [PATCH] feat(skills): task-shaped queries + mid-flow refresh in /investigate /qa /ship The three long skills now pull learnings keyed to their theme at the top, then re-pull at phase boundaries as work shifts to new sub-tasks. Top-of-skill queries (5-6 token unions, token-OR matched): - investigate: "debug investigation root cause hypothesis bug fix" - qa: "qa testing bug regression flake fixture" - ship: "release ship version changelog merge pr" Mid-flow refresh blocks (concrete keyword recipe + worked examples): - investigate: between Phase 1 (hypothesis) and Phase 2 (analysis), keyed to the hypothesis noun. Examples: auth-cookie, session-expiry. - qa: between Phase 7 (triage) and Phase 8 (fix loop), keyed to the buggy component name. Examples: checkout-button, signup-form. - ship: just before Step 12 (VERSION bump), keyed to the headline feature. Examples: learnings-search, pacing, worktree-ship. Keyword recipe enforces alphanumeric+hyphen only (no quotes, slashes, dots, colons) so dynamic queries cannot inject shell metacharacters. The other 13 short-lived skills keep the bare {{LEARNINGS_SEARCH}} form. Backwards-compat verified via diff: their generated SKILL.md output is byte-identical to before this change. Golden ship fixtures regenerated to match the new ship/SKILL.md output. Co-Authored-By: Claude Opus 4.7 --- investigate/SKILL.md | 18 ++++++++++++++++-- investigate/SKILL.md.tmpl | 16 +++++++++++++++- qa/SKILL.md | 18 ++++++++++++++++-- qa/SKILL.md.tmpl | 16 +++++++++++++++- ship/SKILL.md | 18 ++++++++++++++++-- ship/SKILL.md.tmpl | 16 +++++++++++++++- test/fixtures/golden/claude-ship-SKILL.md | 18 ++++++++++++++++-- test/fixtures/golden/codex-ship-SKILL.md | 16 +++++++++++++++- test/fixtures/golden/factory-ship-SKILL.md | 18 ++++++++++++++++-- 9 files changed, 140 insertions(+), 14 deletions(-) diff --git a/investigate/SKILL.md b/investigate/SKILL.md index f69aefe1..9e2b23f0 100644 --- a/investigate/SKILL.md +++ b/investigate/SKILL.md @@ -823,9 +823,9 @@ Search for relevant learnings from previous sessions: _CROSS_PROJ=$(~/.claude/skills/gstack/bin/gstack-config get cross_project_learnings 2>/dev/null || echo "unset") echo "CROSS_PROJECT: $_CROSS_PROJ" if [ "$_CROSS_PROJ" = "true" ]; then - ~/.claude/skills/gstack/bin/gstack-learnings-search --limit 10 --cross-project 2>/dev/null || true + ~/.claude/skills/gstack/bin/gstack-learnings-search --limit 10 --query "debug investigation root cause hypothesis bug fix" --cross-project 2>/dev/null || true else - ~/.claude/skills/gstack/bin/gstack-learnings-search --limit 10 2>/dev/null || true + ~/.claude/skills/gstack/bin/gstack-learnings-search --limit 10 --query "debug investigation root cause hypothesis bug fix" 2>/dev/null || true fi ``` @@ -855,6 +855,20 @@ smarter on their codebase over time. Output: **"Root cause hypothesis: ..."** — a specific, testable claim about what is wrong and why. +### Refresh learnings for the hypothesis you just named + +The top-of-skill learnings pull above is keyed to "debug investigation" broadly. Now that you have a specific hypothesis, re-pull learnings keyed to that hypothesis so prior fixes for the same problem-shape surface. + +Pick ONE keyword from the hypothesis. The keyword should be a noun: the failing component name, the basename of the file you suspect (without extension), or the bug noun. The keyword MUST be alphanumeric or hyphen only — no quotes, slashes, dots, colons, or whitespace. If your candidate has any of those, simplify to just the alphanumeric stem. + +Worked examples (investigate-specific): good keywords are `auth-cookie`, `session-expiry`, `redirect-loop`. Bad: `auth.ts:47`, `fix the auth bug`, ``. + +```bash +~/.claude/skills/gstack/bin/gstack-learnings-search --query "" --limit 5 2>/dev/null || true +``` + +If any learnings come back, name which one applies to your investigation in one sentence. If none come back, continue without reference — the absence of a matching prior learning is itself useful information. + --- ## Scope Lock diff --git a/investigate/SKILL.md.tmpl b/investigate/SKILL.md.tmpl index fb649f02..20cc2e26 100644 --- a/investigate/SKILL.md.tmpl +++ b/investigate/SKILL.md.tmpl @@ -93,10 +93,24 @@ Gather context before forming any hypothesis. 5. **Check investigation history:** Search prior learnings for investigations on the same files. Recurring bugs in the same area are an architectural smell. If prior investigations exist, note patterns and check if the root cause was structural. -{{LEARNINGS_SEARCH}} +{{LEARNINGS_SEARCH:query=debug investigation root cause hypothesis bug fix}} Output: **"Root cause hypothesis: ..."** — a specific, testable claim about what is wrong and why. +### Refresh learnings for the hypothesis you just named + +The top-of-skill learnings pull above is keyed to "debug investigation" broadly. Now that you have a specific hypothesis, re-pull learnings keyed to that hypothesis so prior fixes for the same problem-shape surface. + +Pick ONE keyword from the hypothesis. The keyword should be a noun: the failing component name, the basename of the file you suspect (without extension), or the bug noun. The keyword MUST be alphanumeric or hyphen only — no quotes, slashes, dots, colons, or whitespace. If your candidate has any of those, simplify to just the alphanumeric stem. + +Worked examples (investigate-specific): good keywords are `auth-cookie`, `session-expiry`, `redirect-loop`. Bad: `auth.ts:47`, `fix the auth bug`, ``. + +```bash +~/.claude/skills/gstack/bin/gstack-learnings-search --query "" --limit 5 2>/dev/null || true +``` + +If any learnings come back, name which one applies to your investigation in one sentence. If none come back, continue without reference — the absence of a matching prior learning is itself useful information. + --- ## Scope Lock diff --git a/qa/SKILL.md b/qa/SKILL.md index 41f84fcc..0b56e53e 100644 --- a/qa/SKILL.md +++ b/qa/SKILL.md @@ -1068,9 +1068,9 @@ Search for relevant learnings from previous sessions: _CROSS_PROJ=$(~/.claude/skills/gstack/bin/gstack-config get cross_project_learnings 2>/dev/null || echo "unset") echo "CROSS_PROJECT: $_CROSS_PROJ" if [ "$_CROSS_PROJ" = "true" ]; then - ~/.claude/skills/gstack/bin/gstack-learnings-search --limit 10 --cross-project 2>/dev/null || true + ~/.claude/skills/gstack/bin/gstack-learnings-search --limit 10 --query "qa testing bug regression flake fixture" --cross-project 2>/dev/null || true else - ~/.claude/skills/gstack/bin/gstack-learnings-search --limit 10 2>/dev/null || true + ~/.claude/skills/gstack/bin/gstack-learnings-search --limit 10 --query "qa testing bug regression flake fixture" 2>/dev/null || true fi ``` @@ -1426,6 +1426,20 @@ Sort all discovered issues by severity, then decide which to fix based on the se Mark issues that cannot be fixed from source code (e.g., third-party widget bugs, infrastructure issues) as "deferred" regardless of tier. +### Refresh learnings for the component/page where the bug lives + +The top-of-skill learnings pull was keyed to "qa testing" broadly. Before the fix loop, re-pull learnings keyed to the component or page where the bug you're about to fix lives so prior fixes for the same component-shape surface. + +Pick ONE keyword that names the buggy component or page. The keyword should be a noun: the failing component name, the page route base, or the feature noun. The keyword MUST be alphanumeric or hyphen only — no quotes, slashes, dots, colons, or whitespace. If your candidate has any of those, simplify to just the alphanumeric stem. + +Worked examples (qa-specific): good keywords are `checkout-button`, `signup-form`, `payment`. Bad: `tests are failing`, ``, `app/views/_checkout.html.erb`. + +```bash +~/.claude/skills/gstack/bin/gstack-learnings-search --query "" --limit 5 2>/dev/null || true +``` + +If any learnings come back, name which one applies to the fix you're about to make in one sentence. If none come back, continue without reference — the absence is itself useful information. + --- ## Phase 8: Fix Loop diff --git a/qa/SKILL.md.tmpl b/qa/SKILL.md.tmpl index 62081d2c..11997f7b 100644 --- a/qa/SKILL.md.tmpl +++ b/qa/SKILL.md.tmpl @@ -100,7 +100,7 @@ mkdir -p .gstack/qa-reports/screenshots --- -{{LEARNINGS_SEARCH}} +{{LEARNINGS_SEARCH:query=qa testing bug regression flake fixture}} ## Test Plan Context @@ -154,6 +154,20 @@ Sort all discovered issues by severity, then decide which to fix based on the se Mark issues that cannot be fixed from source code (e.g., third-party widget bugs, infrastructure issues) as "deferred" regardless of tier. +### Refresh learnings for the component/page where the bug lives + +The top-of-skill learnings pull was keyed to "qa testing" broadly. Before the fix loop, re-pull learnings keyed to the component or page where the bug you're about to fix lives so prior fixes for the same component-shape surface. + +Pick ONE keyword that names the buggy component or page. The keyword should be a noun: the failing component name, the page route base, or the feature noun. The keyword MUST be alphanumeric or hyphen only — no quotes, slashes, dots, colons, or whitespace. If your candidate has any of those, simplify to just the alphanumeric stem. + +Worked examples (qa-specific): good keywords are `checkout-button`, `signup-form`, `payment`. Bad: `tests are failing`, ``, `app/views/_checkout.html.erb`. + +```bash +~/.claude/skills/gstack/bin/gstack-learnings-search --query "" --limit 5 2>/dev/null || true +``` + +If any learnings come back, name which one applies to the fix you're about to make in one sentence. If none come back, continue without reference — the absence is itself useful information. + --- ## Phase 8: Fix Loop diff --git a/ship/SKILL.md b/ship/SKILL.md index c1b25c95..25119fb3 100644 --- a/ship/SKILL.md +++ b/ship/SKILL.md @@ -1824,9 +1824,9 @@ Search for relevant learnings from previous sessions: _CROSS_PROJ=$(~/.claude/skills/gstack/bin/gstack-config get cross_project_learnings 2>/dev/null || echo "unset") echo "CROSS_PROJECT: $_CROSS_PROJ" if [ "$_CROSS_PROJ" = "true" ]; then - ~/.claude/skills/gstack/bin/gstack-learnings-search --limit 10 --cross-project 2>/dev/null || true + ~/.claude/skills/gstack/bin/gstack-learnings-search --limit 10 --query "release ship version changelog merge pr" --cross-project 2>/dev/null || true else - ~/.claude/skills/gstack/bin/gstack-learnings-search --limit 10 2>/dev/null || true + ~/.claude/skills/gstack/bin/gstack-learnings-search --limit 10 --query "release ship version changelog merge pr" 2>/dev/null || true fi ``` @@ -2459,6 +2459,20 @@ already knows. A good test: would this insight save time in a future session? If +### Refresh learnings for the headline feature on this branch + +The top-of-skill learnings pull was keyed to "release ship" broadly. Before the VERSION/CHANGELOG step, re-pull learnings keyed to THIS branch's headline feature so any prior version-bump or CHANGELOG pitfalls for similar features surface. + +Pick ONE keyword that names the headline feature you're shipping. The keyword should be a noun: the primary skill or module name, the central feature noun, or the binary you changed. The keyword MUST be alphanumeric or hyphen only — no quotes, slashes, dots, colons, or whitespace. If your candidate has any of those, simplify to just the alphanumeric stem. + +Worked examples (ship-specific): good keywords are `learnings-search`, `pacing`, `worktree-ship`. Bad: `the branch headline`, `v1.31.1.0`, `feat: token-or search`. + +```bash +~/.claude/skills/gstack/bin/gstack-learnings-search --query "" --limit 5 2>/dev/null || true +``` + +If any learnings come back, name which one applies to the version bump or CHANGELOG framing in one sentence. If none come back, continue without reference — the absence is itself useful information. + ## Step 12: Version bump (auto-decide) **Idempotency check:** Before bumping, classify the state by comparing `VERSION` against the base branch AND against `package.json`'s `version` field. Four states: FRESH (do bump), ALREADY_BUMPED (skip bump), DRIFT_STALE_PKG (sync pkg only, no re-bump), DRIFT_UNEXPECTED (stop and ask). diff --git a/ship/SKILL.md.tmpl b/ship/SKILL.md.tmpl index a1c18ecf..5a7c3466 100644 --- a/ship/SKILL.md.tmpl +++ b/ship/SKILL.md.tmpl @@ -283,7 +283,7 @@ If multiple suites need to run, run them sequentially (each needs a test lane). {{PLAN_VERIFICATION_EXEC}} -{{LEARNINGS_SEARCH}} +{{LEARNINGS_SEARCH:query=release ship version changelog merge pr}} {{SCOPE_DRIFT}} @@ -401,6 +401,20 @@ For each comment in `comments`: {{GBRAIN_SAVE_RESULTS}} +### Refresh learnings for the headline feature on this branch + +The top-of-skill learnings pull was keyed to "release ship" broadly. Before the VERSION/CHANGELOG step, re-pull learnings keyed to THIS branch's headline feature so any prior version-bump or CHANGELOG pitfalls for similar features surface. + +Pick ONE keyword that names the headline feature you're shipping. The keyword should be a noun: the primary skill or module name, the central feature noun, or the binary you changed. The keyword MUST be alphanumeric or hyphen only — no quotes, slashes, dots, colons, or whitespace. If your candidate has any of those, simplify to just the alphanumeric stem. + +Worked examples (ship-specific): good keywords are `learnings-search`, `pacing`, `worktree-ship`. Bad: `the branch headline`, `v1.31.1.0`, `feat: token-or search`. + +```bash +~/.claude/skills/gstack/bin/gstack-learnings-search --query "" --limit 5 2>/dev/null || true +``` + +If any learnings come back, name which one applies to the version bump or CHANGELOG framing in one sentence. If none come back, continue without reference — the absence is itself useful information. + ## Step 12: Version bump (auto-decide) **Idempotency check:** Before bumping, classify the state by comparing `VERSION` against the base branch AND against `package.json`'s `version` field. Four states: FRESH (do bump), ALREADY_BUMPED (skip bump), DRIFT_STALE_PKG (sync pkg only, no re-bump), DRIFT_UNEXPECTED (stop and ask). diff --git a/test/fixtures/golden/claude-ship-SKILL.md b/test/fixtures/golden/claude-ship-SKILL.md index c1b25c95..25119fb3 100644 --- a/test/fixtures/golden/claude-ship-SKILL.md +++ b/test/fixtures/golden/claude-ship-SKILL.md @@ -1824,9 +1824,9 @@ Search for relevant learnings from previous sessions: _CROSS_PROJ=$(~/.claude/skills/gstack/bin/gstack-config get cross_project_learnings 2>/dev/null || echo "unset") echo "CROSS_PROJECT: $_CROSS_PROJ" if [ "$_CROSS_PROJ" = "true" ]; then - ~/.claude/skills/gstack/bin/gstack-learnings-search --limit 10 --cross-project 2>/dev/null || true + ~/.claude/skills/gstack/bin/gstack-learnings-search --limit 10 --query "release ship version changelog merge pr" --cross-project 2>/dev/null || true else - ~/.claude/skills/gstack/bin/gstack-learnings-search --limit 10 2>/dev/null || true + ~/.claude/skills/gstack/bin/gstack-learnings-search --limit 10 --query "release ship version changelog merge pr" 2>/dev/null || true fi ``` @@ -2459,6 +2459,20 @@ already knows. A good test: would this insight save time in a future session? If +### Refresh learnings for the headline feature on this branch + +The top-of-skill learnings pull was keyed to "release ship" broadly. Before the VERSION/CHANGELOG step, re-pull learnings keyed to THIS branch's headline feature so any prior version-bump or CHANGELOG pitfalls for similar features surface. + +Pick ONE keyword that names the headline feature you're shipping. The keyword should be a noun: the primary skill or module name, the central feature noun, or the binary you changed. The keyword MUST be alphanumeric or hyphen only — no quotes, slashes, dots, colons, or whitespace. If your candidate has any of those, simplify to just the alphanumeric stem. + +Worked examples (ship-specific): good keywords are `learnings-search`, `pacing`, `worktree-ship`. Bad: `the branch headline`, `v1.31.1.0`, `feat: token-or search`. + +```bash +~/.claude/skills/gstack/bin/gstack-learnings-search --query "" --limit 5 2>/dev/null || true +``` + +If any learnings come back, name which one applies to the version bump or CHANGELOG framing in one sentence. If none come back, continue without reference — the absence is itself useful information. + ## Step 12: Version bump (auto-decide) **Idempotency check:** Before bumping, classify the state by comparing `VERSION` against the base branch AND against `package.json`'s `version` field. Four states: FRESH (do bump), ALREADY_BUMPED (skip bump), DRIFT_STALE_PKG (sync pkg only, no re-bump), DRIFT_UNEXPECTED (stop and ask). diff --git a/test/fixtures/golden/codex-ship-SKILL.md b/test/fixtures/golden/codex-ship-SKILL.md index d09e39e9..7d1ca185 100644 --- a/test/fixtures/golden/codex-ship-SKILL.md +++ b/test/fixtures/golden/codex-ship-SKILL.md @@ -1789,7 +1789,7 @@ Add a `## Verification Results` section to the PR body (Step 19): Search for relevant learnings from previous sessions on this project: ```bash -$GSTACK_BIN/gstack-learnings-search --limit 10 2>/dev/null || true +$GSTACK_BIN/gstack-learnings-search --limit 10 --query "release ship version changelog merge pr" 2>/dev/null || true ``` If learnings are found, incorporate them into your analysis. When a review finding @@ -2053,6 +2053,20 @@ already knows. A good test: would this insight save time in a future session? If +### Refresh learnings for the headline feature on this branch + +The top-of-skill learnings pull was keyed to "release ship" broadly. Before the VERSION/CHANGELOG step, re-pull learnings keyed to THIS branch's headline feature so any prior version-bump or CHANGELOG pitfalls for similar features surface. + +Pick ONE keyword that names the headline feature you're shipping. The keyword should be a noun: the primary skill or module name, the central feature noun, or the binary you changed. The keyword MUST be alphanumeric or hyphen only — no quotes, slashes, dots, colons, or whitespace. If your candidate has any of those, simplify to just the alphanumeric stem. + +Worked examples (ship-specific): good keywords are `learnings-search`, `pacing`, `worktree-ship`. Bad: `the branch headline`, `v1.31.1.0`, `feat: token-or search`. + +```bash +$GSTACK_ROOT/bin/gstack-learnings-search --query "" --limit 5 2>/dev/null || true +``` + +If any learnings come back, name which one applies to the version bump or CHANGELOG framing in one sentence. If none come back, continue without reference — the absence is itself useful information. + ## Step 12: Version bump (auto-decide) **Idempotency check:** Before bumping, classify the state by comparing `VERSION` against the base branch AND against `package.json`'s `version` field. Four states: FRESH (do bump), ALREADY_BUMPED (skip bump), DRIFT_STALE_PKG (sync pkg only, no re-bump), DRIFT_UNEXPECTED (stop and ask). diff --git a/test/fixtures/golden/factory-ship-SKILL.md b/test/fixtures/golden/factory-ship-SKILL.md index ec849bcc..903c1681 100644 --- a/test/fixtures/golden/factory-ship-SKILL.md +++ b/test/fixtures/golden/factory-ship-SKILL.md @@ -1794,9 +1794,9 @@ Search for relevant learnings from previous sessions: _CROSS_PROJ=$($GSTACK_BIN/gstack-config get cross_project_learnings 2>/dev/null || echo "unset") echo "CROSS_PROJECT: $_CROSS_PROJ" if [ "$_CROSS_PROJ" = "true" ]; then - $GSTACK_BIN/gstack-learnings-search --limit 10 --cross-project 2>/dev/null || true + $GSTACK_BIN/gstack-learnings-search --limit 10 --query "release ship version changelog merge pr" --cross-project 2>/dev/null || true else - $GSTACK_BIN/gstack-learnings-search --limit 10 2>/dev/null || true + $GSTACK_BIN/gstack-learnings-search --limit 10 --query "release ship version changelog merge pr" 2>/dev/null || true fi ``` @@ -2429,6 +2429,20 @@ already knows. A good test: would this insight save time in a future session? If +### Refresh learnings for the headline feature on this branch + +The top-of-skill learnings pull was keyed to "release ship" broadly. Before the VERSION/CHANGELOG step, re-pull learnings keyed to THIS branch's headline feature so any prior version-bump or CHANGELOG pitfalls for similar features surface. + +Pick ONE keyword that names the headline feature you're shipping. The keyword should be a noun: the primary skill or module name, the central feature noun, or the binary you changed. The keyword MUST be alphanumeric or hyphen only — no quotes, slashes, dots, colons, or whitespace. If your candidate has any of those, simplify to just the alphanumeric stem. + +Worked examples (ship-specific): good keywords are `learnings-search`, `pacing`, `worktree-ship`. Bad: `the branch headline`, `v1.31.1.0`, `feat: token-or search`. + +```bash +$GSTACK_ROOT/bin/gstack-learnings-search --query "" --limit 5 2>/dev/null || true +``` + +If any learnings come back, name which one applies to the version bump or CHANGELOG framing in one sentence. If none come back, continue without reference — the absence is itself useful information. + ## Step 12: Version bump (auto-decide) **Idempotency check:** Before bumping, classify the state by comparing `VERSION` against the base branch AND against `package.json`'s `version` field. Four states: FRESH (do bump), ALREADY_BUMPED (skip bump), DRIFT_STALE_PKG (sync pkg only, no re-bump), DRIFT_UNEXPECTED (stop and ask).