diff --git a/AGENTS.md b/AGENTS.md
index 74f6b46..faf9fc5 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -29,7 +29,7 @@ Conventional commits, and the type drives the user-facing `CHANGELOG.md`
package's behaviour.
- `docs` — user-facing documentation (`README.md`, `UPGRADING.md`).
- `chore()` — repository maintenance no consumer sees: the loop host
- (`scripts/loop/`), CI workflows, the norms layer (this file, `docs/agents/`,
+ (`scripts/loop/`), CI workflows, the norms layer (this file, `docs/norms/`,
`skills/`), tooling. Name the area: `chore(loop)`, `chore(ci)`,
`chore(norms)`.
@@ -40,21 +40,21 @@ iteration would read to a user as a change to the package.
## References
- Usage and per-provider options: `README.md`; building a custom provider: README "Extension" section and `src/provider.ts`.
-- Domain docs: `docs/agents/domain.md` (CONTEXT/ADR consumption, glossary usage).
+- Domain docs: `docs/norms/domain.md` (CONTEXT/ADR consumption, glossary usage).
## Operations (loop)
This repo is operated by an autonomous loop system. If you are a loop run
-(launched by `.github/workflows/loop.yml`), follow `docs/agents/ops.md` first.
+(launched by `.github/workflows/loop.yml`), follow `docs/norms/ops.md` first.
- Issue tracker: GitHub, via the `gh` CLI. Issues and PRs share one tracker and
- one label system — PRs ARE a triage surface. See `docs/agents/issue-tracker.md`.
+ one label system — PRs ARE a triage surface. See `docs/norms/issue-tracker.md`.
- Triage labels: five canonical roles — `needs-triage`, `needs-info`,
`ready-for-agent`, `ready-for-human`, `wontfix`. Exact semantics:
- `docs/agents/triage-labels.md`.
+ `docs/norms/triage-labels.md`.
- Release: the loop prepares and verifies; a human cuts the release with
`pnpm release` and publishes with `pnpm build && pnpm publish`. See
- `docs/agents/release.md`.
+ `docs/norms/release.md`.
- Skills: `skills/*/SKILL.md` (triage, research, verify, review, sweep, retro)
fix how each stage is done. Invoke them per `ops.md`, never skip the
opening/closing rituals.
@@ -62,6 +62,6 @@ This repo is operated by an autonomous loop system. If you are a loop run
(synced into this checkout's `state/` dir for the duration of your run —
authoritative JSON + `SUMMARY.md`). Never keep cross-run state in your
context or in comments only.
-- Norms layer changes (this file, `docs/agents/*`, `skills/*`) are proposals:
+- Norms layer changes (this file, `docs/norms/*`, `skills/*`) are proposals:
open a PR, never merge your own change.
- You are the maker or the checker, never both for the same change.
diff --git a/bump.config.ts b/bump.config.ts
index 59129d4..cf9a13e 100644
--- a/bump.config.ts
+++ b/bump.config.ts
@@ -13,7 +13,7 @@ import { defineConfig } from 'bumpp'
* ruleset refuses every direct push to `main`, releases included: `422 Changes
* must be made through a pull request`. The owner's bypass (`pull_request`
* mode) covers merging a PR, not pushing one, so there is nothing to route
- * around — see `docs/agents/release.md`.
+ * around — see `docs/norms/release.md`.
*
* `pr.base` is pinned instead of detected: bumpp otherwise reads the base from
* `origin/HEAD`, which still says `master` in clones that predate the rename.
diff --git a/docs/agents/domain.md b/docs/norms/domain.md
similarity index 100%
rename from docs/agents/domain.md
rename to docs/norms/domain.md
diff --git a/docs/agents/issue-tracker.md b/docs/norms/issue-tracker.md
similarity index 100%
rename from docs/agents/issue-tracker.md
rename to docs/norms/issue-tracker.md
diff --git a/docs/agents/ops.md b/docs/norms/ops.md
similarity index 98%
rename from docs/agents/ops.md
rename to docs/norms/ops.md
index 070d149..ece192f 100644
--- a/docs/agents/ops.md
+++ b/docs/norms/ops.md
@@ -61,7 +61,7 @@ Closing (always, before exit):
3. Refresh `state/SUMMARY.md`. Exit `0` on success.
Never do work outside the declared stage; never modify norms-layer files
-(AGENTS.md, docs/agents/*, skills/*) except as a proposal PR.
+(AGENTS.md, docs/norms/*, skills/*) except as a proposal PR.
## Labels → task state
diff --git a/docs/agents/release.md b/docs/norms/release.md
similarity index 100%
rename from docs/agents/release.md
rename to docs/norms/release.md
diff --git a/docs/agents/triage-labels.md b/docs/norms/triage-labels.md
similarity index 100%
rename from docs/agents/triage-labels.md
rename to docs/norms/triage-labels.md
diff --git a/scripts/loop/run.mjs b/scripts/loop/run.mjs
index 6062d0e..b43e30f 100644
--- a/scripts/loop/run.mjs
+++ b/scripts/loop/run.mjs
@@ -183,7 +183,7 @@ async function cmdStart(args) {
console.log(`[loop] run started: ${rid}`);
console.log(`[loop] task #${t.id} (stage=${s}) claimed → ` +
`${path.relative(ROOT, S.taskFile(t.id))}`);
- console.log('[loop] opening ritual: read AGENTS.md → docs/agents/ops.md → the matching skill:');
+ console.log('[loop] opening ritual: read AGENTS.md → docs/norms/ops.md → the matching skill:');
const skillFile = path.join(ROOT, 'skills', s, 'SKILL.md');
const hasSkill = await fs.access(skillFile).then(() => true, () => false);
console.log(hasSkill
diff --git a/scripts/loop/shared/agent.mjs b/scripts/loop/shared/agent.mjs
index 3c5a4df..2ad5e1e 100644
--- a/scripts/loop/shared/agent.mjs
+++ b/scripts/loop/shared/agent.mjs
@@ -31,7 +31,7 @@ export function buildPrompt({ task, stage, runId, writeLevel, mode, repo, lead =
L.push('');
L.push('## Opening ritual (read in order, do not skip)');
L.push('1. `AGENTS.md`');
- L.push('2. `docs/agents/ops.md`');
+ L.push('2. `docs/norms/ops.md`');
L.push(`3. \`skills/${stage.replace(/-scheduled$/, '')}/SKILL.md\` (if missing, use the skills the stage calls for, e.g. verify/review)`);
if (task) L.push(`4. \`state/tasks/${task.id}.json\``);
L.push('');
@@ -120,7 +120,7 @@ export function buildPrompt({ task, stage, runId, writeLevel, mode, repo, lead =
L.push(' "title": "",');
L.push(' "body": "Closes #\\n\\nloop-task: #\\n\\n" }');
L.push(' ```');
- L.push(' The body must pass the loop-PR test in `docs/agents/ops.md` (`Closes #` and');
+ L.push(' The body must pass the loop-PR test in `docs/norms/ops.md` (`Closes #` and');
L.push(' `loop-task: #`). Omit `push` when the stage produced no branch — triage,');
L.push(' sweep, or a `needs-info`/`needs-triage` verdict never pushes anything.');
}
diff --git a/scripts/loop/shared/route.mjs b/scripts/loop/shared/route.mjs
index 4cab377..aa935ee 100644
--- a/scripts/loop/shared/route.mjs
+++ b/scripts/loop/shared/route.mjs
@@ -1,7 +1,7 @@
/**
* GitHub event → Loop decision (pure-function router).
*
- * Authority: 05 host implementation spec §3 routing table / docs/agents/ops.md
+ * Authority: 05 host implementation spec §3 routing table / docs/norms/ops.md
* "Trigger → loop map".
* This module does no IO: the input is the event context injected by the workflow and
* the output is a Decision, executed by entry.mjs.
diff --git a/scripts/loop/shared/state.mjs b/scripts/loop/shared/state.mjs
index 612897c..95e4c52 100644
--- a/scripts/loop/shared/state.mjs
+++ b/scripts/loop/shared/state.mjs
@@ -5,7 +5,7 @@
* so the two implementations cannot drift (#33 during A0 was manual drift).
*
* schema: task files / run rows / locks / SUMMARY — see scripts/loop/README.md;
- * state machine + dual metrics: docs/agents/ops.md, docs/agents/triage-labels.md.
+ * state machine + dual metrics: docs/norms/ops.md, docs/norms/triage-labels.md.
*/
import { promises as fs } from 'node:fs';
diff --git a/skills/triage/SKILL.md b/skills/triage/SKILL.md
index 3f9a632..bbf4e62 100644
--- a/skills/triage/SKILL.md
+++ b/skills/triage/SKILL.md
@@ -15,7 +15,7 @@ Classify one GitHub issue (or external PR) before any deeper work.
## Steps
1. Read the task state file; if `status` is not `new`/`waiting-info`, stop
(another instance owns it) and exit.
-2. Read AGENTS.md conventions and `docs/agents/ops.md`; skim related docs the
+2. Read AGENTS.md conventions and `docs/norms/ops.md`; skim related docs the
issue touches.
3. Judge: what does the reporter want? Reproduce mentally from the report —
if a bug, can it be reproduced from the report alone? If a feature, is the