E2E coverage matrix
The single feature×coverage inventory for iterion. One row per operator-observable promise, at the granularity a regression report would name it. Every row is terminal (covered-deterministic / covered-live / unit-only / excluded) or an honest uncovered gap with the plan.
A citation must be the test that would FAIL if the promise broke. The deterministic gate greps every reference, so it catches a citation that does not exist — it cannot catch one that exists but tests something else. Two adversarial audits sampled 70 rows and found 11 such mis-citations (mostly: a row citing the mechanics of a helper while the WIRING that invokes it went untested). When you touch a row, re-read the cited test and ask what its failure would actually mean.
This file supersedes the three partial coverage docs it reconciles:
- docs/e2e_coverage.md — the iterion×claw-code-go live matrix + the deliberate claw-side gaps (folded into the
backends,tools-mcpandobservabilityfamilies below). - docs/live-e2e-coverage.md — the opt-in real-LLM layer (how it works, the quality-judge panel, the per-bot targets). Still the reference for running the live layer; its bot/feature tables are mirrored here as
covered-liverows. - e2e/SCENARIOS.md — the flagship-workflow stub-executor scenarios (folded into
runtimeanddsl).
Legend
| Status | Meaning |
|---|---|
covered-deterministic | A CI-runnable, credential-free test drives the real seams and asserts observable outcomes |
covered-live | Only exercised in the opt-in live-tagged layer (needs a real model/credential) |
unit-only | Deliberately terminal at unit level — an e2e would only re-test the harness |
excluded | Not exercisable in this repo's harness (needs a third-party tenant / cloud control plane) |
uncovered | Real gap — backlog |
What "the front door" means per family
- dsl — the front door is
.botsource text: parse → compile → the diagnostic or IR an operator sees fromiterion validate. Rows whose behaviour only shows at execution time cite a runtime/e2e test instead. - runtime — the public engine API (
runtime.Engine.Run/Resume) against a realstore.RunStore, asserting persisted status, checkpoint, artifacts and the event stream.e2e/additionally enters through.botfixtures. - cli —
cli.Run*entry points with a real store and (where an LLM would be involved) a stubruntime.NodeExecutorinjected at the documented seam. - server-api / cloud —
httptestagainst the real wired handler. - studio-ui — Playwright (
studio/e2e/,task test:e2e:ui) drives a real Chromium against the REAL server: the builtiterionbinary serving the embedded SPA over a throwaway store thatstudio/e2e/serve.mjsseeds with genuine artifacts — runs the engine actually executed (tool + compute fixtures, no LLM credential) and a board card created through the CLI. The suite asserts rendered content and interactions, never HTTP status codes. It is deliberately NOT wired into the blocking CI job yet (the browser download is opt-in;task test:e2e:uiskips cleanly without it).
Scope of the current campaign
Pass 1 built this inventory and closed the highest-value CLI quick wins (run --preset, run --max-*, secret, runs questions|answer, report). Pass 2 closed the remaining CLI quick wins: issue, diagram, skill, memory, run --recipe. Pass 3 closed the four CLI rows earlier passes had written off as needing a seam or a live model — the cli family is now terminal end to end. Each turned out to have a deterministic front door:
run --model/--backend— drive the REAL executor at fixtures whose backend/model cannot resolve; the failure text quotes whichever value won the resolution chain, offline.run --auto-resume— the loop's only wait is the reset-aware USAGE_LIMIT_BLOCKED delay, and the run's own retry policy clamps it, so a 1ms horizon removes the sleep without a clock seam.bench asymptote— the command re-runs nothing; stub-driven runs of a judge-in-a-loop fixture supply the exact events it parses.dispatch— boot the daemon in-process on a loopback port, assert the served surface, stop it with SIGTERM.
Everything still uncovered is deliberate backlog for later scoped runs, family by family. What is left, and why it is not a quick win:
Pass 5 introduced the browser harness the studio-ui family was waiting on and closed its rows (see the family note above).
Pass 4 closed the three remaining cloud rows — dlq, migrate-blobs, valkey-state — which earlier passes had written off as needing a live Mongo/S3/Valkey. Each had a deterministic front door after all:
valkey-state— two servers built through the realNew()wiring over one miniredis; each flow starts on replica A and finishes on replica B.migrate-blobs— the walker between two real stores, plus the real AWS SDK against an in-process path-style S3 gateway.dlq— the admin REST surface behind a narrowQueueBackendseam; the JetStream-side semantics are covered separately by the live-brokernats-conformancejob (TestSchemaRolloutMixedFleet).
| ID | Feature | Family | Status | Tests | Notes |
|---|---|---|---|---|---|
| dsl.node-agent | agent node: LLM node with structured I/O executes and publishes | dsl | covered-deterministic | TestSingleModel_HappyPath (e2e/e2e_test.go) | |
| dsl.node-judge | judge node: verdict-producing LLM node | dsl | covered-deterministic | TestSingleModel_HappyPath (e2e/e2e_test.go) | |
| dsl.node-tool | tool node: direct shell command, no LLM | dsl | covered-deterministic | TestExecutorToolNodeShellCommand (pkg/backend/model/executor_test.go), TestToolNodeShellMaterializesSecret (pkg/backend/model/secrets_materialize_test.go) | the shell path needs the REAL executor: the e2e scenario stub replaces every node — agent and tool alike — so a tool node rerouted through the LLM path would still pass there |
| dsl.node-compute | compute node: deterministic expression output | dsl | covered-deterministic | TestToolAndComputePublishArtifact (pkg/runtime/engine_test.go) | |
| dsl.node-human | human node: pause/resume with interaction record | dsl | covered-deterministic | TestCompliance_HumanGate (e2e/e2e_test.go) | |
| dsl.node-subbot | subbot node: nested child run, outputs read back | dsl | covered-deterministic | TestRunSubbotsPersistNestedLineage (pkg/cli/run_subbot_test.go) | |
| dsl.node-emit-wait | emit/wait: in-bot event pair with mandatory timeout | dsl | covered-deterministic | TestEventsEmitWait (e2e/events_emit_wait_test.go) | |
| dsl.node-await-answers | await_answers node parks its branch until answers land | dsl | covered-deterministic | TestAwaitAnswersReleasedByAnswer (e2e/async_interaction_test.go) | |
| dsl.node-done | done terminal node ends the run finished | dsl | covered-deterministic | TestSingleModel_HappyPath (e2e/e2e_test.go) | |
| dsl.node-fail | fail terminal node ends the run non-resumable failed | dsl | covered-deterministic | TestFailNode (pkg/runtime/engine_test.go) | |
| dsl.router-fan-out-all | router fan_out_all spawns parallel branches | dsl | covered-deterministic | TestDualParallel_HappyPath (e2e/e2e_test.go) | |
| dsl.router-fan-out-each | router fan_out_each: per-item branches with a dep DAG | dsl | covered-deterministic | TestFanOutEach_DAG_DiamondOrderingAndParallelism (pkg/runtime/fan_out_each_test.go) | |
| dsl.router-condition | router condition mode picks the matching edge | dsl | covered-deterministic | pkg/dsl/ir/validate_test.go, TestElseEdge_Routing (pkg/runtime/else_edge_test.go) | |
| dsl.router-round-robin | router round_robin alternates targets across iterations | dsl | covered-deterministic | pkg/runtime/round_robin_test.go | |
| dsl.router-llm | router llm mode: model picks the route | dsl | covered-deterministic | TestLLMRouterSelectsOtherRoute (pkg/runtime/llm_router_test.go) | |
| dsl.edges-conditional | edge when / when not conditions on a boolean output field | dsl | covered-deterministic | TestSingleModel_RefineLoop (e2e/e2e_test.go) | |
| dsl.edges-else | edge else fires only when no sibling when matched | dsl | covered-deterministic | TestElseEdge_PreferredOverStrayUnconditional (pkg/runtime/else_edge_test.go) | |
| dsl.edges-loop | bounded loop edge as name(n) | dsl | covered-deterministic | TestBoundedLoop (pkg/runtime/engine_test.go) | |
| dsl.edges-loop-templated-cap | loop cap templated from an upstream output | dsl | covered-deterministic | TestLoopTemplatedCap_FromOutput (pkg/runtime/engine_test.go) | |
| dsl.edges-loop-in-parallel | bounded as loop / as foreach wholly owned by one fan_out_all, fan_out_each, or llm multi branch is accepted; boundary-crossing cycles remain C244 | dsl | covered-deterministic | TestValidateLoopInFanOutAllBody_Allowed (pkg/dsl/ir/validate_exec_branch_loops_test.go) | also fan_out_each, llm-multi, foreach, and template-head acceptance; TestValidateLoopReenteringBodyFromJoin_Rejected and TestValidateLoopOnFanOutRouterEdge_Rejected pin boundary diagnostics; TestValidateLoopStraddlingLLMMultiPerEdgeCollector_Rejected / TestValidateLoopBeforeNonElectedAwaitInFanOutAll_Allowed pin the llm-multi rule that each branch is bounded by the collector its OWN edge can elect, since the model may select that edge alone |
| dsl.edges-data-mapping | edge with {…} data mapping and reference interpolation | dsl | covered-deterministic | TestResolveMapping_InterpolatesSurroundingLiterals (pkg/runtime/engine_resolve_mapping_test.go) | |
| dsl.refs | reference syntax: input/vars/outputs/artifacts substitution | dsl | covered-deterministic | pkg/dsl/ir/ref_test.go | |
| dsl.refs-edge-input | edge with {{input.x}} is the source output (C034 and the resolver agree; no run-input fallback; router pass-through preserved, including llm; mid-graph routers warn C032 when the field is not incoming) | dsl | covered-deterministic | TestEdgeInputRef_CompileAndRuntimeAgree (pkg/runtime/edge_input_ref_test.go) | also TestEdgeInputRef_RouterPassThrough, TestEdgeInputRef_LLMRouterPassThrough, TestEdgeInputRef_SchemalessSourceWarnsAndDoesNotFallBack, TestEdgeInputRef_MidGraphRouterDoesNotFallBack, TestEdgeInputRef_MidGraphRouterPassThrough; TestValidateRefInputOnEdge_SourceInputOnly_C034 / TestValidateRefInputOnEdge_RunInputOnly_C034VarsHint / TestValidateRefInputOnEdge_RouterPassThrough_NoSchemaSkip / TestValidateRefInputOnEdge_SchemalessSource_C032Warn / TestValidateRefInputOnEdge_MidGraphRouter_NoIncomingWith_C032 / TestValidateRefInputOnEdge_MidGraphRouter_IncomingWith_OK (pkg/dsl/ir/validate_test.go) |
| dsl.vars-defaults | vars: defaults applied when no override is supplied | dsl | covered-deterministic | pkg/dsl/ir/validate_var_default_test.go | |
| dsl.vars-enum | vars: enum constraint rejects an out-of-set value at launch | dsl | covered-deterministic | TestRunRejectsInvalidEnumVar (pkg/runtime/engine_var_enum_test.go) | |
| dsl.presets | in-source presets: block resolves named value sets | dsl | covered-deterministic | pkg/dsl/ir/presets_test.go | CLI wiring covered by cli.run-preset |
| dsl.prompts | prompt <name>: blocks and prompt includes | dsl | covered-deterministic | pkg/dsl/ir/prompt_include_test.go | |
| dsl.schemas | schema <name>: typed node output contracts | dsl | covered-deterministic | pkg/backend/model/schema_test.go | |
| dsl.cursors | cursor <name>: calibration fragments reach the system prompt | dsl | covered-deterministic | TestBuildSystemPromptCursorsOnly (pkg/backend/delegate/cursors_test.go), pkg/backend/model/cursors_test.go, pkg/dsl/ir/cursor_resolve_test.go | |
| dsl.attachments | attachments: block: files resolved and passed to nodes | dsl | covered-deterministic | pkg/dsl/ir/attachments_test.go, pkg/runtime/attachment_path_test.go | |
| dsl.skills-field | skills: field pulls library skills into the run mirror | dsl | covered-deterministic | pkg/dsl/ir/validate_skills_test.go, pkg/runtime/library_skills_test.go | |
| dsl.mcp-server-block | mcp_server: block declares stdio/http/sse MCP servers | dsl | covered-deterministic | TestMCPServer_SSETransport (pkg/dsl/parser/parser_mcp_test.go) | |
| dsl.capabilities | capabilities: list opens the board tool surface | dsl | covered-deterministic | pkg/dsl/ir/validate_capabilities_test.go, TestBoardDispatcher_E2E_CapabilityGate (e2e/board_dispatcher_test.go) | |
| dsl.supervisor-block | supervisor <name>: declaration compiles and spawns a coordinator | dsl | covered-deterministic | pkg/dsl/ir/compile_supervisors_test.go, pkg/supervise/coordinator_test.go | |
| dsl.compress-field | compress: precedence (CLI → node → workflow → env → default) | dsl | covered-deterministic | TestResolveWithDefault (pkg/backend/rewrite/rewrite_test.go), TestResolveWithDefaultSourced (pkg/backend/rewrite/rewrite_test.go), pkg/dsl/ir/compress_test.go | |
| dsl.auto-memory-field | auto_memory: per-node MEMORY.md switch, off by default | dsl | covered-deterministic | pkg/dsl/ir/auto_memory_test.go, pkg/backend/model/executor_auto_memory_test.go | |
| dsl.permission-field | permission: mode + allow/ask/deny rule lists | dsl | covered-deterministic | pkg/dsl/ir/permission_test.go, pkg/backend/permission/permission_test.go | |
| dsl.budget-block | budget: block fields compile onto the workflow | dsl | covered-deterministic | pkg/dsl/ir/budget_ceiling_test.go | |
| dsl.sandbox-block | sandbox: block (image/build/network/host_state) compiles | dsl | covered-deterministic | pkg/dsl/ir/sandbox_test.go, pkg/dsl/parser/parser_sandbox_test.go | |
| dsl.worktree-field | worktree: mode default resolution | dsl | covered-deterministic | pkg/dsl/ir/worktree_default_test.go | |
| dsl.session-modes | session modes (fresh / inherit / artifacts_only) | dsl | covered-deterministic | TestSessionInherit (pkg/runtime/session_test.go), TestSessionFork (pkg/runtime/session_test.go), TestSessionInheritIfAvailable_FallsBackToFreshWhenNoSession (pkg/runtime/session_test.go) | the modes are a RUNTIME behaviour; pkg/backend/model/session_test.go is the session store (persistence + compaction), a different contract |
| dsl.secrets-block | secrets: declarations + optional-secret semantics | dsl | covered-deterministic | pkg/dsl/ir/secrets_test.go, pkg/dsl/ir/optional_secret_test.go | |
| dsl.memory-block | memory: block scopes/visibility validation | dsl | covered-deterministic | pkg/dsl/ir/memory_visibility_test.go | |
| dsl.verified-action | Verified Action quad (goal/postcondition/policy/recovery) | dsl | covered-deterministic | TestVerifiedActionEngineEmitsAndStrips (e2e/verified_action_test.go) | |
| dsl.groups-iteration | group: expansion / iteration sugar | dsl | covered-deterministic | pkg/dsl/ir/expand_groups_test.go, pkg/dsl/ir/foreach_test.go | |
| dsl.diagnostics | compile diagnostics C001–C2xx codes and severities | dsl | covered-deterministic | pkg/dsl/ir/diag_codes_test.go, TestValidate_Invalid (pkg/cli/cli_test.go) | |
| dsl.unparse-roundtrip | IR → .bot serialization round-trips | dsl | covered-deterministic | pkg/dsl/unparse/roundtrip_test.go | |
| dsl.ast-json | AST JSON encode/decode (MarshalFile/UnmarshalFile) | dsl | covered-deterministic | pkg/dsl/ast/jsonenc_test.go | |
| dsl.expr | expression evaluator for compute nodes and when conditions | dsl | unit-only | pkg/dsl/expr/expr_test.go, pkg/dsl/expr/overflow_test.go | pure evaluator, exhaustively asserted at unit level; its e2e effect is already covered by dsl.node-compute — an extra pipeline test would re-assert a pure function |
| dsl.parser-fuzz | lexer/parser robustness on malformed input | dsl | unit-only | pkg/dsl/parser/fuzz_test.go | fuzzing is by nature a unit-level property test; the operator-visible surface (a diagnostic, not a panic) is dsl.diagnostics |
| runtime.linear-execution | sequential node execution to a terminal node | runtime | covered-deterministic | TestLinearPath (pkg/runtime/engine_test.go) | |
| runtime.selected-incoming-edges | a node input is built only from incoming edges routing selected for this visit; unselected conditional siblings do not clobber, fan-out joins still merge every selected branch, and the set survives pause/resume (issue #484) | runtime | covered-deterministic | TestSelectedIncoming_ExclusiveSiblingsIgnoreUnselectedElse (pkg/runtime/incoming_test.go) | also TestSelectedIncoming_ExclusiveSiblingsIgnoreUnselectedElseRegardlessOfOrder, TestSelectedIncoming_ElsePathStillApplies, TestSelectedIncoming_UntrackedFallbackMergesAllWithOutput, TestSelectedIncoming_FanOutJoinMergesBothSelected, TestSelectedIncoming_SurvivesFailedResume; loop-head back-edge precedence remains TestLoopHeadSelfRefBackEdgeAdvances (pkg/runtime/loop_head_selfref_test.go) |
| runtime.await-wait-all | convergence await: wait_all waits for every branch | runtime | covered-deterministic | TestDualParallel_HappyPath (e2e/e2e_test.go) | |
| runtime.await-best-effort | convergence await: best_effort proceeds on partial branches | runtime | covered-deterministic | TestChaos_FailMidFanOut_BestEffort (pkg/runtime/chaos_test.go) | also TestSharedTargetFanOut_BranchFailure (pkg/runtime/convergence_fires_once_test.go): the survivor's output reaches the collector and the failure is named on join_ready, while wait_all fails the run before the collector |
| runtime.await-fires-once | the collector of a fan-out fires exactly once, after every branch has settled, under both await modes — including when a fan-out target is ALSO reachable from outside the fan-out (the mono/dual review topology, issue #741), across a branch pause + resume, and across a failure downstream of the collector | runtime | covered-deterministic | TestSharedTargetFanOut_CollectorFiresOnce (pkg/runtime/convergence_fires_once_test.go), TestReviewPRDual_CollectorChainFiresOnce (e2e/review_pr_convergence_test.go) | also TestSharedTargetFanOut_ResumeAfterBranchPauseFiresCollectorOnce, TestSharedTargetFanOut_ResumeAfterTailFailureDoesNotRefireCollector, TestSharedTemplateHeadFanOutEach_ReplaysEveryItemAndFiresCollectorOnce (fan_out_each, same class); the election itself is TestFindConvergencePoint_TargetFedFromOutsideTheFanOutIsNotTheCollector (pkg/runtime/fan_out_internal_test.go) and TestShippedDualTopologies_ElectTheDeclaredCollector (e2e/review_pr_convergence_test.go) for review-pr + evolve |
| runtime.local-loop | local loop re-executes and versions artifacts | runtime | covered-deterministic | TestSingleModel_RefineLoop (e2e/e2e_test.go) | |
| runtime.global-reloop | global reloop restarts the recipe from an upstream node | runtime | covered-deterministic | TestSingleModel_GlobalReloop (e2e/e2e_test.go) | |
| runtime.loop-exhaustion | loop cap exhaustion fails the run with LOOP_EXHAUSTED | runtime | covered-deterministic | TestCIFix_LoopExhaustion (e2e/e2e_test.go), TestLoopExhaustionRuntimeError (pkg/runtime/hardening_test.go) | |
| runtime.budget-cost | max_cost_usd exceeded past the graced ceiling stops the run and emits budget_exceeded | runtime | covered-deterministic | TestBudgetCostExceeded (pkg/runtime/budget_test.go) | with the default grace on, 100% alone no longer stops a run — see runtime.budget-exit-grace |
| runtime.budget-tokens | max_tokens exceeded past the graced ceiling stops the run | runtime | covered-deterministic | TestBudgetTokensExceeded (pkg/runtime/budget_test.go) | |
| runtime.budget-duration | max_duration exceeded past the graced ceiling stops the run | runtime | covered-deterministic | TestBudgetDurationExceeded (pkg/runtime/budget_test.go) | |
| runtime.budget-warning | budget warning event at the soft threshold, advisory only | runtime | covered-deterministic | TestBudgetWarningEmitted (pkg/runtime/budget_test.go), TestWarnTokensAdvisoryNeverBlocks (pkg/runtime/budget_test.go) | |
| runtime.budget-shared | budget accounting shared across parallel branches | runtime | covered-deterministic | TestBudgetSharedFirstComeFirstServed (pkg/runtime/budget_test.go) | |
| runtime.budget-exit-grace | a spent cap still walks FORWARD to a terminal node, inside a proportional ceiling, so banked work is delivered | runtime | covered-deterministic | TestBudgetGraceDeliversBankedWork (pkg/runtime/budget_test.go), TestBudgetGraceIsBounded (pkg/runtime/budget_test.go), TestBudgetGraceCoversDuration (pkg/runtime/budget_test.go), TestBudgetGraceCoversImmediateRecordPath (pkg/runtime/budget_test.go), TestBudgetGraceEdgeErrorStillDiesOnBudget (pkg/runtime/budget_test.go) | the delivery promise AND its bound: past cap × (1+ratio) the run fails as before, the duration axis gets a real graced deadline rather than none, and an in-grace overrun with no matching edge still dies as BUDGET_EXCEEDED (the sentinel the runner acks terminal). The fan-out path is its own row below |
| runtime.budget-exit-grace-refusals | the grace is refused when the loop guard is off, when the ratio is 0, and on an externally-imposed cap; a bad ratio fails closed | runtime | covered-deterministic | TestBudgetGraceRefusedWhenLoopGuardOff (pkg/runtime/budget_test.go), TestBudgetGraceAbsoluteWhenZero (pkg/runtime/budget_test.go), TestBudgetGraceRefusedOnImposedCap (pkg/runtime/budget_test.go), TestBudgetGraceInvalidEnvFailsClosed (pkg/runtime/budget_test.go), TestBudgetClampToCeilingMarksImposedCap (pkg/dsl/ir/budget_ceiling_test.go) | the safety half: the grace borrows "no further iteration" from the loop guard, and a cap clamped by the platform ceiling or a pool donor's allowance is absolute — the clamp choke point marking it is covered too |
| runtime.budget-exit-grace-event | every graced node is auditable: one budget_exit_grace event naming the exceeded axis and its own used/limit | runtime | covered-deterministic | TestBudgetGraceEventIsCoherentAndSingular (pkg/runtime/budget_test.go) | a deliberate overspend must be visible in the events, not discovered on the invoice — and the triple must not mix one dimension's ratio under another's name |
| runtime.budget-exit-grace-outranks-hard-limit | on the SEQUENTIAL pre-exec path a granted grace decides and returns: the 90% hard limit on another axis gets no second opinion | runtime | covered-deterministic | TestBudgetGraceSurvivesHardLimitOnAnotherAxis (pkg/runtime/budget_test.go) | the max_cost_usd + max_duration pairing late in a long run; refusing a node at 90% of axis B while permitting 110% of axis A would defeat the grace exactly where it matters. checkBudgetBeforeExec returns the grace verdict (pkg/runtime/budget.go:600-602) |
| runtime.budget-exit-grace-refused-in-branches | a parallel branch never receives the exit grace, and the wait_all death that follows still carries the BUDGET_EXCEEDED sentinel | runtime | covered-deterministic | TestBudgetGraceStopsBeforeFanOutBranches (pkg/runtime/budget_test.go), TestBudgetGraceFanOutWaitAllKeepsBudgetSentinel (pkg/runtime/budget_test.go) | sibling spend lands on one shared budget concurrently, so no branch can price its own next node — the same reason predictive loop pricing is off there. checkPreExecBudget (pkg/runtime/branch.go) now refuses on exceeded and returns, so the earlier grace/hard-limit fall-through that could write a contradicting event pair is gone by construction. The stop-path shape matters as much as the refusal: a naked convergence error would go back to JetStream as retryable and loop resume/refail against the same spent cap |
| runtime.loop-budget-guard | a loop back-edge the remaining budget cannot fund is declined, so the run leaves through its own exit path with the work it banked | runtime | covered-deterministic | TestLoopBudgetGuard_FallsThroughToDeliveryTail (pkg/runtime/loop_budget_test.go), TestLoopBudgetGuard_OffRestoresTheStrandingFailure (pkg/runtime/loop_budget_test.go), TestLoopBudgetGuard_ConditionalBackEdgeIsNotPricedWhenItDoesNotMatch (pkg/runtime/loop_budget_test.go), TestLoopBudgetGuard_IgnoresUnenforcedAxes (pkg/runtime/loop_budget_test.go) | the guard the exit grace borrows its "no further iteration" half from; emits budget_warning with reason loop_budget_guard |
| runtime.loop-budget-guard-pricing | an iteration is priced from the loop's own ENTRY and re-priced on re-entry, and the prices ride the checkpoint | runtime | covered-deterministic | TestLoopBudgetGuard_LateEnteredLoopIsPricedFromItsEntry (pkg/runtime/loop_budget_test.go), TestLoopBudgetGuard_ReEnteredLoopReBasesItsPrice (pkg/runtime/loop_budget_test.go), TestLoopBudgetGuard_MarksSurviveResume (pkg/runtime/loop_budget_test.go), TestLoopBudgetGuard_UnpricedLoopIsNotDeclined (pkg/runtime/loop_budget_test.go) | so a second-phase or nested loop is never charged for the work that preceded it |
| runtime.loop-budget-guard-precedence | --loop-budget-guard → workflow loop_budget_guard: → ITERION_LOOP_BUDGET_GUARD → on, and the run-level override travels onto the cloud queue | runtime | covered-deterministic | TestLoopBudgetGuard_PrecedenceChain (pkg/runtime/loop_budget_test.go), TestLoopBudgetGuard_WorkflowOffIsHonouredEndToEnd (pkg/runtime/loop_budget_test.go), TestValidateLoopBudgetGuardMode (pkg/runtime/loop_budget_test.go) | C133 rejects an invalid mode |
| runtime.budget-unpriced-cost | a delegate that reports no cost is advertised as a FLOOR, not a total, rather than silently counting as $0 | runtime | covered-deterministic | TestSharedBudget_UnpricedSpend (pkg/runtime/budget_test.go) | the cost_usd_unpriced advisory documented in docs/dsl.md; warns at most once per run and never blocks |
| runtime.max-parallel-branches | max_parallel_branches semaphore bounds concurrency | runtime | covered-deterministic | TestFanOutEach_DAG_BoundedParallelism (pkg/runtime/fan_out_each_test.go) | |
| runtime.branch-local-loops | loops/foreach inside parallel branches use independent durable counters, outputs, artifact allocations, human-resume cursors, and rewind invalidation | runtime | covered-deterministic | TestFanOutEachBranchLocalLoopsKeepIndependentCounters (pkg/runtime/branch_local_loop_test.go) | also TestFanOutAllBranchLocalLoopRunsBeforeWaitAll, TestFanOutEachBranchLocalForeachUsesPrivateIndex, TestResolveLoopAndEachSeeEnclosingTrunkNamespaces, TestFanOutInsideTrunkLoopResolvesEnclosingPreviousOutput, TestFanOutInsideTrunkForeachResolvesEnclosingItem, TestFanOutEachBranchLocalLoopHumanResumeKeepsScope, TestFanOutEachSiblingHumanGatesResumeOneScopeAtATime, TestFanOutEachBranchCanPauseAtSequentialHumanGates, and TestRewind_PromotesFanOutBodyToRouter; race-covered |
| runtime.daily-cap-branch-resume | a branch that pauses and resumes contributes BOTH passes' spend to the per-day cap ledger | runtime | covered-deterministic | TestBranchDailyCapLedgerSurvivesResume (pkg/runtime/branch_local_loop_test.go), TestBranchDailyCapLedgerKeyStableAcrossSiblingResume (pkg/runtime/branch_local_loop_test.go), the BranchCheckpoint round-trip in pkg/store/storetest/conformance.go | the ledger key is <run>#<branch>#<loop-path> and AddSpend keeps the monotonic MAX per key; the loop path is restored from the checkpoint, so a resumed branch re-uses its pre-pause key even when sibling goroutine order changes. With branch-local cursors the resumed pass runs only the nodes after the gate, so an accumulator restarting at zero would be max()'d away and every post-resume dollar would vanish from the cap |
| runtime.workspace-safety | only one mutating branch may run concurrently | runtime | covered-deterministic | TestWorkspaceSafetyRejectsDualMutation (pkg/runtime/budget_test.go) | |
| runtime.checkpoint | a checkpoint is saved after every successful node | runtime | covered-deterministic | TestCheckpointPreservesUpstreamOutputs (pkg/runtime/engine_test.go) | |
| runtime.resume-failed | resume from failed_resumable restarts at the failing node | runtime | covered-deterministic | TestResumeFromFailed (pkg/runtime/engine_test.go), TestResumeDoesNotReplayUpstream (pkg/runtime/engine_test.go) | |
| runtime.resume-hash-guard | resume refuses a changed .bot unless --force | runtime | covered-deterministic | TestForceResumeBypassesHashCheck (pkg/runtime/engine_test.go), pkg/runview/service_resume_hash_test.go | |
| runtime.resume-human | resume a paused_waiting_human run with answers | runtime | covered-deterministic | TestHumanPauseAndResume (pkg/runtime/engine_test.go), TestResume_Success (pkg/cli/cli_test.go) | |
| runtime.mission-receipt-cas | durable mission resume claims one exact status and stamps its host receipt on run_resumed; rewind resolves a non-mutating final pivot, guards it before mutation, and stamps run_rewound | runtime | covered-deterministic | TestResumeFromFailure_MissionClaimUsesExactStatusAndStampsReceipt (pkg/runtime/resume_failure_char_test.go), TestResolveRewindPivotIsNonMutatingAndGuardedReceiptIsAuditable (pkg/runview/rewind_test.go), TestSubmitResume_MissionExpectedStatusAndReceiptCrossPublisherCAS (pkg/server/cloudpublisher/publisher_resume_test.go) | cloud publisher consumes expected status before queued; runner keeps receipt identity |
| runtime.cancel | cancellation produces a cancelled status with a checkpoint | runtime | covered-deterministic | TestCancelProducesCancelledStatus (pkg/runtime/hardening_test.go) | |
| runtime.timeout | outer deadline produces a TIMEOUT failure | runtime | covered-deterministic | TestTimeoutProducesFailedStatus (pkg/runtime/hardening_test.go) | |
| runtime.interaction-modes | human interaction: llm / llm_or_human / async escalation | runtime | covered-deterministic | TestInteractionLLMOrHumanEscalation (pkg/runtime/engine_test.go), TestInteractionLLMAutoRespond (pkg/runtime/engine_test.go) | |
| runtime.async-backend-capability | async nodes refuse incapable primary/fallback routes and Pi print transport before dispatch, without retries | runtime | covered-deterministic | pkg/dsl/ir/async_backend_test.go, pkg/backend/model/async_backend_test.go, TestCapabilityUnsupportedDoesNotRetry (pkg/runtime/recovery/capability_test.go) | |
| runtime.ask-user-conversation | ask_user relays prior Q/A and persists the conversation | runtime | covered-deterministic | TestInteractionAskUserPersistsConversation (pkg/runtime/engine_test.go) | |
| runtime.worktree-finalize | worktree: auto creates a branch and fast-forwards the checkout | runtime | covered-deterministic | pkg/runtime/worktree_test.go | |
| runtime.worktree-early-refusal | terminal compute/fail refusal releases a pristine checkout and rewind restores its original baseline | runtime | covered-deterministic | pkg/runtime/worktree_refusal_test.go, pkg/runview/rewind_reclaimed_test.go | |
| runtime.rewind | iterion rewind re-anchors a run and invalidates downstream state | runtime | covered-deterministic | TestRewindThenResume_SkipsUpstreamNodes (e2e/rewind_resume_test.go) | |
| runtime.run-document-concurrency | rename and rewind refuse stale document writes instead of overwriting a concurrent resume | runtime | covered-deterministic | TestRenameDoesNotUndoConcurrentResume (pkg/runview/run_version_test.go), TestRewindDoesNotOverwriteConcurrentResume (pkg/runview/run_version_test.go), TestRewindDoesNotOverwriteCheckpointAfterFinalSave (pkg/runview/run_version_test.go) | Shared FS/Mongo SaveRunVersionConflicts conformance and cross-store FS contention pin the persistence boundary. A rewind conflict after file restoration does not roll files back. |
| runtime.rewind-workspace | rewind restores workspace files for non-worktree runs, scoped to what the run recorded changing (issue #380) | runtime | covered-deterministic | TestRewindRestoresWorkspaceEndToEnd (e2e/rewind_workspace_test.go) | |
| runtime.rewind-workspace-failed-node | a node that dies mid-execution still has its debris undone, via the fail: boundary | runtime | covered-deterministic | TestRewindScopeCoversAFailedNodesDebris (e2e/rewind_workspace_test.go) | |
| runtime.rewind-workspace-stop-window | edits made while a run is stopped (fail → triage → resume, a human gate, a delegate ask_user pause) are not attributed to the run | runtime | covered-deterministic | TestRewindAfterResumeKeepsTriageEdits, TestRewindScopeAfterHumanGatePause, TestRewindScopeAfterDelegatePause (e2e/rewind_workspace_test.go) | |
| runtime.fork | fork a run at a prior LLM turn into a resumable child run | runtime | covered-deterministic | pkg/runview/fork_test.go | |
| runtime.event-stream | event sequence coherence (ordering, pairing, monotonic seq) | runtime | covered-deterministic | TestEventSequenceCoherence (e2e/e2e_test.go) | |
| runtime.artifact-versioning | repeated node executions version their artifacts | runtime | covered-deterministic | TestSingleModel_GlobalReloop (e2e/e2e_test.go) | |
| runtime.publish-gate | only a publish:-declared node leaves an artifact | runtime | covered-deterministic | TestOnlyAPublishedNodeLeavesAnArtifact (e2e/handoff_publish_test.go) | |
| runtime.skills-mirror | bundle/plugin/library skills mirrored into .claude/skills/ | runtime | covered-deterministic | TestMirrorBundleSkills_CopiesIntoClaudeSkills (pkg/runtime/bundle_test.go) | |
| runtime.devbox-provision | a bot's/target's devbox.json is installed and put on PATH | runtime | covered-deterministic | TestEngineRun_HostDevbox_RepoProjectInstallsInPlace (pkg/runtime/devbox_host_test.go) | |
| runtime.subbot-depth-guard | nested subbot recursion depth guard | runtime | covered-deterministic | TestSubbotRunnerForCLI_RecursionDepthGuard (pkg/cli/subbot_nested_test.go) | |
| runtime.supervisor | supervisor steers a watched node via the message inbox | runtime | covered-live | TestLive_Feat_Supervisor (e2e/live_feat_supervisor_test.go) | the composed steer decision is LLM-driven (Coordinator → GenerateObjectDirect), so only the live layer exercises the full watch→decide→inject path; the bricks are unit-tested (pkg/supervise/coordinator_test.go, pkg/backend/model/inbox_test.go) |
| runtime.recovery-dispatch | adaptive recovery ladder for verified action nodes | runtime | covered-deterministic | TestVerifiedActionEngineEmitsAndStrips (e2e/verified_action_test.go), pkg/backend/model/executor_verified_action_test.go | |
| runtime.privacy-redaction | secret/PII redaction across the run pipeline | runtime | covered-deterministic | TestE2E_PrivacyPipeline (e2e/privacy_test.go) | |
| persistence.run-json | run.json metadata, status transitions, format version | persistence | covered-deterministic | TestFormatVersionPersisted (pkg/runtime/hardening_test.go), pkg/store/store_test.go | |
| persistence.events-jsonl | events.jsonl append + monotonic seq + replay | persistence | covered-deterministic | pkg/store/store_test.go | |
| persistence.artifacts | versioned per-node artifacts under artifacts/ | persistence | covered-deterministic | pkg/store/store_test.go | |
| persistence.interactions | interaction records (questions/answers) persisted per run | persistence | covered-deterministic | TestAwaitAnswersAlreadyAnswered (e2e/async_interaction_test.go), pkg/store/store_test.go | |
| persistence.child-runs | parent/child run lineage for subbots | persistence | covered-deterministic | TestRunSubbotsPersistNestedLineage (pkg/cli/run_subbot_test.go) | |
| persistence.workspace-versioning | content-addressed workspace snapshots + restore | persistence | covered-deterministic | pkg/workspacetrack/native_test.go | |
| persistence.store-anchoring | store dir resolution (project .iterion vs $ITERION_HOME/projects) | persistence | covered-deterministic | TestStoreAnchorDir_BotInsideProjectResolvesProjectStore (pkg/cli/storeanchor_test.go) | |
| persistence.mongo-store | cloud Mongo-backed run store conformance | persistence | covered-deterministic | TestConformance_Mongo (pkg/store/mongo/conformance_test.go) | CI job mongo-conformance; skips without a Mongo endpoint. The board (kanban) Mongo store is a different contract — see dispatcher.native-tracker |
| persistence.mongo-future-fields | an older replica renames a run without truncating additive run/checkpoint/branch fields; intentional deletes, stale saves and future schema versions remain guarded | persistence | covered-deterministic | TestSaveRunPreservesFutureStateAcrossOldReaderRename, TestSaveRunRefusesStaleCopyWithFutureState, TestSaveRunRefusesFutureSchema (pkg/store/mongo/runs_unknown_test.go) | Real Mongo under mongo-conformance; includes BSON type preservation and reordered edge records. Skips without a Mongo endpoint. |
| cli.validate | iterion validate parses, compiles and reports diagnostics | cli | covered-deterministic | TestValidate_Valid (pkg/cli/cli_test.go), TestValidate_Invalid (pkg/cli/cli_test.go) | |
| cli.validate-bundle | iterion validate cross-checks a bundle manifest (C2xx) | cli | covered-deterministic | TestRunValidate_BundleVarTypoWarns (pkg/cli/validate_bundle_test.go) | |
| cli.run | iterion run executes a .bot and persists the run | cli | covered-deterministic | TestRun_Success (pkg/cli/cli_test.go) | |
| cli.run-vars | iterion run --var key=value overrides workflow vars | cli | covered-deterministic | TestRun_WithVars (pkg/cli/cli_test.go) | |
| cli.run-preset | iterion run --preset applies an in-source preset, --var wins over it | cli | covered-deterministic | TestRunPresetAppliesValuesAndVarWins (e2e/cli_launch_overrides_test.go) | |
| cli.run-budget-override | iterion run --max-* re-budgets the workflow for this run | cli | covered-deterministic | TestRunBudgetOverrideCapsTheRun (e2e/cli_budget_override_test.go) | |
| cli.run-model-backend-override | iterion run --model/--backend selector=… re-target nodes | cli | covered-deterministic | TestRunBackendOverrideRetargetsNodes (e2e/cli_model_backend_override_test.go), TestRunModelOverrideRetargetsNodes (e2e/cli_model_backend_override_test.go) | drives the REAL ClawExecutor (no stub) against fixtures whose backend/model cannot resolve, so the resolved value is readable from the failure text — credential-free and offline (unknown backend dies at registry lookup, unknown provider inside claw's spec parse) |
| cli.run-human-pause | iterion run returns at a human pause (--no-interactive) | cli | covered-deterministic | TestRun_HumanPause (pkg/cli/cli_test.go) | |
| cli.run-json | --json machine output mode for run | cli | covered-deterministic | TestRun_SuccessJSON (pkg/cli/cli_test.go) | |
| cli.run-recipe | iterion run --recipe <file> applies a recipe overlay | cli | covered-deterministic | TestRunRecipeAppliesPresetVarsAndVarStillWins (e2e/cli_recipe_test.go), TestRunRecipeBudgetOverridesTheWorkflowBudget (e2e/cli_recipe_test.go), TestRunRecipeRefusesAMismatchedWorkflow (e2e/cli_recipe_test.go), TestRunRecipeRefusesAnUnloadableFile (e2e/cli_recipe_test.go) | preset vars reaching the run, --var precedence over the recipe, workflow_ref.path resolving the .bot, the recipe budget changing the run outcome, and the mismatch/unloadable refusals |
| cli.run-auto-resume | --auto-resume N re-drives a retryable failed_resumable run | cli | covered-deterministic | TestRunAutoResumeRecoversRetryableFailure (e2e/cli_auto_resume_test.go), TestRunAutoResumeStaysOffByDefault (e2e/cli_auto_resume_test.go), TestRunAutoResumeRefusesNonRetryableCause (e2e/cli_auto_resume_test.go), TestRunAutoResumeStopsAtTheAttemptBudget (e2e/cli_auto_resume_test.go) | no clock seam needed: a USAGE_LIMIT_BLOCKED cause takes the reset-aware wait, which the run's own Retry policy (the field iterion schedule sets) clamps — a 1ms horizon collapses it, so the whole suite runs in <0.5s |
| cli.resume | iterion resume continues a paused/failed/cancelled run | cli | covered-deterministic | TestResume_Success (pkg/cli/cli_test.go) | |
| cli.resume-answers-file | iterion resume --answers-file / --answer @file | cli | covered-deterministic | TestResolveFileAnswerFlags_AttachesLocalFile (pkg/cli/resume_file_answers_test.go), TestParseAnswersFile (pkg/cli/cli_test.go) | |
| cli.resume-subbot | resume a run that owns subbot children | cli | covered-deterministic | TestResume_RunWithSubbot (pkg/cli/resume_subbot_test.go) | |
| cli.inspect | iterion inspect lists runs and shows a run's state | cli | covered-deterministic | TestInspect_ListRuns (pkg/cli/cli_test.go), TestInspect_SingleRun (pkg/cli/cli_test.go) | |
| cli.inspect-events | iterion inspect --events renders the stored event stream | cli | covered-deterministic | TestInspect_WithEvents (pkg/cli/cli_test.go) | |
| cli.inspect-node | iterion inspect --node per-node trace/artifacts/log sections | cli | covered-deterministic | TestInspect_SectionTrace (pkg/cli/cli_test.go), TestInspect_SectionArtifactsIncludesBody (pkg/cli/cli_test.go) | |
| cli.report | iterion report renders a run's chronological markdown report | cli | covered-deterministic | TestReportRendersChronologicalRunReport (e2e/cli_report_test.go), TestReportHonoursOutputPathAndJSON (e2e/cli_report_test.go) | |
| cli.diagram | iterion diagram emits a Mermaid graph for a .bot | cli | covered-deterministic | TestDiagramRendersEveryNodeAndEdgeOfTheWorkflow (e2e/cli_diagram_test.go), TestDiagramViewsDifferAndUnknownViewIsRefused (e2e/cli_diagram_test.go), TestDiagramJSONCarriesTheRenderedGraph (e2e/cli_diagram_test.go) | every node + edge of e2e/testdata/diagram_mini.bot, the condition/loop/mapping labels, the compact↔detailed↔full deltas, and the typo'd --view refusal |
| cli.runs-prune | iterion runs prune age/status/keep-last retention + dry-run | cli | covered-deterministic | TestRunPrune_AgeFiltering (pkg/cli/runs_prune_test.go), TestRunPrune_DryRunDeletesNothing (pkg/cli/runs_prune_test.go) | |
| cli.runs-async-questions | iterion runs questions / runs answer drive an async question to delivery | cli | covered-deterministic | TestRunsQuestionsThenAnswerReleasesAwaitGate (e2e/cli_async_questions_test.go), TestRunsAnswerRejectsBadInput (e2e/cli_async_questions_test.go) | |
| cli.fork | iterion fork creates a resumable fork at a prior turn | cli | covered-deterministic | pkg/runview/fork_test.go | CLI layer is a thin wrapper over runview.Service.Fork |
| cli.rewind | iterion rewind (incl. --auto bot-diff targeting) | cli | covered-deterministic | TestRewind_RefusesRunningRun_E2E (e2e/rewind_resume_test.go) | |
| cli.import | iterion import lowers a Claude-Code workflow script to a draft .bot | cli | covered-deterministic | TestRunImport_WritesDraft (pkg/cli/import_test.go) | |
| cli.bots-list | iterion bots list discovers .bot/.botz bundles | cli | covered-deterministic | TestBotsList_Bundle (pkg/cli/bots_test.go) | |
| cli.bots-create | iterion bots create scaffolds a discoverable bundle | cli | covered-deterministic | TestBotsCreate_ProducesDiscoverableBundle (pkg/cli/bots_create_test.go) | |
| cli.bots-create-shapes | --template <shape> renders a complete workflow of that form (bounded loop, reviewer fan-out, human gate, verified action, …) with its annex files, compiled through the bundle loader and held to its form | cli | covered-deterministic | TestGalleryShapes (pkg/botscaffold/shapes_test.go) | |
| cli.bots-regen-catalog | iterion bots regen-catalog regenerates Nexie's catalog skill | cli | covered-deterministic | bots/catalog_freshness_test.go | |
| cli.bundle-pack | iterion bundle pack produces a loadable .botz | cli | covered-deterministic | TestBundle_SecAuditSource_PackOpenCompile (e2e/bundle_sec_audit_source_test.go) | |
| cli.marketplace | iterion marketplace submit/install/uninstall (bot + plugin kinds) | cli | covered-deterministic | TestMarketplaceCLI_SubmitInstallUninstall_KindAware (pkg/cli/marketplace_test.go) | |
| cli.plugin | iterion plugin list/enable/disable/install/uninstall/config | cli | covered-deterministic | pkg/plugin/install_test.go, pkg/plugin/config_test.go | |
| cli.skill-library | iterion skill list/show/add/rm/export (layered global/project) | cli | covered-deterministic | TestSkillLibraryAddListShowExportRemove (e2e/cli_skill_test.go), TestSkillLibraryProjectScopeShadowsGlobal (e2e/cli_skill_test.go) | round-trip against an isolated ITERION_HOME, cross-checked through the same skilllib.LocalStoreForProject().Resolve the runtime mirror calls. skill import (git URL) is covered as plugins.install |
| cli.secret | iterion secret set/list/rm local sealed-secret lifecycle | cli | covered-deterministic | TestSecretSetListRemoveRoundTrip (e2e/cli_secret_test.go), TestSecretProjectScopeOverridesGlobal (e2e/cli_secret_test.go) | |
| cli.memory | iterion memory export/import/du | cli | covered-deterministic | TestMemoryExportImportRoundTripsASpace (cmd/iterion/memory_test.go), TestMemoryImportStrategyDecidesWhoWinsOnConflict (cmd/iterion/memory_test.go), TestMemoryDuReportsTheSpaceUsageAndQuota (cmd/iterion/memory_test.go), TestMemoryRefusesAnUnaddressableSpace (cmd/iterion/memory_test.go) | archive round-trip into a different space, the skip/overwrite conflict strategies, usage/quota reporting, and the unaddressable-space refusal — all through the real rootCmd against an isolated ITERION_HOME |
| cli.models | iterion models resolves capabilities and their source | cli | covered-deterministic | TestRunModels_JSONSingleModel (pkg/cli/models_test.go) | |
| cli.openapi | iterion openapi emits this build's OpenAPI 3.1 spec offline | cli | covered-deterministic | pkg/server/openapi_test.go | |
| cli.schedule | iterion schedule add/list/remove/install/uninstall crontab manifest | cli | covered-deterministic | TestRunScheduleAddListRemove (pkg/cli/schedule_test.go), TestRunScheduleInstallUninstall_SeamRoundTrip (pkg/cli/schedule_test.go) | |
| cli.schedule-gate | schedule overlap policy + pre-launch guard + tick audit | cli | covered-deterministic | TestScheduleRun_OverlapSkipsAndAuditsBlockingRun (pkg/cli/schedule_gate_test.go), TestScheduleRun_GuardNonZeroBlocks (pkg/cli/schedule_gate_test.go) | |
| cli.issue | iterion issue create/list/show/move/update/close/board | cli | covered-deterministic | TestIssueCLILifecycleCreateMoveUpdateClose (e2e/cli_issue_test.go), TestIssueCloseRefusesABoardWithNoTerminalState (e2e/cli_issue_test.go) | create → list/show → move → update → close read back through a fresh native.Store, plus the events.jsonl audit trail |
| cli.issue-import | iterion issue import pulls forge issues onto the board | cli | covered-deterministic | TestRunIssueImport_CreatesCardsAndIsIdempotent (e2e/cli_issue_import_test.go), TestRunIssueImport_RejectsUnsupportedForge (e2e/cli_issue_import_test.go) | drives the real CLI against a fake forge, then re-opens the board through a FRESH store: the cards that landed are the oracle, and a re-import proves idempotence |
| security.disable-auth-switch | ITERION_DISABLE_AUTH bypasses authentication on every /api/* endpoint | server-api | covered-deterministic | TestDisableAuthSwitchGovernsEveryProtectedRoute (pkg/server/disable_auth_switch_test.go) | both positions asserted as one contract — only the PAIR is meaningful, since pinning one alone passes for a switch welded shut |
| security.origin-gate | every state-changing /api route refuses a foreign Origin (403), while same-origin, loopback, wails and no-Origin callers pass | server-api | covered-deterministic | TestEveryStateChangingAPIRouteRefusesForeignOrigin (pkg/server/origin_gate_sweep_test.go), TestOriginGateAdmitsLegitimateCallers (pkg/server/origin_gate_sweep_test.go), TestOriginGateSweepBites (pkg/server/origin_gate_sweep_test.go), TestKillSwitchReachesHandlerLevelCallsToo (pkg/server/origin_gate_observability_test.go), TestSameWSOrigin (pkg/server/hub_origin_test.go) | the CSRF boundary, and the promise is "every route", so the sweep reads the LIVE routing table (174 rows) instead of a hand-kept list — a route added tomorrow is asserted with no edit here. Driven through the composed srv.handler, so it proves the gate is WIRED and not merely correct. Two properties keep it honest: it names the endpoints it exists for (a refactor that stops registering them fails rather than silently shrinking the sweep), and …SweepBites flips ITERION_REQUIRE_ORIGIN=0 to prove the 403s come from the gate rather than from some other refusal. The kill switch is asserted on BOTH callers, because it is read inside requireSafeOrigin rather than in the middleware: ~70 handlers call that directly, and a switch reaching only the middleware left the documented emergency rollback working for some routes and silently not for run cancel/merge, project writes, platform settings, bot sources and marketplace writes |
| security.origin-gate-diagnostics | a refusal is logged naming method/path/Origin (at info, so it cannot evict Sentry breadcrumbs), an admitted request logs nothing, and ITERION_ALLOWED_ORIGINS names extra hosts — normalised the way a browser serialises an Origin, malformed entries reported rather than dropped | server-api | covered-deterministic | TestOriginGateNamesWhatItRefused (pkg/server/origin_gate_observability_test.go), TestOriginGateStaysQuietWhenItAdmits (pkg/server/origin_gate_observability_test.go), TestRefusalLogCannotForgeARecord (pkg/server/origin_gate_observability_test.go), TestRefusalLogIsBounded (pkg/server/origin_gate_observability_test.go), TestExtraAllowedOriginsAdmitsASecondPublicHost (pkg/server/origin_gate_observability_test.go), TestExtraAllowedOriginsIsOffByDefault (pkg/server/origin_gate_observability_test.go), TestExtraAllowedOriginsReachesTheGateOnTheCloudServerToo (pkg/server/origin_gate_observability_test.go), TestMalformedAllowedOriginIsReportedNotSwallowed (pkg/server/origin_gate_observability_test.go), TestRefusalDoesNotFireTheLogHook (pkg/server/origin_gate_observability_test.go), TestRefusalIsLoggedAtInfoExactly (pkg/server/origin_gate_observability_test.go), TestAllowlistEntriesAreNormalisedTheWayABrowserSerialisesAnOrigin (pkg/server/origin_gate_observability_test.go), TestWildcardOriginIsRefusedLoudly (pkg/server/origin_gate_observability_test.go), TestTrailingSlashIsAcceptedNotScolded (pkg/server/origin_gate_observability_test.go) | the gate answers the caller and nothing else, so "nothing legitimate is refused" and "we cannot see one" were the same empty grep — which is how the board-MCP no-Origin claim stayed an inference. The env-var half drives the WHOLE chain from BOTH constructors (env → New / BrowserGuard → allowlist → verdict on a real request): asserting the parser alone stays green with the wiring deleted, and pinning only BrowserGuard leaves the cloud server — the surface the variable exists for — free to regress to inert while green. Both log values go through logSafe and NOT %q, whose escaping would neutralise a CRLF on its own and mask a removed sanitiser — the first version of the forging test did exactly that and passed inert. Normalisation is asserted through the GATE and over PublicURL as well as the env var, since both build an entry from a URL and matching is ==: an entry that merely parses is not an entry that works. The LEVEL is pinned in both directions rather than left to the call site, because it is written down in docs an operator greps by: at warn the refusal would evict Sentry breadcrumbs, below info it is invisible in production, and a runbook naming the wrong level rebuilds the false negative the line exists to kill |
| security.cookie-host-prefix | session cookies carry __Host-, so a sibling host under a shared registrable domain cannot toss one; legacy bare-named sessions still authenticate through the migration | server-api | covered-deterministic | TestHostPrefixOnProductionCookieShape (pkg/server/auth_cookie_prefix_test.go), TestHostPrefixWithheldWhenItsTermsCannotBeMet (pkg/server/auth_cookie_prefix_test.go), TestPrefixedCookieWinsOverATossedBareCookie (pkg/server/auth_cookie_prefix_test.go), TestHostPrefixedSessionRoundTrip (pkg/server/auth_cookie_prefix_test.go), TestClearAuthCookiesExpiresBothSpellings (pkg/server/auth_cookie_prefix_test.go) | covers the shape production runs (Secure + no Domain), which the older TestSetAuthCookiesAttributes never exercised — both its cases fall outside the prefix's terms, so they passed whichever way this resolved. The round trip is the composition guard: register through the real handler, replay the minted cookie on /api/auth/me. Write-only and read-only tests would both stay green if the two disagreed on the name |
| security.response-headers | the studio serves nosniff / Referrer-Policy / X-Frame-Options / Permissions-Policy and an enforced CSP, on served AND short-circuited responses | server-api | covered-deterministic | TestSecurityHeadersOnDocuments (pkg/server/middleware_security_headers_test.go), TestSecurityHeadersRideShortCircuitedResponses (pkg/server/middleware_security_headers_test.go), TestSecurityHeadersKillSwitch (pkg/server/middleware_security_headers_test.go), studio/e2e/specs/security-headers.spec.ts | script-src is asserted by exact source list, not substring: 'unsafe-inline' there would turn an injected string back into running code. The kill-switch test proves the headers come from THIS middleware and not from a layer that happens to set them. Browser half in studio-ui.csp |
| studio-ui.dsl-vocabulary | Monaco paints every generated lexer keyword and registered property, list markers and arrow chains while preserving prompt text | studio-ui | covered-deterministic | studio/src/lib/iterLanguage.test.ts, TestGeneratedDSLDocsAreFresh (pkg/dsl/spec/docs_fresh_test.go) | The real Monarch engine consumes the generated module; dsl:check compares it with the parser registry. |
| studio-ui.csp | the SPA boots and mounts Monaco under the enforced CSP with zero violations and zero third-party-CDN requests | studio-ui | covered-deterministic | studio/e2e/specs/security-headers.spec.ts | the only honest oracle for a CSP is a browser: a policy is worth its directives only if the app still works under it. Real chromium against the real binary. It also pins the editor's self-hosting — Monaco used to be fetched from cdn.jsdelivr.net at runtime — and asserts the editor actually rendered the fixture's source, so a blank page (what a too-strict CSP produces) cannot pass |
| security.origin-gate-dispatcher | iterion dispatch's own mux refuses a cross-origin state-changing POST while still serving its board UI and no-Origin callers | cli | covered-deterministic | TestDispatchDaemonRefusesCrossOriginWrites (e2e/cli_dispatch_daemon_test.go) | the daemon builds its HTTP surface by hand rather than through Server.routes(), so the studio's protections reached none of it — a drive-by page could create a board card, move it into the dispatcher-eligible state and force the poll, which runs a workflow with tools on the host. Drives the real daemon over loopback; reverting the BrowserGuard wrap reproduces the 201/202 an adversarial review measured live |
| security.agent-binding-cookies | the per-flow OIDC / forge binding cookies (RFC 9700 §4.7.1 login-CSRF guard) carry __Host-, refuse a tossed bare cookie outright, and clear both spellings | server-api | covered-deterministic | TestAgentBindingCookiesCarryTheHostPrefix (pkg/server/agent_binding_cookie_test.go), TestTossedAgentBindingCookieIsRefused (pkg/server/agent_binding_cookie_test.go), TestAgentBindingCookiesClearBothSpellings (pkg/server/agent_binding_cookie_test.go) | these were left bare on the in-code reasoning that a cross-site script "can't set a cookie for iterion's origin" — the claim a shared registrable domain falsifies. No legacy fallback here, deliberately: an interrupted flow is a re-login, a defeated CSRF guard is an account takeover |
| security.desktop-cookie-handoff | the desktop harvests a rotated refresh token, and strips the cloud's session cookies from its webview, under either cookie spelling | cli | covered-deterministic | TestCloudLoginHarvestsEitherCookieSpelling (cmd/iterion-desktop/cloud_cookie_prefix_test.go), TestHarvestRefreshCookieMatchesBothSpellings (cmd/iterion-desktop/cloud_cookie_prefix_test.go), TestProxyStripsBothSpellingsFromTheWebview (cmd/iterion-desktop/cloud_cookie_prefix_test.go) | the row exists because a private copy of the cookie literal drifted from the server's: the harvest silently returned "", the jar kept the PREVIOUS token, and replaying it made the server revoke every session that user held, on every device, on a ~13-minute loop. The fake cloud is parameterised over both spellings — it only ever emitted the bare one, which is why nothing caught it |
| studio-ui.first-paint | the editor stays off the critical path: the runs list does not fetch Monaco, and opening the editor does | studio-ui | covered-deterministic | studio/e2e/specs/first-paint.spec.ts | measured in the browser, not read off the bundle — a chunk name in the entry file may be a lazy import() specifier. Both halves are asserted so "lazy" cannot degrade into "never": one static import from app chrome had put 4.2 MB of JS plus a render-blocking 158 KB stylesheet on every page |
| cli.sandbox-doctor | iterion sandbox doctor [--strict] host/run pre-flight diagnosis | cli | covered-deterministic | TestRunSandboxDoctorStrictNoSandbox (pkg/cli/sandbox_strict_test.go), TestRunNetworkStrictChecks (pkg/cli/sandbox_strict_test.go) | |
| cli.studio | iterion studio boots the server and reports its port | cli | covered-deterministic | TestRunStudio_OnReady_RandomPort (pkg/cli/studio_test.go), TestIsLoopbackBindHost (pkg/cli/studio_bind_test.go) | |
| cli.server | iterion server boots the HTTP server without the studio launcher | cli | covered-deterministic | TestServerCommandBootsLocalModeAndShutsDownOnSignal (e2e/cli_server_boot_test.go), TestServerCommandFailsLoudlyOnBusyPort (e2e/cli_server_boot_test.go) | spawns the built binary as a subprocess and signals THAT child (not the test binary), so the daemon-SIGTERM aliasing of cli.dispatch is not reproduced |
| cli.runner | iterion runner boots a cloud runner pod from its config | cli | covered-deterministic | TestRunnerCommandRefusesLocalMode (e2e/cli_server_boot_test.go), TestRunnerCommandRefusesBrokenConfig (e2e/cli_server_boot_test.go) | the entry-point posture (mode gate + config loader) is what is deterministic; the claim/execute loop IS a NATS/Mongo/S3 consumer and is covered by cloud.runner-pod |
| cli.bots-templates | iterion bots templates lists the templates bots create accepts | cli | covered-deterministic | TestBotsTemplates_MatchesStudioGallery (pkg/cli/bots_create_test.go) | pins the CLI list against botscaffold.Templates(), the same source the studio gallery renders |
| bots.install | bot bundle install from a git URL or local path (layout validation, name override, existing-needs-force) | bots | covered-deterministic | TestInstall_SingleBundleRoot (pkg/botinstall/install_test.go), TestInstall_MalformedRejected (pkg/botinstall/install_test.go), TestInstall_ExistingNeedsForce (pkg/botinstall/install_test.go) | iterion bots install and the studio install endpoint are both thin wrappers over this core |
| plugins.lifecycle-run | iterion plugin run <name> <phase> executes a plugin's lifecycle command | plugins | covered-deterministic | TestRunLifecycle (pkg/plugin/lifecycle_test.go), pkg/server/plugins_routes_test.go | |
| cli.dispatch | iterion dispatch daemon boots from a config with the bot catalogue | cli | covered-deterministic | TestDispatchDaemonBootsServesAndStopsOnSignal (e2e/cli_dispatch_daemon_test.go), TestDispatchDaemonFailsLoudlyOnABusyPort (e2e/cli_dispatch_daemon_test.go), TestDispatchDaemonRejectsAnInvalidConfig (e2e/cli_dispatch_daemon_test.go) | in-process boot on a temp store + loopback port: asserts /healthz, the server-info advertisement, the started actor's state and the YAML it runs, the mounted native-board routes, then the SIGTERM clean exit and the non-zero exit on a bind failure |
| cli.migrate-to-cloud | iterion migrate to-cloud local store → Mongo/S3 | cli | covered-deterministic | TestMigrateToCloud_TransfersEveryVersionAndIsIdempotent (cmd/iterion/migrate_to_cloud_test.go), TestMigrateToCloud_DryRunWritesNothing (cmd/iterion/migrate_to_cloud_test.go), TestMigrateToCloud_MissingRunIsAnError (cmd/iterion/migrate_to_cloud_test.go), pkg/cli/migrate_orgs_test.go, pkg/cli/migrate_run_paths_test.go | the command's own walker between two real stores (every artifact version, --dry-run writes nothing, re-runs don't duplicate, an unknown run is an error), plus the sibling migrate orgs backfill and run-path rewrite. The S3 upload half is cloud.migrate-blobs |
| cli.mcp-server | iterion mcp operator MCP server (local_/remote_ tools) | cli | covered-deterministic | TestMCPServer_DetachedRunSurvivesServerExit (e2e/mcp_server_test.go), pkg/operatormcp/tools_local_test.go | |
| cli.supervise | iterion supervise attaches to a managed run or a raw claude session | cli | covered-deterministic | pkg/supervise/coordinator_test.go, pkg/supervise/transcript_test.go | |
| cli.remote | iterion remote typed subcommands against a cloud instance | cli | covered-deterministic | TestRemoteRunsLaunch_SendsSourceAndVars (pkg/cli/remote_test.go), TestRemoteRunsFollow_CursorAndTerminal (pkg/cli/remote_test.go) | |
| cli.remote-assistant-mission | `iterion remote runs mission start | get | list | stop` exposes the durable target-scoped mission API and JSON output | cli |
| cli.remote-login | browser loopback CLI-auth token mint + persistence | cli | covered-deterministic | TestResolveRemoteConfig_EnvMode (pkg/cli/remote_test.go), pkg/server/auth_routes_test.go | |
| cli.version | iterion version [--commit] | cli | covered-deterministic | cmd/iterion/version_test.go | |
| cli.bench-asymptote | iterion bench asymptote convergence benchmark | cli | covered-deterministic | TestBenchAsymptoteMeasuresTheConvergenceCurve (e2e/cli_bench_asymptote_test.go), TestBenchAsymptoteComparesTwoGroups (e2e/cli_bench_asymptote_test.go), TestBenchAsymptoteWritesTheMarkdownReport (e2e/cli_bench_asymptote_test.go), TestBenchAsymptoteRefusesAnIncompleteRequest (e2e/cli_bench_asymptote_test.go) | the command re-runs nothing — it derives the curve from what past runs persisted — so real stub-driven runs of a judge-in-a-loop fixture supply the same events an operator's runs would |
| backends.selection-explicit | node backend: / workflow default_backend: selects the delegate | backends | covered-deterministic | pkg/backend/model/resolve_backend_test.go | |
| backends.autodetect | credential probing picks a backend when none is declared | backends | covered-deterministic | pkg/backend/detect/detect_test.go, pkg/backend/model/resolve_backend_test.go | live variant: TestLive_Feat_BackendAutodetect |
| backends.claw | claw in-process client: generation, retry, cache observability | backends | covered-deterministic | pkg/backend/model/claw_backend_test.go, pkg/backend/model/generation_test.go | real-provider behaviour: covered-live by TestLive_Lite_ClawComprehensive |
| backends.claude-code | claude_code CLI delegate: append-system-prompt, setting sources | backends | covered-deterministic | pkg/backend/delegate/claude_code_cred_test.go | |
| backends.pi | pi delegate incl. the RPC session + embedded extension | backends | covered-deterministic | pkg/backend/delegate/pi_rpc_test.go, pkg/backend/delegate/pi_mcp_test.go | |
| backends.kimi | kimi CLI delegate through the generic CLI-agent seam | backends | covered-deterministic | pkg/backend/delegate/cliagent_test.go | |
| backends.grok | grok CLI delegate through the generic CLI-agent seam | backends | covered-deterministic | pkg/backend/delegate/grok_test.go | |
| backends.codex | Codex CLI delegate and supported DSL selection, including explicit native web_search | backends | covered-live | pkg/dsl/ir/compile_test.go, pkg/backend/delegate/delegate_test.go, pkg/backend/delegate/codex_web_search_test.go, TestLive_Feat_CodexWebSearch | a real hosted search cannot be exercised deterministically without a provider credential and network; the live test proves current URLs + readonly write refusal + WebSearch lifecycle, while deterministic tests pin live/disabled config, distinct WebSearch/Bash names, and incompatible-version refusal |
| backends.system-prompt-composition | per-backend SystemPromptMode (Standalone/Append/AuthoredBase) | backends | covered-deterministic | pkg/backend/delegate/delegate_test.go | |
| backends.reasoning-effort | reasoning_effort propagation and wire remapping | backends | covered-deterministic | pkg/backend/model/effort_test.go | |
| backends.ultracode | ultracode mode: xhigh + orchestration prerogative + C089 | backends | covered-deterministic | pkg/dsl/ir/ultracode_test.go, pkg/backend/model/effort_test.go | live behaviour on 4.8: TestLive_Feat_Ultracode |
| backends.retry-classification | transient vs fatal backend errors, retry + feedback | backends | covered-deterministic | pkg/backend/model/executor_retry_classification_test.go, pkg/backend/model/network_retry_test.go | |
| backends.cost-accounting | per-call cost/token accounting reaching the run totals | backends | covered-deterministic | TestMetricsEmitter_delegateFinished_costReachesRunTotals (pkg/runner/metrics_test.go), TestMetricsEmitter_clawCostIsNotCountedTwice (pkg/runner/metrics_test.go), TestRunBudgetOverrideCapsTheRun (e2e/cli_budget_override_test.go), pkg/backend/cost/cost_test.go, pkg/backend/model/executor_hooks_cost_test.go | the whole money path: the delegate prices a call, the executor carries it on the event, the emitter accumulates it into RunTotals (and does NOT double-charge claw, which emits both a step and a delegation total), and the accumulated cost is what trips the run's own budget cap |
| backends.oauth-forfait | subscription OAuth paths (Anthropic auth token, ChatGPT codex) | backends | covered-deterministic | pkg/backend/model/openai_forfait_ctx_test.go, pkg/secrets/subscription_oauth_test.go | credential resolution is deterministic; a real forfait call is excluded (needs a live subscription) |
| backends.bedrock-vertex-foundry | AWS Bedrock / GCP Vertex / Azure Foundry providers | backends | excluded | needs real cloud credentials for AWS/GCP/Azure; claw's SDK paths are unit-tested with mocked clients and iterion adds no logic of its own | |
| backends.model-quality | real model output quality / value-for-money grading | backends | covered-live | e2e/live_quality_test.go | the essence of the feature IS the live model; the judge panel is report-only by default |
| tools-mcp.tool-registry | tool registry + per-node allow lists (claw-native names) | tools-mcp | covered-deterministic | pkg/backend/tool/registry_test.go | |
| tools-mcp.claw-builtins | claw built-in tools (read/write/bash/glob/grep/edit/web_fetch) | tools-mcp | covered-deterministic | pkg/backend/tool/claw_builtins_test.go | live variant: TestLive_Lite_ClawBuiltinTools |
| tools-mcp.mcp-lifecycle | MCP server startup, health check and --skip-mcp-health | tools-mcp | covered-deterministic | pkg/backend/mcp/config_test.go, TestSkipMCPHealthFromEnv (pkg/cli/run_skipmcp_test.go) | |
| tools-mcp.mcp-transports | MCP stdio / streamable-http / legacy-sse transports | tools-mcp | covered-deterministic | pkg/backend/mcp/config_test.go, pkg/backend/delegate/pi_mcp_test.go | |
| tools-mcp.mcp-oauth | MCP OAuth broker / PKCE wiring | tools-mcp | covered-deterministic | pkg/backend/mcp/oauth_test.go | a real third-party OAuth consent flow is excluded (see integrations.third-party-oauth) |
| tools-mcp.strict-mcp-isolation | claude_code nodes get ONLY the resolved MCP set (--strict-mcp-config); host ~/.claude.json servers excluded, ITERION_CLAUDE_CODE_STRICT_MCP=0 opts back in | tools-mcp | covered-deterministic | TestClaudeCodeSpawn_StrictMCPConfigByDefault (pkg/backend/delegate/claude_code_strict_mcp_test.go), TestBuildArgs_StrictMCPConfig (pkg/backend/delegate/claudesdk/buildargs_test.go) | |
| tools-mcp.board-tools | board capability tools over stdio, HTTP and in-process claw | tools-mcp | covered-deterministic | TestBoardDispatcher_E2E_BotCreatesAndDispatches (e2e/board_dispatcher_test.go), pkg/backend/tool/claw_board_tools_test.go | |
| tools-mcp.ask-user | ask_user / ask_user_async / await_answers MCP surface | tools-mcp | covered-deterministic | pkg/askusermcp/http_test.go, TestAwaitAnswersReleasedByAnswer (e2e/async_interaction_test.go) | |
| tools-mcp.permission-gate | permission gate blocks/asks on a non-allow-listed tool call | tools-mcp | covered-deterministic | pkg/backend/model/permission_gate_test.go, pkg/backend/permission/permission_test.go | live variants: TestLive_Feat_Permission_Deny / _Ask |
| tools-mcp.permission-gate-external-hook | the gate holds on a CLI backend through its native PreToolUse hook (grok, kimi), deny-only | tools-mcp | covered-deterministic | pkg/backend/permissionhook/hook_test.go, pkg/backend/delegate/cliagent_test.go, pkg/dsl/ir/validate_fallbacks_test.go | live proof (filesystem sentinel, not model prose): TestLive_Feat_Permission_Deny_Grok / _Kimi |
| tools-mcp.secret-guard | secret placeholders never leak into tool input/output | tools-mcp | covered-deterministic | pkg/backend/model/hooks_secretguard_test.go, pkg/backend/model/secretguard_binding_hosts_test.go | |
| tools-mcp.computer-use | read_image / screenshot / computer_use dispatch | tools-mcp | covered-deterministic | pkg/backend/tool/claw_builtins_test.go | headless-unavailable propagation is the deterministic half; live use is TestLive_Lite_ClawReadImage |
| tools-mcp.tool-display | human-readable rendering of tool calls in console/report | tools-mcp | unit-only | pkg/backend/tooldisplay/display_test.go | pure formatter over an event payload; an e2e would assert string shape through the whole stack without adding risk coverage |
| observability.report-generation | report.md chronological rendering from events + artifacts | observability | covered-deterministic | TestReportRendersChronologicalRunReport (e2e/cli_report_test.go) | the artifact table lifts each artifact's conventional summary: field; node outputs without one are intentionally not inlined |
| observability.metrics | benchmark.CollectMetrics over a finished run | observability | covered-deterministic | TestCIFix_HappyPath (e2e/e2e_test.go), pkg/benchmark/benchmark_test.go | |
| observability.alerts | stall/budget/failure alerting + liveness heartbeat | observability | covered-deterministic | pkg/alert/manager_test.go | |
| observability.completion-webhooks | run-completion webhooks behind the SSRF guard | observability | covered-deterministic | pkg/notify/completion_test.go, pkg/secure/httpdial/httpdial_test.go | |
| observability.user-notifications | run-outcome web-push notifications with per-episode dedup | observability | covered-deterministic | pkg/usernotify/dispatcher_test.go | |
| observability.otlp-tracing | OTLP exporter wiring for runs/server | observability | covered-deterministic | pkg/cloud/tracing/tracing_test.go, pkg/benchmark/otlp_test.go | an end-to-end span assertion needs a real collector; setup/shutdown/no-endpoint paths are asserted here |
| observability.effective-model | the model that actually ran is recorded on delegate_started/delegate_finished, run.json nodes_served, and a model_drift event when it differs from the declared model: | observability | unit-only | TestDelegateModelReachesStore (pkg/backend/model/delegate_observability_test.go), TestRecordNodeServedRoundTrips (pkg/store/nodes_served_test.go) | CLI backends never emit llm_request.model, so these surfaces ARE the durable record; claw still also emits llm_request |
| observability.facade-routing | a node served through an Anthropic-shaped facade says so: nodes_served[<node>].fingerprint plus one model_served_via_facade event per node and facade, raised from the success path only, with no credential from the operator-supplied base URL in the recorded label | observability | unit-only | TestDelegateFacadeRoutingReachesStore (pkg/backend/model/delegate_observability_test.go), TestDelegateFacadeRoutingSilentOnFailure (pkg/backend/model/delegate_observability_test.go), TestProviderFingerprint_FacadeBaseURLCarriesNoCredential (pkg/backend/delegate/claude_code_cred_test.go) | the facade aliases the model id silently, so declared and effective AGREE and model_drift cannot fire — the fingerprint is the only evidence; exercising it live needs a real facade credential |
| sandbox.docker-driver | docker driver: container lifecycle, workspace bind-mount | sandbox | covered-live | e2e/live_feat_sandbox_net_test.go | needs a container runtime; the deterministic half is spec construction (pkg/sandbox/spec_test.go) |
| sandbox.spec-resolution | sandbox spec resolution (auto / devcontainer / image / none) | sandbox | covered-deterministic | pkg/sandbox/spec_test.go, pkg/sandbox/factory_test.go | |
| sandbox.network-policy | network: allowlist/denylist CONNECT proxy enforcement | sandbox | covered-deterministic | TestSandboxNetworkAllowlist_DeclarationStartsAnEnforcingProxy (pkg/runtime/sandbox_network_policy_test.go), TestSandboxNetworkDenylist_BlocksOnlyTheListedHosts (pkg/runtime/sandbox_network_policy_test.go), TestSandboxNetworkOpen_StartsNoProxy (pkg/runtime/sandbox_network_policy_test.go), pkg/sandbox/netproxy/proxy_test.go, e2e/live_feat_sandbox_net_test.go | the proxy runs on the HOST, so the whole wire is deterministic after all: the declaration compiled from real .bot source starts an enforcing proxy, an allowed host tunnels to a loopback echo server, a host outside the policy is refused AND emits the network_blocked event the operator sees, an un-tokened client is refused (not an open relay), and network: open / no block at all start no proxy. Forcing ResolveNetworkPolicy to open turns both policy tests red. Only the container-side half — the sandboxed process actually routing its egress through the injected HTTPS_PROXY — still needs the live layer |
| sandbox.host-state | host_state: auto / none mounts of ~/.iterion and ~/.claude | sandbox | covered-deterministic | TestApplyHostStateMounts_ClaudeConfigFile (pkg/runtime/sandbox_mounts_test.go), TestApplyHostStateMounts_HomeNestedBindParentsWritable (pkg/runtime/sandbox_mounts_test.go) | pkg/sandbox/spec_test.go only validates the enum string; the mounts themselves are asserted in the runtime tests cited here |
| sandbox.kubernetes-driver | kubernetes driver: capabilities, pod/network manifests, mounts, GC, orphan sweep | sandbox | covered-deterministic | TestPodManifestStructure (pkg/sandbox/kubernetes/driver_test.go), TestBuildNetworkPolicyShape (pkg/sandbox/kubernetes/driver_test.go), TestValidateSpecMatchesPrepare (pkg/sandbox/kubernetes/validate_test.go), pkg/sandbox/kubernetes/gc_test.go, pkg/sandbox/kubernetes/mounts_test.go | the manifest/spec/GC half is deterministic (57 unit tests, same shape as the docker driver); only the real pod lifecycle needs a cluster — see sandbox.kubernetes-pod-lifecycle |
| sandbox.kubernetes-pod-lifecycle | a k8s sandbox pod is actually created, executed against and torn down | sandbox | excluded | needs a live cluster + registry; no fake apiserver harness exists in this repo. The manifest/spec/GC half is covered — see sandbox.kubernetes-driver | |
| sandbox.buildkit | sandbox.build: via docker buildx on the local driver | sandbox | excluded | needs a Docker daemon with BuildKit; rejected by design on the k8s driver | |
| plugins.registry | plugin discovery, enable state, builtin embedding | plugins | covered-deterministic | pkg/plugin/plugin_test.go, pkg/plugin/inspect_test.go | |
| plugins.install | plugin install from a git URL or path (incl. bare skills repos) | plugins | covered-deterministic | pkg/plugin/install_test.go, pkg/plugin/skilllib_test.go | |
| plugins.rewriters | rewriter chain rewrites shell commands (rtk compression) | plugins | covered-deterministic | pkg/plugin/plugin_test.go, pkg/dsl/ir/compress_test.go | live end-to-end with the rtk binary: TestLive_Feat_Compress |
| plugins.contributed-skills | plugin skills/commands/agents mirrored into the workspace | plugins | covered-deterministic | TestMirrorInjectedPluginFiles_WritesEachKind (pkg/runtime/contributions_test.go) | |
| plugins.hooks-merge | plugin hook fragments idempotently merged into settings.json | plugins | covered-deterministic | TestMergePluginHooks_InjectIdempotentRemove (pkg/runtime/plugin_hooks_test.go), pkg/backend/model/settings_hooks_test.go | |
| plugins.private-source | team-scoped private plugin source binding (git + secret ref) | plugins | covered-deterministic | pkg/pluginsource/pluginsource_test.go | |
| server-api.run-console | run console REST: run detail, events, log, node sections | server-api | covered-deterministic | pkg/server/runs_test.go, pkg/runview/service_test.go | |
| server-api.run-launch | launch a run over HTTP with vars/overrides | server-api | covered-deterministic | pkg/runview/service_launch_budget_test.go, pkg/runview/service_launch_dispatch_fields_test.go, pkg/runview/service_launch_pause_test.go, pkg/runview/service_launch_operator_resume_test.go, pkg/server/runs_test.go | budget overrides (local + forwarded on the cloud path) and invalid durations, dispatch fields, the paused-launch and operator-resume shapes, and the HTTP surface itself |
| server-api.run-control | pause / cancel / resume / rewind / bump-loop / raise-budget | server-api | covered-deterministic | pkg/runview/service_commands_test.go | |
| server-api.assistant-missions | authenticated target-scoped mission create/reattach/list/get/stop; generic proposal allowlist, durable FS claims, one-shot rewind execution and receipt reconciliation | server-api | covered-deterministic | TestAssistantMissionCreateReattachesTerminalInvocationWithoutRenewal (pkg/server/assistant_mission_test.go), TestAssistantMissionCoordinatorExecutesOnlyPersistedRewindProposal (pkg/server/assistant_mission_test.go), TestFSStoreRejectsConcurrentTargetAndFencesClaims (pkg/assistantmission/fs_test.go), TestValidateMissionProposalRejectsWatchAndSourceMutation (pkg/server/assistant_mission_test.go) | Mongo shares the same store contract and adds unique partial indexes for invocation/active target |
| server-api.run-ws | live run WebSocket stream | server-api | covered-deterministic | pkg/server/runs_ws_test.go | |
| server-api.review-scope | review scope + diff since the previous human gate | server-api | covered-deterministic | pkg/server/runs_review_scope_test.go | |
| server-api.run-files | run workspace file browse/read/write with path containment | server-api | covered-deterministic | pkg/server/runs_files_test.go | |
| server-api.run-commits | per-run commit list + commit detail | server-api | covered-deterministic | pkg/server/runs_commits_test.go | |
| server-api.preview-proxy | run preview proxy behind the SSRF guard | server-api | covered-deterministic | pkg/server/runs_preview_test.go | |
| server-api.answer-human | answer a human gate / async question over HTTP | server-api | covered-deterministic | pkg/server/runs_answer_uploads_test.go | |
| server-api.queued-messages | operator chat messages queued into a running node's inbox | server-api | covered-deterministic | pkg/backend/model/inbox_test.go, pkg/server/runs_steer_test.go | |
| server-api.bots | bot catalog listing + per-bot metadata over HTTP | server-api | covered-deterministic | pkg/server/bots_routes_test.go, pkg/botregistry/registry_test.go | |
| server-api.board | native kanban REST (CRUD, transitions, labels, views) | server-api | covered-deterministic | pkg/dispatcher/native/http_test.go, pkg/dispatcher/native/store_test.go | |
| server-api.dispatcher-dashboard | dispatcher state/refresh/cancel HTTP surface | server-api | covered-deterministic | TestDispatcherE2E_HTTPSurface (e2e/dispatcher_test.go), pkg/dispatcher/http_test.go | |
| server-api.server-info | /api/server/info capability flags gate the SPA features | server-api | covered-deterministic | TestServerInfo (pkg/server/runs_uploads_test.go), TestServerInfo_SkillsEnabledLocal (pkg/server/local_skills_routes_test.go), TestMarketplace_ServerInfoFlag (pkg/server/marketplace_routes_test.go), TestMarketplace_ServerInfoFlagFalseWhenNil (pkg/server/marketplace_routes_test.go), pkg/server/backends_routes_test.go | each flag is asserted against the wiring that decides it — present when the store/feature is wired, false when it is nil |
| server-api.openapi | generated OpenAPI 3.1 spec matches the wired routes | server-api | covered-deterministic | pkg/server/openapi_test.go | |
| server-api.pipeline-board | /api/v1/pipeline-board/* control centre (columns, folding, actions, bulk ops) | server-api | covered-deterministic | TestPipelineBoardColumnBucketing (pkg/server/pipeline_boards_test.go), TestPipelineBoardFoldsDescendantsAndCollectsReviews (pkg/server/pipeline_boards_test.go), pkg/server/pipeline_board_actions_test.go | the REST layer behind studio-ui.pipelines |
| server-api.limits-cost | /api/v1/limits/cost + /override admin cost-cap surface | server-api | covered-deterministic | TestCostCapStatusDisabledByDefault (pkg/server/limits_test.go), TestCostCapStatusAndOverride (pkg/server/limits_test.go) | |
| server-api.backends-detect | /api/backends/detect credential auto-detection the toolbar reads | server-api | covered-deterministic | TestBackendsDetectRouteShape (pkg/server/backends_routes_test.go), TestBackendsDetect_NoSensitiveLeak (pkg/server/backends_routes_test.go) | the no-leak assertion is the one that matters: the endpoint reports availability, never a credential |
| server-api.effort-capabilities | /api/effort-capabilities per-backend/model effort lookup | server-api | covered-deterministic | TestEffortCapabilities_ClawOpus48 (pkg/server/effort_test.go), TestEffortCapabilities_UltracodeOnlyOnOpus48 (pkg/server/effort_test.go), TestEffortCapabilities_UnknownModel (pkg/server/effort_test.go) | also covers the sibling /api/resolve-effort. The ultracode-only-on-4.8 case is the one that would catch a capability table drifting |
| server-api.resolve-model | /api/resolve-model env-expands a node model: literal for the studio canvas | server-api | covered-deterministic | TestResolveModel_EnvSubstitutionUsesSetValue (pkg/server/effort_test.go), TestResolveModel_InvalidExpansionYieldsEmpty (pkg/server/effort_test.go), TestLooksLikeModelSpec (pkg/dsl/ir/validate_test.go) | the canvas used to replace ${VAR:-openai-codex/gpt-5.6-sol} with the word "env"; this endpoint returns the live spec (sol/terra/luna) and refuses expansions that don't look like a model so it cannot leak process env |
| server-api.editor-endpoints | /api/parse, /api/unparse, /api/validate DSL round-trip surface | server-api | covered-deterministic | TestUnparse_RoundTripIsSemanticallyStable (pkg/server/server_dsl_test.go), TestValidate_UnknownNodeReferenceIsC001 (pkg/server/server_dsl_test.go), TestParse_UnparseableSource (pkg/server/server_dsl_test.go) | round-trip fidelity (parse -> unparse -> parse is byte-identical) and the diagnostic CODE, not the message text |
| server-api.local-secrets | /api/local/secrets desktop/CLI secret surface | server-api | covered-deterministic | TestLocalSecrets_CreateListDeleteSealsAndNeverEchoesTheValue (pkg/server/local_secrets_routes_test.go), TestLocalSecrets_RenameOntoAnExistingNameIsRefused (pkg/server/local_secrets_routes_test.go) | the real routes on a New()-built local-mode server with the sealed store FILE as the oracle: create → the plaintext is absent from disk and from every response (only name/last4/fingerprint), list, re-post rotates in place without duplicating or widening the egress lock, delete removes it from both API and file; rename collision 409 leaves both records intact, unknown id 404. The previous citation (local_skills_routes_test.go) was a mis-citation — it holds no secrets coverage |
| server-api.run-shell | /api/ws/runs/{id}/shell post-mortem PTY shell in a preserved worktree | server-api | covered-deterministic | TestRunShell_Gates (pkg/server/runs_shell_test.go), TestShellEligible (pkg/server/runs_shell_test.go) | the gate (which runs may be shelled into) is the part that matters; the PTY itself is Unix-only with a Windows stub |
| cloud.oauth-connections | /api/me/oauth/* connect / authorize / refresh a subscription credential for cloud runs | cloud | covered-deterministic | TestOAuthConnections_SealsAndNeverEchoesTheCredential (pkg/server/oauth_routes_test.go) | the store is the oracle: the persisted payload must not contain the plaintext token, no response may echo it, and a second account is isolated from the first one's credential |
| server-api.static-spa | embedded studio SPA served from the binary | server-api | covered-deterministic | pkg/server/spa_test.go | |
| dispatcher.poll-dispatch | poll a tracker and dispatch one run per eligible issue | dispatcher | covered-deterministic | TestDispatcherE2E_DispatchAndRelease (e2e/dispatcher_test.go) | |
| dispatcher.retry | retry with backoff after a failed run, give up at max attempts | dispatcher | covered-deterministic | TestDispatcherE2E_RetryAfterFailure (e2e/dispatcher_test.go), TestDispatcherGivesUpAfterMaxAttempts (pkg/dispatcher/dispatcher_test.go) | |
| dispatcher.cancel | cancel an in-flight dispatched run | dispatcher | covered-deterministic | TestDispatcherE2E_CancelInFlight (e2e/dispatcher_test.go) | |
| dispatcher.state-transitions | issue state transitions around dispatch + revert on failure | dispatcher | covered-deterministic | TestDispatch_TransitionsToInProgress (pkg/dispatcher/loop_state_test.go), TestDispatcherE2E_RespectsTerminalStateChange (e2e/dispatcher_test.go) | |
| dispatcher.hooks | hook mechanics (script, env, timeout, failure, validation) + the before_remove hook FIRES | dispatcher | covered-deterministic | pkg/dispatcher/hooks_test.go, TestCleanupWorkspace_RunsBeforeRemoveBeforeDeletingDir (pkg/dispatcher/cleanup_workspace_test.go) | |
| dispatcher.hooks-lifecycle-firing | the after_create / before_run / after_run hooks actually FIRE at their lifecycle point | dispatcher | covered-deterministic | TestRunWorker_FiresLifecycleHooksInOrder (pkg/dispatcher/hooks_lifecycle_test.go), TestRunWorker_AfterRunFiresEvenWhenRunnerFails (pkg/dispatcher/hooks_lifecycle_test.go) | every phase appends to one shared order log, so the assertion is the ORDER of what actually fired — deleting any of the three Run() calls turns it red |
| dispatcher.per-ticket-bot | per-ticket bot override + assignee routing | dispatcher | covered-deterministic | TestBuildSpec_PerTicketBotSetsRouteKey (pkg/dispatcher/loop_bot_override_test.go) | |
| dispatcher.concurrency | per-state concurrency caps + claim conflict handling | dispatcher | covered-deterministic | TestDispatcherRespectsClaimConflict (pkg/dispatcher/dispatcher_test.go), TestDispatch_SlotCountedFromClaimTime (pkg/dispatcher/loop_setup_offload_test.go) | |
| dispatcher.cost-cap | daily cost cap gate blocks further dispatch | dispatcher | covered-deterministic | TestRefreshCostCapGatesWhenExceeded (pkg/dispatcher/cost_cap_test.go) | |
| dispatcher.workspace-cleanup | per-run workspace/worktree teardown policies | dispatcher | covered-deterministic | TestCleanupWorkspace_RemovesLinkedWorktreeRegistration (pkg/dispatcher/cleanup_workspace_test.go) | |
| dispatcher.pr-lookup-retry | board PR lookup outage, recovery, drain and terminal refusals | dispatcher | covered-deterministic | TestBoardDispatcher_PRLookupFailureRetriesAfterRecovery, TestBoardDispatcher_PRLookupDrainReturnsUnlaunchedCard, TestBoardDispatcher_PRLookupFailureHonoursAttemptCap, TestBoardDispatcher_PRLookupForkRemainsTerminal, TestBoardDispatcher_PRLookupForeignGrantRemainsTerminal (pkg/server/boarddispatch_pr_lookup_test.go) | real PR context resolution and dispatcher; durable retry ledger and no launch on refusal |
| dispatcher.native-tracker | native filesystem kanban tracker (board.json/issues/events) | dispatcher | covered-deterministic | pkg/dispatcher/native/store_test.go, TestNativeStore_Conformance (pkg/dispatcher/boardmongo/conformance_test.go) | |
| dispatcher.github-tracker | GitHub Issues tracker adapter | dispatcher | covered-deterministic | pkg/dispatcher/tracker/github_test.go | real GitHub API is stubbed at the HTTP boundary |
| dispatcher.forgejo-tracker | Forgejo/Gitea tracker adapter | dispatcher | covered-deterministic | pkg/dispatcher/tracker/forgejo_test.go | real Forgejo API is stubbed at the HTTP boundary |
| triggers.subscription-registry | subscription CRUD through the REST surface | triggers | covered-deterministic | pkg/server/triggers_routes_test.go | matching/mode semantics: pkg/trigger/subscription_test.go |
| triggers.subscription-query | subscription query by repo / by bot (tenant-scoped; by-repo also returns the workspace-wide ones) | triggers | covered-deterministic | TestSubscriptionStoreQueries (pkg/trigger/store_query_test.go) | |
| triggers.evaluator | evaluator matches an event to subscriptions and launches | triggers | covered-deterministic | pkg/trigger/evaluator_test.go | |
| triggers.board-source | board transition promotes a card / direct-launches a bot | triggers | covered-deterministic | pkg/trigger/board_integration_test.go, TestIssueTriageTrigger_E2E_ConsumeAndLaunch (e2e/issue_triage_trigger_test.go) | |
| triggers.consume-labels | consume_labels strips the matcher labels atomically pre-launch | triggers | covered-deterministic | pkg/trigger/consume_labels_test.go, TestIssueTriageTrigger_E2E_ConsumeAndLaunch (e2e/issue_triage_trigger_test.go) | |
| triggers.run-outcome | run completion events chain the next bot | triggers | covered-deterministic | TestEvaluatorRunCompletionChaining (pkg/trigger/evaluator_test.go), pkg/runview/trigger_emit_test.go, pkg/trigger/runoutcome_test.go | the chaining itself (a finished run's event matches a direct-mode subscription and launches the next bot), the emitter that publishes it from runview, and the envelope/episode-id builder shared with the runner |
| triggers.assistant-run-watch | durable target lifecycle → safe assistant diagnostic turns until Done or explicit Stop | triggers | covered-deterministic | pkg/runwatch/fs_test.go, pkg/server/assistant_run_watch_test.go, pkg/server/assistant_run_watch_autoarm_test.go, studio runChat/action-request tests | pins episode dedup/CAS lease recovery, persistence across recoverable assistant failures, repeated target outcomes, cancellations and old pending episodes, chat-only wake eligibility (ask_user and paused_operator excluded), host-selected assistant binding and host-event transcript semantics. A live LLM outcome→diagnostic smoke remains manual; Mongo/NATS use the same store/claim and outcome-bus contracts |
| triggers.scheduler | schedule-kind subscriptions tick on their cron | triggers | covered-deterministic | pkg/trigger/scheduler_test.go, pkg/trigger/scheduler_gate_test.go | |
| triggers.eventbus-inproc | in-process event bus delivery | triggers | covered-deterministic | pkg/eventbus/inproc_test.go | |
| triggers.eventbus-nats | NATS event bus on the separate ITERION_EVENTS stream | triggers | covered-deterministic | pkg/eventbus/nats_test.go | needs a NATS endpoint; skips cleanly without one |
| triggers.cloudsched | cloud recurring-bot scheduler with a multi-replica CAS ticker | triggers | covered-deterministic | pkg/cloudsched/cloudsched_test.go | |
| triggers.retry-policy | usage_window retry policy resolution across all layers | triggers | covered-deterministic | pkg/retrypolicy/policy_test.go | |
| webhooks.gitlab | GitLab MR open/reopen + /revi note re-review launches | webhooks | covered-deterministic | pkg/server/webhooks_gitlab_test.go, pkg/webhooks/webhooks_test.go | |
| webhooks.github | GitHub PR events launch the configured bot | webhooks | covered-deterministic | pkg/server/webhooks_github_test.go | |
| webhooks.forgejo | Forgejo/Gitea PR events launch the configured bot | webhooks | covered-deterministic | pkg/server/webhooks_forgejo_test.go | |
| webhooks.generic | generic JSON inbound trigger | webhooks | covered-deterministic | TestGenericWebhook_HappyPath_VarsPrecedence (pkg/server/webhooks_generic_test.go), TestGenericWebhook_MissingBotIs400 (pkg/server/webhooks_generic_test.go), TestGenericWebhook_BodyHashIdempotency (pkg/server/webhooks_generic_test.go), pkg/webhooks/generic/generic_test.go, pkg/webhooks/router_test.go | the endpoint itself: var precedence on launch, 400 without a bot, body-hash idempotency, oversized-var refusal; the parser in pkg/webhooks/generic and the command routing in router_test.go |
| webhooks.rerequest-review | forge-native "Re-request review" on the bot reviewer relaunches the review (repeatable per click, bot-actor echo filtered, publish self-assigns the GitLab reviewer) | webhooks | covered-deterministic | TestGitLabWebhook_ReRequestReviewLaunches (pkg/server/webhooks_gitlab_test.go), TestGitHubWebhook_ReviewRequestedLaunches (pkg/server/webhooks_github_test.go), TestGitLabAddSelfAsPullReviewer (pkg/forge/gitlab/reviews_test.go), TestForgePublishReview_SelfAssignsReviewer (pkg/server/forge_publish_gate_test.go) | gate opt-out releasing forced review_on_sync: TestProvision_GateDisabledPin* (pkg/forge/orchestrator_botrules_test.go) |
| webhooks.auth | iwh_ token / HMAC admission, rate limits, idempotent delivery | webhooks | covered-deterministic | pkg/webhooks/match_test.go, pkg/server/webhooks_routes_test.go | |
| webhooks.authz-outage | a forge authorization outage is acknowledged, audited as launch_error, and launches no bot | webhooks | covered-deterministic | TestWebhookAuthzErrorsAreAcknowledgedWithoutLaunching (pkg/server/webhooks_authz_error_test.go) | Six real handler lanes; even an authorized=true result accompanied by an error refuses execution. |
| webhooks.handoff | produces/consumes hand-off stamps the next run's launch vars | webhooks | covered-deterministic | pkg/server/webhooks_handoff_test.go, bots/handoff_declarations_test.go | |
| webhooks.merge-gate | Revi posts a deterministic revi/review commit status | webhooks | covered-deterministic | TestForgePublishReview_GatePostedEvenWhenTheReviewFails (pkg/server/forge_publish_test.go), pkg/server/forge_gate_relaunch_test.go, pkg/server/forge_gate_autofix_test.go | pkg/forge/reviews_test.go is a PR-URL parser + markdown folder — orthogonal to the gate |
| forge.connections | forge connection / repo-integration / OAuth-app stores | forge | covered-deterministic | pkg/forge/oauth_app_store_test.go | |
| forge.admin-clients | per-provider admin clients (repos, hooks, permissions) | forge | covered-deterministic | pkg/forge/forgelive_test.go, pkg/forge/command_map_test.go | provider APIs stubbed at the HTTP boundary |
| forge.github-app | GitHub App manifest flow + installation-token minting | forge | covered-deterministic | pkg/server/forge_app_resolution_test.go | the interactive App-creation consent screen is excluded (needs a real GitHub org) |
| forge.bot-avatar | the iterion-bot avatar on a connection's account — auto on a GitLab bot identity at connect, explicit apply (force on an unflagged account), refusals on OAuth / GitHub, /brand/ public route | forge | covered-deterministic | pkg/server/forge_avatar_routes_test.go, pkg/server/brand_routes_test.go, TestSetAvatar_MultipartShape (pkg/forge/gitlab/client_test.go), TestSetAvatar_JSONBase64 (pkg/forge/forgejo/client_test.go), pkg/brand/brand_test.go | TestLiveGitLabAvatar (pkg/forge/forgelive_test.go, tag forgelive) proved on 2026-09-05 that a project-token bot user takes the avatar on GitLab 19.2; Forgejo's endpoint is swagger-verified, not live-tested |
| forge.orchestrator | provision/deprovision: webhook + secret + bindings + schedules | forge | covered-deterministic | pkg/forge/orchestrator_test.go | |
| forge.token-refresh | background token refresh worker | forge | covered-deterministic | pkg/forge/refresh_test.go | |
| forge.config-share | shared-config read/write under a synthetic share grant | forge | covered-deterministic | pkg/configshare/configshare_test.go | |
| cloud.auth-session | login / logout / refresh / session cookies + JWT claims | cloud | covered-deterministic | pkg/auth/service_test.go, pkg/server/auth_routes_test.go | |
| cloud.run-login-return | signed-out run links offer sign-in, then restore the full run URL | studio | covered-deterministic | studio/src/tests/runSignIn.test.tsx, studio/src/auth/returnTo.test.ts, studio/src/views/auth/tests/ForcedPasswordChange.test.tsx | real App routes + AuthProvider + Login with HTTP and destination chrome stubbed; password retry, existing session, restricted account, query/hash, forced password rotation and unsafe return paths covered |
| cloud.sso-oidc | OIDC SSO providers + domain verification | cloud | covered-deterministic | pkg/auth/oidc/generic_test.go, pkg/server/org_sso_routes_test.go | a real IdP consent round-trip is excluded (see integrations.third-party-oauth) |
| cloud.password-reset | password reset request/confirm + mail delivery fallback | cloud | covered-deterministic | pkg/auth/password_reset_test.go, pkg/mail/mail_test.go | |
| cloud.orgs-teams | two-level tenancy: org membership, team scoping, context switch | cloud | covered-deterministic | pkg/identity/team_test.go, pkg/server/auth_teams_test.go | |
| cloud.invitations | team/org invitations: create, lookup, accept | cloud | covered-deterministic | TestInvitations_AdminIssuesAnonymousLookupAcceptGrantsMembership (pkg/server/invitations_e2e_test.go), TestInvitations_DeletingAPendingInviteKillsItsToken (pkg/server/invitations_e2e_test.go), TestInvitationFlow (pkg/auth/service_test.go) | the whole grant path over real HTTP: a plain member is refused (403, nothing created), an admin's token is looked up ANONYMOUSLY (the invitee has no session yet), accepting creates the membership — proven by the outsider's 403 on the team turning into a 200 that lists them at the invited role — and the token is single-use, login-gated, and dead once the admin deletes the invitation. The previous citation (auth_views_test.go) holds only an org-tree test |
| cloud.pat | personal access tokens (iap_ bearers) | cloud | covered-deterministic | TestPATBearer_AuthenticatesProgrammaticClientsThroughTheRealServer (pkg/server/pat_bearer_e2e_test.go), TestPATBearer_DiesWithTheMembershipItResolvesThrough (pkg/server/pat_bearer_e2e_test.go), pkg/server/pat_routes_test.go, pkg/pat/pat_test.go | the promise is programmatic access, and it lives in the auth MIDDLEWARE: the token is minted over real HTTP and then presented as a bearer to a server built by the real New() wiring — identity + pinned team served back, a protected endpoint reachable, cross-team read 403, unknown iap_ failing closed (never falling through to JWT parsing), revoke and membership removal each turning the next call into a 401 while the JWT session survives. Deleting the iap_ branch from requireAuth leaves the store and handler tests green and turns these red |
| cloud.audit-log | tenant + platform audit log of control-plane mutations | cloud | covered-deterministic | TestAuditEndToEnd (pkg/server/audit_routes_test.go), pkg/audit/audit_test.go | a control-plane mutation through the routes leaves the row an operator reads back on /api/teams/{id}/audit; the store half (TTL, filters) in pkg/audit |
| cloud.quotas | per-org monthly run/cost counters gate the launch | cloud | covered-deterministic | pkg/orgusage/orgusage_test.go, pkg/server/launch_gate_test.go | |
| cloud.usage-cap-runtime | usage-cap percentages retunable at runtime via the super-admin API: env stays the default, a DB record overrides it on BOTH enforcement points within the resolver TTL, /healthz echoes the effective value, non-admin and invalid input rejected, update audited | cloud | covered-deterministic | TestAdminUsageCaps_EnvFallback (pkg/server/admin_settings_routes_test.go), TestAdminUsageCaps_UpdateOverridesEnvAndAudits (pkg/server/admin_settings_routes_test.go), TestAdminUsageCaps_NonAdminRejected (pkg/server/admin_settings_routes_test.go), TestAdminUsageCaps_InvalidValuesRejected (pkg/server/admin_settings_routes_test.go), TestUsageCapPreflight_RuntimeSettingsChangeIsLive (pkg/runner/usage_cap_test.go), TestResolver_UpdatePropagatesWithinTTL (pkg/usagecap/settings_test.go) | the server half runs over real HTTP through the production auth middleware; the runner half proves the tightened cap refuses the next claim on the SAME Runner value (no restart); the resolver half pins the TTL as the propagation bound with a fake clock (ADR-090) |
| cloud.usage-cap-trust-window | a stored usage reading is trusted for a bounded time (ITERION_USAGE_CAP_TRUST_WINDOW, default 3h) after it was observed, not until its reset instant: a pre-reset reading cannot lock a credential out through a reset the provider made early, a recent one still parks, and a malformed window refuses to start | cloud | covered-deterministic | TestReadingFresh_TrustWindowBoundsADatedReading (pkg/usagecap/usagecap_test.go), TestPreflight_StaleDatedReadingDoesNotBlock (pkg/usagecap/usagecap_test.go), TestTrustFromEnv (pkg/usagecap/usagecap_test.go), TestUsageCapPreflight_StaleReadingDoesNotRefuseAdmission (pkg/runner/usage_cap_trust_test.go) | the runner half replays the production shape of #690 (0.99 on seven_day, reset four days out, observed 17h37m earlier) at the admission gate that refused every claude_code run; a run refused there never fires the hook that would refresh the reading, which is why the bound is on AGE |
| cloud.usage-readings-clear | a super-admin forgets ONE credential's stored usage readings by fingerprint (DELETE /api/admin/usage-readings/{fingerprint}, iterion remote admin usage-readings clear): every key the credential was metered under, nothing else, audited with the count, idempotent, non-admin refused | cloud | covered-deterministic | TestAdminUsageReadings_ClearForgetsOneCredential (pkg/server/admin_usage_readings_routes_test.go), TestAdminUsageReadings_NonAdminRejected (pkg/server/admin_usage_readings_routes_test.go), TestMemStore_Conformance (pkg/usagecap/store_conformance_test.go), TestMongoStore_Conformance (pkg/usagecap/store_conformance_test.go) | over real HTTP through the production auth middleware; the store half is one conformance suite run against both twins (the Mongo one under the mongo-conformance job) |
| cloud.usage-retry-skipped-credential | the usage-window retry arms on the EARLIER of the failed credential's reset and the reopening of the earliest credential the launch's walk passed over (run.skipped_cred_reopens_at, reset_source: skipped_credential), re-stamped on every resume — EXCEPT on the last attempt the budget allows, which is reserved for the failed credential's own reset when that reset is still ahead and inside max_wait (reset_source: <evidence>+last_attempt_pinned) | cloud | covered-deterministic | TestUsageWindowRetryAt_ArmsOnTheEarliestReopeningCredential (pkg/runner/usage_retry_skipped_test.go), TestArmUsageWindowRetry_ReadsTheSkippedCredentialFromTheRun (pkg/runner/usage_retry_skipped_test.go), TestUsageWindowRetryAt_BudgetOutlastsTheAuthoritativeWall (pkg/runner/usage_retry_budget_test.go), TestUsageWindowRetryAt_SpeculativeWakeSurvivesWhileTheBudgetCanSpareIt (pkg/runner/usage_retry_budget_test.go), TestArmUsageWindowRetry_ReadsTheSpentAttemptsFromTheRun (pkg/runner/usage_retry_budget_test.go), TestRunRetry_SpentAttemptsAreReadableFromTheRunDocument (pkg/store/mongo/runs_retry_test.go), TestResolve_ReportsWhenTheSkippedForfaitReopens (pkg/server/cloudpublisher/skipped_reopens_test.go), TestApiKeyUsable_ReportsTheEarliestReopening (pkg/server/cloudpublisher/skipped_reopens_test.go) | the production shape of #684: a team key refused on its five-hour window (reopens 16:40Z) and a platform forfait walled until Monday — armed at 16:41Z, not Monday; #922 is the budget half — both clocks spend one max_attempts purse, so five wakes on a five-hour cycle used to retire a run six days before a seven-day wall fell; the store field rides the CredFingerprintMeter conformance row |
| cloud.credential-ceiling-counting | a key's max_concurrent_runs counts only alive runs whose RESOLVED routes can spend it (the stamp is narrowed through model.EffectiveProviders) and which are executing a model node (run.llm_idle_since toggled by the runner at model-node boundaries, cleared by every re-stamp) | cloud | covered-deterministic | TestResolve_StampsOnlyTheSpendableFingerprints (pkg/server/cloudpublisher/stamp_narrowing_test.go), TestCredSlotTracker_IdleBetweenModelNodes (pkg/runner/cred_slot_test.go), TestCredSlotObserver_WiresWorkflowAndStore (pkg/runner/cred_slot_test.go), TestConformance_FilesystemShared (pkg/store/conformance_test.go) | the two production shapes of #661: a rite pinned to the forfait holding a facade-key slot (next launch died AUTH_FAILED), and a finished agent node sitting in a sixty-minute tool-only gate; the count filter is the CredFingerprintMeter row of the shared store conformance, run on both twins |
| cloud.credential-observability | the run API exposes the credential stamp (cred_fingerprints, llm_idle_since, skipped_cred_reopens_at), the key views report alive_runs from the SAME count the ceiling asks, and last_used_at is bumped under the run's tenant for a tenant's own key and across tenants for a platform/pool key | cloud | covered-deterministic | TestHeaderFromRun_ExposesTheCredentialStamp (pkg/runview/snapshot_cred_test.go), TestListApiKeys_ReportsAliveRuns (pkg/server/byok_alive_runs_test.go), TestMarkCredFingerprintsUsed_ScopesByTier (pkg/runner/loop_spend_scope_test.go), TestMemoryApiKey_MarkFingerprintUsed_ScopesToTheContextTenant (pkg/secrets/byok_fp_scope_test.go), TestMongoApiKey_MarkFingerprintUsed_ScopesToTheContextTenant (pkg/secrets/byok_mongo_fp_scope_test.go) | #659 pt 3; the Mongo twin of the scoping runs under the mongo-conformance job |
| cloud.queue-dispatch | NATS work queue: enqueue, claim, schema-version handling | cloud | covered-deterministic | pkg/queue/types_test.go, TestSchemaVersionMismatchIsATypedTransientError (pkg/queue/schema_version_transient_test.go) | |
| cloud.runner-pod | runner claims a queued run, executes, reports status back | cloud | covered-deterministic | pkg/runner/loop_test.go | |
| cloud.runner-credentials | credential injection + sealing into a runner pod | cloud | covered-deterministic | pkg/runner/git_credentials_test.go, pkg/secrets/run_secrets_test.go | |
| cloud.probes-readiness | /readyz gates on CRITICAL dependencies only (a non-critical blip stays 200 degraded), /healthz never follows a dependency | cloud | covered-deterministic | TestReadyzCriticalVsDegraded (pkg/server/health_test.go), TestHealthzAlwaysOK (pkg/server/health_test.go) | every replica pings the same backends, so a critical check on a shared one converts a blip into a fleet-wide outage — the split is the promise, and the table drives all three outcomes through the real mux |
| cloud.probes-resilience | a dependency ping that panics, hangs, or is already in flight cannot kill the pod, hang the probe, or evict a healthy one | cloud | covered-deterministic | TestReadyzSurvivesAPanickingCheck (pkg/server/health_test.go), TestReadyzDoesNotHangOnAContextIgnoringCheck (pkg/server/health_test.go), TestReadyzDoesNotRelaunchAWedgedCheck (pkg/server/health_test.go), TestReadyzConcurrentProbesShareOneAnswer (pkg/server/health_test.go) | the probe runs pings concurrently in their own goroutines, i.e. outside net/http's recover and outside the request's lifetime — each test pins one way that turned into an un-drained exit (panic → process death, hang → wedged handler + blocked Shutdown, relaunch → goroutine leak → OOMKill) or into evicting a healthy pod (overlapping probes). All four were found by adversarial review, not by the original tests |
| cloud.probes-lame-duck | SIGTERM flips /readyz to 503 draining while the listener still accepts, for ITERION_SHUTDOWN_DELAY, with /healthz still 200 | cloud | covered-deterministic | TestServerCommandBootsLocalModeAndShutsDownOnSignal (e2e/cli_server_boot_test.go), TestReadyzDrainingIs503AndSkipsChecks (pkg/server/health_test.go), TestBeginDrainWaitsButRespectsContext (pkg/server/health_test.go) | the e2e half polls the REAL binary between SIGTERM and exit — the only place the window is observable; drop the draining branch and it fails within the 5s window (verified by mutation) |
| cloud.probes-runner | runner /healthz tells a busy consume loop from a wedged one; /readyz reports the whole lame-duck drain | cloud | covered-deterministic | TestHealthAliveDistinguishesBusyFromWedged (pkg/runner/health_test.go), TestShutdown_CompleteMode_LetsRunFinish (pkg/runner/loop_test.go), TestShutdown_NoInFlight_NoOp (pkg/runner/loop_test.go) | replaces a tcpSocket probe that could not distinguish them; the Shutdown tests are the WIRING half (flag actually flipped at drain start), the health tests the policy half |
| cloud.credential-pool | pledge/lease broker as the fourth credential tier | cloud | covered-deterministic | pkg/credpool/broker_test.go, pkg/server/cloudpublisher/credpool_tier_test.go, pkg/server/credpool_routes_test.go | |
| cloud.secrets-sealing | AES-256-GCM sealing + BYOK/generic/bot-binding domains | cloud | covered-deterministic | pkg/secrets/sealer_test.go, pkg/secrets/run_secrets_test.go | |
| cloud.bot-sources | team-authored bot bundles (fork a catalog bot, author a new one) | cloud | covered-deterministic | pkg/botsource/botsource_test.go, pkg/server/bot_sources_routes_test.go | |
| cloud.platform-bot-overrides | platform bot overrides: super-admin push/delete under the platform: sentinel, resolution team → platform → baked at every launch surface, digest-audited, size-capped | cloud | covered-deterministic | TestAdminBots_PlatformOverrideLifecycle (pkg/server/admin_bots_routes_test.go), TestAdminBots_SuperAdminOnly (pkg/server/admin_bots_routes_test.go), TestAdminBots_SizeLimits (pkg/server/admin_bots_routes_test.go), TestEffectiveEntries_PlatformOverlay (pkg/server/platform_settings_test.go), TestBotResolutionSweep_NoRawRegistryReads (pkg/server/bot_resolver_sweep_test.go) | the sweep test is what keeps NEW pkg/server code from bypassing the resolver — the class stays closed |
| cloud.platform-bot-runner-rebuild | a stored-bot run rebuilds its bundle from the DB ref on the runner, verifying the version (drift/missing row fail loudly, never a stale-baked fallback) | cloud | covered-deterministic | TestMaterializeBotBundle (pkg/runner/botbundle_test.go), TestValidate_DualAcceptWindow (pkg/queue/types_test.go) | the dual-accept test pins the v8/v9 rolling-deploy guarantee |
| cloud.platform-bot-roles | webhook role→bot bindings runtime-mutable (bot_roles settings family; consts stay defaults) | cloud | covered-deterministic | TestRoleBots_DefaultsAndOverride (pkg/server/platform_settings_test.go), TestAdminBotRoles_PutMergeAndOrigin (pkg/server/platform_settings_test.go), TestBotRoleSweep_ConstsOnlyInDefaults (pkg/server/bot_resolver_sweep_test.go) | |
| cloud.platform-sandbox-image | sandbox: auto default image runtime-mutable, resolved at publish and pinned on the RunMessage | cloud | covered-deterministic | TestAdminSandboxSettings (pkg/server/platform_settings_test.go), pkg/platformcfg/platformcfg_test.go | the runner consumes msg.SandboxImage via runtime.WithSandboxDefaultImage; publish-time pinning is what makes a redelivery rerun identically |
| cloud.marketplace | hosted registry entries (bot + plugin), moderation, visibility | cloud | covered-deterministic | TestMarketplace_SubmitListGetInstall (pkg/server/marketplace_routes_test.go), TestMarketplace_InstallThenUninstall (pkg/server/marketplace_routes_test.go), pkg/marketplace/moderation_test.go, pkg/marketplace/visibility_test.go, pkg/marketplace/jsonstore_test.go, pkg/cli/marketplace_test.go | submit → list → get → install/uninstall over the REST surface (plus the disabled/404/malformed-bundle refusals), with moderation status and visibility scope asserted at store level and the CLI half in pkg/cli |
| cloud.memory-store | cloud MemoryStore adapter + quota | cloud | covered-deterministic | pkg/knowledge/scope_test.go, pkg/memory/space_test.go, pkg/server/memory_routes_test.go | |
| cloud.dlq | dead-letter queue show/replay/delete (admin REST surface) | cloud | covered-deterministic | TestDLQAdmin_ListPeekReplayLeavesAuditTrail (pkg/server/dlq_admin_routes_test.go), TestDLQAdmin_NonSuperAdminCannotReplayOrDiscard (pkg/server/dlq_admin_routes_test.go) | the endpoints behind iterion remote admin dlq: super-admin gate (an unprivileged caller never reaches the queue), list/peek/replay/discard state transitions, the platform audit row naming the replayed run, and 400/404/502 mapping. Driven through the real New()/routes()/auth middleware with an in-process QueueBackend double (the seam added for it); the broker-side half is cloud.dlq-jetstream |
| cloud.dlq-jetstream | DLQ transport semantics: park with headers, inspect verbatim payload, replay/discard, report depth | cloud | covered-deterministic | TestSchemaRolloutMixedFleet (pkg/runner/schema_rollout_integration_test.go) | CI's nats-conformance job supplies a real JetStream service container and verifies delayed redelivery, final park headers/reason, ListDLQ, PeekDLQ byte identity, RepublishDLQ/DiscardDLQ and DLQDepth. |
| cloud.lock-delivery-exhaustion | a delivery that cannot take the run lock reaches the DLQ at MaxDeliver without changing the run | cloud | covered-deterministic | TestHeldLockFinalDeliveryArchivesOnNATS (pkg/runner/lock_delivery_test.go), TestHeldLockDoesNotSpendFinalDeliverySilently (pkg/runner/lock_delivery_test.go), TestHeldLockArchiveFailureLeavesDurableEvidence (pkg/runner/lock_delivery_test.go), TestLockFailureReasonSeparatesHeldFromUnconfirmed (pkg/runner/lock_delivery_test.go), TestExhaustedPublishDeadlineStillRecordsTheAuditRow (pkg/runner/lock_delivery_test.go) | Real JetStream payload round trip in the NATS one (CI's nats-conformance service container). The pure-Go ones cover the failure halves it cannot reach: an archive failure stays visible on the run timeline, the archived reason separates CONFIRMED contention from a lock error that leaves ownership unconfirmed, and a publish deadline exhausted by a broker outage still records run_delivery_exhausted — the only confirmed trail when the DLQ copy is not. Every one asserts the run doc is untouched. |
| cloud.migrate-blobs | migrate to-cloud artifact/blob upload to S3 | cloud | covered-deterministic | TestMigrateToCloud_TransfersEveryVersionAndIsIdempotent (cmd/iterion/migrate_to_cloud_test.go), TestMigrateToCloud_DryRunWritesNothing (cmd/iterion/migrate_to_cloud_test.go), TestS3Client_ArtifactUploadRoundTripAndLayout (pkg/store/blob/s3_roundtrip_test.go), TestS3Client_DeleteRunSweepsOnlyThatRunsPrefix (pkg/store/blob/s3_roundtrip_test.go) | both halves of the one-way door: the walker (migrateRun between two real stores — every artifact VERSION, events, interactions, --dry-run writes nothing, re-runs don't duplicate) and the S3 upload driven by the REAL AWS SDK against an in-process path-style gateway (canonical key layout on the wire, byte round-trip, ErrArtifactNotFound mapping, prefix-scoped DeleteRun). Not covered: the Mongo store's own WriteArtifact→blob glue, which needs a live Mongo (mongo-conformance CI job) |
| cloud.desktop-exchange | desktop auth token exchange endpoint | cloud | covered-deterministic | pkg/server/desktop_sso_test.go | |
| cloud.valkey-state | ephemeral cross-replica state (OAuth/CSRF, board tokens, rate buckets) | cloud | covered-deterministic | TestValkeyCrossReplica_ForgeOAuthStartedOnACompletesOnB (pkg/server/valkey_cross_replica_test.go), TestValkeyCrossReplica_BoardTokenMintedOnAAuthorizesWriteOnB (pkg/server/valkey_cross_replica_test.go), TestValkeyCrossReplica_LoginRateBudgetIsSharedNotPerPod (pkg/server/valkey_cross_replica_test.go), pkg/server/valkey_stores_test.go | two servers built through the real New() wiring over ONE miniredis: each flow starts on replica A and finishes on replica B (OAuth connect → callback creates the connection, board token → board write, login burst → 429). Give each replica its own Valkey and all three fail. store-level TTL/GETDEL/write-failure surfacing in valkey_stores_test.go. Not covered: valkey.New's Sentinel-HA topology (needs a real Sentinel quorum; the single-node client is what miniredis speaks) |
| bots.catalog-universality | catalog bots stay repo- and stack-agnostic | bots | covered-deterministic | bots/catalog_universality_test.go | |
| cloud.bot-bundle-snapshot | cloud launch and resume freeze resources plus transitive subbots; a divergent runner catalog cannot replace the snapshot | cloud | covered-deterministic | TestSnapshotCatalogLaunchAndResume (pkg/server/bot_snapshot_test.go), TestSnapshotChildUsesServerAuthorityAndRefusesMissingChild (pkg/server/bot_snapshot_test.go), TestSnapshotRunnerIgnoresDivergentCatalog (pkg/runner/bot_snapshot_test.go), TestSnapshotRunnerFetchesAndChecksStoredBytes (pkg/runner/bot_snapshot_test.go), TestSnapshotOffloadIsImmutableAcrossResume (pkg/server/cloudpublisher/bundle_snapshot_test.go), TestSnapshotPromptsTravelInCompiledPayload (pkg/server/cloudpublisher/bundle_snapshot_test.go) | real child execution against conflicting runner catalog; object transport tested with fake blob backend; live coordinated rollout not covered |
| bots.catalog-compiles | every catalog bot parses + compiles clean | bots | covered-deterministic | bots/catalog_parse_compile_test.go, bots/catalog_typing_test.go | |
| bots.catalog-freshness | the generated bot-catalog skill matches the manifests | bots | covered-deterministic | bots/catalog_freshness_test.go | |
| bots.golden-replay | bot golden replay revalidates frozen LLM outputs | bots | covered-deterministic | TestGoldens (pkg/botreplay/goldens_test.go) | |
| bots.feature-dev | feature-dev (Featurly): campaign + gate convergence | bots | covered-deterministic | TestVibeFeatureDev_ConvergesFirstPass (e2e/feature_dev_test.go), TestVibeFeatureDev_RedVerifyRoutesBackToCampaign (e2e/feature_dev_test.go) | |
| bots.whole-improve-loop | whole-improve-loop (Willy) | bots | covered-deterministic | TestWholeImproveLoop_ContinuesUntilComplete (e2e/whole_improve_loop_test.go) | |
| bots.branch-improve-loop | branch-improve-loop (Billy) | bots | covered-deterministic | TestBranchImproveLoop_ContinuesUntilClean (e2e/branch_improve_loop_test.go) | |
| bots.docs-refresh | docs-refresh (Doki) | bots | covered-deterministic | TestDocsRefresh_ConvergesFirstPass (e2e/docs_refresh_test.go) | |
| bots.whats-next | whats-next (Nexie) chat loop + dispatch | bots | covered-deterministic | TestWhatsNextV2_ChatLoop_PauseResumeClose (e2e/whats_next_loop_test.go) | |
| bots.secured-renovacy | secured-renovacy (Renovacy) patch/minor/fix-loop paths | bots | covered-deterministic | TestSecuredRenovacy_PatchFastTrack (e2e/secured_renovacy_test.go) | |
| bots.sec-audit-source | sec-audit-source (Seki): cap_findings + scan_health gates | bots | covered-deterministic | TestSecAuditSource_ScanHealth_GuardsAgainstFacade (e2e/sec_audit_scan_health_test.go), TestSecAuditSource_CapFindings_BoundsScannerOutput (e2e/sec_audit_cap_findings_test.go) | |
| bots.sec-audit-deps | sec-audit-deps (Depsy): per-ecosystem + generic CVE heuristics | bots | covered-deterministic | TestSecAuditDeps_GenericHeuristic_DetectsMalwareSignals (e2e/sec_audit_deps_heuristics_test.go) | |
| bots.e2e-coverage | e2e-coverage (Endy): matrix gate + continuation loop | bots | covered-deterministic | TestE2ECoverage_ContinuesUntilComplete (e2e/e2e_coverage_bot_test.go), bots/e2e_coverage_matrix_gate_test.go | |
| bots.review-pr | review-pr (Revi): finding ids, stale anchors, gate status, concise publication and collapsed AI run details | bots | covered-deterministic | bots/review_pr_finding_id_test.go, bots/review_pr_stale_anchor_test.go, TestReviewPRRunDetails (bots/review_pr_run_details_test.go), TestReviewPRConcisePublication and TestReviewPRConciseScope (bots/review_pr_concise_test.go) | brief visible verdict; authenticated instance run link strips callback query/fragment; full findings/replacements survive missing anchors; gaps and decisions stay visible; verification limits are collapsed; served model/harness, run tokens and audited scope are collapsed; missing telemetry remains unavailable |
| bots.dep-update-guard | dep-update-guard (Vetty): prepare/gate/automerge routing | bots | covered-deterministic | bots/dep_update_guard_gate_test.go, bots/dep_update_guard_automerge_test.go | |
| bots.feed-watch | feed-watch: state machine, routing, SSRF-safe fetch | bots | covered-deterministic | TestFeedWatch_ScriptsStateMachine (e2e/feed_watch_test.go), TestFeedWatch_FetchRejectsSSRF (e2e/feed_watch_test.go) | |
| bots.feed-watch-split | feed-watch (Vigie): a digest over the per-message budget is delivered whole as consecutive numbered messages — per-sink max_chars, max_messages ceiling, no orphaned heading, intra-sink partial failure does not fail the run, nothing delivered does | bots | covered-deterministic | TestFeedWatch_NotifySplitsLongDigest (e2e/feed_watch_test.go) | drives the real python notify script against an httptest webhook that records every payload; the reassembly assertion is what proves no content is lost |
| bots.vuln-watch | vuln-watch (Senti): exploitation-driven alert policy, KEV re-fire, alias dedup, word-boundary inventory matching, explicit token failure, SSRF posture, at-least-once delivery, zero-LLM invariant | bots | covered-deterministic | TestVulnWatch_PolicyAndRefire (e2e/vuln_watch_test.go), TestVulnWatch_WordBoundaryMatching, TestVulnWatch_MissingTokenFailsHard, TestVulnWatch_FetchRejectsSSRF, TestVulnWatch_DryRunAndNoSinksDoNotConsume, TestVulnWatch_ZeroLLMInvariant | the real python tool scripts run against httptest GitHub/advisory/webhook fakes + a file:// KEV; the engine-side dependabot_tokens flow is covered by pkg/forge/security_read_test.go |
| bots.issue-triage | issue-triage (Triagy): author trust gate + label consumption | bots | covered-deterministic | TestIssueTriageTrigger_E2E_ConsumeAndLaunch (e2e/issue_triage_trigger_test.go) | |
| bots.golden-master-sync | the golden-master bot and its oracle harness stay in sync (same functions, same report fields) | bots | covered-deterministic | bots/golden_master_harness_sync_test.go | |
| bots.review-topology | mono/dual review topology injected only into opting-in bots | bots | covered-deterministic | TestReviewTopology_MonoClaudeSingleFamily (e2e/review_topology_test.go) | |
| bots.verify-gate | the deterministic verify_build/verify_run gate resists drift | bots | covered-deterministic | bots/verify_run_drift_test.go, bots/verify_probe_wiring_test.go | |
| bots.live-covered-catalog | the catalog bots that HAVE a live test (evolve, adr-cartograph, adr-rechallenge, rgaa-audit, bmady, devbox-setup, revi-converse, feature-gap-fill, test-coverage) | bots | covered-live | e2e/live_bot_adr_cartograph_test.go, e2e/live_bot_adr_rechallenge_test.go, e2e/live_bot_evolve_test.go, e2e/live_bot_rgaa_audit_test.go, e2e/live_bot_bmady_test.go, e2e/live_bot_devbox_setup_test.go, e2e/live_bot_revi_converse_test.go, e2e/live_bot_feature_gap_fill_test.go, e2e/live_bot_test_coverage_test.go | these bots' value IS the LLM work product (a review, an ADR map, an accessibility audit); they have no deterministic graph gate to assert against, so the live layer + quality panel is the honest coverage. Their graphs are compile-checked by bots.catalog-compiles |
| bots.uncovered-catalog | the catalog bots with NO test beyond parse+compile (modernize, wiki-gen, app-dev, supply-shield, supply-shield-cve, smoke) | bots | uncovered | plan: one e2e/live_bot_<name>_test.go each, on the runBotLive harness, with the quality panel — same shape as the live-covered row. Compile-only coverage (bots.catalog-compiles) is NOT coverage of what these bots produce | |
| studio-ui.run-console | run console view: timeline, node detail, diffs, chat | studio-ui | covered-deterministic | studio/e2e/specs/run-console.spec.ts | Playwright against the real server: the seeded run's IR graph (node ids, kinds, per-node status incl. the never-reached fail), its declared budget, its replayed edge-selection log lines and a published artifact's real payload all render. Chat needs a live agent — out of this row's deterministic reach |
| studio-ui.launch-modal | Launch modal: bot picker, vars, overrides, target repo | studio-ui | covered-deterministic | studio/e2e/specs/launch.spec.ts | Playwright: ?bot= resolves through the catalog to the workflow, the vars: block splits into required primaries vs defaulted Bot options, missing-required validation blocks the launch, and Engine options offers the workflow's own agent node for model retargeting. The "target repo" attach needs a forge connection (covered at REST level by the forge rows). The same spec found a REAL BUG — preview-cost answers nodes: null for a workflow with NO agent/judge node and CostPreviewChip dereferenced it, dropping the whole view into its error boundary — fixed in 457374dd; the test now asserts the positive contract (such a workflow still renders a launchable view) |
| studio-ui.board | /board kanban with drag-and-drop | studio-ui | covered-deterministic | studio/e2e/specs/board.spec.ts | Playwright: the native board's real columns + the CLI-seeded card render, and moving the card through the UI is asserted against the native store's REST read AND a reload (an optimistic-only client update fails). The move uses the selection toolbar rather than an HTML5 drag gesture — same mutation, same endpoint, no synthetic-DnD flake |
| studio-ui.pipelines | /pipelines control-center board + concurrency cap | studio-ui | covered-deterministic | studio/e2e/specs/pipelines.spec.ts | Playwright: the banner renders the cap the server actually booted with (--max-concurrent-pipelines, read back from /api/server/info — changing one side alone turns it red), and the seeded finished runs land as Closed cards linking to their own run console |
| studio-ui.dispatcher | /dispatcher live dashboard | studio-ui | covered-deterministic | studio/e2e/specs/dispatcher.spec.ts | Playwright drives the whole lifecycle: Start refused without a config, settings saved, dispatcher started, then the dashboard asserted against THAT instance's real settings (name, tracker, poll interval, slots) and lane counters, then stopped through its confirm dialog. A second test asserts the server's own config-validation error reaches the dialog. Poll pinned to 1h so the actor never claims the seeded card mid-test |
| studio-ui.bots-gallery | /bots gallery, per-bot home, guided builder /bots/new | studio-ui | covered-deterministic | studio/e2e/specs/bots-gallery.spec.ts | Playwright: the gallery lists what botregistry discovered on disk (and its search filters that set), the per-bot home renders the manifest fields + "declares no vars", and the guided builder is driven end to end — the assertion is the bundle it WRITES (main.bot + manifest.yaml under bots/scaffold-probe/) and the registry picking it up, not a toast |
| studio-ui.editor | workflow editor + /api/parse round-trip | studio-ui | covered-deterministic | studio/e2e/specs/editor.spec.ts | Playwright: the canvas + inspector are asserted against what the Go parser produced (node kinds, the tool node's command, entry node, budget) plus the real compiler diagnostic (C128), and an inspector edit is followed through save into the REWRITTEN .bot source on disk and back out through a fresh parse |
| studio-ui.editor-llm-meta | agent/judge canvas cards show the resolved model and the authored fallbacks: chain | studio-ui | unit-only | studio/src/lib/modelLabel.test.ts | displayModel never emits "env"; shortenModel keeps gpt-5.6-sol/terra/luna readable on a 160px card; displayFallbackChain joins routes in declaration order |
| studio-ui.secrets-view | Secrets view gated on server_info.secrets_enabled | studio-ui | covered-deterministic | studio/e2e/specs/secrets.spec.ts | Playwright: the gate flag is asserted, then add → list → delete is driven through the UI with the SEALED store file on disk as the oracle (name + last4 present, plaintext absent). ITERION_HOME/HOME/ITERION_SECRETS_KEY are redirected into the throwaway workspace so the operator's own store and keychain are never touched |
| studio-ui.browser-pane | Browser pane / preview attach | studio-ui | covered-deterministic | studio/e2e/specs/browser-pane.spec.ts | Playwright: a fixture tool node prints [iterion] preview_url=…, the runtime turns it into a preview_url_available event, and the pane auto-reveals carrying exactly that URL (bar + open link). The negative case — a run that published none has no Browser tab — pins the trigger. The URL is the suite's own loopback origin, so the iframe never leaves the test server. Live CDP attach needs a real Chromium session and stays out of the deterministic layer |
| desktop.wails-app | Wails desktop wrapper (window, runtime bridge, packaging) | desktop | unit-only | studio/src/tests/desktopBridge.test.ts | the Go half is cgo + build-tagged (desktop,webkit2_41) and excluded from lint/CI; an e2e needs a GUI session — the bridge contract is the testable seam |
| integrations.third-party-oauth | real third-party OAuth consent flows (GitHub App, IdP, MCP OAuth) | integrations | excluded | needs a real provider tenant and a human consent screen; iterion's side (state/PKCE, callback handling, token storage) is covered by cloud.sso-oidc, forge.github-app and tools-mcp.mcp-oauth | |
| integrations.claude-md-autoload | claw TUI CLAUDE.md auto-load | integrations | excluded | a claw-code-go TUI-boot behaviour with no iterion workflow surface; iterion uses its own command registry (carried over from docs/e2e_coverage.md) | |
| integrations.claw-lifecycle-hooks | claw lifecycle hooks / ctx propagation into hook handlers | integrations | excluded | iterion installs no lifehooks.Runner on its claw client, so there is no iterion-level behaviour to exercise; wiring one is a separate feature (carried over from docs/e2e_coverage.md) | |
| integrations.permission-modes-auto | claw permission modes auto / dontAsk | integrations | excluded | iterion runs headless (workflow mode) and never surfaces these modes; the two it does use are covered by tools-mcp.permission-gate |
