# Repository contract

## Repository file

Edit `AGENTS.md`, never `CLAUDE.md`. `CLAUDE.md` is a symlink, so replacing it forks the two files.

## Canonical baseline

Make every persona or doctrine change in `system-prompt-baseline.md`; it is the only source of truth. The Claude Code loader resolves no references, so each of the six output styles under `plugins/odin-core/output-styles/` embeds the full baseline as its tail, byte-identical from its second `<role>` through EOF. The generator owns that tail; never hand-propagate it:

1. Edit `system-prompt-baseline.md` without changing an output style below its charter `<role>`.
2. Run `python3 scripts/sync-baseline.py`. It replaces each style from its second `<role>` through EOF and preserves the persona preamble above it.
3. Run `python3 scripts/sync-baseline.py --check`. Exit 0 means all styles match; exit 1 names drifted files; exit 2 means the canonical file or a required two-`<role>` layout is missing.
4. Stage and commit the canonical file and all six styles together.

Never hand-edit `plugins/odin-core/output-styles/benchmark.md`. Its margin-runner v0.5.5 header marks it as generated. The baseline generator may change only the embedded cascade below the runner preamble; a hand edit above that region requires explicit user authorization.

## Submodule publishing

Commit and push from this repository, not its parent `~/.claude`, because this tree is a Git
submodule. This checkout's `.git` is an unwritable submodule pointer, so git operations must run
in a clone inside `.outline/worktree/<name>`, never in `/tmp`, where work is easily lost.

Never force-push, and that includes every `--force-with-lease` variant: a lease protects the
remote from a stale overwrite and protects nothing from a rewrite you intended. On a branch with
an open pull request, rewriting history strands every inline review comment on commits that no
longer exist, and no permission error tells you that.

If a push is rejected as non-fast-forward, the answer is to fetch and rebase or to ask, never to
reach for a force variant.

## The skill tree

A skill is authored once, at `plugins/<plugin>/skills/<slug>/SKILL.md`. That path is its only home, and the directory states which plugin owns the skill. Do not add a membership registry, a second skill tree, or a per-plugin copy: the earlier model kept all three in sync and each one drifted.

Adding a skill means creating `plugins/<plugin>/skills/<slug>/SKILL.md` and running `just render`.

Moving a skill between plugins means moving its directory. Nothing else records membership. For a batch of moves, or for creating, merging, or retiring a plugin, run the `retaxonomize-plugins` skill; it rewrites `catalog/plugins.json`, replaces retired ids in authored files, regenerates, and proves the gates.

Each harness reads the immediate children of `skills/`, so a skill nested deeper than `skills/<slug>/` never loads.

## Distribution surfaces

Five harness surfaces are supported, and no others: Claude Code, Codex, Cursor, Grok, and Kimi. Nothing is published to a package registry, and no npm artifact belongs in this tree. A flat Devin mirror of these same skills is exported to the outline repository, which publishes nothing and installs nothing.

`catalog/plugins.json` owns plugin identity: name, description, category, tags, and directory. Every manifest and registry is generated from it. Keep every plugin and marketplace version at the single `releaseVersion` literal `2.1.0`; never bump only some manifests.

Treat these as generator-owned and never hand-edit them:

- `plugins/*/.claude-plugin/plugin.json`, `plugins/*/.codex-plugin/plugin.json`, `plugins/*/.cursor-plugin/plugin.json`, `plugins/*/.grok-plugin/plugin.json`, `plugins/*/.kimi-plugin/plugin.json`, `plugins/*/README.md`, `plugins/*/LICENSE`, `plugins/*/NOTICE`
- `.claude-plugin/marketplace.json`, `.codex-plugin/marketplace.json`, `.cursor-plugin/marketplace.json`, `.grok-plugin/marketplace.json`, `.kimi-plugin/marketplace.json`
- `plugins/*/skills/*/agents/openai.yaml`
- the plugin table under `## Plugins` in the root `README.md`, and nothing else in that file
- `docs/specs/skill-index.md`

To change one, change its generator or `catalog/plugins.json`, run `just render`, and commit input and output together.

Each harness dotdir manifest declares only what its own defaults do not already resolve: Kimi needs `skills`, and Codex and Grok need `mcpServers` where a plugin ships the dotless `mcp.json`. Do not add component declarations a harness resolves by convention.

Bump `releaseVersion` by one patch (`+0.0.1`) for every change that ships a skill, output style, manifest, or attribution; bump the minor version only on explicit request. Three authored copies carry the literal, and the bump commit updates all three: `catalog/plugins.json`, the literal in this file, and the sentence under the skill count in the root `README.md`. Run `just render` and commit the catalog with its generated output. Do not change `releaseVersion` for tooling-only changes such as pre-commit hooks or formatter configuration, or for edits to this file alone. Do not add or backfill `CHANGELOG.md` entries for routine version work; a bump that ships a skill or behavior change gets one entry.

A plugin id names a job someone is doing or a stack they are working in. A tier suffix such as `-advanced` is not a job, and a grab-bag id that collects whatever fits is not one either; split by job instead. `scripts/check-plugin-surfaces.mjs` rejects a tier-suffixed id, so the rule fails a commit rather than a review.

## Devin skill mirror

The outline repository carries a flat copy of every skill at `.devin/skills/<slug>/`, the
project-scope path Devin reads. `scripts/sync-outline-skills.mjs` generates it from this tree, so
it is an export of the same skills rather than a sixth distribution surface.

Regenerate it with `just sync-outline`. The default target is the sibling checkout
`../outline-driven-development`, resolved from this tree's own parent directory, so from a clone
under `.outline/worktree/` it points at a directory that does not exist; pass
`--target <path-of-the-real-outline-checkout>` there. The script mirrors
exactly the files git tracks under each skill directory, prunes anything under `.devin/skills/`
that the plugin tree no longer carries, and refuses a target that does not hold both
`manifest.json` and `.git`.

Never hand-edit the mirror. Edit the skill under `plugins/<plugin>/skills/<slug>/` and resync,
because the next run reverts an edit made in the mirror.

A skill whose `SKILL.md` is untracked is a sync error, not a skip. Add the file to git first.

The mirror lives in another repository with its own history, so commit it there, in its own
commit, and never from this repository.

## Skill metadata

Frontmatter carries `name` and `description` and little else. `name` must equal the directory name, or `gh skill install` drops the skill. `description` must open with a trigger a model can route on; `scripts/check-skill-routes.mjs` accepts `Use when ` and its listed variants and rejects `Use when,` or a bare imperative, and its first sentence becomes the generated `short_description`.

Single-quote every frontmatter value containing `: `. Strict YAML parsers reject an unquoted colon-space even though Claude Code's loader accepts it, so it ships silently broken.

Do not add a `license` field to a skill. This tree has mixed provenance and attribution lives in `licenses/NOTICE`; a uniform value would misstate the provenance of adapted skills.

## Verification

Before a commit, run `just check`; it runs every hook in `.pre-commit-config.yaml` over the whole tree (`prek run --all-files`) and can repair the style cascade, so read `git status` afterwards. `just verify` adds `gh skill publish --dry-run`, which validates all 543 skills against the Agent Skills specification; its `recommended field missing: license` advisories are accepted, not fixed.

Do not invent language test commands or add CI without an explicit request; this repository has no build, no unit-test suite, and no GitHub Actions workflow.

Test persona or doctrine changes in a fresh Claude Code session. The canonical baseline and output styles load only at session start, so the current session cannot verify them.

## Prompt audit

Run the `prompt-optimizer` skill in audit mode when a prompt, skill, output style, or tool description changes behavior, and again at each model release. Publish its report and proposed diff. Apply only high- and medium-confidence hunks with explicit consent, and leave low-confidence and flagged items in the report.

Ground every prompting claim in a current vendor guide. Re-fetch the guides in `plugins/odin-skills/skills/prompt-optimizer/references/prompt-guides.md` before an audit run, at each model release, and whenever a row is older than one release cycle. Update the index in the same change: stamp each re-read row `Verified <ISO date>`, move a superseded guide to the legacy-avoid rows and name its successor, and add the new model's guide as a current row. A claim whose row is stale is unverified: report it and keep it out of any applied diff.

## External harness carriers

Propagate every shared doctrine change to `~/.codex/AGENTS.md` and `~/.omp/agent/AGENTS.md` with `just sync-carriers`, and prove it with `just sync-carriers-check` (`scripts/check-carriers.py` is the same gate as a pre-commit hook). The baseline generator does not touch these carriers.

Each carrier holds every shared section of the baseline byte for byte, `<change_discipline>` included. The four tool-layer sections, `<git>`, `<directives>`, `<code_tools>`, and `<thinking>`, differ by design and are compared for presence only: Codex shells out through `rtk`; omp and Claude Code provide native file tools.

Edit both carriers in place. Never commit them from this repository, and never stage `~/.codex/config.toml`; their owning repositories live outside this submodule.

## Writing style

Write content under this tree so each section is independently actionable: state a needed rule where the reader needs it, and let no sentence send the reader back to an earlier passage for it.

Prefer a short repeated rule to a decorative inter-file pointer. Use a cross-reference only when the target itself is required for correct behavior, such as the byte-identical canonical baseline span.

## Voice

Every skill in this tree is authored in one register, set by the ODIN doctrine in
`system-prompt-baseline.md` and the spine taste anchors. `docs/specs/voice.md` is the contract.

The spine itself is user-private, at `~/.claude/skills/spine/`. Read it when authoring; never
edit it from this repository, and never vendor a copy into this tree. `docs/specs/voice.md`
carries what an editor needs without loading it.

Passing `scripts/check-voice.py` is not passing the register. That script sees formatting
tells, not absent conviction; whether a section earns its place is the spine audit's
judgment, not a regular expression's.
