Commit Graph

274 Commits

Author SHA1 Message Date
kami 75703ec0c8 refactor(server,cli): shared payload-discriminator helper, single-read digest reuse, DOT label escaping 2026-06-12 19:23:05 +04:00
kami 4422aa8b7a feat(cli): causation-graph DOT export for event inspector 2026-06-12 19:17:26 +04:00
kami 64b58e3b05 feat(server,cli): session replay inspection — timeline + determinism digest 2026-06-12 14:39:54 +04:00
kami a04cd1fa24 feat(server,cli): event stream inspector — /sessions/{id}/events + correx events 2026-06-12 14:28:19 +04:00
kami a7d5211f3f feat(server,logging): correlation-structured MDC logging at seams
Implement T1 of observability epic: every server log line carries sessionId
(and stageId where known) via SLF4J MDC, propagated across coroutine
suspension points.

Changes:
- Create com.correx.apps.server.logging.Correlation: withSessionContext()
  helper that sets MDC (sessionId, stageId), wraps block in MDCContext(),
  and restores prior values on exit; supports safe nesting
- Wrap launchSessionRun() orchestrator loop in withSessionContext(sessionId)
  so all session logs carry the sessionId
- Wrap GlobalStreamHandler ChatInput and StartChatSession onUserInput call
  sites in withSessionContext(sessionId)
- Wrap SessionStreamHandler ChatInput onUserInput in withSessionContext(sessionId)
- Update log4j2.properties patterns: append
  %notEmpty{ [%X{sessionId}]}%notEmpty{ [%X{stageId}]} before %msg
  on both console and file appenders
- Add kotlinx-coroutines-slf4j:1.9.0 dependency for MDCContext

Test (6 tests):
- withSessionContext sets/restores sessionId ✓
- withSessionContext sets/restores stageId ✓
- Nested contexts stack and restore correctly ✓
- MDC cleared when stageId not provided ✓
- Propagation across coroutine boundaries via MDCContext ✓
- Cleanup after block exit ✓

Acceptance:
- Zero behavior change; no core module touched ✓
- All imports verified as used ✓
- No bare try-catch; try/finally used correctly ✓
- Detekt-compliant ✓
- Full test suite passes (120 tests, 119 passed, 1 skipped) ✓
2026-06-12 14:17:54 +04:00
kami e195c79510 fix(server): record boot-time parking of stale sessions as OrchestrationPaused
A stale RUNNING session skipped by resumeAbandoned stayed RUNNING in
every projection — the TUI showed a phantom running workflow that no
process was executing, and each boot re-logged the same skip. Parking
now emits OrchestrationPaused(reason=ABANDONED_STALE): status becomes
PAUSED (truthful — not executing, resumable via POST /resume) and
subsequent boots skip it on status alone.
2026-06-12 13:54:08 +04:00
kami a455762dd5 fix(router,server,config,tui-go): close QA findings #2 #3 #9 #10 #12
#2: approval pauses narrate from ApprovalRequestedEvent (carries
tool/tier/preview/stage directly) instead of OrchestrationPaused +
a pending-approvals map the next event had not yet populated — the
narrator always lost that race and produced generic text.

#3: NarrationTrigger now carries the triggering event's stageId; the
narration status line and RouterNarrationEvent.stageId use it instead
of the router projection's currentStageId, which terminal events have
already cleared ('Stage: none').

#9: ExecutionPlanLocked -> plan.locked and ArtifactValidated ->
artifact.validated mapped to the TUI (Go: feed lines, plan shows the
compiled stage chain); ArtifactValidating explicitly dropped.

#10: blank router turn guard — a length-finish with empty text now
emits an explanatory turn naming the max_tokens budget instead of a
silent blank; blank steering responses no longer emit steering notes.

#12: resumeAbandoned only auto-resumes sessions whose last event is
within orchestration.resume_abandoned_max_age_minutes (default 24h,
0 disables); staler sessions stay parked for POST /resume. Knob is
TUI-editable and persisted.
2026-06-12 13:20:04 +04:00
kami 4107a595db refactor(server): single guarded freestyleHandoff shared by run and resume launchers
launchSessionRun and launchSessionResumeWithRehydrate each inlined their
own copy of the freestyle phase-2 handoff with different guard sets — the
run path had none, so a failed planning run still called lockAndRun and
emitted a spurious ExecutionPlanRejected. Both now call one handoff that
checks graph id, planning result, and an existing plan lock before
locking and running phase 2.
2026-06-12 12:32:57 +04:00
kami a0da220e8e fix(server): boot/event-driven resume paths get rehydrate + freestyle handoff
resumeAbandonedSessions (boot pickup of RUNNING sessions) and the
restart-while-approval-pending subscription still used the bare
launchSessionResume: no artifact-cache rehydrate and no freestyle
plan-lock handoff. A freestyle session killed mid-planning was grabbed
by the boot path before the operator could POST /resume, completed the
planning graph, and stranded — WorkflowCompleted but never locked
(live repro: session b36b0e45, 2026-06-12).

Both paths now use launchSessionResumeWithRehydrate; the bare launcher
is deleted.
2026-06-12 12:26:04 +04:00
kami e503a28db2 fix(server,kernel): freestyle survives kill/restart at every phase (B4)
Three gaps found by live QA (kill between planning-complete and plan lock):
- launchSessionResumeWithRehydrate never handed off to FreestyleDriver, so a
  resumed freestyle session stranded at planning-complete with no plan lock
  and no phase 2; now locks+runs when planning completed and no
  ExecutionPlanLockedEvent exists yet.
- resume route 400'd on phase-2 sessions (workflowId freestyle-<sid> is
  compiled, never registered); now recompiles the locked plan after
  rehydrating the artifact cache.
- orchestrator.resume threw when currentStageId was terminal ('done') or
  unknown to the graph; now returns WorkflowResult.Completed.
2026-06-11 22:35:51 +04:00
kami 50602b0f11 fix(server): bind project profile on chat-session start
Chat sessions never emitted ProjectProfileBoundEvent — only the workflow
path did — so router triage always saw a null profile and could not cite
conventions or commands. Extract the binding from launchSessionRun into
ServerModule.bindProjectProfile and call it from handleStartChatSession.
2026-06-11 22:09:34 +04:00
kami f521ac89e5 feat(memory): markdown heading extraction in RepoMapIndexer
h1-h3 headings become the file's symbols, so design docs and GDDs are
embedded and retrievable alongside code. .md files now also participate in
workspace fingerprinting (INDEXED_EXTENSIONS derives from pattern keys).
2026-06-11 14:39:05 +04:00
kami 81a21bfe57 feat(memory): GDScript symbol extraction in RepoMapIndexer
Adds 'gd' to SYMBOL_PATTERNS (func/class_name/class/signal/enum at column 0,
optional static prefix). Because INDEXED_EXTENSIONS derives from the pattern
keys, .gd files now also participate in WorkspaceStateProbe fingerprinting,
making fp: state keys content-sensitive for Godot repos.
2026-06-11 14:32:04 +04:00
kami 7a9e060a55 feat(kernel): RepoKnowledgeRetriever port + relevance-retrieved repo context with recency fallback 2026-06-11 13:39:57 +04:00
kami 9d38a89c88 feat(memory): state-keyed repo-map reuse via L3 presence check; embed entries on fresh scan
- Add existsByTurnIdPrefix(prefix) to L3MemoryStore interface; implemented in
  InMemoryL3MemoryStore (mutex-guarded) and TurboVecL3MemoryStore (metadata map).
  All test fakes (TrackingL3MemoryStore, CapturingStore) updated.
- Introduce RepoMapIndexerPort interface; RepoMapIndexer implements it. Allows
  injection of test doubles without framework overhead.
- ProjectMemoryService.indexAndRecord: reads latest WorkspaceStateObservedEvent
  from event store (invariant #9 — recorded fact, not re-probe); skips scan+embed
  when L3 already holds entries for "repomap:<root>:<stateKey>"; passes stateKey
  to RepoMapComputedEvent; embeds each scanned entry after append; per-entry
  failures warn-logged (CancellationException rethrown).
- Tests: InMemoryL3MemoryStoreTest +2 cases; new ProjectMemoryServiceReuseTest
  covers same-key skip, changed-key re-index, no-observation always-reindex,
  and embedding turnId tag verification.
2026-06-11 13:30:57 +04:00
kami 4dbe637f4a feat(memory): WorkspaceStateProbe (git or fingerprint) + observeAndRecord at session start 2026-06-11 13:22:50 +04:00
kami f1fc43cc85 feat(router,server): wire workflow inventory and project profile into router context per turn 2026-06-11 13:15:32 +04:00
kami ac458d83e5 feat(workflow): root description field in workflow TOML surfaced through registry 2026-06-11 11:08:33 +04:00
kami ed0dca8b78 feat(kernel,artifacts): inject artifact-kind vocabulary into architect context 2026-06-11 10:06:40 +04:00
kami 91cca9aee3 feat(server,kernel): bind ProjectProfile per session and inject as L0 context 2026-06-10 21:49:31 +04:00
kami 0de02bb3a7 feat(server,kernel): post-plan approval gate — operator reviews plan before lock
After a freestyle plan compiles successfully, requestPlanApproval is invoked
before ExecutionPlanLockedEvent is emitted. Rejection emits
ExecutionPlanRejectedEvent(source="operator") with no lock and no phase-2 run.
Adds public SessionOrchestrator.requestPlanApproval seam delegating to
requestStageApproval, wired in Main.kt. Two new tests cover the reject and
approve paths; existing tests stay green via the default passthrough param.
2026-06-10 21:36:17 +04:00
kami 3d43f34d3b fix(narration): use plan_rejected kind and include source in instruction 2026-06-10 21:31:34 +04:00
kami 04836b751c feat(server): narrate execution-plan rejection 2026-06-10 21:30:07 +04:00
kami 0553b1b6ee feat(events,server): ExecutionPlanRejectedEvent — freestyle compile failure visible in log
Both silent-failure branches in FreestyleDriver.lockAndRun now emit
ExecutionPlanRejectedEvent (source=compile or missing_content) before
returning, satisfying invariant #1. Event registered in eventModule for
correct polymorphic serialization.
2026-06-10 21:26:18 +04:00
kami 113f403f5a chore(examples): add qa_ping smoke workflow; ignore tui-go binary and qa/ scratch
qa_ping is a minimal single-stage file_write workflow used for live QA smoke
runs (writes 'pong' into the qa/ scratch repo). The qa/ workspace itself is a
nested git repo and stays untracked; the compiled tui-go binary is ignored.
2026-06-10 20:54:59 +04:00
kami c82a86477d fix(tui): wrap long artifact lines in viewer instead of truncating
Artifact content wider than the modal was silently cut off. Lines are now
hard-wrapped at rune boundaries to the modal content width, and scroll
clamping uses the wrapped line count so the last page stays reachable.
2026-06-10 20:54:39 +04:00
kami cba9dd4583 fix(server): artifact viewer showed FileWrittenArtifact envelope, not file content
file_written artifacts store a JSON envelope ({path, contentHash, size, mode})
whose contentHash points at the real bytes in CAS. The viewer rendered the
envelope itself. StreamQueries now detects the envelope shape (string "path" +
"contentHash") and dereferences the inner hash, falling back to the raw string
when parsing fails or the inner hash is missing (WARN logged — likely evicted).
2026-06-10 20:54:29 +04:00
kami 883e23dec7 feat(router,inference,config): pin narration to a configured model_id
[router.narration] model_id selects which provider handles narration turns
instead of generic capability routing — lets a small/fast model own narration
while the main model keeps CHAT/STEERING.

- NarrationSettings.modelId parsed from TOML, threaded via RouterConfig
  .narrationModelId into DefaultRouterFacade.narrate (3-arg route)
- DefaultInferenceRouter: exact-id match against healthy providers, with a
  post-select health check; any miss logs WARN and falls back to capability
  routing (never fails the narration turn)
- onUserInput unchanged — only narrate uses the pinned model (tested)
2026-06-10 20:53:28 +04:00
kami cc6b402a23 fix(server,kernel,events): harden artifact read + restore workspace on reopen + cleanups
Follow-ups spotted while fixing the artifact-content bug:

- #1 robustness: listArtifacts resolves content via runCatching, degrading to null
  instead of failing the whole listing on one bad CAS read (resolveContent helper)
- #2 eviction visibility: WARN when a referenced artifact hash resolves to null
  (most likely evicted/compacted while still referenced by the event log)
- #3 ordering trap: document on ArtifactCreated/ArtifactContentStored that 'Created'
  fires at validation, AFTER ContentStored at inference — the latent fold hazard
- #4 reopen gap: SessionSnapshot now carries workspaceRoot (derived from
  SessionWorkspaceBound), so a reopened session restores its workspace label
- #5 orchestrator headroom: isBackEdge externalised to a top-level function so
  DefaultSessionOrchestrator drops below the TooManyFunctions threshold (was at it)

#6 (orphaned empty F-010-era artifacts) needs no code change — empty content is
already normalised to null ('(no content stored)'); emission is prevented going
forward by the shipped F-010/F-018/F-020 fixes.
2026-06-10 12:58:28 +04:00
kami 5f7b6f1f18 fix(server): artifact viewer dropped content hash due to event ordering
Root cause of empty artifact content (even for role_pipeline sessions with intact CAS
data): ArtifactContentStored is emitted at inference time, BEFORE ArtifactCreated (which
fires at validation). listArtifacts only applied the content hash via accs[id]?.let{} —
a no-op because the artifact wasn't in the map yet — so the hash was silently dropped and
every artifact showed blank.

Verified against the live store (session 4679ed1e): all 5 artifacts had hash=none before,
now resolve to their validated content (analysis 867B, design 1074B, impl_plan 966B,
patch 574B, review_report 369B).

- ArtifactContentStored now seeds the accumulator (getOrPut), order-independent
- fold extracted to pure StreamQueries.planArtifacts for unit testing
- regression test: content hash captured when ContentStored precedes Created
- inference-output fallback retained for genuinely content-less stages
2026-06-10 12:49:11 +04:00
kami 90ba7244d5 fix(server): artifact viewer falls back to raw stage output when no content hash
Artifacts with no ArtifactContentStored mapping (older sessions, or stages where the
slot->hash link was lost) showed a blank pane. listArtifacts now falls back to the
stage's last InferenceCompleted output so the operator can still see what the stage
produced. Empty-string content is normalised to null so the viewer shows a clear
'(no content stored)' instead of a blank pane.

Verified: role_pipeline sessions already resolve content from CAS (index + segments
intact, store rooted at ~/.config/correx/artifacts); the previously-blank sessions are
healthcheck/degenerate runs whose inference output was genuinely empty.
2026-06-10 12:35:07 +04:00
kami 3c5c2999d3 fix(server,tui): restore output panel + full event history on session reopen
Reopening a session after relaunch sent only a thin summary snapshot, so the output
panel was blank and the event list showed at most 7 entries (of a 100+ event run).

- SessionSnapshot now carries lastOutput/lastResponse, resolved from the last
  InferenceCompleted artifact in CAS; tui-go onSnapshot restores the output panel
- recentEvents cap raised 7 -> 200 so a normal session's event list isn't truncated
- resolveLastOutput extracted as a helper

Note: artifact content is unaffected — verified intact and CAS-retrievable for
role_pipeline sessions (artread); content-less artifacts occur only in workflows that
record no ArtifactContentStored (e.g. healthcheck/process-result stages).
2026-06-10 12:22:54 +04:00
kami bb70c94a99 feat(kernel,events): freestyle graph re-routing — deterministic override core
Implements the replay-safe half of preemptive redirect (graph re-routing). An
operator-confirmed PreemptRedirectEvent overrides the resolver's edge at the next
transition boundary; the pure resolver stays untouched.

- PreemptRedirectEvent / PreemptRedirectBlockedEvent (+ serialization registration)
- TransitionExecutedEvent + TransitionDecision.Move gain optional redirectId — the
  durable 'consumed once' marker
- PreemptRedirect.decide: pure decision over the event log (override / block / none),
  so replay reaches the identical outcome without re-classifying (invariant #8)
- override wired in DefaultSessionOrchestrator.step above resolveTransition; back-edge
  jumps count against the existing maxRetries cap via executeMove
- blocks jumps to unknown stages or targets with unsatisfied needs
- DomainEventMapper: redirect events mapped to null (operator surface ships with the
  LLM-proposal + approval-confirm front-half)
- tests: override+consume-once, block-on-needs, block-on-unknown, ignore-consumed

Front-half (LLM proposal -> approval-gate confirm -> emit PreemptRedirectEvent) is
deferred; needs live LLM verification. Until it ships no redirect event is emitted in
production, so the override is inert. Spec: docs/plans/2026-06-10-freestyle-graph-rerouting.md
2026-06-10 11:51:47 +04:00
kami 8c9ca9db00 fix(tui): F-006 flatten multi-line paste in input render
A multi-line paste put raw newlines into the single-line input slot, overflowing
the fixed-height box and leaving a smeared/stale region. flattenForDisplay collapses
newlines (↵) and tabs for rendering only; the inputBuffer keeps real characters for
submission.
2026-06-10 11:13:45 +04:00
kami ee24b7786a fix(kernel,server,tui,inference): generic resource gauge + F-002/F-003/F-004
- generic SystemResourceProbe: owner-agnostic /proc/meminfo system RAM
  overlaid on the vendor GPU probe, wired on both managed and static paths
  so the VRAM/GPU/RAM gauge renders with an external llama-server (was dormant)
- F-002: classify provider 4xx (e.g. llama.cpp 400) as terminal, not retryable
  (except 408/429); stops retrying deterministic request failures to exhaustion
- F-003: FileSystemPromptLoader expands leading ~ / ~/ to user home
- F-004: map InferenceFailedEvent + RetryAttemptedEvent to new
  ServerMessage.InferenceFailed / RetryAttempted, decoded+rendered in tui-go;
  ArtifactContentStoredEvent explicitly mapped to null (internal, no warn)
- tests: tilde expansion, SystemResourceProbe (static/managed/fail-soft)
2026-06-10 11:07:08 +04:00
kami a92b5a3531 feat(tui,server,config): live config editor + artifact viewer
Two operator features over the existing WebSocket protocol, plus a tui-go nav fix.

Config editor (g / palette "config"):
- core:config gains a thin registry stack: OrchestrationKnobs ([orchestration]
  block), CorrexConfigWriter (round-trip TOML serializer; parseToml(write(c))==c),
  ConfigHolder (AtomicReference live config), and EditableConfig (allowlist of
  editable fields + patch applier; security fields are absent so they can never
  be patched).
- ConfigService validates -> persists (atomic temp+move) -> swaps the holder ->
  rebuilds config-derived services. Live-apply is scoped to safe seams: stage
  timeout, compaction threshold (now a supplier), router knobs (routerFacade
  rebuild), and personalization/project toggles all take effect on the next
  session/turn; in-flight sessions keep the config they started with.
  server.host/port are persisted + badged "restart required", not hot-swapped.
- Protocol: GetConfig / UpdateConfig / ConfigSnapshot; TUI overlay with
  type-aware editing (bool toggle, enum cycle, inline int/string edit) and save.

Artifact viewer (v / palette "artifacts"):
- Server assembles a session's artifacts from the event log and resolves bytes
  from the CAS store (StreamQueries.listArtifacts) — a replay-neutral snapshot
  read. TUI overlay lists artifacts and shows scrollable content.

tui-go fix: workflow failure no longer clears selectedID (which yanked the user
to the list); listNav lands on the first session when nothing is selected
instead of wrapping to a random one.

Config is not event-sourced (it lives in TOML); editing stays outside the log.
2026-06-09 10:18:35 +04:00
kami b407b47503 fix(kernel,tools,validation): unblock role_pipeline end-to-end + QA audit
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.
2026-06-08 21:51:21 +04:00
kami d518400b5f fix(validation): resolve F-007 artifact validator CAS-hash conflation
ArtifactPayloadValidator passed the logical slot name into the
content-hash-keyed CAS store, crashing every workflow with a typed
produces slot. Validator now reads payloads from a content map threaded
through ValidationContext (populated from the orchestrator's per-session
artifact cache across all stages) and no longer depends on ArtifactStore.

Also records the slot->CAS-hash mapping as a new ArtifactContentStoredEvent
(registered for serialization), emitted at both CAS write sites, so
artifact content is recoverable from CAS by hash after a cold start.
2026-06-08 17:26:34 +04:00
kami 3f59faaa08 fix(inference,tools): unblock llama.cpp tool stages + workspace-relative file_read
Two fixes surfaced by the 2026-06-08 QA audit running role_pipeline on a local
llama-server.

F-001: LlamaCppInferenceProvider sent both a GBNF grammar and tools on the same
request; llama.cpp rejects the combination ("Cannot use custom grammar
constraints with tools"), failing every stage that has tools and produces a
schema-constrained artifact. Drop the grammar when tools are present and rely on
post-hoc schema validation + retry (invariant #7 still holds). TODO left for a
first-class emit_artifact tool as the proper fix.

F-005: FileReadTool resolved relative paths via toAbsolutePath() against the JVM
process cwd instead of the bound workspace, so the file-read jail anchored to the
wrong root and disagreed with the Plane-2 PATH_CONTAINMENT check. Add workingDir
to FileReadConfig, wire workspace.workingDir in the per-workspace tool builder,
and give FileReadTool a resolvePath() mirroring FileWriteTool/FileEditTool.
2026-06-08 16:37:20 +04:00
kami 54a54f4760 feat(server): reinstate JournalCompactionService with real inference 2026-06-08 11:02:14 +04:00
kami 5c03d1a772 feat(server): wire real inference into ProfileAdaptationService 2026-06-08 10:59:23 +04:00
kami 90d76e7bd1 feat(personalization): ProfileAdaptationService — propose-only learned adaptation 2026-06-08 10:42:19 +04:00
kami 0c7fa70f8d feat(personalization): OperatorProfileBoundEvent + bind-at-start + inject about context
Records operator profile as a snapshot event at session start (invariants #8/#9),
populates SessionState.boundProfile via reducer, and injects the about text as a
pinned L0 SYSTEM context entry in every stage. Gated by PersonalizationConfig.enabled.
2026-06-08 10:38:47 +04:00
kami 7af5d602bc fix(kernel,server): remove stub compaction + log missing summary artifact 2026-06-08 10:22:16 +04:00
kami 2b1faeaadd fix(kernel,server): wire JournalCompactionService in production + fix SessionSummaryProjector import 2026-06-08 10:20:30 +04:00
kami 7cec168e86 feat(server): real GET /sessions via SessionSummaryProjector 2026-06-08 10:17:20 +04:00
kami b830528d31 feat(kernel,server): rehydrate() + POST /sessions/{id}/resume 2026-06-08 10:13:33 +04:00
kami 37ac767d1f feat(freestyle): two-phase planning->execution driver (Slice 4)
- freestyle_planning.toml: analyst -> (approval) -> architect, producing
  execution_plan; analyst_freestyle.md surfaces open questions.
- TomlWorkflowLoader: requires_approval stage flag -> metadata.
- SessionOrchestrator: inline-prompt branch (metadata[promptInline]) +
  requestStageApproval helper reusing the existing pause/approve path.
- DefaultSessionOrchestrator: enterStage gates on requiresApproval
  (idempotent via resolved-approval lookup), preview derived from the
  gated stage's needs artifact; validatedArtifactContent accessor.
- FreestyleDriver: compiles validated plan, emits ExecutionPlanLockedEvent,
  runs phase 2 in-session via a runPhase2 seam; wired through ServerModule
  + Main (execution_plan kind registered).
2026-06-08 02:50:36 +04:00
kami 638f57709d feat(tui): workflow-start intent input box wired to StartSession.input 2026-06-04 02:24:41 +04:00
kami fe561ada09 feat(server): intent input channel — StartSession.input seeds decision journal 2026-06-04 02:16:23 +04:00