Skip to content

[Chore] require-agdr-for-arch-pr.sh — block gh pr create when diff touches architecture without AgDR link #112

@atlas-apex

Description

@atlas-apex

Driver

.claude/rules/agdr-decisions.md calls /decide a HARD STOP before any technical decision — library choice, architecture move, new dependency, infra shape. The Code Reviewer agent post-hoc nudges the author if a PR touches architecture without a linked AgDR. There is no PreToolUse hook. The rule is asymmetric: every other HARD STOP in the ruleset (merge approval, ticket-first, migration-first) is mechanically enforced; this one is not.

Scope

Add .claude/hooks/require-agdr-for-arch-pr.sh, wired to PreToolUse on Bash matching gh pr create ….

The hook:

  1. Reads the PR's diff via git diff $(git merge-base HEAD <base>)..HEAD --name-only.

  2. Loads a configurable set of arch-change patterns from project config:

    # .claude/project-config.json
    agdr_trigger_paths:
      - "**/domain/**"           # DDD domain layer
      - "**/infrastructure/**"   # infra code in hexagonal layout
      - "**/migrations/**"       # data migrations (handled separately by migration hook too)
      - "infrastructure/**"      # Terraform
      - "template.yaml"          # SAM
      - "**/*.tf"                # Terraform HCL
      - ".github/workflows/**"   # CI
    agdr_trigger_dep_files:
      - "package.json"           # new deps
      - "pyproject.toml"
      - "Cargo.toml"
      - "go.mod"
      - "Gemfile"
  3. If any changed file matches agdr_trigger_paths, OR any dep-file is modified in a way that adds a dependency, require the PR body to contain a reference matching AgDR-\d+-[a-z0-9-]+.

  4. For dep files: parse the diff to detect additions in the dependency sections (don't fire on version bumps — those are a separate /audit-deps concern).

  5. On fail: exit 2 with a message naming the triggering file(s) and the skill to invoke (/decide).

  6. Skip condition: body contains <!-- agdr: not-applicable --> (rare — e.g. a PR that renames a dependency without a decision change).

Acceptance Criteria

  • Hook fires only when the diff touches a trigger path or adds a dependency.
  • Hook blocks when no AgDR- reference is in the body.
  • Hook passes silently when there's no trigger (most PRs).
  • Skip marker passes with a warning.
  • Configurable path list ships with sensible defaults; fork owners extend without framework edits.
  • Diff parser distinguishes added deps from version-only bumps (unit-tested).
  • Fixtures in .claude/hooks/tests/ cover: domain change, infra change, new dep, version-only bump (no fire), skip marker.
  • docs/rule-audit.md entry added.

Risks / Dependencies

  • False positive on refactors that move files through a trigger path without introducing a decision. Mitigation: skip marker.
  • Diff parsing for package.json dependency additions (not bumps) is non-trivial. Use jq or a tiny diff parser. Cover with tests.
  • Shares config with the issue-structure validator (apexyard#107). Land after the config location is decided (apexyard#109).

Glossary

Term Definition
AgDR Agent Decision Record — a Markdown file under docs/agdr/ capturing a technical decision.
Trigger path A glob pattern; any file in the PR diff matching it fires the AgDR requirement.
Dep file A dependency manifest; only additions (new deps) fire the requirement, not version bumps.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1High — material gap or user-impactingenhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions