Skip to content

np-critic-acceptance (audit-surface module)

Module file, not a spawnable agent. Per the Single-Critic Revision (ADR-0010 §2026-05-05) this file carries module: true in its frontmatter. It is loaded via Read by the parent np-critic spawn as the Acceptance audit-surface — lib/agents.cjs::loadAgent rejects it for spawning, and loop-audit-tool-use --agent np-critic-acceptance is also rejected.

AttributeValue
Frontmatter module:true
Tier metadatasonnet (legacy — informational only)
Loaded bynp-critic as one of three audit-surface modules
Definesthe Acceptance category set, per-criterion verdict shapes, and stop conditions

Role

The Acceptance audit surface verifies that each success_criterion listed in the task plan is observably met by the executor's diff. It is the most expensive of the three audit axes because acceptance verification reads the spec, the diff, the tests, and the verify output together. The parent np-critic agent applies this audit surface as part of its merged JSON, including the per-criterion verdict shape that the routing engine promotes into unmet-criterion or information-missing findings.

Audit surface

Per success_criterion verdict

For every entry in the task plan's <success_criteria> block, the critic emits one of:

VerdictMeaningRouting
SatisfiedThe diff demonstrates it; cite test name, grep result, or artefact pathnone — passes
UnsatisfiedThe diff doesn't demonstrate it; cite what is missing→ Executor / Build-Fixer
Information-MissingCriterion references behaviour the diff cannot establish without external info→ Researcher-Schwarm

Cross-cutting checks

CheckDetail
Locked-decision conformanceThe diff doesn't violate any locked decision in M<NNN>-CONTEXT.md
Scope creepThe diff doesn't edit files outside files_modified
Stuck detectionIf round = loop.maxRounds with no progress, flag stuck-detected

Output schema

The Acceptance module does not produce its own output — its criteria[] and findings[] appear inside the parent np-critic's merged JSON (np-critic output schema).

Acceptance-axis category enum:

unmet-criterion, locked-decision-violation, scope-creep, information-missing, question-to-user, infrastructure-mismatch, stuck-detected.

Each routes per the findings routing table:

CategoryRoutes to
unmet-criterion / scope-creepExecutor / Build-Fixer
information-missingResearcher-Schwarm
question-to-useraskuser (Temporal-style signal-wait)
locked-decision-violation / infrastructure-mismatchnp-plan-checker
stuck-detectedloop terminates → stuck state

Completeness rules bound

RuleWhy this critic enforces it
Rule 5 — Aim to genuinely impress"Mostly satisfied" is not a category. Either Satisfied with cited evidence, or Unsatisfied.
Rule 6 — Never offer to "table this for later"A criterion the diff doesn't meet is a finding now, not a follow-up
Rule 11 — Ship the complete thingEvery criterion gets a verdict — no silent skips
Rule 12 — Boil the ocean"Information missing" routes to Researcher, not "passes with reservations"

Routing-engine contract

lib/nubosloop.cjs::_normalizeFinding consumes exactly five fields per finding: category, severity, file, line, remediation. Every other field (id, criterion_id, question_to_user, etc.) is preserved on the merged finding under raw; routing is driven only by the five contract fields.

Note on dual-shape outputs. The orchestrator's mergeCriticOutputs promotes any criterion with verdict Unsatisfied to an unmet-criterion finding, and any Information-Missing to an information-missing finding (via lib/nubosloop.cjs::_criteriaAsFindings). Still emit findings explicitly when you want to add file, line, or remediation details; auto-promotion is a safety net rather than a substitute for them. Identical findings are deduplicated by fingerprint.

Stop conditions

ConditionBehaviour
Task plan has no <success_criteria> blockSingle unmet-criterion finding pointing at the gap; routes to plan-checker
Critic timeout exhaustedEmit collected criteria + findings + verdict: issues_found

Source

agents/np-critic-acceptance.md in the source tree.