↑ ↓ to move · Enter to open · Esc to closeTap a result

Architecture
agent · class installer · sonnet

archunit-installer

Installs ArchUnit and wires the JaCoCo coverage gate into an already-generated project. Invoked by test-architect's setup mode, never by you.

agent · installersonneteffort medium6 allowed paths
§ the agent's definition

archunit-installer.md, section by section

The sections of the agent's own file, excerpted. Hover or click one to see which project rules and templates it cites. The sections are also chips: click one to jump to it.

nerviz/.claude/agents/archunit-installer.md

## Why this is an agent (Form 3)

Preserves context. Setup mode is purely mechanical: resolve a version from Maven Central, translate exemplar packages to the project's own, write one file, edit the POM twice, run ./mvnw up to three times, iterate until green. None of it needs the conversation — unlike test-architect's design mode, which stays inline on purpose because its interview reads live decisions no subagent can see (@.claude/decisions/0008-testing-rule-and-design.md). Run inline, every curl response and every ./mvnw build log — often the longest single output in a session — lands permanently in the caller's context and gets re-paid on every later turn. Isolating it costs design mode nothing and stops that bill. Invariant 6 requires only one of the three reasons; this is the one that applies.

omitClaudeMd: true: the root CLAUDE.md is a declared input, Read explicitly for the commons package; auto-loading it too paid for the same file twice (@.claude/decisions/0083-unused-ecosystem-fields-and-real-allow-list.md).

No tool or model reason applies on its own — reads and writes stay inside the project, and package-translation reasoning doesn't need more than sonnet already used elsewhere in this repo (java-spring-boot-developer).

## Procedure

  1. Resolve the ArchUnit version on Maven Central, never from memory:
        1. Declare the dependency without <version> only in the module with
        1. Write <main-module>/src/test/java/<packageBase>/ArchitectureTest.java with the
        1. **Translate the packages to the project's own — and the naming-convention rules with

        … cut here, the rest is in the file

        ## Failure mode

        No network for step 1: `` ❌ archunit-installer stopped — no network reachable to resolve the ArchUnit version Ask the user for the version, or retry once network is back. ``

        Compilation or ArchUnit rule breaks after translation: `` ❌ ArchitectureTest.java: rule "domain must not depend on adapter" failed on [Class].java:12 — <real violation> Translation bug or a real boundary violation — fix before continuing. ``

        Coverage gate fails: `` ❌ Coverage gate: 61% lines / 48% branches (needs 80% / 70%) Gate wired correctly; missing tests is test-architect design mode's job, not this agent's. ``

        No rollback. The caller decides whether to retry after a fix.

        ---

        ## Summary format returned to the caller

        ✅ archunit-installer complete
        - ArchUnit: <version> (Maven Central)
        - ArchitectureTest.java: written, <n> rules, packages translated to <packageBase>
        - ./mvnw test: green
        - Coverage gate: wired (80% line / 70% branch) — ./mvnw clean verify → <PASS <n%>/<n%> | FAIL <n%>/<n%>>
        - Testcontainers image: pinned to postgres:16-alpine
        - docker-compose.yml: <in sync | mismatch — <engine> pinned to <tag>, invoke docker-architect>

        On failure, same shape with ❌ and the one line that matters (real coverage number, or the failing rule and why) — not the full build log.

        ---

        ## References

        • Invariant 6 — agent only for one of three reasons (context, tools, model)
        • @.claude/decisions/0011-bootstrap-without-business-code.md — why setup mode runs
        • @.claude/decisions/0030-archunit-installer-split.md — why this agent was split out
        • @.claude/rules/testing.md — coverage gate numbers, pyramid
        • @.claude/rules/persistence.md § Boundary — why the Testcontainers tag must match
        Open the full file on GitHub →
        § behavior

        What it reads, writes and refuses

        The skill's own contract, from SKILL.md, in the original wording.

        Class

        installer — the territory is agent_classes.installer.overrides.archunit-installer in @.claude/schemas/extensions.json: the POMs, ArchitectureTest.java, and TestcontainersConfiguration.java. Nothing else. The Does not write: list below is that data restated in prose, not a second promise: ArchHook.java guard reads this agent's agent_type on every write and refuses a path outside the list with exit 2.

        Executor

        yes — writes under src/ while a design phase may still be open. The class grants it (executor: true), and ArchHook.java schema cross-checks this marker against that flag in both directions.

        Pattern catalog

        not injected — copies fixed templates, designs no code (agent_classes.installer.pattern_catalog: false; schema cross-checks this line).

        Input (required)

        project root. Precondition — business classes already exist — is the caller's (test-architect's) to check before invoking; this agent doesn't re-verify it.

        Reads

        root POM, module POMs, docker-compose.yml (tag comparison only), the active blueprint's YAML (for packages.map and the naming-convention comment), .claude/forbidden-imports.txt, .claude/rules/testing.md, .claude/rules/naming.md, .claude/rules/code-quality.md, .claude/skills/test-architect/templates/ArchitectureTest.java.example, .claude/skills/test-architect/templates/PersistenceIT.java.example (image tag reference only).

        Writes

        <main-module>/src/test/java/<packageBase>/ArchitectureTest.java; the ArchUnit <archunit.version> property and dependencyManagement entry in the root POM, plus the bare dependency declaration in the module with contains_main: true; the jacoco-maven-plugin's check execution in the root POM; the pinned Testcontainers image tag — one line — in the Initializr-generated TestcontainersConfiguration.java.

        Does not write

        docker-compose.yml (single owner is docker-architect), anything under src/test/ besides ArchitectureTest.java, any file under docs/use-cases/.

        Does not invoke other agents or skills — no `Agent` tool

        If the Testcontainers tag doesn't match docker-compose.yml, report the mismatch in the summary and stop there. The caller reports it too, with the /docker-architect command that resolves it: nobody chains that skill from inside a design run, and the guard refuses the call if anybody tries.

        Returns

        one structured summary (shape at the bottom). Not the raw curl or ./mvnw output — that output does its job by making this run correct, not by traveling back to the caller.

        Source: the agent's § Contract, at nerviz e4cae27.

        § guard and hook

        What the guard does with it

        installer is the agent's class. ArchHook reads its agent_type on every write and judges the path against the list on the left; the skill it invokes gets no territory of its own. The text on the right is the hook's own.

        write_allow of class archunit-installer

        • ✓pom.xml
        • ✓**/pom.xml
        • ✓src/test/java/**/ArchitectureTest.java
        • ✓**/src/test/java/**/ArchitectureTest.java
        • ✓src/test/java/**/TestcontainersConfiguration.java
        • ✓**/src/test/java/**/TestcontainersConfiguration.java
        • any path outside this list: refused, exit 2

        A refusal exits with code 2 and the message goes back to the model.

        PreToolUse  Agent(archunit-installer)
          audit call                       exit 0
          guard call                       exit 0
        SubagentStart
          context subagent                 exit 0
          tests agent-start                exit 0
        # installer · sonnet · write_allow: pom.xml, **/pom.xml, src/test/java/**/ArchitectureTest.java, **/src/test/java/**/ArchitectureTest.java, src/test/java/**/TestcontainersConfiguration.java, **/src/test/java/**/TestcontainersConfiguration.java
        
        § how it is called

        Who calls it

        This agent is not a step of /new-feature-implement: another skill calls it, and the agent's description says which. The guard judges its writes by its own class, whatever phase is open.

        ← back to the chains