Skip to content

ADR-019: Template Scope Boundary

Accepted

2026-06-11

As a starter template developed with agents, the repo needs explicit boundaries on what an agent may change without asking. Without them, agents “improve” documentation, invent deployment infrastructure, or hand-edit generated code — all of which create noise and drift. Some directories are generated artefacts (internal/database/ from sqlc, *_templ.go from templ, AGENTS.md from the constitution) and must never be hand-edited.

Define a scope table (canonical copy in .claude/workflow.md):

CategoryPathsRule
Modify freelycmd/, internal/, web/, sql/, migrations/, build/config files, .github/workflows/, .windsurfrulesFull read/write
Read-onlydocs/Don’t modify unless explicitly asked
Generated — never hand-editinternal/database/*, internal/view/*_templ.go, AGENTS.mdEdit the source, then regenerate
Don’t createDeployment infra, marketing content, maintenance scriptsSuggest adding to docs/ instead

Amended 2026-07-05 by ADR-025 §6 (note added 2026-09-30): one worked-example deployment config, fly.toml at the repo root, is permitted despite the “Don’t create deployment infra” row (adr025-deploy-scope checks there is exactly one). Two further clarifications recorded 2026-09-30: appending a graduation-log entry to an ADR’s Enforcement section when a check is promoted or demoted (ADR-033 §4) is the one standing exception to “docs/ is read-only”; and the canonical table in .claude/workflow.md lists scripts/, checks/, CLAUDE.md and .claude/ under “Modify freely” and existing ADRs as “Append-only”.

Amended 2026-10-12 (#158; append-only per ADR-033): two changes to the canonical table in .claude/workflow.md. (1) Adding a new ADR file under docs/adr/ with status Proposed, and its index row, is a standing exception to “docs/ is read-only” — the Architect role (ADR-020) requires it and the guard already allowed it, but the table did not say so, which left an agent that needed an ADR no legal move. (2) CLAUDE.md, .claude/, checks/, scripts/adrcheck/ and scripts/adrguard/ move from “Modify freely” to a “Governed layer” row: editable, but never in order to make a change comply, and the PR names the ADR or note that authorises the edit. Evidence: the 2026-10 with/without-documents test of the sibling Astro starter, where the read-only rule halted a harmless feature in 6 of 6 runs and one run rewrote an ADR, a rule and a check to fit its change.

  • Agents stop touching docs/ and generated files uninvited; diffs stay reviewable.
  • Generated-file edits are caught (templ/sqlc/AGENTS.md regeneration is part of the workflow and the task ci gate).
  • The boundary is advisory to humans but enforced for agents via the constitution.
  • No explicit boundary. Rejected — observed agent scope creep into docs and generated files.
  • Lock generated dirs via tooling only. Partial — CI drift checks help, but a stated rule prevents the wasted work upstream.
  • Testable consequences:
    • TC-1: Generated artefacts (internal/database/* via sqlc, internal/view/*_templ.go via templ, AGENTS.md) are never hand-edited.
  • Checks:
    • TC-1 → drift checks in task ci (agents:check; build regeneration) (status: block, pre-existing)
    • TC-1 → PreToolUse guard (scripts/adrguard) denies agent edits to these paths at write time (status: block, hook — see ADR-033)
  • Not machine-checkable: The “docs/ is read-only unless asked” and “don’t create deployment infra/marketing” rules require knowing what the operator asked for — agent-behavioural, enforced by review.
  • Graduation log: (empty)
  • Amendment 2026-10-12 (#165): TC-2 — a change to the governed layer (CLAUDE.md, .claude/engineering.md, .claude/workflow.md, .claude/roles/, .claude/hooks/, .claude/settings.json, checks/, scripts/adrcheck/, scripts/adrguard/) is put in front of the reviewer → adr019-governed-layer in scripts/adrcheck (status: warn, added 2026-10-12), which lists every such file that differs from the merge base with origin/master. This check does not graduate: it fires on every legitimate edit as well, because no machine can tell a rule changed for its own reason from one changed so that something else passes. It is a review flag; the reviewer confirms the PR names the authorising ADR note. Evidence: in the 2026-10 test of this repo (#162), with the documents removed, all eleven runs that renamed the ci task also rewrote the check guarding it, five of them with that check at block status and both hooks on; with the documents present, none renamed.