Gap-driven feature completer. A specialisation of feature_dev: the input is a
structured gap_spec (“here is what’s implemented, here is what’s missing”),
not a greenfield prompt. Fini reads the partial implementation, completes the
missing parts, runs the alternating Claude/GPT review-fix loop to convergence,
then commits. Inputs are typically the type:feature-gap issues filed by the
adr-cartograph (Adry) bot.
iterion-sandbox-full:edge), zero delegate retries.dev+a239f80eb (the fix stack below)./tmp/iterion-probe-221e/fini-fixture3 — NOT the Claude scratchpad, see defect 3), --store-dir <workspace>/.iterion, --merge-into none, post_to_board=false, --max-cost-usd 8. ~9 min wall.finished; campaign gap_closed=true, commits_this_pass=1, needs_human=false → verify_run passed=true → gate converged=true; storage branch iterion/run/magneto-chase-vortexvape-5c36 @ 3d7996637b9d feat(user): validate empty name and email without '@', add table-driven tests; 0 delegate_retry / 0 delegate_error on the whole run (vs 100% cold-abort pre-fix); container cleaned up, no leaked claude processes.~/.claude.json not mounted (root cause): host_state carried the ~/.claude dir but not the sibling top-level config file; in-container claude saw the host’s config backups (inside the mounted dir) with no config → manual-restore stderr loop, zero stdout forever → 90s cold-abort every attempt. Fix a239f80eb (+ regression test). Bisect proof: prompt-arg claude printed the restore error; stream-json hung mute; with the mount the init frame arrived in 3s.ec31b056f (pidfile-then-exec wrapper + deferred TERM→KILL) + 834a53a5c (wrapper self-cleans on respawn). Proven live: exactly 1 claude + 1 pidfile across retries./tmp/claude-1000/… (the operator-agent scratchpad); docker creates the bind’s parents ROOT-OWNED in-container, shadowing claude’s own temp root /tmp/claude-$UID → silent pre-init hang even with 1+2 fixed. Surgical A/B: same fixture at /tmp/probe-fixture boots in 3s, under /tmp/claude-1000/ hangs. Now documented in CLAUDE.md (dogfood section).ITERION_CLAUDE_CODE_STREAM_COLD_TIMEOUT takes a Go duration (5m), not a bare number.dev+239203525cc8.--store-dir <workspace>/.iterion, --merge-into none, --sandbox none, gap_spec = User.Validate stub + missing validations + table tests, --max-cost-usd 15. 4m06s wall, converged first pass.finished, gate.converged=true. 1 commit in stride (feat(user): validate empty name and email without '@' + Bot: feature-gap-fill trailer) on iterion/run/pixel-leap-borealroar-d544 — all 3 missing items on the existing seam, granularity defensible (same function + its table test). Deterministic verify: go build + go test green. Functional proof from the delivered branch: TestUserValidate 3/3 subtests PASS.--var workspace_dir=<path>: the sandbox mounts the RUN’s workspace, so an out-of-tree workspace_dir doesn’t exist in-container. First launch (019f3d4a) mis-launched that way, cancelled.--sandbox none — the sandboxed delegate stdin/stream path is the suspect. Testy’s sandboxed run worked 90min earlier, so it may be load/ordering sensitive.ITERION_CLAUDE_CODE_STREAM_COLD_TIMEOUT takes a Go duration (5m), NOT bare millis — 300000 parses as invalid → silent 90s fallback (worth a startup warning; candidate small fix).--sandbox none for fixture-repo dogfoods until 221edac8 lands; re-run the sandboxed variant afterwards to close the loop.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.030031f6 (main)ITERION_OPENAI_USE_OAUTH=1 ./iterion run
bots/feature-gap-fill/main.bot --var gap_spec='<08aaf4ef body>' --store-dir
.iterion --merge-into none. gap_spec = Adry’s bot-marketplace-shallow-clone
issue (Add transport validation for bot marketplace shallow clone sources).
Ran SANDBOXED (iterion-sandbox-full:edge, worktree: auto) — unlike the
019ec599 run which forced --sandbox none. Forfait forced.a7f44eb3 (“feat(git): gate git clone sources to safe https/ssh transports”,
4 files +154/-2) on storage branch iterion/run/chrome-surge-scalarsmol-9428.
I reviewed + validated (go test ./pkg/git ./pkg/botinstall → ok) then
FF-merged to main. Board 08aaf4ef → done.ValidateCloneSource
(pkg/git/safety.go) allowlists https:///ssh:///scp-like and rejects the
:: remote-helper marker (catches ext:: arbitrary-command-exec) +
file:///git:///http:///bare paths; ShallowClone now calls it (keeping
-- as flag-injection defense-in-depth). clone_test.go tests 6 accept + 12
reject cases incl. the error-message acceptance criterion. Survey was
excellent: found ADR-020 as the doc home, identified the HTTP marketplace
routes as the actual untrusted surface, noted ValidateRelPath/
ValidateBranchName pre-existed (stayed in scope).StructuredOutput: no such tool
error (d8e8dde1 holding on schema+tools claude_code nodes), no forfait
flakiness, no retries. Sandboxed claude_code + reviewer_gpt (claw/forfait)
both ran cleanly in-container — the sandbox path is viable for Fini now
(contrast the 019ec599 bilan’s “host-mode until ~/.codex mounted” caveat).devbox cache permission-denied
go can’t fetch the 1.26.0 toolchain in the container). Reviewers
approved by reading the diff; tests were never executed by Fini. So a
human/CLI must go test on the host before merge (I did → pass). Known
“devbox silently broken in sandbox” limitation.ShallowClone hermetically via a file:// URL — but
08aaf4ef’s new gate rejects file://, obsoleting that approach. The
empty/whitespace-guard intent is now covered by clone_test.go
(ValidateCloneSource is the guard); the actual-clone cases (with/without
ref, stderr-wrap) can’t be tested hermetically post-gate (would need a
cloneArgs(url,ref,dest) extraction or a test seam). 50bbe258 needs
re-scope; left in inbox, not run as-is. Lesson: when Adry files multiple
gap tickets on one function, one fix can invalidate another’s approach.http:// rejection as a
possible config need (internal cleartext servers) and the go.mod yaml.v3
indirect→direct drift, both as observations, not scope creep.03f398e2 (main)iterion run bots/feature-gap-fill/main.bot --var gap_spec='<…>'
--sandbox none --merge-into none, gap_spec = the file-diff-payload
issue Adry filed (Cap file contents loaded for Monaco diff payloads).
Launched under devbox run with ~/.local/bin on PATH so the host run had
both go (devbox) and claude (host) — sandbox forced off because this
worktree’s engine predates the concurrent sandboxed-claw fixes and ~/.codex
(forfait) is not mounted into the container. worktree: auto still isolated
the Go edits; forfait forced (ITERION_OPENAI_USE_OAUTH=1).88943d4b (“feat(git): cap diff payload
reads to avoid OOM on oversized files”, 5 files, +267/-30) on the
storage branch iterion/run/magneto-whomp-etherspark-4f0a — NOT on main
(--merge-into none), preserved for human review. The engine recorded
final_commit + final_branch and removed the worktree cleanly.errOversized sentinel + diffPayloadCap (reuses
untrackedReadCap’s 5 MiB), the reading primitives (readWorktreeFile,
showAt) return oversized before loading the blob into memory, both
sides blanked + Oversized=true, oversize-wins-over-binary — meeting all the
issue’s acceptance criteria. It also ADDED pkg/git/diff_test.go (160 lines:
TestDiffOversizedWorktree, TestDiffOversizedHead), exactly as the
acceptance criteria required.88943d4b into a throwaway
worktree and ran go build ./pkg/git/ + go test ./pkg/git/ independently
→ builds clean, tests pass (ok 1.162s). Real work, not a reported
parity façade.type:feature-gap issue → Fini completed it with tested
code. This is the architecture-evolution loop the suite was designed for.--sandbox none) needs BOTH go and claude on PATH: launch
under devbox run (go) with ~/.local/bin appended (claude). The sandbox
path is cleaner if ~/.codex (forfait) is mounted into the container —
it currently is not, so host-mode is the reliable forfait path until that’s
wired (or an API key is used).--merge-into none) for human
review — the operator merges it (or routes it through adr-rechallenge) rather
than Fini pushing to main. Correct default for an autonomous code-mutating bot.