| name | architecture-review |
| description | Use when reviewing codebase architecture for refactoring opportunities, surfacing shallow modules, or proposing deepening refactors. Identifies architectural friction and produces GitHub issues with the ops-triage labeling scheme. Supports interactive (human approval) and auto (CI/headless) modes — auto mode files every surviving candidate directly and writes a step-summary report. |
Modes
Two execution modes. Pick by context, not by preference.
| Mode | Behaviour | When to use |
|---|
| Interactive (default) | Present a numbered candidate list. Wait for user approval. File issues one-by-one as approved. | Local run with a human in the loop. |
| Auto | Apply deletion test, dedupe against existing issues, file every surviving candidate directly, write a step-summary report. Do not stop to ask. | CI / headless run with no human in the loop. |
Auto mode is selected by ARCHITECTURE_REVIEW_MODE=auto (set by the calling workflow) or by an explicit "run in auto mode" directive in the invoking message. Default is interactive.
Mode Detection
Determine the mode in this priority order:
- Explicit directive — if the invoking message contains "auto mode" or "interactive mode", honour it.
- Env var —
ARCHITECTURE_REVIEW_MODE (auto | interactive). The CI workflow sets this; honour it.
- Default —
interactive. Used when neither signal is present.
Never guess the other direction. If signals disagree (e.g., directive says auto but env says interactive), prefer the explicit directive and log the conflict to the step summary.
Core Workflow
1. Explore
If the project has CONTEXT.md or docs/adr/, read them first. Don't flag their absence.
Walk the codebase and note friction:
- Where understanding one concept requires bouncing between many small modules
- Where modules are shallow (interface nearly as complex as implementation)
- Where pure functions were extracted for testability but real bugs hide in how they're called (no locality)
- Where tightly-coupled modules leak across their seams
- Which parts are untested or hard to test through their current interface
Apply the deletion test: would deleting the suspect module concentrate complexity (keep) or move it (remove)?
2a. Ship candidates — Interactive
Search GitHub issues for existing reports on the identified friction to avoid duplicates. Present a numbered list of deepening opportunities, then create a GitHub issue for every new candidate the user approves.
Issue title — Deepen <module-name>: <one-line outcome>
Issue body includes: context, recommendation strength, files involved, current shape vs target shape, acceptance criteria.
Labels — exactly one per category: chore (category), planned (state), afk (default execution).
Stop and wait for user confirmation before creating any issue.
2b. Ship candidates — Auto
Auto mode requires a different protocol because there is no human to approve between discovery and filing. Load references/auto-mode.md before executing this step — it codifies the dedupe, creation, and reporting commands.
For each candidate that survives the deletion test:
- Dedupe — run
gh issue list --state all --limit 200 --json number,title --search "Deepen <module-keyword>" against the target repo. If a match exists, record duplicate: #N in the step summary and move on.
- Re-dedupe at creation time — between dedupe and
gh issue create, the agent runs in a single shell context, so a re-run is unnecessary in practice. (Documented in references/auto-mode.md for future hardening.)
- Create — run
gh issue create --title "Deepen <module>: <outcome>" --body-file - --label chore,planned,afk --repo "$GITHUB_REPOSITORY", piping the issue body via stdin. Capture the new issue URL.
- Record outcome — append one row per candidate to
$GITHUB_STEP_SUMMARY with Action ∈ {created, duplicate, skipped} and a rationale.
Final line of the step summary: Created N issues, skipped M duplicates, K other.
Failure handling: on a single gh failure, capture stderr, log the candidate title and the error to the step summary, and continue with the remaining candidates. Never abort the batch on one error.
If $GITHUB_STEP_SUMMARY is not writable, fall back to stdout. The run still succeeds; the report just lands in the job log instead of the summary tab.
Issue body includes: context, recommendation strength, files involved, current shape vs target shape, acceptance criteria — same as interactive.
Labels — exactly the triplet chore, planned, afk per issue. No extras.
3. Grilling loop (user-initiated)
When the user picks a candidate, load references/deepening.md and walk the design tree:
- Classify dependencies
- Shape the deepened module
- Decide testing strategy
- Apply seam discipline
- Update CONTEXT.md
In auto mode, step 3 does not run.
Common Rationalizations
| Rationalization | Reality |
|---|
| "The code works, don't touch it" | Working code with shallow modules costs more in cognitive load and bugs than the refactor. |
| "I'll refactor when I need to change this area" | By then the module has 5 callers and the refactor is 10× harder. |
| "This abstraction is fine, it's just one wrapper" | Every wrapper is indirection. A pass-through wrapper that concentrates no logic is noise. |
| "The deletion test says keep — it's earning its keep" | Keep is not permanent. The test says it earns its keep today. Flag it anyway for tracking. |
| "Auto mode will spam the repo with junk" | The deletion test and dedupe run first. Only survivors land as issues. Every decision is auditable in the step summary. |
Red Flags
Verification
Constraints
MUST DO
- Use vocabulary from
references/language.md exactly.
- Read
CONTEXT.md and docs/adr/ if they exist before exploring.
- Apply the deletion test before flagging any module as shallow.
- Check for existing GitHub issues before creating a new one.
- Label each issue with exactly one category, state, execution.
- Auto: load
references/auto-mode.md before executing step 2b.
- Auto: write one row per candidate to
$GITHUB_STEP_SUMMARY.
- Auto: on a single
gh failure, capture stderr, log to step summary, continue with remaining candidates.
- Auto: never propose interface signatures or code in the issue body (existing rule — preserved).
MUST NOT DO
- Propose interface signatures or code in step 2.
- Suggest creating CONTEXT.md or ADRs proactively.
- Re-litigate ADR decisions unless friction genuinely warrants reopening.
- Introduce a port with only one adapter.
- Layer tests on top of existing tests — replace them.
- Bundle multiple candidates into a single issue.
- Auto: stop mid-batch to ask the human a clarifying question.
- Auto: abort the batch on a single
gh issue create failure.
- Auto: silently drop a candidate — every decision (created / duplicate / skipped) appears in the step summary.
Reference Guide
| File | When to load |
|---|
references/architecture-rules.md | Before step 1 (Explore) and before step 2 (Ship candidates) |
references/language.md | When writing proposals, issue bodies, or documentation |
references/deepening.md | When user initiates step 3 (Grilling loop) |
references/auto-mode.md | Auto mode only — before executing step 2b |