Makes the research feature runnable end-to-end, off by default.
- config: [tools.research] (enabled, searxng_url, max_results, max_fetch_bytes).
- registration: web_search/web_fetch are built into BOTH the default and per-workspace
tool registries when research.enabled, sharing one HTTP client threaded from Main
(none built on the static path). Egress stays harness-enforced: web_fetch is T2
(operator-approved) and the existing NetworkHostRule still applies.
- workflow: examples/workflows/research.toml — decompose → gather → report, with the
three artifact schemas and prompts. Fan-out (search per sub-question, fetch per source)
runs as repeated tool calls inside the gather stage (Correx has no parallel agents);
per-source synthesis into the dossier is the compression step, so the report stage
consumes summaries, never raw pages. ResearchWorkflowTest validates the graph contract.
To run: set [tools.research].enabled, register the 3 [[artifacts]], copy research.toml +
prompts + schemas into the workflows dir, start SearXNG. Launch like any workflow (the
T2 fetch approval surfaces as an approval card; the report opens in the artifact viewer).
Follow-ups (noted, not blocking): batch fetch-approval at the source-list level (§3),
a dedicated SourceFetched/LowQualityExtraction event (quality + content hash are already
in tool-result metadata), dynamic per-session egress allowlist, and the web approval client (§6).
The JSON-schema artifact validator enforced `required` keys but not array
contents, so a model could emit `"requirements": []` (or `"steps": []`,
`"components": []`) and pass — a misread brief sailing through as a valid
artifact. That empty-list gap is the hole under role-reliability §3's
keystone ("force the analyst to define done; verifiability propagates
downstream").
- JsonSchemaProperty gains `minItems` and `items` (recursive), letting a
schema declare a required-non-empty / element-typed array.
- JsonSchemaValidator checks array length >= minItems and each element's
declared item type (with index in the message). Pure + deterministic;
single-return to stay within the detekt ReturnCount budget.
- Role-pipeline schemas tightened: analysis.requirements, design.components,
impl_plan.steps → minItems 1 + items string. Prompt-free — these arrays
were already `required`; this only forbids them being empty.
§4 (force a non-empty `alternativesConsidered` on the architect) is
deliberately NOT taken: it contradicts the standing "don't raise
alternatives unnecessarily" preference the architect prompt already encodes.
ExecutionPlanCompiler treated the plan's single 'produces' string as a
registry kind id, while the architect prompt described it as a unique
artifact id referenced by needs/edges — the model followed the prompt,
invented descriptive ids (files_created), and every freestyle plan
failed to compile. Collapsing both onto one string is also unsound:
two stages producing the same kind would collide on slot name and make
artifact_validated edge conditions ambiguous.
Plan stages now carry an optional 'kind' selecting the registered kind
(mirroring TOML's produces = { name, kind }); 'produces' stays the
unique slot name. Missing 'kind' falls back to the old produces-as-kind
reading so existing plans still compile. Vocabulary entry, architect
prompt, and execution_plan schemas updated to match.
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.
Add docs/schemas/execution_plan.json (goal/stages/edges), the
architect_freestyle prompt that instructs emitting the execution pipeline as
JSON, and register the execution_plan llm-emitted kind in both
artifacts.config.toml and sample-config.toml. Validated via
ExecutionPlanSchemaValidationTest (minimal plan passes; missing stages rejected).