9.3 KiB
adr_number, title, status_history, tier, authors, superseded_by, related_adrs, acceptance
| adr_number | title | status_history | tier | authors | superseded_by | related_adrs | acceptance | ||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 13 | Validation Abstraction |
|
2 |
|
null |
|
|
Context
Plans must verify that their work meets quality, correctness, and compliance criteria before changes are applied to real project resources. This verification must be structured (machine-parseable pass/fail results, not free-text), composable (multiple validations can run in parallel), and gating (required validations block Apply if they fail). The system needs a validation mechanism that integrates with the existing tool infrastructure rather than being a separate system.
Decision Drivers
- Verification results must be machine-parseable (structured pass/fail), not free-text LLM interpretation
- Validations must integrate with the existing tool infrastructure rather than creating a parallel system
- Required validations must gate the Apply phase — failed checks block changes from reaching real resources
- Read-only enforcement is essential for safe parallel execution and retry without side effects
- Validation attachment must support multiple scoping levels (direct, project, plan) for fine-grained control
- Existing tools should be reusable as validations via wrapping, avoiding reimplementation
Decision
A Validation is a specialized subtype of Tool designed to verify work. It extends Tool via standard class inheritance, adding mode (required/informational), a structured JSON return format ({ "passed": bool, "message": str, "data": object }), and strict read-only enforcement. Validations share the tool namespace, reuse the entire tool infrastructure, and are composable into skills and actor graphs.
Design
Relationship to Tool
Validations inherit all Tool fields: name, description, source, input_schema, output_schema, capability, resource_slots, lifecycle hooks, code, mcp_server/mcp_tool_name, timeout, idempotent.
Additional validation-specific fields: mode, structured return format enforcement, read-only enforcement, attachment scoping, attachment ULID, wraps (for tool wrapping), and transform.
Validations share the same namespace as tools. They are a superset (validation IS-A tool). Unified management via agents tool and agents validation commands.
Validation Mode
Required (mode: required): Must pass for execution to proceed to Apply. On failure: fix-then-revalidate loop with retry limit (default: 3), then strategy revision, then escalation to user.
Informational (mode: informational): Recorded but does not block execution. Useful for advisory checks and gradual adoption. Mode is set at registration time and cannot be overridden per-attachment.
Structured Return Format
{
"passed": true,
"message": "All 247 tests passed, 94% coverage",
"data": {
"tests_run": 247,
"tests_passed": 247,
"coverage_percent": 94.2
}
}
passed (boolean) is required. message (string) and data (object) are optional. Malformed returns are treated as errors with passed: false.
Read-Only Enforcement
Validations are always read-only: writes: false, checkpointable: false, read_only: true. Enforced at registration time and at runtime. This guarantee enables safe parallelization, speculative validation, and retry without side-effect concerns.
Attachment Scoping
Validations are attached to resources with three scoping levels:
- Direct attachment: Always active for that resource, regardless of plan or project.
- Project-scoped attachment: Active only when the resource is accessed through the specified project.
- Plan-scoped attachment: Active only for the specified plan.
Attachment resolution: collect all applicable attachments (direct → project → plan), union them, most-specific scope wins for identical arguments. Each attachment gets a system-assigned ULID, enabling the same validation to be attached multiple times with different arguments.
Validation Lifecycle in Plan Execution
Strategize: Not executed, but the strategy actor is aware of applicable validations and plans accordingly.
Execute: Final step of execution. Collect all applicable validations → execute in parallel (safe due to read-only) → process results. All required pass → proceed to Apply. Any required fail → fix-then-revalidate loop.
Apply: Not run. The sandbox model ensures all verification happens during Execute. Apply is the point of no return.
Required Validation Failure Handling
- Diagnose (examine
messageanddata) - Self-fix attempt by the execution actor
- Re-validation
- Retry limit reached (default: 3)
- Request strategy revision (revert to Strategize)
- Escalate to user
- Terminal failure if still unresolved
Tool Wrapping
Validations can wrap existing tools using wraps and transform fields. The wraps field references an existing tool; the transform function interprets its output as pass/fail. Wrapped tools inherit input_schema, resource_slots, and timeout from the wrapped tool. The transform is a pure data transformation that receives tool_output and returns the structured validation result. Multiple validations can wrap the same tool with different transforms.
Validations in Actor Graphs and Skills
Validations can appear as tool nodes in actor graphs, with return values available to downstream nodes. Being in a skill makes a validation callable; attachment determines whether it acts as a mandatory gate.
Constraints
- Validations must always be read-only. Registration of a validation with
writes: trueis rejected. - The structured return format is enforced.
passed(boolean) is required in every return value. - Validation mode (
required/informational) is set at registration and cannot be overridden per-attachment. - Validations run during Execute, never during Apply.
- Required validation failures must follow the fix-then-revalidate → strategy revision → escalation sequence. No bypassing.
- Wrapped tool transforms must be pure data transformations with no side effects.
Consequences
Positive
- Extending Tool rather than creating a separate system means validations benefit from the entire tool infrastructure — lifecycle, adapters, resource bindings, skills, actor graphs.
- Read-only enforcement enables safe parallel execution of all validations.
- Attachment scoping provides fine-grained control over which validations apply in which contexts.
- The structured return format enables machine-driven fix-then-revalidate loops.
- Tool wrapping enables reusing existing tools as validations without reimplementation.
Negative
- The IS-A relationship with Tool means validation-specific behavior (mode, gating) must be carefully distinguished from general tool behavior in the execution engine.
- Attachment scoping with three levels and system-assigned ULIDs adds management complexity.
- The fix-then-revalidate loop with strategy revision escalation is a complex state machine.
Risks
- Required validations that are flaky (intermittent failures unrelated to code quality) could block plans and erode trust in the system.
- The retry limit is a blunt instrument — some failures need more attempts while others should fail immediately.
- Informational validations may be ignored entirely if there is no mechanism to surface their results prominently.
Alternatives Considered
Separate validation system (not extending Tool) — Would duplicate the lifecycle, adapter, registry, and namespace infrastructure. The specification explicitly chose inheritance to avoid this duplication.
Validations only in Apply phase — Would require running validations on real (non-sandboxed) resources, risking failures after changes are partially committed. The sandbox model requires validation during Execute.
Compliance
- Read-only enforcement tests: Tests verify that validation registration rejects
writes: trueand that runtime execution blocks any write attempts. - Structured return tests: Tests verify that well-formed, malformed, and missing return values are handled correctly.
- Attachment scoping tests: Tests verify correct resolution across direct, project-scoped, and plan-scoped attachments.
- Failure handling tests: BDD scenarios exercise the full failure sequence: fix → revalidate → retry limit → strategy revision → escalation → terminal failure.
- Wrapping tests: Tests verify that wrapped tool transforms correctly interpret tool output and that inheritance rules are applied.