Skip to content

Resolve the real site running state when resuming code sessions headlessly - #4096

Merged
bcotrim merged 4 commits into
trunkfrom
stu-2001-fix-agent-stopped-site-status
Jul 7, 2026
Merged

Resolve the real site running state when resuming code sessions headlessly#4096
bcotrim merged 4 commits into
trunkfrom
stu-2001-fix-agent-stopped-site-status

Conversation

@shaunandrews

Copy link
Copy Markdown
Contributor

Related issues

How AI was used in this PR

Claude Code investigated the root cause, wrote the fix and tests, and drafted this PR. I reviewed and directed the work.

Proposed Changes

In desktop Studio Code sessions, the agent's per-turn context banner always described the active local site as (stopped), no matter its actual state. The agent would then defensively call site_start before WP-CLI or other site operations — wasting a tool call every turn and confusing users whose site was clearly already running.

The cause: every desktop turn runs studio code sessions resume --json, which hydrates the active site from the session's event log. That log carries no running state, and the missing flag defaulted to "stopped". Now the headless resume path asks the daemon whether the site is actually up before dispatching the turn, so the agent sees the truth: no more redundant site_start calls, and the agent can correctly warn when the site really is stopped.

Sites missing from the CLI config are still treated as stopped, and remote (WordPress.com) sites skip the check since running state doesn't apply to them.

Testing Instructions

  1. Start a local site in Studio and open a Studio Code session on it.
  2. Ask the agent something that makes it run WP-CLI (e.g. "list my plugins with wp-cli").
  3. Before this fix, the agent's context showed (stopped) and it would often call site_start first; now the context shows (running) and it goes straight to the WP-CLI call.
  4. Stop the site and send another message — the context should now report (stopped).
  5. Unit tests: npm test -- apps/cli/commands/ai/sessions/tests/resume.test.ts

Pre-merge Checklist

  • Have you checked for TypeScript, React or other console errors?

🤖 Generated with Claude Code

…essly

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@wpmobilebot

wpmobilebot commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator

📊 Performance Test Results

Comparing 2da0d55 vs trunk

app-size

Metric trunk 2da0d55 Diff Change
App Size (Mac) 1412.01 MB 1412.01 MB +0.00 MB ⚪ 0.0%

site-editor

Metric trunk 2da0d55 Diff Change
load 747 ms 1122 ms +375 ms 🔴 50.2%

site-startup

Metric trunk 2da0d55 Diff Change
siteCreation 6528 ms 6518 ms 10 ms ⚪ 0.0%
siteStartup 2384 ms 2383 ms 1 ms ⚪ 0.0%

Results are median values from multiple test runs.

Legend: 🟢 Improvement (faster) | 🔴 Regression (slower) | ⚪ No change (<50ms diff)

@shaunandrews
shaunandrews requested a review from bcotrim July 6, 2026 23:18

@bcotrim bcotrim left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@shaunandrews — while reviewing this we found the same bug hiding in two more entry points, so the fix moved one level down and got broader:

  • Before: the resume command resolved the running state itself — fixing only the desktop/headless path.
  • Now: runAgentTurn asks the daemon right before building the context banner, every turn. One guard covers all entry points — desktop headless resume (the original STU-2001), interactive studio code sessions resume (session replay hardcoded running: false), and studio code --path (flag never set) — plus mid-session changes (stop/start a site from another terminal and the next turn reflects it).

Simple test plan (needs a built CLI: npm run cli:build):

  1. Start a local site in Studio.
  2. studio code → pick the running site → send "just reply ok, don't use tools" → exit.
  3. studio code sessions resume latest → first message: "Without using any tools, is my active site running?" → should say running (on trunk it says stopped).
  4. Stop the site, send the same question again → should say stopped.
  5. Desktop is still covered by the original testing instructions in the PR description.
  6. Unit tests: npm test -- apps/cli/commands/ai

Pushed the fix and approved so we can merge this as CI goes green

@bcotrim
bcotrim merged commit 41dfe11 into trunk Jul 7, 2026
11 checks passed
@bcotrim
bcotrim deleted the stu-2001-fix-agent-stopped-site-status branch July 7, 2026 17:00
bcotrim pushed a commit that referenced this pull request Jul 11, 2026
…headless runs can exit (#4175)

## Related issues

- Fixes
[STU-2040](https://linear.app/a8c/issue/STU-2040/headless-code-sessions-never-exit-after-turncompleted-leaving-desktop)
- Related to
[STU-2001](https://linear.app/a8c/issue/STU-2001/agent-always-sees-local-sites-as-stopped-in-desktop-studio-code)
/ #4096

## How AI was used in this PR

Claude Code applied the fix, verified it end-to-end in both directions
(fixed build exits, unfixed build hangs), and drafted this PR. I
reviewed and directed the work.

## Proposed Changes

Since #4096, every headless `studio code … --json` turn on a local site
leaves the CLI process alive after it reports `turn.completed`. The
per-turn site running-state check opens a connection to the
process-manager daemon and never closes it, and that open socket keeps
the process from exiting.

The desktop app feels this the most: each turn forks a headless `code
sessions resume` child and treats the child's exit as the end of the
turn. Because the child never exits, the session appears stuck in the
working state forever — the stop button and the sidebar agent-activity
indicator never clear — and an orphaned node process piles up for every
turn taken on a running-or-stopped local site.

The fix closes the daemon connection as soon as the running-state check
completes, the same way every other daemon consumer in the CLI already
does. The connection is a singleton, so anything later in the turn that
needs the daemon (like the WP-CLI tool) reconnects transparently.

## Testing Instructions

1. `npm run cli:build`
2. Run a headless turn against a local site: `node
apps/cli/dist/cli/main.mjs code --json --path ~/Studio/<site> "Reply
with only the word OK."`
3. The process should exit on its own a moment after the
`turn.completed` event (on trunk it hangs indefinitely and must be
killed).
4. In the desktop app, take a turn in a Studio Code session on a local
site and confirm the working indicator clears when the turn finishes.
5. Tests: `npm test --
apps/cli/commands/ai/sessions/tests/resume.test.ts
apps/cli/commands/ai/tests/index.test.ts`

## Pre-merge Checklist

- [x] Have you checked for TypeScript, React or other console errors?

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
shaunandrews added a commit that referenced this pull request Jul 17, 2026
The STU-2001 fix (#4096) asks the daemon whether the active site is
running before every turn, but never disconnected. The open socket kept
the headless --json child alive after turn.completed, so the desktop
never saw run.exited and sessions stayed stuck in the working state
(stop button + sidebar activity indicator).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

3 participants