Live QA audit of role_pipeline against a sample repo surfaced and fixed a
chain of defects that prevented any tool+artifact workflow from running
end-to-end. The pipeline now completes cleanly with a real, validated,
reviewed file change.
- F-008 workflow: propagate stage token_budget -> generationConfig.maxTokens
(TomlWorkflowLoader) so large stages stop truncating at the 2048 default.
- F-009 tools/kernel: file_read missing-file is recoverable; recoverable tool
errors feed back into the loop instead of aborting the stage.
- F-010/F-018 kernel: reject premature stage_complete and nudge the model to
emit the owed artifact / invoke a write tool (bounded by MAX_TOOL_ROUNDS).
- F-011 schemas: list-typed artifact fields string -> array (analysis/design/
impl_plan) to match model output.
- F-012 kernel: strip an outer markdown code fence from LLM artifacts.
- F-013 validation: payload-validation failures are retryable; structural
failures stay terminal (wires the invariant-#7 reject+retry contract).
- F-014 tools: file_edit schema matches its real params; edits emit a diff.
- F-015 kernel: record tool-execution events + materialise a real file_written
artifact from the on-disk write; gate validation so a no-write stage cannot
be rubber-stamped (no more false-success runs).
- F-016 server: raise stageTimeoutMs 60s -> 180s for slow local models.
- F-019 artifacts/kernel: file_written artifact carries the unified diff so the
reviewer can verify the change (shared DiffUtil; file_write emits a diff too).
- F-020 tools: model-correctable file_edit failures are recoverable + steer
toward replace/file_write over the fragile patch op.
Full findings register (F-001..F-021, incl. open F-021 resume rehydrate bug)
in qa/audit-report-2026-06-08.md. All module tests green.
Users declare artifact kinds in [[artifacts]] (id + schema_path to a JSON-schema file + llm_emitted); ConfigArtifactKind registers them at startup via createWorkflowLoader(extraKinds). New JsonSchemaValidator validates any non-built-in kind generically against its declared deriveJsonSchema(), so an LLM-emitted custom kind is checked against its shape, never trusted. Removed the dead payloadSerializer from the ArtifactKind contract. Schema source is path-to-file (not inline TOML — the hand-rolled parser can't nest).
DefaultMaterializingArtifactWriter and its MaterializingArtifactWriter interface
were test-only orphans after the sandbox dual-write retirement (95e79bf) - no
production wiring, never instantiated outside their own test. Delete all three.
Add healthcheck_*.txt to .gitignore (one-off generated output).
P2-1: Guard SessionId NPE with safe-call in SessionsReducer
P2-2: Remove 16 dead event classes + reducer branches; replace with live orchestration events in tests
P2-3: Standardize ChatInput divergences — guard CancelSession, single-arg ProtocolError
P2-4: Remove dead TuiToolRecord.diff and ToolDisplayStatus.REQUESTED
P2-5: Remove dead streamLive from SessionEventBridge
P2-6: Extract SessionsReducerContext data class for 6+ param method
P2-7: Replace StageId("none") sentinel with TypeId.NONE
P2-9: Add TypeId.random() factory on all type-alias IDs
P2-10: Add KDoc on schemaVersion documenting reserved-for-migration
P2-8: Verified RouterReducer string-template already correct (TypeId value class toString)
- Add field to ProcessResultArtifact ("success"/"failed")
- Materialize ToolResult.Failure as a failed ProcessResult artifact
in the orchestrator, with artifact lifecycle events emitted
- Non-recoverable ToolResult.Failure now fails the stage ("FATAL:")
instead of being silently fed back as LLM context
- Fix enterStage to return Continue on non-retryable failures,
enabling back-edge transitions (fix/retry loops)
- Add ArtifactFieldEquals transition condition with flat and
nested dot-notation field access + FieldOperator enum
(eq, neq, gt, gte, lt, lte)
- Wire artifact_field_equals through ConditionFactory and
TomlWorkflowLoader (condition_field, condition_operator)
- Cache ProcessResult artifact content for evaluation context
- Add 16 tests covering all condition operators and error cases
- DefaultTransitionResolver catches condition evaluation errors
and returns Blocked instead of crashing
Implements the full conversational router facade: RouterState, RouterReducer,
RouterProjector, RouterRepository, RouterContextBuilder, RouterFacade, protocol
types, WebSocket wiring, infrastructure factory, and deterministic test suite.
Also fixes spec divergences found in post-implementation review:
- Add SteeringNote domain object to core:context (epic prerequisite)
- Rename RouterFacade.handleChat → onUserInput per spec interface contract
- Add in-memory ConcurrentHashMap conversation history to DefaultRouterFacade
- Make RouterRepository.getRouterState suspend
- Rename RouterConfig.keepLast → conversationKeepLast, fix defaults (6, 4096)
- Refactor InfrastructureModule.createRouterFacade to self-assemble internally
- Fix FileReadTool: allowedPaths was dead constructor param (@SuppressUnusedParameter);
now stored as private val and enforced in validateRequest
- Disable koverVerify on modules tested via testing/ submodules or with
hardware/integration dependencies (24 modules); build gate now passes clean
Deletes 21 Module.kt scaffolding objects that were never wired into any DI
registry. Removes unused imports across 8 production and 3 test files.
Restores StageExecutor, CyclePolicyResolver, PolicyValidation, and
ReplayContractTest — these are deferred features, not dead code.