From 95b66b56ca0ffb7d389b62c2e908c625a08d0aa8 Mon Sep 17 00:00:00 2001 From: Garry Tan Date: Sun, 16 Aug 2026 10:20:47 -0700 Subject: [PATCH] fix(preamble): probe AGENTS.md for skill routing; team-init resolves GSTACK_ROOT (#2500) The HAS_ROUTING preamble probe only checked CLAUDE.md, so repos that route skills via AGENTS.md (the cross-harness convention for Codex, Cursor, and generic agent hosts) reported HAS_ROUTING: no and got nagged to create CLAUDE.md. The probe now iterates CLAUDE.md and AGENTS.md. gstack-team-init's required-mode enforcement (the CLAUDE.md verification snippet and the generated .claude/hooks/check-gstack.sh) hardcoded ~/.claude/skills/gstack, false-blocking installs living at any other host's global root or the migrated ~/.gstack/repos/gstack location. Both sites now resolve the install root: GSTACK_ROOT env first, then every registered host's globalRoot, then the migrated repo path. Install instructions keep pointing at the canonical Claude location. test/routing-probe.test.ts pins both: rendered-preamble assertions plus a live execution of the extracted probe block (AGENTS.md-only repo => yes), and a drift test that requires every hosts-registry globalRoot to appear in team-init's probe list. Re-derived from PR #2500 onto current code (the PR's 52-file regen was discarded and regenerated here). Contributed by @gamerey43. Fixes #2500 Co-authored-by: gamerey43 Co-Authored-By: Claude Fable 5 --- SKILL.md | 8 +- autoplan/SKILL.md | 8 +- benchmark-models/SKILL.md | 8 +- benchmark/SKILL.md | 8 +- bin/gstack-team-init | 20 ++- browse/SKILL.md | 8 +- canary/SKILL.md | 8 +- codex/SKILL.md | 8 +- context-restore/SKILL.md | 8 +- context-save/SKILL.md | 8 +- cso/SKILL.md | 8 +- design-consultation/SKILL.md | 8 +- design-html/SKILL.md | 8 +- design-review/SKILL.md | 8 +- design-shotgun/SKILL.md | 8 +- devex-review/SKILL.md | 8 +- diagram/SKILL.md | 8 +- document-generate/SKILL.md | 8 +- document-release/SKILL.md | 8 +- health/SKILL.md | 8 +- investigate/SKILL.md | 8 +- ios-clean/SKILL.md | 8 +- ios-design-review/SKILL.md | 8 +- ios-fix/SKILL.md | 8 +- ios-qa/SKILL.md | 8 +- ios-sync/SKILL.md | 8 +- land-and-deploy/SKILL.md | 8 +- landing-report/SKILL.md | 8 +- learn/SKILL.md | 8 +- make-pdf/SKILL.md | 8 +- office-hours/SKILL.md | 8 +- open-gstack-browser/SKILL.md | 8 +- pair-agent/SKILL.md | 8 +- plan-ceo-review/SKILL.md | 8 +- plan-design-review/SKILL.md | 8 +- plan-devex-review/SKILL.md | 8 +- plan-eng-review/SKILL.md | 8 +- plan-tune/SKILL.md | 8 +- qa-only/SKILL.md | 8 +- qa/SKILL.md | 8 +- retro/SKILL.md | 8 +- review/SKILL.md | 8 +- scrape/SKILL.md | 8 +- .../preamble/generate-preamble-bash.ts | 8 +- setup-browser-cookies/SKILL.md | 8 +- setup-deploy/SKILL.md | 8 +- setup-gbrain/SKILL.md | 8 +- ship/SKILL.md | 8 +- skillify/SKILL.md | 8 +- spec/SKILL.md | 8 +- sync-gbrain/SKILL.md | 8 +- test/fixtures/golden/claude-ship-SKILL.md | 8 +- test/fixtures/golden/codex-ship-SKILL.md | 8 +- test/fixtures/golden/factory-ship-SKILL.md | 8 +- test/routing-probe.test.ts | 116 ++++++++++++++++++ 55 files changed, 398 insertions(+), 162 deletions(-) create mode 100644 test/routing-probe.test.ts diff --git a/SKILL.md b/SKILL.md index 8c1ff4dfb..9069bbb1b 100644 --- a/SKILL.md +++ b/SKILL.md @@ -106,9 +106,11 @@ else fi ~/.claude/skills/gstack/bin/gstack-timeline-log '{"skill":"gstack","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & _HAS_ROUTING="no" -if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then - _HAS_ROUTING="yes" -fi +for _RF in CLAUDE.md AGENTS.md; do + if [ -f "$_RF" ] && grep -q "## Skill routing" "$_RF" 2>/dev/null; then + _HAS_ROUTING="yes" + fi +done _ROUTING_DECLINED=$(~/.claude/skills/gstack/bin/gstack-config get routing_declined 2>/dev/null || echo "false") echo "HAS_ROUTING: $_HAS_ROUTING" echo "ROUTING_DECLINED: $_ROUTING_DECLINED" diff --git a/autoplan/SKILL.md b/autoplan/SKILL.md index f81dc72a5..695cdcb11 100644 --- a/autoplan/SKILL.md +++ b/autoplan/SKILL.md @@ -116,9 +116,11 @@ else fi ~/.claude/skills/gstack/bin/gstack-timeline-log '{"skill":"autoplan","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & _HAS_ROUTING="no" -if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then - _HAS_ROUTING="yes" -fi +for _RF in CLAUDE.md AGENTS.md; do + if [ -f "$_RF" ] && grep -q "## Skill routing" "$_RF" 2>/dev/null; then + _HAS_ROUTING="yes" + fi +done _ROUTING_DECLINED=$(~/.claude/skills/gstack/bin/gstack-config get routing_declined 2>/dev/null || echo "false") echo "HAS_ROUTING: $_HAS_ROUTING" echo "ROUTING_DECLINED: $_ROUTING_DECLINED" diff --git a/benchmark-models/SKILL.md b/benchmark-models/SKILL.md index 75e7e5128..80d32a6b7 100644 --- a/benchmark-models/SKILL.md +++ b/benchmark-models/SKILL.md @@ -110,9 +110,11 @@ else fi ~/.claude/skills/gstack/bin/gstack-timeline-log '{"skill":"benchmark-models","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & _HAS_ROUTING="no" -if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then - _HAS_ROUTING="yes" -fi +for _RF in CLAUDE.md AGENTS.md; do + if [ -f "$_RF" ] && grep -q "## Skill routing" "$_RF" 2>/dev/null; then + _HAS_ROUTING="yes" + fi +done _ROUTING_DECLINED=$(~/.claude/skills/gstack/bin/gstack-config get routing_declined 2>/dev/null || echo "false") echo "HAS_ROUTING: $_HAS_ROUTING" echo "ROUTING_DECLINED: $_ROUTING_DECLINED" diff --git a/benchmark/SKILL.md b/benchmark/SKILL.md index 10a68e818..8b1176b24 100644 --- a/benchmark/SKILL.md +++ b/benchmark/SKILL.md @@ -110,9 +110,11 @@ else fi ~/.claude/skills/gstack/bin/gstack-timeline-log '{"skill":"benchmark","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & _HAS_ROUTING="no" -if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then - _HAS_ROUTING="yes" -fi +for _RF in CLAUDE.md AGENTS.md; do + if [ -f "$_RF" ] && grep -q "## Skill routing" "$_RF" 2>/dev/null; then + _HAS_ROUTING="yes" + fi +done _ROUTING_DECLINED=$(~/.claude/skills/gstack/bin/gstack-config get routing_declined 2>/dev/null || echo "false") echo "HAS_ROUTING: $_HAS_ROUTING" echo "ROUTING_DECLINED: $_ROUTING_DECLINED" diff --git a/bin/gstack-team-init b/bin/gstack-team-init index fd6c1b7d9..99538425f 100755 --- a/bin/gstack-team-init +++ b/bin/gstack-team-init @@ -70,7 +70,11 @@ else **Before doing ANY work, verify gstack is installed:** ```bash -test -d ~/.claude/skills/gstack/bin && echo "GSTACK_OK" || echo "GSTACK_MISSING" +_GS="" +for _D in "${GSTACK_ROOT:-}" "$HOME/.claude/skills/gstack" "$HOME/.codex/skills/gstack" "$HOME/.factory/skills/gstack" "$HOME/.kiro/skills/gstack" "$HOME/.config/opencode/skills/gstack" "$HOME/.slate/skills/gstack" "$HOME/.cursor/skills/gstack" "$HOME/.openclaw/skills/gstack" "$HOME/.hermes/skills/gstack" "$HOME/.gbrain/skills/gstack" "$HOME/.gstack/repos/gstack"; do + [ -z "$_GS" ] && [ -n "$_D" ] && [ -d "$_D/bin" ] && _GS="$_D" +done +[ -n "$_GS" ] && echo "GSTACK_OK: $_GS" || echo "GSTACK_MISSING" ``` If GSTACK_MISSING: STOP. Do not proceed. Tell the user: @@ -87,7 +91,8 @@ Do not skip skills, ignore gstack errors, or work around missing gstack. Using gstack skills: After install, skills like /qa, /ship, /review, /investigate, and /browse are available. Use /browse for all web browsing. -Use ~/.claude/skills/gstack/... for gstack file paths (the global path).' +Use the resolved install path above for gstack file paths +(default: ~/.claude/skills/gstack).' fi # Check if CLAUDE.md already has a gstack section @@ -114,8 +119,17 @@ if [ "$MODE" = "required" ]; then cat > "$HOOKS_DIR/check-gstack.sh" << 'HOOK_EOF' #!/bin/bash # Block skill usage when gstack is not installed globally. +# +# Resolve the install root the way gstack skill preambles do: the GSTACK_ROOT +# env var first, then every host's global install location, then the migrated +# repo location. Block only when NONE exist (#2500 — hardcoding +# ~/.claude/skills/gstack false-blocked Codex-host and migrated-repo installs). +_GSTACK_ROOT="" +for _D in "${GSTACK_ROOT:-}" "$HOME/.claude/skills/gstack" "$HOME/.codex/skills/gstack" "$HOME/.factory/skills/gstack" "$HOME/.kiro/skills/gstack" "$HOME/.config/opencode/skills/gstack" "$HOME/.slate/skills/gstack" "$HOME/.cursor/skills/gstack" "$HOME/.openclaw/skills/gstack" "$HOME/.hermes/skills/gstack" "$HOME/.gbrain/skills/gstack" "$HOME/.gstack/repos/gstack"; do + [ -z "$_GSTACK_ROOT" ] && [ -n "$_D" ] && [ -d "$_D/bin" ] && _GSTACK_ROOT="$_D" +done -if [ ! -d "$HOME/.claude/skills/gstack/bin" ]; then +if [ -z "$_GSTACK_ROOT" ]; then cat >&2 <<'MSG' BLOCKED: gstack is not installed globally. diff --git a/browse/SKILL.md b/browse/SKILL.md index 37b6b1a19..964c6d3c2 100644 --- a/browse/SKILL.md +++ b/browse/SKILL.md @@ -108,9 +108,11 @@ else fi ~/.claude/skills/gstack/bin/gstack-timeline-log '{"skill":"browse","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & _HAS_ROUTING="no" -if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then - _HAS_ROUTING="yes" -fi +for _RF in CLAUDE.md AGENTS.md; do + if [ -f "$_RF" ] && grep -q "## Skill routing" "$_RF" 2>/dev/null; then + _HAS_ROUTING="yes" + fi +done _ROUTING_DECLINED=$(~/.claude/skills/gstack/bin/gstack-config get routing_declined 2>/dev/null || echo "false") echo "HAS_ROUTING: $_HAS_ROUTING" echo "ROUTING_DECLINED: $_ROUTING_DECLINED" diff --git a/canary/SKILL.md b/canary/SKILL.md index 806e1f3b9..95dc82fe6 100644 --- a/canary/SKILL.md +++ b/canary/SKILL.md @@ -108,9 +108,11 @@ else fi ~/.claude/skills/gstack/bin/gstack-timeline-log '{"skill":"canary","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & _HAS_ROUTING="no" -if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then - _HAS_ROUTING="yes" -fi +for _RF in CLAUDE.md AGENTS.md; do + if [ -f "$_RF" ] && grep -q "## Skill routing" "$_RF" 2>/dev/null; then + _HAS_ROUTING="yes" + fi +done _ROUTING_DECLINED=$(~/.claude/skills/gstack/bin/gstack-config get routing_declined 2>/dev/null || echo "false") echo "HAS_ROUTING: $_HAS_ROUTING" echo "ROUTING_DECLINED: $_ROUTING_DECLINED" diff --git a/codex/SKILL.md b/codex/SKILL.md index 36eadff5e..2ddbabc87 100644 --- a/codex/SKILL.md +++ b/codex/SKILL.md @@ -111,9 +111,11 @@ else fi ~/.claude/skills/gstack/bin/gstack-timeline-log '{"skill":"codex","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & _HAS_ROUTING="no" -if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then - _HAS_ROUTING="yes" -fi +for _RF in CLAUDE.md AGENTS.md; do + if [ -f "$_RF" ] && grep -q "## Skill routing" "$_RF" 2>/dev/null; then + _HAS_ROUTING="yes" + fi +done _ROUTING_DECLINED=$(~/.claude/skills/gstack/bin/gstack-config get routing_declined 2>/dev/null || echo "false") echo "HAS_ROUTING: $_HAS_ROUTING" echo "ROUTING_DECLINED: $_ROUTING_DECLINED" diff --git a/context-restore/SKILL.md b/context-restore/SKILL.md index 5a3c5b6ef..becf13369 100644 --- a/context-restore/SKILL.md +++ b/context-restore/SKILL.md @@ -112,9 +112,11 @@ else fi ~/.claude/skills/gstack/bin/gstack-timeline-log '{"skill":"context-restore","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & _HAS_ROUTING="no" -if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then - _HAS_ROUTING="yes" -fi +for _RF in CLAUDE.md AGENTS.md; do + if [ -f "$_RF" ] && grep -q "## Skill routing" "$_RF" 2>/dev/null; then + _HAS_ROUTING="yes" + fi +done _ROUTING_DECLINED=$(~/.claude/skills/gstack/bin/gstack-config get routing_declined 2>/dev/null || echo "false") echo "HAS_ROUTING: $_HAS_ROUTING" echo "ROUTING_DECLINED: $_ROUTING_DECLINED" diff --git a/context-save/SKILL.md b/context-save/SKILL.md index be9df4146..3625efdba 100644 --- a/context-save/SKILL.md +++ b/context-save/SKILL.md @@ -111,9 +111,11 @@ else fi ~/.claude/skills/gstack/bin/gstack-timeline-log '{"skill":"context-save","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & _HAS_ROUTING="no" -if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then - _HAS_ROUTING="yes" -fi +for _RF in CLAUDE.md AGENTS.md; do + if [ -f "$_RF" ] && grep -q "## Skill routing" "$_RF" 2>/dev/null; then + _HAS_ROUTING="yes" + fi +done _ROUTING_DECLINED=$(~/.claude/skills/gstack/bin/gstack-config get routing_declined 2>/dev/null || echo "false") echo "HAS_ROUTING: $_HAS_ROUTING" echo "ROUTING_DECLINED: $_ROUTING_DECLINED" diff --git a/cso/SKILL.md b/cso/SKILL.md index 99e6cb9c0..1add06b4b 100644 --- a/cso/SKILL.md +++ b/cso/SKILL.md @@ -114,9 +114,11 @@ else fi ~/.claude/skills/gstack/bin/gstack-timeline-log '{"skill":"cso","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & _HAS_ROUTING="no" -if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then - _HAS_ROUTING="yes" -fi +for _RF in CLAUDE.md AGENTS.md; do + if [ -f "$_RF" ] && grep -q "## Skill routing" "$_RF" 2>/dev/null; then + _HAS_ROUTING="yes" + fi +done _ROUTING_DECLINED=$(~/.claude/skills/gstack/bin/gstack-config get routing_declined 2>/dev/null || echo "false") echo "HAS_ROUTING: $_HAS_ROUTING" echo "ROUTING_DECLINED: $_ROUTING_DECLINED" diff --git a/design-consultation/SKILL.md b/design-consultation/SKILL.md index 57450909c..9b5e235c3 100644 --- a/design-consultation/SKILL.md +++ b/design-consultation/SKILL.md @@ -134,9 +134,11 @@ else fi ~/.claude/skills/gstack/bin/gstack-timeline-log '{"skill":"design-consultation","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & _HAS_ROUTING="no" -if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then - _HAS_ROUTING="yes" -fi +for _RF in CLAUDE.md AGENTS.md; do + if [ -f "$_RF" ] && grep -q "## Skill routing" "$_RF" 2>/dev/null; then + _HAS_ROUTING="yes" + fi +done _ROUTING_DECLINED=$(~/.claude/skills/gstack/bin/gstack-config get routing_declined 2>/dev/null || echo "false") echo "HAS_ROUTING: $_HAS_ROUTING" echo "ROUTING_DECLINED: $_ROUTING_DECLINED" diff --git a/design-html/SKILL.md b/design-html/SKILL.md index a9e1ac1a9..fec3c3d3d 100644 --- a/design-html/SKILL.md +++ b/design-html/SKILL.md @@ -115,9 +115,11 @@ else fi ~/.claude/skills/gstack/bin/gstack-timeline-log '{"skill":"design-html","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & _HAS_ROUTING="no" -if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then - _HAS_ROUTING="yes" -fi +for _RF in CLAUDE.md AGENTS.md; do + if [ -f "$_RF" ] && grep -q "## Skill routing" "$_RF" 2>/dev/null; then + _HAS_ROUTING="yes" + fi +done _ROUTING_DECLINED=$(~/.claude/skills/gstack/bin/gstack-config get routing_declined 2>/dev/null || echo "false") echo "HAS_ROUTING: $_HAS_ROUTING" echo "ROUTING_DECLINED: $_ROUTING_DECLINED" diff --git a/design-review/SKILL.md b/design-review/SKILL.md index 786423e76..dce3ccbd5 100644 --- a/design-review/SKILL.md +++ b/design-review/SKILL.md @@ -112,9 +112,11 @@ else fi ~/.claude/skills/gstack/bin/gstack-timeline-log '{"skill":"design-review","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & _HAS_ROUTING="no" -if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then - _HAS_ROUTING="yes" -fi +for _RF in CLAUDE.md AGENTS.md; do + if [ -f "$_RF" ] && grep -q "## Skill routing" "$_RF" 2>/dev/null; then + _HAS_ROUTING="yes" + fi +done _ROUTING_DECLINED=$(~/.claude/skills/gstack/bin/gstack-config get routing_declined 2>/dev/null || echo "false") echo "HAS_ROUTING: $_HAS_ROUTING" echo "ROUTING_DECLINED: $_ROUTING_DECLINED" diff --git a/design-shotgun/SKILL.md b/design-shotgun/SKILL.md index 4066154c1..a664da86f 100644 --- a/design-shotgun/SKILL.md +++ b/design-shotgun/SKILL.md @@ -129,9 +129,11 @@ else fi ~/.claude/skills/gstack/bin/gstack-timeline-log '{"skill":"design-shotgun","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & _HAS_ROUTING="no" -if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then - _HAS_ROUTING="yes" -fi +for _RF in CLAUDE.md AGENTS.md; do + if [ -f "$_RF" ] && grep -q "## Skill routing" "$_RF" 2>/dev/null; then + _HAS_ROUTING="yes" + fi +done _ROUTING_DECLINED=$(~/.claude/skills/gstack/bin/gstack-config get routing_declined 2>/dev/null || echo "false") echo "HAS_ROUTING: $_HAS_ROUTING" echo "ROUTING_DECLINED: $_ROUTING_DECLINED" diff --git a/devex-review/SKILL.md b/devex-review/SKILL.md index 1450b9bbb..766c38527 100644 --- a/devex-review/SKILL.md +++ b/devex-review/SKILL.md @@ -114,9 +114,11 @@ else fi ~/.claude/skills/gstack/bin/gstack-timeline-log '{"skill":"devex-review","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & _HAS_ROUTING="no" -if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then - _HAS_ROUTING="yes" -fi +for _RF in CLAUDE.md AGENTS.md; do + if [ -f "$_RF" ] && grep -q "## Skill routing" "$_RF" 2>/dev/null; then + _HAS_ROUTING="yes" + fi +done _ROUTING_DECLINED=$(~/.claude/skills/gstack/bin/gstack-config get routing_declined 2>/dev/null || echo "false") echo "HAS_ROUTING: $_HAS_ROUTING" echo "ROUTING_DECLINED: $_ROUTING_DECLINED" diff --git a/diagram/SKILL.md b/diagram/SKILL.md index c2d16b2fb..ae98dd629 100644 --- a/diagram/SKILL.md +++ b/diagram/SKILL.md @@ -109,9 +109,11 @@ else fi ~/.claude/skills/gstack/bin/gstack-timeline-log '{"skill":"diagram","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & _HAS_ROUTING="no" -if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then - _HAS_ROUTING="yes" -fi +for _RF in CLAUDE.md AGENTS.md; do + if [ -f "$_RF" ] && grep -q "## Skill routing" "$_RF" 2>/dev/null; then + _HAS_ROUTING="yes" + fi +done _ROUTING_DECLINED=$(~/.claude/skills/gstack/bin/gstack-config get routing_declined 2>/dev/null || echo "false") echo "HAS_ROUTING: $_HAS_ROUTING" echo "ROUTING_DECLINED: $_ROUTING_DECLINED" diff --git a/document-generate/SKILL.md b/document-generate/SKILL.md index 7d8b34bc0..c15065c6d 100644 --- a/document-generate/SKILL.md +++ b/document-generate/SKILL.md @@ -114,9 +114,11 @@ else fi ~/.claude/skills/gstack/bin/gstack-timeline-log '{"skill":"document-generate","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & _HAS_ROUTING="no" -if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then - _HAS_ROUTING="yes" -fi +for _RF in CLAUDE.md AGENTS.md; do + if [ -f "$_RF" ] && grep -q "## Skill routing" "$_RF" 2>/dev/null; then + _HAS_ROUTING="yes" + fi +done _ROUTING_DECLINED=$(~/.claude/skills/gstack/bin/gstack-config get routing_declined 2>/dev/null || echo "false") echo "HAS_ROUTING: $_HAS_ROUTING" echo "ROUTING_DECLINED: $_ROUTING_DECLINED" diff --git a/document-release/SKILL.md b/document-release/SKILL.md index a87ba0f18..5c5ec112a 100644 --- a/document-release/SKILL.md +++ b/document-release/SKILL.md @@ -112,9 +112,11 @@ else fi ~/.claude/skills/gstack/bin/gstack-timeline-log '{"skill":"document-release","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & _HAS_ROUTING="no" -if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then - _HAS_ROUTING="yes" -fi +for _RF in CLAUDE.md AGENTS.md; do + if [ -f "$_RF" ] && grep -q "## Skill routing" "$_RF" 2>/dev/null; then + _HAS_ROUTING="yes" + fi +done _ROUTING_DECLINED=$(~/.claude/skills/gstack/bin/gstack-config get routing_declined 2>/dev/null || echo "false") echo "HAS_ROUTING: $_HAS_ROUTING" echo "ROUTING_DECLINED: $_ROUTING_DECLINED" diff --git a/health/SKILL.md b/health/SKILL.md index 2466a83c5..e6eeb4609 100644 --- a/health/SKILL.md +++ b/health/SKILL.md @@ -110,9 +110,11 @@ else fi ~/.claude/skills/gstack/bin/gstack-timeline-log '{"skill":"health","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & _HAS_ROUTING="no" -if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then - _HAS_ROUTING="yes" -fi +for _RF in CLAUDE.md AGENTS.md; do + if [ -f "$_RF" ] && grep -q "## Skill routing" "$_RF" 2>/dev/null; then + _HAS_ROUTING="yes" + fi +done _ROUTING_DECLINED=$(~/.claude/skills/gstack/bin/gstack-config get routing_declined 2>/dev/null || echo "false") echo "HAS_ROUTING: $_HAS_ROUTING" echo "ROUTING_DECLINED: $_ROUTING_DECLINED" diff --git a/investigate/SKILL.md b/investigate/SKILL.md index 81b872d0c..0a13927cd 100644 --- a/investigate/SKILL.md +++ b/investigate/SKILL.md @@ -149,9 +149,11 @@ else fi ~/.claude/skills/gstack/bin/gstack-timeline-log '{"skill":"investigate","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & _HAS_ROUTING="no" -if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then - _HAS_ROUTING="yes" -fi +for _RF in CLAUDE.md AGENTS.md; do + if [ -f "$_RF" ] && grep -q "## Skill routing" "$_RF" 2>/dev/null; then + _HAS_ROUTING="yes" + fi +done _ROUTING_DECLINED=$(~/.claude/skills/gstack/bin/gstack-config get routing_declined 2>/dev/null || echo "false") echo "HAS_ROUTING: $_HAS_ROUTING" echo "ROUTING_DECLINED: $_ROUTING_DECLINED" diff --git a/ios-clean/SKILL.md b/ios-clean/SKILL.md index f5f3fdf81..9419c9e8d 100644 --- a/ios-clean/SKILL.md +++ b/ios-clean/SKILL.md @@ -112,9 +112,11 @@ else fi ~/.claude/skills/gstack/bin/gstack-timeline-log '{"skill":"ios-clean","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & _HAS_ROUTING="no" -if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then - _HAS_ROUTING="yes" -fi +for _RF in CLAUDE.md AGENTS.md; do + if [ -f "$_RF" ] && grep -q "## Skill routing" "$_RF" 2>/dev/null; then + _HAS_ROUTING="yes" + fi +done _ROUTING_DECLINED=$(~/.claude/skills/gstack/bin/gstack-config get routing_declined 2>/dev/null || echo "false") echo "HAS_ROUTING: $_HAS_ROUTING" echo "ROUTING_DECLINED: $_ROUTING_DECLINED" diff --git a/ios-design-review/SKILL.md b/ios-design-review/SKILL.md index 185a24c98..2be1456a5 100644 --- a/ios-design-review/SKILL.md +++ b/ios-design-review/SKILL.md @@ -114,9 +114,11 @@ else fi ~/.claude/skills/gstack/bin/gstack-timeline-log '{"skill":"ios-design-review","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & _HAS_ROUTING="no" -if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then - _HAS_ROUTING="yes" -fi +for _RF in CLAUDE.md AGENTS.md; do + if [ -f "$_RF" ] && grep -q "## Skill routing" "$_RF" 2>/dev/null; then + _HAS_ROUTING="yes" + fi +done _ROUTING_DECLINED=$(~/.claude/skills/gstack/bin/gstack-config get routing_declined 2>/dev/null || echo "false") echo "HAS_ROUTING: $_HAS_ROUTING" echo "ROUTING_DECLINED: $_ROUTING_DECLINED" diff --git a/ios-fix/SKILL.md b/ios-fix/SKILL.md index 989b0a6ac..1bd9ee48e 100644 --- a/ios-fix/SKILL.md +++ b/ios-fix/SKILL.md @@ -115,9 +115,11 @@ else fi ~/.claude/skills/gstack/bin/gstack-timeline-log '{"skill":"ios-fix","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & _HAS_ROUTING="no" -if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then - _HAS_ROUTING="yes" -fi +for _RF in CLAUDE.md AGENTS.md; do + if [ -f "$_RF" ] && grep -q "## Skill routing" "$_RF" 2>/dev/null; then + _HAS_ROUTING="yes" + fi +done _ROUTING_DECLINED=$(~/.claude/skills/gstack/bin/gstack-config get routing_declined 2>/dev/null || echo "false") echo "HAS_ROUTING: $_HAS_ROUTING" echo "ROUTING_DECLINED: $_ROUTING_DECLINED" diff --git a/ios-qa/SKILL.md b/ios-qa/SKILL.md index 72b02a7f6..61697af4b 100644 --- a/ios-qa/SKILL.md +++ b/ios-qa/SKILL.md @@ -118,9 +118,11 @@ else fi ~/.claude/skills/gstack/bin/gstack-timeline-log '{"skill":"ios-qa","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & _HAS_ROUTING="no" -if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then - _HAS_ROUTING="yes" -fi +for _RF in CLAUDE.md AGENTS.md; do + if [ -f "$_RF" ] && grep -q "## Skill routing" "$_RF" 2>/dev/null; then + _HAS_ROUTING="yes" + fi +done _ROUTING_DECLINED=$(~/.claude/skills/gstack/bin/gstack-config get routing_declined 2>/dev/null || echo "false") echo "HAS_ROUTING: $_HAS_ROUTING" echo "ROUTING_DECLINED: $_ROUTING_DECLINED" diff --git a/ios-sync/SKILL.md b/ios-sync/SKILL.md index 4fdc28866..432768345 100644 --- a/ios-sync/SKILL.md +++ b/ios-sync/SKILL.md @@ -112,9 +112,11 @@ else fi ~/.claude/skills/gstack/bin/gstack-timeline-log '{"skill":"ios-sync","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & _HAS_ROUTING="no" -if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then - _HAS_ROUTING="yes" -fi +for _RF in CLAUDE.md AGENTS.md; do + if [ -f "$_RF" ] && grep -q "## Skill routing" "$_RF" 2>/dev/null; then + _HAS_ROUTING="yes" + fi +done _ROUTING_DECLINED=$(~/.claude/skills/gstack/bin/gstack-config get routing_declined 2>/dev/null || echo "false") echo "HAS_ROUTING: $_HAS_ROUTING" echo "ROUTING_DECLINED: $_ROUTING_DECLINED" diff --git a/land-and-deploy/SKILL.md b/land-and-deploy/SKILL.md index 67813624a..7145ab656 100644 --- a/land-and-deploy/SKILL.md +++ b/land-and-deploy/SKILL.md @@ -107,9 +107,11 @@ else fi ~/.claude/skills/gstack/bin/gstack-timeline-log '{"skill":"land-and-deploy","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & _HAS_ROUTING="no" -if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then - _HAS_ROUTING="yes" -fi +for _RF in CLAUDE.md AGENTS.md; do + if [ -f "$_RF" ] && grep -q "## Skill routing" "$_RF" 2>/dev/null; then + _HAS_ROUTING="yes" + fi +done _ROUTING_DECLINED=$(~/.claude/skills/gstack/bin/gstack-config get routing_declined 2>/dev/null || echo "false") echo "HAS_ROUTING: $_HAS_ROUTING" echo "ROUTING_DECLINED: $_ROUTING_DECLINED" diff --git a/landing-report/SKILL.md b/landing-report/SKILL.md index 114e54210..6bf4f5220 100644 --- a/landing-report/SKILL.md +++ b/landing-report/SKILL.md @@ -109,9 +109,11 @@ else fi ~/.claude/skills/gstack/bin/gstack-timeline-log '{"skill":"landing-report","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & _HAS_ROUTING="no" -if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then - _HAS_ROUTING="yes" -fi +for _RF in CLAUDE.md AGENTS.md; do + if [ -f "$_RF" ] && grep -q "## Skill routing" "$_RF" 2>/dev/null; then + _HAS_ROUTING="yes" + fi +done _ROUTING_DECLINED=$(~/.claude/skills/gstack/bin/gstack-config get routing_declined 2>/dev/null || echo "false") echo "HAS_ROUTING: $_HAS_ROUTING" echo "ROUTING_DECLINED: $_ROUTING_DECLINED" diff --git a/learn/SKILL.md b/learn/SKILL.md index eccf8a3fd..77a708ef0 100644 --- a/learn/SKILL.md +++ b/learn/SKILL.md @@ -110,9 +110,11 @@ else fi ~/.claude/skills/gstack/bin/gstack-timeline-log '{"skill":"learn","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & _HAS_ROUTING="no" -if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then - _HAS_ROUTING="yes" -fi +for _RF in CLAUDE.md AGENTS.md; do + if [ -f "$_RF" ] && grep -q "## Skill routing" "$_RF" 2>/dev/null; then + _HAS_ROUTING="yes" + fi +done _ROUTING_DECLINED=$(~/.claude/skills/gstack/bin/gstack-config get routing_declined 2>/dev/null || echo "false") echo "HAS_ROUTING: $_HAS_ROUTING" echo "ROUTING_DECLINED: $_ROUTING_DECLINED" diff --git a/make-pdf/SKILL.md b/make-pdf/SKILL.md index 8ddfe5c51..9fbe62c8e 100644 --- a/make-pdf/SKILL.md +++ b/make-pdf/SKILL.md @@ -109,9 +109,11 @@ else fi ~/.claude/skills/gstack/bin/gstack-timeline-log '{"skill":"make-pdf","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & _HAS_ROUTING="no" -if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then - _HAS_ROUTING="yes" -fi +for _RF in CLAUDE.md AGENTS.md; do + if [ -f "$_RF" ] && grep -q "## Skill routing" "$_RF" 2>/dev/null; then + _HAS_ROUTING="yes" + fi +done _ROUTING_DECLINED=$(~/.claude/skills/gstack/bin/gstack-config get routing_declined 2>/dev/null || echo "false") echo "HAS_ROUTING: $_HAS_ROUTING" echo "ROUTING_DECLINED: $_ROUTING_DECLINED" diff --git a/office-hours/SKILL.md b/office-hours/SKILL.md index 2b4eff1f2..5286a6eec 100644 --- a/office-hours/SKILL.md +++ b/office-hours/SKILL.md @@ -145,9 +145,11 @@ else fi ~/.claude/skills/gstack/bin/gstack-timeline-log '{"skill":"office-hours","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & _HAS_ROUTING="no" -if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then - _HAS_ROUTING="yes" -fi +for _RF in CLAUDE.md AGENTS.md; do + if [ -f "$_RF" ] && grep -q "## Skill routing" "$_RF" 2>/dev/null; then + _HAS_ROUTING="yes" + fi +done _ROUTING_DECLINED=$(~/.claude/skills/gstack/bin/gstack-config get routing_declined 2>/dev/null || echo "false") echo "HAS_ROUTING: $_HAS_ROUTING" echo "ROUTING_DECLINED: $_ROUTING_DECLINED" diff --git a/open-gstack-browser/SKILL.md b/open-gstack-browser/SKILL.md index a1b98c3ca..956a748ef 100644 --- a/open-gstack-browser/SKILL.md +++ b/open-gstack-browser/SKILL.md @@ -108,9 +108,11 @@ else fi ~/.claude/skills/gstack/bin/gstack-timeline-log '{"skill":"open-gstack-browser","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & _HAS_ROUTING="no" -if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then - _HAS_ROUTING="yes" -fi +for _RF in CLAUDE.md AGENTS.md; do + if [ -f "$_RF" ] && grep -q "## Skill routing" "$_RF" 2>/dev/null; then + _HAS_ROUTING="yes" + fi +done _ROUTING_DECLINED=$(~/.claude/skills/gstack/bin/gstack-config get routing_declined 2>/dev/null || echo "false") echo "HAS_ROUTING: $_HAS_ROUTING" echo "ROUTING_DECLINED: $_ROUTING_DECLINED" diff --git a/pair-agent/SKILL.md b/pair-agent/SKILL.md index 2aa276d2d..d97aa99bc 100644 --- a/pair-agent/SKILL.md +++ b/pair-agent/SKILL.md @@ -110,9 +110,11 @@ else fi ~/.claude/skills/gstack/bin/gstack-timeline-log '{"skill":"pair-agent","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & _HAS_ROUTING="no" -if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then - _HAS_ROUTING="yes" -fi +for _RF in CLAUDE.md AGENTS.md; do + if [ -f "$_RF" ] && grep -q "## Skill routing" "$_RF" 2>/dev/null; then + _HAS_ROUTING="yes" + fi +done _ROUTING_DECLINED=$(~/.claude/skills/gstack/bin/gstack-config get routing_declined 2>/dev/null || echo "false") echo "HAS_ROUTING: $_HAS_ROUTING" echo "ROUTING_DECLINED: $_ROUTING_DECLINED" diff --git a/plan-ceo-review/SKILL.md b/plan-ceo-review/SKILL.md index 3c7607e0f..f2eb83529 100644 --- a/plan-ceo-review/SKILL.md +++ b/plan-ceo-review/SKILL.md @@ -139,9 +139,11 @@ else fi ~/.claude/skills/gstack/bin/gstack-timeline-log '{"skill":"plan-ceo-review","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & _HAS_ROUTING="no" -if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then - _HAS_ROUTING="yes" -fi +for _RF in CLAUDE.md AGENTS.md; do + if [ -f "$_RF" ] && grep -q "## Skill routing" "$_RF" 2>/dev/null; then + _HAS_ROUTING="yes" + fi +done _ROUTING_DECLINED=$(~/.claude/skills/gstack/bin/gstack-config get routing_declined 2>/dev/null || echo "false") echo "HAS_ROUTING: $_HAS_ROUTING" echo "ROUTING_DECLINED: $_ROUTING_DECLINED" diff --git a/plan-design-review/SKILL.md b/plan-design-review/SKILL.md index d7fb3a74a..2c493c2b5 100644 --- a/plan-design-review/SKILL.md +++ b/plan-design-review/SKILL.md @@ -111,9 +111,11 @@ else fi ~/.claude/skills/gstack/bin/gstack-timeline-log '{"skill":"plan-design-review","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & _HAS_ROUTING="no" -if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then - _HAS_ROUTING="yes" -fi +for _RF in CLAUDE.md AGENTS.md; do + if [ -f "$_RF" ] && grep -q "## Skill routing" "$_RF" 2>/dev/null; then + _HAS_ROUTING="yes" + fi +done _ROUTING_DECLINED=$(~/.claude/skills/gstack/bin/gstack-config get routing_declined 2>/dev/null || echo "false") echo "HAS_ROUTING: $_HAS_ROUTING" echo "ROUTING_DECLINED: $_ROUTING_DECLINED" diff --git a/plan-devex-review/SKILL.md b/plan-devex-review/SKILL.md index d80bfba77..1665c3113 100644 --- a/plan-devex-review/SKILL.md +++ b/plan-devex-review/SKILL.md @@ -117,9 +117,11 @@ else fi ~/.claude/skills/gstack/bin/gstack-timeline-log '{"skill":"plan-devex-review","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & _HAS_ROUTING="no" -if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then - _HAS_ROUTING="yes" -fi +for _RF in CLAUDE.md AGENTS.md; do + if [ -f "$_RF" ] && grep -q "## Skill routing" "$_RF" 2>/dev/null; then + _HAS_ROUTING="yes" + fi +done _ROUTING_DECLINED=$(~/.claude/skills/gstack/bin/gstack-config get routing_declined 2>/dev/null || echo "false") echo "HAS_ROUTING: $_HAS_ROUTING" echo "ROUTING_DECLINED: $_ROUTING_DECLINED" diff --git a/plan-eng-review/SKILL.md b/plan-eng-review/SKILL.md index d196dba7f..ad5f6f7d2 100644 --- a/plan-eng-review/SKILL.md +++ b/plan-eng-review/SKILL.md @@ -115,9 +115,11 @@ else fi ~/.claude/skills/gstack/bin/gstack-timeline-log '{"skill":"plan-eng-review","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & _HAS_ROUTING="no" -if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then - _HAS_ROUTING="yes" -fi +for _RF in CLAUDE.md AGENTS.md; do + if [ -f "$_RF" ] && grep -q "## Skill routing" "$_RF" 2>/dev/null; then + _HAS_ROUTING="yes" + fi +done _ROUTING_DECLINED=$(~/.claude/skills/gstack/bin/gstack-config get routing_declined 2>/dev/null || echo "false") echo "HAS_ROUTING: $_HAS_ROUTING" echo "ROUTING_DECLINED: $_ROUTING_DECLINED" diff --git a/plan-tune/SKILL.md b/plan-tune/SKILL.md index 2f1e265fb..91e6fbf7d 100644 --- a/plan-tune/SKILL.md +++ b/plan-tune/SKILL.md @@ -120,9 +120,11 @@ else fi ~/.claude/skills/gstack/bin/gstack-timeline-log '{"skill":"plan-tune","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & _HAS_ROUTING="no" -if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then - _HAS_ROUTING="yes" -fi +for _RF in CLAUDE.md AGENTS.md; do + if [ -f "$_RF" ] && grep -q "## Skill routing" "$_RF" 2>/dev/null; then + _HAS_ROUTING="yes" + fi +done _ROUTING_DECLINED=$(~/.claude/skills/gstack/bin/gstack-config get routing_declined 2>/dev/null || echo "false") echo "HAS_ROUTING: $_HAS_ROUTING" echo "ROUTING_DECLINED: $_ROUTING_DECLINED" diff --git a/qa-only/SKILL.md b/qa-only/SKILL.md index 3209628b7..1df889835 100644 --- a/qa-only/SKILL.md +++ b/qa-only/SKILL.md @@ -110,9 +110,11 @@ else fi ~/.claude/skills/gstack/bin/gstack-timeline-log '{"skill":"qa-only","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & _HAS_ROUTING="no" -if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then - _HAS_ROUTING="yes" -fi +for _RF in CLAUDE.md AGENTS.md; do + if [ -f "$_RF" ] && grep -q "## Skill routing" "$_RF" 2>/dev/null; then + _HAS_ROUTING="yes" + fi +done _ROUTING_DECLINED=$(~/.claude/skills/gstack/bin/gstack-config get routing_declined 2>/dev/null || echo "false") echo "HAS_ROUTING: $_HAS_ROUTING" echo "ROUTING_DECLINED: $_ROUTING_DECLINED" diff --git a/qa/SKILL.md b/qa/SKILL.md index 4fb7f86c2..2a5c13b13 100644 --- a/qa/SKILL.md +++ b/qa/SKILL.md @@ -116,9 +116,11 @@ else fi ~/.claude/skills/gstack/bin/gstack-timeline-log '{"skill":"qa","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & _HAS_ROUTING="no" -if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then - _HAS_ROUTING="yes" -fi +for _RF in CLAUDE.md AGENTS.md; do + if [ -f "$_RF" ] && grep -q "## Skill routing" "$_RF" 2>/dev/null; then + _HAS_ROUTING="yes" + fi +done _ROUTING_DECLINED=$(~/.claude/skills/gstack/bin/gstack-config get routing_declined 2>/dev/null || echo "false") echo "HAS_ROUTING: $_HAS_ROUTING" echo "ROUTING_DECLINED: $_ROUTING_DECLINED" diff --git a/retro/SKILL.md b/retro/SKILL.md index ef723d679..ef984308e 100644 --- a/retro/SKILL.md +++ b/retro/SKILL.md @@ -130,9 +130,11 @@ else fi ~/.claude/skills/gstack/bin/gstack-timeline-log '{"skill":"retro","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & _HAS_ROUTING="no" -if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then - _HAS_ROUTING="yes" -fi +for _RF in CLAUDE.md AGENTS.md; do + if [ -f "$_RF" ] && grep -q "## Skill routing" "$_RF" 2>/dev/null; then + _HAS_ROUTING="yes" + fi +done _ROUTING_DECLINED=$(~/.claude/skills/gstack/bin/gstack-config get routing_declined 2>/dev/null || echo "false") echo "HAS_ROUTING: $_HAS_ROUTING" echo "ROUTING_DECLINED: $_ROUTING_DECLINED" diff --git a/review/SKILL.md b/review/SKILL.md index 6099d2b91..a178f8f7c 100644 --- a/review/SKILL.md +++ b/review/SKILL.md @@ -112,9 +112,11 @@ else fi ~/.claude/skills/gstack/bin/gstack-timeline-log '{"skill":"review","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & _HAS_ROUTING="no" -if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then - _HAS_ROUTING="yes" -fi +for _RF in CLAUDE.md AGENTS.md; do + if [ -f "$_RF" ] && grep -q "## Skill routing" "$_RF" 2>/dev/null; then + _HAS_ROUTING="yes" + fi +done _ROUTING_DECLINED=$(~/.claude/skills/gstack/bin/gstack-config get routing_declined 2>/dev/null || echo "false") echo "HAS_ROUTING: $_HAS_ROUTING" echo "ROUTING_DECLINED: $_ROUTING_DECLINED" diff --git a/scrape/SKILL.md b/scrape/SKILL.md index 87d174fbf..1b202d66f 100644 --- a/scrape/SKILL.md +++ b/scrape/SKILL.md @@ -109,9 +109,11 @@ else fi ~/.claude/skills/gstack/bin/gstack-timeline-log '{"skill":"scrape","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & _HAS_ROUTING="no" -if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then - _HAS_ROUTING="yes" -fi +for _RF in CLAUDE.md AGENTS.md; do + if [ -f "$_RF" ] && grep -q "## Skill routing" "$_RF" 2>/dev/null; then + _HAS_ROUTING="yes" + fi +done _ROUTING_DECLINED=$(~/.claude/skills/gstack/bin/gstack-config get routing_declined 2>/dev/null || echo "false") echo "HAS_ROUTING: $_HAS_ROUTING" echo "ROUTING_DECLINED: $_ROUTING_DECLINED" diff --git a/scripts/resolvers/preamble/generate-preamble-bash.ts b/scripts/resolvers/preamble/generate-preamble-bash.ts index 13ef420ca..e133b5d76 100644 --- a/scripts/resolvers/preamble/generate-preamble-bash.ts +++ b/scripts/resolvers/preamble/generate-preamble-bash.ts @@ -96,9 +96,11 @@ else fi ${ctx.paths.binDir}/gstack-timeline-log '{"skill":"${ctx.skillName}","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & _HAS_ROUTING="no" -if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then - _HAS_ROUTING="yes" -fi +for _RF in CLAUDE.md AGENTS.md; do + if [ -f "$_RF" ] && grep -q "## Skill routing" "$_RF" 2>/dev/null; then + _HAS_ROUTING="yes" + fi +done _ROUTING_DECLINED=$(${ctx.paths.binDir}/gstack-config get routing_declined 2>/dev/null || echo "false") echo "HAS_ROUTING: $_HAS_ROUTING" echo "ROUTING_DECLINED: $_ROUTING_DECLINED" diff --git a/setup-browser-cookies/SKILL.md b/setup-browser-cookies/SKILL.md index 79f4d8809..57f831718 100644 --- a/setup-browser-cookies/SKILL.md +++ b/setup-browser-cookies/SKILL.md @@ -104,9 +104,11 @@ else fi ~/.claude/skills/gstack/bin/gstack-timeline-log '{"skill":"setup-browser-cookies","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & _HAS_ROUTING="no" -if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then - _HAS_ROUTING="yes" -fi +for _RF in CLAUDE.md AGENTS.md; do + if [ -f "$_RF" ] && grep -q "## Skill routing" "$_RF" 2>/dev/null; then + _HAS_ROUTING="yes" + fi +done _ROUTING_DECLINED=$(~/.claude/skills/gstack/bin/gstack-config get routing_declined 2>/dev/null || echo "false") echo "HAS_ROUTING: $_HAS_ROUTING" echo "ROUTING_DECLINED: $_ROUTING_DECLINED" diff --git a/setup-deploy/SKILL.md b/setup-deploy/SKILL.md index e4cb5b513..b4edcecb1 100644 --- a/setup-deploy/SKILL.md +++ b/setup-deploy/SKILL.md @@ -111,9 +111,11 @@ else fi ~/.claude/skills/gstack/bin/gstack-timeline-log '{"skill":"setup-deploy","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & _HAS_ROUTING="no" -if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then - _HAS_ROUTING="yes" -fi +for _RF in CLAUDE.md AGENTS.md; do + if [ -f "$_RF" ] && grep -q "## Skill routing" "$_RF" 2>/dev/null; then + _HAS_ROUTING="yes" + fi +done _ROUTING_DECLINED=$(~/.claude/skills/gstack/bin/gstack-config get routing_declined 2>/dev/null || echo "false") echo "HAS_ROUTING: $_HAS_ROUTING" echo "ROUTING_DECLINED: $_ROUTING_DECLINED" diff --git a/setup-gbrain/SKILL.md b/setup-gbrain/SKILL.md index 93a8cf4e1..91a2b4c24 100644 --- a/setup-gbrain/SKILL.md +++ b/setup-gbrain/SKILL.md @@ -110,9 +110,11 @@ else fi ~/.claude/skills/gstack/bin/gstack-timeline-log '{"skill":"setup-gbrain","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & _HAS_ROUTING="no" -if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then - _HAS_ROUTING="yes" -fi +for _RF in CLAUDE.md AGENTS.md; do + if [ -f "$_RF" ] && grep -q "## Skill routing" "$_RF" 2>/dev/null; then + _HAS_ROUTING="yes" + fi +done _ROUTING_DECLINED=$(~/.claude/skills/gstack/bin/gstack-config get routing_declined 2>/dev/null || echo "false") echo "HAS_ROUTING: $_HAS_ROUTING" echo "ROUTING_DECLINED: $_ROUTING_DECLINED" diff --git a/ship/SKILL.md b/ship/SKILL.md index 86340ae65..1a44b4dd3 100644 --- a/ship/SKILL.md +++ b/ship/SKILL.md @@ -112,9 +112,11 @@ else fi ~/.claude/skills/gstack/bin/gstack-timeline-log '{"skill":"ship","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & _HAS_ROUTING="no" -if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then - _HAS_ROUTING="yes" -fi +for _RF in CLAUDE.md AGENTS.md; do + if [ -f "$_RF" ] && grep -q "## Skill routing" "$_RF" 2>/dev/null; then + _HAS_ROUTING="yes" + fi +done _ROUTING_DECLINED=$(~/.claude/skills/gstack/bin/gstack-config get routing_declined 2>/dev/null || echo "false") echo "HAS_ROUTING: $_HAS_ROUTING" echo "ROUTING_DECLINED: $_ROUTING_DECLINED" diff --git a/skillify/SKILL.md b/skillify/SKILL.md index e2a73c4d3..0c85ad5af 100644 --- a/skillify/SKILL.md +++ b/skillify/SKILL.md @@ -109,9 +109,11 @@ else fi ~/.claude/skills/gstack/bin/gstack-timeline-log '{"skill":"skillify","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & _HAS_ROUTING="no" -if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then - _HAS_ROUTING="yes" -fi +for _RF in CLAUDE.md AGENTS.md; do + if [ -f "$_RF" ] && grep -q "## Skill routing" "$_RF" 2>/dev/null; then + _HAS_ROUTING="yes" + fi +done _ROUTING_DECLINED=$(~/.claude/skills/gstack/bin/gstack-config get routing_declined 2>/dev/null || echo "false") echo "HAS_ROUTING: $_HAS_ROUTING" echo "ROUTING_DECLINED: $_ROUTING_DECLINED" diff --git a/spec/SKILL.md b/spec/SKILL.md index d0c0c8a3a..309dfbff2 100644 --- a/spec/SKILL.md +++ b/spec/SKILL.md @@ -110,9 +110,11 @@ else fi ~/.claude/skills/gstack/bin/gstack-timeline-log '{"skill":"spec","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & _HAS_ROUTING="no" -if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then - _HAS_ROUTING="yes" -fi +for _RF in CLAUDE.md AGENTS.md; do + if [ -f "$_RF" ] && grep -q "## Skill routing" "$_RF" 2>/dev/null; then + _HAS_ROUTING="yes" + fi +done _ROUTING_DECLINED=$(~/.claude/skills/gstack/bin/gstack-config get routing_declined 2>/dev/null || echo "false") echo "HAS_ROUTING: $_HAS_ROUTING" echo "ROUTING_DECLINED: $_ROUTING_DECLINED" diff --git a/sync-gbrain/SKILL.md b/sync-gbrain/SKILL.md index 89abd243e..c7b995fb2 100644 --- a/sync-gbrain/SKILL.md +++ b/sync-gbrain/SKILL.md @@ -111,9 +111,11 @@ else fi ~/.claude/skills/gstack/bin/gstack-timeline-log '{"skill":"sync-gbrain","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & _HAS_ROUTING="no" -if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then - _HAS_ROUTING="yes" -fi +for _RF in CLAUDE.md AGENTS.md; do + if [ -f "$_RF" ] && grep -q "## Skill routing" "$_RF" 2>/dev/null; then + _HAS_ROUTING="yes" + fi +done _ROUTING_DECLINED=$(~/.claude/skills/gstack/bin/gstack-config get routing_declined 2>/dev/null || echo "false") echo "HAS_ROUTING: $_HAS_ROUTING" echo "ROUTING_DECLINED: $_ROUTING_DECLINED" diff --git a/test/fixtures/golden/claude-ship-SKILL.md b/test/fixtures/golden/claude-ship-SKILL.md index 86340ae65..1a44b4dd3 100644 --- a/test/fixtures/golden/claude-ship-SKILL.md +++ b/test/fixtures/golden/claude-ship-SKILL.md @@ -112,9 +112,11 @@ else fi ~/.claude/skills/gstack/bin/gstack-timeline-log '{"skill":"ship","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & _HAS_ROUTING="no" -if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then - _HAS_ROUTING="yes" -fi +for _RF in CLAUDE.md AGENTS.md; do + if [ -f "$_RF" ] && grep -q "## Skill routing" "$_RF" 2>/dev/null; then + _HAS_ROUTING="yes" + fi +done _ROUTING_DECLINED=$(~/.claude/skills/gstack/bin/gstack-config get routing_declined 2>/dev/null || echo "false") echo "HAS_ROUTING: $_HAS_ROUTING" echo "ROUTING_DECLINED: $_ROUTING_DECLINED" diff --git a/test/fixtures/golden/codex-ship-SKILL.md b/test/fixtures/golden/codex-ship-SKILL.md index 98b6a9ed9..4e3fcd5ce 100644 --- a/test/fixtures/golden/codex-ship-SKILL.md +++ b/test/fixtures/golden/codex-ship-SKILL.md @@ -98,9 +98,11 @@ else fi $GSTACK_BIN/gstack-timeline-log '{"skill":"ship","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & _HAS_ROUTING="no" -if [ -f AGENTS.md ] && grep -q "## Skill routing" AGENTS.md 2>/dev/null; then - _HAS_ROUTING="yes" -fi +for _RF in AGENTS.md AGENTS.md; do + if [ -f "$_RF" ] && grep -q "## Skill routing" "$_RF" 2>/dev/null; then + _HAS_ROUTING="yes" + fi +done _ROUTING_DECLINED=$($GSTACK_BIN/gstack-config get routing_declined 2>/dev/null || echo "false") echo "HAS_ROUTING: $_HAS_ROUTING" echo "ROUTING_DECLINED: $_ROUTING_DECLINED" diff --git a/test/fixtures/golden/factory-ship-SKILL.md b/test/fixtures/golden/factory-ship-SKILL.md index 94533d246..9d4b9943a 100644 --- a/test/fixtures/golden/factory-ship-SKILL.md +++ b/test/fixtures/golden/factory-ship-SKILL.md @@ -100,9 +100,11 @@ else fi $GSTACK_BIN/gstack-timeline-log '{"skill":"ship","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null & _HAS_ROUTING="no" -if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then - _HAS_ROUTING="yes" -fi +for _RF in CLAUDE.md AGENTS.md; do + if [ -f "$_RF" ] && grep -q "## Skill routing" "$_RF" 2>/dev/null; then + _HAS_ROUTING="yes" + fi +done _ROUTING_DECLINED=$($GSTACK_BIN/gstack-config get routing_declined 2>/dev/null || echo "false") echo "HAS_ROUTING: $_HAS_ROUTING" echo "ROUTING_DECLINED: $_ROUTING_DECLINED" diff --git a/test/routing-probe.test.ts b/test/routing-probe.test.ts new file mode 100644 index 000000000..fd5d13df3 --- /dev/null +++ b/test/routing-probe.test.ts @@ -0,0 +1,116 @@ +/** + * Routing probe + team-init install resolution — gate-tier tests (#2500). + * + * 1. The preamble's HAS_ROUTING probe must check AGENTS.md as well as + * CLAUDE.md. Non-Claude hosts (Codex, Cursor, generic harnesses) route + * skills via AGENTS.md — the cross-harness convention file. Before this + * fix, a repo with AGENTS.md routing but no CLAUDE.md reported + * HAS_ROUTING: no and got nagged to create CLAUDE.md. + * + * 2. gstack-team-init's required-mode enforcement (the CLAUDE.md + * verification snippet and the generated check-gstack.sh hook) must + * resolve the install root across GSTACK_ROOT + every host's global + * install location, never hardcode ~/.claude/skills/gstack. The drift + * test pins the probe list against the hosts registry so a new host + * can't silently fall out of team-mode enforcement. + * + * Re-derived from community PR #2500 by @gamerey43. + */ +import { describe, test, expect } from 'bun:test'; +import { execSync } from 'child_process'; +import * as fs from 'fs'; +import * as os from 'os'; +import * as path from 'path'; +import { HOST_PATHS } from '../scripts/resolvers/types'; +import type { TemplateContext } from '../scripts/resolvers/types'; +import { generatePreambleBash } from '../scripts/resolvers/preamble/generate-preamble-bash'; +import { ALL_HOST_CONFIGS } from '../hosts/index'; + +const ROOT = path.join(import.meta.dir, '..'); + +function makeCtx(host: 'claude' | 'codex'): TemplateContext { + return { + skillName: 'test-skill', + tmplPath: 'test.tmpl', + host, + paths: HOST_PATHS[host], + preambleTier: 2, + }; +} + +/** Extract the routing-probe block from the rendered preamble bash. */ +function extractRoutingProbe(rendered: string): string { + const start = rendered.indexOf('_HAS_ROUTING="no"'); + expect(start).toBeGreaterThan(-1); + const end = rendered.indexOf('done', start); + expect(end).toBeGreaterThan(start); + return rendered.slice(start, end + 'done'.length); +} + +describe('routing probe checks AGENTS.md too (#2500)', () => { + for (const host of ['claude', 'codex'] as const) { + test(`rendered preamble probes CLAUDE.md AND AGENTS.md (${host})`, () => { + const rendered = generatePreambleBash(makeCtx(host)); + const probe = extractRoutingProbe(rendered); + expect(probe).toContain('CLAUDE.md'); + expect(probe).toContain('AGENTS.md'); + }); + } + + test('live probe block: AGENTS.md-only repo reports HAS_ROUTING=yes', () => { + const rendered = generatePreambleBash(makeCtx('claude')); + const probe = extractRoutingProbe(rendered); + const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'routing-probe-')); + try { + fs.writeFileSync( + path.join(dir, 'AGENTS.md'), + '## Skill routing\n\n- Bugs → /investigate\n', + ); + const out = execSync( + `bash -c '${probe.replace(/'/g, `'\\''`)}\necho "HAS_ROUTING: $_HAS_ROUTING"'`, + { cwd: dir, encoding: 'utf-8' }, + ); + expect(out).toContain('HAS_ROUTING: yes'); + } finally { + fs.rmSync(dir, { recursive: true, force: true }); + } + }); + + test('live probe block: repo with neither file reports HAS_ROUTING=no', () => { + const rendered = generatePreambleBash(makeCtx('claude')); + const probe = extractRoutingProbe(rendered); + const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'routing-probe-')); + try { + const out = execSync( + `bash -c '${probe.replace(/'/g, `'\\''`)}\necho "HAS_ROUTING: $_HAS_ROUTING"'`, + { cwd: dir, encoding: 'utf-8' }, + ); + expect(out).toContain('HAS_ROUTING: no'); + } finally { + fs.rmSync(dir, { recursive: true, force: true }); + } + }); +}); + +describe('team-init resolves GSTACK_ROOT across every host (#2500)', () => { + const teamInit = fs.readFileSync(path.join(ROOT, 'bin', 'gstack-team-init'), 'utf-8'); + + test('probe list covers GSTACK_ROOT env + every registered host globalRoot + migrated repo', () => { + expect(teamInit).toContain('"${GSTACK_ROOT:-}"'); + for (const config of ALL_HOST_CONFIGS) { + expect(teamInit).toContain(`$HOME/${config.globalRoot}`); + } + expect(teamInit).toContain('$HOME/.gstack/repos/gstack'); + }); + + test('enforcement no longer hardcodes the Claude path as the only gate', () => { + expect(teamInit).not.toContain('test -d ~/.claude/skills/gstack/bin'); + expect(teamInit).not.toContain('if [ ! -d "$HOME/.claude/skills/gstack/bin" ]'); + }); + + test('generated hook blocks only when NO install root resolves', () => { + // The hook's block branch must gate on the resolved root being empty, + // not on any single hardcoded directory. + expect(teamInit).toContain('if [ -z "$_GSTACK_ROOT" ]; then'); + }); +});