# 6. `shared/core/` vs `shared/external/` source organization

**Status:** Accepted · 2026-04 (v5.3.3) · The "install destination is unchanged" clause is superseded by [ADR-0009](./0009-claude-stack-skills-plugin-only.md) (v15.0.0): Claude Code no longer receives the external tree; Copilot/Codex receive a stack-filtered subset.

## Context

ADR-0003 (v3.5.0) collapsed the split `skills/claude/` + `skills/copilot/` into a single `skills/shared/` tree. That resolved drift between CLIs and made skill authoring a single-write operation. Two years later the flat tree carries 148 directories.

By v5.3.x the maintenance burden of the flat tree became visible in everyday work:

- **Source navigation.** Browsing `pipeline/skills/shared/` on GitHub shows 148 sibling directories with no hint which ones are load-bearing for the pipeline vs. which ones are third-party imports.
- **Code review cost.** Changes under `shared/` have very different risk profiles depending on which kind of skill changed. `multi-agent-sync/SKILL.md` is pipeline-critical - any drift breaks cross-CLI parity. `ios-developer/SKILL.md` is a reference guide imported from upstream - edits almost never affect pipeline behavior.
- **Grep noise.** `grep -r skills/shared/` produces 148× the noise it should when searching for pipeline code.
- **Audit findings.** The v5.3.0 audit flagged this as technical debt worth addressing once the pipeline stabilized.

## Decision

Keep the single-write benefit of ADR-0003. Split the source layout into two subdirectories by origin / blast radius:

```
pipeline/skills/shared/
├── core/         - 21 multi-agent* orchestration skills (pipeline-critical)
├── external/     - 127 iOS / Android / generic skills imported from upstream
└── README.md     - skill index
```

**Install destination is unchanged.** Both trees flatten into `~/.claude/skills/` and `~/.copilot/skills/`; skill discovery at runtime sees the same flat list of 148 skills regardless of where they live in source. ADR-0003's core decision ("same coverage on both CLIs") is preserved.

`install.js` was updated to `copyDir(sharedCoreSrc, CLAUDE_SKILLS)` + `copyDir(sharedExternalSrc, CLAUDE_SKILLS)` - two reads, same flat write.

## Consequences

Positive:

- Source browsing separates the 21 files that get changed by pipeline work from the 127 that get refreshed on upstream sync.
- Code review can apply different scrutiny by subdirectory. A PR touching `external/*` is almost always a mechanical refresh; a PR touching `core/*` is pipeline logic.
- Grep / Glob queries can scope to `core/` or `external/` cheaply (`rg --glob 'shared/core/**'`).
- Prepares for a future per-stack install filter (ADR-0003's deferred "skills/ios/" idea) by making "external" a single unit.

Negative:

- `install.js` walks two source trees instead of one. Implementation cost: 6 lines.
- Every smoke test and doc reference that hard-coded `pipeline/skills/shared/multi-agent-*/` as a path had to update to `pipeline/skills/shared/core/multi-agent-*/`. One-time sweep.
- ADR-0003's "single source of truth" wording becomes "single install target from two logical sources" - slightly more nuance to explain.

## Alternatives Considered

**Per-stack tree (`skills/ios/`, `skills/android/`, ...):** the original idea ADR-0003 deferred. Rejected for v5.3.x because install-time stack filtering still needs a stack detector accurate enough not to exclude relevant cross-cutting skills (e.g. `api-security-best-practices` applies to both backend and mobile). Revisit when the stack-detection story is solid.

**Leave the flat tree alone:** the 148-dir tree is cosmetically ugly but functionally correct. Rejected because the blast-radius distinction between `multi-agent*` skills and upstream mirrors is real and recurring; naming it in the source layout documents it.

**Soft categorization via `SKILL.md` frontmatter (`category: core`):** would support tooling but wouldn't help the primary use case (source browsing on GitHub). Rejected as insufficient on its own.
