Skip to content

fix(workflows): mark runs awaiting human input with the awaiting-input indicator - #2192

Open
flora131 wants to merge 5 commits into
mainfrom
fix/awaiting-input-run-indicator
Open

fix(workflows): mark runs awaiting human input with the awaiting-input indicator#2192
flora131 wants to merge 5 commits into
mainfrom
fix/awaiting-input-run-indicator

Conversation

@flora131

@flora131 flora131 commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator

Closes #2185

Summary

Runs paused on a human-input prompt now show a distinct awaiting-input indicator instead of the generic running spinner.

  • Shared predicate: new packages/workflows/src/shared/run-indicator-status.ts exports runIndicatorStatus(run, allRuns), the single source of truth for a run's primary indicator status.
  • Three surfaces: the BACKGROUND widget, the /workflow connect picker, and the /workflow status listing all resolve their indicator through the shared predicate.
  • Nested-ancestor marking: a pending prompt in a hidden nested descendant is attributed to the visible top-level ancestor by following rootRunId/parentRunId (with cycle protection), so the surface the user can see is the one that lights up.
  • Revert: once the prompt is answered the indicator returns to the plain running status; quit runs stay resumable.
  • Precedence: effective terminal and blocked statuses (completed, failed, killed, cancelled, skipped, blocked) win over a stale pending-prompt marker left in a snapshot.
  • No copy changes: the BACKGROUND widget header badge, meta lines, and progress text stay byte-identical. PR fix(workflows): show which run is awaiting human input #2135's prompt-attribution header (AWAITING INPUT · <run id> <name>) is deliberately not relanded — it is out of scope.

Relationship to closed PR #2135

This is a fresh implementation from clean main. Nothing was checked out, cherry-picked, merged, or copied from fix/hil-run-attribution-indicator; PR #2135's description was consulted only as a spec reference.

Verification (local)

  • npm run check — biome, tsc --noEmit, and shrinkwrap check all pass.
  • Targeted vitest run of the touched suites (run-indicator-status, session-picker, status-list-render, widget-rendering, workflow-status-listing): 5 files, 86 tests, all pass.
  • npm run test:unit — 630 files, 5890 passed, 1 skipped.
  • Pre-push hooks (biome, npm run check, test:unit, test:integration, test:ci-contracts) all passed on the pushed commit. One earlier hook run saw two unrelated interactive-engine tests fail under parallel-suite load; both pass standalone and on the accepted run.

View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

Greptile Summary

This change adds a shared workflow indicator for runs awaiting human input, including attribution from hidden nested runs, and carries that indicator into status cards, widgets, pickers, and restored chat entries.

A reproduced behavior gap remains: an unfiltered status listing correctly marks a visible parent workflow as awaiting input when its hidden nested child has a prompt, but /workflow status filtered to awaiting-input returns no matching workflow. Users and agents can therefore miss an actionable workflow when relying on that filter.

Confidence Score: 4/5

Not safe to merge until the awaiting-input filter includes visible workflows whose nested descendants require input.

The status display and filtered status results disagree for the same active workflow. This makes an actionable human-input request undiscoverable through the filter intended to surface it.

Files Needing Attention: packages/workflows/src/extension/workflow-status-summary.ts, packages/workflows/src/extension/workflow-tool.ts

T-Rex T-Rex Logs

What T-Rex did

  • T-Rex produced a finding-comment-proof for a posted P1 finding and attached four artifacts showing the workflow status with and without a hidden child prompt, plus the nested-prompt reproduction harness and a focused test run.
  • T-Rex issued a second finding-comment-proof for another P1 finding.
  • T-Rex validated the contract behavior by inspecting the unfiltered and statusFilter results, confirming the nested prompt status behavior using the accompanying logs.
  • T-Rex attached the harness source for the nested prompt status and ran a focused regression, with the focused run log captured for review.

View all artifacts

T-Rex Ran code and verified through T-Rex

Comments Outside Diff (2)

  1. packages/workflows/src/extension/workflow-status-summary.ts, line 206 (link)

    P1 Awaiting-input filter ignores nested workflow prompts

    statusFilter: "awaiting_input" only checks summary.awaitingInputCount, which is derived from the visible run's own snapshot. A top-level run with a hidden nested descendant awaiting a prompt is therefore omitted from the filtered /workflow status result, even though the unfiltered status renderer correctly marks that same top-level run with the awaiting-input indicator. This prevents users and agents from discovering the actionable visible workflow through the awaiting-input filter. Resolve descendant-aware indicator status against the complete run collection before filtering, and treat a resolved awaiting_input status as a match.

    Artifacts

    Unfiltered workflow status with a hidden child prompt

    • Executed the narrow harness without a filter; the visible root is listed and rendered with the awaiting-input glyph even though its own summary reports zero prompts, demonstrating rendering-side descendant attribution. Takeaway: unfiltered text recognizes the hidden child prompt.

    Filtered workflow status with a hidden child prompt

    • Executed the same seeded workflow through `statusFilter: awaiting_input`; the exact status path returns an empty listing. Takeaway: the filter drops the visible root that needs attention.

    Nested prompt status reproduction harness source

    • Authored narrow Vitest harness that seeds the top-level and hidden child runs, invokes `makeExecuteWorkflowTool`, and records both comparison modes. Takeaway: the reproduction is executable and directly exercises the reported path.

    Focused workflow status and indicator test run

    • Ran the reproduction alongside existing workflow status-listing and indicator tests; all 14 focused tests passed while the harness recorded the unfiltered indicator behavior. Takeaway: the defect is isolated to filtered listing semantics rather than a failed runtime setup.

    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/extension/workflow-status-summary.ts
    Line: 206
    
    Comment:
    **Awaiting-input filter ignores nested workflow prompts**
    
    `statusFilter: "awaiting_input"` only checks `summary.awaitingInputCount`, which is derived from the visible run's own snapshot. A top-level run with a hidden nested descendant awaiting a prompt is therefore omitted from the filtered `/workflow status` result, even though the unfiltered status renderer correctly marks that same top-level run with the awaiting-input indicator. This prevents users and agents from discovering the actionable visible workflow through the awaiting-input filter. Resolve descendant-aware indicator status against the complete run collection before filtering, and treat a resolved `awaiting_input` status as a match.
    
    ---
    
    For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.
  2. General comment

    P1 awaiting_input status filter omits visible roots whose hidden descendants need input

    • Bug
      • The user-facing root is shown as needing attention by unfiltered status text, but is absent from the filtered status result. This prevents an agent/user using /workflow status with statusFilter: "awaiting_input" from discovering the actionable visible workflow whenever the pending prompt belongs to a nested hidden run.
    • Cause
      • makeExecuteWorkflowTool invokes buildWorkflowStatusListing(topLevelExpandedSnapshots(), args.statusFilter ?? "all") at packages/workflows/src/extension/workflow-tool.ts:97. buildWorkflowStatusListing summarizes only each visible snapshot and filters it at packages/workflows/src/extension/workflow-status-summary.ts:219-221; the awaiting_input predicate at :204-207 only checks that summary's own awaitingInputCount. By contrast, unfiltered rendering calls runIndicatorStatus(snapshot, allRuns) at packages/workflows/src/extension/workflow-tool-content.ts:75-85, and the resolver attributes descendant prompts through rootRunId/parentRunId at packages/workflows/src/shared/run-indicator-status.ts:18-28,64-74.
    • Fix
      • Resolve each visible run's descendant-aware indicator status against the complete store snapshot before filtering, and treat resolved awaiting_input as matching the filter. Ensure the summary/detail representation also exposes enough descendant prompt attribution to make the returned root actionable.

    T-Rex Ran code and verified through T-Rex

Prompt To Fix All With AI
### Issue 1
packages/workflows/src/extension/workflow-status-summary.ts:206
**Awaiting-input filter ignores nested workflow prompts**

`statusFilter: "awaiting_input"` only checks `summary.awaitingInputCount`, which is derived from the visible run's own snapshot. A top-level run with a hidden nested descendant awaiting a prompt is therefore omitted from the filtered `/workflow status` result, even though the unfiltered status renderer correctly marks that same top-level run with the awaiting-input indicator. This prevents users and agents from discovering the actionable visible workflow through the awaiting-input filter. Resolve descendant-aware indicator status against the complete run collection before filtering, and treat a resolved `awaiting_input` status as a match.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Reviews (4): Last reviewed commit: "fix(test): harden gated bash synchroniza..." | Re-trigger Greptile

…t indicator

Apply the shared runIndicatorStatus predicate to the BACKGROUND widget, /workflow connect picker, and /workflow status listing. Attribute hidden nested child prompts to the visible top-level ancestor, preserve terminal and blocked precedence, and keep quit runs resumable. Add direct regression coverage for quit runs carrying pending prompts.

Refs #2185
@mintlify

mintlify Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
bastani 🟢 Ready View Preview Aug 4, 2026, 5:41 PM

💡 Tip: Enable Workflows to automatically generate PRs for you.

@flora131

flora131 commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator Author

E2E evidence: awaiting-input run indicator (#2185)

Verified end-to-end with the real Atomic CLI built from this branch (worktree commit 8e9c4a0c8), run under tmux (120x40) in a scratch project (/tmp/hil-e2e-2185). Two fixture workflows ran as top-level background runs: hil-demo (raises a run-level ctx.ui.confirm after 8s) and sleeper (long sleep). Captures below are trimmed to the relevant region; content is unaltered.

1. BACKGROUND widget — on the asking run, on the sibling, needs-attention badge

╭ BACKGROUND  2 runs  ● 2 running  ? ↵ 1 needs attention (attach to workflow with `/workflow connect`) ───────────────╮
│   ●  d57d2cbf-aebd-47bb-be00-1c10d163e091                                                                            │
│     sleeper · single · 9s                                                                                            │
│                                                                                                                      │
│   ?  8724a716-540e-4526-842c-77fe2e10139e                                                                           │
│     hil-demo · single · 0/1 · 15s                                                                                    │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

2. /workflow connect picker — on hil-demo, on sleeper

╭── Connect to workflow run ───────────────────────────────────────────────────────────────────────────────────────────╮
│                                                                                                                      │
│   filter  (type to filter by name or id)                                                                             │
│                                                                                                                      │
│   ACTIVE                                                                                                             │
│ ? 8724a716-540e-4526-842c-77fe2e10139e                                                                              │
│   hil-demo                                                                                          21s   0/1 stages │
│ ● d57d2cbf-aebd-47bb-be00-1c10d163e091                                                                               │
│   sleeper                                                                                           15s   0/0 stages │
│                                                                                                                      │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

3. /workflow status row glyph and [?] stage marker on hil-demo

╭ BACKGROUND  2 runs  ● 2 ─────────────────────────────────────────────────────────────────────────────────────────────╮
│ ●  d57d2cbf-aebd-47bb-be00-1c10d163e091                                                                              │
│   sleeper  ● running                                                                                                 │
│   single    [●]                                                                                                21s   │
│                                                                                                                      │
│ ?  8724a716-540e-4526-842c-77fe2e10139e                                                                             │
│   hil-demo  ● running                                                                                                │
│   single    [?]                                                                                               26s   │
│                                                                                                                      │
│ ▸ /workflow status d57d2cbf-aebd-47bb-be00-1c10d163e091  drill into a run                                            │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

4. After answering the confirm prompt — both runs revert to , badge cleared

╭ HIL ANSWERED ────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ✓ Workflow "hil-demo" received the user's response                                                                   │
│ workflow  hil-demo                                                                                                   │
│ run       8724a716-540e-4526-842c-77fe2e10139e                                                                       │
│ stage     confirm                                                                                                    │
│ prompt    E2E 2185: proceed with the demo?                                                                           │
│ answer    true                                                                                                       │
│ No main-chat action is needed; do not answer other workflow prompts unless the user explicitly provides that answer. │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

╭ BACKGROUND  2 runs  ● 2 ─────────────────────────────────────────────────────────────────────────────────────────────╮
│ ●  d57d2cbf-aebd-47bb-be00-1c10d163e091                                                                              │
│   sleeper  ● running                                                                                                 │
│   single    [●]                                                                                             1m 20s   │
│                                                                                                                      │
│ ●  8724a716-540e-4526-842c-77fe2e10139e                                                                              │
│   hil-demo  ● running                                                                                                │
│   single    [✓]                                                                                             1m 25s   │
│                                                                                                                      │
│ ▸ /workflow status d57d2cbf-aebd-47bb-be00-1c10d163e091  drill into a run                                            │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

╭ BACKGROUND  2 runs  ● 2 running ─────────────────────────────────────────────────────────────────────────────────────╮
│   ●  d57d2cbf-aebd-47bb-be00-1c10d163e091                                                                            │
│     sleeper · single · 1m 31s                                                                                        │
│                                                                                                                      │
│   ●  8724a716-540e-4526-842c-77fe2e10139e                                                                            │
│     hil-demo · single · 1/1 · 1m 36s                                                                                 │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

After the answer, zero glyphs remained anywhere in the pane and the needs-attention badge cleared. The tmux session and CLI processes were killed after capture.

Comment thread packages/workflows/src/tui/chat-surface-message.ts Outdated
The Windows release-archive timeout was based on warm measurements, but a healthy run's 4m04s p100 left no room for cold setup. Two 6m1x cancellations followed, including one on the unrelated feat/2159-curl-irm-installers branch. The rust-toolchain step measured 12s/36s on healthy runs versus 152s/140s on the cancelled runs; checkout also reached 71s/64s. Raise the Windows cap to 9 minutes for the observed cold tail and the native build and archive smoke steps.

This is a CI budget correction, not a product change.

Refs #2185
…sion restore

The /workflow status chat entry kept its point-in-time full run collection
in a WeakMap keyed by the in-memory StatusPayload. A payload rebuilt from
persisted message details after a session restore is a different object,
so a visible running ancestor lost its hidden nested descendant's
awaiting-input attribution and re-rendered with the running dot.

Resolve each visible run's indicator status against the complete
collection at emit time (resolveRunIndicatorStatuses) and persist that
small serializable record on the payload instead; hidden run snapshots
still never reach the serialized message. renderStatusList prefers the
precomputed record over deriving from allRuns.

Addresses the P1 review finding on #2192.
Two coding-agent suites failed only on Windows CI, both because they
synchronized on an event that is not the one they need.

bash-session-metadata "propagates the same snapshot into detached async
jobs" gated on existsSync(outputPath). The shell's `>` redirect creates
and truncates the file when the command starts, before printf runs and
before the job exits, so the predicate is satisfied by a zero-byte file
and a loaded runner reads ''. Verified directly: a gated writer under
`>` reports exists=yes size=0 while the process is still alive, and the
test reproduces `expected '' to be '<id>:<id>'` when it keeps polling
only for existence. It now waits for the managed job to report
"completed" via __atomic_bash_job, and additionally asserts the file is
empty at creation time so the defect itself stays pinned.

rpc-bash-session-replacement burned the whole 90s budget in an unbounded
waitFor() spinning on `updatesFor(...) === "before"`. Chunking is
opportunistic, not guaranteed: createLocalBashOperations forwards raw
'data' events, so `printf before; sleep 0.05; printf after` can arrive
as one buffer. Confirmed on macOS by driving exec() directly, which
delivered chunks ["beforeafter"] - the accumulated string never equals
"before", so the loop could not terminate.

waitFor is replaced by waitForOutput: bounded by a named constant,
matching a monotonically reachable prefix, and throwing an error naming
the id and the observed accumulated output on expiry. The two tests that
must issue a replacement mid-execution no longer rely on a 50ms sleep to
stay in flight; they block the shell on a marker file in a temp
directory that is also the session cwd, which widens the in-flight window
deterministically rather than removing it. A focused test feeds a single
coalesced "beforeafter" delta through the helper and fails under the old
exact-equality predicate.

Test synchronization only; no production behavior changed. Every
existing assertion is preserved verbatim.

Assistant-model: Claude Opus 5
Retry gated cwd cleanup on Windows and run it from finally blocks. Gate the shared-manager clone on an explicit in-flight marker so coalesced output cannot make the test pass vacuously. Widen diagnostic wait bounds to 10 seconds for cold Git Bash starts while preserving the suite timeout headroom.

Assistant-model: GPT-5.6 Sol
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.

Mark the run awaiting human input with the ? indicator (reland #2135)

1 participant