Universal test-coverage augmentation bot. Plans missing tests for a target
area, writes them with the repo’s own framework, proves they pass with a
deterministic gate, then runs the cross-family (Claude + GPT) anti-façade
review loop to a test: commit. Modelled on feature-dev + whole-improve-loop’s
verify gate; stack knowledge lives in skills/ (test-coverage, verify-tests,
test-types). Anti-façade is the design center: the metric is meaningful tests
that catch a real regression, NOT coverage %.
dev+239203525cc8 · sandbox-full (worktree: auto).--store-dir <workspace>/.iterion, --merge-into none, target = “pkg/skilllib — frontmatter parser + layered store”, max_passes=3, --max-cost-usd 20 --max-duration 1h (mono claude, forfait). 7m50s wall.finished, gate.converged=true first pass. 2 semantic commits in stride on iterion/run/sonic-blast-fiberglyph-fb91: test(skilllib): lock down ScanFrontmatter parsing edge cases (frontmatter_test.go, 14-case table — the parser previously had ZERO direct test) then test(skilllib): cover store error paths, skip rules, and invariants (store_edge_test.go), +327 test lines. Coverage 78.1%→93.2%, 35 tests, self-reported mutation-verified. Deterministic gate: suite green AND new_test_code=true — the diff-vs-RUN-BASE (reflog) measurement counted the in-stride commits correctly (the exact hole the v2 conversion hardened).iterion validate clean, catalog universality/typing/bundle-consistency green, stub e2e green where wired. NOT yet live-dogfooded in the v2 shape; treat the sections below as describing the RETIRED v1 shape.--store-dir .iterion --merge-into none, no target, no test-type vars
(the last untested path: bot picks BOTH scope and types). Engine binary @356053e8b
(has the tail() fix).shellquote shell-injection
boundary, proc iterion-binary locator, dsl/types enum→keyword String()),
skipped trivial glue + Mongo-bound code (anti-façade), chose unit with
mutation-test framing. act wrote 4 test files; verify gate passed first try;
reviewer_claude approved; reviewer_gpt found a blocker → fix_gpt → FAILED.tail() fix validated LIVE: streak_check evaluated the capped accumulator
twice with NO “unknown function” error — the engine resolves tail() correctly.fix_gpt
(claw openai/gpt-5.5, session: inherit + a multi-package diff) hit a genuine
context_length_exceeded overflow on its first call, and the node-retry then hit a
400 {"detail":"Unsupported content type"} and the retries exhausted → run failed.
Run’s 4 auto-picked tests left in the preserved worktree (unfinished — not repatriated).done (commit e3e0817 on its storage branch). The bot’s scope-auto path is sound.400 {"detail":"Unsupported content
type"} is a TRANSIENT chatgpt-forfait endpoint flake, NOT a compaction bug. In
019ef60f it hit reviewer_gpt on a session: fresh FIRST call (no compaction
possible) and the executor’s node-retry RECOVERED (2nd attempt approved → streak →
commit → done). So run 019ef5d3 only died because the transient 400 coincided with a
real fix_gpt overflow and the ~2 retries exhausted before a clean attempt.function_call_output and shipped dropOrphanedToolResults (commit dadfc49b2) — that
was WRONG (it can’t even run for a session: fresh reviewer) and was reverted.
LESSON: don’t ship a fix to shared LLM-client code on an unreproduced hypothesis;
reviewer_gpt being session: fresh already ruled out compaction. (See
[project_claw_gpt5_context_overflow_fix] memory.)fix_gpt session: inherit overflow
on big multi-package diffs (gpt-5.5-forfait small window) — long-term mitigated by
explore-mode-style read-on-demand (Willy ADR-045). The bot itself is validated across
all 4 paths.--store-dir .iterion (visible in the operator’s studio) --merge-into none.
019ef53b, nova-mosh-prismfox): --var target=pkg/secrets,
NO test-type checkboxes. The bot chose Unit only, explicitly: “operator left
all types unset → I choose”, and excluded the Mongo stores as “integration
territory, out of scope without a harness”, citing the anti-façade doctrine. Targeted
security-relevant pure logic (path-traversal rejection, tenant isolation, OAuth-kind
validation, Codex auth fallback). Converged cross-family → commit 2663ac6 on
iterion/run/nova-mosh-prismfox-d157: 5 test files, 342 insertions, coverage 46.3%→
(~70% on the testable surface). The modest jump is the right signal — it covered only
what’s meaningfully testable instead of writing façade Mongo tests to game the %.019ef54d, wonky-thrash-riffboi):
--var test_unit=true --var test_integration=true --var target=pkg/store. The plan
addressed both types, correctly categorized: Unit = pure in-memory helpers
(IsTerminal, tenant/watched-issue, snapshot-ref); Integration = FilesystemRunStore
crossing the real FS via the repo’s existing tmpStore() helper (CAS status writes,
checkpoint round-trips, event-range reads, PublishInboxEvent) — “matches the house
style of existing store_test.go”. 10 funcs / 58 assertions; coverage 62.7%→70.7%.
Converged cross-family → commit bf775d6 on iterion/run/wonky-thrash-riffboi-b057.git diff HEAD to build the commit. ROOT CAUSE: the
streak_check -> prepare_commit with {_session_id: …} edge carries the session id but
NOT _session_fingerprint, and the fork-safety check at
claude_code.go:1888 requires it. Pre-existing
and shared with feature-dev (same fork pattern), benign (the commit is correct; minor
extra cost re-reading the tree). Optional fix: add
_session_fingerprint: "" to that edge to
restore cheap inheritance (do in a worktree; verify it resolves + same-provider only).git merge them
into a feature branch if you want the pkg/secrets + pkg/store coverage (not auto-merged;
--merge-into none).target).test:
commit. (Surfaced + fixed one engine bug along the way; the GPT half was
briefly blocked by an exhausted OpenAI forfait, resolved by switching Codex
account + iterion resume.)main @ e2cd45c + this work)iterion run bots/test-coverage/main.bot --var target=pkg/log --var
test_unit=true --merge-into none; backends claude_code (opus-4-8) for
plan/act/simplify/reviewer_claude/prepare_commit, claw openai/gpt-5.5 for
reviewer_gpt; sandbox iterion-sandbox-full:edge, worktree: auto,
network open.done. plan → act → simplify → verify gate PASSED
first try (passed=true, new_test_code=true, 537 ms, no repair loop) →
reviewer_claude approved (high, 0 blockers, 7 areas) → [forfait 429,
resumed] → reviewer_gpt approved (high, 0 blockers, family=gpt) →
streak_check stop (cross-family double approval) → prepare_commit picked
only pkg/log/log_test.go (correctly excluded an unrelated catalog
regen line) → commit_changes → done. Commit aac2ab2 on storage branch
iterion/run/019ef505… (--merge-into none, main untouched); message
test(log): cover Truncate rune-boundary and writer levels (+386 lines).
Cost ≈ $2.9 total, ~13 min wall across the initial run + resume.pkg/log
(pkg/log/log_test.go +399 lines) — 51 assertions, 38 table cases, targeting
edge/error paths (nil-receiver safety, JSON marshal-failure drops the line,
UTF-8-safe byte cut, level resolution precedence, emoji gating). Coverage
58.1% → 99.2%. Repatriated to the main tree and independently verified
(build + go test + vet + gofmt all green, 99.2%).act: “disabling the
safeByteCut walk-back made TestSafeByteCut/TestTruncate/TestBlockPreview
fail … restoring it passed. Proves the tests catch a real regression.” The
skill’s mutation-test doctrine reached the implementer concretely.verify_run_tests gate passed first try
(passed=true, new_test_code=true, 537 ms) — no repair loop needed.extra_test_kinds/checkbox substitution rendered correctly in prompts
(unit: true …); empty selection would have let the bot choose.plan
node’s result text, so the node “succeeded” with a non-plan and act
inherited a poisoned session and hung. Fixed: isTransientAPIErrorResult
in pkg/backend/delegate/claude_code.go
re-types a transient API-error-as-result (429/5xx/529/connectivity, short +
API Error: prefix) to ErrTransient so the executor retries; 4xx
client/auth errors still surface. 21-case unit test
(claude_code_apierror_test.go).devbox run fails
(~/.cache/devbox unwritable); the agent adapted to plain go test, and
skills/verify-tests.md now documents the XDG_CACHE_HOME=/tmp retry →
direct-toolchain fallback.scope_notes).
Harmless — prepare_commit excludes non-test files by design.429 usage limit reached) is a hard cap a retry can’t
clear — switching the Codex account (or setting OPENAI_API_KEY) + iterion
resume --run-id … --file … --force picks up the new creds (the resumed
sandbox re-mounts ~/.codex) and closes the loop from the checkpoint.prepare_commit session-fork is dropped (“parent session
has no recorded provider fingerprint”) and it starts fresh — harmless, it
re-reads git diff HEAD to build the commit. Expected resume-path behaviour.iterion resume has no --timeout flag (unlike run).