Generated SKILL.md trigger vocabulary lives in a 'triggers:' frontmatter key the Claude Code skill router never reads
- Dominant language
- TypeScript
- Stars
- 133k
- Forks
- 19.9k
- Avg merge
- 18h 46m
- Merged PRs (30d)
- 26
Description
## Problem
gstack-generated `SKILL.md` files (via `gen:skill-docs` / `scripts/gen-skill-docs.ts`) store their real trigger vocabulary in a nonstandard `triggers:` YAML frontmatter key. Claude Code's skill router only reads `name:` and `description:` from frontmatter — it never sees `triggers:` — so those phrases contribute nothing to routing and the affected skills are under-triggered.
Concrete example from `qa/SKILL.md` at v1.60.1.0:
```yaml
description: Systematically QA test a web application and fix bugs found. (gstack)
triggers:
- qa test this
- find bugs on site
- test the site
```
A user saying "find bugs on site" has no lexical overlap with the description the router actually reads, so the skill often doesn't fire. In practice we see roughly 30 gstack skills that under-trigger this way; on `main` at v1.60.1.0, 55 of 59 generated `SKILL.md` files carry a `triggers:` key.
Users also can't fix this locally: hand-edits to installed `SKILL.md` files are clobbered by the next `/gstack-upgrade` regeneration.
## Proposed fix
Have the generator merge the `triggers:` list into the generated `description:`, e.g. appending:
> Use when the user says "qa test this", "find bugs on site", "test the site".
so the router-visible surface carries the trigger vocabulary. The generator already does exactly this for the `voice-triggers:` key (`processVoiceTriggers` in `scripts/gen-skill-docs.ts` folds the list into the description and strips the field), so the plumbing pattern exists — it just doesn't cover `triggers:`.
I'm deliberately filing this as an issue rather than a PR: the change sits in a generator that emits ~400 skills, and it interacts with the catalog-trim work (the v1.45 "Catalog Trim" intentionally moved routing prose out of `description:` into `## When to invoke` sections and `scripts/proactive-suggestions.json` to cut always-loaded token cost). Merging `triggers:` into `description:` partially reverses that tradeoff, so the token budget vs. routing-recall balance deserves a maintainer decision rather than a drive-by patch.
## Environment
- gstack v1.60.1.0 (also confirmed on current `main`)
- Claude Code as the skill host
Contributor guide
Research direction
Start with scripts/gen-skill-docs.ts and its processVoiceTriggers implementation, then run gen:skill-docs to inspect the generated SKILL.md files. Compare the handling of voice-triggers: with triggers: and review the catalog-trim context before deciding how routing vocabulary should be represented. Done means generated descriptions expose the intended trigger phrases without leaving an unused triggers: key.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100