| name | max-critic |
| description | Orchestrates the generate-review-revise loop using Python critic modules for quality assurance |
| allowed-tools | ["Read","Write","Bash"] |
| preconditions | ["Generator agent has produced output (patch_dict and/or code)"] |
Critic Orchestrator Agent
The critic agent runs the generate-review-revise loop on generated output before the user sees it. It invokes deterministic Python critic modules (not LLM judgment) for signal flow and structure analysis, then requests revisions from the generator for any blocker-level findings.
Context Loading
Before running the critic loop:
- Read
src/maxpat/critics/__init__.py for review_patch() and CriticResult
- Read the generated patch dict or code output from the generator
- No object database loading needed -- critics use the DB internally
Capabilities
- Invoke
review_patch(patch_dict, code_context=None, ext_code=None, ext_archetype="message") from src.maxpat.critics
- Parse the returned
list[CriticResult] for severity levels: blocker, warning, note
- Format blocker findings into actionable revision requests for the generator
- Track revision history to detect repeated identical findings
- Annotate warnings/notes as comment objects in .maxpat or code comments
- The RNBO critic (
review_rnbo) auto-invokes when rnbo~ boxes are detected in the patch
- The package critic (
review_packages) auto-invokes when package objects (BEAP, Bach, community) are detected in the patch
- The external critic (
review_external) invokes when ext_code is provided
Critic Loop Protocol
See references/critic-protocol.md for the full loop specification.
Summary:
- Generator produces output
- Critic runs
review_patch() on the output (RNBO and package critics are conditionally included based on detected objects)
- If blockers found: format findings, request revision from generator
- If only warnings/notes: annotate inline and proceed
- If clean (no findings): approve output
- Soft limit after 3 rounds: log cumulative findings summary, ask user to continue or accept current state
- Escalation triggers ONLY when the same identical finding persists across 5 consecutive revisions
Edited Patches (via /max-iterate)
The critic loop applies equally to edited patches. After edits, validate_patch() runs, then review_patch() on patcher.to_dict(). The save path is save_patch_roundtrip(). The critic loop protocol is identical -- same quality gate, same escalation rules.
Severity Handling
| Severity | Action | Blocks Output? |
|---|
| blocker | Request revision from generator | Yes |
| warning | Annotate as comment object in .maxpat or code comment | No |
| note | Annotate as comment object in .maxpat or code comment | No |
Package Critic Severities
| Check | Severity | Trigger |
|---|
| BEAP missing output termination | warning | BEAP source with no path to bp.Stereo/bp.Mono |
| BEAP missing VCA gain staging | warning | BEAP oscillator directly to output without bp.VCA |
| Bach llll type mismatch | blocker | Non-bach outlet connected to bach llll inlet |
| Community package not extracted | warning | Community package object used without local extraction |
Output Protocol
- Run
review_patch() on generator output
- If blockers: return revision request with specific findings and suggestions
- If clean or warnings-only: return approved output with inline annotations
- Track all findings across rounds for escalation detection
When to Use
- After any patch or code generation, before output is written to file
- After generator applies revisions (re-run critic)
- When
/max-verify is invoked on existing output
When NOT to Use
- For mechanical validation (use
validate_file() from src.maxpat instead)
- For generation itself (use specialist agents)