garrytan / garrytan/gstack

Generated SKILL.md trigger vocabulary lives in a 'triggers:' frontmatter key the Claude Code skill router never reads

Open
#2,286 0 comments 0 reactions 0 assignees View on GitHub
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.