Per the hygiene rule: the §B-§5 static_check stage seam + emitter and the §B-§6/A3 critique-outcome producer are built and unit-verified, so move them out of the live "missing" list. Both narrowed to their remaining live-QA-gated *activations* (a sandboxed production CommandRunner for §B-§5; model-emitted CritiqueFindingsRecordedEvents for §6), with a dated RETRO entry + commit map. Updated QA-reviewer-static-first (the producing stage now exists — check 4 reframed from "blocked on unbuilt seam" to an activation step) and its README index line. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
17 KiB
CORREX — RETRO (archive of resolved BACKLOG items)
Counterpart to BACKLOG.md (the live outstanding list). Items here are built and
unit-verified (Gradle green). Where a live-QA gate applies, that's called out as a
follow-up — this sandbox has no local model / SearXNG / GPU / network, so live-QA
could not be run here.
2026-06-22 — BACKLOG hygiene reconcile + operator-requested TUI wave (branch feat/backlog-burndown)
Hygiene reconcile. Per BACKLOG.md's own maintenance rule, cut the resolved body bullets
that were left ticked-but-in-place after the 2026-06-20 burndown and 2026-06-21 grants work.
Sections affected: §A (health probes), §B (static-first infra, CritiqueFinding, architect
contradiction-check), §C (A1/A2 gate code), §D (batch fetch-approval, source events, dynamic
egress), §E (render matrix, markdown, session list, idea promotion), §G (turnId/probe/narration),
§I (.cs symbols, scene validator). Partially-done items were narrowed to their live
follow-up rather than deleted: §B5 → "static_check stage emitter only", §B6/§C-A3 → "the
CritiqueOutcomeCorrelatedEvent producer only", §C-A1 → "planner-prompt activation only". The
full commit map stays in the BACKLOG "✅ RESOLVED" index; detail is in the tables below.
Operator-requested TUI wave (archived here — never BACKLOG items, like the grants work).
A run of TUI/UX features added on the branch after the burndown, each compiled + go vet/go test green and rendered via cmd/preview before commit:
| Commit | What |
|---|---|
9143d55 |
Global input history + stop idle redraws (copy-safe — no redraw churn while selecting text). |
85bfddf |
Slash-command menu in the chat input. |
2662156 |
Transparent modal backdrops (overlays no longer paint an opaque box over the transcript). |
ba7ac06 |
Transcript message-jump (^↑/^↓ to your prev/next message) + OSC52 clipboard copy. |
65e5d88 |
Server: ListFiles/FileList protocol backing the TUI @ picker. |
04d7e26 |
@ file-reference picker in the input. |
c616982 |
Context: inject CLAUDE.md / AGENTS.md as L0 standing context. |
54f94a5 |
Command-palette keybinds + configurable (hideable) status bar. |
6a06f2e |
Inline action rows in the OUTPUT transcript (tool results / approvals / writes / grants as RouterEntry role action, interleaved by arrival). |
f14a83c |
Drop the inline tool-start rows (they doubled up with the result rows). |
531910d |
Transcript free-scroll (PgUp/PgDn, ^u/^d, esc snaps to tail-follow; clamped via outputViewport()/buildTranscriptRows, 2 tests) + help overlay (?) + event-inspector / filter. |
db27b34 |
Page-scroll the ^x diff/preview/command fullscreen viewer (↑↓ line, PgUp/PgDn page, ^u/^d half, g/G ends; scrollDiff() clamp, 2 tests) + advertise it in the modal hint and the ? help overlay. Closes the §E approval-ergonomics re-audit. |
d247b19 |
Bubble Tea v1 → v2 (charm.land/{bubbletea,lipgloss}/v2, Go 1.25). A key-handling shim (key.go: v2 KeyPressMsg → v1-shaped keyMsg at the single Update boundary) keeps ~190 match sites untouched. Other v2 breaks handled: lipgloss.Color is now a func returning color.Color (retyped fields/params); View() returns tea.View (render() builds the string, View() carries AltScreen — alt-screen is a per-frame field now, not a program option); WithWhitespaceStyle replaced WithWhitespace{Background,Foreground}; preview dropped SetColorProfile (v2 = truecolor by default). Enables literal Shift+Enter newline via v2 kitty disambiguation (Ctrl+J/Alt+Enter kept as non-kitty fallback). Live-QA: docs/qa/QA-tui-v2.md. |
85af2c6 |
Real terminal cursor in composer + window title. View.Cursor replaces the frame-animated ▏: a width-1 marker rune (U+E123) is located in the fully-composited frame → blinking CursorBar at (X,Y); static render() resolves it back to ▏ so screenshots/goldens are unchanged. Nil in normal mode (hidden, vim-correct), suppressed when a modal is open (which keeps editMode==Insert). animating() no longer ticks in insert mode — the terminal blinks the cursor itself, so an idle insert screen holds still (native text selection survives). View.WindowTitle = active session/model. New cursor_test.go (3) + updated animating-gate test. |
These are mostly deterministic render/UX changes (verifiable by go test + cmd/preview).
The v2 migration + native cursor are unit-verified the same way, but their behavioral wins
(Shift+Enter, the real blinking cursor, no regressions across the new render layer) need a real
kitty terminal — that's the live-QA gate in docs/qa/QA-tui-v2.md.
§E approval-ergonomics re-audit — DONE (db27b34). Re-checked the band after it gained the
grant scope-picker (A) and inline action rows: the spec still holds — single-key y/n/e for
T0–T2, mandatory second-key confirm for T3+ (HighTier), navigable queue with an i/n indicator,
docked band never modal-stacks. All covered green by approval_test.go. The one gap was the diff
viewer scrolling one line at a time; db27b34 adds paging. Item moved out of BACKLOG.
2026-06-22 — reviewer reliability: static_check stage + critique calibration producer (branch feat/backlog-burndown)
Two deterministic role-reliability tracks whose consumer halves already existed but had nothing feeding them. Both built + unit-verified (Gradle green, detekt clean); their activations are model-/sandbox-gated and stay narrowed in BACKLOG.
| Commit | What | Item |
|---|---|---|
e46777e |
§B-§5 deterministic static_check stage seam + emitter. StaticCheckStageExecutor runs a configured tool (static_tool/static_argv via stage metadata) through the existing StaticAnalysisRunner and emits StaticFindingsRecordedEvent; DefaultSessionOrchestrator.enterStage dispatches any metadata["stage_type"]=="static_check" stage to it instead of the LLM subagent and advances on the unconditional exit edge; TomlWorkflowLoader gained stage_type/static_tool/static_argv fields; role_pipeline.toml carries a static_check stage between implementer and reviewer. No-op until a sandboxed, workspace-scoped CommandRunner is wired + static_argv set (live-QA-gated). Tests: StaticCheckStageExecutorTest (4) + StaticCheckStageTest integration (1). |
B §5 |
e46777e |
§B-§6 / A3 critique-outcome producer. New CritiqueFindingsRecordedEvent (+ CritiqueVerdict) is the producing side — a critic's findings + verdict per iteration, with modelHash. CritiqueOutcomeCorrelator (pure, in the reviewer-loop runtime) decides UPHELD / DISMISSED / INCONCLUSIVE per critic and finding id; a hook in completeWorkflow/failWorkflow correlates recorded findings into CritiqueOutcomeCorrelatedEvents at loop resolution (no-op + idempotent), feeding the existing :core:critique calibration projection. Dormant until the reviewer/plan-critic emit CritiqueFindingsRecordedEvents (model-gated). Tests: CritiqueOutcomeCorrelatorTest (8) + CritiqueCalibrationWiringTest integration (1). |
B §6 / C-A3 |
Both follow the same shape as the earlier dormant-activation work: the deterministic seam + the
event wiring land and are unit-proven now; the LLM-/sandbox-side activation is the live-QA-gated
follow-up. docs/qa/QA-reviewer-static-first.md updated (no longer "producing stage not built").
2026-06-21 — wider grants + revoke (branch feat/backlog-burndown)
Operator-requested (not a prior BACKLOG item): grants that outlive a single session, plus a revoke path. Two commits, each compiled + unit-tested green.
| Commit | What |
|---|---|
c36d41b |
Cross-session grant scopes (PROJECT/GLOBAL) + revoke. GrantScope.GLOBAL(toolName) added; PROJECT made tool-bound. Engine scopeMatches: GLOBAL matches the bound tool anywhere, PROJECT when the session's projectId (derived from the bound workspace root via ProjectIdentity.of) AND tool match. New reserved GRANT_LEDGER_SESSION_ID stream holds PROJECT/GLOBAL grants; the approval gate unions the ledger's grants with the session's. RevokeGrant → ApprovalGrantExpiredEvent on the ledger (reducer already drops it); ListGrants/GrantList expose the active standing grants. Server-side T2 grant ceiling removed per operator request — a grant may now authorize any tier (incl. T3/T4); tool-binding is the remaining guard. New GrantScopeMatchingTest (5). |
8df0ec7 |
TUI: scope picker (A) + standing-grants viewer. A (approve-always) opens a session/project/global picker (SESSION default = old behaviour); p/g create wider grants. grants palette command + G shortcut open OverlayGrants listing scope/tool/tiers/path with x/enter to revoke. protocol.go: TypeGrantList+GrantDto, RevokeGrant/ListGrants encoders. Both overlays rendered via cmd/preview (kinds grants, grant-scope). |
Why the design: session grants are event-sourced per-session and die with the session; project/global grants must outlive any one session, so they live in a dedicated ledger stream the gate folds in — keeps grants in the audit log (invariant #9) rather than config.
⚠️ Live-QA gate (move out of RETRO once passed): unit tests cover the engine matching, reducer, and ledger fold, but the cross-session behaviour — create a GLOBAL/PROJECT grant in session A, confirm a different session B auto-clears that tool, then revoke and confirm it prompts again — needs a running server + model. Not runnable in this sandbox.
2026-06-20 — backlog burndown (branch feat/backlog-burndown)
Nine tracks, each compiled + unit-tested green before commit.
| Commit | Track | BACKLOG ref |
|---|---|---|
f783eed |
CritiqueFinding/CritiqueSeverity/CritiqueRole type + CritiqueOutcomeCorrelatedEvent + core/critique calibration projection (state/reducer/projector) |
B §6 + C-A3 |
784accb |
repomap: turnId namespace requires trailing : (no /repo↔/repo2 collision; L3RepoKnowledgeRetriever filter + ProjectMemoryService write) + WorkspaceStateProbe newline fingerprint |
G |
266bbf0 |
EventStoreLatencyProbe (wired) + LlamaServerHealthProbe (+ injectable LlamaLivenessClient) + HealthConfig.eventStoreWarnLatencyMs |
A §4 |
f715ffa |
.cs / Godot-Mono type symbols in RepoMapIndexer.SYMBOL_PATTERNS |
I |
0e251d6 |
SceneValidator — structural .tscn/.tres (header well-formedness, ExtResource/SubResource id resolution, node parent integrity) |
I |
1df7af5 |
Brief echo-back gate: BriefEchoMismatchEvent + BriefEchoComparator/BriefEchoExtractor + checkBriefEcho orchestrator gate |
C-A1 |
1a1b5cc |
Stage-level plan checkpointing: StageCheckpointPassed/FailedEvent + StageCheckpointReconciler + emitStageCheckpoint (gated on a locked plan) |
C-A2 |
eae0a0c |
Architect contradiction-check (display-only): PossibleContradictionFlaggedEvent + L3-backed ArchitectContradictionChecker |
B §4 |
b098d87 |
Dedicated SourceFetchedEvent / LowQualityExtractionEvent (promoted from ToolExecutionCompletedEvent metadata; additive), emitted from SandboxedToolExecutor |
D |
027ff1f |
Dynamic per-session egress allowlist: EgressHostsGrantedEvent + EgressAllowlist union helper + EgressAllowlistProjection; NetworkHostRule delegates to the union |
D |
447fc7a |
Reviewer static-first: StaticFindingsRecordedEvent + StaticAnalysisRunner (injectable CommandRunner; compiler/ktlint/detekt parsers) + excludeStaticFindingsFromReview filter, live-wired into reviewer context assembly |
B §5 |
eff8f8d |
Narration-lane lag: stale pause narrations dropped per-approval-request on resolve / per-session on resume (replay-safe) | G |
1e6699a |
tui-go go.mod go 1.26 → 1.24.2 (1.26 toolchain unreleased/unfetchable) — unblocks Go build/test on released toolchains |
E (enabler) |
da72ee5 |
tui-go: markdown rendering for chat turns via glamour (dark, per-width memoized), plain-text fallback; other roles/UI untouched |
E |
1f7a5d9 |
tui-go session list / resume view: R overlay over GET /sessions, resume via POST /sessions/{id}/resume onto the existing global stream |
E |
2a99e15 |
tui-go per-event render-matrix golden tests (37 cases) + a coverage guard that parses protocol.go so any new event type without a golden fails |
E §2 |
d5afcd3 |
tui-go approval ergonomics: navigable pending-approval queue (no modal stacking) + y/n/e keys + tier-gated T3+ arm/confirm |
E §3 |
641051b |
Plan-derived diff manifest: PlanStage.writes + PlanDerivedManifest.deriveAllowedWrites/combine, unioned into StageConfig.writeManifest at compile, enforced by the existing containment matcher |
B §2 |
ab7e4be |
Egress allowlist activation: resolveSessionEgressHosts threads the session's EgressAllowlistProjection state into ToolCallAssessmentInput at runPlane2Assessment, so NetworkHostRule now consults the live per-session union (was fed emptySet()) |
D (activation) |
4b0024f |
Batch source-list fetch-approval: POST /sessions/{id}/approve-sources → SourceListHosts.extract (java.net.URI, lower-cased, ports stripped, dossier-line tolerant) → one EgressHostsGrantedEvent; live allowlist then auto-clears those web_fetches (no per-URL T2) |
D |
f107ff5 |
Idea-board → project-profile promotion: IdeaPromotedEvent (board tombstone, like discard) + ProjectProfileWriter (escape-aware TOML serialize/write) + ProjectProfile.withConvention (deduped) + server PromoteIdea handler (loads profile, appends idea text, writes .correx/project.toml); also made SimpleToml's reader unescape \\/\" symmetrically with the writers (fixes pre-existing read/write asymmetry) |
E |
4e08510 |
Architect contradiction-check activation: ServerModule.start() subscribes to the architect stage's design ArtifactCreatedEvent, resolves decision text (design-schema approach field, capped fallback), runs ArchitectContradictionChecker.check, appends the non-null PossibleContradictionFlaggedEvent. Live-only, never halts. Checker built in Main.kt (gated on project.enabled) and threaded into ServerModule. Replaces the Main.kt TODO(wiring) |
B §4 (activation) |
64a90e7 |
Llama-probe registration: LlamaServerHealthProbe (266bbf0) wired into the health monitor when a llamacpp provider URL is configured — dedicated CIO client (3s timeout, shutdown-hook close) + HttpLlamaLivenessClient. Gated so a model-less box reports no spurious LLAMA_SERVER DEGRADED. Replaces the Main.kt TODO(wiring) |
A §4 (activation) |
Follow-ups created this pass (refiled into BACKLOG)
- C-A1 activation —
planner.mdmust emit abrief_echoblock androle_pipeline.tomlmust setbriefEcho="true"/briefEchoSourcefor the gate to fire live (model-dependent → live-QA). - C-A3 producer — nothing emits
CritiqueOutcomeCorrelatedEventyet; the calibration projection has no live feed until a reviewer-loop producer records finding outcomes. - B §4 wiring — ✅ DONE (
4e08510):ServerModule.start()now subscribes to the architectdesignartifact and emits the flag. (In-session L3 embedding is NOT needed — the checker filters to PRIOR sessions by design, so it works against prior runs' distilled decisions.) - A §4 llama wiring — ✅ DONE (
64a90e7): the probe is registered in the health monitor (gated on a configuredllamacppprovider URL) viaHttpLlamaLivenessClient. (tokens/sec telemetry still rides liveness-only — the/healthendpoint reports reachability; a throughput feed remains future work but the spec's liveness probe is live.) - D egress wiring — ✅ DONE (
ab7e4be): session egress state is now threaded intoToolCallAssessmentInputatrunPlane2Assessment, soNetworkHostRuleconsults the live union. Batch fetch-approval ✅ DONE (4b0024f):POST /sessions/{id}/approve-sourcesemits oneEgressHostsGrantedEventfor the whole source list. - B §5 static_check stage — runner/event/filter complete and the filter is live, but no workflow stage emits
StaticFindingsRecordedEventyet (// TODO(wiring)inStaticAnalysisRunner.kt); needs an event-emitting deterministic stage-type seam. - E toolchain — tui-go now builds via auto-downloaded go1.24.2 (
GOTOOLCHAIN=auto). The committed directive fix assumes 1.26 was unintended; bump if a specific newer release is actually wanted.
Environment note
- A
~/.gradle/gradle.propertiesmachine-local override was added on this box (-Xmx768m,parallel=false, kotlin daemon-Xmx640m) because the repo's-Xmx4GOOM-killed the foreground process on a 1.9 GB machine. Not committed — repo defaults intact for higher-RAM machines.