feat(#1866): agent-side self-load of configured agent_skills

Each of the 22 consumer agents now self-loads its configured agent_skills
in its mandatory init step, so .planning/config.json agent_skills.<type>
reaches the agent on every runtime — including Cursor and /gsd-autonomous,
where Skill()-delegated workflow bash init did not reliably execute.

- gsd-core/references/agent-skills-bootstrap.md: shared contract
  (query + Read + dedup guard that skips when <agent_skills> is already
  in the prompt, so Claude's orchestrator-side injection never doubles)
- 22 agents/gsd-*.md: one self-load line naming the agent's own type
- gsd-core/workflows/autonomous.md: note that delegated agents self-load
- tests/agent-skills-bootstrap.test.cjs: regression + parity (CONSUMER_AGENTS
  bijection + fast-check property) — Generative-Fix-Divergence guard
- docs: ADR-1866, CONFIGURATION dual-injection How It Works, INVENTORY
  row, Changed changeset

Closes #1866
This commit is contained in:
Tom Boucher
2026-07-01 12:51:04 -04:00
parent c32698dc9e
commit 3c13903dcd
48 changed files with 736 additions and 417 deletions

View File

@@ -0,0 +1,60 @@
# Agent Skills Self-Load (Bootstrap)
> **Shared contract.** Every `agent_skills` consumer agent self-loads its configured
> skills in its mandatory init step, so a project's `.planning/config.json`
> `agent_skills.<agent-type>` mapping reaches the agent that actually does the work —
> even when the orchestrator did not run bash init (e.g. a runtime whose `Skill()`
> delegation does not reliably execute the delegated workflow's bash, such as Cursor;
> see open-gsd/gsd-core#1600 / #1601). This is the durable counterpart to the
> orchestrator-side injection documented under
> [Agent Skills Injection](../../docs/CONFIGURATION.md#agent-skills-injection).
## When to run
In your mandatory init step — right after `mandatory-initial-read.md` / the
`Project skills` discovery, before any other work.
## Steps
1. **Dedup guard (MANDATORY).** Look at your own prompt. If it already contains an
`<agent_skills>` block, the orchestrator already injected one — **skip self-load
entirely.** Loading a second copy wastes context on runtimes where orchestrator-side
injection also runs (e.g. Claude Code). The guard is what keeps the two seams from
doubling the block.
2. **Query your configured skills.** Use **your own agent type** — the `name:` value in
your frontmatter (e.g. an agent whose frontmatter says `name: gsd-executor` queries
`gsd-executor`). The query is read-only and idempotent — it exits 0 with an empty
block when nothing is configured for your type:
```bash
_AGENT_SKILLS=$(gsd_run query agent-skills <YOUR-FRONTMATTER-NAME> 2>/dev/null || true)
```
The runtime `gsd_run` resolver is the standard one from
`_runtime-launcher.snippet.sh`; your own init already defines it.
3. **Read every listed skill.** The block emits entries as `@<path>/SKILL.md`
includes — `Read` each one before starting work. If the block is empty, there is
nothing to do (zero overhead).
## What self-load does and does not cover
| Skill form | Self-loads? | Notes |
|---|---|---|
| Project-relative path (`skills/my-skill`) | ✅ everywhere | `Read` the `@`-include |
| Global personal (`global:<name>`) | ✅ everywhere | resolves to the runtime global skills dir, then `Read` |
| Plugin-provided (`global:<plugin>:<skill>`) | Claude only | emitted as a Skill-tool directive on Claude; **skipped with a warning on all other runtimes** — the plugin/Skill-tool model has no equivalent elsewhere (#1601, #1258). Not closeable on Cursor. |
## Notes
- **Idempotent and read-only.** `query agent-skills` never mutates state; calling it
twice (once by the orchestrator, once by the agent) is harmless because the dedup
guard suppresses the second load.
- **No new config keys.** This reuses the existing `agent_skills` map and the existing
`buildAgentSkillsBlock` / `cmdAgentSkills` machinery (`src/init.cts`). The 22 consumer
agent types are mirrored in `tests/agent-skills.test.cjs` (`CONSUMER_AGENTS`) and
guarded against drift by `tests/agent-skills-bootstrap.test.cjs`.
- **Checkers / read-only agents.** Bash is universal across consumer agents, so
self-load works for plan-checkers, verifiers, and auditors too; the bootstrap assumes
no tool an agent lacks.

View File

@@ -114,6 +114,8 @@ If `TO_PHASE` is set, display: `Stopping after phase ${TO_PHASE}`
If `INTERACTIVE` is set, display: `Mode: Interactive (discuss inline, plan+execute inline — background on Codex only)`
If `PLAN_STRATEGY` is `converge`, display: `Planning: Plan-review convergence enabled`
**Agent skills (delegated agents self-load):** This workflow delegates plan/execute/review via flat `Skill()` invocations rather than resolving `agent_skills` itself. Each consumer agent (`gsd-planner`, `gsd-executor`, `gsd-plan-checker`, `gsd-verifier`, …) self-loads its configured `.planning/config.json` `agent_skills` in its own mandatory init step per `@~/.claude/gsd-core/references/agent-skills-bootstrap.md`. This is the durable path that works on every runtime — including Cursor, where `Skill()`-delegated workflow bash init does not reliably execute. No per-delegation injection is needed here. See open-gsd/gsd-core#1866.
</step>
<step name="discover_phases">