PostToolUse hooks run after every file edit: - Backend: ./mvnw compile (Checkstyle Google Style + javac) - Frontend: vue-tsc --noEmit + oxlint + ESLint Stop hook runs test suites when source files changed, blocks the agent on failure and re-engages it to fix the issue. Output is filtered to [ERROR] lines only for context efficiency. Static analysis: Checkstyle (validate phase), SpotBugs (verify phase), ArchUnit (9 hexagonal architecture rules as JUnit tests). Fail-fast: Surefire skipAfterFailureCount=1, Vitest bail=1. Test log noise suppressed via logback-test.xml (WARN level), redirectTestOutputToFile, and trimStackTrace. Existing Java sources reformatted to Google Style (2-space indent, import order, Javadoc on public types). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
217 lines
12 KiB
Markdown
217 lines
12 KiB
Markdown
---
|
|
date: 2026-03-04T01:40:21+01:00
|
|
git_commit: a55174b32333d0f46a55d94a50604344d1ba33f6
|
|
branch: master
|
|
topic: "Backpressure for Agentic Coding"
|
|
tags: [research, backpressure, agentic-coding, quality, tooling, hooks, static-analysis, archunit]
|
|
status: complete
|
|
---
|
|
|
|
# Research: Backpressure for Agentic Coding
|
|
|
|
## Research Question
|
|
|
|
What tools, methodologies, and patterns exist for implementing backpressure in agentic coding workflows? Which are applicable to the fete tech stack (Java 25, Spring Boot 3.5, Maven, Vue 3, TypeScript, Vitest)?
|
|
|
|
## Summary
|
|
|
|
Backpressure in agentic coding means: **automated feedback mechanisms that reject wrong output deterministically**, forcing the agent to self-correct before a human ever sees the result. The concept is borrowed from distributed systems (reactive streams, flow control) and applied to AI-assisted development.
|
|
|
|
The key insight from the literature: **90% deterministic, 10% agentic.** Encode constraints in the type system, linting rules, architecture tests, and test suites — not in prose instructions. The agent runs verification on its own output, sees failures, and fixes itself. Humans review only code that has already passed all automated gates.
|
|
|
|
### Core Sources
|
|
|
|
| Source | Author | Key Contribution |
|
|
|--------|--------|-----------------|
|
|
| [Don't waste your back pressure](https://ghuntley.com/pressure/) | Geoffrey Huntley | Coined "backpressure for agents." Feedback-driven quality, progressive delegation. |
|
|
| [If you don't engineer backpressure, you'll get slopped](https://jw.hn/engineering-backpressure) | JW | Verification hierarchy: types → linting → tests → agentic review. 90/10 rule. |
|
|
| [Context-Efficient Backpressure for Coding Agents](https://www.hlyr.dev/blog/context-efficient-backpressure) | HumanLayer | Output filtering, fail-fast, context window preservation. |
|
|
| [Claude Code Hooks Reference](https://code.claude.com/docs/en/hooks) | Anthropic | PostToolUse hooks for automated feedback after file edits. |
|
|
| [ArchUnit](https://www.archunit.org/) | TNG Technology Consulting | Architecture rules as unit tests. Hexagonal architecture enforcement. |
|
|
|
|
## Detailed Findings
|
|
|
|
### 1. The Backpressure Concept
|
|
|
|
In distributed systems, backpressure prevents upstream producers from overwhelming downstream consumers. Applied to agentic coding:
|
|
|
|
- **Producer:** The AI agent generating code
|
|
- **Consumer:** The quality gates (compiler, linter, tests, architecture rules)
|
|
- **Backpressure:** Automated rejection of output that doesn't pass gates
|
|
|
|
Geoffrey Huntley: *"If you aren't capturing your back-pressure then you are failing as a software engineer."*
|
|
|
|
The paradigm shift: instead of telling the agent what to do (prompt engineering), **engineer an environment where wrong outputs get rejected automatically** (backpressure engineering).
|
|
|
|
### 2. The Verification Hierarchy
|
|
|
|
JW's article establishes a strict ordering — deterministic first, agentic last:
|
|
|
|
```
|
|
Layer 1: Type System (hardest constraint, compile-time)
|
|
Layer 2: Static Analysis (linting rules, pattern enforcement)
|
|
Layer 3: Architecture Tests (dependency rules, layer violations)
|
|
Layer 4: Unit/Integration Tests (behavioral correctness)
|
|
Layer 5: Agentic Review (judgment calls — only after 1-4 pass)
|
|
```
|
|
|
|
**Critical rule:** If a constraint can be checked deterministically, it MUST be checked deterministically. Relying on agentic review for things a linter could catch is "building on sand."
|
|
|
|
**Context efficiency:** Don't dump rules into CLAUDE.md that could be expressed as type constraints, lint rules, or tests. Reserve documentation for architectural intent and domain knowledge that genuinely requires natural language.
|
|
|
|
### 3. Context-Efficient Output
|
|
|
|
HumanLayer's research on context window management for coding agents:
|
|
|
|
- **On success:** Show only `✓` — don't waste tokens on 200 lines of passing test output
|
|
- **On failure:** Show the full error — the agent needs the details to self-correct
|
|
- **Fail-fast:** Enable `--bail` / `-x` / `-failfast` — one failure at a time prevents context-switching between multiple bugs
|
|
- **Filter output:** Strip generic stack frames, timing info, and irrelevant details
|
|
|
|
**Anti-pattern:** Piping output to `/dev/null` or using `head -n 50` — this hides information the agent might need and can force repeated test runs.
|
|
|
|
### 4. Claude Code Hooks
|
|
|
|
Hooks are shell commands that execute automatically at specific points in Claude Code's lifecycle:
|
|
|
|
| Event | Trigger | Use Case |
|
|
|-------|---------|----------|
|
|
| `PreToolUse` | Before a tool runs | Block dangerous operations |
|
|
| `PostToolUse` | After a tool completes | Run compile/lint/test checks |
|
|
| `Stop` | Agent finishes response | Final validation |
|
|
| `UserPromptSubmit` | User sends a prompt | Inject context |
|
|
| `SessionStart` | Session begins | Setup checks |
|
|
|
|
**PostToolUse** is the primary backpressure mechanism: after every file edit, run deterministic checks and feed the result back to the agent.
|
|
|
|
**Configuration:** `.claude/settings.json` (project-level, committed) or `.claude/settings.local.json` (personal, gitignored).
|
|
|
|
**Hook format example:**
|
|
|
|
```json
|
|
{
|
|
"hooks": {
|
|
"PostToolUse": [
|
|
{
|
|
"matcher": "Edit:*.java",
|
|
"hooks": [
|
|
{
|
|
"type": "command",
|
|
"command": "cd backend && ./mvnw compile -q 2>&1 || true"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
The hook output is fed back to the agent as context, enabling self-correction in the same conversation turn.
|
|
|
|
### 5. Applicable Tools for fete's Tech Stack
|
|
|
|
#### 5.1 Java / Maven Backend
|
|
|
|
**Checkstyle** (coding conventions)
|
|
- Maven plugin: `maven-checkstyle-plugin`
|
|
- Enforces formatting, naming, imports, Javadoc rules
|
|
- Rulesets: Google Style (most widely adopted), Sun Style (legacy)
|
|
- Fails build on violation when configured with `<failOnViolation>true</failOnViolation>`
|
|
- Actively maintained, open source (LGPL-2.1)
|
|
|
|
**SpotBugs** (bug detection)
|
|
- Maven plugin: `spotbugs-maven-plugin`
|
|
- Successor to FindBugs — finds null pointer dereferences, infinite loops, resource leaks, concurrency bugs
|
|
- Runs bytecode analysis (requires compilation first)
|
|
- Configurable effort/threshold levels
|
|
- Actively maintained, open source (LGPL-2.1)
|
|
|
|
**Error Prone** (compile-time bug detection)
|
|
- Google's javac plugin — catches errors during compilation
|
|
- Tighter feedback loop than SpotBugs (compile-time vs. post-compile)
|
|
- Requires `maven-compiler-plugin` configuration with annotation processor
|
|
- More invasive setup, Java version compatibility can lag
|
|
- Actively maintained, open source (Apache-2.0)
|
|
|
|
**ArchUnit** (architecture enforcement)
|
|
- Library for writing architecture rules as JUnit tests
|
|
- Built-in support for onion/hexagonal architecture via `onionArchitecture()`
|
|
- Dedicated hexagonal ruleset: [archunit-hexagonal](https://github.com/whiskeysierra/archunit-hexagonal)
|
|
- Rules: "domain must not depend on adapters", "ports are interfaces", "no Spring annotations in domain"
|
|
- Fails as a normal test — agent sees the failure and can fix it
|
|
- Actively maintained, open source (Apache-2.0)
|
|
|
|
#### 5.2 Vue 3 / TypeScript Frontend
|
|
|
|
**TypeScript strict mode** (already configured)
|
|
- `strict: true` via `@vue/tsconfig`
|
|
- `noUncheckedIndexedAccess: true` (already in `tsconfig.app.json`)
|
|
- `vue-tsc --build` for type-checking (already in `package.json` as `type-check`)
|
|
|
|
**ESLint + oxlint** (already configured)
|
|
- ESLint with `@vue/eslint-config-typescript` (recommended rules)
|
|
- oxlint as fast pre-pass (Rust-based, handles simple rules)
|
|
- Custom ESLint rules can encode repeated agent mistakes
|
|
|
|
**Vitest** (already configured)
|
|
- `--bail` flag available for fail-fast behavior
|
|
- `--reporter=verbose` for detailed output on failure
|
|
|
|
### 6. Current State Analysis (fete project)
|
|
|
|
| Layer | Backend | Frontend |
|
|
|-------|---------|----------|
|
|
| Type System | Java 25 (strong, but no extra strictness configured) | TypeScript strict + `noUncheckedIndexedAccess` ✓ |
|
|
| Static Analysis | **Nothing configured** | ESLint + oxlint + Prettier ✓ |
|
|
| Architecture Tests | **Nothing configured** | N/A (flat structure) |
|
|
| Unit Tests | JUnit 5 via `./mvnw test` ✓ | Vitest via `npm run test:unit` ✓ |
|
|
| Claude Code Hooks | **Not configured** | **Not configured** |
|
|
| Fail-fast | **Not configured** | **Not configured** |
|
|
|
|
**Gaps:** The backend has zero static analysis or architecture enforcement. Claude Code hooks don't exist yet. Neither side has fail-fast configured.
|
|
|
|
### 7. Evaluation: What to Implement
|
|
|
|
| Measure | Effort | Impact | Privacy OK | Maintained | Recommendation |
|
|
|---------|--------|--------|------------|------------|----------------|
|
|
| Claude Code Hooks (PostToolUse) | Low | High | Yes (local) | N/A (config) | **Immediate** |
|
|
| Fail-fast + output filtering | Low | Medium | Yes (local) | N/A (config) | **Immediate** |
|
|
| Checkstyle Maven plugin | Low | Medium | Yes (no network) | Yes (LGPL) | **Yes** |
|
|
| SpotBugs Maven plugin | Low | Medium | Yes (no network) | Yes (LGPL) | **Yes** |
|
|
| ArchUnit hexagonal tests | Medium | High | Yes (no network) | Yes (Apache) | **Yes** |
|
|
| Error Prone | Medium | Medium | Yes (no network) | Yes (Apache) | **Defer** — overlaps with SpotBugs, more invasive setup, Java 25 compatibility uncertain |
|
|
| Custom ESLint rules | Low | Low-Medium | Yes (local) | N/A (project rules) | **As needed** — add rules when recurring agent mistakes are observed |
|
|
| MCP LSP Server | High | Medium | Yes (local) | Varies | **Defer** — experimental, high setup cost, unclear benefit vs. hooks |
|
|
|
|
### 8. Tool Compatibility Notes
|
|
|
|
**Java 25 compatibility:**
|
|
- Checkstyle: Confirmed support for Java 21+, Java 25 should work (runs on source, not bytecode)
|
|
- SpotBugs: Bytecode analysis — needs ASM version that supports Java 25 classfiles. Latest SpotBugs (4.9.x) supports up to Java 24; Java 25 support may require a newer release. **Verify before adopting.**
|
|
- ArchUnit: Runs via JUnit, analyzes compiled classes. Similar ASM dependency concern as SpotBugs. **Verify before adopting.**
|
|
- Error Prone: Tightly coupled to javac internals. Java 25 compatibility typically lags. **Higher risk.**
|
|
|
|
**Privacy compliance:** All recommended tools are offline-only. None phone home, none require external services. All are open source with permissive or copyleft licenses compatible with GPL.
|
|
|
|
## Decisions Required
|
|
|
|
| # | Decision | Options | Recommendation |
|
|
|---|----------|---------|----------------|
|
|
| 1 | Hooks in which settings file? | `.claude/settings.json` (project, committed) vs. `.claude/settings.local.json` (personal, gitignored) | **Project-level** — every agent user benefits |
|
|
| 2 | Checkstyle ruleset | Google Style vs. Sun Style vs. custom | **Google Style** — most widely adopted, well-documented |
|
|
| 3 | Include Error Prone in plan? | Yes (more coverage) vs. defer (simpler, overlap with SpotBugs) | **Defer** — Java 25 compatibility uncertain, overlaps with SpotBugs |
|
|
|
|
## References
|
|
|
|
- Geoffrey Huntley: [Don't waste your back pressure](https://ghuntley.com/pressure/)
|
|
- JW: [If you don't engineer backpressure, you'll get slopped](https://jw.hn/engineering-backpressure)
|
|
- HumanLayer: [Context-Efficient Backpressure for Coding Agents](https://www.hlyr.dev/blog/context-efficient-backpressure)
|
|
- Anthropic: [Claude Code Hooks Reference](https://code.claude.com/docs/en/hooks)
|
|
- Anthropic: [2026 Agentic Coding Trends Report](https://resources.anthropic.com/hubfs/2026%20Agentic%20Coding%20Trends%20Report.pdf)
|
|
- ArchUnit: [User Guide](https://www.archunit.org/userguide/html/000_Index.html)
|
|
- ArchUnit Hexagonal: [GitHub](https://github.com/whiskeysierra/archunit-hexagonal)
|
|
- SpotBugs: [Documentation](https://spotbugs.github.io/)
|
|
- Checkstyle: [Documentation](https://checkstyle.sourceforge.io/)
|
|
- Claude Code Hooks Guide: [Luiz Tanure](https://www.letanure.dev/blog/2025-08-06--claude-code-part-8-hooks-automated-quality-checks)
|
|
- lsp-mcp: [GitHub](https://github.com/jonrad/lsp-mcp)
|