Skip to content

feat(workflows): show model + thinking level on graph node cards - #1859

Open
sina85 wants to merge 14 commits into
bastani-inc:mainfrom
sina85:feat/background-widget-model-thinking
Open

feat(workflows): show model + thinking level on graph node cards#1859
sina85 wants to merge 14 commits into
bastani-inc:mainfrom
sina85:feat/background-widget-model-thinking

Conversation

@sina85

@sina85 sina85 commented Jul 18, 2026

Copy link
Copy Markdown

What this does

Shows the effective model + thinking level (and Codex fast tier) for each workflow stage on the /workflow connect graph node cards, and persists that identity across /workflow resume. The main-session footer has always shown <model> <thinking>, but background/orchestrated runs were opaque about which model (and reasoning level) each stage used. This closes that gap in the place you inspect a running workflow — the graph overlay.

Scope note: an earlier revision of this PR also added the same display to the above-editor BACKGROUND widget. Per review that has been removed — the widget summarizes each run on a single line, so a parallel fan-out on several models has no clean way to show them. Model/thinking/fast identity lives only on the graph node cards, which have one card per stage and room to show each. This PR now has zero net diff to widget.ts.

1. Graph node cards (/workflow connect)

Node cards showed title / duration / status / deps but deliberately hid the model. They now carry a dedicated compact model row beneath the status line:

╭───── specialist ─────╮  ╭─────── scout ────────╮  ╭───── codex-fix ──────╮
│         12s          │  │          8s          │  │          8s          │
│      ● running       │  │      ● running       │  │      ● running       │
│claude-opus-4.8 · high│  │        gpt-5         │  │  gpt-5.1-codex fast  │
│         root         │  │         root         │  │         root         │
╰──────────────────────╯  ╰──────────────────────╯  ╰──────────────────────╯
  • Provider prefix dropped and thinking omitted when off to fit the ~22-cell card; shows when no model is resolved yet.
  • Codex fast tier is appended on the model row, mirroring the footer's formatCodexFastModeModelLabel (<model> <thinking> fast). When the card would overflow, the thinking level is dropped so the fast marker is never truncated away.
  • Live model fallbacks are reflected: when a stage falls back to another model the row updates to the model actually running (it renders from the live StageSnapshot.model, which applyModelFallbackMeta rewrites on each fallback).
  • Cards grow from 5 → 6 rows (NODE_H); graph layout and edge routing derive from NODE_H and adapt automatically.

2. Persistence across /workflow resume

thinkingLevel now rides alongside model at every serialize/restore site of the mandatory DBOS durable path — the DurableStageCheckpoint type, stage/task checkpoint metadata, the DBOS envelope encode/validate/decode, the completed-run catalog merge, checkpoint→snapshot hydration, and the replay __modelFallbackMeta (plus WorkflowTaskResult). A resumed run therefore restores the same model + thinking identity, not just the model.

Plumbing (shared live-snapshot path)

  • StageModelFallbackMeta gains thinkingLevel, populated by StageSessionController.currentModelFallbackMeta() from the live session (or a pending level set before the session exists).
  • executor-stage-factory's applyModelFallbackMeta writes it to StageSnapshot.thinkingLevel, next to the existing model field.
  • The node card renders the compact <short-model> · <thinking> [fast] row via a small local codex-fast-label.ts — a mirror of the footer helper, kept local because importing the @bastani/atomic barrel into the TUI module graph breaks the pi-tui-mocked overlay test subprocesses.

Contract change

The node cards previously hid the model by design; this reverses that. The three tests pinning the old behavior are updated to assert the model row is shown, and the dependency-row assertions move down one row.

Tests

  • node-card.test.ts: compact model row; thinking append/omit; fast marker on the model row (not the deps row); width-guard (drop the level to preserve fast); when absent; mid-run fallback swap; geometry (NODE_H = 6).
  • durable-dbos-topology.test.ts: model + thinking-level round-trip through the DBOS envelope (encode → decode).
  • durable-stage-frontier-fixes.test.ts: cached-replay hydration restores thinkingLevel (checkpoint → snapshot).
  • stage-runner-reasoning-suffix.test.ts: a 429 fallback surfaces the fallback model and thinking level on meta.
  • bun run typecheck / lint / check:file-length clean; the overlay-graph-* and durable-* suites pass.

Notes

  • Rebased onto the latest main.
  • The only test:unit failures on this branch (MCP lazy-startup ×3 and the Pi v0.81.1 declarations and publish artifacts sync check) reproduce identically with these changes stashed on a clean tree — pre-existing and unrelated.

Greptile Summary

This PR shows workflow stage model identity on graph node cards and preserves it across resume. The main changes are:

  • Adds a compact model row with thinking level and Codex fast tier to graph node cards.
  • Threads thinkingLevel through live fallback metadata, task results, replay, and DBOS checkpoint encode/decode.
  • Updates node-card layout height and tests for rendering, replay hydration, and fallback metadata.

Confidence Score: 5/5

This PR is safe to merge with minimal risk.

The changes consistently extend existing model metadata paths with thinkingLevel and include tests for DBOS round-trip, cached replay, executor replay, fallback metadata, and node-card rendering. No verified functional or security issues were found.

Files Needing Attention: No files require special attention.

T-Rex T-Rex Logs

What T-Rex did

  • Ran the focused Vitest test suite for the node-card workflow and confirmed 2 test files and 49 tests passed with exit code 0.
  • Generated and wired a render harness that imports and executes the repository's TUI renderer modules.
  • Rendered the node-card across all requested model/thinking/fast/fallback/em-dash/geometry cases and verified exit code 0.

View all artifacts

T-Rex Ran code and verified through T-Rex

Important Files Changed

Filename Overview
packages/workflows/src/tui/node-card.ts Renders a compact model/thinking/fast row while keeping dependency metadata separate.
packages/workflows/src/runs/foreground/stage-runner-controller.ts Adds current fallback metadata support for pending or live session thinking level.
packages/workflows/src/runs/foreground/executor-stage-factory.ts Copies replay model identity into snapshots and applies live fallback thinkingLevel updates.
packages/workflows/src/durable/dbos-envelope.ts Adds DBOS envelope encode/decode validation for thinkingLevel.
packages/workflows/src/durable/stage-primitive.ts Propagates task and cached replay thinkingLevel metadata through checkpoint hydration.
test/unit/node-card.test.ts Updates and expands node card rendering tests for model rows, thinking levels, fast marker preservation, and geometry.
test/unit/executor-replay-model-identity.test.ts Adds tests for replayed stages retaining or omitting model identity as persisted.

Sequence Diagram

sequenceDiagram
  participant Stage as StageSessionController
  participant Factory as executor-stage-factory
  participant Store as StageSnapshot / Store
  participant DBOS as DBOS checkpoint envelope
  participant TUI as Graph node card

  Stage->>Stage: Resolve selected model + thinkingLevel + fastMode
  Stage-->>Factory: __modelFallbackMeta()
  Factory->>Store: Apply model, thinkingLevel, fastMode to StageSnapshot
  Store->>DBOS: encodeCheckpoint() persists metadata
  DBOS-->>Store: decode/hydrate on resume or replay
  Store-->>TUI: StageSnapshot model identity
  TUI->>TUI: Render compact model row under status
Loading

Reviews (13): Last reviewed commit: "fix(workflows): reserve the thinking lev..." | Re-trigger Greptile

@sina85 sina85 changed the title feat(workflows): show model + thinking level on background widget feat(workflows): show model + thinking level on background widget and graph node cards Jul 18, 2026
@sina85
sina85 marked this pull request as ready for review July 18, 2026 03:27

@lavaman131 lavaman131 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Hey @sina85, thanks for the contribution. This looks like a very cool idea! For the background widget change can you make sure that parallel workflow stages with different models are intuitive to see? I think the graph node cards are cleaner since they can each show the model, but the background widget gets messy. Also, can you make sure you properly handle model fallbacks and change the model in the node card when that happens? Another edge case is to make sure you display (fast) for the model if using the fast tier for OpenAI providers. Finally, you need to make sure that when you run /workflow resume that this data is saved. If you give evidence for each of these will review again and we can look into getting this checked in for the next release.

@sina85

sina85 commented Jul 18, 2026

Copy link
Copy Markdown
Author

Hi @lavaman131, thanks for the feedback, I will double check the edge cases and get back to you.

@sina85
sina85 force-pushed the feat/background-widget-model-thinking branch from e94b547 to b732e18 Compare July 22, 2026 00:10
@sina85

sina85 commented Jul 22, 2026

Copy link
Copy Markdown
Author

@lavaman131 thanks for the detailed review.

Update (edited): after the first pass I reconsidered your parallel point and removed the model/thinking display from the BACKGROUND widget entirely — you were right that a single per-run line gets messy for a parallel fan-out, and the widget isn't the place for it. That identity now lives only on the /workflow connect graph node cards (one card per stage, so each shows its own model). The PR now has zero net diff to widget.ts. Evidence for the node-card work + persistence below; all four of your points are addressed (point 1 by removal).

1. Parallel stages → handled by the graph node cards, not the widget

Per your observation, the widget was the wrong surface. Each stage gets its own node card, so parallel stages on different models are each shown cleanly, no cramming:

╭───── specialist ─────╮  ╭─────── scout ────────╮  ╭───── codex-fix ──────╮
│         12s          │  │          8s          │  │          8s          │
│      ● running       │  │      ● running       │  │      ● running       │
│claude-opus-4.8 · high│  │        gpt-5         │  │  gpt-5.1-codex fast  │
│         root         │  │         root         │  │         root         │
╰──────────────────────╯  ╰──────────────────────╯  ╰──────────────────────╯

2. Model fallbacks update the node card

The card renders from the live StageSnapshot.model, which applyModelFallbackMeta rewrites on every fallback, so the displayed model swaps to the model actually running. Proven on both halves of the chain:

  • controller → meta: stage-runner-reasoning-suffix.test.ts now asserts that after a 429 fallback meta.model === "openai/fallback" (the fallback, not the failed primary).
  • render: node-card.test.ts"model row reflects a fallback swapping the stage's model mid-run" renders the same snapshot before/after the swap.

3. Fast tier shown with the model

Mirrors the footer's formatCodexFastModeModelLabel (<model> <thinking> fast). On the node card the fast marker sits on the model row (off the deps row); when the ~22‑cell card would overflow, the thinking level is dropped so the marker is never truncated:

fast tier on model row            width-guard (·high dropped, fast kept)
╭───── specialist ─────╮          ╭───── specialist ─────╮
│         12s          │          │         12s          │
│      ● running       │          │      ● running       │
│  gpt-5.1-codex fast  │          │  gpt-5.1-codex fast  │
│         root         │          │         root         │
╰──────────────────────╯          ╰──────────────────────╯

Tests: node‑card "shows the fast tier on the model row, not the deps row", "…keeps both the thinking level and the fast marker when they fit", "…drops the thinking level to preserve the fast marker when the card would overflow".

4. /workflow resume persists the data

Promoted the deferred follow‑up into this PR. thinkingLevel now rides alongside model at every serialize/restore site of the mandatory DBOS durable path — the DurableStageCheckpoint type, stage/task checkpoint metadata, the DBOS envelope encode/validate/decode, the completed‑run catalog merge, the checkpoint→snapshot hydration, and the replay __modelFallbackMeta (plus WorkflowTaskResult). Tests:

  • durable-dbos-topology.test.ts"round-trips stage model + thinking-level metadata through the DBOS envelope" (encode → decode).
  • durable-stage-frontier-fixes.test.ts → the cached‑replay hydration test now asserts stage.thinkingLevel survives checkpoint → snapshot.

Verification

  • bun run typecheck / bun run lint clean; bun run check:file-length passes. widget.ts and its test are reverted to upstream (zero widget diff); the shared codex-fast-label.ts stays for the node card, mirroring formatCodexFastModeModelLabel locally so the @bastani/atomic barrel never enters the TUI module graph (importing it breaks the pi-tui‑mocked overlay test subprocesses).
  • Full test:unit is green apart from 4 pre‑existing failures (MCP lazy‑startup ×3 and the Pi v0.81.1 declarations and publish artifacts sync check), which reproduce identically with these changes stashed on a clean tree — unrelated to this PR.
  • Rebased onto the latest main.

@sina85 sina85 changed the title feat(workflows): show model + thinking level on background widget and graph node cards feat(workflows): show model + thinking level on graph node cards Jul 22, 2026
Comment on lines +215 to +219
* {@link model} so background-run surfaces can show the same model +
* thinking identity the main session footer shows. Optional: absent for
* restored runs and stages whose model has no reasoning control.
*/
thinkingLevel?: string;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Widget path missing
StageSnapshot.thinkingLevel is documented for background-run surfaces here, but packages/workflows/src/tui/widget.ts still builds its meta line only from mode, progress, and elapsed time (metaLine/themedRunLines), so the BACKGROUND widget never displays the model or thinking level promised by this PR. This leaves direct background runs opaque even when stageSnapshot.model and thinkingLevel are populated.

Context Used: AGENTS.md (source)

Artifacts

Repro: Bun TypeScript harness that renders the real BACKGROUND widget with populated stage model and thinkingLevel

  • Contains supporting evidence from the run (text/typescript; charset=utf-8).

Repro: execution output showing the widget meta line omits model and thinking level

  • Keeps the command output available without making the summary code-heavy.

View artifacts

T-Rex Ran code and verified through T-Rex

Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/workflows/src/shared/store-types.ts
Line: 215-219

Comment:
**Widget path missing**
`StageSnapshot.thinkingLevel` is documented for background-run surfaces here, but `packages/workflows/src/tui/widget.ts` still builds its meta line only from `mode`, progress, and elapsed time (`metaLine`/`themedRunLines`), so the `BACKGROUND` widget never displays the model or thinking level promised by this PR. This leaves direct background runs opaque even when `stageSnapshot.model` and `thinkingLevel` are populated.

**Context Used:** AGENTS.md ([source](https://app.greptile.com/bastani-inc/github/bastani-inc/atomic/-/custom-context?memory=6b6bc6e3-dafb-4fa7-9d98-538aac70844a))

How can I resolve this? If you propose a fix, please make it concise.

@sina85
sina85 force-pushed the feat/background-widget-model-thinking branch from a256d30 to a6b8afb Compare July 22, 2026 19:48

@lavaman131 lavaman131 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Hey @sina85, can you address the review bot (Greptile) feedback and rebase with the latest origin/main. Otherwise, once you do that, looks great and we can check it in pending CI is green.

@sina85
sina85 force-pushed the feat/background-widget-model-thinking branch 2 times, most recently from 25400a3 to 8930fb1 Compare July 26, 2026 20:35
@sina85
sina85 requested a review from lavaman131 July 26, 2026 20:42
@sina85
sina85 force-pushed the feat/background-widget-model-thinking branch from 8930fb1 to 168d858 Compare July 29, 2026 21:41
sina85 and others added 9 commits July 30, 2026 10:01
The background-workflow (BACKGROUND) widget listed each running direct
task/chain with mode, progress, and duration, but not which model or
thinking level the run was using — information the main-session footer
already shows. Background runs were opaque about their model identity.

Surface the running stage's model and thinking level on each run card,
mirroring the footer's `<model> <thinking>` format (thinking omitted when
off). Chains show the currently running stage's model; the segment is
skipped until a stage records an effective model.

Plumbing (live snapshot path):
- StageModelFallbackMeta gains `thinkingLevel`, populated by the stage
  controller from the live session (or a pending level).
- The executor applies it to `StageSnapshot.thinkingLevel`, next to the
  existing `model` field.
- The widget's meta line renders `<model> <thinking>` for the active stage.

Scope: live in-memory snapshot only (the "currently running" case). Durable
persistence parity for thinkingLevel is a follow-up; `model` already persists.

Tests: widget rendering for single/chain/off/no-model cases, plus a
controller assertion that the session's thinking level reaches the meta.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Extend the model/thinking transparency to the `/workflow connect` graph
overlay. The orchestrator node cards showed title, duration, status, and
dependency (root/deps) metadata but deliberately hid the model — so an
attached run gave no per-stage model visibility.

Add a dedicated compact model row to each node card, beneath the status
line: `<short-model> · <thinking>`. The provider prefix is dropped and the
thinking level is omitted when off so it fits the ~22-cell card; `—` shows
when no model is resolved yet. All existing fields are preserved (duration,
status, deps), so the card grows from 5 to 6 rows (NODE_H). The graph layout
and edge routing derive from NODE_H and adapt automatically.

Reverses the earlier "cards hide model metadata" contract; the three tests
that pinned it are updated to assert the model row is shown, and the
dependency-row assertions move one row down.

Tests: node-card model row (compact model, thinking append/omit, em-dash
when absent, fast marker stays on the deps row); full overlay-graph suite
passes unchanged against the new height.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…he BACKGROUND widget

Addresses review feedback that the widget "gets messy" for parallel stages
and did not show the Codex fast tier.

- Parallel fan-outs: when >1 stage runs concurrently the run is labelled
  `parallel`, and if those stages use different models the segment lists the
  distinct, provider-stripped models deduped and capped with `+N`
  (e.g. `gpt-5, opus +1`). Single-model runs are unchanged (full provider id).
- Fast tier: the active-stage model now appends the Codex `fast` marker,
  mirroring the main-session footer (`<model> <thinking> fast`).

Extracts the model-segment formatting into `widget-model-label.ts` and the
fast-tier suffix into `codex-fast-label.ts` (a local mirror of
`formatCodexFastModeModelLabel` — importing the `@bastani/atomic` barrel into
the TUI graph breaks the pi-tui-mocked overlay test subprocesses). Keeps
widget.ts under the 500-line gate; the model+thinking tests move to a
dedicated `widget-model-thinking.test.ts` for the same reason.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…lect model fallbacks

Addresses review feedback to display `(fast)` for the fast tier and to update
the node card's model when a fallback changes it.

- The fast tier now rides the model row (footer parity) instead of the
  dependency row; the deps row returns to plain `root`/`N deps`. When the
  card would overflow (~22 cells) the thinking level is dropped so the fast
  marker is never truncated away.
- The model row renders from the live `StageSnapshot.model`, which
  `applyModelFallbackMeta` rewrites on every fallback — so a fallback visibly
  swaps the displayed model. Added a test rendering the same snapshot before
  and after a fallback to lock this in.

The three tests that pinned the old "fast on the deps row" behaviour are
updated; new tests cover the width-guard and the fallback swap.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Extends the reasoning-suffix retry test to assert that after a 429 fallback
the meta surfaced to the background/graph UIs (`meta.model` →
`StageSnapshot.model` → node card) is the fallback model, not the failed
primary — the controller→meta→snapshot half of the fallback-display chain.

Also condenses two `StageSessionController` helpers to keep the file within
the 500-line gate after the earlier thinking-level addition.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Addresses review feedback that `/workflow resume` must save this data. The
PR previously scoped durable persistence of `thinkingLevel` as a follow-up;
this promotes it into the PR so restored runs show the same model + thinking
identity, not just the model.

`thinkingLevel` now rides alongside `model` at every serialize/restore site
of the mandatory DBOS durable path: the `DurableStageCheckpoint` type, the
stage/task checkpoint metadata, the DBOS envelope encode/validate/decode,
the completed-run catalog merge, the checkpoint→snapshot hydration, and the
replay `__modelFallbackMeta`. `WorkflowTaskResult` carries it too.

Tests: the DBOS envelope round-trip and the cached-replay hydration test now
assert `thinkingLevel` survives encode→decode and checkpoint→snapshot.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…urfaces

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…dget

Per review, the model + thinking + fast display does not belong on the
above-editor BACKGROUND widget: it summarises each run on a single line, so
a parallel fan-out on several models has no clean way to show them (that was
the "gets messy" concern). Model/thinking/fast identity stays on the
`/workflow connect` graph node cards, which have one box per stage and room
to show each model.

Restores widget.ts and widget-rendering.test.ts to their upstream state
(zero net widget diff on this PR) and removes the widget-only helper and
test (`widget-model-label.ts`, `widget-model-thinking.test.ts`). The shared
`codex-fast-label.ts` stays — the node card still uses it. Node-card model
row, live fallback reflection, and durable `thinkingLevel` persistence are
unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Review feedback: `/workflow resume` persisted the model + thinking identity
but never rendered it. `shouldReplay` stages build their graph node card from
the replay-source snapshot, and that initialization copied only the result and
session fields -- `model`, `thinkingLevel`, and `fastMode` were left absent, so
a replayed card rendered the em-dash placeholder instead of the restored model
row. The durable layer was already storing them; only the read-back was
missing.

`replaySource` is a full `StageSnapshot`, so the persisted values are copied
straight across next to the existing session fields, guarded the same way.

Also retires the stale `StageSnapshot.thinkingLevel` doc wording: it pointed at
"background-run surfaces" (from when the BACKGROUND widget was in scope, since
reverted) and claimed the level is "absent for restored runs", which this
change makes untrue. It now names the graph node card and the resume path.

Tests: a new continuation-replay suite asserts a resumed run restores model,
thinking level, and fast tier onto the replayed stage, and that a source
without model identity does not gain one. This covers a different path from the
existing `recordCachedStageIntoStore` hydration test -- the continuation
snapshot path is the one that regressed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@sina85
sina85 force-pushed the feat/background-widget-model-thinking branch from 168d858 to 644ae34 Compare July 30, 2026 17:03
sina85 added 3 commits August 3, 2026 11:36
Bring the node-card model/thinking/fast + durable thinkingLevel persistence
up to date with upstream's tabs reformat, the ModelRuntime refactor (bastani-inc#2064),
and the reshaped graph node cards (bastani-inc#2140). Re-applied thinkingLevel across
the durable serialize/restore path, integrated the model row into the
reshaped card, and preserved the replay model-identity fix. NODE_H stays 6
for the model row; updated the bastani-inc#2100 graph-perf composed-row expectation to
match the taller card.
Bring node-card model/thinking display + durable thinkingLevel persistence up
to date with upstream 0.9.12. Only CHANGELOG conflicted (our [Unreleased]
bullet vs the cut 0.9.12 release section); the thinkingLevel type additions
auto-merged.
Bring node-card model/thinking display + durable thinkingLevel persistence up
to date with upstream 0.9.13-alpha.1. Only CHANGELOG conflicted; the
stage-runner thinkingLevel additions auto-merged cleanly against upstream's
model-fallback convergence (bastani-inc#2201).
@flora131

flora131 commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator

Sorry for the delay in responding. I just had a chance to check this after the latest commits. I really appreciate the contribution.

I verified the exact PR head (23eb0c23eb5881c102b78585387c20979d702d62) using the local Atomic CLI in tmux and found three blockers:

  1. The new replay test suite does not load under the repository’s test runner.

    test/unit/executor-replay-model-identity.test.ts:14 imports describe from bun:test, but root unit tests run under Node/Vitest.

    Repro:

    npx vitest --run --project unit \
      test/unit/node-card.test.ts \
      test/unit/executor-replay-model-identity.test.ts \
      test/unit/durable-dbos-topology.test.ts \
      test/unit/durable-stage-frontier-fixes.test.ts \
      test/unit/stage-runner-reasoning-suffix.test.ts \
      test/unit/overlay-graph-perf.test.ts

    Result:

    Cannot find package 'bun:test'
    

    Please use the repository’s Vitest imports so the two new replay tests execute.

  2. A long configured Codex model name truncates the required fast marker.

    Rendering openai-codex/gpt-5.3-codex-spark in fast mode produces:

    │gpt-5.3-codex-spark f…│
    

    The model comes from the configured catalog. The card should reserve enough room for the full fast marker, truncating the model name first if needed. Please add a regression test for this long-name case.

  3. The changed files fail the repository’s Biome gate.

    npm run check reports five formatting/import errors in the new or modified files, including indentation, import order, and comment spacing. Please format the branch and rerun the check.

The core behavior otherwise worked in manual testing: model and thinking rows appeared in /workflow connect, off was omitted, unresolved identity showed , the six-row layout remained readable, and same-process /workflow resume retained the model and thinking level.

Please rerun the focused tests and npm run check after addressing these items.

@flora131

flora131 commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator

By the way, you can also ask Atomic to verify your PR directly. For example:

Can you run a workflow to verify this PR? Check out the exact PR head in an isolated worktree, run that checkout’s local Atomic CLI inside a tmux session, and manually test the behavior covered by the PR. Please run the relevant automated checks as well. If you find any bugs, document each one with reproduction steps, expected and actual behavior, and return the findings inline when the workflow completes.

PR: #1859

You can ask to attach evidence to this PR or even change the prompt to automatically apply the fixes.

@sina85

sina85 commented Aug 7, 2026

Copy link
Copy Markdown
Author

By the way, you can also ask Atomic to verify your PR directly. For example:

Can you run a workflow to verify this PR? Check out the exact PR head in an isolated worktree, run that checkout’s local Atomic CLI inside a tmux session, and manually test the behavior covered by the PR. Please run the relevant automated checks as well. If you find any bugs, document each one with reproduction steps, expected and actual behavior, and return the findings inline when the workflow completes.
PR: #1859

Thanks for replying, I will run those changes and update the PR.

Resolves @flora131's three blockers on bastani-inc#1859:

1. The new replay-identity test imported `describe` from `bun:test`, so it
   failed to load under the repo's Vitest runner
   ("Cannot find package 'bun:test'"). Switched to the `vitest` import; the
   suite now runs and passes under `vitest --run --project unit`.
2. A long configured Codex model name truncated the required `fast` marker
   (`gpt-5.3-codex-spark f…`). `modelText` now drops the thinking level first
   and then truncates the model name, reserving the whole ` fast` marker so it
   is never cut. Added a long-name regression test.
3. Formatted the branch with Biome (tabs in codex-fast-label.ts, import order
   in node-card.ts and the test) so `npm run check` passes.

Verified: `npm run check` clean (Biome + tsc + shrinkwrap); the six focused
suites pass under `npx vitest --run --project unit` (68 tests).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@sina85

sina85 commented Aug 10, 2026

Copy link
Copy Markdown
Author

@flora131 thank you — all three were spot on, and the bun:test one in particular was a real gap. Fixed in 15ac7c14.

1. Replay test now loads under Vitest

test/unit/executor-replay-model-identity.test.ts:14 imported describe from bun:test; switched it to vitest. It runs and passes under the repo runner now.

2. Long model name truncates first, fast marker is preserved

modelText now drops the thinking level first, then truncates the model name, reserving the whole fast marker. Actual render of openai-codex/gpt-5.3-codex-spark in fast mode:

before:  │gpt-5.3-codex-spark f…│
after:   │gpt-5.3-codex-sp… fast│

Short names are unchanged (│ gpt-5.1-codex fast │). Added a regression test: "keeps the full fast marker and truncates a long model name instead of the marker."

3. Biome gate is clean

Ran biome check --write (tabs in codex-fast-label.ts, import order in node-card.ts and the test). npm run check now passes.

Verification (the exact commands you gave)

$ npm run check
Checked 2340 files … No fixes applied.     # biome
tsc --noEmit                                # clean
npm-shrinkwrap.json is up to date.          # shrinkwrap
→ exit 0

$ npx vitest --run --project unit \
    test/unit/node-card.test.ts \
    test/unit/executor-replay-model-identity.test.ts \
    test/unit/durable-dbos-topology.test.ts \
    test/unit/durable-stage-frontier-fixes.test.ts \
    test/unit/stage-runner-reasoning-suffix.test.ts \
    test/unit/overlay-graph-perf.test.ts
 Test Files  6 passed (6)
      Tests  68 passed (68)

Also appreciate the tip on driving Atomic to verify a PR in an isolated worktree/tmux — I'll use that flow next time so the runner/gate mismatch doesn't slip through again. Ready for another look when you have a chance.

@flora131

Copy link
Copy Markdown
Collaborator

Recorded a hands-on run of this PR on a local build of the head commit (15ac7c1), driving the Atomic TUI in a tmux session and inspecting the /workflow connect graph node cards. Attaching the screen recording of that session for reference.

pr1859-review.mp4

@flora131

Copy link
Copy Markdown
Collaborator

Thanks for the fix here. While testing this PR's exact head (15ac7c14c3441ad399b9d08f17ba961f2f531edd) in the real Atomic TUI, I found one issue with the new model/thinking-level row:

Thinking levels can be truncated or omitted for normal model IDs.

Repro:

  1. Run workflow stages with models such as anthropic/claude-haiku-4-5:high and anthropic/claude-sonnet-4-5-20250929:medium.
  2. Open the workflow graph with F2.
  3. Inspect the model row on each stage card.

Expected: the effective model and full thinking level remain identifiable.

Actual:

  • claude-haiku-4-5 · high renders as claude-haiku-4-5 · hi….
  • The longer Sonnet model renders as claude-sonnet-4-5-202…, with medium omitted entirely.

It looks like the 22-cell card interior applies the model-row width budget only in fast mode; otherwise the generic card truncation can consume the thinking level. The attached test video shows this around 1:24–1:40.

Are you able to reproduce this as well? If so, could the row reserve space for the thinking level before truncating the model name?

Follow-up to @flora131's review: the model-row width budget (reserve the
suffix, truncate the model name first) was applied only in fast mode, so for
ordinary models the generic card truncation consumed the thinking level:

  claude-haiku-4-5 · high              → claude-haiku-4-5 · hi…
  claude-sonnet-4-5-20250929 · medium  → claude-sonnet-4-5-202…  (medium gone)

modelText now treats the thinking level and the ` fast` marker as one
load-bearing suffix and always truncates the model name first, in every mode:

  claude-haiku-4-5 · high              → claude-haiku-4… · high
  claude-sonnet-4-5-20250929 · medium  → claude-sonne… · medium
  gpt-5.1-codex · high (fast)          → gpt-5.1-c… · high fast

Short names are unchanged. Added regression tests for the non-fast long-name
case and the combined level+fast overflow.

Verified: npm run check clean; the six focused suites pass under
`npx vitest --run --project unit` (70 tests).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@sina85

sina85 commented Aug 13, 2026

Copy link
Copy Markdown
Author

@flora131 reproduced it exactly — thanks, and good catch. My earlier fix only reserved space in fast mode, so for ordinary models the generic 22-cell truncation ate the thinking level. Fixed in 6cb25927.

modelText now treats the thinking level and the fast marker as one load-bearing suffix and always truncates the model name first, in every mode (not just fast). Actual renders on the exact head:

before                          after
claude-haiku-4-5 · hi…          claude-haiku-4… · high
claude-sonnet-4-5-202…          claude-sonne… · medium

And the combined + short cases stay correct:

gpt-5.1-c… · high fast     (fast + level overflow: both kept)
gpt-5.3-codex-sp… fast     (fast, long name: marker kept)
claude-opus-4.8 · high     (fits: unchanged)
gpt-5.1-codex fast         (fits: unchanged)

Added two regression tests: the non-fast long-name case (· high / · medium survive) and the combined level+fast overflow.

Verified with the real gates:

$ npm run check      → exit 0  (biome clean · tsc clean · shrinkwrap up to date)
$ npx vitest --run --project unit  <the six focused files>
 Test Files  6 passed (6)
      Tests  70 passed (70)

Ready for another look. (Also — appreciate you recording the TUI run; that's a much better signal than my earlier headless checks, and it caught exactly what I missed.)

@greptile-apps

greptile-apps Bot commented Aug 13, 2026

Copy link
Copy Markdown

Want your agent to iterate on Greptile's feedback? Try greploops.

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.

3 participants