Skip to content

chore(agents): make local checks targeted and setup non-destructive - #706

Merged
JArmandoAnaya merged 3 commits into
mainfrom
chore/targeted-local-check-policy
Aug 19, 2026
Merged

chore(agents): make local checks targeted and setup non-destructive#706
JArmandoAnaya merged 3 commits into
mainfrom
chore/targeted-local-check-policy

Conversation

@JArmandoAnaya

@JArmandoAnaya JArmandoAnaya commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

The agent-policy consolidation that merged as the one-home-per-rule change (#705) left two gaps on main. The check policy still required a full local bash scripts/check.sh run once before every pull request, kept "every commit leaves the checks above green", and escalated two whole change categories straight to the full gate — each of which reads, to a coding agent, as an instruction to run the entire repository locally before ordinary work is allowed to complete. And scripts/setup_agents.sh deleted a regular CLAUDE.md to replace it with the AGENTS.md symlink, which is destructive toward a file that may carry a developer's local configuration.

What changed

The policy now says one thing, in AGENTS.md ## Checks, and the other documents point at it: local development runs the smallest set of checks that gives real feedback on the change, GitHub Actions runs the exhaustive matrix on every pull request, and reading what CI answered is part of pushing. High-risk changes escalate to broader relevant checks — the real-server cycle scenario for anything touching state, gating or progress, the generation/drift checks and stub-driven browser specs for a published wire shape — never automatically to every test in the repository. scripts/check.sh keeps all of its groups and remains the comprehensive local run for the moments a developer deliberately chooses its cost: reproducing a CI failure, debugging an integration problem, validating a high-risk change locally. It is no longer described as a routine step before a commit, push, or pull request. CONTRIBUTING.md, refactor-protocol, python-setup and nodejs-setup were reconciled to the same statement; "Report failures verbatim. Never claim a check passed without running it" stands unchanged.

setup_agents.sh now creates the CLAUDE.md → AGENTS.md symlink only where no CLAUDE.md exists, and the expected symlink is recognized and left alone on re-runs. A conflicting CLAUDE.md — a regular file, a directory, or a symlink to any other target — is preserved exactly as found and fails the run: the script prints an ERROR naming what it found and the manual command that adopts the canonical text, exits non-zero, and does so before creating or pruning any skill symlink, so a conflict performs no setup at all and never prints the success message. A new regression suite, tests/scripts/setup_agents.test.mjs, runs the real script in a throwaway repository layout and holds six cases: the symlink is created where nothing exists, both runs of an idempotent pair succeed, a regular CLAUDE.md survives byte-for-byte and fails the run with nothing created, a directory survives whole and fails the run, a foreign symlink keeps its target and the error names both targets, and a deleted skill's dangling link is pruned.

Test plan

Targeted validation, which is the policy this pull request states; the exhaustive matrix is delegated to this pull request's own CI by design.

bash -n scripts/setup_agents.sh                                          clean
node --test tests/scripts/setup_agents.test.mjs                          6 pass, 0 fail
node --test tests/scripts/check_stages.test.mjs tests/scripts/docs_links.test.mjs
                                                                         18 pass, 0 fail
uv run pytest tests/architecture/test_tracked_file_sizes.py              4 passed
git diff --check                                                         clean

Found, not fixed

.gitignore lists .codex/ among the generated agent directories, but setup_agents.sh has never created it; the entry is either anticipatory or stale. Nothing in this change depends on it.

The policy still carried a mandatory comprehensive step: check.sh ran once
before every pull request, every commit was to leave the full check table
green, and two change categories escalated straight to the whole gate. Each
of those reads as an instruction to run the entire repository locally, which
is CI's job.

The policy now says one thing in one place: choose the smallest set of
checks that gives real feedback on the change, read what CI answered after
pushing, and never claim a check passed without running it. High-risk
changes escalate to the *relevant* suites — the real-server cycle scenario
for state, gating and progress, the drift checks and stub-driven browser
specs for a published wire shape — not automatically to everything.
check.sh keeps every group and stays the comprehensive local run for the
moments a developer deliberately chooses its cost: reproducing a CI failure,
debugging an integration problem, validating a high-risk change.
setup_agents.sh deleted a regular CLAUDE.md and replaced it with the
AGENTS.md symlink. A CLAUDE.md that is not the generated symlink is a
developer's own file, possibly carrying local configuration, and a setup
script has no business converting it by force.

The symlink is now created only where nothing exists. The expected symlink
is recognized and left alone; a regular file, a directory, or a symlink to
any other target is left exactly as found, with a notice naming what was
found and the manual command that adopts the canonical text. A regression
test runs the real script in a throwaway repository layout and holds all
five cases: creation, idempotence, the preserved regular file, the
preserved foreign symlink, and the pruning of a deleted skill's link.
Preserving an unexpected CLAUDE.md while exiting 0 was the quieter half of
the failure the last commit removed: a caller reads "setup succeeded"
while Claude is still reading a divergent file. A conflicting CLAUDE.md —
a regular file, a directory, or a symlink to any other target — now aborts
the run with an ERROR on stderr and a non-zero exit, and the check happens
before any skill symlink is created or pruned, so a conflict leaves the
tree exactly as it found it and never prints the success message. The
missing-file and expected-symlink paths are unchanged: create, or
recognize and succeed.

The regression suite flips the file and foreign-symlink cases to expect
failure, asserts the conflict performed no setup at all, and adds the
directory case.
@JArmandoAnaya
JArmandoAnaya merged commit e731a9c into main Aug 19, 2026
15 checks passed
@JArmandoAnaya
JArmandoAnaya deleted the chore/targeted-local-check-policy branch August 19, 2026 08:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant