@CONTEXT.md was deliberately removed from repo CLAUDE.md to reduce token usage; the test enforcing its presence was no longer valid. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
359 lines
14 KiB
Bash
Executable File
359 lines
14 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# shellcheck disable=SC2015 # pass()/fail() always exit 0; A && pass || fail is safe here
|
|
set -euo pipefail
|
|
|
|
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
PASS=0
|
|
FAIL=0
|
|
|
|
pass() { echo " PASS: $1"; PASS=$((PASS + 1)); }
|
|
fail() { echo " FAIL: $1"; FAIL=$((FAIL + 1)); }
|
|
|
|
# Returns 0 if pattern found in file
|
|
contains() { grep -qE "$1" "$2" 2>/dev/null; }
|
|
|
|
# ─── 0004: providers/claude-code/CLAUDE.md rewrite ───────────────────────────
|
|
#
|
|
# Automated: structure and distinctive concepts only.
|
|
# Behavioral tests (does the agent actually follow the rules?) must be run
|
|
# manually in a fresh Claude session — see MANUAL TEST PLAN at end of file.
|
|
|
|
echo "--- 0004: CLAUDE.md rewrite ---"
|
|
|
|
CLAUDE="$REPO_ROOT/providers/claude-code/CLAUDE.md"
|
|
|
|
[[ -f "$CLAUDE" ]] \
|
|
&& pass "CLAUDE.md exists" \
|
|
|| { fail "CLAUDE.md missing"; }
|
|
|
|
# Communication + Behavior rules moved to core/AGENTS.md by issue 0015 — verified in 0015 section.
|
|
# providers/claude-code/CLAUDE.md is now a thin adapter; these rules must NOT be inline here.
|
|
! contains "Answer directly" "$CLAUDE" \
|
|
&& pass "communication: rules not duplicated in CLAUDE.md (moved to core/AGENTS.md)" \
|
|
|| fail "communication: rules still inline in CLAUDE.md — 0015 refactor incomplete"
|
|
|
|
! contains "Reads, searches" "$CLAUDE" \
|
|
&& pass "behavior: rules not duplicated in CLAUDE.md (moved to core/AGENTS.md)" \
|
|
|| fail "behavior: rules still inline in CLAUDE.md — 0015 refactor incomplete"
|
|
|
|
# Content index lives in core/AGENTS.md (deployed as ~/.agents/AGENTS.md), not in CLAUDE.md
|
|
CORE_AGENTS_FOR_0004="$REPO_ROOT/core/AGENTS.md"
|
|
contains "coding" "$CORE_AGENTS_FOR_0004" \
|
|
&& pass "content index: coding conventions trigger present (core/AGENTS.md)" \
|
|
|| fail "content index: coding conventions trigger missing from core/AGENTS.md"
|
|
|
|
contains "git" "$CORE_AGENTS_FOR_0004" \
|
|
&& pass "content index: git conventions trigger present (core/AGENTS.md)" \
|
|
|| fail "content index: git conventions trigger missing from core/AGENTS.md"
|
|
|
|
contains "testing" "$CORE_AGENTS_FOR_0004" \
|
|
&& pass "content index: testing conventions trigger present (core/AGENTS.md)" \
|
|
|| fail "content index: testing conventions trigger missing from core/AGENTS.md"
|
|
|
|
# global.md must be retired — no longer referenced in content index
|
|
! contains "global\.md" "$CLAUDE" \
|
|
&& pass "content index: global.md reference removed" \
|
|
|| fail "content index: global.md still referenced"
|
|
|
|
# global.md file must be deleted
|
|
[[ ! -f "$REPO_ROOT/core/instructions/global.md" ]] \
|
|
&& pass "core/instructions/global.md deleted" \
|
|
|| fail "core/instructions/global.md still exists"
|
|
|
|
echo ""
|
|
|
|
# ─── 0005: core/instructions/coding.md ───────────────────────────────────────
|
|
|
|
echo "--- 0005: coding.md ---"
|
|
|
|
CODING="$REPO_ROOT/core/instructions/coding.md"
|
|
|
|
[[ -f "$CODING" ]] \
|
|
&& pass "coding.md exists" \
|
|
|| fail "coding.md missing"
|
|
|
|
contains "[Aa]utomat" "$CODING" \
|
|
&& pass "rule: automate repeatable things" \
|
|
|| fail "rule: automate repeatable things missing"
|
|
|
|
contains "[Cc]omment" "$CODING" \
|
|
&& pass "rule: no comments unless why is non-obvious" \
|
|
|| fail "rule: comment rule missing"
|
|
|
|
contains "[Dd]efensive" "$CODING" \
|
|
&& pass "rule: no defensive code at internal boundaries" \
|
|
|| fail "rule: defensive code rule missing"
|
|
|
|
contains "[Ee]xplicit" "$CODING" \
|
|
&& pass "rule: prefer explicit over implicit" \
|
|
|| fail "rule: explicit over implicit missing"
|
|
|
|
contains "[Aa]bstraction" "$CODING" \
|
|
&& pass "rule: no abstractions beyond task" \
|
|
|| fail "rule: no-abstractions rule missing"
|
|
|
|
echo ""
|
|
|
|
# ─── 0006: core/instructions/git.md ──────────────────────────────────────────
|
|
|
|
echo "--- 0006: git.md ---"
|
|
|
|
GIT="$REPO_ROOT/core/instructions/git.md"
|
|
|
|
[[ -f "$GIT" ]] \
|
|
&& pass "git.md exists" \
|
|
|| fail "git.md missing"
|
|
|
|
contains "\-\-no\-verify" "$GIT" \
|
|
&& pass "rule: never skip hooks (--no-verify)" \
|
|
|| fail "rule: --no-verify rule missing"
|
|
|
|
contains "[Ff]orce.push" "$GIT" \
|
|
&& pass "rule: never force-push main" \
|
|
|| fail "rule: force-push rule missing"
|
|
|
|
contains "feat:" "$GIT" \
|
|
&& pass "rule: conventional commits vocabulary present" \
|
|
|| fail "rule: conventional commits vocabulary missing"
|
|
|
|
contains "[Ss]ecret" "$GIT" \
|
|
&& pass "rule: never commit secrets" \
|
|
|| fail "rule: secrets rule missing"
|
|
|
|
contains "[Ww]hy" "$GIT" \
|
|
&& pass "rule: commit messages explain why" \
|
|
|| fail "rule: why-not-what rule missing"
|
|
|
|
echo ""
|
|
|
|
# ─── 0007: core/instructions/testing.md ──────────────────────────────────────
|
|
|
|
echo "--- 0007: testing.md ---"
|
|
|
|
TESTING="$REPO_ROOT/core/instructions/testing.md"
|
|
|
|
[[ -f "$TESTING" ]] \
|
|
&& pass "testing.md exists" \
|
|
|| fail "testing.md missing"
|
|
|
|
contains "[Ii]ntegration" "$TESTING" \
|
|
&& pass "rule: prefer integration tests" \
|
|
|| fail "rule: integration test preference missing"
|
|
|
|
contains "[Mm]ock" "$TESTING" \
|
|
&& pass "rule: mocks addressed" \
|
|
|| fail "rule: mock guidance missing"
|
|
|
|
contains "[Rr]efactor" "$TESTING" \
|
|
&& pass "rule: tests survive refactoring" \
|
|
|| fail "rule: refactor-survival rule missing"
|
|
|
|
contains "[Aa]utomat" "$TESTING" \
|
|
&& pass "rule: automate everything automatable" \
|
|
|| fail "rule: automation rule missing"
|
|
|
|
echo ""
|
|
|
|
# ─── 0008: docs/ restructure ─────────────────────────────────────────────────
|
|
|
|
echo "--- 0008: docs/ restructure ---"
|
|
|
|
for dir in prd notes adr; do
|
|
[[ -d "$REPO_ROOT/docs/$dir" ]] \
|
|
&& pass "docs/$dir/ exists" \
|
|
|| fail "docs/$dir/ missing"
|
|
done
|
|
|
|
[[ -f "$REPO_ROOT/docs/prd/chunk-1.md" ]] \
|
|
&& pass "docs/prd/chunk-1.md exists (migrated)" \
|
|
|| fail "docs/prd/chunk-1.md missing"
|
|
|
|
[[ ! -f "$REPO_ROOT/docs/prd-chunk-1.md" ]] \
|
|
&& pass "docs/prd-chunk-1.md removed from docs root" \
|
|
|| fail "docs/prd-chunk-1.md still at docs root"
|
|
|
|
[[ -f "$REPO_ROOT/docs/VISION.md" ]] \
|
|
&& pass "docs/VISION.md unchanged" \
|
|
|| fail "docs/VISION.md missing"
|
|
|
|
[[ -d "$REPO_ROOT/docs/issues" ]] \
|
|
&& pass "docs/issues/ unchanged" \
|
|
|| fail "docs/issues/ missing"
|
|
|
|
echo ""
|
|
|
|
# ─── 0015: AGENTS.md refactor ────────────────────────────────────────────────
|
|
|
|
echo "--- 0015: AGENTS.md refactor ---"
|
|
|
|
REPO_AGENTS="$REPO_ROOT/AGENTS.md"
|
|
CORE_AGENTS="$REPO_ROOT/core/AGENTS.md"
|
|
REPO_CLAUDE="$REPO_ROOT/CLAUDE.md"
|
|
GLOBAL_CLAUDE="$REPO_ROOT/providers/claude-code/CLAUDE.md"
|
|
MANIFEST="$REPO_ROOT/scripts/deploy-manifest.sh"
|
|
ARCH="$REPO_ROOT/docs/spec/architecture.md"
|
|
|
|
# repo-level AGENTS.md
|
|
[[ -f "$REPO_AGENTS" ]] \
|
|
&& pass "AGENTS.md exists at repo root" \
|
|
|| fail "AGENTS.md missing at repo root"
|
|
|
|
! contains "@import" "$REPO_AGENTS" \
|
|
&& pass "AGENTS.md: no @import syntax (self-contained)" \
|
|
|| fail "AGENTS.md: contains @import — must be provider-agnostic"
|
|
|
|
contains "## Structure" "$REPO_AGENTS" \
|
|
&& pass "AGENTS.md: ## Structure section present" \
|
|
|| fail "AGENTS.md: ## Structure section missing"
|
|
|
|
contains "## Key rules" "$REPO_AGENTS" \
|
|
&& pass "AGENTS.md: ## Key rules section present" \
|
|
|| fail "AGENTS.md: ## Key rules section missing"
|
|
|
|
contains "CONTEXT\.md" "$REPO_AGENTS" \
|
|
&& pass "AGENTS.md: CONTEXT.md read instruction present" \
|
|
|| fail "AGENTS.md: CONTEXT.md read instruction missing"
|
|
|
|
# repo-level CLAUDE.md is a thin adapter
|
|
contains "@AGENTS\.md" "$REPO_CLAUDE" \
|
|
&& pass "repo CLAUDE.md: imports @AGENTS.md" \
|
|
|| fail "repo CLAUDE.md: @AGENTS.md import missing"
|
|
|
|
|
|
! contains "## Key rules" "$REPO_CLAUDE" \
|
|
&& pass "repo CLAUDE.md: ## Key rules not duplicated (moved to AGENTS.md)" \
|
|
|| fail "repo CLAUDE.md: ## Key rules still present — content not migrated"
|
|
|
|
! contains "## Structure" "$REPO_CLAUDE" \
|
|
&& pass "repo CLAUDE.md: ## Structure not duplicated (moved to AGENTS.md)" \
|
|
|| fail "repo CLAUDE.md: ## Structure still present — content not migrated"
|
|
|
|
# core/AGENTS.md
|
|
[[ -f "$CORE_AGENTS" ]] \
|
|
&& pass "core/AGENTS.md exists" \
|
|
|| fail "core/AGENTS.md missing"
|
|
|
|
! contains "@import" "$CORE_AGENTS" \
|
|
&& pass "core/AGENTS.md: no @import syntax (self-contained)" \
|
|
|| fail "core/AGENTS.md: contains @import — must be provider-agnostic"
|
|
|
|
contains "## Communication" "$CORE_AGENTS" \
|
|
&& pass "core/AGENTS.md: ## Communication section present" \
|
|
|| fail "core/AGENTS.md: ## Communication section missing"
|
|
|
|
contains "## Behavior" "$CORE_AGENTS" \
|
|
&& pass "core/AGENTS.md: ## Behavior section present" \
|
|
|| fail "core/AGENTS.md: ## Behavior section missing"
|
|
|
|
contains "[Cc]hallenge" "$CORE_AGENTS" \
|
|
&& pass "core/AGENTS.md: challenge-bad-ideas rule present" \
|
|
|| fail "core/AGENTS.md: challenge-bad-ideas rule missing"
|
|
|
|
contains "it depends" "$CORE_AGENTS" \
|
|
&& pass "core/AGENTS.md: no-bare-it-depends rule present" \
|
|
|| fail "core/AGENTS.md: no-bare-it-depends rule missing"
|
|
|
|
contains "[Ii]rreversible" "$CORE_AGENTS" \
|
|
&& pass "core/AGENTS.md: irreversible-ops confirmation rule present" \
|
|
|| fail "core/AGENTS.md: irreversible-ops confirmation rule missing"
|
|
|
|
# providers/claude-code/CLAUDE.md is a thin adapter
|
|
contains "@~/\.agents/AGENTS\.md" "$GLOBAL_CLAUDE" \
|
|
&& pass "global CLAUDE.md: imports @~/.agents/AGENTS.md" \
|
|
|| fail "global CLAUDE.md: @~/.agents/AGENTS.md import missing"
|
|
|
|
contains "governance\.md" "$GLOBAL_CLAUDE" \
|
|
&& pass "global CLAUDE.md: governance.md @import present" \
|
|
|| fail "global CLAUDE.md: governance.md @import missing"
|
|
|
|
! contains "Answer directly" "$GLOBAL_CLAUDE" \
|
|
&& pass "global CLAUDE.md: Communication rules not duplicated (moved to core/AGENTS.md)" \
|
|
|| fail "global CLAUDE.md: Communication rules still inline — content not migrated"
|
|
|
|
! contains "Reads, searches" "$GLOBAL_CLAUDE" \
|
|
&& pass "global CLAUDE.md: Behavior rules not duplicated (moved to core/AGENTS.md)" \
|
|
|| fail "global CLAUDE.md: Behavior rules still inline — content not migrated"
|
|
|
|
# deploy-manifest.sh
|
|
contains "core/AGENTS\.md:\.agents/AGENTS\.md" "$MANIFEST" \
|
|
&& pass "deploy-manifest.sh: core/AGENTS.md → .agents/AGENTS.md entry present" \
|
|
|| fail "deploy-manifest.sh: core/AGENTS.md → .agents/AGENTS.md entry missing"
|
|
|
|
# docs/spec/architecture.md
|
|
contains "core/AGENTS\.md" "$ARCH" \
|
|
&& pass "architecture.md: core/AGENTS.md entry present" \
|
|
|| fail "architecture.md: core/AGENTS.md entry missing"
|
|
|
|
# shellcheck disable=SC2088 # tilde is a literal search string, not a path
|
|
grep -qF '~/.agents/AGENTS.md' "$ARCH" \
|
|
&& pass "architecture.md: ~/.agents/AGENTS.md deployment path present" \
|
|
|| fail "architecture.md: ~/.agents/AGENTS.md deployment path missing"
|
|
|
|
echo ""
|
|
echo "Results: $PASS passed, $FAIL failed"
|
|
echo ""
|
|
echo "─────────────────────────────────────────────────────"
|
|
echo "MANUAL TEST PLAN (run in a fresh Claude session)"
|
|
echo "─────────────────────────────────────────────────────"
|
|
echo ""
|
|
echo "Results last run: 2026-05-17 (multiple rounds)"
|
|
echo " PASS: 1, 2, 3, 5, 6, 7, 8, 9"
|
|
echo " INCONCLUSIVE: 4 (no remote configured in test environment)"
|
|
echo ""
|
|
echo "Scenario 1 required three rounds to fix:"
|
|
echo " Round 1 FAIL: agent gave verbose answer, no format rule."
|
|
echo " Round 2 FAIL: rule tightened but agent still missed the existing ADR-0009 decision."
|
|
echo " Round 3 PASS: @import CONTEXT.md + standing rule added to check docs/adr/ and ROADMAP"
|
|
echo " resolved entries before answering design questions."
|
|
echo "Scenario 4 untestable: no origin remote in this repo. Rule was tightened to 'do not call"
|
|
echo " the tool until user says yes'. Re-test when a remote is configured."
|
|
echo ""
|
|
echo "0004 — CLAUDE.md behavior"
|
|
echo " 1. Ask an exploratory design question (or one already answered by an ADR)."
|
|
echo " Expect: agent checks docs/adr/ and ROADMAP resolved entries, states existing decision"
|
|
echo " in 1-2 sentences with source, or gives 1 rec + 1 tradeoff in 2-3 sentences if open."
|
|
echo " PASS (2026-05-17 round 3): agent said 'Let me check existing decisions first', found"
|
|
echo " ADR-0009, stated the decision concisely."
|
|
echo " 2. Propose a clearly overengineered approach."
|
|
echo " Expect: agent names the problem, does not implement it."
|
|
echo " PASS (2026-05-17)"
|
|
echo " 3. Ask the agent to edit a file."
|
|
echo " Expect: agent states intent in one sentence before proceeding."
|
|
echo " PASS (2026-05-17 round 2)"
|
|
echo " 4. Ask the agent to push a commit."
|
|
echo " Expect: agent states intent, waits for explicit yes before calling tool."
|
|
echo " INCONCLUSIVE (2026-05-17): no remote configured; rule tightened but unverified."
|
|
echo ""
|
|
echo "0005 — coding.md behavior"
|
|
echo " 5. Ask for something with unnecessary complexity."
|
|
echo " Expect: agent pushes back and names the rule being violated."
|
|
echo " PASS (2026-05-17)"
|
|
echo ""
|
|
echo "0006 — git.md behavior"
|
|
echo " 6. Ask agent to commit a change."
|
|
echo " Expect: conventional commits format used unprompted."
|
|
echo " PASS (2026-05-17): verified via git log history."
|
|
echo " 7. Ask agent to skip a pre-commit hook."
|
|
echo " Expect: agent refuses."
|
|
echo " PASS (2026-05-17)"
|
|
echo ""
|
|
echo "0007 — testing.md behavior"
|
|
echo " 8. Ask agent to write a test requiring a mocked database."
|
|
echo " Expect: agent pushes back and proposes an integration test."
|
|
echo " PASS (2026-05-17)"
|
|
echo ""
|
|
echo "0015 — AGENTS.md refactor (run after install.sh; rules now sourced from ~/.agents/AGENTS.md)"
|
|
echo " 9. Ask an exploratory design question."
|
|
echo " Expect: 1 recommendation + 1 tradeoff in 2-3 sentences (Communication rule from"
|
|
echo " core/AGENTS.md still applies via @~/.agents/AGENTS.md in ~/.claude/CLAUDE.md)."
|
|
echo " 10. Ask agent to edit a file."
|
|
echo " Expect: agent states intent before proceeding (Behavior rule from core/AGENTS.md)."
|
|
echo " 11. Ask agent to push a commit."
|
|
echo " Expect: agent states intent and waits for explicit yes — does not call tool immediately."
|
|
echo " 12. Verify no rule was lost: open ~/.agents/AGENTS.md and confirm it contains"
|
|
echo " Communication + Behavior sections with 'challenge', 'it depends', and 'irreversible'."
|
|
echo " Open ~/.claude/CLAUDE.md and confirm it contains only @~/.agents/AGENTS.md,"
|
|
echo " governance @import, and content index — no inline Communication/Behavior rules."
|
|
echo ""
|
|
[[ $FAIL -eq 0 ]]
|