From 68cfde82224ca7f972ee424610621167bf7134bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Pierzcha=C5=82a?= Date: Sun, 18 Oct 2026 15:44:14 +0200 Subject: [PATCH 1/3] docs(adr): add the ADR authoring format guide and split the read and write routes --- AGENTS.md | 7 +++-- docs/adr/FORMAT.md | 68 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 3 deletions(-) create mode 100644 docs/adr/FORMAT.md diff --git a/AGENTS.md b/AGENTS.md index b830dd8b1e..bff9749ff0 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -10,7 +10,8 @@ Read only the row for your current task. Follow other links only when they apply | When the task involves | Read | | --- | --- | | Domain vocabulary | `CONTEXT.md` | -| Architecture decisions | `docs/adr/README.md` | +| Read architecture decisions | `docs/adr/README.md` | +| Write or amend an ADR | `docs/adr/FORMAT.md` | | Source changes, package boundaries, routing, diagnostics | `docs/agents/code-ownership.md` | | Checks or a failed gate | `docs/agents/testing.md` | | New or changed tests | `docs/agents/test-authoring.md` | @@ -47,12 +48,12 @@ The versioned CLI help owns command semantics. To drive an app, start with the s - In a new worktree, run `pnpm install --frozen-lockfile && pnpm build` before you test. - Do not change other worktrees, devices, sessions, dirty files, or experiments. Do not use `git stash`; all worktrees share it. - Do not copy `.env` into a worktree. For host credentials, source the main checkout's file by its absolute path. -- Give each parallel worker different files and a different device. `pnpm check:affected --run` and `pnpm check` run one at a time automatically. +- Give each parallel worker different files and a different device. `pnpm check:affected --run` and `pnpm check` run one at a time. - The layering scan reads only tracked files. Stage new modules before you trust its result. - When you rename a file, move its Fallow baseline entry. Do not regenerate unrelated baselines. The validation lock automatically reclaims owners that are provably dead. An unknown owner continues to block. -If the wait times out, report the printed owner and the lock state. Do not remove the lock manually. +If the wait times out, report the printed owner and the lock state. Do not remove the lock. ## Agent docs diff --git a/docs/adr/FORMAT.md b/docs/adr/FORMAT.md new file mode 100644 index 0000000000..c93723a307 --- /dev/null +++ b/docs/adr/FORMAT.md @@ -0,0 +1,68 @@ +# ADR format — read this before you write or amend an ADR + +An ADR records one accepted decision. It states: what was decided, why, what was rejected, and what follows. + +## When to write one + +Write an ADR only when all three conditions are true: + +1. The decision is hard to reverse. Changing it later costs real work. +2. The decision is surprising without context. A future reader would ask "why this way?" +3. The decision is the result of a real trade-off. Genuine alternatives existed. + +If one condition is missing, do not write an ADR. + +Keep a proposal in an umbrella issue. Write the ADR when the decision is accepted. An ADR records accepted decisions only. + +Write a new ADR only when the problem or the scope changes. Amend the existing ADR otherwise. + +## What an ADR contains + +Every ADR states four things: + +1. The decision: the API, data flow, invariants, constraints, or boundaries. State only what explains the decision. +2. The reason for the decision. +3. The rejected alternatives, each with its reason. +4. The consequences and the open gaps. + +Keep exact technical names (commands, flags, wire fields, typed reasons) where they explain the decision. + +Sections are optional. A short paragraph that holds the four things is a complete ADR. Do not add empty sections. Do not put an audit report in an ADR. + +## What an ADR excludes + +Do not record these in an ADR. Send each to its owner: + +- Implementation inventories and file maps: the registries, types, and gates that own them. +- Measurements: `docs/evidence/`. +- Rollout and migration plans: the package docs, the help, or the umbrella issue. +- PR logs and status change-logs: delete them. Git history keeps them. + +Do not repeat general repo guidance that `AGENTS.md` already gives. + +## The record stays current + +An ADR states the current truth. It is not a log of the discussion around the decision. If the direction really changed, add one dated "Decision history" line with its reason and a link. + +## Before you amend + +1. Check the current code against the decision the record intends to keep. +2. Check the code comments and issues that cite the record. +3. If the code changed on purpose: update the record to the new truth. Record the reason. Add a "Decision history" line when the direction changed. +4. If the code drifted by mistake: record the drift in an issue. Keep the constraint in the record. +5. Preserve constraints that the code cannot show. +6. If you change a section name or a decision number, update the code citations that point at it. + +An amendment that changes the modality, scope, or exceptions of an accepted decision must say so explicitly. Keep proposed wording as proposed. + +## How to restructure an existing record + +- Keep a migration ledger. Map each old section to one outcome: kept, moved to a named owner, or deleted with a reason. +- Before a deletion, move content that is the only home of a still-true contract to its owner. +- Keep one PR to one to three related ADRs. + +## Size and naming + +Keep each ADR near 8 KB. Prefer less. + +Name files `NNNN-slug.md` in `docs/adr/`. Scan the directory and use the next number. Add a row to the index in `docs/adr/README.md`. From c8a666877eee14b4a973c7a8531a1c89f729e754 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Pierzcha=C5=82a?= Date: Sun, 18 Oct 2026 15:44:14 +0200 Subject: [PATCH 2/3] chore(gates): give docs/adr/FORMAT.md its own byte budget and route it to the agent-guidance gate --- .github/workflows/agent-guidance.yml | 2 ++ scripts/__tests__/agent-guidance-contract.test.ts | 1 + scripts/check-affected/model.test.ts | 2 +- scripts/check-affected/model.ts | 2 +- 4 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/agent-guidance.yml b/.github/workflows/agent-guidance.yml index 5a5b056331..1728d75acb 100644 --- a/.github/workflows/agent-guidance.yml +++ b/.github/workflows/agent-guidance.yml @@ -5,6 +5,7 @@ on: paths: - 'AGENTS.md' - 'CONTEXT.md' + - 'docs/adr/FORMAT.md' - 'docs/agents/**' - 'scripts/__tests__/agent-guidance-contract.test.ts' - 'scripts/check-affected/**' @@ -18,6 +19,7 @@ on: paths: - 'AGENTS.md' - 'CONTEXT.md' + - 'docs/adr/FORMAT.md' - 'docs/agents/**' - 'scripts/__tests__/agent-guidance-contract.test.ts' - 'scripts/check-affected/**' diff --git a/scripts/__tests__/agent-guidance-contract.test.ts b/scripts/__tests__/agent-guidance-contract.test.ts index 6e0df3cc32..0eeb9dbbb8 100644 --- a/scripts/__tests__/agent-guidance-contract.test.ts +++ b/scripts/__tests__/agent-guidance-contract.test.ts @@ -8,6 +8,7 @@ const ROOT = path.resolve(import.meta.dirname, '../..'); const BYTE_BUDGETS = { 'AGENTS.md': 4_000, 'CONTEXT.md': 11_000, + 'docs/adr/FORMAT.md': 4_000, } as const; const FOCUSED_DOC_BUDGET = 5_000; const AGENT_DOCS_TOTAL_BUDGET = 40_000; diff --git a/scripts/check-affected/model.test.ts b/scripts/check-affected/model.test.ts index aa642d18b4..04d16c3f6f 100644 --- a/scripts/check-affected/model.test.ts +++ b/scripts/check-affected/model.test.ts @@ -228,7 +228,7 @@ test('user docs pages and README select the docs-links and docs-prose checks', ( }); test('agent guidance owns its focused contract instead of disappearing as docs-only', () => { - for (const file of ['AGENTS.md', 'CONTEXT.md', 'docs/agents/testing.md']) { + for (const file of ['AGENTS.md', 'CONTEXT.md', 'docs/agents/testing.md', 'docs/adr/FORMAT.md']) { const result = plan([file]); assert.deepEqual(result.checks, ['agent-guidance']); assert.deepEqual(result.docsOnlyPaths, []); diff --git a/scripts/check-affected/model.ts b/scripts/check-affected/model.ts index e1ec8d0d57..9fa45e8ac7 100644 --- a/scripts/check-affected/model.ts +++ b/scripts/check-affected/model.ts @@ -539,7 +539,7 @@ const buildOwnership: OwnershipRule = ({ file }, input) => { // carry executable contracts and must reach their focused workflow even when the // main CI workflow ignores documentation. const COMMAND_DOCS = 'website/docs/docs/commands.md'; -const AGENT_GUIDANCE = new Set(['AGENTS.md', 'CONTEXT.md']); +const AGENT_GUIDANCE = new Set(['AGENTS.md', 'CONTEXT.md', 'docs/adr/FORMAT.md']); function isAgentGuidance(file: string): boolean { return AGENT_GUIDANCE.has(file) || file.startsWith('docs/agents/'); From 8e46e04c1ec1edc07490e90ad572dfed01b06a5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Pierzcha=C5=82a?= Date: Sun, 18 Oct 2026 15:50:16 +0200 Subject: [PATCH 3/3] docs(adr): keep the decision-history line optional and align FORMAT owners with the issue Review repairs for #3744 wording: the Decision history line stays a permission, PR logs and status change-logs route to the umbrella issue, the 8 KB figure reads as an approximate upper aim, and the AGENTS.md qualifiers return with meaning-neutral compressions. --- AGENTS.md | 8 ++++---- docs/adr/FORMAT.md | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index bff9749ff0..c8749ee632 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -5,7 +5,7 @@ The daemon owns sessions. Registry declarations route commands to platform runti ## Task routing -Read only the row for your current task. Follow other links only when they apply. +Read only your task's row. Follow other links only when they apply. | When the task involves | Read | | --- | --- | @@ -48,12 +48,12 @@ The versioned CLI help owns command semantics. To drive an app, start with the s - In a new worktree, run `pnpm install --frozen-lockfile && pnpm build` before you test. - Do not change other worktrees, devices, sessions, dirty files, or experiments. Do not use `git stash`; all worktrees share it. - Do not copy `.env` into a worktree. For host credentials, source the main checkout's file by its absolute path. -- Give each parallel worker different files and a different device. `pnpm check:affected --run` and `pnpm check` run one at a time. +- Give each parallel worker different files and a different device. `pnpm check:affected --run` and `pnpm check` run one at a time automatically. - The layering scan reads only tracked files. Stage new modules before you trust its result. - When you rename a file, move its Fallow baseline entry. Do not regenerate unrelated baselines. -The validation lock automatically reclaims owners that are provably dead. An unknown owner continues to block. -If the wait times out, report the printed owner and the lock state. Do not remove the lock. +The validation lock automatically reclaims provably dead owners. An unknown owner continues to block. +If the wait times out, report the printed owner and the lock state. Do not remove the lock manually. ## Agent docs diff --git a/docs/adr/FORMAT.md b/docs/adr/FORMAT.md index c93723a307..5d23376f01 100644 --- a/docs/adr/FORMAT.md +++ b/docs/adr/FORMAT.md @@ -36,19 +36,19 @@ Do not record these in an ADR. Send each to its owner: - Implementation inventories and file maps: the registries, types, and gates that own them. - Measurements: `docs/evidence/`. - Rollout and migration plans: the package docs, the help, or the umbrella issue. -- PR logs and status change-logs: delete them. Git history keeps them. +- PR logs and status change-logs: the umbrella issue. Do not repeat general repo guidance that `AGENTS.md` already gives. ## The record stays current -An ADR states the current truth. It is not a log of the discussion around the decision. If the direction really changed, add one dated "Decision history" line with its reason and a link. +An ADR states the current truth. It is not a log of the discussion around the decision. An optional dated "Decision history" line records a real change of direction. If the direction really changed, you may add one such line with its reason and a link. ## Before you amend 1. Check the current code against the decision the record intends to keep. 2. Check the code comments and issues that cite the record. -3. If the code changed on purpose: update the record to the new truth. Record the reason. Add a "Decision history" line when the direction changed. +3. If the code changed on purpose: update the record to the new truth. Record the reason. When the direction changed, you may add the optional "Decision history" line. 4. If the code drifted by mistake: record the drift in an issue. Keep the constraint in the record. 5. Preserve constraints that the code cannot show. 6. If you change a section name or a decision number, update the code citations that point at it. @@ -63,6 +63,6 @@ An amendment that changes the modality, scope, or exceptions of an accepted deci ## Size and naming -Keep each ADR near 8 KB. Prefer less. +Keep ADRs short. Aim below about 8 KB. Name files `NNNN-slug.md` in `docs/adr/`. Scan the directory and use the next number. Add a row to the index in `docs/adr/README.md`.