# Agent Instructions

This repo is **etna — the forge** where every Nurix harness is authored: skills, agents, rules, and harness definitions, composed into plugins and shipped to consumer repos by the `@nurix/etna` CLI. Working here means editing **authoring artifacts** — almost all markdown, plus the CLI and hook scripts (ESM JS) — not application source. etna has no `src/` app, no database, and no runtime API of its own; the usual code-project scaffolding (schema, wire contracts, a test suite) mostly doesn't apply, and where a rule below would in a normal repo, it's reframed for the forge.

etna governs itself with the **`etna`** harness — deliberately forked from the **`code`** harness it ships, so a capability added to `code` (a new mode, a new agent) never silently lands in the forge's own governance. Rules marked **[override]** deliberately replace a Claude Code default; the rule here wins.

---

## Documentation Is Not a Veto

**A document records what is; it never constrains what should be.** When a proposed change contradicts a doc — a feature doc, a harness `Readme.md`, an architecture passage, a past decision record — the doc is the thing that is out of date. Never cite it as a reason the change cannot proceed: the doc is downstream of the decision it would be defending, so that reasoning is circular and it is how a system ossifies.

Every change picks one order, and names which:

| Order | Sequence |
| --- | --- |
| **Harness first** | change the components → update the docs to match → check for inconsistencies |
| **Docs first** | rewrite the docs → reconcile them → bring the components to match |

Both are valid. The only legitimate blockers are **mechanical**: a contract that breaks at runtime, data that would be lost, a build that hard-fails, a reader left pointing at what no writer produces. "The documentation says otherwise" is never one — that is a task, not an objection.

---

## Maintenance

Invoke the `maintenance` agent whenever the docs look like they need it — not just at first setup: a missing `docs/structure.md` (the repo isn't reconciled — baseline before applying anything below), a `harness-version` marker behind the installed version, docs contradicting the components they describe, unowned source paths, or drift noticed while working. Never reconcile these by hand — the agent auto-selects its mode (baseline when the marker is missing or behind, coherence audit otherwise) and hands back; if it returns a follow-up (typically the module proposal), re-invoke it to finish. Each component's internals live in the component, not here.

---

## Getting Started

- Read **[`docs/structure.md`](docs/structure.md)** — the documentation authority map. The top level mirrors the source roots the forge ships from (`skills/`, `harness/`, `rules/`, `packages/`), plus `playbooks/` for the craft guides and `architecture/` for truth spanning two or more subjects. Don't restate it here.
- Read **[`docs/writing-style.md`](docs/writing-style.md)** before writing anything — the single style authority for this repo.
- Read **[`docs/memory/`](docs/memory/)** for agent memory files (one per agent).
- Prefer `docs/` over `README.md` — `docs/` is canonical for agents.
- The CLI and hooks are the only real code — detect the package manager from the lockfile (see `.claude/rules/general.md`) for anything under `packages/`.

---

## Authoring & Distribution

etna authors the components it also runs and ships, so **three copies of every component exist** — know which copy an edit lands in:

| Copy | Where | Role |
| --- | --- | --- |
| **Source** (canonical) | the shared catalogs — `skills/`, `agents/`, `rules/`, plus `harness/*/` (each harness — its `readme.md` manifest, `CLAUDE.md` policy, and owned trees in one folder) | Edit here. Etna is the source of truth. |
| **Dogfood** | `.claude/skills/`, `.claude/agents/`, `.claude/rules/`, `.claude/hooks/` (git-tracked) | The subset the `etna` harness installs on itself — the copy this repo actually runs this session. |
| **Shipped bundle** | `packages/cli/data/harnesses/*/` (generated by `packages/cli/scripts/build-data.js`; gitignored except each harness `CLAUDE.md`, and rebuilt by `prepack` on every publish) | Generated — never hand-edit. |

- **Keep source and dogfood in sync.** When a dogfooded component's source changes, mirror the edit into its `.claude/` copy in the same change — otherwise the skill this session runs diverges from the authored one.
- **A component edit ships.** On push to `dev`, CI fingerprints the payload, patch-bumps, and publishes to the marketplace and `@nurix/etna` npm — reaching every consumer repo. Weigh catalog edits with that blast radius in mind. The pipeline authority is **[`docs/architecture/distribution.md`](docs/architecture/distribution.md)** — link, don't restate.

---

## Workflows

Three peer modes plus a Completion step — enter wherever the user's thinking already is. Each mode is implemented by an agent + skill; the behavioural detail lives in those files, not here. "Code" below means **authoring artifacts** — a feature LLD owns `skills/**`, `harness/**`, `packages/cli/**`, not `src/`.

| Mode | Enter when | Implemented by | Exits to |
| --- | --- | --- | --- |
| **Brainstorming** | explicit ask (`/brainstorm start`); or offer a session — never auto-enter — when the user brings a large piece of work (name what makes it big) or an utterance contradicts a recorded pillar (name the principle) | `brainstorm` agent + skill | LLD, Plan, or close + harvest |
| **LLD** (low-level design) | new component/feature work | `lld-mode` agent + `documentation` skill | Plan |
| **Plan** | an LLD is approved | `documentation` skill → `docs/history/plans/YYYY-MM-DD-{slug}.md` | Completion |

> Brainstorm entry needs a **basis** — a reference document or a one-shot brain dump; drip-sized asks (a one-line fix) are too small and get redirected. A **pillar** is a recorded strategic principle from a past brainstorm: in-progress sessions under `docs/research/`, harvested ones under `docs/history/brainstorms/`, harvested doctrine under `docs/architecture/`. The LLD is the component's own doc — `docs/skills/{name}/`, `docs/harness/{name}/`, or `docs/packages/{name}.md` — design intent first, extended in place at Completion.

**On Plan Completion:**

1. Freeze the plan — `Status: Complete`, fill the Completed date. The file is now frozen.
2. **Discharge the plan's Doc Obligations ledger — every row, into exactly one outcome**: **updated**, **owes nothing** (with the reason), or **blocked** (→ backlog). For each row's doc: flip `status: active` if it was `draft`, extend it in place with the how-it-works sections, confirm its `owns:` globs against the actual components. The ledger, not memory, says how many docs this plan owes.
3. The `boundary` skill must already have gated this plan before its first implementation step — see Ownership, Boundaries & Documentation.

**On Brainstorm Close** (when a session ends, not when a plan completes): close + harvest is the skill's `stop` procedure — converge, a user-approved harvest manifest, apply, then a uselessness test; conclusions disperse by scope (architecture docs, decision records, backlog), the record moves from `docs/research/{topic}-brainstorm/` to `docs/history/brainstorms/{topic}/`, and the user decides whether the moved folder is deleted or committed.

---

## Ownership, Boundaries & Documentation

These three mechanisms keep the repo self-updating: **ownership** routes an edit to the canonical doc before the component is touched, the **boundary** check reads both sides of every contract a change participates in so one side never ships alone, and **documentation** closes the loop so the next session inherits the truth. Skipping any leg breaks the other two.

### Ownership — route before editing

**Ownership is declared, not positional.** Any document under `docs/` carrying `owns:` frontmatter claims those code paths — path globs pointing at `skills/**`, `harness/**`, `packages/**`, … — plus an optional `module:` label, `keywords:`, and `status:`. The SessionStart hook scans the whole tree and builds the injected index from the union, so a component's own record claims its path directly and a doc's location is a browsing decision, never an ownership one. Where two docs overlap, the **narrower glob wins**. A module is tied to its components by the `owns:` globs of the docs carrying its `module:` label — not a folder, not a separate map. Indexes, chapters, and explainers carry no `owns:`, so a subject claims its path exactly once.

Before modifying a component in an unfamiliar area:

1. Consult the **injected ownership index** — the `glob → doc · module · keywords · status` map. Match the path or topic to the owning doc and read it first. (No index in context ⇒ the repo isn't reconciled — see Maintenance.)
2. If a `docs/memory/` file exists for the area, read it for domain knowledge and failure modes.

The `lld-mode` agent checks for ownership conflicts during LLD research — docs whose `owns:` globs overlap at equal specificity. Resolve them in the LLD before proceeding.

### Boundaries — check while changing

etna has no db schema, wire envelope, or auth of its own — the `boundary` skill's stack mechanisms describe the contracts of the **rules etna ships**, checked in the consumer's repo, not here. etna's **own** live contracts are authoring and distribution ones, each with no static link between the two sides:

- a harness `readme.md` manifest's `skills:` / `rules:` / `agents:` list ↔ the shared catalogs it resolves from (local-first);
- a component's **source ↔ `.claude/` dogfood ↔ shipped bundle** (three-way parity, per Authoring & Distribution);
- a hook script ↔ its `hooks.json` registration;
- the CLI's managed-block edits ↔ a consumer's `settings.json` / `.env`.

Invoke the `boundary` skill after a plan is approved and before its first implementation step — it parses the plan's Proposed Changes, reads the touched source fresh, and reports severity-ranked violations with a pass/block verdict, read-only. Fold the amendments in before coding. For a component etna ships, its boundaries also include whatever contracts that component asserts once installed in a consumer repo.

### Documentation — close the loop

- **Everything written in this repo follows [`docs/writing-style.md`](docs/writing-style.md) — no exceptions.** It is the single style authority for both genres: instruction files (`CLAUDE.md`, rules, agents, skill prose) and documents. Read it before writing prose here, not after. Its load-bearing rule is the Two Natures — truth documents state the present and narrate no history; records are dated and never edited to match the present.
- **Every markdown document also goes through the `documentation` skill** for its *genre* — invoke it before creating or substantively editing any `.md` file and apply the matching template. The skill supplies structure; `writing-style.md` supplies the prose.
- **[override]** Keep `docs/` updated when a change alters documented behaviour — creating and updating docs is part of the work.
- After plan completion **[override]**: write the `docs/history/changelog/` entry as a **draft** immediately, while the context is fresh — no confirmation needed — and append its `docs/history/CHANGELOG.md` row; the commit fills what the draft left open and freezes it. Non-plan work needs no separate prompt: every non-exempt commit carries its own entry (the `changelog` rule).
- When moving or renaming a component: update the `owns:` globs of the doc that owns it so the ownership index stays accurate. A new doc that owns code declares its paths in its own `owns:` frontmatter.
- `docs/structure.md` is the authority on what belongs where — read it before adding or moving a doc; one canonical source per topic, link don't copy. Only `CLAUDE.md`, `AGENTS.md`, and `README.md` live at the repo root.

> Agents and skills live under `.claude/agents/` and `.claude/skills/`. Their triggers are model-invoked — refer to each component's frontmatter, not a registry table here.

---

## Changelog

A commit marks the user's behavioral verification of the work, and the working session is the last holder of the refinement context that produced it — asks, iterations, rejections, skill outcomes, discoveries. That context is captured in the changelog and distilled on demand. The `changelog` rule carries the trigger and the lifecycle; this is the policy:

- **Every non-mechanical commit is covered by an entry** at `docs/history/changelog/YYYY-MM-DD-{three-words}.md`, staged inside the commit it describes — whatever tool or session performs the commit — plus a row in `docs/history/CHANGELOG.md`. Format, required fields, and the closed exemption list are the `documentation` skill's `templates/changelog-entry.md`; the failure fields (rejected attempts, overridden skill output) and verbatim taste quotes are required, not optional — the entry's value concentrates there.
- **An entry may exist before its commit.** A plan reaching `Status: Complete` writes its entry as a **draft** immediately, while the context is fresh; the commit fills what the draft left open. **Immutability begins at commit, not creation** — a draft is mutable, a committed entry never is, and a correction is a new entry that links back. Doc-health passes skip the genre.
- **A commit is the smallest unit an entry may describe**; above that the mapping is judgment. Work exceeding a draft's scope gets a *second* entry rather than stretching the first.
- **Distillation is the `retro` agent** — run on demand (before a brainstorm or LLD, before a new project, after a refinement arc), it converts accumulated entries into a typed punch list (doc content, doc structure, skill evolution, pins, harness rules), appends actionable items to the backlog, and proposes only — application runs through the normal documentation loop.

**One-shot migrations are a different genre.** Work that runs **once** against a live system — a harness rollout across consumer repos, a catalog-wide cutover, a data backfill — is a **migration runbook** at `docs/history/migrations/YYYY-MM-DD-{slug}.md` (template: the `documentation` skill's `templates/migration-runbook.md`), authored **before** execution and outcome-stamped after. A changelog entry says what changed in this repo; a runbook says what was executed against the world and how to verify or undo it. A repeatable procedure is neither — that belongs with the component it operates. When a runbook defers targets, it records **why** and the **trigger to re-evaluate them**, so the next run re-checks rather than inheriting the skip.

---

## Project Memory

Project-specific learnings live in `docs/memory/` (git-tracked). Cross-project user preferences live in `~/.claude/` (untracked).

| File | Owner | Contents |
| --- | --- | --- |
| `docs/memory/main.md` | Main agent | Project-wide patterns, conventions confirmed in this repo, recurring failure modes, decisions whose rationale isn't obvious from the components |
| `docs/memory/{agent-name}.md` | The named sub-agent | Strategy memory for that agent — how to be more effective here. Never user-centric. |
| `~/.claude/projects/...` | Auto-memory system | User preferences, role, communication style, cross-project habits |

Override the auto-memory default for project-relevant facts. When recording a learning, ask: _true of this project, or true of this user?_ Project facts → `docs/memory/`. User facts → `~/.claude/`. `docs/memory/main.md` is created on first write; append entries dated `## YYYY-MM-DD — {topic}`.

---

## Out-of-Scope Discovery

When a plan's implementation surfaces work that is important but outside the plan's scope:

- Append it to `docs/history/backlog.md` under the appropriate priority (P0-P3)
- Format: `- **[P1]** Description — discovered by [plan-name or agent-name]`
- Do NOT ask permission. Just append and mention it in the reply.

---

## Delegation

The single policy for sub-agent dispatch — when to fan out, at what tier, and how far to trust the result. Component-internal dispatch mechanics (the foreman loop, the brainstorm twin, batch classification) stay in their components and defer here for anything this section covers. No dispatch mechanism ⇒ inline.

- **Delegate to keep bulk out of the main context.** Wide file reads, sweeps, broad research, audits, fixture prep — work whose raw tool output the main session doesn't need — defaults to a sub-agent: output a sub-agent reads dies with it, while output read inline is re-read and re-billed on every later turn. The hand-off is self-contained (the sub-agent sees none of the conversation), so it must still cost less than the work; run independent delegations in parallel.
- **Small or judgment work stays inline.** A task finishable in a handful of tool calls is faster done than briefed. **Never delegate judgment by reflex** — a second opinion is for a high-stakes call or an explicit request.
- **A delegated result is a report, not verifiable ground truth** — verify load-bearing results directly.
- **Tiers**: mechanical fan-out → the cheapest capable tier; judgment-heavy delegation → the session's standard tier; the strongest tier **only** on explicit user request. The session itself defaults to the standard tier, entering the strongest only by explicit user switch. Model names live in Runtime Notes.
- **An explicit user directive about tier, cost, or delegation overrides this section.**

---

## Guardrails & Defaults

❌ prohibitions hold unless the user explicitly asks otherwise; ✅ and ⚠️ items are standing policy:

- ❌ **Tests** — etna authors markdown; the only suite is the CLI's, under `packages/cli/`. Never generate, update, or modify test files unless the user explicitly asks. (The `code` harness ships a gated-verification posture for the projects it governs — that is a shipped rule, not etna's own.)
- ❌ **Dependencies** — never upgrade frameworks, libraries, or dependencies.
- ❌ **Branches & Worktrees [override]** — never self-create git branches or worktrees; commit straight to the checked-out branch. This replaces any built-in "branch first on the default branch" default. Exception: when the user asks for a pull request, create the branch the PR requires before committing its changes.
- ❌ **Protected Files** — never modify `AGENTS.md`.
- ✅ **Delegation** — when to fan out, tiers, and trust are § Delegation.
- ⚠️ **Plans** — created directly in `docs/history/plans/` (see Workflows). Once `Status: Complete` or `Abandoned`, frozen — never edited. If scope changes after completion, write a new dated plan linking back.
- ⚠️ **Tool Issues** — if any CLI tool, shell alias, or MCP tool behaves unexpectedly (syntax errors, silent failures, wrong defaults), report the exact tool, command, and error to the user so they can fix the underlying library.

---

## Authoring Conventions

Almost everything here is markdown — skills, agents, rules, harness policies, docs. **The prose style for all of it is [`docs/writing-style.md`](docs/writing-style.md)**; the guides below add what is specific to each artifact class. Follow the `kb` / `nomenclature` rules; markdown has no file-path-comment rule. Keep the `.claude/rules/*` reference docs frontmatter-free.

**Each artifact class has an authoring guide — read the one you are editing, before you edit it.** The forge is the only repo that authors these, so the guides live here and ship nowhere:

| Editing | Guide |
| --- | --- |
| A **rule** (`rules/*.md`) | [`docs/rules/Readme.md`](docs/rules/Readme.md) — the catalog, the conventions, and the whole-file audit |
| A **skill** (`skills/*/`) | [`docs/playbooks/skills/`](docs/playbooks/skills/Readme.md) — fit and scope through shipping and maintenance |
| An **agent** (`agents/*.md`) | [`docs/playbooks/agents.md`](docs/playbooks/agents.md) |

Authoring or updating an **agent** keeps both runtimes in sync: the `.md` is the single source, and its Codex `.codex.toml` twin is derived from it by the guide above, then checked with `node packages/cli/lib/codex/validate-codex-agents.mjs`.

For real code (the CLI under `packages/`, hook scripts):

- File-path header comment at the top, in the file's comment syntax: `// packages/cli/bin/etna.js - the installer entry`.
- A 1-line description above each function whose purpose isn't evident from its name and signature. A comment that restates the name is noise; no commented-out code — if a block needs a comment to be understandable, refactor instead.

---

## Runtime Notes

etna runs in Claude Code. Sub-agent dispatch is the Agent tool; sub-agents can run skills and spawn their own sub-agents (probe-verified; re-verify on runtime updates), but cannot hold the browser connection (browser work is Claude in Chrome, main session only). The user-level memory store is `~/.claude/` (auto-memory under `~/.claude/projects/...`). The ownership index and skill/agent descriptions are injected at session start; skills are invoked as slash commands (e.g. `/brainstorm start`). Dispatch tiers (§ Delegation): the standard tier is the session default; mechanical fan-out runs on the cheapest capable tier; the strongest tier only on explicit user switch or request — pick by capability at dispatch, since model names go stale.
