## Do all skills flow together?
**No — not until this PR.** Investigating the question surfaced a
structural gap: skill dependencies are declared across **three
overlapping frontmatter fields that drifted apart and were never
reconciled**, and nothing enforced connectivity or constrained the
`consumes` vocabulary.
| Field | Meaning | Read by context-map? |
|-------|---------|----------------------|
| `consumes` | upstream inputs | yes (data-flow table) |
| `context_rel` | DDD relationship | yes (mermaid) |
| `metadata.dependencies` | upstream skill slugs | **no** |
Findings (76 skills):
- **33 skills** where `consumes` (skills) ≠ `metadata.dependencies` —
the two skill-slug fields disagree.
- The generated `context-map.md` **ignored `metadata.dependencies`
entirely** (34 skills, the richest layer).
- Counting all three layers, **16 true orphans** (incl. core skills like
`push`, `session-bootstrap`) with zero skill-to-skill edges — silently.
- `consumes` was an **open free-text field**: no check that a token
resolves to anything.
`scripts/audit-skill-metadata.sh` already flagged the
`consumes`-vocabulary and connectivity checks as *"discovered
follow-ups, not enforced."* This is that follow-up.
## What this PR does
**1. Connectivity gate** — `scripts/validate-skill-flow.sh` (+
`validate-skill-flow` CI job):
- **Closed `consumes` vocabulary**: every token must resolve to a skill
slug, a whitelisted external input (`repo-context`, `external-api`,
`bd`, `github-pr`, `onboard`), or an artifact some skill produces.
Catches typos/undeclared deps.
- **`metadata.dependencies` resolution**: every entry must name a real
skill.
- **Orphan detection** across all three edge layers; un-allowlisted
orphans fail.
- Reports (non-fatal): cross-layer disagreement + dead-end artifacts, so
they can be reconciled later.
**2. Wire the genuine-gap edges** — added `context_rel` for 6
disconnected skills and regenerated `context-map.md`:
- `deps` → `vibe`, `red-team` → `vibe` (mirrors
`security`/`security-suite`)
- `provenance` ↔ `trace`
- `scenario` → `validation`
- `release` → `ship-loop`
**3. Close the vocabulary** — the closed `consumes` namespace is
enforced by the gate and documented in `docs/contracts/skill-flow.md`
(linked in `documentation-index.md`). 14 intentionally-standalone leaves
are allowlisted in `scripts/skill-flow-standalone.txt` with a rationale
per entry.
## Verification
```
$ bash scripts/validate-skill-flow.sh
validate-skill-flow: 76 skill(s), 121 skill-to-skill edge(s)
orphans: 14 (allowlisted standalone: 14)
OK: skill flow is connected and the consumes vocabulary is closed.
```
- `validate-skill-flow.sh`: exit 0 ✅
- `validate-context-map-drift.sh`: exit 0 ✅
- `check-contracts-structural-floor.sh`: PASS (contract cataloged) ✅
- 11 acceptance tests in `tests/scripts/validate-skill-flow.bats` (bats
not installed locally; exercised via manual smoke + will run in CI
`bats-tests`).
Bounded-context: BC1-Corpus
Evidence: OK: skill flow is connected and the consumes vocabulary is
closed.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01WLdHEva31cixBjxo8z9TXK)_
Co-authored-by: Claude <noreply@anthropic.com>