feat(kernel): static-first reviewer gate (role-reliability §5)
Run operator-configured static-analysis commands (compiler/detekt/formatters) as a
deterministic harness step on the producing stage, before the LLM reviewer. A stage
declares `static_analysis = [commands]`; after it produces its artifact, each command
runs in the workspace root and the results are recorded in a StaticAnalysisCompletedEvent
(invariant #9 env observation — recorded live, folded on replay, never re-run). A
non-clean command fails the stage retryably with its output fed back verbatim (§2:
compiler/test output is ground truth), so the implementer fixes it and only static-clean
code ever reaches the reviewer. This makes §5's "reviewer context excludes static findings"
mechanical — the findings are resolved upstream, so the reviewer can't waste inference on
what detekt catches for free; no output-parsing, no context plumbing.
- StaticAnalysisCompletedEvent + StaticAnalysisFinding (core:events) + registration.
- StaticAnalysisRunner seam + ProcessStaticAnalysisRunner (whitespace-split argv, stderr
merged, timeout→nonzero exit) in core:kernel; wired (nullable) into OrchestratorEngines
and the server. Null runner / no workspace root → logged no-op, never blocks the run.
- StageConfig.staticAnalysis + `static_analysis` TOML field; runStaticAnalysis folded into
a runPostStageGates sequence (produces → grounding → echo → static analysis).
- Documented `static_analysis` on the role_pipeline implementer stage (commented; commands
are workspace-specific). The reviewer prompt half shipped in 3467826.
This commit is contained in:
@@ -75,12 +75,20 @@ max_retries = 2
|
||||
# stage may write — a FILE_WRITE outside it is blocked as scope creep. Left open
|
||||
# here because the targets are task-specific; a task-scoped workflow would set e.g.
|
||||
# writes = ["core/sessions/**", "testing/sessions/**"]
|
||||
# Optional: `static_analysis` runs deterministic tools (compiler/detekt/formatters)
|
||||
# against the patch BEFORE the reviewer (role-reliability §5). A non-clean command
|
||||
# fails this stage retryably with its output fed back verbatim, so only static-clean
|
||||
# code reaches the reviewer — the reviewer never spends inference on what tools catch
|
||||
# for free. Commands are workspace-specific, so left commented; a Kotlin/Gradle repo
|
||||
# would set e.g.
|
||||
# static_analysis = ["./gradlew compileKotlin -q", "./gradlew detekt -q"]
|
||||
[[stages]]
|
||||
id = "implementer"
|
||||
prompt = "prompts/implementer.md"
|
||||
needs = ["impl_plan"]
|
||||
produces = [{ name = "patch", kind = "file_written" }]
|
||||
allowed_tools = ["file_read", "file_write", "file_edit", "ShellTool"]
|
||||
# static_analysis = ["./gradlew compileKotlin -q", "./gradlew detekt -q"]
|
||||
token_budget = 32768
|
||||
max_retries = 3
|
||||
|
||||
|
||||
Reference in New Issue
Block a user