ADR 0020: Dissolve .discern/ — one root config file, config-driven point-and-override, feature toggles
Amendments.
- Vocabulary: current pointers use
standards(formerlyratchets),[jobs]/[jobs.<name>](formerly[capabilities]/[checks.<name>]),Agent file(formerlyCompiled agent file),Project-owned file(formerly theYour files/Yourscategory), andGenerated file(formerlyThe binary's files); the retired product-category wording reads asdiscern, the gate, or the bar; the decisions below are unchanged.- ADR 0137 — Project Scripts: the config-pointing and ownership rule now applies to
[scripts].dir; Project Scripts live underdiscern script, not the root command namespace.
Status: accepted; supersedes ADR 0016; the single-root-file config footprint is narrowed for runtime per-worktree state by ADR 0025 (the resource ledger under .git/); the [features] set introduced here is later revised by ADR 0045 (which drops mcp — the MCP server became core infrastructure, not a toggle); the root-scatter defaults introduced here are consolidated under a visible discern/ namespace by ADR 0099, and the [features] set is retired outright by ADR 0101 — this ADR's config-pointing and ownership rules stand
Context
§ADR 0016 consolidated everything the kit owned under a hidden .discern/ namespace: config.toml, guidelines/, brief.md, recipes/, and skills/. That answered "discern is all over the place" — but the single-binary cutover changed the calculus, and three DX problems remained, all about the install footprint rather than the tool:
- It hid content you author. Guidance, recipes, and skills are things you write and want to see — burying them in a dotfolder is poor discoverability.
- It forced the binary's artifacts to cohabit with your files.
.discern/skills/held bundled skills (generated, gitignored, re-published) and authored skills (project-owned, tracked) in one directory — a part-tracked/part-ignored mess that silently de-tracked authored skills on upgrade. (The concrete trigger: a repo with hand-authored skills under.discern/skills/would lose them by following the upgrade guide literally.) - There was no provider-agnostic, config-driven way to point discern at your own conventions.
This is still pre-adoption beyond the maintainer, so the layout can change freely.
Decision
§Dissolve .discern/. The entire discern footprint in a project becomes one root file: discern.toml. Everything else is one of three things:
- Bundled in the binary — the engine (already), the built-in discern guidance (
templates/guidance/*), and the built-in skills (templates/skills/). - A config-pointed location you choose, with a sensible discoverable default, read only when present:
[guidance].sources(→guidance.md),[skills].dir(→./skills),[recipes].dir(→./recipes). - Generated files and directories discern writes (never project-owned): the Agent files (
AGENTS.mdtracked;CLAUDE.md/GEMINI.mdgitignored) and the materialized.claude/skills/.
Concretely:
- Root discovery keys on
discern.toml. The pre-6.discern/config.tomlis demoted to a legacy/migration-source marker (recognised so a not-yet-upgraded install still works and is carried forward). - Skills, guidance, recipes are bundled built-ins ⊕ project-owned config-pointed additions, project-owned sources overriding/extending — one consistent rule for all three.
- Skills materialize into the provider dir
.claude/skills/(gitignored): bundled skills as copies (their source is in the binary, out of the tree), authored skills as symlinks into[skills].dir(so edits are live). No directory is ever part-tracked/part-ignored —[skills].diris 100% project-owned,.claude/skills/is 100% generated.discern skills list|ejectmanage the set. - Built-in discern guidance is bundled, always-on, and feature-aware. The compiler assembles
[built-in base] + [built-in section per enabled feature] + [your [guidance].sources]into each provider file in[guidance].agents. A generated banner heads every output; onlyAGENTS.mdis tracked. [features]toggles whole subsystems (worktrees, standards, guidance, skills, docs); each defaults on. A disabled feature vanishes coherently: its verbs hide from--help(and error "feature disabled" if invoked), its hooks aren't written, its guidance section is omitted, and its doctor checks skip. This is distinct from[capabilities](the gate's command table) — they are different sections with different jobs..claude/is the provider's, not discern's. discern writes hooks and materializes skills there because that is where Claude Code looks; it is a write-target, never part of "where discern keeps its stuff."
This is a schema 5 → 6 migration (the first under the ADR 0014 chain to move the config back to the root — where the pre-0016 layout already had it).
Consequences
§- An empty install is one file:
discern.toml(plus the generatedAGENTS.md/CLAUDE.mdand the two integration files.claude/settings.json+.gitignore). As you opt in, your files appear in the open at paths you control. - The part-tracked/part-ignored skills bug is gone by construction (R1): the 5→6 migration splits
.discern/skills/by name — authored dirs move to./skills/, pristine bundled copies are pruned, and a customized bundled-named dir is preserved (moved to./skills/as an override) rather than lost. A fixture-backed test asserts the split. AGENTS.mdis tracked but generated. A loud banner and the docs say so; a staleAGENTS.mdfails CI'sgit diff --exit-code. Every other provider mirror is gitignored.- Downstream installs with custom recipes that sourced the old shell library still need a manual rewrite (the R3 contract from ADR 0019);
doctorflags them, and the upgrade guide calls it out. - This supersedes [ADR 0016]: the
.discern/namespace it introduced is gone. It also retires 0016's managed-skills relocation question — skills are now bundled-plus-authored with a clear override rule.
Alternatives considered
§- Keep
.discern/but un-hide the authored parts. Rejected: the real problem was the mixed-ownership directory and the lack of config-driven pointing, not merely the dot-prefix. A half-measure would keep the de-tracking trap. - Put authored skills/guidance under
.claude/. Rejected:.claude/is the provider's directory (gitignored, regenerated). Authored content must be the user's, tracked, and provider-agnostic. - Keep
AGENTS.mdgitignored like the other mirrors. Rejected: a tracked agent file makes guidance changes reviewable and gives CI a drift check; one tracked mirror is enough, andAGENTS.mdis the committed cross-tool standard. - A blanket prune of
.discern/skills/on migration. Rejected: it would lose hand-authored skills (the exact bug that triggered this). The by-name split with a content guard preserves authored work.