Skip to content

Phase 2.5.H — reasoning render, live-turn feedback & actionable errors (development → main)#68

Merged
cemililik merged 17 commits into
mainfrom
development
Jul 7, 2026
Merged

Phase 2.5.H — reasoning render, live-turn feedback & actionable errors (development → main)#68
cemililik merged 17 commits into
mainfrom
development

Conversation

@cemililik

@cemililik cemililik commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

development → main — Phase 2.5.H (+ a trailing docs commit)

Release-gate PR bringing development up to main. The substantive change is Phase 2.5.H; it also carries one small trailing docs commit left behind after PR #66.

Contents

  • Phase 2.5.H — Reasoning rendering, live-turn feedback & actionable error taxonomy (14 commits, 0a0e368…9c62ae9) — the review target below.
  • 20027fcdocs(roadmap): mark the reasoning-effort model-UX follow-up complete (ADR-0066) — a doc-only reconciliation (the ADR-0066/0059 model-UX follow-up marked done) that landed on development just after PR Phase 2.5.G — provider economics (S8–S12) + model-UX follow-up (A–E) #66 merged; carried here so main's roadmap surfaces are in sync.

Phase 2.5.H (the substantive change)

Makes the reasoning the @relavium/llm seam already carries (ADR-0030) visible in the chat TUI, gives every in-flight turn live latency + honest truncation + failover attribution, and turns each failed-turn ErrorCode into an actionable, session-survives recovery hint. The @relavium/llm seam is not modified; the engine change is one additive event.

Behind EA6 — a new dual-envelope agent:reasoning stream event that amends ADR-0036 (the event substrate) via an append-only note. No new top-level ADR (pre-authorized by the roadmap 2.5.H section + the EA appendix). Was reviewed on its own feature-branch PR (#67).

Delivered (4 steps, each with an opus → Sonnet review round)

  • Step 1 — agent:reasoning (EA6) · @relavium/shared + @relavium/core + docs. A dual-envelope stream event emitted by the correlation-agnostic turn core per reasoning_delta chunk (pure host-emit); added to the shared union + RUN_EVENT_TYPES + the drift-pin; carried on both the run path (engine #nodeEmit, now compile-exhaustive) and the session sink; never the ephemeral signature.
  • Step 2a — Live-turn feedback + elision + attribution · apps/cli. Thinking…/Working… {elapsed}s · Esc to stop timer; a visible elision marker (fixing the silent head-drop, baked into the finalized transcript entry too); per-attempt via {model} failover attribution.
  • Step 2b — Collapsible "thinking" panel · apps/cli. Default collapsed; /thinking + Ctrl+T (both surfaces, mid-turn). "Thinking…" only while the model is plausibly reasoning (not while a tool executes).
  • Step 3 — Actionable error taxonomy · apps/cli. A static, secret-free per-ErrorCode recovery hint ("the session is still active") — provider rate-limit / unavailability / auth+keychain, a context-overflow message heuristic → /compact·/trim, tool_failed / MCP timeout, budget / turn-cap / content-filter / internal. TUI + plain driver; suppressed on the one-shot agent run; --json unchanged.

Design decisions (confirmed up front)

/thinking + Ctrl+T (both surfaces) · context-overflow via a message keyword heuristic (secondary net; 2.5.F auto-compaction is primary) · agent:reasoning is in the --json session stream (consumers filter on type).

Security

  • The ephemeral signature (ADR-0030) never reaches the event, a log, or the transcript (traced end-to-end).
  • The error-hint provider message is read for the heuristic but never echoed (every hint is a static host string; tested with a secret-ish substring on both surfaces).
  • All model-produced text goes through the existing terminal sanitizers. Seam holds; packages/core stays platform-free; no new dependency.

Review cadence & fixes

Every step: aggressive multi-dimensional opus review → fix → Sonnet review → fix. ~15 verified findings fixed, incl. 5 HIGH: a run-path silent-drop of the new event (+ an exhaustiveness guard), a frozen Home live-timer, a scrollback elision loss, a one-shot agent run hint-leak, and an Opus-fix over-reach on tool_unavailable — all fixed. Plus hint-accuracy corrections, a heuristic false-negative/false-positive tightening, and an ERROR_CODES-derived drift-guard test.

Deferred (tracked in deferred-tasks.md, none blocking)

A CLI render-layer (ink component) test harness (the React prop-plumbing layer is untestable by design — the Home-timer fix is verified by tracing + the type-shape); a line-bounded expanded panel; an approval-gated Ctrl+T (deliberately fail-closed).

CI / tests

pnpm turbo run lint typecheck test build24/24 tasks green; lint:fence-check, lint:engine-deps, format:check clean. New tests across @relavium/shared, @relavium/core, @relavium/db, apps/cli.

Known pre-existing flake (NOT introduced here): apps/cli/src/engine/media-gc.test.ts ("sweeps a row-less CAS orphan") is non-deterministic and fails intermittently — it touches no file in this change (media CAS, not events). Verified it fails 3/3 on the pre-2.5.H base commit 1598798. Worth a separate fix.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added a collapsible “thinking” panel to chat, controllable via /thinking and Ctrl+T, including live streamed reasoning (when available) with an elapsed-time indicator.
  • Bug Fixes
    • Improved plain/non-TTY failed-turn rendering: secret-free, actionable recovery hints when enabled, suppressed for one-shot/non-interactive runs; strict bare failure-code output otherwise. Enhanced TUI streaming with truncation elision, producing-model attribution, and control-sequence sanitization.
  • Documentation
    • Updated CLI chat session docs for /thinking, Ctrl+T, live reasoning, actionable error recovery, and hint behavior.

cemililik and others added 15 commits July 7, 2026 13:14
…(ADR-0066)

The PR is merged. Reconcile the canonical status:
- current.md: the reasoning-effort paragraph now reflects the SHIPPED state —
  all four providers (DeepSeek-v4 thinking included), the interactive /effort
  overlay (§6), and the bare-Home /models effort-default write (the new global
  [preferences].reasoning_effort key), plus the two review-caught fixes; merged
  2026-07-07.
- phase-2.5-cli-consolidation.md: the 2.5.G Acceptance parenthetical no longer
  claims "reseat stays Phase 2.6" — the reseat + reasoning-effort landed as the
  post-2.5.G follow-up (ADR-0059 + ADR-0066), pointing to current.md.

Co-Authored-By: Claude <noreply@anthropic.com>
Add the reasoning ("thinking") counterpart of `agent:token`: a dual-envelope
`agent:reasoning` stream event the correlation-agnostic agent turn core emits
per `reasoning_delta` chunk. Pure host-emit — the @relavium/llm seam already
carries the reasoning chunks (ADR-0030); the turn core previously only
ACCUMULATED reasoning deltas with no event of their own. The seam and the
engine architecture are unchanged.

- @relavium/shared: AgentReasoningEventSchema + type, added to the RunEvent
  union, RUN_EVENT_TYPES (22→23), and the dualBase family; drift-pin matrix +
  dual-envelope test extended.
- @relavium/core: 'agent:reasoning' in InNodeEventType; foldReasoningChunk emits
  it (mirrors the agent:token emit) carrying text + active model, never the
  ephemeral same-provider signature (ADR-0030); the session sink carries it
  (not run-only, unlike agent:file_patch_proposed). Engine + sink tests.
- docs: sse-event-schema.md row + Selected-definition + session-stream notes;
  ADR-0036 append-only amendment note (EA6 amends the event substrate; no new
  top-level ADR — an additive event in the shared union).

Toolchain: lint + typecheck + test + build green (24 tasks); format:check clean;
seam-hold clean.

Refs: ADR-0036, phase-2.5-cli-consolidation.md (2.5.H, EA6)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ore throttle

Fix the review-caught gaps in the agent:reasoning (EA6) landing:

- BLOCKER: the engine's #nodeEmit run-path translation point switched on
  event.type with no default, so agent:reasoning (added to InNodeEventType) fell
  through and was SILENTLY DROPPED on the workflow-run path — the dual-envelope
  contract was only half-delivered (the session path emitted it, a run did not).
  Add the pass-through case AND an exhaustiveness guard (`const exhaustive: never`)
  so a future in-node event is a compile error here, never another silent drop.
  New engine.test.ts regression asserts it reaches the bus with runId.
- MEDIUM: agent:reasoning was missing from HIGH_FREQUENCY_EVENTS in chat-store +
  run-store, so each reasoning delta flushed an immediate repaint (a live thrash on
  the session path now — reasoning models emit many thinking tokens). Coalesce it
  like agent:token.
- LOW: add it to the db STREAMING_EVENT_TYPES firehose set (defensive; never
  persisted); broaden the agent-turn.ts model-attribution NOTE (both mid-stream
  events share the pre-content-failover edge) + the deferred-task entry; fix the
  stale "four dual events" enumerations (agent-session.ts, node-executor.ts,
  agent-runner.md).
- Tests: run-path bus assertion (would have caught the BLOCKER) + a redacted-block
  zero-emit test.

Toolchain: lint + typecheck + test + build green (media-gc flake passed on retry);
format:check clean.

Refs: ADR-0036, phase-2.5-cli-consolidation.md (2.5.H, EA6)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…+ doc consistency

Close the review-caught gaps (0 blocker/high; 2 medium + 1 low):

- MEDIUM: sse-event-schema.md had a self-contradictory paragraph — its first
  sentence listed the reused in-turn events WITHOUT agent:reasoning while a later
  sentence in the same paragraph included it. Add it to the first list so the
  canonical home is internally consistent.
- MEDIUM: agent:reasoning was the one HIGH_FREQUENCY_EVENTS member with no
  coalescing regression test in either store. Add a chat-store test (mirrors the
  cost:updated test) + extend the run-store family test — so dropping it from
  either set fails a test (the untested-drift class the BLOCKER post-mortem flags).
- LOW: run-history-store.test.ts claimed "ALL THREE excluded streaming types" but
  the set now has four; persist + assert the 4th (agent:reasoning) so the
  "fails on drift/misspelling" guarantee holds for it too.

Toolchain: shared/core/db/cli green (media-gc CAS-orphan flake confirmed
pre-existing + unrelated — non-deterministic across repeated isolated runs, touches
no event code); format:check clean.

Refs: ADR-0036, phase-2.5-cli-consolidation.md (2.5.H, EA6)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… attribution

Additive `relavium chat` UX (host-only, no engine change):

- Live-turn timer: before the first token streams, the busy line shows
  `⠋ Working… {elapsed} · Esc to stop` (whole-second `formatElapsed`, floored so it
  doesn't jitter per frame) — a running turn never reads as a frozen bare spinner.
  `nowMs` is threaded to `ChatView` from both `ChatApp` (Date.now()) and the Home.
- Elision marker: the live token buffer already sliced its head at
  MAX_LIVE_TOKEN_CHARS but dropped it SILENTLY; now the view-model tracks
  `liveTokensTruncated` (reset with the buffer) and the render shows a leading `…`,
  so the scroll-out is visible. `appendBounded` reports the elision (reused by Step
  2b for reasoning).
- Per-attempt model attribution: the completed-turn summary shows `via {model}` when
  the committed model (from the accurate per-attempt `cost:updated.model`, EA2)
  differs from the bound model — a within-turn failover — and is omitted otherwise
  (the footer already shows the bound model), so a plain turn is unchanged.

Tests: view-model truncation-flag + reset + failover-attribution; formatElapsed;
formatTurnSummary `via {model}` + sanitization. lint/typecheck/test/build green;
format:check clean.

Refs: phase-2.5-cli-consolidation.md (2.5.H)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…-line tests

Fix the review-caught HIGH + close the coverage gap:

- HIGH: the live-turn timer was frozen at 0s in the bare-Home in-process chat.
  `nowMs` was computed once per RootApp render (which only re-renders on controller
  state changes), then handed to the per-frame ChatRegion as a frozen number — so
  during the pre-first-token wait the elapsed stuck at 0s (worse than no timer).
  Thread the clock as a FUNCTION into ChatRegion (which re-renders every frame while
  a turn streams, via its own store subscription) and read it there. Standalone
  `relavium chat` was already correct (ChatApp reads Date.now() in its own render).
- MEDIUM: the busy-line branch matrix was inline JSX with zero test coverage.
  Extract a pure `formatBusyLine({...}) → { text, dim }` into chat-projection.ts and
  unit-test every branch (compaction / shell / pre-token Working…+elapsed / streaming
  content + elision adjacency / sanitization). The render now only maps `dim` → <Text>.
- LOW: guard formatElapsed against a non-finite input (symmetry with spinnerFrame);
  document the last-cost:updated "committed model" engine-ordering dependency + add a
  multi-attempt attribution test (cost A → cost B → `via B`).

Deferred to 2b (holistic busy-region redesign for the reasoning panel): keeping a
compact abort hint visible during token streaming.

Toolchain: lint/typecheck/test/build green (media-gc CAS-orphan flake CONFIRMED
pre-existing — fails 3/3 on the pre-2.5.H base commit, touches no file in my diff);
format:check clean.

Refs: phase-2.5-cli-consolidation.md (2.5.H)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…+ test gaps

Close the review-caught HIGH + the smaller gaps:

- HIGH: the elision marker vanished the instant a turn completed. reduceTurnCompleted
  built the transcript entry from raw liveTokens (no `…`), and the live busy-line
  marker (formatBusyLine, in-flight only) never applied to it — so once the turn
  landed in ink <Static> (the terminal's PERMANENT scrollback) it rendered verbatim,
  reverting to the silent head-loss the feature exists to surface. Bake `…` into the
  FINALIZED display text when the final segment truncated (guarded on the RAW text so
  no spurious empty entry), fully reducer-testable. The DURABLE record (persister →
  resume/export) is untouched + full — only the bounded live echo is short.
- MEDIUM: formatElapsed's non-finite guard shipped untested — add NaN/Infinity → "0s".
- LOW: pin formatBusyLine's compaction-over-shell priority.
- MEDIUM (tracked, not silently deferred): the Home live-timer fix has no regression
  test — the CLI has no ink component-render harness by design (pure-logic testing).
  Filed as a deferred task (a render-layer harness is a first-of-its-kind devDep/ADR
  decision, out of 2.5.H scope) alongside the streaming-abort-hint follow-up.

Toolchain: lint/typecheck/test/build green (1560 CLI tests; media-gc CAS-orphan flake
pre-existing — fails 3/3 on the pre-2.5.H base commit); format:check clean.

Refs: phase-2.5-cli-consolidation.md (2.5.H), deferred-tasks.md

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…nking + Ctrl+T)

Render the streamed reasoning (agent:reasoning, EA6) in the chat TUI:

- View-model: fold agent:reasoning into a bounded `liveReasoning` buffer (+ its
  `liveReasoningTruncated` elision flag). Unlike liveTokens it is reset only per
  TURN (started/completed/cancelled), NOT per tool call, so the panel accumulates
  the whole turn's thinking across tool rounds.
- A collapsible "thinking" panel (pure `formatReasoningPanel`) — default COLLAPSED
  (a dim `✻ Reasoning · Ctrl+T show` header); expanded shows the sanitized reasoning
  body (newline-preserving) with a leading `…` elision marker. The busy line labels
  the pre-token phase "Thinking…" (vs "Working…") when reasoning is streaming.
- Toggle both ways (the maintainer's choice): a chat-only `/thinking` slash command
  (a new `toggleReasoning` ReplCommandContext capability, wired in chat.ts's replCtx,
  inert in the bare-Home ctx) + a `Ctrl+T` keybind (a new `toggle-reasoning`
  ChatKeyAction, decided before the running-swallow so it works mid-turn). Both flip
  the store's new `reasoningVisible` flag; wired in BOTH surfaces (chat + Home).
- Home parity: ChatRegion threads reasoningVisible; the controller routes Ctrl+T to
  the store toggle.

Docs: commands.md + chat-session.md (the `/thinking` command, the Ctrl+T keymap row,
and a "Reasoning & live-turn feedback" section). Tests: reasoning fold + per-turn
reset + cross-tool accumulation; store toggle; formatReasoningPanel + the Thinking…
label; the Ctrl+T key action; the Home integration; the /thinking→toggleReasoning
dispatch. lint/typecheck/test/build green (media-gc flake pre-existing); format clean.

Refs: phase-2.5-cli-consolidation.md (2.5.H, EA6)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Address the review-caught polish (all LOW; Opus verdict was "ship it"):

- The pre-token busy line read "Thinking… {elapsed}" even while a tool was
  executing (reasoning is turn-scoped and liveTokens resets on a tool call, so the
  empty-tokens gap during a tool round showed the thinking label). Now the label is
  "Thinking…" only when reasoning has streamed AND no tool call is unresolved — during
  a tool round it falls back to "Working…", so the timer never claims the model is
  thinking while a tool runs.
- Tests: a sticky-truncation-across-deltas test for liveReasoning; a `/thinking`
  end-to-end dispatch test (through the real chat command → replCtx.toggleReasoning →
  the shown/hidden notice) closing the one untested wiring link.
- Deferred (tracked, not silently): bound the expanded reasoning panel by rendered
  LINES not chars (live-region flicker on a short terminal); allow Ctrl+T/`/thinking`
  during a pending approval (deliberately left fail-closed — the approval floor is
  security-sensitive, ADR-0057).

Toolchain: lint/typecheck/test/build green (media-gc CAS-orphan flake pre-existing);
format:check clean.

Refs: phase-2.5-cli-consolidation.md (2.5.H), deferred-tasks.md

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…reasoningLabelActive

Close the two MEDIUMs (same root) + the doc LOW (Sonnet verdict: 0 blocker/high):

- The Opus-fix's "Thinking… only when no tool is executing" derivation lived inline
  in ChatView (untestable without an ink harness) and left formatBusyLine's
  `hasReasoning` param doc describing the PRE-fix semantics (the caller now passes the
  narrower tool-gated value). Extract a pure, exported `reasoningLabelActive(hasReasoning,
  liveToolCalls)` in chat-projection.ts, unit-tested with the resolved/unresolved/mixed/
  empty/no-reasoning cases; rename formatBusyLine's param to `reasoningActive` with an
  accurate doc. The inline glue is now a one-line call to the tested helper.
- Documented the LOW bound-interaction note (liveToolCalls is capped) on the helper.
- Docs: chat-session.md now notes the "Working…" fallback also applies while a tool
  call is unresolved (not only when there is no reasoning).

Left as-is (Sonnet LOW, deliberate/acceptable): the turn-sticky "Thinking…" heuristic
in the resolved-tool→compose gap (a reasonable approximation, not a defect); the
approval-gated toggle + line-bounded panel remain tracked in deferred-tasks.

Toolchain: lint/typecheck/test/build green (1577 CLI tests, no flake this run);
format:check clean.

Refs: phase-2.5-cli-consolidation.md (2.5.H)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…rvives)

A failed turn is never a terminal (only session:cancelled ends a session), so a
failure always leaves the REPL live. Beyond the closed ErrorCode, the chat now
renders a one-line, secret-free recovery hint for each operational class that names
the next step + makes "the session is still active" explicit — extending the "say so
plainly" philosophy from the 2.5.A capability gap to the transport/quota/limit
classes:

- provider_rate_limit / provider_unavailable → retried w/ backoff + failover, resend.
- provider_auth → check the key or UNLOCK the OS keychain (if locked mid-session).
- context-overflow → surfaces as `validation`; a keyword heuristic on the (never-
  displayed) provider message distinguishes it from a shape error and suggests
  /compact·/trim (the maintainer-chosen detection; a SECONDARY net — 2.5.F auto-
  compaction pre-empts most overflows).
- tool_failed (incl. an MCP-server timeout), budget_exceeded, run_timeout,
  turn_limit, content_filter, internal → each an actionable one-liner.

The hint is ALWAYS a static host string — the provider message is read only to pick
the hint (the overflow heuristic), NEVER echoed, so no provider text/secret reaches
the terminal (tested). Rendered on the interactive TUI (a yellow line under the
summary) + the plain non-TTY driver (under `[turn failed: <code>]`); --json stays the
structured stream. `cancelled` (user-initiated) / `sandbox_error` (not chat-reachable)
get no hint.

Docs: chat-session.md "Actionable error recovery" section. Tests: errorRecoveryHint
per class + the overflow heuristic + the no-echo security assertion; the plain-printer
hint (+ secret-free). lint/typecheck/test/build green; format + seam clean.

Refs: phase-2.5-cli-consolidation.md (2.5.H)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…+ drift-guard

Address the review-caught accuracy debt (0 HIGH; 4 MEDIUM, all one-line string
edits with real user impact; the no-echo security crux was verified clean):

- tool_failed: the hint over-claimed "retried within budget" (there is NO session-
  level tool retry) and told the user to "try again" — unsafe for the non-recoverable
  (side-effecting) failure that actually reaches a completed turn, and contradicting
  the summary line's own path/target framing. Reframed to complement the summary:
  "fix the path or target (or check the MCP server) and resend" (no blind retry).
- turn_limit: had TWO producers — the per-turn tool-call ceiling AND the session HARD
  round cap (agent-session.ts) — and "send another message" is re-blocked by the
  latter. Now covers both (`/clear` if the hard cap is hit).
- internal: pointed at a "correlation id from the logs" that the session path never
  produces (correlationId is WorkflowEngine-only, ADR-0036). Dropped that clause.
- context-overflow heuristic: added Anthropic's "…exceed context limit" phrasing
  (a real false-negative), and dropped the false-positive-prone bare "exceeds the
  maximum" / "token limit" markers (a param 400 like "temperature exceeds the maximum"
  would mis-suggest /compact). Added a false-positive-boundary test.
- run_timeout: dropped its hint — it is WorkflowEngine-only (a session-path provider
  timeout classifies as provider_unavailable), so it's as unreachable as sandbox_error
  was already excluded (consistent rationale).
- tool_unavailable: added a resend affordance for parity.
- Test drift-guard: derive the taxonomy check from `ERROR_CODES` (partitioned
  hint / no-hint / message-conditional), so a NEW ErrorCode forces a decision.

Docs: chat-session.md tool_failed bullet corrected. lint/typecheck/test/build green
(1582 CLI tests); format clean.

Refs: phase-2.5-cli-consolidation.md (2.5.H)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…l_unavailable

Close the two review-caught HIGHs + the docs/LOW gaps:

- HIGH: the session-continuity recovery hints leaked into `relavium agent run`'s
  PLAIN output — a one-shot that cancels its session in `finally` right after. So
  "the session is still active", `/compact`, resend (a REPL-only affordance) were all
  FALSE there. Gate the hint via `makePlainPrinter(io, recoveryHints = true)`: the
  chat REPL (`drivePlain`) keeps it (session survives); the one-shot `agent run`
  passes `false` → only `[turn failed: <code>]`. A plain-mode agent-run failed-turn
  test + a makePlainPrinter suppression test lock it.
- HIGH: my own step-3-Opus fix over-reached — `tool_unavailable`'s hint became
  "resend and the model will answer without it", an unconditional promise that
  re-fails identically (the capability arm isn't wired for the whole session; it's
  not a `/mode` toggle). Softened to the same no-blind-retry standard the sibling
  tool_failed fix set (rephrase to avoid it, or wire it + fresh session).
- MEDIUM/LOW: docs now enumerate tool_denied/tool_unavailable + the one-shot
  suppression; reorder tool_failed so "session is still active" isn't leading (parity
  with its 8 siblings); drop the dead `context_length` underscore marker (the
  heuristic reads the message, not the code); tighten the `cancelled` rationale (it's
  structurally unreachable — settles as `aborted` with no error); make `internal`'s
  tail concrete (`/doctor`, not a dangling "report it"); add a no-hint plain-printer
  test.

Toolchain: lint/typecheck/test/build green (1585 CLI tests); format clean.

Refs: phase-2.5-cli-consolidation.md (2.5.H)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…5-3 reached

Reconcile the canonical status surfaces now that 2.5.H (reasoning rendering +
live-turn feedback + the actionable error taxonomy, behind EA6 amending ADR-0036)
has landed across four opus+Sonnet-reviewed steps:

- phase-2.5-cli-consolidation.md: a ✅-Done status block on the 2.5.H workstream, the
  top-of-file status line, the milestone table (M2.5-3 reached with 2.5.E), and the
  EA6 "Required ADRs" note (landed).
- current.md + CLAUDE.md: the additive-lane mention updated to 2.5.H ✅ Done (detail
  in current.md per the one-canonical-home rule); the stale "2.5.H / I / J" triple is
  gone (2.5.I / J remain).

(The reference homes — sse-event-schema.md, chat-session.md, commands.md, ADR-0036's
append-only note, deferred-tasks.md — were updated in their own step commits.)

format:check + lint:fence-check clean.

Refs: phase-2.5-cli-consolidation.md (2.5.H, EA6), ADR-0036

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… optional param

The full-repo lint gate flagged `message?: string | undefined` (the `?` already
implies `undefined`) — @typescript-eslint/no-duplicate-type-constituents. Simplify to
`message?: string`; behaviorally identical (a function-parameter optional, not an
exactOptionalPropertyTypes object property). lint/typecheck/test/build all green.

Refs: phase-2.5-cli-consolidation.md (2.5.H)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @cemililik, your pull request is larger than the review limit of 150000 diff characters

@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1f639f5d-22d7-4440-8d8e-02db9a56cc10

📥 Commits

Reviewing files that changed from the base of the PR and between 7d3f935 and f261c54.

📒 Files selected for processing (1)
  • docs/decisions/0036-run-loop-substrate-event-bus-and-execution-host.md

📝 Walkthrough

Walkthrough

This PR adds agent:reasoning across shared contracts, engine/session plumbing, storage, and CLI/TUI rendering. It also introduces /thinking and Ctrl+T toggles, updates plain-output failure rendering, and marks Phase 2.5.H complete in docs and roadmap files.

Changes

Reasoning event and chat UI

Layer / File(s) Summary
Shared event contract
packages/shared/src/run-event.ts, packages/shared/src/constants.ts, packages/shared/src/run-event.test.ts, docs/reference/contracts/sse-event-schema.md, docs/reference/shared-core/agent-runner.md, docs/decisions/0036-run-loop-substrate-event-bus-and-execution-host.md, docs/roadmap/*, CLAUDE.md
Adds agent:reasoning to the shared event vocabulary, schema, docs, and Phase 2.5.H status notes.
Turn emission and session pass-through
packages/core/src/engine/agent-turn.ts, packages/core/src/engine/agent-turn.test.ts, packages/core/src/engine/agent-session.ts, packages/core/src/engine/engine.ts, packages/core/src/engine/engine.test.ts, packages/core/src/engine/node-executor.ts, packages/core/src/engine/session-handle.ts, packages/core/src/engine/session-handle.test.ts
Emits agent:reasoning from turn processing and carries it through engine/session types and tests.
Run history filtering
packages/db/src/run-history-store.ts, packages/db/src/run-history-store.test.ts
Treats agent:reasoning as streaming data excluded from state reconstruction.
Session view model
apps/cli/src/render/tui/session-view-model.ts, apps/cli/src/render/tui/session-view-model.test.ts
Tracks reasoning buffers, truncation, and per-turn model attribution in the session view state.
Chat and run store state
apps/cli/src/render/tui/chat-store.ts, apps/cli/src/render/tui/chat-store.test.ts, apps/cli/src/render/tui/run-store.ts, apps/cli/src/render/tui/run-store.test.ts
Adds reasoningVisible, toggleReasoning, and coalesced handling for agent:reasoning updates.
Projection helpers
apps/cli/src/render/tui/chat-projection.ts, apps/cli/src/render/tui/chat-projection.test.ts, apps/cli/src/render/tui/format.ts, apps/cli/src/render/tui/format.test.ts
Adds elapsed-time formatting, recovery hints, busy-line rendering, reasoning-label logic, and the collapsible reasoning panel projection.
TUI rendering and input
apps/cli/src/render/tui/chat-ink.tsx, apps/cli/src/render/tui/chat-input.ts, apps/cli/src/render/tui/chat-input.test.ts, apps/cli/src/render/tui/home-app.tsx, apps/cli/src/render/tui/home-controller.ts, apps/cli/src/render/tui/home-controller.test.ts
Renders the thinking panel, live timers, and recovery hints, and wires Ctrl+T plus wall-clock timing into the UI.
REPL and plain-output wiring
apps/cli/src/commands/repl-commands.ts, apps/cli/src/commands/repl-commands.test.ts, apps/cli/src/commands/chat.ts, apps/cli/src/commands/chat.test.ts, apps/cli/src/commands/agent-run.ts, apps/cli/src/commands/agent-run.test.ts
Adds /thinking, toggling behavior, and plain-output recovery-hint handling, including the one-shot suppression path.

Estimated code review effort: 4 (Complex) | ~80 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant ChatInput
  participant ChatStore
  participant ChatView

  User->>ChatInput: Ctrl+T
  ChatInput->>ChatStore: toggleReasoning
  ChatStore->>ChatStore: flip reasoningVisible
  ChatStore-->>ChatView: snapshot update
  ChatView-->>User: render /thinking panel
Loading
sequenceDiagram
  participant User
  participant ChatCommand
  participant PlainPrinter
  participant ErrorRecoveryHint

  User->>ChatCommand: turn completes with error
  ChatCommand->>PlainPrinter: session:turn_completed
  PlainPrinter->>PlainPrinter: print [turn failed: code]
  PlainPrinter->>ErrorRecoveryHint: errorRecoveryHint(code, message)
  ErrorRecoveryHint-->>PlainPrinter: hint text or undefined
  PlainPrinter-->>User: emit plain failure output
Loading

Possibly related PRs

  • HodeTech/Relavium#28: Touches the same session-event plumbing and session-stream contract path in packages/core.
  • HodeTech/Relavium#54: Introduces the chat REPL and plain printer that this PR extends with /thinking and recovery hints.
  • HodeTech/Relavium#62: Works in the same in-REPL slash-command registry that this PR extends with /thinking.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the PR’s main scope: Phase 2.5.H reasoning rendering, live feedback, and actionable error handling.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch development

Comment @coderabbitai help to get the list of available commands.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request implements Phase 2.5.H, introducing a collapsible 'thinking' panel for reasoning models, live-turn feedback with an elapsed timer, and actionable error recovery hints for failed turns. It also adds the agent:reasoning event to the event bus and session stream, improves model attribution during failovers, and updates documentation and tests to reflect these changes. I have no feedback to provide.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (4)
docs/reference/cli/commands.md (1)

155-155: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Keep the command reference shallow.

This paragraph duplicates REPL behavior already documented in chat-session.md (/thinking, /effort, /models, bare Home vs live chat). Linking out here would keep the command surface reference from drifting.

Based on learnings, maintain one canonical home per artifact; concrete specs should live only in their docs/reference/ file and be linked elsewhere rather than restated.

Suggested trim
- The interactive `/` palette + slash commands inside the Home and chat are a SEPARATE, curated surface (...) — ... /thinking ... /models ...
+ The interactive `/` palette is a curated, REPL-only surface. See `chat-session.md` for the full behavioral contract.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/reference/cli/commands.md` at line 155, The command reference is too
deep and repeats REPL behavior that is already canonical elsewhere. Trim the
long `/` palette paragraph in commands.md so it only briefly names the in-REPL
commands and links out to chat-session.md and the ADRs for `/thinking`,
`/effort`, and `/models` details, keeping the reference shallow and avoiding
duplicated behavioral specs.

Source: Learnings

apps/cli/src/render/tui/session-view-model.test.ts (2)

625-625: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use toHaveLength for a more specific assertion.

SonarCloud flags this generic length check; toHaveLength gives a clearer failure message.

🧹 Proposed fix
-    expect(state.liveTokens.length).toBe(MAX_LIVE_TOKEN_CHARS); // only the trailing window is kept
+    expect(state.liveTokens).toHaveLength(MAX_LIVE_TOKEN_CHARS); // only the trailing window is kept
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/cli/src/render/tui/session-view-model.test.ts` at line 625, The
assertion in the session-view-model test is using a generic numeric length check
instead of the more specific Jest matcher. Update the expectation in the test
around state.liveTokens to use toHaveLength with MAX_LIVE_TOKEN_CHARS, keeping
the same trailing-window intent while making the assertion clearer and more
descriptive.

Source: Linters/SAST tools


759-759: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use toHaveLength for a more specific assertion.

Same SonarCloud finding as the liveTokens case above.

🧹 Proposed fix
-    expect(state.liveReasoning.length).toBe(MAX_LIVE_TOKEN_CHARS);
+    expect(state.liveReasoning).toHaveLength(MAX_LIVE_TOKEN_CHARS);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/cli/src/render/tui/session-view-model.test.ts` at line 759, The
assertion in the live reasoning test uses a generic numeric length check instead
of the more specific array/string matcher. Update the expectation in the
session-view-model test to use toHaveLength on state.liveReasoning, matching the
existing liveTokens pattern and keeping the assertion tied to the collection
itself.

Source: Linters/SAST tools

apps/cli/src/commands/chat.ts (1)

1687-1725: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extract the nested template literal flagged by SonarCloud.

Line 1722 nests a template literal inside another, which SonarCloud's no-nested-template-literals rule flags as a code smell — confirmed this is a real rule, not a tool false positive.

🧹 Proposed fix
-        const hint = recoveryHints
-          ? errorRecoveryHint(event.error.code, event.error.message)
-          : undefined;
-        io.writeOut(
-          `\n[turn failed: ${event.error.code}]\n${hint === undefined ? '' : `${hint}\n`}`,
-        );
+        const hint = recoveryHints
+          ? errorRecoveryHint(event.error.code, event.error.message)
+          : undefined;
+        const hintLine = hint === undefined ? '' : `${hint}\n`;
+        io.writeOut(`\n[turn failed: ${event.error.code}]\n${hintLine}`);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/cli/src/commands/chat.ts` around lines 1687 - 1725, The nested template
literal inside makePlainPrinter’s session:turn_completed error output is
triggering SonarCloud’s no-nested-template-literals rule. Refactor the
turn-failed message construction in makePlainPrinter so the hint string is built
separately (or via simple concatenation) before passing it to io.writeOut, while
keeping the same recoveryHints and errorRecoveryHint behavior.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@apps/cli/src/commands/chat.ts`:
- Around line 1687-1725: The nested template literal inside makePlainPrinter’s
session:turn_completed error output is triggering SonarCloud’s
no-nested-template-literals rule. Refactor the turn-failed message construction
in makePlainPrinter so the hint string is built separately (or via simple
concatenation) before passing it to io.writeOut, while keeping the same
recoveryHints and errorRecoveryHint behavior.

In `@apps/cli/src/render/tui/session-view-model.test.ts`:
- Line 625: The assertion in the session-view-model test is using a generic
numeric length check instead of the more specific Jest matcher. Update the
expectation in the test around state.liveTokens to use toHaveLength with
MAX_LIVE_TOKEN_CHARS, keeping the same trailing-window intent while making the
assertion clearer and more descriptive.
- Line 759: The assertion in the live reasoning test uses a generic numeric
length check instead of the more specific array/string matcher. Update the
expectation in the session-view-model test to use toHaveLength on
state.liveReasoning, matching the existing liveTokens pattern and keeping the
assertion tied to the collection itself.

In `@docs/reference/cli/commands.md`:
- Line 155: The command reference is too deep and repeats REPL behavior that is
already canonical elsewhere. Trim the long `/` palette paragraph in commands.md
so it only briefly names the in-REPL commands and links out to chat-session.md
and the ADRs for `/thinking`, `/effort`, and `/models` details, keeping the
reference shallow and avoiding duplicated behavioral specs.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7f7708c0-767d-4841-b39e-b2bc77dad42d

📥 Commits

Reviewing files that changed from the base of the PR and between eca235b and 9c62ae9.

📒 Files selected for processing (44)
  • CLAUDE.md
  • apps/cli/src/commands/agent-run.test.ts
  • apps/cli/src/commands/agent-run.ts
  • apps/cli/src/commands/chat.test.ts
  • apps/cli/src/commands/chat.ts
  • apps/cli/src/commands/repl-commands.test.ts
  • apps/cli/src/commands/repl-commands.ts
  • apps/cli/src/render/tui/chat-ink.tsx
  • apps/cli/src/render/tui/chat-input.test.ts
  • apps/cli/src/render/tui/chat-input.ts
  • apps/cli/src/render/tui/chat-projection.test.ts
  • apps/cli/src/render/tui/chat-projection.ts
  • apps/cli/src/render/tui/chat-store.test.ts
  • apps/cli/src/render/tui/chat-store.ts
  • apps/cli/src/render/tui/format.test.ts
  • apps/cli/src/render/tui/format.ts
  • apps/cli/src/render/tui/home-app.tsx
  • apps/cli/src/render/tui/home-controller.test.ts
  • apps/cli/src/render/tui/home-controller.ts
  • apps/cli/src/render/tui/run-store.test.ts
  • apps/cli/src/render/tui/run-store.ts
  • apps/cli/src/render/tui/session-view-model.test.ts
  • apps/cli/src/render/tui/session-view-model.ts
  • docs/decisions/0036-run-loop-substrate-event-bus-and-execution-host.md
  • docs/reference/cli/chat-session.md
  • docs/reference/cli/commands.md
  • docs/reference/contracts/sse-event-schema.md
  • docs/reference/shared-core/agent-runner.md
  • docs/roadmap/current.md
  • docs/roadmap/deferred-tasks.md
  • docs/roadmap/phases/phase-2.5-cli-consolidation.md
  • packages/core/src/engine/agent-session.ts
  • packages/core/src/engine/agent-turn.test.ts
  • packages/core/src/engine/agent-turn.ts
  • packages/core/src/engine/engine.test.ts
  • packages/core/src/engine/engine.ts
  • packages/core/src/engine/node-executor.ts
  • packages/core/src/engine/session-handle.test.ts
  • packages/core/src/engine/session-handle.ts
  • packages/db/src/run-history-store.test.ts
  • packages/db/src/run-history-store.ts
  • packages/shared/src/constants.ts
  • packages/shared/src/run-event.test.ts
  • packages/shared/src/run-event.ts

…ertions, doc depth)

Address the PR #68 SonarCloud + review findings (all verified valid against current
code; minimal changes):

- chat.ts makePlainPrinter: extract the optional recovery-hint LINE into `hintLine`
  before io.writeOut, removing the nested template literal (no-nested-template-literals)
  — identical output/behavior.
- session-view-model.test.ts: `expect(state.liveTokens/liveReasoning).toHaveLength(
  MAX_LIVE_TOKEN_CHARS)` instead of the generic `.length).toBe(...)` (clearer matcher,
  same intent).
- commands.md: trim the deep `/` in-REPL-slash paragraph — it restated /models reseat/
  write-default + the effort sub-step + picker UX that is canonically homed in
  chat-session.md + ADR-0059/0063/0064/0066 (CLAUDE.md rule 8). Now names the commands
  + links out; the commands.md-unique content (two-registry model, shell-vs-REPL
  boundary, arg/positional/unknown-slash, palette entry) is kept.

lint/typecheck/test/build green; format:check clean.

Refs: phase-2.5-cli-consolidation.md (2.5.H)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@cemililik

Copy link
Copy Markdown
Contributor Author

@coderabbitai review all

@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown

@cemililik Sure, I'll perform a full review of all the changes in this PR.

✅ Action performed

Full review finished.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
docs/decisions/0036-run-loop-substrate-event-bus-and-execution-host.md (1)

12-13: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Amendment doesn't reconcile the now-stale "four reused" count in the original Decision body.

The EA6 amendment correctly documents agent:reasoning as a new dual-envelope reused event, but the unchanged Decision bullet at Line 32 still reads "the four reused agent:* / cost:updated events" — that count is now five (agent:token / agent:reasoning / agent:tool_call / agent:tool_result / cost:updated), matching the updated wording elsewhere in this PR (run-event.ts, sse-event-schema.md). Since ADRs are append-only, the original bullet shouldn't be rewritten — but the amendment note should call out that the "four reused" language in the Decision section is now superseded to five, so a reader isn't left with a silently stale count.

As per coding guidelines, docs/decisions/**/*.md: "Record non-trivial decisions as ADRs in docs/decisions/ using the condensed MADR form, and treat ADRs as append-only: supersede them with a new ADR rather than rewriting history."

📝 Proposed clarification in the amendment note
 > **Amended 2026-07-07 by Phase 2.5.H (EA6).** A refinement, not a reversal: 2.5.H adds one additive **dual-envelope** stream event `agent:reasoning` — the reasoning ("thinking") counterpart of `agent:token` — emitted by the correlation-agnostic agent turn core per `reasoning_delta` chunk, through the single producer-side translation point this ADR defines (so it is `sequenceNumber`-stamped and masked like every other event). It is a **pure host-emit**: the `@relavium/llm` seam already carries the reasoning chunks (ADR-0030), which the turn core previously only *accumulated* with no event of their own; the seam and the engine architecture are unchanged. It carries `text` + `model` but **never** the ephemeral same-provider `signature` (ADR-0030 — never written to an event or log). A `default`-arm consumer ignores the new arm forward-compatibly (there is no `assertNever` over the union). Canonical home [sse-event-schema.md](../reference/contracts/sse-event-schema.md) + the drift-pin test are updated with it; this ADR's substrate decisions stand. (EA6 needs no top-level ADR of its own — it is an additive event in the shared union, tracked in the [Phase 2.5 engine-amendments appendix](../roadmap/phases/phase-2.5-cli-consolidation.md#engine-amendments-appendix-ea1ea8).)
+>
+> Note: the "one bus, two namespaces" bullet below still says "the four reused `agent:*` / `cost:updated` events" — as of this amendment that count is **five** (`agent:token` / `agent:reasoning` / `agent:tool_call` / `agent:tool_result` / `cost:updated`); the original bullet is left as historical record per this ADR's append-only convention.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/decisions/0036-run-loop-substrate-event-bus-and-execution-host.md`
around lines 12 - 13, Update the EA6 amendment note in this ADR to explicitly
supersede the stale “four reused” count in the original Decision section, since
the reusable `agent:*` / `cost:updated` event set is now five. Keep the original
Decision text unchanged, but add clarifying wording in the amendment around the
`agent:reasoning` addition that the prior count is now superseded by the
expanded set (`agent:token`, `agent:reasoning`, `agent:tool_call`,
`agent:tool_result`, `cost:updated`) so readers are not left with an outdated
total.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@docs/decisions/0036-run-loop-substrate-event-bus-and-execution-host.md`:
- Around line 12-13: Update the EA6 amendment note in this ADR to explicitly
supersede the stale “four reused” count in the original Decision section, since
the reusable `agent:*` / `cost:updated` event set is now five. Keep the original
Decision text unchanged, but add clarifying wording in the amendment around the
`agent:reasoning` addition that the prior count is now superseded by the
expanded set (`agent:token`, `agent:reasoning`, `agent:tool_call`,
`agent:tool_result`, `cost:updated`) so readers are not left with an outdated
total.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a94b4d18-a542-4801-ac4d-786b16fe3355

📥 Commits

Reviewing files that changed from the base of the PR and between eca235b and 7d3f935.

📒 Files selected for processing (44)
  • CLAUDE.md
  • apps/cli/src/commands/agent-run.test.ts
  • apps/cli/src/commands/agent-run.ts
  • apps/cli/src/commands/chat.test.ts
  • apps/cli/src/commands/chat.ts
  • apps/cli/src/commands/repl-commands.test.ts
  • apps/cli/src/commands/repl-commands.ts
  • apps/cli/src/render/tui/chat-ink.tsx
  • apps/cli/src/render/tui/chat-input.test.ts
  • apps/cli/src/render/tui/chat-input.ts
  • apps/cli/src/render/tui/chat-projection.test.ts
  • apps/cli/src/render/tui/chat-projection.ts
  • apps/cli/src/render/tui/chat-store.test.ts
  • apps/cli/src/render/tui/chat-store.ts
  • apps/cli/src/render/tui/format.test.ts
  • apps/cli/src/render/tui/format.ts
  • apps/cli/src/render/tui/home-app.tsx
  • apps/cli/src/render/tui/home-controller.test.ts
  • apps/cli/src/render/tui/home-controller.ts
  • apps/cli/src/render/tui/run-store.test.ts
  • apps/cli/src/render/tui/run-store.ts
  • apps/cli/src/render/tui/session-view-model.test.ts
  • apps/cli/src/render/tui/session-view-model.ts
  • docs/decisions/0036-run-loop-substrate-event-bus-and-execution-host.md
  • docs/reference/cli/chat-session.md
  • docs/reference/cli/commands.md
  • docs/reference/contracts/sse-event-schema.md
  • docs/reference/shared-core/agent-runner.md
  • docs/roadmap/current.md
  • docs/roadmap/deferred-tasks.md
  • docs/roadmap/phases/phase-2.5-cli-consolidation.md
  • packages/core/src/engine/agent-session.ts
  • packages/core/src/engine/agent-turn.test.ts
  • packages/core/src/engine/agent-turn.ts
  • packages/core/src/engine/engine.test.ts
  • packages/core/src/engine/engine.ts
  • packages/core/src/engine/node-executor.ts
  • packages/core/src/engine/session-handle.test.ts
  • packages/core/src/engine/session-handle.ts
  • packages/db/src/run-history-store.test.ts
  • packages/db/src/run-history-store.ts
  • packages/shared/src/constants.ts
  • packages/shared/src/run-event.test.ts
  • packages/shared/src/run-event.ts

…w five)

The Decision §"One bus, two namespaces" still reads "the four reused agent:*/
cost:updated events"; EA6 (2.5.H) made `agent:reasoning` a fifth. Per the
append-only ADR rule the Decision text stays unedited — add a clarifying clause to
the 2026-07-07 EA6 amendment note stating it supersedes that count: the reused
dual-envelope set is now five (agent:token, agent:reasoning, agent:tool_call,
agent:tool_result, cost:updated). No other change.

format:check clean.

Refs: ADR-0036, phase-2.5-cli-consolidation.md (2.5.H, EA6)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@sonarqubecloud

sonarqubecloud Bot commented Jul 7, 2026

Copy link
Copy Markdown

@cemililik
cemililik merged commit 84fb7a4 into main Jul 7, 2026
8 of 9 checks passed
cemililik added a commit that referenced this pull request Jul 7, 2026
2.5.H landed on main (PR #68, development→main). Add the workstream PR reference
(#67 — the 2.5.H feature PR to development, matching how 2.5.A–G cite their feature
PR; #68 is the dev→main release mechanism, like #66) to the 2.5.H status surfaces:
phase-2.5-cli-consolidation.md (top status + the 2.5.H block header + Status line),
current.md, and CLAUDE.md. Date-only; no other change.

format:check + lint:fence-check clean.

Refs: phase-2.5-cli-consolidation.md (2.5.H)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant