From bfe0b5162643de5cda9e80597258634d1e181fca Mon Sep 17 00:00:00 2001 From: Cameron Date: Thu, 9 Jul 2026 13:07:39 -0700 Subject: [PATCH] Scope verification to impacted surfaces Defense: The development process should spend verification effort where it can detect regressions. Full Rust and Bevy gates are required for executable-impacting changes; forcing them for prose or reference art wastes time without increasing confidence. Focused validation preserves the honesty rule while keeping minor work lightweight. --- AGENT.md | 31 +++++++++--- AGENTS.md | 13 +++-- CLAUDE.md | 13 +++-- tools/check.sh | 27 +++++++---- wiki/log/2026-07-09-proportional-checks.md | 55 ++++++++++++++++++++++ wiki/log/DEVLOG.md | 11 +++++ wiki/process/development-style.md | 7 ++- wiki/process/workflows.md | 41 ++++++++++++---- 8 files changed, 161 insertions(+), 37 deletions(-) create mode 100644 wiki/log/2026-07-09-proportional-checks.md diff --git a/AGENT.md b/AGENT.md index 32ded225..b7998338 100644 --- a/AGENT.md +++ b/AGENT.md @@ -77,10 +77,25 @@ behavior change. - Game rules live only in the lib (`src/sim.rs` and friends); the terminal and Bevy binaries are thin views. `Sim` never reads the wall clock or does I/O. -- Definition of done: `cargo test` green, `cargo clippy --all-targets` clean - (both with and without `--features bevy_ui`), `cargo fmt` applied, and the - change observed in an actual run (see wiki/process/workflows.md for the pty - smoke test and Bevy launch check). +- **Verification is proportional to impact. Do not run the full Rust/Bevy gate + for every minor edit.** + - Changes that can affect the executable — Rust under `src/`, Cargo/build + configuration, Rust tests/examples/benches — run the full + `./tools/check.sh` gate (fmt, tests, agent smoke, both clippy feature sets, + Bevy builds) and the relevant observed-run check. + - Docs, specs, process text, logs, and reference art run focused checks only: + `git diff --check`, the wiki/link gate when wiki-facing, render/inspect for + visual artifacts, and any directly relevant formatter or validator. **Do + not run Cargo, clippy, or Bevy merely because the commit is otherwise + complete or the worktree became clean.** + - Site, shell, and other tooling changes run their own targeted build, + syntax, or smoke check. They require the full Rust gate only when they can + affect the Rust executable/build. + `tools/check.sh` classifies both dirty changes and committed task-worktree + changes against `origin/main`, so a docs-only branch stays on the focused + path after commit/rebase. `MISALIGNED_FORCE_RUST_GATE=1` is for deliberately + forcing the full gate, not routine caution. See + [wiki/process/workflows.md](wiki/process/workflows.md). - **Constitution enforcement is mechanical.** A pre-commit hook (`.githooks/pre-commit`) rejects any commit that touches `src/` without also touching `wiki/` (a `Type: spec` page's amendment) or `DESIGN.md`. A @@ -90,9 +105,11 @@ behavior change. genuinely non-functional (generated code, test-only, formatting). - Commits: no AI attribution, explicit `git add` of intended files only. - Update any `Type: knowledge` wiki page your change made stale, add a - `wiki/log/` entry for the session, and land the work by merging to - `main` directly after `./tools/check.sh` passes (the PR rule was - removed 2026-07-07 — see the DESIGN.md decisions log). + `wiki/log/` entry for the session, and land the work by merging to `main` + directly after the **appropriate scoped verification** passes. Functional + Rust changes require the full `./tools/check.sh`; minor non-runtime changes + do not. (The PR rule was removed 2026-07-07 — see the DESIGN.md decisions + log.) - **Ledgers merge by union.** `wiki/log/DEVLOG.md`, the DESIGN.md decisions log, and `wiki/process/specs.md`'s tables are append-only records: resolve merge conflicts in them by keeping BOTH sides' entries. diff --git a/AGENTS.md b/AGENTS.md index 28d8b95d..7c419716 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -22,8 +22,9 @@ only the navigation shortcut so sessions stop rediscovering the layout. - `src/` — the sim lib. `sim.rs` is the orchestrator, `save.rs` the serde JSON save; these two are the parallel-agent conflict hotspots. Frontends are thin views: `src/bin/terminal/`, `src/bin/bevy.rs` (feature `bevy_ui`). -- `tools/check.sh` — the definition of done (fmt, tests, clippy both feature - sets, bevy build, spec-header lint). Run before every commit. +- `tools/check.sh` — the scoped gate: full fmt/tests/clippy/Bevy only for + Rust/executable-impacting changes; focused spec/wiki checks for docs/process + changes. Do not force the full gate for minor non-runtime edits. - `wiki/log/` — one entry per session; `wiki/log/DEVLOG.md` is the ledger. - `prompts/` — the dispatch library for sub-agent task types. @@ -44,9 +45,11 @@ only the navigation shortcut so sessions stop rediscovering the layout. never `git add -A`. - Ledger files (wiki/log/DEVLOG.md, the DESIGN.md decisions log, wiki status tables) merge by UNION — keep both sides' entries in any conflict. -- Landing: rebase onto `origin/main`, re-run `./tools/check.sh`, merge/push - to main directly (the PR rule was removed 2026-07-07), then remove the - worktree and delete its branch. No stale worktrees. +- Landing: rebase onto `origin/main`, re-run the **appropriate scoped + verification** (full `./tools/check.sh` for Rust-impacting work; focused + checks for docs/art/process-only work), merge/push to main directly (the PR + rule was removed 2026-07-07), then remove the worktree and delete its branch. + No stale worktrees. - Run at most ONE sim+save-heavy work order at a time (see the ROADMAP conflict flags); isolated items (frontend-only, test-only, docs) can run alongside anything. diff --git a/CLAUDE.md b/CLAUDE.md index 10ade07d..b09cf943 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -22,8 +22,9 @@ only the navigation shortcut so sessions stop rediscovering the layout. - `src/` — the sim lib. `sim.rs` is the orchestrator, `save.rs` the serde JSON save; these two are the parallel-agent conflict hotspots. Frontends are thin views: `src/bin/terminal/`, `src/bin/bevy.rs` (feature `bevy_ui`). -- `tools/check.sh` — the definition of done (fmt, tests, clippy both feature - sets, bevy build, spec-header lint). Run before every commit. +- `tools/check.sh` — the scoped gate: full fmt/tests/clippy/Bevy only for + Rust/executable-impacting changes; focused spec/wiki checks for docs/process + changes. Do not force the full gate for minor non-runtime edits. - `wiki/log/` — one entry per session; `wiki/log/DEVLOG.md` is the ledger. - `prompts/` — the dispatch library for sub-agent task types. @@ -44,9 +45,11 @@ only the navigation shortcut so sessions stop rediscovering the layout. never `git add -A`. - Ledger files (wiki/log/DEVLOG.md, the DESIGN.md decisions log, wiki status tables) merge by UNION — keep both sides' entries in any conflict. -- Landing: rebase onto `origin/main`, re-run `./tools/check.sh`, merge/push - to main directly (the PR rule was removed 2026-07-07), then remove the - worktree and delete its branch. No stale worktrees. +- Landing: rebase onto `origin/main`, re-run the **appropriate scoped + verification** (full `./tools/check.sh` for Rust-impacting work; focused + checks for docs/art/process-only work), merge/push to main directly (the PR + rule was removed 2026-07-07), then remove the worktree and delete its branch. + No stale worktrees. - Run at most ONE sim+save-heavy work order at a time (see the ROADMAP conflict flags); isolated items (frontend-only, test-only, docs) can run alongside anything. diff --git a/tools/check.sh b/tools/check.sh index dd880b83..1157cc0f 100755 --- a/tools/check.sh +++ b/tools/check.sh @@ -1,7 +1,8 @@ #!/usr/bin/env bash -# The self-enforcing gate. Run before every commit and in any CI. -# Encodes AGENT.md's definition of done so the constitution holds itself up -# when no one with taste is watching. Exit non-zero on any failure. +# The self-enforcing gate. Rust/executable-impacting changes run the full gate; +# docs/spec/process/reference-art changes run only the focused non-Rust checks. +# CI and an unclassifiable clean checkout stay conservative and run everything. +# Exit non-zero on any failure. set -euo pipefail cd "$(dirname "$0")/.." @@ -9,12 +10,20 @@ fail=0 step() { printf '\n=== %s ===\n' "$1"; } changed_files() { - # Local pre-commit speed path: compare the working tree to HEAD and include - # untracked files. CI checkouts are clean, so they intentionally fall back to - # the full gate below. + # Classify both uncommitted work and commits on a linked task worktree. The + # latter matters after commit/rebase: `git diff HEAD` is clean there, but a + # docs-only branch still must not trigger a pointless Cargo/Bevy rebuild. + # CI and the primary checkout normally have a .git directory, not the .git + # file used by linked worktrees, so they retain the conservative full gate. { git diff --name-only HEAD -- git ls-files --others --exclude-standard + + if [ -f .git ] && git rev-parse --verify origin/main >/dev/null 2>&1; then + local base + base=$(git merge-base HEAD origin/main) + git diff --name-only "$base"...HEAD -- + fi } | sort -u } @@ -24,8 +33,8 @@ needs_rust_gate() { changed=$(changed_files) if [ -z "$changed" ]; then - # Clean tree / CI: run everything. A clean checkout has no local diff to - # classify, and the remote gate should never silently fast-path. + # CI, primary checkout, or a task branch with no delta: run everything. + # The remote gate should never silently fast-path an unclassifiable build. return 0 fi @@ -103,7 +112,7 @@ if [ "$rust_gate" -eq 1 ]; then done else step "rust gate" - echo "SKIP: local changes do not touch Rust-impacting paths; CI/clean checkouts still run the full Rust gate." + echo "SKIP: classified task changes do not touch Rust-impacting paths; CI/unclassifiable checkouts still run the full Rust gate." fi setup_local_pkg_config() { diff --git a/wiki/log/2026-07-09-proportional-checks.md b/wiki/log/2026-07-09-proportional-checks.md new file mode 100644 index 00000000..5059779d --- /dev/null +++ b/wiki/log/2026-07-09-proportional-checks.md @@ -0,0 +1,55 @@ +# Proportional verification — stop rebuilding Bevy for prose + +``` +Type: log +``` + +## Finding + +Cameron called out a process failure after a docs/reference-art design session +started a clean-tree full Rust and Bevy gate. The local dirty-tree speed path +had already run the useful wiki and mdBook checks, but the written instructions +still said “run before every commit” and “re-run after rebase.” Once the branch +was committed, `tools/check.sh` saw a clean tree, lost the path classification, +and conservatively rebuilt everything. + +That is expensive and low-signal. Rust tests cannot validate prose, a decision +record, or an SVG render. + +## Policy + +Verification is now explicitly proportional: + +- Rust/executable-impacting work runs the full `./tools/check.sh` gate and an + appropriate observed-run check. +- Docs, specs, process text, logs, and reference art run focused validators + only: whitespace/link/spec gates, rendering and visual inspection, or the + directly relevant formatter. +- Site, shell, and other tooling run their own targeted build/syntax/smoke + checks. They do not inherit the Rust gate unless they can affect the Rust + executable/build. +- Agents must not force Cargo/clippy/Bevy out of generic caution for a minor + non-runtime edit. + +The binding `AGENT.md`, both navigation shims (`AGENTS.md`, `CLAUDE.md`), +development style, and workflows now say this directly. Landing requires the +appropriate scoped verification, not an unconditional clean-tree full gate. + +## Mechanical fix + +`tools/check.sh` now includes committed task-branch paths relative to +`origin/main` when it runs from a linked worktree. A docs-only branch therefore +stays on the focused path after commit and rebase instead of appearing +unclassifiably clean. CI and the primary checkout keep the conservative full +fallback. + +## Verification + +- `bash -n tools/check.sh` +- dirty linked-worktree run: focused gate selected +- committed linked-worktree run: focused gate still selected +- `git diff --check` +- `bash tools/wiki_gate.sh` + +No Cargo, clippy, or Bevy command is appropriate for this process/docs/script +classification change. diff --git a/wiki/log/DEVLOG.md b/wiki/log/DEVLOG.md index af8435bb..174a5bb6 100644 --- a/wiki/log/DEVLOG.md +++ b/wiki/log/DEVLOG.md @@ -5,6 +5,17 @@ Type: log ``` Reverse chronological implementation notes. Keep this factual: what changed, why, checks, and spec impact. +## 2026-07-09 - Proportional verification policy + +- Intent: stop full Cargo/clippy/Bevy gates from running for minor docs, spec, + process, log, or reference-art edits. +- Changed: binding agent instructions and workflow docs now require scoped + verification; `tools/check.sh` classifies committed linked-worktree changes + against `origin/main`, preserving the focused path after commit/rebase. +- Checks: shell syntax; dirty and committed focused-path runs; diff check; wiki + gate. No Rust/Bevy gate — this change cannot affect the game executable. +- Log: wiki/log/2026-07-09-proportional-checks.md. + ## 2026-07-09 - Knowledge token reopened against the hero - Intent: correct the hollow-facet token treatment after Cameron directed the diff --git a/wiki/process/development-style.md b/wiki/process/development-style.md index d09b571d..3518754a 100644 --- a/wiki/process/development-style.md +++ b/wiki/process/development-style.md @@ -54,8 +54,11 @@ That only works if: specifies it). 3. Implement in the sim core first, frontends second (see [architecture.md](../engineering/architecture.md)). -4. Verify: tests, clippy, both-feature builds, and an actual run (see - [workflows.md](workflows.md)). +4. Verify in proportion to impact (see [workflows.md](workflows.md)): + functional Rust/executable changes get tests, clippy, both-feature builds, + and an actual run; docs/spec/process/reference-art changes get only the + focused validators relevant to what changed. Never run the full Cargo/Bevy + gate solely because a minor-change worktree is clean. 5. Update any `Type: knowledge` wiki page the change made stale. 6. Write it down: `wiki/log/YYYY-MM-DD-topic.md` for a session's work, `wiki/log/DEVLOG.md` line for the ledger. diff --git a/wiki/process/workflows.md b/wiki/process/workflows.md index 4ff1af09..32cd75b3 100644 --- a/wiki/process/workflows.md +++ b/wiki/process/workflows.md @@ -25,19 +25,40 @@ incremental compilation stays warm. reason; override only for a deliberately isolated target with `MISALIGNED_ALLOW_EXTERNAL_TARGET=1`. -**One command runs the whole gate — use it before every commit:** +**Verification is proportional to impact.** The full Rust/Bevy gate is for +changes that can affect the executable, not every Markdown, log, process, or +reference-art edit. + +For Rust-impacting work (`src/`, Cargo/build configuration, Rust +tests/examples/benches), run: ```bash ./tools/check.sh # fmt, tests, clippy (both features), bevy build, spec headers, wiki gate, mdbook build ``` -`check.sh` is the executable form of AGENT.md's definition of done; if it -passes, the mechanical bar is met. Local dirty worktrees get a speed path: -when the only changed paths are docs/process/tooling that cannot affect Rust -artifacts, `check.sh` skips Cargo fmt/tests/clippy/Bevy and still runs shell -syntax, spec headers, the wiki gate, and mdBook. A clean checkout (including -CI after push) has no local diff to classify, so it always runs the full Rust -gate. Force the local full gate with `MISALIGNED_FORCE_RUST_GATE=1 ./tools/check.sh`. +For non-Rust work, run the smallest checks that can actually detect a mistake: + +- docs/spec/process/logs: `git diff --check` and `bash tools/wiki_gate.sh` when + wiki-facing; `mdbook build` only when the rendered book surface matters; +- reference art: validate the source format, render it, and inspect the output; +- public site: run the site sync/build relevant to the changed page or style; +- shell/tooling: syntax-check the changed script and run its targeted smoke or + fixture test. + +Do **not** run Cargo tests, clippy, or Bevy builds for a minor non-runtime +change. A green full gate proves nothing useful about prose or a reference SVG. + +`check.sh` implements this scope automatically in linked task worktrees. It +classifies both uncommitted files and commits on the task branch relative to +`origin/main`, so a docs-only branch remains on the focused path even after +commit/rebase. CI and an unclassifiable primary/clean checkout remain +conservative and run the full Rust gate. Force the local full gate only when +you intentionally need it: + +```bash +MISALIGNED_FORCE_RUST_GATE=1 ./tools/check.sh +``` + The individual steps, if you need them: ```bash @@ -194,7 +215,9 @@ sleep 8 && kill %1; grep -iE "panic|ERROR" /tmp/bevy.log - Spec-driven rule: functional change commits include their DESIGN.md amendment and any affected `Type: knowledge` wiki updates (see development-style.md). - Remote: `origin` is a Tangled knot (`tangled.org`, SSH). **Land changes - by merging to `main` directly** after `./tools/check.sh` passes. (The + by merging to `main` directly** after the appropriate scoped verification + passes (full `./tools/check.sh` for Rust-impacting work; focused checks for + docs/art/process-only work). (The "PRs are the norm" rule was removed 2026-07-07 — CLI-created PRs write to the PDS but don't render on tangled.org, so the process could not be followed. See the DESIGN.md decisions log.) From your worktree: -- 2.51.2