mirror of https://github.com/garrytan/gstack.git
feat: composable skills — INVOKE_SKILL resolver + factoring infrastructure (v0.13.7.0) (#644)
* feat: add parameterized resolver support to gen-skill-docs
Extend the placeholder regex from {{WORD}} to {{WORD:arg1:arg2}},
enabling parameterized resolvers like {{INVOKE_SKILL:plan-ceo-review}}.
- Widen ResolverFn type to accept optional args?: string[]
- Update RESOLVERS record to use ResolverFn type
- Both replacement and unresolved-check regexes updated
- Fully backward compatible: existing {{WORD}} patterns unchanged
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add INVOKE_SKILL resolver for composable skill loading
New composition.ts resolver module that emits prose instructing Claude
to read another skill's SKILL.md and follow it, skipping preamble
sections. Supports optional skip= parameter for additional sections.
Usage: {{INVOKE_SKILL:plan-ceo-review}} or
{{INVOKE_SKILL:plan-ceo-review:skip=Outside Voice}}
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: use frontmatter name: for skill symlinks and Codex paths
Patch all 3 name-derivation paths to read name: from SKILL.md
frontmatter instead of relying solely on directory basenames.
This enables directory names that differ from invocation names
(e.g., run-tests/ directory with name: test).
- setup: link_claude_skill_dirs reads name: via grep, falls back to basename
- gen-skill-docs.ts: codexSkillName uses frontmatter name for Codex output paths
- gen-skill-docs.ts: moved frontmatter extraction before Codex path logic
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: extract CHANGELOG_WORKFLOW resolver from /ship
Move changelog generation logic into a reusable resolver. The resolver
is changelog-only (no version bump per Codex review recommendation).
Adds voice rules inline. /ship Step 5 now uses {{CHANGELOG_WORKFLOW}}.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor: use INVOKE_SKILL resolver for plan-ceo-review office-hours fallback
Replace inline skill loading prose (read file, skip sections) with
{{INVOKE_SKILL:office-hours}} in the mid-session detection path.
The BENEFITS_FROM prerequisite offer is unchanged (separate use case).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor: BENEFITS_FROM resolver delegates to INVOKE_SKILL
Eliminate duplicated skip-list logic by having generateBenefitsFrom
call generateInvokeSkill internally. The wrapper (AskUserQuestion,
design doc re-check) stays in BENEFITS_FROM. The loading instructions
(read file, skip sections, error handling) come from INVOKE_SKILL.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* test: add resolver tests for INVOKE_SKILL, CHANGELOG_WORKFLOW, parameterized args
12 new tests covering:
- INVOKE_SKILL: template placeholder, default skip list, error handling,
BENEFITS_FROM delegation
- CHANGELOG_WORKFLOW: content, cross-check, voice guidance, format
- Parameterized resolver infra: colon-separated args processing,
no unresolved placeholders across all generated SKILL.md files
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* chore: bump version and changelog (v0.13.7.0)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: journey routing tests — CLAUDE.md routing rules + stronger descriptions
Three journey E2E tests (ideation, ship, debug) were failing because
Claude answered directly instead of invoking the Skill tool. Root cause:
skill descriptions in system-reminder are too weak to override Claude's
default behavior for tasks it can handle natively.
Fix has two parts:
1. CLAUDE.md routing rules in test workdir — Claude weighs project-level
instructions higher than skill description metadata
2. "Proactively invoke" (not "suggest") in office-hours, investigate,
ship descriptions — reinforces the routing signal
10/10 journey tests now pass (was 7/10).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: one-time CLAUDE.md routing injection prompt
Add a preamble section that checks if the project's CLAUDE.md has
skill routing rules. If not (and user hasn't declined), asks once
via AskUserQuestion to inject a "## Skill routing" section.
Root cause: skill descriptions in system-reminder metadata are too
weak to reliably trigger proactive Skill tool invocation. CLAUDE.md
project instructions carry higher weight in Claude's decision making.
- Preamble bash checks for "## Skill routing" in CLAUDE.md
- Stores decline in gstack-config (routing_declined=true)
- Only asks once per project (HAS_ROUTING check + config check)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: annotated config file + routing injection tests
gstack-config now writes a documented header on first config creation
with every supported key explained (proactive, telemetry, auto_upgrade,
skill_prefix, routing_declined, codex_reviews, skip_eng_review, etc.).
Users can edit ~/.gstack/config.yaml directly, anytime.
Also fixes grep to use ^KEY: anchoring so commented header lines don't
shadow real config values.
Tests added:
- 7 new gstack-config tests (annotated header, no duplication, comment
safety, routing_declined get/set/reset)
- 6 new gen-skill-docs tests (preamble routing injection: bash checks,
config reads, AskUserQuestion, decline persistence, routing rules)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* chore: bump to v0.13.9.0, separate CHANGELOG from main's releases
Split our branch's changes into a new 0.13.9.0 entry instead of
jamming them into 0.13.7.0 which already landed on main as
"Community Wave."
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs: clarify branch-scoped VERSION/CHANGELOG after merging main
Add explicit rules: merging main doesn't mean adopting main's version.
Branch always gets its own entry on top with a higher version number.
Three-point checklist after every merge.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: put our 0.13.9.0 entry on top of CHANGELOG
Newest version goes on top. Our branch lands next, so our entry
must be above main's 0.13.8.0.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: restore missing 0.13.7.0 Community Wave entry
Accidentally dropped the 0.13.7.0 entry when reordering.
All entries now present: 0.13.9.0 > 0.13.8.0 > 0.13.7.0 > 0.13.6.0.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs: add CHANGELOG integrity check rule
After any edit that moves/adds/removes entries, grep for version
headers and verify no gaps or duplicates before committing.
Prevents accidentally dropping entries during reordering.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
3cda8deec9
commit
66c09644a7
23
CHANGELOG.md
23
CHANGELOG.md
|
|
@ -1,5 +1,28 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## [0.13.9.0] - 2026-03-29 — Composable Skills
|
||||||
|
|
||||||
|
Skills can now load other skills inline. Write `{{INVOKE_SKILL:office-hours}}` in a template and the generator emits the right "read file, skip preamble, follow instructions" prose automatically. Handles host-aware paths and customizable skip lists.
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- **`{{INVOKE_SKILL:skill-name}}` resolver.** Composable skill loading as a first-class resolver. Emits host-aware prose that tells Claude or Codex to read another skill's SKILL.md and follow it inline, skipping preamble sections. Supports optional `skip=` parameter for additional sections to skip.
|
||||||
|
- **Parameterized resolver support.** The placeholder regex now handles `{{NAME:arg1:arg2}}`, enabling resolvers that take arguments at generation time. Fully backward compatible with existing `{{NAME}}` patterns.
|
||||||
|
- **`{{CHANGELOG_WORKFLOW}}` resolver.** Changelog generation logic extracted from /ship into a reusable resolver. Includes voice guidance ("lead with what the user can now do") inline.
|
||||||
|
- **Frontmatter `name:` for skill registration.** Setup script and gen-skill-docs now read `name:` from SKILL.md frontmatter for symlink naming. Enables directory names that differ from invocation names (e.g., `run-tests/` directory registered as `/test`).
|
||||||
|
- **Proactive skill routing.** Skills now ask once to add routing rules to your project's CLAUDE.md. This makes Claude invoke the right skill automatically instead of answering directly. Your choice is remembered in `~/.gstack/config.yaml`.
|
||||||
|
- **Annotated config file.** `~/.gstack/config.yaml` now gets a documented header on first creation explaining every setting. Edit it anytime.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- **BENEFITS_FROM now delegates to INVOKE_SKILL.** Eliminated duplicated skip-list logic. The prerequisite offer wrapper stays in BENEFITS_FROM, but the actual "read and follow" instructions come from INVOKE_SKILL.
|
||||||
|
- **/plan-ceo-review mid-session fallback uses INVOKE_SKILL.** The "user can't articulate the problem, offer /office-hours" path now uses the composable resolver instead of inline prose.
|
||||||
|
- **Stronger routing language.** office-hours, investigate, and ship descriptions now say "Proactively invoke" instead of "Proactively suggest" for more reliable automatic skill invocation.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- **Config grep anchored to line start.** Commented header lines no longer shadow real config values.
|
||||||
|
|
||||||
## [0.13.8.0] - 2026-03-29 — Security Audit Round 2
|
## [0.13.8.0] - 2026-03-29 — Security Audit Round 2
|
||||||
|
|
||||||
Browse output is now wrapped in trust boundary markers so agents can tell page content from tool output. Markers are escape-proof. The Chrome extension validates message senders. CDP binds to localhost only. Bun installs use checksum verification.
|
Browse output is now wrapped in trust boundary markers so agents can tell page content from tool output. Markers are escape-proof. The Chrome extension validates message senders. CDP binds to localhost only. Bun installs use checksum verification.
|
||||||
|
|
|
||||||
17
CLAUDE.md
17
CLAUDE.md
|
|
@ -258,6 +258,23 @@ not what was already on main.
|
||||||
3. Does an existing entry on this branch already cover earlier work? (If yes, replace
|
3. Does an existing entry on this branch already cover earlier work? (If yes, replace
|
||||||
it with one unified entry for the final version.)
|
it with one unified entry for the final version.)
|
||||||
|
|
||||||
|
**Merging main does NOT mean adopting main's version.** When you merge origin/main into
|
||||||
|
a feature branch, main may bring new CHANGELOG entries and a higher VERSION. Your branch
|
||||||
|
still needs its OWN version bump on top. If main is at v0.13.8.0 and your branch adds
|
||||||
|
features, bump to v0.13.9.0 with a new entry. Never jam your changes into an entry that
|
||||||
|
already landed on main. Your entry goes on top because your branch lands next.
|
||||||
|
|
||||||
|
**After merging main, always check:**
|
||||||
|
- Does CHANGELOG have your branch's own entry separate from main's entries?
|
||||||
|
- Is VERSION higher than main's VERSION?
|
||||||
|
- Is your entry the topmost entry in CHANGELOG (above main's latest)?
|
||||||
|
If any answer is no, fix it before continuing.
|
||||||
|
|
||||||
|
**After any CHANGELOG edit that moves, adds, or removes entries,** immediately run
|
||||||
|
`grep "^## \[" CHANGELOG.md` and verify the full version sequence is contiguous
|
||||||
|
with no gaps or duplicates before committing. If a version is missing, the edit
|
||||||
|
broke something. Fix it before moving on.
|
||||||
|
|
||||||
CHANGELOG.md is **for users**, not contributors. Write it like product release notes:
|
CHANGELOG.md is **for users**, not contributors. Write it like product release notes:
|
||||||
|
|
||||||
- Lead with what the user can now **do** that they couldn't before. Sell the feature.
|
- Lead with what the user can now **do** that they couldn't before. Sell the feature.
|
||||||
|
|
|
||||||
102
SKILL.md
102
SKILL.md
|
|
@ -68,6 +68,14 @@ if [ -f "$_LEARN_FILE" ]; then
|
||||||
else
|
else
|
||||||
echo "LEARNINGS: 0"
|
echo "LEARNINGS: 0"
|
||||||
fi
|
fi
|
||||||
|
# Check if CLAUDE.md has routing rules
|
||||||
|
_HAS_ROUTING="no"
|
||||||
|
if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then
|
||||||
|
_HAS_ROUTING="yes"
|
||||||
|
fi
|
||||||
|
_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"
|
||||||
```
|
```
|
||||||
|
|
||||||
If `PROACTIVE` is `"false"`, do not proactively suggest gstack skills AND do not
|
If `PROACTIVE` is `"false"`, do not proactively suggest gstack skills AND do not
|
||||||
|
|
@ -149,6 +157,49 @@ touch ~/.gstack/.proactive-prompted
|
||||||
|
|
||||||
This only happens once. If `PROACTIVE_PROMPTED` is `yes`, skip this entirely.
|
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 CLAUDE.md file exists in the project root. If it does not exist, create it.
|
||||||
|
|
||||||
|
Use AskUserQuestion:
|
||||||
|
|
||||||
|
> gstack works best when your project's CLAUDE.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 CLAUDE.md (recommended)
|
||||||
|
- B) No thanks, I'll invoke skills manually
|
||||||
|
|
||||||
|
If A: Append this section to the end of CLAUDE.md:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
|
||||||
|
## Skill routing
|
||||||
|
|
||||||
|
When the user's request matches an available skill, ALWAYS invoke it using the Skill
|
||||||
|
tool as your FIRST action. Do NOT answer directly, do NOT use other tools first.
|
||||||
|
The skill has specialized workflows that produce better results than ad-hoc answers.
|
||||||
|
|
||||||
|
Key routing rules:
|
||||||
|
- Product ideas, "is this worth building", brainstorming → invoke office-hours
|
||||||
|
- Bugs, errors, "why is this broken", 500 errors → invoke investigate
|
||||||
|
- Ship, deploy, push, create PR → invoke ship
|
||||||
|
- QA, test the site, find bugs → invoke qa
|
||||||
|
- Code review, check my diff → invoke review
|
||||||
|
- Update docs after shipping → invoke document-release
|
||||||
|
- Weekly retro → invoke retro
|
||||||
|
- Design system, brand → invoke design-consultation
|
||||||
|
- Visual audit, design polish → invoke design-review
|
||||||
|
- Architecture review → invoke plan-eng-review
|
||||||
|
```
|
||||||
|
|
||||||
|
Then commit the change: `git add CLAUDE.md && git commit -m "chore: add gstack skill routing rules to CLAUDE.md"`
|
||||||
|
|
||||||
|
If B: run `~/.claude/skills/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.
|
||||||
|
|
||||||
## Voice
|
## Voice
|
||||||
|
|
||||||
**Tone:** direct, concrete, sharp, never corporate, never academic. Sound like a builder, not a consultant. Name the file, the function, the command. No filler, no throat-clearing.
|
**Tone:** direct, concrete, sharp, never corporate, never academic. Sound like a builder, not a consultant. Name the file, the function, the command. No filler, no throat-clearing.
|
||||||
|
|
@ -271,28 +322,37 @@ Then write a `## GSTACK REVIEW REPORT` section to the end of the plan file:
|
||||||
file you are allowed to edit in plan mode. The plan file review report is part of the
|
file you are allowed to edit in plan mode. The plan file review report is part of the
|
||||||
plan's living status.
|
plan's living status.
|
||||||
|
|
||||||
If `PROACTIVE` is `false`: do NOT proactively suggest other gstack skills during this session.
|
If `PROACTIVE` is `false`: do NOT proactively invoke or suggest other gstack skills during
|
||||||
Only run skills the user explicitly invokes. This preference persists across sessions via
|
this session. Only run skills the user explicitly invokes. This preference persists across
|
||||||
`gstack-config`.
|
sessions via `gstack-config`.
|
||||||
|
|
||||||
If `PROACTIVE` is `true` (default): suggest adjacent gstack skills when relevant to the
|
If `PROACTIVE` is `true` (default): **invoke the Skill tool** when the user's request
|
||||||
user's workflow stage:
|
matches a skill's purpose. Do NOT answer directly when a skill exists for the task.
|
||||||
- Brainstorming → /office-hours
|
Use the Skill tool to invoke it. The skill has specialized workflows, checklists, and
|
||||||
- Strategy → /plan-ceo-review
|
quality gates that produce better results than answering inline.
|
||||||
- Architecture → /plan-eng-review
|
|
||||||
- Design → /plan-design-review or /design-consultation
|
**Routing rules — when you see these patterns, INVOKE the skill via the Skill tool:**
|
||||||
- Auto-review → /autoplan
|
- User describes a new idea, asks "is this worth building", wants to brainstorm → invoke `/office-hours`
|
||||||
- Debugging → /investigate
|
- User asks about strategy, scope, ambition, "think bigger" → invoke `/plan-ceo-review`
|
||||||
- QA → /qa
|
- User asks to review architecture, lock in the plan → invoke `/plan-eng-review`
|
||||||
- Code review → /review
|
- User asks about design system, brand, visual identity → invoke `/design-consultation`
|
||||||
- Visual audit → /design-review
|
- User asks to review design of a plan → invoke `/plan-design-review`
|
||||||
- Shipping → /ship
|
- User wants all reviews done automatically → invoke `/autoplan`
|
||||||
- Docs → /document-release
|
- User reports a bug, error, broken behavior, asks "why is this broken" → invoke `/investigate`
|
||||||
- Retro → /retro
|
- User asks to test the site, find bugs, QA → invoke `/qa`
|
||||||
- Second opinion → /codex
|
- User asks to review code, check the diff, pre-landing review → invoke `/review`
|
||||||
- Prod safety → /careful or /guard
|
- User asks about visual polish, design audit of a live site → invoke `/design-review`
|
||||||
- Scoped edits → /freeze or /unfreeze
|
- User asks to ship, deploy, push, create a PR → invoke `/ship`
|
||||||
- Upgrades → /gstack-upgrade
|
- User asks to update docs after shipping → invoke `/document-release`
|
||||||
|
- User asks for a weekly retro, what did we ship → invoke `/retro`
|
||||||
|
- User asks for a second opinion, codex review → invoke `/codex`
|
||||||
|
- User asks for safety mode, careful mode → invoke `/careful` or `/guard`
|
||||||
|
- User asks to restrict edits to a directory → invoke `/freeze` or `/unfreeze`
|
||||||
|
- User asks to upgrade gstack → invoke `/gstack-upgrade`
|
||||||
|
|
||||||
|
**Do NOT answer the user's question directly when a matching skill exists.** The skill
|
||||||
|
provides a structured, multi-step workflow that is always better than an ad-hoc answer.
|
||||||
|
Invoke the skill first. If no skill matches, answer directly as usual.
|
||||||
|
|
||||||
If the user opts out of suggestions, run `gstack-config set proactive false`.
|
If the user opts out of suggestions, run `gstack-config set proactive false`.
|
||||||
If they opt back in, run `gstack-config set proactive true`.
|
If they opt back in, run `gstack-config set proactive true`.
|
||||||
|
|
|
||||||
|
|
@ -16,28 +16,37 @@ allowed-tools:
|
||||||
|
|
||||||
{{PREAMBLE}}
|
{{PREAMBLE}}
|
||||||
|
|
||||||
If `PROACTIVE` is `false`: do NOT proactively suggest other gstack skills during this session.
|
If `PROACTIVE` is `false`: do NOT proactively invoke or suggest other gstack skills during
|
||||||
Only run skills the user explicitly invokes. This preference persists across sessions via
|
this session. Only run skills the user explicitly invokes. This preference persists across
|
||||||
`gstack-config`.
|
sessions via `gstack-config`.
|
||||||
|
|
||||||
If `PROACTIVE` is `true` (default): suggest adjacent gstack skills when relevant to the
|
If `PROACTIVE` is `true` (default): **invoke the Skill tool** when the user's request
|
||||||
user's workflow stage:
|
matches a skill's purpose. Do NOT answer directly when a skill exists for the task.
|
||||||
- Brainstorming → /office-hours
|
Use the Skill tool to invoke it. The skill has specialized workflows, checklists, and
|
||||||
- Strategy → /plan-ceo-review
|
quality gates that produce better results than answering inline.
|
||||||
- Architecture → /plan-eng-review
|
|
||||||
- Design → /plan-design-review or /design-consultation
|
**Routing rules — when you see these patterns, INVOKE the skill via the Skill tool:**
|
||||||
- Auto-review → /autoplan
|
- User describes a new idea, asks "is this worth building", wants to brainstorm → invoke `/office-hours`
|
||||||
- Debugging → /investigate
|
- User asks about strategy, scope, ambition, "think bigger" → invoke `/plan-ceo-review`
|
||||||
- QA → /qa
|
- User asks to review architecture, lock in the plan → invoke `/plan-eng-review`
|
||||||
- Code review → /review
|
- User asks about design system, brand, visual identity → invoke `/design-consultation`
|
||||||
- Visual audit → /design-review
|
- User asks to review design of a plan → invoke `/plan-design-review`
|
||||||
- Shipping → /ship
|
- User wants all reviews done automatically → invoke `/autoplan`
|
||||||
- Docs → /document-release
|
- User reports a bug, error, broken behavior, asks "why is this broken" → invoke `/investigate`
|
||||||
- Retro → /retro
|
- User asks to test the site, find bugs, QA → invoke `/qa`
|
||||||
- Second opinion → /codex
|
- User asks to review code, check the diff, pre-landing review → invoke `/review`
|
||||||
- Prod safety → /careful or /guard
|
- User asks about visual polish, design audit of a live site → invoke `/design-review`
|
||||||
- Scoped edits → /freeze or /unfreeze
|
- User asks to ship, deploy, push, create a PR → invoke `/ship`
|
||||||
- Upgrades → /gstack-upgrade
|
- User asks to update docs after shipping → invoke `/document-release`
|
||||||
|
- User asks for a weekly retro, what did we ship → invoke `/retro`
|
||||||
|
- User asks for a second opinion, codex review → invoke `/codex`
|
||||||
|
- User asks for safety mode, careful mode → invoke `/careful` or `/guard`
|
||||||
|
- User asks to restrict edits to a directory → invoke `/freeze` or `/unfreeze`
|
||||||
|
- User asks to upgrade gstack → invoke `/gstack-upgrade`
|
||||||
|
|
||||||
|
**Do NOT answer the user's question directly when a matching skill exists.** The skill
|
||||||
|
provides a structured, multi-step workflow that is always better than an ad-hoc answer.
|
||||||
|
Invoke the skill first. If no skill matches, answer directly as usual.
|
||||||
|
|
||||||
If the user opts out of suggestions, run `gstack-config set proactive false`.
|
If the user opts out of suggestions, run `gstack-config set proactive false`.
|
||||||
If they opt back in, run `gstack-config set proactive true`.
|
If they opt back in, run `gstack-config set proactive true`.
|
||||||
|
|
|
||||||
|
|
@ -77,6 +77,14 @@ if [ -f "$_LEARN_FILE" ]; then
|
||||||
else
|
else
|
||||||
echo "LEARNINGS: 0"
|
echo "LEARNINGS: 0"
|
||||||
fi
|
fi
|
||||||
|
# Check if CLAUDE.md has routing rules
|
||||||
|
_HAS_ROUTING="no"
|
||||||
|
if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then
|
||||||
|
_HAS_ROUTING="yes"
|
||||||
|
fi
|
||||||
|
_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"
|
||||||
```
|
```
|
||||||
|
|
||||||
If `PROACTIVE` is `"false"`, do not proactively suggest gstack skills AND do not
|
If `PROACTIVE` is `"false"`, do not proactively suggest gstack skills AND do not
|
||||||
|
|
@ -158,6 +166,49 @@ touch ~/.gstack/.proactive-prompted
|
||||||
|
|
||||||
This only happens once. If `PROACTIVE_PROMPTED` is `yes`, skip this entirely.
|
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 CLAUDE.md file exists in the project root. If it does not exist, create it.
|
||||||
|
|
||||||
|
Use AskUserQuestion:
|
||||||
|
|
||||||
|
> gstack works best when your project's CLAUDE.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 CLAUDE.md (recommended)
|
||||||
|
- B) No thanks, I'll invoke skills manually
|
||||||
|
|
||||||
|
If A: Append this section to the end of CLAUDE.md:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
|
||||||
|
## Skill routing
|
||||||
|
|
||||||
|
When the user's request matches an available skill, ALWAYS invoke it using the Skill
|
||||||
|
tool as your FIRST action. Do NOT answer directly, do NOT use other tools first.
|
||||||
|
The skill has specialized workflows that produce better results than ad-hoc answers.
|
||||||
|
|
||||||
|
Key routing rules:
|
||||||
|
- Product ideas, "is this worth building", brainstorming → invoke office-hours
|
||||||
|
- Bugs, errors, "why is this broken", 500 errors → invoke investigate
|
||||||
|
- Ship, deploy, push, create PR → invoke ship
|
||||||
|
- QA, test the site, find bugs → invoke qa
|
||||||
|
- Code review, check my diff → invoke review
|
||||||
|
- Update docs after shipping → invoke document-release
|
||||||
|
- Weekly retro → invoke retro
|
||||||
|
- Design system, brand → invoke design-consultation
|
||||||
|
- Visual audit, design polish → invoke design-review
|
||||||
|
- Architecture review → invoke plan-eng-review
|
||||||
|
```
|
||||||
|
|
||||||
|
Then commit the change: `git add CLAUDE.md && git commit -m "chore: add gstack skill routing rules to CLAUDE.md"`
|
||||||
|
|
||||||
|
If B: run `~/.claude/skills/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.
|
||||||
|
|
||||||
## Voice
|
## Voice
|
||||||
|
|
||||||
You are GStack, an open source AI builder framework shaped by Garry Tan's product, startup, and engineering judgment. Encode how he thinks, not his biography.
|
You are GStack, an open source AI builder framework shaped by Garry Tan's product, startup, and engineering judgment. Encode how he thinks, not his biography.
|
||||||
|
|
@ -426,10 +477,11 @@ If they choose A:
|
||||||
Say: "Running /office-hours inline. Once the design doc is ready, I'll pick up
|
Say: "Running /office-hours inline. Once the design doc is ready, I'll pick up
|
||||||
the review right where we left off."
|
the review right where we left off."
|
||||||
|
|
||||||
Read the office-hours skill file from disk using the Read tool:
|
Read the `/office-hours` skill file at `~/.claude/skills/gstack/office-hours/SKILL.md` using the Read tool.
|
||||||
`~/.claude/skills/gstack/office-hours/SKILL.md`
|
|
||||||
|
|
||||||
Follow it inline, **skipping these sections** (already handled by the parent skill):
|
**If unreadable:** Skip with "Could not load /office-hours — skipping." and continue.
|
||||||
|
|
||||||
|
Follow its instructions from top to bottom, **skipping these sections** (already handled by the parent skill):
|
||||||
- Preamble (run first)
|
- Preamble (run first)
|
||||||
- AskUserQuestion Format
|
- AskUserQuestion Format
|
||||||
- Completeness Principle — Boil the Lake
|
- Completeness Principle — Boil the Lake
|
||||||
|
|
@ -437,9 +489,13 @@ Follow it inline, **skipping these sections** (already handled by the parent ski
|
||||||
- Contributor Mode
|
- Contributor Mode
|
||||||
- Completion Status Protocol
|
- Completion Status Protocol
|
||||||
- Telemetry (run last)
|
- Telemetry (run last)
|
||||||
|
- Step 0: Detect platform and base branch
|
||||||
|
- Review Readiness Dashboard
|
||||||
|
- Plan File Review Report
|
||||||
|
- Prerequisite Skill Offer
|
||||||
|
- Plan Status Footer
|
||||||
|
|
||||||
If the Read fails (file not found), say:
|
Execute every other section at full depth. When the loaded skill's instructions are complete, continue with the next step below.
|
||||||
"Could not load /office-hours — proceeding with standard review."
|
|
||||||
|
|
||||||
After /office-hours completes, re-run the design doc check:
|
After /office-hours completes, re-run the design doc check:
|
||||||
```bash
|
```bash
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,14 @@ if [ -f "$_LEARN_FILE" ]; then
|
||||||
else
|
else
|
||||||
echo "LEARNINGS: 0"
|
echo "LEARNINGS: 0"
|
||||||
fi
|
fi
|
||||||
|
# Check if CLAUDE.md has routing rules
|
||||||
|
_HAS_ROUTING="no"
|
||||||
|
if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then
|
||||||
|
_HAS_ROUTING="yes"
|
||||||
|
fi
|
||||||
|
_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"
|
||||||
```
|
```
|
||||||
|
|
||||||
If `PROACTIVE` is `"false"`, do not proactively suggest gstack skills AND do not
|
If `PROACTIVE` is `"false"`, do not proactively suggest gstack skills AND do not
|
||||||
|
|
@ -151,6 +159,49 @@ touch ~/.gstack/.proactive-prompted
|
||||||
|
|
||||||
This only happens once. If `PROACTIVE_PROMPTED` is `yes`, skip this entirely.
|
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 CLAUDE.md file exists in the project root. If it does not exist, create it.
|
||||||
|
|
||||||
|
Use AskUserQuestion:
|
||||||
|
|
||||||
|
> gstack works best when your project's CLAUDE.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 CLAUDE.md (recommended)
|
||||||
|
- B) No thanks, I'll invoke skills manually
|
||||||
|
|
||||||
|
If A: Append this section to the end of CLAUDE.md:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
|
||||||
|
## Skill routing
|
||||||
|
|
||||||
|
When the user's request matches an available skill, ALWAYS invoke it using the Skill
|
||||||
|
tool as your FIRST action. Do NOT answer directly, do NOT use other tools first.
|
||||||
|
The skill has specialized workflows that produce better results than ad-hoc answers.
|
||||||
|
|
||||||
|
Key routing rules:
|
||||||
|
- Product ideas, "is this worth building", brainstorming → invoke office-hours
|
||||||
|
- Bugs, errors, "why is this broken", 500 errors → invoke investigate
|
||||||
|
- Ship, deploy, push, create PR → invoke ship
|
||||||
|
- QA, test the site, find bugs → invoke qa
|
||||||
|
- Code review, check my diff → invoke review
|
||||||
|
- Update docs after shipping → invoke document-release
|
||||||
|
- Weekly retro → invoke retro
|
||||||
|
- Design system, brand → invoke design-consultation
|
||||||
|
- Visual audit, design polish → invoke design-review
|
||||||
|
- Architecture review → invoke plan-eng-review
|
||||||
|
```
|
||||||
|
|
||||||
|
Then commit the change: `git add CLAUDE.md && git commit -m "chore: add gstack skill routing rules to CLAUDE.md"`
|
||||||
|
|
||||||
|
If B: run `~/.claude/skills/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.
|
||||||
|
|
||||||
## Voice
|
## Voice
|
||||||
|
|
||||||
**Tone:** direct, concrete, sharp, never corporate, never academic. Sound like a builder, not a consultant. Name the file, the function, the command. No filler, no throat-clearing.
|
**Tone:** direct, concrete, sharp, never corporate, never academic. Sound like a builder, not a consultant. Name the file, the function, the command. No filler, no throat-clearing.
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,38 @@ set -euo pipefail
|
||||||
STATE_DIR="${GSTACK_STATE_DIR:-$HOME/.gstack}"
|
STATE_DIR="${GSTACK_STATE_DIR:-$HOME/.gstack}"
|
||||||
CONFIG_FILE="$STATE_DIR/config.yaml"
|
CONFIG_FILE="$STATE_DIR/config.yaml"
|
||||||
|
|
||||||
|
# Annotated header for new config files. Written once on first `set`.
|
||||||
|
CONFIG_HEADER='# gstack configuration — edit freely, changes take effect on next skill run.
|
||||||
|
# Docs: https://github.com/garrytan/gstack
|
||||||
|
#
|
||||||
|
# ─── Behavior ────────────────────────────────────────────────────────
|
||||||
|
# proactive: true # Auto-invoke skills when your request matches one.
|
||||||
|
# # Set to false to only run skills you type explicitly.
|
||||||
|
#
|
||||||
|
# routing_declined: false # Set to true to skip the CLAUDE.md routing injection
|
||||||
|
# # prompt. Set back to false to be asked again.
|
||||||
|
#
|
||||||
|
# ─── Telemetry ───────────────────────────────────────────────────────
|
||||||
|
# telemetry: anonymous # off | anonymous | community
|
||||||
|
# # off — no data sent, no local analytics
|
||||||
|
# # anonymous — counter only, no device ID
|
||||||
|
# # community — usage data + stable device ID
|
||||||
|
#
|
||||||
|
# ─── Updates ─────────────────────────────────────────────────────────
|
||||||
|
# auto_upgrade: false # true = silently upgrade on session start
|
||||||
|
# update_check: true # false = suppress version check notifications
|
||||||
|
#
|
||||||
|
# ─── Skill naming ────────────────────────────────────────────────────
|
||||||
|
# skill_prefix: false # true = namespace skills as /gstack-qa, /gstack-ship
|
||||||
|
# # false = short names /qa, /ship
|
||||||
|
#
|
||||||
|
# ─── Advanced ────────────────────────────────────────────────────────
|
||||||
|
# codex_reviews: enabled # disabled = skip Codex adversarial reviews in /ship
|
||||||
|
# gstack_contributor: false # true = file field reports when gstack misbehaves
|
||||||
|
# skip_eng_review: false # true = skip eng review gate in /ship (not recommended)
|
||||||
|
#
|
||||||
|
'
|
||||||
|
|
||||||
case "${1:-}" in
|
case "${1:-}" in
|
||||||
get)
|
get)
|
||||||
KEY="${2:?Usage: gstack-config get <key>}"
|
KEY="${2:?Usage: gstack-config get <key>}"
|
||||||
|
|
@ -21,7 +53,7 @@ case "${1:-}" in
|
||||||
echo "Error: key must contain only alphanumeric characters and underscores" >&2
|
echo "Error: key must contain only alphanumeric characters and underscores" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
grep -F "${KEY}:" "$CONFIG_FILE" 2>/dev/null | tail -1 | awk '{print $2}' | tr -d '[:space:]' || true
|
grep -E "^${KEY}:" "$CONFIG_FILE" 2>/dev/null | tail -1 | awk '{print $2}' | tr -d '[:space:]' || true
|
||||||
;;
|
;;
|
||||||
set)
|
set)
|
||||||
KEY="${2:?Usage: gstack-config set <key> <value>}"
|
KEY="${2:?Usage: gstack-config set <key> <value>}"
|
||||||
|
|
@ -32,12 +64,16 @@ case "${1:-}" in
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
mkdir -p "$STATE_DIR"
|
mkdir -p "$STATE_DIR"
|
||||||
|
# Write annotated header on first creation
|
||||||
|
if [ ! -f "$CONFIG_FILE" ]; then
|
||||||
|
printf '%s' "$CONFIG_HEADER" > "$CONFIG_FILE"
|
||||||
|
fi
|
||||||
# Escape sed special chars in value and drop embedded newlines
|
# Escape sed special chars in value and drop embedded newlines
|
||||||
ESC_VALUE="$(printf '%s' "$VALUE" | head -1 | sed 's/[&/\]/\\&/g')"
|
ESC_VALUE="$(printf '%s' "$VALUE" | head -1 | sed 's/[&/\]/\\&/g')"
|
||||||
if grep -qF "${KEY}:" "$CONFIG_FILE" 2>/dev/null; then
|
if grep -qE "^${KEY}:" "$CONFIG_FILE" 2>/dev/null; then
|
||||||
# Portable in-place edit (BSD sed uses -i '', GNU sed uses -i without arg)
|
# Portable in-place edit (BSD sed uses -i '', GNU sed uses -i without arg)
|
||||||
_tmpfile="$(mktemp "${CONFIG_FILE}.XXXXXX")"
|
_tmpfile="$(mktemp "${CONFIG_FILE}.XXXXXX")"
|
||||||
sed "s/^${KEY}:.*/${KEY}: ${ESC_VALUE}/" "$CONFIG_FILE" > "$_tmpfile" && mv "$_tmpfile" "$CONFIG_FILE"
|
sed "/^${KEY}:/s/.*/${KEY}: ${ESC_VALUE}/" "$CONFIG_FILE" > "$_tmpfile" && mv "$_tmpfile" "$CONFIG_FILE"
|
||||||
else
|
else
|
||||||
echo "${KEY}: ${VALUE}" >> "$CONFIG_FILE"
|
echo "${KEY}: ${VALUE}" >> "$CONFIG_FILE"
|
||||||
fi
|
fi
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,14 @@ if [ -f "$_LEARN_FILE" ]; then
|
||||||
else
|
else
|
||||||
echo "LEARNINGS: 0"
|
echo "LEARNINGS: 0"
|
||||||
fi
|
fi
|
||||||
|
# Check if CLAUDE.md has routing rules
|
||||||
|
_HAS_ROUTING="no"
|
||||||
|
if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then
|
||||||
|
_HAS_ROUTING="yes"
|
||||||
|
fi
|
||||||
|
_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"
|
||||||
```
|
```
|
||||||
|
|
||||||
If `PROACTIVE` is `"false"`, do not proactively suggest gstack skills AND do not
|
If `PROACTIVE` is `"false"`, do not proactively suggest gstack skills AND do not
|
||||||
|
|
@ -151,6 +159,49 @@ touch ~/.gstack/.proactive-prompted
|
||||||
|
|
||||||
This only happens once. If `PROACTIVE_PROMPTED` is `yes`, skip this entirely.
|
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 CLAUDE.md file exists in the project root. If it does not exist, create it.
|
||||||
|
|
||||||
|
Use AskUserQuestion:
|
||||||
|
|
||||||
|
> gstack works best when your project's CLAUDE.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 CLAUDE.md (recommended)
|
||||||
|
- B) No thanks, I'll invoke skills manually
|
||||||
|
|
||||||
|
If A: Append this section to the end of CLAUDE.md:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
|
||||||
|
## Skill routing
|
||||||
|
|
||||||
|
When the user's request matches an available skill, ALWAYS invoke it using the Skill
|
||||||
|
tool as your FIRST action. Do NOT answer directly, do NOT use other tools first.
|
||||||
|
The skill has specialized workflows that produce better results than ad-hoc answers.
|
||||||
|
|
||||||
|
Key routing rules:
|
||||||
|
- Product ideas, "is this worth building", brainstorming → invoke office-hours
|
||||||
|
- Bugs, errors, "why is this broken", 500 errors → invoke investigate
|
||||||
|
- Ship, deploy, push, create PR → invoke ship
|
||||||
|
- QA, test the site, find bugs → invoke qa
|
||||||
|
- Code review, check my diff → invoke review
|
||||||
|
- Update docs after shipping → invoke document-release
|
||||||
|
- Weekly retro → invoke retro
|
||||||
|
- Design system, brand → invoke design-consultation
|
||||||
|
- Visual audit, design polish → invoke design-review
|
||||||
|
- Architecture review → invoke plan-eng-review
|
||||||
|
```
|
||||||
|
|
||||||
|
Then commit the change: `git add CLAUDE.md && git commit -m "chore: add gstack skill routing rules to CLAUDE.md"`
|
||||||
|
|
||||||
|
If B: run `~/.claude/skills/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.
|
||||||
|
|
||||||
## Voice
|
## Voice
|
||||||
|
|
||||||
**Tone:** direct, concrete, sharp, never corporate, never academic. Sound like a builder, not a consultant. Name the file, the function, the command. No filler, no throat-clearing.
|
**Tone:** direct, concrete, sharp, never corporate, never academic. Sound like a builder, not a consultant. Name the file, the function, the command. No filler, no throat-clearing.
|
||||||
|
|
|
||||||
|
|
@ -135,4 +135,62 @@ describe('gstack-config', () => {
|
||||||
const { stdout } = run(['get', 'test_special']);
|
const { stdout } = run(['get', 'test_special']);
|
||||||
expect(stdout).toBe('a/b&c\\d');
|
expect(stdout).toBe('a/b&c\\d');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ─── annotated header ──────────────────────────────────────
|
||||||
|
test('first set writes annotated header with docs', () => {
|
||||||
|
run(['set', 'telemetry', 'off']);
|
||||||
|
const content = readFileSync(join(stateDir, 'config.yaml'), 'utf-8');
|
||||||
|
expect(content).toContain('# gstack configuration');
|
||||||
|
expect(content).toContain('edit freely');
|
||||||
|
expect(content).toContain('proactive:');
|
||||||
|
expect(content).toContain('telemetry:');
|
||||||
|
expect(content).toContain('auto_upgrade:');
|
||||||
|
expect(content).toContain('skill_prefix:');
|
||||||
|
expect(content).toContain('routing_declined:');
|
||||||
|
expect(content).toContain('codex_reviews:');
|
||||||
|
expect(content).toContain('skip_eng_review:');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('header written only once, not duplicated on second set', () => {
|
||||||
|
run(['set', 'foo', 'bar']);
|
||||||
|
run(['set', 'baz', 'qux']);
|
||||||
|
const content = readFileSync(join(stateDir, 'config.yaml'), 'utf-8');
|
||||||
|
const headerCount = (content.match(/# gstack configuration/g) || []).length;
|
||||||
|
expect(headerCount).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('header does not break get on commented-out keys', () => {
|
||||||
|
run(['set', 'telemetry', 'community']);
|
||||||
|
// Header contains "# telemetry: anonymous" as a comment example.
|
||||||
|
// get should return the real value, not the comment.
|
||||||
|
const { stdout } = run(['get', 'telemetry']);
|
||||||
|
expect(stdout).toBe('community');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('existing config file is not overwritten with header', () => {
|
||||||
|
writeFileSync(join(stateDir, 'config.yaml'), 'existing: value\n');
|
||||||
|
run(['set', 'new_key', 'new_value']);
|
||||||
|
const content = readFileSync(join(stateDir, 'config.yaml'), 'utf-8');
|
||||||
|
expect(content).toContain('existing: value');
|
||||||
|
expect(content).not.toContain('# gstack configuration');
|
||||||
|
});
|
||||||
|
|
||||||
|
// ─── routing_declined ──────────────────────────────────────
|
||||||
|
test('routing_declined defaults to empty (not set)', () => {
|
||||||
|
const { stdout } = run(['get', 'routing_declined']);
|
||||||
|
expect(stdout).toBe('');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('routing_declined can be set and read', () => {
|
||||||
|
run(['set', 'routing_declined', 'true']);
|
||||||
|
const { stdout } = run(['get', 'routing_declined']);
|
||||||
|
expect(stdout).toBe('true');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('routing_declined can be reset to false', () => {
|
||||||
|
run(['set', 'routing_declined', 'true']);
|
||||||
|
run(['set', 'routing_declined', 'false']);
|
||||||
|
const { stdout } = run(['get', 'routing_declined']);
|
||||||
|
expect(stdout).toBe('false');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,14 @@ if [ -f "$_LEARN_FILE" ]; then
|
||||||
else
|
else
|
||||||
echo "LEARNINGS: 0"
|
echo "LEARNINGS: 0"
|
||||||
fi
|
fi
|
||||||
|
# Check if CLAUDE.md has routing rules
|
||||||
|
_HAS_ROUTING="no"
|
||||||
|
if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then
|
||||||
|
_HAS_ROUTING="yes"
|
||||||
|
fi
|
||||||
|
_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"
|
||||||
```
|
```
|
||||||
|
|
||||||
If `PROACTIVE` is `"false"`, do not proactively suggest gstack skills AND do not
|
If `PROACTIVE` is `"false"`, do not proactively suggest gstack skills AND do not
|
||||||
|
|
@ -151,6 +159,49 @@ touch ~/.gstack/.proactive-prompted
|
||||||
|
|
||||||
This only happens once. If `PROACTIVE_PROMPTED` is `yes`, skip this entirely.
|
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 CLAUDE.md file exists in the project root. If it does not exist, create it.
|
||||||
|
|
||||||
|
Use AskUserQuestion:
|
||||||
|
|
||||||
|
> gstack works best when your project's CLAUDE.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 CLAUDE.md (recommended)
|
||||||
|
- B) No thanks, I'll invoke skills manually
|
||||||
|
|
||||||
|
If A: Append this section to the end of CLAUDE.md:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
|
||||||
|
## Skill routing
|
||||||
|
|
||||||
|
When the user's request matches an available skill, ALWAYS invoke it using the Skill
|
||||||
|
tool as your FIRST action. Do NOT answer directly, do NOT use other tools first.
|
||||||
|
The skill has specialized workflows that produce better results than ad-hoc answers.
|
||||||
|
|
||||||
|
Key routing rules:
|
||||||
|
- Product ideas, "is this worth building", brainstorming → invoke office-hours
|
||||||
|
- Bugs, errors, "why is this broken", 500 errors → invoke investigate
|
||||||
|
- Ship, deploy, push, create PR → invoke ship
|
||||||
|
- QA, test the site, find bugs → invoke qa
|
||||||
|
- Code review, check my diff → invoke review
|
||||||
|
- Update docs after shipping → invoke document-release
|
||||||
|
- Weekly retro → invoke retro
|
||||||
|
- Design system, brand → invoke design-consultation
|
||||||
|
- Visual audit, design polish → invoke design-review
|
||||||
|
- Architecture review → invoke plan-eng-review
|
||||||
|
```
|
||||||
|
|
||||||
|
Then commit the change: `git add CLAUDE.md && git commit -m "chore: add gstack skill routing rules to CLAUDE.md"`
|
||||||
|
|
||||||
|
If B: run `~/.claude/skills/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.
|
||||||
|
|
||||||
## Voice
|
## Voice
|
||||||
|
|
||||||
You are GStack, an open source AI builder framework shaped by Garry Tan's product, startup, and engineering judgment. Encode how he thinks, not his biography.
|
You are GStack, an open source AI builder framework shaped by Garry Tan's product, startup, and engineering judgment. Encode how he thinks, not his biography.
|
||||||
|
|
|
||||||
|
|
@ -71,6 +71,14 @@ if [ -f "$_LEARN_FILE" ]; then
|
||||||
else
|
else
|
||||||
echo "LEARNINGS: 0"
|
echo "LEARNINGS: 0"
|
||||||
fi
|
fi
|
||||||
|
# Check if CLAUDE.md has routing rules
|
||||||
|
_HAS_ROUTING="no"
|
||||||
|
if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then
|
||||||
|
_HAS_ROUTING="yes"
|
||||||
|
fi
|
||||||
|
_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"
|
||||||
```
|
```
|
||||||
|
|
||||||
If `PROACTIVE` is `"false"`, do not proactively suggest gstack skills AND do not
|
If `PROACTIVE` is `"false"`, do not proactively suggest gstack skills AND do not
|
||||||
|
|
@ -152,6 +160,49 @@ touch ~/.gstack/.proactive-prompted
|
||||||
|
|
||||||
This only happens once. If `PROACTIVE_PROMPTED` is `yes`, skip this entirely.
|
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 CLAUDE.md file exists in the project root. If it does not exist, create it.
|
||||||
|
|
||||||
|
Use AskUserQuestion:
|
||||||
|
|
||||||
|
> gstack works best when your project's CLAUDE.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 CLAUDE.md (recommended)
|
||||||
|
- B) No thanks, I'll invoke skills manually
|
||||||
|
|
||||||
|
If A: Append this section to the end of CLAUDE.md:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
|
||||||
|
## Skill routing
|
||||||
|
|
||||||
|
When the user's request matches an available skill, ALWAYS invoke it using the Skill
|
||||||
|
tool as your FIRST action. Do NOT answer directly, do NOT use other tools first.
|
||||||
|
The skill has specialized workflows that produce better results than ad-hoc answers.
|
||||||
|
|
||||||
|
Key routing rules:
|
||||||
|
- Product ideas, "is this worth building", brainstorming → invoke office-hours
|
||||||
|
- Bugs, errors, "why is this broken", 500 errors → invoke investigate
|
||||||
|
- Ship, deploy, push, create PR → invoke ship
|
||||||
|
- QA, test the site, find bugs → invoke qa
|
||||||
|
- Code review, check my diff → invoke review
|
||||||
|
- Update docs after shipping → invoke document-release
|
||||||
|
- Weekly retro → invoke retro
|
||||||
|
- Design system, brand → invoke design-consultation
|
||||||
|
- Visual audit, design polish → invoke design-review
|
||||||
|
- Architecture review → invoke plan-eng-review
|
||||||
|
```
|
||||||
|
|
||||||
|
Then commit the change: `git add CLAUDE.md && git commit -m "chore: add gstack skill routing rules to CLAUDE.md"`
|
||||||
|
|
||||||
|
If B: run `~/.claude/skills/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.
|
||||||
|
|
||||||
## Voice
|
## Voice
|
||||||
|
|
||||||
You are GStack, an open source AI builder framework shaped by Garry Tan's product, startup, and engineering judgment. Encode how he thinks, not his biography.
|
You are GStack, an open source AI builder framework shaped by Garry Tan's product, startup, and engineering judgment. Encode how he thinks, not his biography.
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,14 @@ if [ -f "$_LEARN_FILE" ]; then
|
||||||
else
|
else
|
||||||
echo "LEARNINGS: 0"
|
echo "LEARNINGS: 0"
|
||||||
fi
|
fi
|
||||||
|
# Check if CLAUDE.md has routing rules
|
||||||
|
_HAS_ROUTING="no"
|
||||||
|
if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then
|
||||||
|
_HAS_ROUTING="yes"
|
||||||
|
fi
|
||||||
|
_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"
|
||||||
```
|
```
|
||||||
|
|
||||||
If `PROACTIVE` is `"false"`, do not proactively suggest gstack skills AND do not
|
If `PROACTIVE` is `"false"`, do not proactively suggest gstack skills AND do not
|
||||||
|
|
@ -149,6 +157,49 @@ touch ~/.gstack/.proactive-prompted
|
||||||
|
|
||||||
This only happens once. If `PROACTIVE_PROMPTED` is `yes`, skip this entirely.
|
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 CLAUDE.md file exists in the project root. If it does not exist, create it.
|
||||||
|
|
||||||
|
Use AskUserQuestion:
|
||||||
|
|
||||||
|
> gstack works best when your project's CLAUDE.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 CLAUDE.md (recommended)
|
||||||
|
- B) No thanks, I'll invoke skills manually
|
||||||
|
|
||||||
|
If A: Append this section to the end of CLAUDE.md:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
|
||||||
|
## Skill routing
|
||||||
|
|
||||||
|
When the user's request matches an available skill, ALWAYS invoke it using the Skill
|
||||||
|
tool as your FIRST action. Do NOT answer directly, do NOT use other tools first.
|
||||||
|
The skill has specialized workflows that produce better results than ad-hoc answers.
|
||||||
|
|
||||||
|
Key routing rules:
|
||||||
|
- Product ideas, "is this worth building", brainstorming → invoke office-hours
|
||||||
|
- Bugs, errors, "why is this broken", 500 errors → invoke investigate
|
||||||
|
- Ship, deploy, push, create PR → invoke ship
|
||||||
|
- QA, test the site, find bugs → invoke qa
|
||||||
|
- Code review, check my diff → invoke review
|
||||||
|
- Update docs after shipping → invoke document-release
|
||||||
|
- Weekly retro → invoke retro
|
||||||
|
- Design system, brand → invoke design-consultation
|
||||||
|
- Visual audit, design polish → invoke design-review
|
||||||
|
- Architecture review → invoke plan-eng-review
|
||||||
|
```
|
||||||
|
|
||||||
|
Then commit the change: `git add CLAUDE.md && git commit -m "chore: add gstack skill routing rules to CLAUDE.md"`
|
||||||
|
|
||||||
|
If B: run `~/.claude/skills/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.
|
||||||
|
|
||||||
## Voice
|
## Voice
|
||||||
|
|
||||||
You are GStack, an open source AI builder framework shaped by Garry Tan's product, startup, and engineering judgment. Encode how he thinks, not his biography.
|
You are GStack, an open source AI builder framework shaped by Garry Tan's product, startup, and engineering judgment. Encode how he thinks, not his biography.
|
||||||
|
|
|
||||||
51
cso/SKILL.md
51
cso/SKILL.md
|
|
@ -74,6 +74,14 @@ if [ -f "$_LEARN_FILE" ]; then
|
||||||
else
|
else
|
||||||
echo "LEARNINGS: 0"
|
echo "LEARNINGS: 0"
|
||||||
fi
|
fi
|
||||||
|
# Check if CLAUDE.md has routing rules
|
||||||
|
_HAS_ROUTING="no"
|
||||||
|
if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then
|
||||||
|
_HAS_ROUTING="yes"
|
||||||
|
fi
|
||||||
|
_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"
|
||||||
```
|
```
|
||||||
|
|
||||||
If `PROACTIVE` is `"false"`, do not proactively suggest gstack skills AND do not
|
If `PROACTIVE` is `"false"`, do not proactively suggest gstack skills AND do not
|
||||||
|
|
@ -155,6 +163,49 @@ touch ~/.gstack/.proactive-prompted
|
||||||
|
|
||||||
This only happens once. If `PROACTIVE_PROMPTED` is `yes`, skip this entirely.
|
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 CLAUDE.md file exists in the project root. If it does not exist, create it.
|
||||||
|
|
||||||
|
Use AskUserQuestion:
|
||||||
|
|
||||||
|
> gstack works best when your project's CLAUDE.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 CLAUDE.md (recommended)
|
||||||
|
- B) No thanks, I'll invoke skills manually
|
||||||
|
|
||||||
|
If A: Append this section to the end of CLAUDE.md:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
|
||||||
|
## Skill routing
|
||||||
|
|
||||||
|
When the user's request matches an available skill, ALWAYS invoke it using the Skill
|
||||||
|
tool as your FIRST action. Do NOT answer directly, do NOT use other tools first.
|
||||||
|
The skill has specialized workflows that produce better results than ad-hoc answers.
|
||||||
|
|
||||||
|
Key routing rules:
|
||||||
|
- Product ideas, "is this worth building", brainstorming → invoke office-hours
|
||||||
|
- Bugs, errors, "why is this broken", 500 errors → invoke investigate
|
||||||
|
- Ship, deploy, push, create PR → invoke ship
|
||||||
|
- QA, test the site, find bugs → invoke qa
|
||||||
|
- Code review, check my diff → invoke review
|
||||||
|
- Update docs after shipping → invoke document-release
|
||||||
|
- Weekly retro → invoke retro
|
||||||
|
- Design system, brand → invoke design-consultation
|
||||||
|
- Visual audit, design polish → invoke design-review
|
||||||
|
- Architecture review → invoke plan-eng-review
|
||||||
|
```
|
||||||
|
|
||||||
|
Then commit the change: `git add CLAUDE.md && git commit -m "chore: add gstack skill routing rules to CLAUDE.md"`
|
||||||
|
|
||||||
|
If B: run `~/.claude/skills/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.
|
||||||
|
|
||||||
## Voice
|
## Voice
|
||||||
|
|
||||||
You are GStack, an open source AI builder framework shaped by Garry Tan's product, startup, and engineering judgment. Encode how he thinks, not his biography.
|
You are GStack, an open source AI builder framework shaped by Garry Tan's product, startup, and engineering judgment. Encode how he thinks, not his biography.
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,14 @@ if [ -f "$_LEARN_FILE" ]; then
|
||||||
else
|
else
|
||||||
echo "LEARNINGS: 0"
|
echo "LEARNINGS: 0"
|
||||||
fi
|
fi
|
||||||
|
# Check if CLAUDE.md has routing rules
|
||||||
|
_HAS_ROUTING="no"
|
||||||
|
if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then
|
||||||
|
_HAS_ROUTING="yes"
|
||||||
|
fi
|
||||||
|
_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"
|
||||||
```
|
```
|
||||||
|
|
||||||
If `PROACTIVE` is `"false"`, do not proactively suggest gstack skills AND do not
|
If `PROACTIVE` is `"false"`, do not proactively suggest gstack skills AND do not
|
||||||
|
|
@ -156,6 +164,49 @@ touch ~/.gstack/.proactive-prompted
|
||||||
|
|
||||||
This only happens once. If `PROACTIVE_PROMPTED` is `yes`, skip this entirely.
|
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 CLAUDE.md file exists in the project root. If it does not exist, create it.
|
||||||
|
|
||||||
|
Use AskUserQuestion:
|
||||||
|
|
||||||
|
> gstack works best when your project's CLAUDE.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 CLAUDE.md (recommended)
|
||||||
|
- B) No thanks, I'll invoke skills manually
|
||||||
|
|
||||||
|
If A: Append this section to the end of CLAUDE.md:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
|
||||||
|
## Skill routing
|
||||||
|
|
||||||
|
When the user's request matches an available skill, ALWAYS invoke it using the Skill
|
||||||
|
tool as your FIRST action. Do NOT answer directly, do NOT use other tools first.
|
||||||
|
The skill has specialized workflows that produce better results than ad-hoc answers.
|
||||||
|
|
||||||
|
Key routing rules:
|
||||||
|
- Product ideas, "is this worth building", brainstorming → invoke office-hours
|
||||||
|
- Bugs, errors, "why is this broken", 500 errors → invoke investigate
|
||||||
|
- Ship, deploy, push, create PR → invoke ship
|
||||||
|
- QA, test the site, find bugs → invoke qa
|
||||||
|
- Code review, check my diff → invoke review
|
||||||
|
- Update docs after shipping → invoke document-release
|
||||||
|
- Weekly retro → invoke retro
|
||||||
|
- Design system, brand → invoke design-consultation
|
||||||
|
- Visual audit, design polish → invoke design-review
|
||||||
|
- Architecture review → invoke plan-eng-review
|
||||||
|
```
|
||||||
|
|
||||||
|
Then commit the change: `git add CLAUDE.md && git commit -m "chore: add gstack skill routing rules to CLAUDE.md"`
|
||||||
|
|
||||||
|
If B: run `~/.claude/skills/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.
|
||||||
|
|
||||||
## Voice
|
## Voice
|
||||||
|
|
||||||
You are GStack, an open source AI builder framework shaped by Garry Tan's product, startup, and engineering judgment. Encode how he thinks, not his biography.
|
You are GStack, an open source AI builder framework shaped by Garry Tan's product, startup, and engineering judgment. Encode how he thinks, not his biography.
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,14 @@ if [ -f "$_LEARN_FILE" ]; then
|
||||||
else
|
else
|
||||||
echo "LEARNINGS: 0"
|
echo "LEARNINGS: 0"
|
||||||
fi
|
fi
|
||||||
|
# Check if CLAUDE.md has routing rules
|
||||||
|
_HAS_ROUTING="no"
|
||||||
|
if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then
|
||||||
|
_HAS_ROUTING="yes"
|
||||||
|
fi
|
||||||
|
_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"
|
||||||
```
|
```
|
||||||
|
|
||||||
If `PROACTIVE` is `"false"`, do not proactively suggest gstack skills AND do not
|
If `PROACTIVE` is `"false"`, do not proactively suggest gstack skills AND do not
|
||||||
|
|
@ -156,6 +164,49 @@ touch ~/.gstack/.proactive-prompted
|
||||||
|
|
||||||
This only happens once. If `PROACTIVE_PROMPTED` is `yes`, skip this entirely.
|
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 CLAUDE.md file exists in the project root. If it does not exist, create it.
|
||||||
|
|
||||||
|
Use AskUserQuestion:
|
||||||
|
|
||||||
|
> gstack works best when your project's CLAUDE.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 CLAUDE.md (recommended)
|
||||||
|
- B) No thanks, I'll invoke skills manually
|
||||||
|
|
||||||
|
If A: Append this section to the end of CLAUDE.md:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
|
||||||
|
## Skill routing
|
||||||
|
|
||||||
|
When the user's request matches an available skill, ALWAYS invoke it using the Skill
|
||||||
|
tool as your FIRST action. Do NOT answer directly, do NOT use other tools first.
|
||||||
|
The skill has specialized workflows that produce better results than ad-hoc answers.
|
||||||
|
|
||||||
|
Key routing rules:
|
||||||
|
- Product ideas, "is this worth building", brainstorming → invoke office-hours
|
||||||
|
- Bugs, errors, "why is this broken", 500 errors → invoke investigate
|
||||||
|
- Ship, deploy, push, create PR → invoke ship
|
||||||
|
- QA, test the site, find bugs → invoke qa
|
||||||
|
- Code review, check my diff → invoke review
|
||||||
|
- Update docs after shipping → invoke document-release
|
||||||
|
- Weekly retro → invoke retro
|
||||||
|
- Design system, brand → invoke design-consultation
|
||||||
|
- Visual audit, design polish → invoke design-review
|
||||||
|
- Architecture review → invoke plan-eng-review
|
||||||
|
```
|
||||||
|
|
||||||
|
Then commit the change: `git add CLAUDE.md && git commit -m "chore: add gstack skill routing rules to CLAUDE.md"`
|
||||||
|
|
||||||
|
If B: run `~/.claude/skills/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.
|
||||||
|
|
||||||
## Voice
|
## Voice
|
||||||
|
|
||||||
You are GStack, an open source AI builder framework shaped by Garry Tan's product, startup, and engineering judgment. Encode how he thinks, not his biography.
|
You are GStack, an open source AI builder framework shaped by Garry Tan's product, startup, and engineering judgment. Encode how he thinks, not his biography.
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,14 @@ if [ -f "$_LEARN_FILE" ]; then
|
||||||
else
|
else
|
||||||
echo "LEARNINGS: 0"
|
echo "LEARNINGS: 0"
|
||||||
fi
|
fi
|
||||||
|
# Check if CLAUDE.md has routing rules
|
||||||
|
_HAS_ROUTING="no"
|
||||||
|
if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then
|
||||||
|
_HAS_ROUTING="yes"
|
||||||
|
fi
|
||||||
|
_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"
|
||||||
```
|
```
|
||||||
|
|
||||||
If `PROACTIVE` is `"false"`, do not proactively suggest gstack skills AND do not
|
If `PROACTIVE` is `"false"`, do not proactively suggest gstack skills AND do not
|
||||||
|
|
@ -153,6 +161,49 @@ touch ~/.gstack/.proactive-prompted
|
||||||
|
|
||||||
This only happens once. If `PROACTIVE_PROMPTED` is `yes`, skip this entirely.
|
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 CLAUDE.md file exists in the project root. If it does not exist, create it.
|
||||||
|
|
||||||
|
Use AskUserQuestion:
|
||||||
|
|
||||||
|
> gstack works best when your project's CLAUDE.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 CLAUDE.md (recommended)
|
||||||
|
- B) No thanks, I'll invoke skills manually
|
||||||
|
|
||||||
|
If A: Append this section to the end of CLAUDE.md:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
|
||||||
|
## Skill routing
|
||||||
|
|
||||||
|
When the user's request matches an available skill, ALWAYS invoke it using the Skill
|
||||||
|
tool as your FIRST action. Do NOT answer directly, do NOT use other tools first.
|
||||||
|
The skill has specialized workflows that produce better results than ad-hoc answers.
|
||||||
|
|
||||||
|
Key routing rules:
|
||||||
|
- Product ideas, "is this worth building", brainstorming → invoke office-hours
|
||||||
|
- Bugs, errors, "why is this broken", 500 errors → invoke investigate
|
||||||
|
- Ship, deploy, push, create PR → invoke ship
|
||||||
|
- QA, test the site, find bugs → invoke qa
|
||||||
|
- Code review, check my diff → invoke review
|
||||||
|
- Update docs after shipping → invoke document-release
|
||||||
|
- Weekly retro → invoke retro
|
||||||
|
- Design system, brand → invoke design-consultation
|
||||||
|
- Visual audit, design polish → invoke design-review
|
||||||
|
- Architecture review → invoke plan-eng-review
|
||||||
|
```
|
||||||
|
|
||||||
|
Then commit the change: `git add CLAUDE.md && git commit -m "chore: add gstack skill routing rules to CLAUDE.md"`
|
||||||
|
|
||||||
|
If B: run `~/.claude/skills/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.
|
||||||
|
|
||||||
## Voice
|
## Voice
|
||||||
|
|
||||||
You are GStack, an open source AI builder framework shaped by Garry Tan's product, startup, and engineering judgment. Encode how he thinks, not his biography.
|
You are GStack, an open source AI builder framework shaped by Garry Tan's product, startup, and engineering judgment. Encode how he thinks, not his biography.
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,14 @@ if [ -f "$_LEARN_FILE" ]; then
|
||||||
else
|
else
|
||||||
echo "LEARNINGS: 0"
|
echo "LEARNINGS: 0"
|
||||||
fi
|
fi
|
||||||
|
# Check if CLAUDE.md has routing rules
|
||||||
|
_HAS_ROUTING="no"
|
||||||
|
if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then
|
||||||
|
_HAS_ROUTING="yes"
|
||||||
|
fi
|
||||||
|
_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"
|
||||||
```
|
```
|
||||||
|
|
||||||
If `PROACTIVE` is `"false"`, do not proactively suggest gstack skills AND do not
|
If `PROACTIVE` is `"false"`, do not proactively suggest gstack skills AND do not
|
||||||
|
|
@ -153,6 +161,49 @@ touch ~/.gstack/.proactive-prompted
|
||||||
|
|
||||||
This only happens once. If `PROACTIVE_PROMPTED` is `yes`, skip this entirely.
|
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 CLAUDE.md file exists in the project root. If it does not exist, create it.
|
||||||
|
|
||||||
|
Use AskUserQuestion:
|
||||||
|
|
||||||
|
> gstack works best when your project's CLAUDE.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 CLAUDE.md (recommended)
|
||||||
|
- B) No thanks, I'll invoke skills manually
|
||||||
|
|
||||||
|
If A: Append this section to the end of CLAUDE.md:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
|
||||||
|
## Skill routing
|
||||||
|
|
||||||
|
When the user's request matches an available skill, ALWAYS invoke it using the Skill
|
||||||
|
tool as your FIRST action. Do NOT answer directly, do NOT use other tools first.
|
||||||
|
The skill has specialized workflows that produce better results than ad-hoc answers.
|
||||||
|
|
||||||
|
Key routing rules:
|
||||||
|
- Product ideas, "is this worth building", brainstorming → invoke office-hours
|
||||||
|
- Bugs, errors, "why is this broken", 500 errors → invoke investigate
|
||||||
|
- Ship, deploy, push, create PR → invoke ship
|
||||||
|
- QA, test the site, find bugs → invoke qa
|
||||||
|
- Code review, check my diff → invoke review
|
||||||
|
- Update docs after shipping → invoke document-release
|
||||||
|
- Weekly retro → invoke retro
|
||||||
|
- Design system, brand → invoke design-consultation
|
||||||
|
- Visual audit, design polish → invoke design-review
|
||||||
|
- Architecture review → invoke plan-eng-review
|
||||||
|
```
|
||||||
|
|
||||||
|
Then commit the change: `git add CLAUDE.md && git commit -m "chore: add gstack skill routing rules to CLAUDE.md"`
|
||||||
|
|
||||||
|
If B: run `~/.claude/skills/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.
|
||||||
|
|
||||||
## Voice
|
## Voice
|
||||||
|
|
||||||
You are GStack, an open source AI builder framework shaped by Garry Tan's product, startup, and engineering judgment. Encode how he thinks, not his biography.
|
You are GStack, an open source AI builder framework shaped by Garry Tan's product, startup, and engineering judgment. Encode how he thinks, not his biography.
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,9 @@ description: |
|
||||||
analyze, hypothesize, implement. Iron Law: no fixes without root cause.
|
analyze, hypothesize, implement. Iron Law: no fixes without root cause.
|
||||||
Use when asked to "debug this", "fix this bug", "why is this broken",
|
Use when asked to "debug this", "fix this bug", "why is this broken",
|
||||||
"investigate this error", or "root cause analysis".
|
"investigate this error", or "root cause analysis".
|
||||||
Proactively suggest when the user reports errors, unexpected behavior, or
|
Proactively invoke this skill (do NOT debug directly) when the user reports
|
||||||
is troubleshooting why something stopped working. (gstack)
|
errors, 500 errors, stack traces, unexpected behavior, "it was working
|
||||||
|
yesterday", or is troubleshooting why something stopped working. (gstack)
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
- Read
|
- Read
|
||||||
|
|
@ -86,6 +87,14 @@ if [ -f "$_LEARN_FILE" ]; then
|
||||||
else
|
else
|
||||||
echo "LEARNINGS: 0"
|
echo "LEARNINGS: 0"
|
||||||
fi
|
fi
|
||||||
|
# Check if CLAUDE.md has routing rules
|
||||||
|
_HAS_ROUTING="no"
|
||||||
|
if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then
|
||||||
|
_HAS_ROUTING="yes"
|
||||||
|
fi
|
||||||
|
_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"
|
||||||
```
|
```
|
||||||
|
|
||||||
If `PROACTIVE` is `"false"`, do not proactively suggest gstack skills AND do not
|
If `PROACTIVE` is `"false"`, do not proactively suggest gstack skills AND do not
|
||||||
|
|
@ -167,6 +176,49 @@ touch ~/.gstack/.proactive-prompted
|
||||||
|
|
||||||
This only happens once. If `PROACTIVE_PROMPTED` is `yes`, skip this entirely.
|
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 CLAUDE.md file exists in the project root. If it does not exist, create it.
|
||||||
|
|
||||||
|
Use AskUserQuestion:
|
||||||
|
|
||||||
|
> gstack works best when your project's CLAUDE.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 CLAUDE.md (recommended)
|
||||||
|
- B) No thanks, I'll invoke skills manually
|
||||||
|
|
||||||
|
If A: Append this section to the end of CLAUDE.md:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
|
||||||
|
## Skill routing
|
||||||
|
|
||||||
|
When the user's request matches an available skill, ALWAYS invoke it using the Skill
|
||||||
|
tool as your FIRST action. Do NOT answer directly, do NOT use other tools first.
|
||||||
|
The skill has specialized workflows that produce better results than ad-hoc answers.
|
||||||
|
|
||||||
|
Key routing rules:
|
||||||
|
- Product ideas, "is this worth building", brainstorming → invoke office-hours
|
||||||
|
- Bugs, errors, "why is this broken", 500 errors → invoke investigate
|
||||||
|
- Ship, deploy, push, create PR → invoke ship
|
||||||
|
- QA, test the site, find bugs → invoke qa
|
||||||
|
- Code review, check my diff → invoke review
|
||||||
|
- Update docs after shipping → invoke document-release
|
||||||
|
- Weekly retro → invoke retro
|
||||||
|
- Design system, brand → invoke design-consultation
|
||||||
|
- Visual audit, design polish → invoke design-review
|
||||||
|
- Architecture review → invoke plan-eng-review
|
||||||
|
```
|
||||||
|
|
||||||
|
Then commit the change: `git add CLAUDE.md && git commit -m "chore: add gstack skill routing rules to CLAUDE.md"`
|
||||||
|
|
||||||
|
If B: run `~/.claude/skills/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.
|
||||||
|
|
||||||
## Voice
|
## Voice
|
||||||
|
|
||||||
You are GStack, an open source AI builder framework shaped by Garry Tan's product, startup, and engineering judgment. Encode how he thinks, not his biography.
|
You are GStack, an open source AI builder framework shaped by Garry Tan's product, startup, and engineering judgment. Encode how he thinks, not his biography.
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,9 @@ description: |
|
||||||
analyze, hypothesize, implement. Iron Law: no fixes without root cause.
|
analyze, hypothesize, implement. Iron Law: no fixes without root cause.
|
||||||
Use when asked to "debug this", "fix this bug", "why is this broken",
|
Use when asked to "debug this", "fix this bug", "why is this broken",
|
||||||
"investigate this error", or "root cause analysis".
|
"investigate this error", or "root cause analysis".
|
||||||
Proactively suggest when the user reports errors, unexpected behavior, or
|
Proactively invoke this skill (do NOT debug directly) when the user reports
|
||||||
is troubleshooting why something stopped working. (gstack)
|
errors, 500 errors, stack traces, unexpected behavior, "it was working
|
||||||
|
yesterday", or is troubleshooting why something stopped working. (gstack)
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
- Read
|
- Read
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,14 @@ if [ -f "$_LEARN_FILE" ]; then
|
||||||
else
|
else
|
||||||
echo "LEARNINGS: 0"
|
echo "LEARNINGS: 0"
|
||||||
fi
|
fi
|
||||||
|
# Check if CLAUDE.md has routing rules
|
||||||
|
_HAS_ROUTING="no"
|
||||||
|
if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then
|
||||||
|
_HAS_ROUTING="yes"
|
||||||
|
fi
|
||||||
|
_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"
|
||||||
```
|
```
|
||||||
|
|
||||||
If `PROACTIVE` is `"false"`, do not proactively suggest gstack skills AND do not
|
If `PROACTIVE` is `"false"`, do not proactively suggest gstack skills AND do not
|
||||||
|
|
@ -150,6 +158,49 @@ touch ~/.gstack/.proactive-prompted
|
||||||
|
|
||||||
This only happens once. If `PROACTIVE_PROMPTED` is `yes`, skip this entirely.
|
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 CLAUDE.md file exists in the project root. If it does not exist, create it.
|
||||||
|
|
||||||
|
Use AskUserQuestion:
|
||||||
|
|
||||||
|
> gstack works best when your project's CLAUDE.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 CLAUDE.md (recommended)
|
||||||
|
- B) No thanks, I'll invoke skills manually
|
||||||
|
|
||||||
|
If A: Append this section to the end of CLAUDE.md:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
|
||||||
|
## Skill routing
|
||||||
|
|
||||||
|
When the user's request matches an available skill, ALWAYS invoke it using the Skill
|
||||||
|
tool as your FIRST action. Do NOT answer directly, do NOT use other tools first.
|
||||||
|
The skill has specialized workflows that produce better results than ad-hoc answers.
|
||||||
|
|
||||||
|
Key routing rules:
|
||||||
|
- Product ideas, "is this worth building", brainstorming → invoke office-hours
|
||||||
|
- Bugs, errors, "why is this broken", 500 errors → invoke investigate
|
||||||
|
- Ship, deploy, push, create PR → invoke ship
|
||||||
|
- QA, test the site, find bugs → invoke qa
|
||||||
|
- Code review, check my diff → invoke review
|
||||||
|
- Update docs after shipping → invoke document-release
|
||||||
|
- Weekly retro → invoke retro
|
||||||
|
- Design system, brand → invoke design-consultation
|
||||||
|
- Visual audit, design polish → invoke design-review
|
||||||
|
- Architecture review → invoke plan-eng-review
|
||||||
|
```
|
||||||
|
|
||||||
|
Then commit the change: `git add CLAUDE.md && git commit -m "chore: add gstack skill routing rules to CLAUDE.md"`
|
||||||
|
|
||||||
|
If B: run `~/.claude/skills/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.
|
||||||
|
|
||||||
## Voice
|
## Voice
|
||||||
|
|
||||||
You are GStack, an open source AI builder framework shaped by Garry Tan's product, startup, and engineering judgment. Encode how he thinks, not his biography.
|
You are GStack, an open source AI builder framework shaped by Garry Tan's product, startup, and engineering judgment. Encode how he thinks, not his biography.
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,14 @@ if [ -f "$_LEARN_FILE" ]; then
|
||||||
else
|
else
|
||||||
echo "LEARNINGS: 0"
|
echo "LEARNINGS: 0"
|
||||||
fi
|
fi
|
||||||
|
# Check if CLAUDE.md has routing rules
|
||||||
|
_HAS_ROUTING="no"
|
||||||
|
if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then
|
||||||
|
_HAS_ROUTING="yes"
|
||||||
|
fi
|
||||||
|
_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"
|
||||||
```
|
```
|
||||||
|
|
||||||
If `PROACTIVE` is `"false"`, do not proactively suggest gstack skills AND do not
|
If `PROACTIVE` is `"false"`, do not proactively suggest gstack skills AND do not
|
||||||
|
|
@ -153,6 +161,49 @@ touch ~/.gstack/.proactive-prompted
|
||||||
|
|
||||||
This only happens once. If `PROACTIVE_PROMPTED` is `yes`, skip this entirely.
|
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 CLAUDE.md file exists in the project root. If it does not exist, create it.
|
||||||
|
|
||||||
|
Use AskUserQuestion:
|
||||||
|
|
||||||
|
> gstack works best when your project's CLAUDE.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 CLAUDE.md (recommended)
|
||||||
|
- B) No thanks, I'll invoke skills manually
|
||||||
|
|
||||||
|
If A: Append this section to the end of CLAUDE.md:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
|
||||||
|
## Skill routing
|
||||||
|
|
||||||
|
When the user's request matches an available skill, ALWAYS invoke it using the Skill
|
||||||
|
tool as your FIRST action. Do NOT answer directly, do NOT use other tools first.
|
||||||
|
The skill has specialized workflows that produce better results than ad-hoc answers.
|
||||||
|
|
||||||
|
Key routing rules:
|
||||||
|
- Product ideas, "is this worth building", brainstorming → invoke office-hours
|
||||||
|
- Bugs, errors, "why is this broken", 500 errors → invoke investigate
|
||||||
|
- Ship, deploy, push, create PR → invoke ship
|
||||||
|
- QA, test the site, find bugs → invoke qa
|
||||||
|
- Code review, check my diff → invoke review
|
||||||
|
- Update docs after shipping → invoke document-release
|
||||||
|
- Weekly retro → invoke retro
|
||||||
|
- Design system, brand → invoke design-consultation
|
||||||
|
- Visual audit, design polish → invoke design-review
|
||||||
|
- Architecture review → invoke plan-eng-review
|
||||||
|
```
|
||||||
|
|
||||||
|
Then commit the change: `git add CLAUDE.md && git commit -m "chore: add gstack skill routing rules to CLAUDE.md"`
|
||||||
|
|
||||||
|
If B: run `~/.claude/skills/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.
|
||||||
|
|
||||||
## Voice
|
## Voice
|
||||||
|
|
||||||
You are GStack, an open source AI builder framework shaped by Garry Tan's product, startup, and engineering judgment. Encode how he thinks, not his biography.
|
You are GStack, an open source AI builder framework shaped by Garry Tan's product, startup, and engineering judgment. Encode how he thinks, not his biography.
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,10 @@ description: |
|
||||||
hackathons, learning, and open source. Saves a design doc.
|
hackathons, learning, and open source. Saves a design doc.
|
||||||
Use when asked to "brainstorm this", "I have an idea", "help me think through
|
Use when asked to "brainstorm this", "I have an idea", "help me think through
|
||||||
this", "office hours", or "is this worth building".
|
this", "office hours", or "is this worth building".
|
||||||
Proactively suggest when the user describes a new product idea or is exploring
|
Proactively invoke this skill (do NOT answer directly) when the user describes
|
||||||
whether something is worth building — before any code is written.
|
a new product idea, asks whether something is worth building, wants to think
|
||||||
|
through design decisions for something that doesn't exist yet, or is exploring
|
||||||
|
a concept before any code is written.
|
||||||
Use before /plan-ceo-review or /plan-eng-review. (gstack)
|
Use before /plan-ceo-review or /plan-eng-review. (gstack)
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
|
|
@ -77,6 +79,14 @@ if [ -f "$_LEARN_FILE" ]; then
|
||||||
else
|
else
|
||||||
echo "LEARNINGS: 0"
|
echo "LEARNINGS: 0"
|
||||||
fi
|
fi
|
||||||
|
# Check if CLAUDE.md has routing rules
|
||||||
|
_HAS_ROUTING="no"
|
||||||
|
if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then
|
||||||
|
_HAS_ROUTING="yes"
|
||||||
|
fi
|
||||||
|
_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"
|
||||||
```
|
```
|
||||||
|
|
||||||
If `PROACTIVE` is `"false"`, do not proactively suggest gstack skills AND do not
|
If `PROACTIVE` is `"false"`, do not proactively suggest gstack skills AND do not
|
||||||
|
|
@ -158,6 +168,49 @@ touch ~/.gstack/.proactive-prompted
|
||||||
|
|
||||||
This only happens once. If `PROACTIVE_PROMPTED` is `yes`, skip this entirely.
|
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 CLAUDE.md file exists in the project root. If it does not exist, create it.
|
||||||
|
|
||||||
|
Use AskUserQuestion:
|
||||||
|
|
||||||
|
> gstack works best when your project's CLAUDE.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 CLAUDE.md (recommended)
|
||||||
|
- B) No thanks, I'll invoke skills manually
|
||||||
|
|
||||||
|
If A: Append this section to the end of CLAUDE.md:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
|
||||||
|
## Skill routing
|
||||||
|
|
||||||
|
When the user's request matches an available skill, ALWAYS invoke it using the Skill
|
||||||
|
tool as your FIRST action. Do NOT answer directly, do NOT use other tools first.
|
||||||
|
The skill has specialized workflows that produce better results than ad-hoc answers.
|
||||||
|
|
||||||
|
Key routing rules:
|
||||||
|
- Product ideas, "is this worth building", brainstorming → invoke office-hours
|
||||||
|
- Bugs, errors, "why is this broken", 500 errors → invoke investigate
|
||||||
|
- Ship, deploy, push, create PR → invoke ship
|
||||||
|
- QA, test the site, find bugs → invoke qa
|
||||||
|
- Code review, check my diff → invoke review
|
||||||
|
- Update docs after shipping → invoke document-release
|
||||||
|
- Weekly retro → invoke retro
|
||||||
|
- Design system, brand → invoke design-consultation
|
||||||
|
- Visual audit, design polish → invoke design-review
|
||||||
|
- Architecture review → invoke plan-eng-review
|
||||||
|
```
|
||||||
|
|
||||||
|
Then commit the change: `git add CLAUDE.md && git commit -m "chore: add gstack skill routing rules to CLAUDE.md"`
|
||||||
|
|
||||||
|
If B: run `~/.claude/skills/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.
|
||||||
|
|
||||||
## Voice
|
## Voice
|
||||||
|
|
||||||
You are GStack, an open source AI builder framework shaped by Garry Tan's product, startup, and engineering judgment. Encode how he thinks, not his biography.
|
You are GStack, an open source AI builder framework shaped by Garry Tan's product, startup, and engineering judgment. Encode how he thinks, not his biography.
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,10 @@ description: |
|
||||||
hackathons, learning, and open source. Saves a design doc.
|
hackathons, learning, and open source. Saves a design doc.
|
||||||
Use when asked to "brainstorm this", "I have an idea", "help me think through
|
Use when asked to "brainstorm this", "I have an idea", "help me think through
|
||||||
this", "office hours", or "is this worth building".
|
this", "office hours", or "is this worth building".
|
||||||
Proactively suggest when the user describes a new product idea or is exploring
|
Proactively invoke this skill (do NOT answer directly) when the user describes
|
||||||
whether something is worth building — before any code is written.
|
a new product idea, asks whether something is worth building, wants to think
|
||||||
|
through design decisions for something that doesn't exist yet, or is exploring
|
||||||
|
a concept before any code is written.
|
||||||
Use before /plan-ceo-review or /plan-eng-review. (gstack)
|
Use before /plan-ceo-review or /plan-eng-review. (gstack)
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "gstack",
|
"name": "gstack",
|
||||||
"version": "0.13.8.0",
|
"version": "0.13.9.0",
|
||||||
"description": "Garry's Stack — Claude Code skills + fast headless browser. One repo, one install, entire AI engineering workflow.",
|
"description": "Garry's Stack — Claude Code skills + fast headless browser. One repo, one install, entire AI engineering workflow.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,14 @@ if [ -f "$_LEARN_FILE" ]; then
|
||||||
else
|
else
|
||||||
echo "LEARNINGS: 0"
|
echo "LEARNINGS: 0"
|
||||||
fi
|
fi
|
||||||
|
# Check if CLAUDE.md has routing rules
|
||||||
|
_HAS_ROUTING="no"
|
||||||
|
if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then
|
||||||
|
_HAS_ROUTING="yes"
|
||||||
|
fi
|
||||||
|
_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"
|
||||||
```
|
```
|
||||||
|
|
||||||
If `PROACTIVE` is `"false"`, do not proactively suggest gstack skills AND do not
|
If `PROACTIVE` is `"false"`, do not proactively suggest gstack skills AND do not
|
||||||
|
|
@ -156,6 +164,49 @@ touch ~/.gstack/.proactive-prompted
|
||||||
|
|
||||||
This only happens once. If `PROACTIVE_PROMPTED` is `yes`, skip this entirely.
|
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 CLAUDE.md file exists in the project root. If it does not exist, create it.
|
||||||
|
|
||||||
|
Use AskUserQuestion:
|
||||||
|
|
||||||
|
> gstack works best when your project's CLAUDE.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 CLAUDE.md (recommended)
|
||||||
|
- B) No thanks, I'll invoke skills manually
|
||||||
|
|
||||||
|
If A: Append this section to the end of CLAUDE.md:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
|
||||||
|
## Skill routing
|
||||||
|
|
||||||
|
When the user's request matches an available skill, ALWAYS invoke it using the Skill
|
||||||
|
tool as your FIRST action. Do NOT answer directly, do NOT use other tools first.
|
||||||
|
The skill has specialized workflows that produce better results than ad-hoc answers.
|
||||||
|
|
||||||
|
Key routing rules:
|
||||||
|
- Product ideas, "is this worth building", brainstorming → invoke office-hours
|
||||||
|
- Bugs, errors, "why is this broken", 500 errors → invoke investigate
|
||||||
|
- Ship, deploy, push, create PR → invoke ship
|
||||||
|
- QA, test the site, find bugs → invoke qa
|
||||||
|
- Code review, check my diff → invoke review
|
||||||
|
- Update docs after shipping → invoke document-release
|
||||||
|
- Weekly retro → invoke retro
|
||||||
|
- Design system, brand → invoke design-consultation
|
||||||
|
- Visual audit, design polish → invoke design-review
|
||||||
|
- Architecture review → invoke plan-eng-review
|
||||||
|
```
|
||||||
|
|
||||||
|
Then commit the change: `git add CLAUDE.md && git commit -m "chore: add gstack skill routing rules to CLAUDE.md"`
|
||||||
|
|
||||||
|
If B: run `~/.claude/skills/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.
|
||||||
|
|
||||||
## Voice
|
## Voice
|
||||||
|
|
||||||
You are GStack, an open source AI builder framework shaped by Garry Tan's product, startup, and engineering judgment. Encode how he thinks, not his biography.
|
You are GStack, an open source AI builder framework shaped by Garry Tan's product, startup, and engineering judgment. Encode how he thinks, not his biography.
|
||||||
|
|
@ -529,10 +580,11 @@ If they choose A:
|
||||||
Say: "Running /office-hours inline. Once the design doc is ready, I'll pick up
|
Say: "Running /office-hours inline. Once the design doc is ready, I'll pick up
|
||||||
the review right where we left off."
|
the review right where we left off."
|
||||||
|
|
||||||
Read the office-hours skill file from disk using the Read tool:
|
Read the `/office-hours` skill file at `~/.claude/skills/gstack/office-hours/SKILL.md` using the Read tool.
|
||||||
`~/.claude/skills/gstack/office-hours/SKILL.md`
|
|
||||||
|
|
||||||
Follow it inline, **skipping these sections** (already handled by the parent skill):
|
**If unreadable:** Skip with "Could not load /office-hours — skipping." and continue.
|
||||||
|
|
||||||
|
Follow its instructions from top to bottom, **skipping these sections** (already handled by the parent skill):
|
||||||
- Preamble (run first)
|
- Preamble (run first)
|
||||||
- AskUserQuestion Format
|
- AskUserQuestion Format
|
||||||
- Completeness Principle — Boil the Lake
|
- Completeness Principle — Boil the Lake
|
||||||
|
|
@ -540,9 +592,13 @@ Follow it inline, **skipping these sections** (already handled by the parent ski
|
||||||
- Contributor Mode
|
- Contributor Mode
|
||||||
- Completion Status Protocol
|
- Completion Status Protocol
|
||||||
- Telemetry (run last)
|
- Telemetry (run last)
|
||||||
|
- Step 0: Detect platform and base branch
|
||||||
|
- Review Readiness Dashboard
|
||||||
|
- Plan File Review Report
|
||||||
|
- Prerequisite Skill Offer
|
||||||
|
- Plan Status Footer
|
||||||
|
|
||||||
If the Read fails (file not found), say:
|
Execute every other section at full depth. When the loaded skill's instructions are complete, continue with the next step below.
|
||||||
"Could not load /office-hours — proceeding with standard review."
|
|
||||||
|
|
||||||
After /office-hours completes, re-run the design doc check:
|
After /office-hours completes, re-run the design doc check:
|
||||||
```bash
|
```bash
|
||||||
|
|
@ -568,12 +624,27 @@ sure," or is clearly exploring rather than reviewing — offer `/office-hours`:
|
||||||
Options: A) Yes, run /office-hours now. B) No, keep going.
|
Options: A) Yes, run /office-hours now. B) No, keep going.
|
||||||
If they keep going, proceed normally — no guilt, no re-asking.
|
If they keep going, proceed normally — no guilt, no re-asking.
|
||||||
|
|
||||||
If they choose A: Read the office-hours skill file from disk:
|
If they choose A:
|
||||||
`~/.claude/skills/gstack/office-hours/SKILL.md`
|
|
||||||
|
|
||||||
Follow it inline, skipping these sections (already handled by parent skill):
|
Read the `/office-hours` skill file at `~/.claude/skills/gstack/office-hours/SKILL.md` using the Read tool.
|
||||||
Preamble, AskUserQuestion Format, Completeness Principle, Search Before Building,
|
|
||||||
Contributor Mode, Completion Status Protocol, Telemetry.
|
**If unreadable:** Skip with "Could not load /office-hours — skipping." and continue.
|
||||||
|
|
||||||
|
Follow its instructions from top to bottom, **skipping these sections** (already handled by the parent skill):
|
||||||
|
- Preamble (run first)
|
||||||
|
- AskUserQuestion Format
|
||||||
|
- Completeness Principle — Boil the Lake
|
||||||
|
- Search Before Building
|
||||||
|
- Contributor Mode
|
||||||
|
- Completion Status Protocol
|
||||||
|
- Telemetry (run last)
|
||||||
|
- Step 0: Detect platform and base branch
|
||||||
|
- Review Readiness Dashboard
|
||||||
|
- Plan File Review Report
|
||||||
|
- Prerequisite Skill Offer
|
||||||
|
- Plan Status Footer
|
||||||
|
|
||||||
|
Execute every other section at full depth. When the loaded skill's instructions are complete, continue with the next step below.
|
||||||
|
|
||||||
Note current Step 0A progress so you don't re-ask questions already answered.
|
Note current Step 0A progress so you don't re-ask questions already answered.
|
||||||
After completion, re-run the design doc check and resume the review.
|
After completion, re-run the design doc check and resume the review.
|
||||||
|
|
|
||||||
|
|
@ -143,12 +143,9 @@ sure," or is clearly exploring rather than reviewing — offer `/office-hours`:
|
||||||
Options: A) Yes, run /office-hours now. B) No, keep going.
|
Options: A) Yes, run /office-hours now. B) No, keep going.
|
||||||
If they keep going, proceed normally — no guilt, no re-asking.
|
If they keep going, proceed normally — no guilt, no re-asking.
|
||||||
|
|
||||||
If they choose A: Read the office-hours skill file from disk:
|
If they choose A:
|
||||||
`~/.claude/skills/gstack/office-hours/SKILL.md`
|
|
||||||
|
|
||||||
Follow it inline, skipping these sections (already handled by parent skill):
|
{{INVOKE_SKILL:office-hours}}
|
||||||
Preamble, AskUserQuestion Format, Completeness Principle, Search Before Building,
|
|
||||||
Contributor Mode, Completion Status Protocol, Telemetry.
|
|
||||||
|
|
||||||
Note current Step 0A progress so you don't re-ask questions already answered.
|
Note current Step 0A progress so you don't re-ask questions already answered.
|
||||||
After completion, re-run the design doc check and resume the review.
|
After completion, re-run the design doc check and resume the review.
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,14 @@ if [ -f "$_LEARN_FILE" ]; then
|
||||||
else
|
else
|
||||||
echo "LEARNINGS: 0"
|
echo "LEARNINGS: 0"
|
||||||
fi
|
fi
|
||||||
|
# Check if CLAUDE.md has routing rules
|
||||||
|
_HAS_ROUTING="no"
|
||||||
|
if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then
|
||||||
|
_HAS_ROUTING="yes"
|
||||||
|
fi
|
||||||
|
_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"
|
||||||
```
|
```
|
||||||
|
|
||||||
If `PROACTIVE` is `"false"`, do not proactively suggest gstack skills AND do not
|
If `PROACTIVE` is `"false"`, do not proactively suggest gstack skills AND do not
|
||||||
|
|
@ -154,6 +162,49 @@ touch ~/.gstack/.proactive-prompted
|
||||||
|
|
||||||
This only happens once. If `PROACTIVE_PROMPTED` is `yes`, skip this entirely.
|
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 CLAUDE.md file exists in the project root. If it does not exist, create it.
|
||||||
|
|
||||||
|
Use AskUserQuestion:
|
||||||
|
|
||||||
|
> gstack works best when your project's CLAUDE.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 CLAUDE.md (recommended)
|
||||||
|
- B) No thanks, I'll invoke skills manually
|
||||||
|
|
||||||
|
If A: Append this section to the end of CLAUDE.md:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
|
||||||
|
## Skill routing
|
||||||
|
|
||||||
|
When the user's request matches an available skill, ALWAYS invoke it using the Skill
|
||||||
|
tool as your FIRST action. Do NOT answer directly, do NOT use other tools first.
|
||||||
|
The skill has specialized workflows that produce better results than ad-hoc answers.
|
||||||
|
|
||||||
|
Key routing rules:
|
||||||
|
- Product ideas, "is this worth building", brainstorming → invoke office-hours
|
||||||
|
- Bugs, errors, "why is this broken", 500 errors → invoke investigate
|
||||||
|
- Ship, deploy, push, create PR → invoke ship
|
||||||
|
- QA, test the site, find bugs → invoke qa
|
||||||
|
- Code review, check my diff → invoke review
|
||||||
|
- Update docs after shipping → invoke document-release
|
||||||
|
- Weekly retro → invoke retro
|
||||||
|
- Design system, brand → invoke design-consultation
|
||||||
|
- Visual audit, design polish → invoke design-review
|
||||||
|
- Architecture review → invoke plan-eng-review
|
||||||
|
```
|
||||||
|
|
||||||
|
Then commit the change: `git add CLAUDE.md && git commit -m "chore: add gstack skill routing rules to CLAUDE.md"`
|
||||||
|
|
||||||
|
If B: run `~/.claude/skills/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.
|
||||||
|
|
||||||
## Voice
|
## Voice
|
||||||
|
|
||||||
You are GStack, an open source AI builder framework shaped by Garry Tan's product, startup, and engineering judgment. Encode how he thinks, not his biography.
|
You are GStack, an open source AI builder framework shaped by Garry Tan's product, startup, and engineering judgment. Encode how he thinks, not his biography.
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,14 @@ if [ -f "$_LEARN_FILE" ]; then
|
||||||
else
|
else
|
||||||
echo "LEARNINGS: 0"
|
echo "LEARNINGS: 0"
|
||||||
fi
|
fi
|
||||||
|
# Check if CLAUDE.md has routing rules
|
||||||
|
_HAS_ROUTING="no"
|
||||||
|
if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then
|
||||||
|
_HAS_ROUTING="yes"
|
||||||
|
fi
|
||||||
|
_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"
|
||||||
```
|
```
|
||||||
|
|
||||||
If `PROACTIVE` is `"false"`, do not proactively suggest gstack skills AND do not
|
If `PROACTIVE` is `"false"`, do not proactively suggest gstack skills AND do not
|
||||||
|
|
@ -155,6 +163,49 @@ touch ~/.gstack/.proactive-prompted
|
||||||
|
|
||||||
This only happens once. If `PROACTIVE_PROMPTED` is `yes`, skip this entirely.
|
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 CLAUDE.md file exists in the project root. If it does not exist, create it.
|
||||||
|
|
||||||
|
Use AskUserQuestion:
|
||||||
|
|
||||||
|
> gstack works best when your project's CLAUDE.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 CLAUDE.md (recommended)
|
||||||
|
- B) No thanks, I'll invoke skills manually
|
||||||
|
|
||||||
|
If A: Append this section to the end of CLAUDE.md:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
|
||||||
|
## Skill routing
|
||||||
|
|
||||||
|
When the user's request matches an available skill, ALWAYS invoke it using the Skill
|
||||||
|
tool as your FIRST action. Do NOT answer directly, do NOT use other tools first.
|
||||||
|
The skill has specialized workflows that produce better results than ad-hoc answers.
|
||||||
|
|
||||||
|
Key routing rules:
|
||||||
|
- Product ideas, "is this worth building", brainstorming → invoke office-hours
|
||||||
|
- Bugs, errors, "why is this broken", 500 errors → invoke investigate
|
||||||
|
- Ship, deploy, push, create PR → invoke ship
|
||||||
|
- QA, test the site, find bugs → invoke qa
|
||||||
|
- Code review, check my diff → invoke review
|
||||||
|
- Update docs after shipping → invoke document-release
|
||||||
|
- Weekly retro → invoke retro
|
||||||
|
- Design system, brand → invoke design-consultation
|
||||||
|
- Visual audit, design polish → invoke design-review
|
||||||
|
- Architecture review → invoke plan-eng-review
|
||||||
|
```
|
||||||
|
|
||||||
|
Then commit the change: `git add CLAUDE.md && git commit -m "chore: add gstack skill routing rules to CLAUDE.md"`
|
||||||
|
|
||||||
|
If B: run `~/.claude/skills/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.
|
||||||
|
|
||||||
## Voice
|
## Voice
|
||||||
|
|
||||||
You are GStack, an open source AI builder framework shaped by Garry Tan's product, startup, and engineering judgment. Encode how he thinks, not his biography.
|
You are GStack, an open source AI builder framework shaped by Garry Tan's product, startup, and engineering judgment. Encode how he thinks, not his biography.
|
||||||
|
|
@ -439,10 +490,11 @@ If they choose A:
|
||||||
Say: "Running /office-hours inline. Once the design doc is ready, I'll pick up
|
Say: "Running /office-hours inline. Once the design doc is ready, I'll pick up
|
||||||
the review right where we left off."
|
the review right where we left off."
|
||||||
|
|
||||||
Read the office-hours skill file from disk using the Read tool:
|
Read the `/office-hours` skill file at `~/.claude/skills/gstack/office-hours/SKILL.md` using the Read tool.
|
||||||
`~/.claude/skills/gstack/office-hours/SKILL.md`
|
|
||||||
|
|
||||||
Follow it inline, **skipping these sections** (already handled by the parent skill):
|
**If unreadable:** Skip with "Could not load /office-hours — skipping." and continue.
|
||||||
|
|
||||||
|
Follow its instructions from top to bottom, **skipping these sections** (already handled by the parent skill):
|
||||||
- Preamble (run first)
|
- Preamble (run first)
|
||||||
- AskUserQuestion Format
|
- AskUserQuestion Format
|
||||||
- Completeness Principle — Boil the Lake
|
- Completeness Principle — Boil the Lake
|
||||||
|
|
@ -450,9 +502,13 @@ Follow it inline, **skipping these sections** (already handled by the parent ski
|
||||||
- Contributor Mode
|
- Contributor Mode
|
||||||
- Completion Status Protocol
|
- Completion Status Protocol
|
||||||
- Telemetry (run last)
|
- Telemetry (run last)
|
||||||
|
- Step 0: Detect platform and base branch
|
||||||
|
- Review Readiness Dashboard
|
||||||
|
- Plan File Review Report
|
||||||
|
- Prerequisite Skill Offer
|
||||||
|
- Plan Status Footer
|
||||||
|
|
||||||
If the Read fails (file not found), say:
|
Execute every other section at full depth. When the loaded skill's instructions are complete, continue with the next step below.
|
||||||
"Could not load /office-hours — proceeding with standard review."
|
|
||||||
|
|
||||||
After /office-hours completes, re-run the design doc check:
|
After /office-hours completes, re-run the design doc check:
|
||||||
```bash
|
```bash
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,14 @@ if [ -f "$_LEARN_FILE" ]; then
|
||||||
else
|
else
|
||||||
echo "LEARNINGS: 0"
|
echo "LEARNINGS: 0"
|
||||||
fi
|
fi
|
||||||
|
# Check if CLAUDE.md has routing rules
|
||||||
|
_HAS_ROUTING="no"
|
||||||
|
if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then
|
||||||
|
_HAS_ROUTING="yes"
|
||||||
|
fi
|
||||||
|
_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"
|
||||||
```
|
```
|
||||||
|
|
||||||
If `PROACTIVE` is `"false"`, do not proactively suggest gstack skills AND do not
|
If `PROACTIVE` is `"false"`, do not proactively suggest gstack skills AND do not
|
||||||
|
|
@ -151,6 +159,49 @@ touch ~/.gstack/.proactive-prompted
|
||||||
|
|
||||||
This only happens once. If `PROACTIVE_PROMPTED` is `yes`, skip this entirely.
|
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 CLAUDE.md file exists in the project root. If it does not exist, create it.
|
||||||
|
|
||||||
|
Use AskUserQuestion:
|
||||||
|
|
||||||
|
> gstack works best when your project's CLAUDE.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 CLAUDE.md (recommended)
|
||||||
|
- B) No thanks, I'll invoke skills manually
|
||||||
|
|
||||||
|
If A: Append this section to the end of CLAUDE.md:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
|
||||||
|
## Skill routing
|
||||||
|
|
||||||
|
When the user's request matches an available skill, ALWAYS invoke it using the Skill
|
||||||
|
tool as your FIRST action. Do NOT answer directly, do NOT use other tools first.
|
||||||
|
The skill has specialized workflows that produce better results than ad-hoc answers.
|
||||||
|
|
||||||
|
Key routing rules:
|
||||||
|
- Product ideas, "is this worth building", brainstorming → invoke office-hours
|
||||||
|
- Bugs, errors, "why is this broken", 500 errors → invoke investigate
|
||||||
|
- Ship, deploy, push, create PR → invoke ship
|
||||||
|
- QA, test the site, find bugs → invoke qa
|
||||||
|
- Code review, check my diff → invoke review
|
||||||
|
- Update docs after shipping → invoke document-release
|
||||||
|
- Weekly retro → invoke retro
|
||||||
|
- Design system, brand → invoke design-consultation
|
||||||
|
- Visual audit, design polish → invoke design-review
|
||||||
|
- Architecture review → invoke plan-eng-review
|
||||||
|
```
|
||||||
|
|
||||||
|
Then commit the change: `git add CLAUDE.md && git commit -m "chore: add gstack skill routing rules to CLAUDE.md"`
|
||||||
|
|
||||||
|
If B: run `~/.claude/skills/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.
|
||||||
|
|
||||||
## Voice
|
## Voice
|
||||||
|
|
||||||
You are GStack, an open source AI builder framework shaped by Garry Tan's product, startup, and engineering judgment. Encode how he thinks, not his biography.
|
You are GStack, an open source AI builder framework shaped by Garry Tan's product, startup, and engineering judgment. Encode how he thinks, not his biography.
|
||||||
|
|
|
||||||
51
qa/SKILL.md
51
qa/SKILL.md
|
|
@ -76,6 +76,14 @@ if [ -f "$_LEARN_FILE" ]; then
|
||||||
else
|
else
|
||||||
echo "LEARNINGS: 0"
|
echo "LEARNINGS: 0"
|
||||||
fi
|
fi
|
||||||
|
# Check if CLAUDE.md has routing rules
|
||||||
|
_HAS_ROUTING="no"
|
||||||
|
if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then
|
||||||
|
_HAS_ROUTING="yes"
|
||||||
|
fi
|
||||||
|
_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"
|
||||||
```
|
```
|
||||||
|
|
||||||
If `PROACTIVE` is `"false"`, do not proactively suggest gstack skills AND do not
|
If `PROACTIVE` is `"false"`, do not proactively suggest gstack skills AND do not
|
||||||
|
|
@ -157,6 +165,49 @@ touch ~/.gstack/.proactive-prompted
|
||||||
|
|
||||||
This only happens once. If `PROACTIVE_PROMPTED` is `yes`, skip this entirely.
|
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 CLAUDE.md file exists in the project root. If it does not exist, create it.
|
||||||
|
|
||||||
|
Use AskUserQuestion:
|
||||||
|
|
||||||
|
> gstack works best when your project's CLAUDE.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 CLAUDE.md (recommended)
|
||||||
|
- B) No thanks, I'll invoke skills manually
|
||||||
|
|
||||||
|
If A: Append this section to the end of CLAUDE.md:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
|
||||||
|
## Skill routing
|
||||||
|
|
||||||
|
When the user's request matches an available skill, ALWAYS invoke it using the Skill
|
||||||
|
tool as your FIRST action. Do NOT answer directly, do NOT use other tools first.
|
||||||
|
The skill has specialized workflows that produce better results than ad-hoc answers.
|
||||||
|
|
||||||
|
Key routing rules:
|
||||||
|
- Product ideas, "is this worth building", brainstorming → invoke office-hours
|
||||||
|
- Bugs, errors, "why is this broken", 500 errors → invoke investigate
|
||||||
|
- Ship, deploy, push, create PR → invoke ship
|
||||||
|
- QA, test the site, find bugs → invoke qa
|
||||||
|
- Code review, check my diff → invoke review
|
||||||
|
- Update docs after shipping → invoke document-release
|
||||||
|
- Weekly retro → invoke retro
|
||||||
|
- Design system, brand → invoke design-consultation
|
||||||
|
- Visual audit, design polish → invoke design-review
|
||||||
|
- Architecture review → invoke plan-eng-review
|
||||||
|
```
|
||||||
|
|
||||||
|
Then commit the change: `git add CLAUDE.md && git commit -m "chore: add gstack skill routing rules to CLAUDE.md"`
|
||||||
|
|
||||||
|
If B: run `~/.claude/skills/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.
|
||||||
|
|
||||||
## Voice
|
## Voice
|
||||||
|
|
||||||
You are GStack, an open source AI builder framework shaped by Garry Tan's product, startup, and engineering judgment. Encode how he thinks, not his biography.
|
You are GStack, an open source AI builder framework shaped by Garry Tan's product, startup, and engineering judgment. Encode how he thinks, not his biography.
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,14 @@ if [ -f "$_LEARN_FILE" ]; then
|
||||||
else
|
else
|
||||||
echo "LEARNINGS: 0"
|
echo "LEARNINGS: 0"
|
||||||
fi
|
fi
|
||||||
|
# Check if CLAUDE.md has routing rules
|
||||||
|
_HAS_ROUTING="no"
|
||||||
|
if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then
|
||||||
|
_HAS_ROUTING="yes"
|
||||||
|
fi
|
||||||
|
_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"
|
||||||
```
|
```
|
||||||
|
|
||||||
If `PROACTIVE` is `"false"`, do not proactively suggest gstack skills AND do not
|
If `PROACTIVE` is `"false"`, do not proactively suggest gstack skills AND do not
|
||||||
|
|
@ -151,6 +159,49 @@ touch ~/.gstack/.proactive-prompted
|
||||||
|
|
||||||
This only happens once. If `PROACTIVE_PROMPTED` is `yes`, skip this entirely.
|
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 CLAUDE.md file exists in the project root. If it does not exist, create it.
|
||||||
|
|
||||||
|
Use AskUserQuestion:
|
||||||
|
|
||||||
|
> gstack works best when your project's CLAUDE.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 CLAUDE.md (recommended)
|
||||||
|
- B) No thanks, I'll invoke skills manually
|
||||||
|
|
||||||
|
If A: Append this section to the end of CLAUDE.md:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
|
||||||
|
## Skill routing
|
||||||
|
|
||||||
|
When the user's request matches an available skill, ALWAYS invoke it using the Skill
|
||||||
|
tool as your FIRST action. Do NOT answer directly, do NOT use other tools first.
|
||||||
|
The skill has specialized workflows that produce better results than ad-hoc answers.
|
||||||
|
|
||||||
|
Key routing rules:
|
||||||
|
- Product ideas, "is this worth building", brainstorming → invoke office-hours
|
||||||
|
- Bugs, errors, "why is this broken", 500 errors → invoke investigate
|
||||||
|
- Ship, deploy, push, create PR → invoke ship
|
||||||
|
- QA, test the site, find bugs → invoke qa
|
||||||
|
- Code review, check my diff → invoke review
|
||||||
|
- Update docs after shipping → invoke document-release
|
||||||
|
- Weekly retro → invoke retro
|
||||||
|
- Design system, brand → invoke design-consultation
|
||||||
|
- Visual audit, design polish → invoke design-review
|
||||||
|
- Architecture review → invoke plan-eng-review
|
||||||
|
```
|
||||||
|
|
||||||
|
Then commit the change: `git add CLAUDE.md && git commit -m "chore: add gstack skill routing rules to CLAUDE.md"`
|
||||||
|
|
||||||
|
If B: run `~/.claude/skills/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.
|
||||||
|
|
||||||
## Voice
|
## Voice
|
||||||
|
|
||||||
You are GStack, an open source AI builder framework shaped by Garry Tan's product, startup, and engineering judgment. Encode how he thinks, not his biography.
|
You are GStack, an open source AI builder framework shaped by Garry Tan's product, startup, and engineering judgment. Encode how he thinks, not his biography.
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,14 @@ if [ -f "$_LEARN_FILE" ]; then
|
||||||
else
|
else
|
||||||
echo "LEARNINGS: 0"
|
echo "LEARNINGS: 0"
|
||||||
fi
|
fi
|
||||||
|
# Check if CLAUDE.md has routing rules
|
||||||
|
_HAS_ROUTING="no"
|
||||||
|
if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then
|
||||||
|
_HAS_ROUTING="yes"
|
||||||
|
fi
|
||||||
|
_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"
|
||||||
```
|
```
|
||||||
|
|
||||||
If `PROACTIVE` is `"false"`, do not proactively suggest gstack skills AND do not
|
If `PROACTIVE` is `"false"`, do not proactively suggest gstack skills AND do not
|
||||||
|
|
@ -154,6 +162,49 @@ touch ~/.gstack/.proactive-prompted
|
||||||
|
|
||||||
This only happens once. If `PROACTIVE_PROMPTED` is `yes`, skip this entirely.
|
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 CLAUDE.md file exists in the project root. If it does not exist, create it.
|
||||||
|
|
||||||
|
Use AskUserQuestion:
|
||||||
|
|
||||||
|
> gstack works best when your project's CLAUDE.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 CLAUDE.md (recommended)
|
||||||
|
- B) No thanks, I'll invoke skills manually
|
||||||
|
|
||||||
|
If A: Append this section to the end of CLAUDE.md:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
|
||||||
|
## Skill routing
|
||||||
|
|
||||||
|
When the user's request matches an available skill, ALWAYS invoke it using the Skill
|
||||||
|
tool as your FIRST action. Do NOT answer directly, do NOT use other tools first.
|
||||||
|
The skill has specialized workflows that produce better results than ad-hoc answers.
|
||||||
|
|
||||||
|
Key routing rules:
|
||||||
|
- Product ideas, "is this worth building", brainstorming → invoke office-hours
|
||||||
|
- Bugs, errors, "why is this broken", 500 errors → invoke investigate
|
||||||
|
- Ship, deploy, push, create PR → invoke ship
|
||||||
|
- QA, test the site, find bugs → invoke qa
|
||||||
|
- Code review, check my diff → invoke review
|
||||||
|
- Update docs after shipping → invoke document-release
|
||||||
|
- Weekly retro → invoke retro
|
||||||
|
- Design system, brand → invoke design-consultation
|
||||||
|
- Visual audit, design polish → invoke design-review
|
||||||
|
- Architecture review → invoke plan-eng-review
|
||||||
|
```
|
||||||
|
|
||||||
|
Then commit the change: `git add CLAUDE.md && git commit -m "chore: add gstack skill routing rules to CLAUDE.md"`
|
||||||
|
|
||||||
|
If B: run `~/.claude/skills/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.
|
||||||
|
|
||||||
## Voice
|
## Voice
|
||||||
|
|
||||||
You are GStack, an open source AI builder framework shaped by Garry Tan's product, startup, and engineering judgment. Encode how he thinks, not his biography.
|
You are GStack, an open source AI builder framework shaped by Garry Tan's product, startup, and engineering judgment. Encode how he thinks, not his biography.
|
||||||
|
|
|
||||||
|
|
@ -83,11 +83,15 @@ const OPENAI_LITMUS_CHECKS = [
|
||||||
// ─── External Host Helpers ───────────────────────────────────
|
// ─── External Host Helpers ───────────────────────────────────
|
||||||
|
|
||||||
// Re-export local copy for use in this file (matches codex-helpers.ts)
|
// Re-export local copy for use in this file (matches codex-helpers.ts)
|
||||||
function externalSkillName(skillDir: string): string {
|
// Accepts optional frontmatter name to support directory/invocation name divergence
|
||||||
|
function externalSkillName(skillDir: string, frontmatterName?: string): string {
|
||||||
|
// Root skill (skillDir === '' or '.') always maps to 'gstack' regardless of frontmatter
|
||||||
if (skillDir === '.' || skillDir === '') return 'gstack';
|
if (skillDir === '.' || skillDir === '') return 'gstack';
|
||||||
|
// Use frontmatter name when it differs from directory name (e.g., run-tests/ with name: test)
|
||||||
|
const baseName = frontmatterName && frontmatterName !== skillDir ? frontmatterName : skillDir;
|
||||||
// Don't double-prefix: gstack-upgrade → gstack-upgrade (not gstack-gstack-upgrade)
|
// Don't double-prefix: gstack-upgrade → gstack-upgrade (not gstack-gstack-upgrade)
|
||||||
if (skillDir.startsWith('gstack-')) return skillDir;
|
if (baseName.startsWith('gstack-')) return baseName;
|
||||||
return `gstack-${skillDir}`;
|
return `gstack-${baseName}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function extractNameAndDescription(content: string): { name: string; description: string } {
|
function extractNameAndDescription(content: string): { name: string; description: string } {
|
||||||
|
|
@ -255,11 +259,12 @@ function processExternalHost(
|
||||||
skillDir: string,
|
skillDir: string,
|
||||||
extractedDescription: string,
|
extractedDescription: string,
|
||||||
ctx: TemplateContext,
|
ctx: TemplateContext,
|
||||||
|
frontmatterName?: string,
|
||||||
): { content: string; outputPath: string; outputDir: string; symlinkLoop: boolean } {
|
): { content: string; outputPath: string; outputDir: string; symlinkLoop: boolean } {
|
||||||
const config = EXTERNAL_HOST_CONFIG[host];
|
const config = EXTERNAL_HOST_CONFIG[host];
|
||||||
if (!config) throw new Error(`No external host config for: ${host}`);
|
if (!config) throw new Error(`No external host config for: ${host}`);
|
||||||
|
|
||||||
const name = externalSkillName(skillDir === '.' ? '' : skillDir);
|
const name = externalSkillName(skillDir === '.' ? '' : skillDir, frontmatterName);
|
||||||
const outputDir = path.join(ROOT, config.hostSubdir, 'skills', name);
|
const outputDir = path.join(ROOT, config.hostSubdir, 'skills', name);
|
||||||
fs.mkdirSync(outputDir, { recursive: true });
|
fs.mkdirSync(outputDir, { recursive: true });
|
||||||
const outputPath = path.join(outputDir, 'SKILL.md');
|
const outputPath = path.join(outputDir, 'SKILL.md');
|
||||||
|
|
@ -324,10 +329,13 @@ function processTemplate(tmplPath: string, host: Host = 'claude'): { outputPath:
|
||||||
// Determine skill directory relative to ROOT
|
// Determine skill directory relative to ROOT
|
||||||
const skillDir = path.relative(ROOT, path.dirname(tmplPath));
|
const skillDir = path.relative(ROOT, path.dirname(tmplPath));
|
||||||
|
|
||||||
// Extract skill name from frontmatter for TemplateContext
|
// Extract skill name from frontmatter early — needed for both TemplateContext and external host output paths.
|
||||||
|
// When frontmatter name: differs from directory name (e.g., run-tests/ with name: test),
|
||||||
|
// the frontmatter name is used for external skill naming and setup script symlinks.
|
||||||
const { name: extractedName, description: extractedDescription } = extractNameAndDescription(tmplContent);
|
const { name: extractedName, description: extractedDescription } = extractNameAndDescription(tmplContent);
|
||||||
const skillName = extractedName || path.basename(path.dirname(tmplPath));
|
const skillName = extractedName || path.basename(path.dirname(tmplPath));
|
||||||
|
|
||||||
|
|
||||||
// Extract benefits-from list from frontmatter (inline YAML: benefits-from: [a, b])
|
// Extract benefits-from list from frontmatter (inline YAML: benefits-from: [a, b])
|
||||||
const benefitsMatch = tmplContent.match(/^benefits-from:\s*\[([^\]]*)\]/m);
|
const benefitsMatch = tmplContent.match(/^benefits-from:\s*\[([^\]]*)\]/m);
|
||||||
const benefitsFrom = benefitsMatch
|
const benefitsFrom = benefitsMatch
|
||||||
|
|
@ -340,15 +348,18 @@ function processTemplate(tmplPath: string, host: Host = 'claude'): { outputPath:
|
||||||
|
|
||||||
const ctx: TemplateContext = { skillName, tmplPath, benefitsFrom, host, paths: HOST_PATHS[host], preambleTier };
|
const ctx: TemplateContext = { skillName, tmplPath, benefitsFrom, host, paths: HOST_PATHS[host], preambleTier };
|
||||||
|
|
||||||
// Replace placeholders
|
// Replace placeholders (supports parameterized: {{NAME:arg1:arg2}})
|
||||||
let content = tmplContent.replace(/\{\{(\w+)\}\}/g, (match, name) => {
|
let content = tmplContent.replace(/\{\{(\w+(?::[^}]+)?)\}\}/g, (match, fullKey) => {
|
||||||
const resolver = RESOLVERS[name];
|
const parts = fullKey.split(':');
|
||||||
if (!resolver) throw new Error(`Unknown placeholder {{${name}}} in ${relTmplPath}`);
|
const resolverName = parts[0];
|
||||||
return resolver(ctx);
|
const args = parts.slice(1);
|
||||||
|
const resolver = RESOLVERS[resolverName];
|
||||||
|
if (!resolver) throw new Error(`Unknown placeholder {{${resolverName}}} in ${relTmplPath}`);
|
||||||
|
return args.length > 0 ? resolver(ctx, args) : resolver(ctx);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Check for any remaining unresolved placeholders
|
// Check for any remaining unresolved placeholders
|
||||||
const remaining = content.match(/\{\{(\w+)\}\}/g);
|
const remaining = content.match(/\{\{(\w+(?::[^}]+)?)\}\}/g);
|
||||||
if (remaining) {
|
if (remaining) {
|
||||||
throw new Error(`Unresolved placeholders in ${relTmplPath}: ${remaining.join(', ')}`);
|
throw new Error(`Unresolved placeholders in ${relTmplPath}: ${remaining.join(', ')}`);
|
||||||
}
|
}
|
||||||
|
|
@ -359,7 +370,7 @@ function processTemplate(tmplPath: string, host: Host = 'claude'): { outputPath:
|
||||||
if (host === 'claude') {
|
if (host === 'claude') {
|
||||||
content = transformFrontmatter(content, host);
|
content = transformFrontmatter(content, host);
|
||||||
} else {
|
} else {
|
||||||
const result = processExternalHost(content, tmplContent, host, skillDir, extractedDescription, ctx);
|
const result = processExternalHost(content, tmplContent, host, skillDir, extractedDescription, ctx, extractedName || undefined);
|
||||||
content = result.content;
|
content = result.content;
|
||||||
outputPath = result.outputPath;
|
outputPath = result.outputPath;
|
||||||
symlinkLoop = result.symlinkLoop;
|
symlinkLoop = result.symlinkLoop;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
import type { TemplateContext } from './types';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {{INVOKE_SKILL:skill-name}} — emits prose instructing Claude to read
|
||||||
|
* another skill's SKILL.md and follow it, skipping preamble sections.
|
||||||
|
*
|
||||||
|
* Supports optional skip= parameter for additional sections to skip:
|
||||||
|
* {{INVOKE_SKILL:plan-ceo-review:skip=Outside Voice,Design Outside Voices}}
|
||||||
|
*/
|
||||||
|
export function generateInvokeSkill(ctx: TemplateContext, args?: string[]): string {
|
||||||
|
const skillName = args?.[0];
|
||||||
|
if (!skillName || skillName === '') {
|
||||||
|
throw new Error('{{INVOKE_SKILL}} requires a skill name, e.g. {{INVOKE_SKILL:plan-ceo-review}}');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse optional skip= parameter from args[1+]
|
||||||
|
const extraSkips = (args?.slice(1) || [])
|
||||||
|
.filter(a => a.startsWith('skip='))
|
||||||
|
.flatMap(a => a.slice(5).split(','))
|
||||||
|
.map(s => s.trim())
|
||||||
|
.filter(Boolean);
|
||||||
|
|
||||||
|
const DEFAULT_SKIPS = [
|
||||||
|
'Preamble (run first)',
|
||||||
|
'AskUserQuestion Format',
|
||||||
|
'Completeness Principle — Boil the Lake',
|
||||||
|
'Search Before Building',
|
||||||
|
'Contributor Mode',
|
||||||
|
'Completion Status Protocol',
|
||||||
|
'Telemetry (run last)',
|
||||||
|
'Step 0: Detect platform and base branch',
|
||||||
|
'Review Readiness Dashboard',
|
||||||
|
'Plan File Review Report',
|
||||||
|
'Prerequisite Skill Offer',
|
||||||
|
'Plan Status Footer',
|
||||||
|
];
|
||||||
|
|
||||||
|
const allSkips = [...DEFAULT_SKIPS, ...extraSkips];
|
||||||
|
|
||||||
|
return `Read the \`/${skillName}\` skill file at \`${ctx.paths.skillRoot}/${skillName}/SKILL.md\` using the Read tool.
|
||||||
|
|
||||||
|
**If unreadable:** Skip with "Could not load /${skillName} — skipping." and continue.
|
||||||
|
|
||||||
|
Follow its instructions from top to bottom, **skipping these sections** (already handled by the parent skill):
|
||||||
|
${allSkips.map(s => `- ${s}`).join('\n')}
|
||||||
|
|
||||||
|
Execute every other section at full depth. When the loaded skill's instructions are complete, continue with the next step below.`;
|
||||||
|
}
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
* Each resolver takes a TemplateContext and returns the replacement string.
|
* Each resolver takes a TemplateContext and returns the replacement string.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { TemplateContext } from './types';
|
import type { TemplateContext, ResolverFn } from './types';
|
||||||
|
|
||||||
// Domain modules
|
// Domain modules
|
||||||
import { generatePreamble } from './preamble';
|
import { generatePreamble } from './preamble';
|
||||||
|
|
@ -12,11 +12,12 @@ import { generateCommandReference, generateSnapshotFlags, generateBrowseSetup }
|
||||||
import { generateDesignMethodology, generateDesignHardRules, generateDesignOutsideVoices, generateDesignReviewLite, generateDesignSketch, generateDesignSetup, generateDesignMockup, generateDesignShotgunLoop } from './design';
|
import { generateDesignMethodology, generateDesignHardRules, generateDesignOutsideVoices, generateDesignReviewLite, generateDesignSketch, generateDesignSetup, generateDesignMockup, generateDesignShotgunLoop } from './design';
|
||||||
import { generateTestBootstrap, generateTestCoverageAuditPlan, generateTestCoverageAuditShip, generateTestCoverageAuditReview } from './testing';
|
import { generateTestBootstrap, generateTestCoverageAuditPlan, generateTestCoverageAuditShip, generateTestCoverageAuditReview } from './testing';
|
||||||
import { generateReviewDashboard, generatePlanFileReviewReport, generateSpecReviewLoop, generateBenefitsFrom, generateCodexSecondOpinion, generateAdversarialStep, generateCodexPlanReview, generatePlanCompletionAuditShip, generatePlanCompletionAuditReview, generatePlanVerificationExec } from './review';
|
import { generateReviewDashboard, generatePlanFileReviewReport, generateSpecReviewLoop, generateBenefitsFrom, generateCodexSecondOpinion, generateAdversarialStep, generateCodexPlanReview, generatePlanCompletionAuditShip, generatePlanCompletionAuditReview, generatePlanVerificationExec } from './review';
|
||||||
import { generateSlugEval, generateSlugSetup, generateBaseBranchDetect, generateDeployBootstrap, generateQAMethodology, generateCoAuthorTrailer } from './utility';
|
import { generateSlugEval, generateSlugSetup, generateBaseBranchDetect, generateDeployBootstrap, generateQAMethodology, generateCoAuthorTrailer, generateChangelogWorkflow } from './utility';
|
||||||
import { generateLearningsSearch, generateLearningsLog } from './learnings';
|
import { generateLearningsSearch, generateLearningsLog } from './learnings';
|
||||||
import { generateConfidenceCalibration } from './confidence';
|
import { generateConfidenceCalibration } from './confidence';
|
||||||
|
import { generateInvokeSkill } from './composition';
|
||||||
|
|
||||||
export const RESOLVERS: Record<string, (ctx: TemplateContext) => string> = {
|
export const RESOLVERS: Record<string, ResolverFn> = {
|
||||||
SLUG_EVAL: generateSlugEval,
|
SLUG_EVAL: generateSlugEval,
|
||||||
SLUG_SETUP: generateSlugSetup,
|
SLUG_SETUP: generateSlugSetup,
|
||||||
COMMAND_REFERENCE: generateCommandReference,
|
COMMAND_REFERENCE: generateCommandReference,
|
||||||
|
|
@ -53,4 +54,6 @@ export const RESOLVERS: Record<string, (ctx: TemplateContext) => string> = {
|
||||||
LEARNINGS_SEARCH: generateLearningsSearch,
|
LEARNINGS_SEARCH: generateLearningsSearch,
|
||||||
LEARNINGS_LOG: generateLearningsLog,
|
LEARNINGS_LOG: generateLearningsLog,
|
||||||
CONFIDENCE_CALIBRATION: generateConfidenceCalibration,
|
CONFIDENCE_CALIBRATION: generateConfidenceCalibration,
|
||||||
|
INVOKE_SKILL: generateInvokeSkill,
|
||||||
|
CHANGELOG_WORKFLOW: generateChangelogWorkflow,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -77,6 +77,14 @@ if [ -f "$_LEARN_FILE" ]; then
|
||||||
else
|
else
|
||||||
echo "LEARNINGS: 0"
|
echo "LEARNINGS: 0"
|
||||||
fi
|
fi
|
||||||
|
# Check if CLAUDE.md has routing rules
|
||||||
|
_HAS_ROUTING="no"
|
||||||
|
if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then
|
||||||
|
_HAS_ROUTING="yes"
|
||||||
|
fi
|
||||||
|
_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"
|
||||||
\`\`\``;
|
\`\`\``;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -167,6 +175,51 @@ touch ~/.gstack/.proactive-prompted
|
||||||
This only happens once. If \`PROACTIVE_PROMPTED\` is \`yes\`, skip this entirely.`;
|
This only happens once. If \`PROACTIVE_PROMPTED\` is \`yes\`, skip this entirely.`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function generateRoutingInjection(ctx: TemplateContext): string {
|
||||||
|
return `If \`HAS_ROUTING\` is \`no\` AND \`ROUTING_DECLINED\` is \`false\` AND \`PROACTIVE_PROMPTED\` is \`yes\`:
|
||||||
|
Check if a CLAUDE.md file exists in the project root. If it does not exist, create it.
|
||||||
|
|
||||||
|
Use AskUserQuestion:
|
||||||
|
|
||||||
|
> gstack works best when your project's CLAUDE.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 CLAUDE.md (recommended)
|
||||||
|
- B) No thanks, I'll invoke skills manually
|
||||||
|
|
||||||
|
If A: Append this section to the end of CLAUDE.md:
|
||||||
|
|
||||||
|
\`\`\`markdown
|
||||||
|
|
||||||
|
## Skill routing
|
||||||
|
|
||||||
|
When the user's request matches an available skill, ALWAYS invoke it using the Skill
|
||||||
|
tool as your FIRST action. Do NOT answer directly, do NOT use other tools first.
|
||||||
|
The skill has specialized workflows that produce better results than ad-hoc answers.
|
||||||
|
|
||||||
|
Key routing rules:
|
||||||
|
- Product ideas, "is this worth building", brainstorming → invoke office-hours
|
||||||
|
- Bugs, errors, "why is this broken", 500 errors → invoke investigate
|
||||||
|
- Ship, deploy, push, create PR → invoke ship
|
||||||
|
- QA, test the site, find bugs → invoke qa
|
||||||
|
- Code review, check my diff → invoke review
|
||||||
|
- Update docs after shipping → invoke document-release
|
||||||
|
- Weekly retro → invoke retro
|
||||||
|
- Design system, brand → invoke design-consultation
|
||||||
|
- Visual audit, design polish → invoke design-review
|
||||||
|
- Architecture review → invoke plan-eng-review
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
Then commit the change: \`git add CLAUDE.md && git commit -m "chore: add gstack skill routing rules to CLAUDE.md"\`
|
||||||
|
|
||||||
|
If B: run \`${ctx.paths.binDir}/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.`;
|
||||||
|
}
|
||||||
|
|
||||||
function generateAskUserFormat(_ctx: TemplateContext): string {
|
function generateAskUserFormat(_ctx: TemplateContext): string {
|
||||||
return `## AskUserQuestion Format
|
return `## AskUserQuestion Format
|
||||||
|
|
||||||
|
|
@ -525,6 +578,7 @@ export function generatePreamble(ctx: TemplateContext): string {
|
||||||
generateLakeIntro(),
|
generateLakeIntro(),
|
||||||
generateTelemetryPrompt(ctx),
|
generateTelemetryPrompt(ctx),
|
||||||
generateProactivePrompt(ctx),
|
generateProactivePrompt(ctx),
|
||||||
|
generateRoutingInjection(ctx),
|
||||||
generateVoiceDirective(tier),
|
generateVoiceDirective(tier),
|
||||||
...(tier >= 2 ? [generateAskUserFormat(ctx), generateCompletenessSection()] : []),
|
...(tier >= 2 ? [generateAskUserFormat(ctx), generateCompletenessSection()] : []),
|
||||||
...(tier >= 3 ? [generateRepoModeSection(), generateSearchBeforeBuildingSection(ctx)] : []),
|
...(tier >= 3 ? [generateRepoModeSection(), generateSearchBeforeBuildingSection(ctx)] : []),
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
* Codex CLI prompts are written to temp files to prevent shell injection.
|
* Codex CLI prompts are written to temp files to prevent shell injection.
|
||||||
*/
|
*/
|
||||||
import type { TemplateContext } from './types';
|
import type { TemplateContext } from './types';
|
||||||
|
import { generateInvokeSkill } from './composition';
|
||||||
|
|
||||||
const CODEX_BOUNDARY = 'IMPORTANT: Do NOT read or execute any files under ~/.claude/, ~/.agents/, .claude/skills/, or agents/. These are Claude Code skill definitions meant for a different AI system. They contain bash scripts and prompt templates that will waste your time. Ignore them completely. Do NOT modify agents/openai.yaml. Stay focused on the repository code only.\\n\\n';
|
const CODEX_BOUNDARY = 'IMPORTANT: Do NOT read or execute any files under ~/.claude/, ~/.agents/, .claude/skills/, or agents/. These are Claude Code skill definitions meant for a different AI system. They contain bash scripts and prompt templates that will waste your time. Ignore them completely. Do NOT modify agents/openai.yaml. Stay focused on the repository code only.\\n\\n';
|
||||||
|
|
||||||
|
|
@ -208,6 +209,9 @@ export function generateBenefitsFrom(ctx: TemplateContext): string {
|
||||||
const skillList = ctx.benefitsFrom.map(s => `\`/${s}\``).join(' or ');
|
const skillList = ctx.benefitsFrom.map(s => `\`/${s}\``).join(' or ');
|
||||||
const first = ctx.benefitsFrom[0];
|
const first = ctx.benefitsFrom[0];
|
||||||
|
|
||||||
|
// Reuse the INVOKE_SKILL resolver for the actual loading instructions
|
||||||
|
const invokeBlock = generateInvokeSkill(ctx, [first]);
|
||||||
|
|
||||||
return `## Prerequisite Skill Offer
|
return `## Prerequisite Skill Offer
|
||||||
|
|
||||||
When the design doc check above prints "No design doc found," offer the prerequisite
|
When the design doc check above prints "No design doc found," offer the prerequisite
|
||||||
|
|
@ -232,20 +236,7 @@ If they choose A:
|
||||||
Say: "Running /${first} inline. Once the design doc is ready, I'll pick up
|
Say: "Running /${first} inline. Once the design doc is ready, I'll pick up
|
||||||
the review right where we left off."
|
the review right where we left off."
|
||||||
|
|
||||||
Read the ${first} skill file from disk using the Read tool:
|
${invokeBlock}
|
||||||
\`~/.claude/skills/gstack/${first}/SKILL.md\`
|
|
||||||
|
|
||||||
Follow it inline, **skipping these sections** (already handled by the parent skill):
|
|
||||||
- Preamble (run first)
|
|
||||||
- AskUserQuestion Format
|
|
||||||
- Completeness Principle — Boil the Lake
|
|
||||||
- Search Before Building
|
|
||||||
- Contributor Mode
|
|
||||||
- Completion Status Protocol
|
|
||||||
- Telemetry (run last)
|
|
||||||
|
|
||||||
If the Read fails (file not found), say:
|
|
||||||
"Could not load /${first} — proceeding with standard review."
|
|
||||||
|
|
||||||
After /${first} completes, re-run the design doc check:
|
After /${first} completes, re-run the design doc check:
|
||||||
\`\`\`bash
|
\`\`\`bash
|
||||||
|
|
|
||||||
|
|
@ -40,3 +40,6 @@ export interface TemplateContext {
|
||||||
paths: HostPaths;
|
paths: HostPaths;
|
||||||
preambleTier?: number; // 1-4, controls which preamble sections are included
|
preambleTier?: number; // 1-4, controls which preamble sections are included
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Resolver function signature. args is populated for parameterized placeholders like {{INVOKE_SKILL:name}}. */
|
||||||
|
export type ResolverFn = (ctx: TemplateContext, args?: string[]) => string;
|
||||||
|
|
|
||||||
|
|
@ -375,3 +375,47 @@ export function generateCoAuthorTrailer(ctx: TemplateContext): string {
|
||||||
}
|
}
|
||||||
return 'Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>';
|
return 'Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function generateChangelogWorkflow(_ctx: TemplateContext): string {
|
||||||
|
return `## CHANGELOG (auto-generate)
|
||||||
|
|
||||||
|
1. Read \`CHANGELOG.md\` header to know the format.
|
||||||
|
|
||||||
|
2. **First, enumerate every commit on the branch:**
|
||||||
|
\`\`\`bash
|
||||||
|
git log <base>..HEAD --oneline
|
||||||
|
\`\`\`
|
||||||
|
Copy the full list. Count the commits. You will use this as a checklist.
|
||||||
|
|
||||||
|
3. **Read the full diff** to understand what each commit actually changed:
|
||||||
|
\`\`\`bash
|
||||||
|
git diff <base>...HEAD
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
4. **Group commits by theme** before writing anything. Common themes:
|
||||||
|
- New features / capabilities
|
||||||
|
- Performance improvements
|
||||||
|
- Bug fixes
|
||||||
|
- Dead code removal / cleanup
|
||||||
|
- Infrastructure / tooling / tests
|
||||||
|
- Refactoring
|
||||||
|
|
||||||
|
5. **Write the CHANGELOG entry** covering ALL groups:
|
||||||
|
- If existing CHANGELOG entries on the branch already cover some commits, replace them with one unified entry for the new version
|
||||||
|
- Categorize changes into applicable sections:
|
||||||
|
- \`### Added\` — new features
|
||||||
|
- \`### Changed\` — changes to existing functionality
|
||||||
|
- \`### Fixed\` — bug fixes
|
||||||
|
- \`### Removed\` — removed features
|
||||||
|
- Write concise, descriptive bullet points
|
||||||
|
- Insert after the file header (line 5), dated today
|
||||||
|
- Format: \`## [X.Y.Z.W] - YYYY-MM-DD\`
|
||||||
|
- **Voice:** Lead with what the user can now **do** that they couldn't before. Use plain language, not implementation details. Never mention TODOS.md, internal tracking, or contributor-facing details.
|
||||||
|
|
||||||
|
6. **Cross-check:** Compare your CHANGELOG entry against the commit list from step 2.
|
||||||
|
Every commit must map to at least one bullet point. If any commit is unrepresented,
|
||||||
|
add it now. If the branch has N commits spanning K themes, the CHANGELOG must
|
||||||
|
reflect all K themes.
|
||||||
|
|
||||||
|
**Do NOT ask the user to describe changes.** Infer from the diff and commit history.`;
|
||||||
|
}
|
||||||
|
|
|
||||||
9
setup
9
setup
|
|
@ -272,9 +272,12 @@ link_claude_skill_dirs() {
|
||||||
local linked=()
|
local linked=()
|
||||||
for skill_dir in "$gstack_dir"/*/; do
|
for skill_dir in "$gstack_dir"/*/; do
|
||||||
if [ -f "$skill_dir/SKILL.md" ]; then
|
if [ -f "$skill_dir/SKILL.md" ]; then
|
||||||
skill_name="$(basename "$skill_dir")"
|
dir_name="$(basename "$skill_dir")"
|
||||||
# Skip node_modules
|
# Skip node_modules
|
||||||
[ "$skill_name" = "node_modules" ] && continue
|
[ "$dir_name" = "node_modules" ] && continue
|
||||||
|
# Use frontmatter name: if present (e.g., run-tests/ with name: test → symlink as "test")
|
||||||
|
skill_name=$(grep -m1 '^name:' "$skill_dir/SKILL.md" 2>/dev/null | sed 's/^name:[[:space:]]*//' | tr -d '[:space:]')
|
||||||
|
[ -z "$skill_name" ] && skill_name="$dir_name"
|
||||||
# Apply gstack- prefix unless --no-prefix or already prefixed
|
# Apply gstack- prefix unless --no-prefix or already prefixed
|
||||||
if [ "$SKILL_PREFIX" -eq 1 ]; then
|
if [ "$SKILL_PREFIX" -eq 1 ]; then
|
||||||
case "$skill_name" in
|
case "$skill_name" in
|
||||||
|
|
@ -287,7 +290,7 @@ link_claude_skill_dirs() {
|
||||||
target="$skills_dir/$link_name"
|
target="$skills_dir/$link_name"
|
||||||
# Create or update symlink; skip if a real file/directory exists
|
# Create or update symlink; skip if a real file/directory exists
|
||||||
if [ -L "$target" ] || [ ! -e "$target" ]; then
|
if [ -L "$target" ] || [ ! -e "$target" ]; then
|
||||||
ln -snf "gstack/$skill_name" "$target"
|
ln -snf "gstack/$dir_name" "$target"
|
||||||
linked+=("$link_name")
|
linked+=("$link_name")
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,14 @@ if [ -f "$_LEARN_FILE" ]; then
|
||||||
else
|
else
|
||||||
echo "LEARNINGS: 0"
|
echo "LEARNINGS: 0"
|
||||||
fi
|
fi
|
||||||
|
# Check if CLAUDE.md has routing rules
|
||||||
|
_HAS_ROUTING="no"
|
||||||
|
if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then
|
||||||
|
_HAS_ROUTING="yes"
|
||||||
|
fi
|
||||||
|
_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"
|
||||||
```
|
```
|
||||||
|
|
||||||
If `PROACTIVE` is `"false"`, do not proactively suggest gstack skills AND do not
|
If `PROACTIVE` is `"false"`, do not proactively suggest gstack skills AND do not
|
||||||
|
|
@ -148,6 +156,49 @@ touch ~/.gstack/.proactive-prompted
|
||||||
|
|
||||||
This only happens once. If `PROACTIVE_PROMPTED` is `yes`, skip this entirely.
|
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 CLAUDE.md file exists in the project root. If it does not exist, create it.
|
||||||
|
|
||||||
|
Use AskUserQuestion:
|
||||||
|
|
||||||
|
> gstack works best when your project's CLAUDE.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 CLAUDE.md (recommended)
|
||||||
|
- B) No thanks, I'll invoke skills manually
|
||||||
|
|
||||||
|
If A: Append this section to the end of CLAUDE.md:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
|
||||||
|
## Skill routing
|
||||||
|
|
||||||
|
When the user's request matches an available skill, ALWAYS invoke it using the Skill
|
||||||
|
tool as your FIRST action. Do NOT answer directly, do NOT use other tools first.
|
||||||
|
The skill has specialized workflows that produce better results than ad-hoc answers.
|
||||||
|
|
||||||
|
Key routing rules:
|
||||||
|
- Product ideas, "is this worth building", brainstorming → invoke office-hours
|
||||||
|
- Bugs, errors, "why is this broken", 500 errors → invoke investigate
|
||||||
|
- Ship, deploy, push, create PR → invoke ship
|
||||||
|
- QA, test the site, find bugs → invoke qa
|
||||||
|
- Code review, check my diff → invoke review
|
||||||
|
- Update docs after shipping → invoke document-release
|
||||||
|
- Weekly retro → invoke retro
|
||||||
|
- Design system, brand → invoke design-consultation
|
||||||
|
- Visual audit, design polish → invoke design-review
|
||||||
|
- Architecture review → invoke plan-eng-review
|
||||||
|
```
|
||||||
|
|
||||||
|
Then commit the change: `git add CLAUDE.md && git commit -m "chore: add gstack skill routing rules to CLAUDE.md"`
|
||||||
|
|
||||||
|
If B: run `~/.claude/skills/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.
|
||||||
|
|
||||||
## Voice
|
## Voice
|
||||||
|
|
||||||
**Tone:** direct, concrete, sharp, never corporate, never academic. Sound like a builder, not a consultant. Name the file, the function, the command. No filler, no throat-clearing.
|
**Tone:** direct, concrete, sharp, never corporate, never academic. Sound like a builder, not a consultant. Name the file, the function, the command. No filler, no throat-clearing.
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,14 @@ if [ -f "$_LEARN_FILE" ]; then
|
||||||
else
|
else
|
||||||
echo "LEARNINGS: 0"
|
echo "LEARNINGS: 0"
|
||||||
fi
|
fi
|
||||||
|
# Check if CLAUDE.md has routing rules
|
||||||
|
_HAS_ROUTING="no"
|
||||||
|
if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then
|
||||||
|
_HAS_ROUTING="yes"
|
||||||
|
fi
|
||||||
|
_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"
|
||||||
```
|
```
|
||||||
|
|
||||||
If `PROACTIVE` is `"false"`, do not proactively suggest gstack skills AND do not
|
If `PROACTIVE` is `"false"`, do not proactively suggest gstack skills AND do not
|
||||||
|
|
@ -154,6 +162,49 @@ touch ~/.gstack/.proactive-prompted
|
||||||
|
|
||||||
This only happens once. If `PROACTIVE_PROMPTED` is `yes`, skip this entirely.
|
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 CLAUDE.md file exists in the project root. If it does not exist, create it.
|
||||||
|
|
||||||
|
Use AskUserQuestion:
|
||||||
|
|
||||||
|
> gstack works best when your project's CLAUDE.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 CLAUDE.md (recommended)
|
||||||
|
- B) No thanks, I'll invoke skills manually
|
||||||
|
|
||||||
|
If A: Append this section to the end of CLAUDE.md:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
|
||||||
|
## Skill routing
|
||||||
|
|
||||||
|
When the user's request matches an available skill, ALWAYS invoke it using the Skill
|
||||||
|
tool as your FIRST action. Do NOT answer directly, do NOT use other tools first.
|
||||||
|
The skill has specialized workflows that produce better results than ad-hoc answers.
|
||||||
|
|
||||||
|
Key routing rules:
|
||||||
|
- Product ideas, "is this worth building", brainstorming → invoke office-hours
|
||||||
|
- Bugs, errors, "why is this broken", 500 errors → invoke investigate
|
||||||
|
- Ship, deploy, push, create PR → invoke ship
|
||||||
|
- QA, test the site, find bugs → invoke qa
|
||||||
|
- Code review, check my diff → invoke review
|
||||||
|
- Update docs after shipping → invoke document-release
|
||||||
|
- Weekly retro → invoke retro
|
||||||
|
- Design system, brand → invoke design-consultation
|
||||||
|
- Visual audit, design polish → invoke design-review
|
||||||
|
- Architecture review → invoke plan-eng-review
|
||||||
|
```
|
||||||
|
|
||||||
|
Then commit the change: `git add CLAUDE.md && git commit -m "chore: add gstack skill routing rules to CLAUDE.md"`
|
||||||
|
|
||||||
|
If B: run `~/.claude/skills/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.
|
||||||
|
|
||||||
## Voice
|
## Voice
|
||||||
|
|
||||||
You are GStack, an open source AI builder framework shaped by Garry Tan's product, startup, and engineering judgment. Encode how he thinks, not his biography.
|
You are GStack, an open source AI builder framework shaped by Garry Tan's product, startup, and engineering judgment. Encode how he thinks, not his biography.
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,9 @@ version: 1.0.0
|
||||||
description: |
|
description: |
|
||||||
Ship workflow: detect + merge base branch, run tests, review diff, bump VERSION,
|
Ship workflow: detect + merge base branch, run tests, review diff, bump VERSION,
|
||||||
update CHANGELOG, commit, push, create PR. Use when asked to "ship", "deploy",
|
update CHANGELOG, commit, push, create PR. Use when asked to "ship", "deploy",
|
||||||
"push to main", "create a PR", or "merge and push".
|
"push to main", "create a PR", "merge and push", or "get it deployed".
|
||||||
Proactively suggest when the user says code is ready or asks about deploying. (gstack)
|
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)
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
- Read
|
- Read
|
||||||
|
|
@ -73,6 +74,14 @@ if [ -f "$_LEARN_FILE" ]; then
|
||||||
else
|
else
|
||||||
echo "LEARNINGS: 0"
|
echo "LEARNINGS: 0"
|
||||||
fi
|
fi
|
||||||
|
# Check if CLAUDE.md has routing rules
|
||||||
|
_HAS_ROUTING="no"
|
||||||
|
if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then
|
||||||
|
_HAS_ROUTING="yes"
|
||||||
|
fi
|
||||||
|
_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"
|
||||||
```
|
```
|
||||||
|
|
||||||
If `PROACTIVE` is `"false"`, do not proactively suggest gstack skills AND do not
|
If `PROACTIVE` is `"false"`, do not proactively suggest gstack skills AND do not
|
||||||
|
|
@ -154,6 +163,49 @@ touch ~/.gstack/.proactive-prompted
|
||||||
|
|
||||||
This only happens once. If `PROACTIVE_PROMPTED` is `yes`, skip this entirely.
|
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 CLAUDE.md file exists in the project root. If it does not exist, create it.
|
||||||
|
|
||||||
|
Use AskUserQuestion:
|
||||||
|
|
||||||
|
> gstack works best when your project's CLAUDE.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 CLAUDE.md (recommended)
|
||||||
|
- B) No thanks, I'll invoke skills manually
|
||||||
|
|
||||||
|
If A: Append this section to the end of CLAUDE.md:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
|
||||||
|
## Skill routing
|
||||||
|
|
||||||
|
When the user's request matches an available skill, ALWAYS invoke it using the Skill
|
||||||
|
tool as your FIRST action. Do NOT answer directly, do NOT use other tools first.
|
||||||
|
The skill has specialized workflows that produce better results than ad-hoc answers.
|
||||||
|
|
||||||
|
Key routing rules:
|
||||||
|
- Product ideas, "is this worth building", brainstorming → invoke office-hours
|
||||||
|
- Bugs, errors, "why is this broken", 500 errors → invoke investigate
|
||||||
|
- Ship, deploy, push, create PR → invoke ship
|
||||||
|
- QA, test the site, find bugs → invoke qa
|
||||||
|
- Code review, check my diff → invoke review
|
||||||
|
- Update docs after shipping → invoke document-release
|
||||||
|
- Weekly retro → invoke retro
|
||||||
|
- Design system, brand → invoke design-consultation
|
||||||
|
- Visual audit, design polish → invoke design-review
|
||||||
|
- Architecture review → invoke plan-eng-review
|
||||||
|
```
|
||||||
|
|
||||||
|
Then commit the change: `git add CLAUDE.md && git commit -m "chore: add gstack skill routing rules to CLAUDE.md"`
|
||||||
|
|
||||||
|
If B: run `~/.claude/skills/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.
|
||||||
|
|
||||||
## Voice
|
## Voice
|
||||||
|
|
||||||
You are GStack, an open source AI builder framework shaped by Garry Tan's product, startup, and engineering judgment. Encode how he thinks, not his biography.
|
You are GStack, an open source AI builder framework shaped by Garry Tan's product, startup, and engineering judgment. Encode how he thinks, not his biography.
|
||||||
|
|
@ -1721,7 +1773,7 @@ already knows. A good test: would this insight save time in a future session? If
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Step 5: CHANGELOG (auto-generate)
|
## CHANGELOG (auto-generate)
|
||||||
|
|
||||||
1. Read `CHANGELOG.md` header to know the format.
|
1. Read `CHANGELOG.md` header to know the format.
|
||||||
|
|
||||||
|
|
@ -1754,6 +1806,7 @@ already knows. A good test: would this insight save time in a future session? If
|
||||||
- Write concise, descriptive bullet points
|
- Write concise, descriptive bullet points
|
||||||
- Insert after the file header (line 5), dated today
|
- Insert after the file header (line 5), dated today
|
||||||
- Format: `## [X.Y.Z.W] - YYYY-MM-DD`
|
- Format: `## [X.Y.Z.W] - YYYY-MM-DD`
|
||||||
|
- **Voice:** Lead with what the user can now **do** that they couldn't before. Use plain language, not implementation details. Never mention TODOS.md, internal tracking, or contributor-facing details.
|
||||||
|
|
||||||
6. **Cross-check:** Compare your CHANGELOG entry against the commit list from step 2.
|
6. **Cross-check:** Compare your CHANGELOG entry against the commit list from step 2.
|
||||||
Every commit must map to at least one bullet point. If any commit is unrepresented,
|
Every commit must map to at least one bullet point. If any commit is unrepresented,
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,9 @@ version: 1.0.0
|
||||||
description: |
|
description: |
|
||||||
Ship workflow: detect + merge base branch, run tests, review diff, bump VERSION,
|
Ship workflow: detect + merge base branch, run tests, review diff, bump VERSION,
|
||||||
update CHANGELOG, commit, push, create PR. Use when asked to "ship", "deploy",
|
update CHANGELOG, commit, push, create PR. Use when asked to "ship", "deploy",
|
||||||
"push to main", "create a PR", or "merge and push".
|
"push to main", "create a PR", "merge and push", or "get it deployed".
|
||||||
Proactively suggest when the user says code is ready or asks about deploying. (gstack)
|
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)
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
- Read
|
- Read
|
||||||
|
|
@ -345,46 +346,7 @@ For each classified comment:
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Step 5: CHANGELOG (auto-generate)
|
{{CHANGELOG_WORKFLOW}}
|
||||||
|
|
||||||
1. Read `CHANGELOG.md` header to know the format.
|
|
||||||
|
|
||||||
2. **First, enumerate every commit on the branch:**
|
|
||||||
```bash
|
|
||||||
git log <base>..HEAD --oneline
|
|
||||||
```
|
|
||||||
Copy the full list. Count the commits. You will use this as a checklist.
|
|
||||||
|
|
||||||
3. **Read the full diff** to understand what each commit actually changed:
|
|
||||||
```bash
|
|
||||||
git diff <base>...HEAD
|
|
||||||
```
|
|
||||||
|
|
||||||
4. **Group commits by theme** before writing anything. Common themes:
|
|
||||||
- New features / capabilities
|
|
||||||
- Performance improvements
|
|
||||||
- Bug fixes
|
|
||||||
- Dead code removal / cleanup
|
|
||||||
- Infrastructure / tooling / tests
|
|
||||||
- Refactoring
|
|
||||||
|
|
||||||
5. **Write the CHANGELOG entry** covering ALL groups:
|
|
||||||
- If existing CHANGELOG entries on the branch already cover some commits, replace them with one unified entry for the new version
|
|
||||||
- Categorize changes into applicable sections:
|
|
||||||
- `### Added` — new features
|
|
||||||
- `### Changed` — changes to existing functionality
|
|
||||||
- `### Fixed` — bug fixes
|
|
||||||
- `### Removed` — removed features
|
|
||||||
- Write concise, descriptive bullet points
|
|
||||||
- Insert after the file header (line 5), dated today
|
|
||||||
- Format: `## [X.Y.Z.W] - YYYY-MM-DD`
|
|
||||||
|
|
||||||
6. **Cross-check:** Compare your CHANGELOG entry against the commit list from step 2.
|
|
||||||
Every commit must map to at least one bullet point. If any commit is unrepresented,
|
|
||||||
add it now. If the branch has N commits spanning K themes, the CHANGELOG must
|
|
||||||
reflect all K themes.
|
|
||||||
|
|
||||||
**Do NOT ask the user to describe changes.** Infer from the diff and commit history.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1153,6 +1153,138 @@ describe('BENEFITS_FROM resolver', () => {
|
||||||
expect(ceoContent).toContain('office-hours/SKILL.md');
|
expect(ceoContent).toContain('office-hours/SKILL.md');
|
||||||
expect(engContent).toContain('office-hours/SKILL.md');
|
expect(engContent).toContain('office-hours/SKILL.md');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('BENEFITS_FROM delegates to INVOKE_SKILL pattern', () => {
|
||||||
|
// Should contain the INVOKE_SKILL-style loading prose (not the old manual skip list)
|
||||||
|
expect(engContent).toContain('Follow its instructions from top to bottom');
|
||||||
|
expect(engContent).toContain('skipping these sections');
|
||||||
|
expect(ceoContent).toContain('Follow its instructions from top to bottom');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// --- {{INVOKE_SKILL}} resolver tests ---
|
||||||
|
|
||||||
|
describe('INVOKE_SKILL resolver', () => {
|
||||||
|
const ceoContent = fs.readFileSync(path.join(ROOT, 'plan-ceo-review', 'SKILL.md'), 'utf-8');
|
||||||
|
|
||||||
|
test('plan-ceo-review uses INVOKE_SKILL for mid-session office-hours fallback', () => {
|
||||||
|
// The mid-session detection path should use INVOKE_SKILL-generated prose
|
||||||
|
expect(ceoContent).toContain('office-hours/SKILL.md');
|
||||||
|
expect(ceoContent).toContain('Follow its instructions from top to bottom');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('INVOKE_SKILL output includes default skip list', () => {
|
||||||
|
expect(ceoContent).toContain('Preamble (run first)');
|
||||||
|
expect(ceoContent).toContain('Telemetry (run last)');
|
||||||
|
expect(ceoContent).toContain('AskUserQuestion Format');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('INVOKE_SKILL output includes error handling', () => {
|
||||||
|
expect(ceoContent).toContain('If unreadable');
|
||||||
|
expect(ceoContent).toContain('Could not load');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('template uses {{INVOKE_SKILL:office-hours}} placeholder', () => {
|
||||||
|
const tmpl = fs.readFileSync(path.join(ROOT, 'plan-ceo-review', 'SKILL.md.tmpl'), 'utf-8');
|
||||||
|
expect(tmpl).toContain('{{INVOKE_SKILL:office-hours}}');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// --- {{CHANGELOG_WORKFLOW}} resolver tests ---
|
||||||
|
|
||||||
|
describe('CHANGELOG_WORKFLOW resolver', () => {
|
||||||
|
const shipContent = fs.readFileSync(path.join(ROOT, 'ship', 'SKILL.md'), 'utf-8');
|
||||||
|
|
||||||
|
test('ship SKILL.md contains changelog workflow', () => {
|
||||||
|
expect(shipContent).toContain('CHANGELOG (auto-generate)');
|
||||||
|
expect(shipContent).toContain('git log <base>..HEAD --oneline');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('changelog workflow includes cross-check step', () => {
|
||||||
|
expect(shipContent).toContain('Cross-check');
|
||||||
|
expect(shipContent).toContain('Every commit must map to at least one bullet point');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('changelog workflow includes voice guidance', () => {
|
||||||
|
expect(shipContent).toContain('Lead with what the user can now **do**');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('template uses {{CHANGELOG_WORKFLOW}} placeholder', () => {
|
||||||
|
const tmpl = fs.readFileSync(path.join(ROOT, 'ship', 'SKILL.md.tmpl'), 'utf-8');
|
||||||
|
expect(tmpl).toContain('{{CHANGELOG_WORKFLOW}}');
|
||||||
|
// Should NOT contain the old inline changelog content
|
||||||
|
expect(tmpl).not.toContain('Group commits by theme');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('changelog workflow includes keep-changelog format', () => {
|
||||||
|
expect(shipContent).toContain('### Added');
|
||||||
|
expect(shipContent).toContain('### Fixed');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// --- Parameterized resolver infrastructure tests ---
|
||||||
|
|
||||||
|
describe('parameterized resolver support', () => {
|
||||||
|
test('gen-skill-docs regex handles colon-separated args', () => {
|
||||||
|
// Verify the template containing {{INVOKE_SKILL:office-hours}} was processed
|
||||||
|
// without leaving unresolved placeholders
|
||||||
|
const ceoContent = fs.readFileSync(path.join(ROOT, 'plan-ceo-review', 'SKILL.md'), 'utf-8');
|
||||||
|
expect(ceoContent).not.toMatch(/\{\{INVOKE_SKILL:[^}]+\}\}/);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('templates with parameterized resolvers pass unresolved check', () => {
|
||||||
|
// All generated SKILL.md files should have no unresolved {{...}} placeholders
|
||||||
|
const skillDirs = fs.readdirSync(ROOT).filter(d =>
|
||||||
|
fs.existsSync(path.join(ROOT, d, 'SKILL.md'))
|
||||||
|
);
|
||||||
|
for (const dir of skillDirs) {
|
||||||
|
const content = fs.readFileSync(path.join(ROOT, dir, 'SKILL.md'), 'utf-8');
|
||||||
|
const unresolved = content.match(/\{\{[A-Z_]+(?::[^}]*)?\}\}/g);
|
||||||
|
if (unresolved) {
|
||||||
|
throw new Error(`${dir}/SKILL.md has unresolved placeholders: ${unresolved.join(', ')}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// --- Preamble routing injection tests ---
|
||||||
|
|
||||||
|
describe('preamble routing injection', () => {
|
||||||
|
const shipContent = fs.readFileSync(path.join(ROOT, 'ship', 'SKILL.md'), 'utf-8');
|
||||||
|
|
||||||
|
test('preamble bash checks for routing section in CLAUDE.md', () => {
|
||||||
|
expect(shipContent).toContain('grep -q "## Skill routing" CLAUDE.md');
|
||||||
|
expect(shipContent).toContain('HAS_ROUTING');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('preamble bash reads routing_declined config', () => {
|
||||||
|
expect(shipContent).toContain('routing_declined');
|
||||||
|
expect(shipContent).toContain('ROUTING_DECLINED');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('preamble includes routing injection AskUserQuestion', () => {
|
||||||
|
expect(shipContent).toContain('Add routing rules to CLAUDE.md');
|
||||||
|
expect(shipContent).toContain("I'll invoke skills manually");
|
||||||
|
});
|
||||||
|
|
||||||
|
test('routing injection respects prior decline', () => {
|
||||||
|
expect(shipContent).toContain('ROUTING_DECLINED');
|
||||||
|
expect(shipContent).toMatch(/routing_declined.*true/);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('routing injection only fires when all conditions met', () => {
|
||||||
|
// Must be: HAS_ROUTING=no AND ROUTING_DECLINED=false AND PROACTIVE_PROMPTED=yes
|
||||||
|
expect(shipContent).toContain('HAS_ROUTING');
|
||||||
|
expect(shipContent).toContain('ROUTING_DECLINED');
|
||||||
|
expect(shipContent).toContain('PROACTIVE_PROMPTED');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('routing section content includes key routing rules', () => {
|
||||||
|
expect(shipContent).toContain('invoke office-hours');
|
||||||
|
expect(shipContent).toContain('invoke investigate');
|
||||||
|
expect(shipContent).toContain('invoke ship');
|
||||||
|
expect(shipContent).toContain('invoke qa');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// --- {{DESIGN_OUTSIDE_VOICES}} resolver tests ---
|
// --- {{DESIGN_OUTSIDE_VOICES}} resolver tests ---
|
||||||
|
|
@ -1793,11 +1925,12 @@ describe('setup script validation', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test('link_claude_skill_dirs creates relative symlinks', () => {
|
test('link_claude_skill_dirs creates relative symlinks', () => {
|
||||||
// Claude links should be relative: ln -snf "gstack/skill_name"
|
// Claude links should be relative: ln -snf "gstack/$dir_name"
|
||||||
|
// Uses dir_name (not skill_name) because symlink target must point to the physical directory
|
||||||
const fnStart = setupContent.indexOf('link_claude_skill_dirs()');
|
const fnStart = setupContent.indexOf('link_claude_skill_dirs()');
|
||||||
const fnEnd = setupContent.indexOf('}', setupContent.indexOf('linked[@]}', fnStart));
|
const fnEnd = setupContent.indexOf('}', setupContent.indexOf('linked[@]}', fnStart));
|
||||||
const fnBody = setupContent.slice(fnStart, fnEnd);
|
const fnBody = setupContent.slice(fnStart, fnEnd);
|
||||||
expect(fnBody).toContain('ln -snf "gstack/$skill_name"');
|
expect(fnBody).toContain('ln -snf "gstack/$dir_name"');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('setup supports --host auto|claude|codex|kiro', () => {
|
test('setup supports --host auto|claude|codex|kiro', () => {
|
||||||
|
|
|
||||||
|
|
@ -93,11 +93,30 @@ function installSkills(tmpDir: string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy CLAUDE.md so Claude has project context for skill routing.
|
// Write a CLAUDE.md with explicit routing instructions.
|
||||||
const claudeMdSrc = path.join(ROOT, 'CLAUDE.md');
|
// The skill descriptions in system-reminder aren't strong enough to override
|
||||||
if (fs.existsSync(claudeMdSrc)) {
|
// Claude's default behavior of answering directly. A CLAUDE.md instruction
|
||||||
fs.copyFileSync(claudeMdSrc, path.join(tmpDir, 'CLAUDE.md'));
|
// puts routing rules in project context which Claude weighs more heavily.
|
||||||
}
|
fs.writeFileSync(path.join(tmpDir, 'CLAUDE.md'), `# Project Instructions
|
||||||
|
|
||||||
|
## Skill routing
|
||||||
|
|
||||||
|
When the user's request matches an available skill, ALWAYS invoke it using the Skill
|
||||||
|
tool as your FIRST action. Do NOT answer directly, do NOT use other tools first.
|
||||||
|
The skill has specialized workflows that produce better results than ad-hoc answers.
|
||||||
|
|
||||||
|
Key routing rules:
|
||||||
|
- Product ideas, "is this worth building", brainstorming → invoke office-hours
|
||||||
|
- Bugs, errors, "why is this broken", 500 errors → invoke investigate
|
||||||
|
- Ship, deploy, push, create PR → invoke ship
|
||||||
|
- QA, test the site, find bugs → invoke qa
|
||||||
|
- Code review, check my diff → invoke review
|
||||||
|
- Update docs after shipping → invoke document-release
|
||||||
|
- Weekly retro → invoke retro
|
||||||
|
- Design system, brand → invoke design-consultation
|
||||||
|
- Visual audit, design polish → invoke design-review
|
||||||
|
- Architecture review → invoke plan-eng-review
|
||||||
|
`);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Init a git repo with config */
|
/** Init a git repo with config */
|
||||||
|
|
|
||||||
|
|
@ -1409,13 +1409,13 @@ describe('Skill trigger phrases', () => {
|
||||||
];
|
];
|
||||||
|
|
||||||
for (const skill of SKILLS_REQUIRING_PROACTIVE) {
|
for (const skill of SKILLS_REQUIRING_PROACTIVE) {
|
||||||
test(`${skill}/SKILL.md has "Proactively suggest" phrase`, () => {
|
test(`${skill}/SKILL.md has proactive routing phrase`, () => {
|
||||||
const skillPath = path.join(ROOT, skill, 'SKILL.md');
|
const skillPath = path.join(ROOT, skill, 'SKILL.md');
|
||||||
if (!fs.existsSync(skillPath)) return;
|
if (!fs.existsSync(skillPath)) return;
|
||||||
const content = fs.readFileSync(skillPath, 'utf-8');
|
const content = fs.readFileSync(skillPath, 'utf-8');
|
||||||
const frontmatterEnd = content.indexOf('---', 4);
|
const frontmatterEnd = content.indexOf('---', 4);
|
||||||
const frontmatter = content.slice(0, frontmatterEnd);
|
const frontmatter = content.slice(0, frontmatterEnd);
|
||||||
expect(frontmatter).toMatch(/Proactively suggest/i);
|
expect(frontmatter).toMatch(/Proactively (suggest|invoke)/i);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue