Runs a project-agnostic autonomous Implement-then-Validate-then-Test compliance loop on any git worktree. Detects the project's test framework (vitest, jest, mocha, pytest, unittest, go-test, cargo-test, rspec, phpunit, bats, or other) and iterates until the implementation satisfies its specification, recording convergence metrics to the manifest. Use when given an implementation task that must ship verified: the IVT loop is the autonomous compliance layer enforced before any release or PR. T...
Scanned 5/28/2026
Install via CLI
openskills install kryptobaseddev/cleo---
name: ct-ivt-looper
description: "Runs a project-agnostic autonomous Implement-then-Validate-then-Test compliance loop on any git worktree. Detects the project's test framework (vitest, jest, mocha, pytest, unittest, go-test, cargo-test, rspec, phpunit, bats, or other) and iterates until the implementation satisfies its specification, recording convergence metrics to the manifest. Use when given an implementation task that must ship verified: the IVT loop is the autonomous compliance layer enforced before any release or PR. Triggers on phrases like 'implement and verify', 'run the IVT loop', 'ship this task', 'complete implementation with tests', 'verify against spec', or any implementation task with acceptance criteria. Works in any git worktree regardless of language or framework, never hardcoded to one project's tooling."
protocol: testing
loomStage: testing
adrRefs:
- ADR-051
- ADR-061
---
# IVT Looper
## Overview
Runs an autonomous Implement-then-Validate-then-Test loop against any git worktree, detects the test framework in use, and iterates until the implementation converges on its specification. This skill is the autonomous compliance layer: no task ships, no release runs, and no PR opens until the loop has recorded a converged result to the manifest.
## Core Principle
> The loop converges on the spec, not on 'tests pass'. Passing tests that don't cover the spec is a failure.
## Immutable Constraints
| ID | Rule | Enforcement |
|----|------|-------------|
| IVT-001 | Test framework MUST be detected or declared before the loop starts. | `validateTestingProtocol` rejects entries without a `framework`; deducts 20 from score. |
| IVT-002 | Loop MUST cap iterations at `MAX_ITERATIONS` (default 5). | Hard counter in the loop; unreachable convergence forces HITL escalation. |
| IVT-003 | Every MUST requirement in the spec MUST map to at least one passing test. | Spec-to-test traceability matrix; gaps block convergence. |
| IVT-004 | Final manifest entry MUST record `framework`, `testsRun`, `testsPassed`, `testsFailed`, `ivtLoopConverged`, `ivtLoopIterations`. | `validateTestingProtocol` requires these fields; `ivtLoopConverged: false` fails validation. |
| IVT-005 | Framework detection MUST NOT be hardcoded to one project's tooling. | Detection walks the project tree; no vitest/jest-only code paths. |
| IVT-006 | Loop MUST NOT run on the main branch. | Check `git branch --show-current`; stop if on `main`/`master`/`trunk`. |
| IVT-007 | Non-convergence after `MAX_ITERATIONS` MUST escalate to HITL (exit code 65). | Agent stops, writes manifest with `ivtLoopConverged: false`, exits. |
| IVT-008 | Final manifest entry MUST set `agent_type: "testing"`. | Validator rejects any other value. |
## The IVT Loop
```
load_spec(task_id) # read acceptance criteria from canon
detect_framework(worktree) # see references/frameworks.md
branch_check() # abort if on main/master/trunk
iteration = 0
while iteration < MAX_ITERATIONS: # IVT-002
iteration += 1
# ----- I : Implement -----
apply_patch(current_diff) # patch generated by the implementer
ensure_provenance_tags(new_code) # IMPL-003 tags on new functions
# ----- V : Validate -----
lint_result = run_project_linter()
type_result = run_type_checker() # tsc / mypy / go vet / rustc
if lint_result.failed or type_result.failed:
regenerate_fix_for(lint_result, type_result)
continue # back to top, same iteration count
# ----- T : Test -----
test_result = run_framework_tests() # framework-specific command
trace = spec_to_test_trace(spec) # IVT-003: every MUST has a test
if test_result.all_passed and trace.complete:
write_manifest(
framework=framework,
iterations=iteration,
converged=True,
agent_type="testing",
)
return CONVERGED # exit loop, exit skill with code 0
# ----- Analyze and regenerate fix -----
failure = diagnose(test_result, trace)
current_diff = regenerate_fix_for(failure)
# MAX_ITERATIONS reached without convergence
write_manifest(
framework=framework,
iterations=MAX_ITERATIONS,
converged=False,
agent_type="testing",
)
escalate_to_hitl() # IVT-007: exit code 65
```
The loop is a *single* stage from the lifecycle's point of view. Implement, Validate, and Test are not three separate tasks — they are three phases of one autonomous run that either converges or escalates.
## Out of Scope (T9675)
`ct-ivt-looper` operates on the **`testing`** LOOM lifecycle stage (stage 8). It performs the **dynamic** Implement-then-Validate-then-Test loop with framework detection and iterate-until-green convergence semantics.
This skill does NOT:
- Audit static artifacts for schema/compliance/RFC-2119 keyword usage, ADR-document structure, or JSON Schema conformance. Those belong to **`ct-validator`** at the `validation` stage (stage 7). When the question is "is this document/manifest well-formed?" rather than "does this code converge on its spec?", chain to `ct-validator` rather than expanding scope here.
- Promote a green loop to release. Release sequencing belongs to **`ct-release-orchestrator`** at stage 9.
### Chain handoffs
| Direction | When | Handoff |
|---|---|---|
| `ct-ivt-looper` → `ct-validator` | Loop converged; need to audit the resulting artifacts (e.g. final manifest, spec back-references) against schema/compliance | Emit the convergence manifest entry, then dispatch the `validation` stage |
| `ct-validator` → `ct-ivt-looper` | Spec is valid but implementation needs dynamic verification | Receive a dispatch from the `validation` stage; iterate the IVT loop on the worktree |
Governance: see **ADR-051** (programmatic gate integrity) which defines the evidence atoms (`tool:test`, `test-run:<json>`) the loop emits and that downstream `cleo verify --gate testsPassed` re-validates, and **ADR-061** (project-agnostic verify tools) which defines the canonical tool-resolution layer.
## Framework Detection
Framework detection is project-agnostic: the skill walks the worktree, inspects config files, and selects the correct test command. No language or framework is special-cased above another. The full detection table lives in [references/frameworks.md](references/frameworks.md). In summary: detection reads the project manifest (`package.json`, `pyproject.toml`, `Cargo.toml`, `go.mod`, `Gemfile`, `composer.json`, or `.cleo/project-context.json#testing.command`) and selects one of: `vitest`, `jest`, `mocha`, `pytest`, `unittest`, `go-test`, `cargo-test`, `rspec`, `phpunit`, `bats`, `other`.
## Convergence Criteria
The loop has converged when **all** of the following hold:
- Every MUST requirement in the task's linked specification has at least one passing test (spec-to-test traceability complete).
- `testsFailed == 0`, `testsRun > 0`, and `testsPassed == testsRun`.
- Project linter reports zero errors (warnings are allowed).
- Type checker reports zero errors.
- CI-equivalent local commands return zero (e.g., `pnpm run build`, `cargo build`, `go build ./...`).
- No new runtime errors were observed during the test run.
A loop that makes tests pass by deleting assertions, narrowing scope, or mocking the thing under test is **not** converged — that is a spec violation dressed up as a green run. See [references/loop-anatomy.md](references/loop-anatomy.md) for worked examples.
## Branch Discipline
Before iteration 1, the skill MUST verify the current branch:
```bash
branch=$(git branch --show-current)
if [[ "$branch" == "main" || "$branch" == "master" || "$branch" == "trunk" ]]; then
echo "Refusing to run IVT loop on protected branch: $branch"
exit 65 # HANDOFF_REQUIRED: ask HITL for a feature branch
fi
```
The loop is destructive in the sense that it rewrites code on failed iterations. It MUST run on a feature branch or worktree. If the user invoked it on a protected branch, stop and request a feature branch.
## Escalation on Non-Convergence
When the loop exhausts `MAX_ITERATIONS` without converging, the skill MUST:
1. Write the manifest entry with `ivtLoopConverged: false` and the iteration count.
2. Record the last diagnostic output in `key_findings`.
3. Exit with code 65 (`HANDOFF_REQUIRED`).
4. Leave the worktree in its last state — do **not** revert.
The human reviewer picks up the worktree, reads the diagnostics, and either raises the iteration cap, rewrites the spec, or manually corrects the implementation before rerunning the skill. The full escalation handoff protocol is in [references/escalation.md](references/escalation.md).
## Integration
Record the loop outcome through `cleo check protocol`:
```bash
# Success case: loop converged on iteration 3.
cleo check protocol \
--protocolType testing \
--framework vitest \
--testsRun 142 \
--testsPassed 142 \
--testsFailed 0 \
--ivtLoopConverged true \
--ivtLoopIterations 3
# Failure case: loop exhausted iterations, HITL escalation.
cleo check protocol \
--protocolType testing \
--framework pytest \
--testsRun 87 \
--testsPassed 84 \
--testsFailed 3 \
--ivtLoopConverged false \
--ivtLoopIterations 5
```
Exit code 0 = loop converged and protocol is valid. Exit code 65 = `HANDOFF_REQUIRED` (non-convergence).
This skill MUST also chain a validation check against the spec before its own testing check:
```bash
cleo check protocol \
--protocolType validation \
--specMatchConfirmed true \
--testSuitePassed true \
--protocolComplianceChecked true
```
## Anti-Patterns
| Pattern | Problem | Solution |
|---------|---------|----------|
| Hardcoding vitest or jest | Violates IVT-005; breaks on any non-JS project | Walk the worktree and pick the framework per project |
| Running the loop on main/master | Violates IVT-006; pollutes shared branch | Check `git branch --show-current` and refuse protected branches |
| No iteration cap | Infinite loop on unreachable convergence; context burn | Enforce `MAX_ITERATIONS` (default 5); escalate to HITL on exhaustion |
| Deleting assertions to force green | Tests pass but the spec is not met | The skill requires spec-to-test traceability; gaps block convergence |
| Skipping the validation phase | Lint or type errors slip through | The loop MUST run lint and type check before the test phase every iteration |
| Treating testing as "just run the tests" | Misses the loop; one-shot runs are not compliant | Testing is a loop, not a single call; record `ivtLoopIterations` |
| Exiting without writing the manifest | Downstream skills cannot see the outcome | Always write the manifest entry — converged or not — before exiting |
| Reverting the worktree on escalation | Destroys diagnostic evidence | Leave the failed state; the human reviewer needs it |
## Critical Rules Summary
1. Detect the test framework from the worktree before iterating; never hardcode.
2. Cap iterations at `MAX_ITERATIONS` (default 5); escalate on exhaustion.
3. Every MUST in the spec MUST map to a passing test before declaring convergence.
4. Each iteration runs all three phases: Implement, Validate, Test.
5. Never run on `main`, `master`, or `trunk` — stop and request a feature branch.
6. Record `framework`, `testsRun`, `testsPassed`, `testsFailed`, `ivtLoopConverged`, `ivtLoopIterations` in the manifest.
7. On non-convergence, exit 65 and leave the worktree untouched.
8. Validate every run via `cleo check protocol --protocolType testing`.
## See also / References
This skill binds to the **testing** LOOM lifecycle stage. Governing ADRs:
- [ADR-051 — programmatic gate integrity](../../../../.cleo/adrs/ADR-051-programmatic-gate-integrity.md) — defines the evidence atoms (`tool:test`, `test-run:<json>`) that the IVT loop emits and that downstream `cleo verify --gate testsPassed` re-validates.
- [ADR-061 — project-agnostic verify tools](../../../../.cleo/adrs/ADR-061-project-agnostic-verify-tools.md) — defines the canonical tool-resolution layer (`test`, `build`, `lint`, `typecheck`) that the loop walks for framework-agnostic execution.
LOOM coverage matrix: [docs/skills/loom-coverage-matrix.md](../../../../docs/skills/loom-coverage-matrix.md).
No comments yet. Be the first to comment!