Skip to content

fix(runtime): treat Pi/OMP state-marker idle title as idle for terminal wait - #24111

Closed
drakeo338 wants to merge 2 commits into
stablyai:mainfrom
drakeo338:claude/24068-fix
Closed

drakeo338 wants to merge 2 commits into
stablyai:mainfrom
drakeo338:claude/24068-fix

Conversation

@drakeo338

Copy link
Copy Markdown
Contributor

ELI5

OMP 18.4's idle title π > dir was not seen as idle, so worker-start --agent omp timed out.

What Changed

computeExplicitIdleStatusFromTitle now accepts the state-marker idle title via a new isPiIdleTitle in pi-state-title-marker.ts (legacy prefix, or getPiStateTitleStatus(title) === 'idle'). π : and π ! stay not idle.

Why

Reuses the marker table; terminal-wait-detection.ts is at its max-lines limit.

Linked Issue

Fixes #24068

Visual Proof

N/A, no UI change.

Testing

  • I manually tested these changes locally
  • Automated tests added/updated, or explained why not below

terminal-wait-pi-idle-title.test.ts, via pnpm exec vitest run --config config/vitest.config.ts <file>: main 1 failed / 3 passed, fix 4 passed; related suites 330 passed. tsc (node, web), oxlint, anti-slop, oxfmt --check, max-lines ratchet: clean. Linux only.

AI Disclosure

Written with Claude Code; reviewed and tested by me.

Review

Agent skill upstream boundary

  • Not applicable, or this change follows docs/reference/agent-skill-sharing-upstream-boundary.md and copies or mechanically translates no upstream skill-installer source, tests, fixtures, registry entries, path tables, comments, or documentation.

Notes

Title check only; no platform impact.

Checklist

  • This PR is small and focused
  • I explained what changed and why (ELI5, the user-facing before/after, the mechanism, and why over the alternatives)
  • Before/after screenshots or videos attached for UI changes, or N/A with reason
  • Self-reviewed for correctness, security, and performance
  • Cross-platform, SSH/remote, and path/shortcut impact considered (or N/A)
  • pnpm lint, pnpm typecheck, pnpm test, and pnpm build pass (or CI will cover; local preferred)

🤖 Generated with Claude Code

@greptile-apps

greptile-apps Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 5/5

[Medium risk] Adjusts terminal idle detection for Pi/OMP state markers.

The PR appears safe to merge; no distinct new actionable issue was established.

Summary

The PR recognizes Pi/OMP’s π > state-marker title as explicit idle evidence for terminal waits. It also records when main’s stale-title timer synthesized that title and excludes those synthesized titles from strong idle evidence.

Reviews (3) · Last reviewed commit: "fix(runtime): ignore stale-cleared Pi id..."

Comment thread src/main/runtime/terminal-wait-detection.ts Outdated

@pullfrog pullfrog Bot 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.

ℹ️ No critical issues — one consistency gap worth a look.

Reviewed changes

  • Shared idle helper — adds isPiIdleTitle to pi-state-title-marker.ts, true for the legacy π - prefix or a state-marker title whose status is idle.
  • Terminal-wait gate — computeExplicitIdleStatusFromTitle now calls isPiIdleTitle(title) in place of the inline legacy-prefix check, so π > dir reads idle. The detectAgentStatusFromTitle(title) === 'idle' gate still rejects π !/π : first, so this only widens explicit-idle evidence.
  • Test — new terminal-wait-pi-idle-title.test.ts pins legacy idle, state-marker idle, and the two not-idle markers; discriminating because it fails on main for π > dir.

ℹ️ Renderer send path still uses the legacy-only prefix

src/renderer/src/lib/agent-send-title-status.ts is a second consumer of the same idle-evidence rule and still checks only title.startsWith('\u03c0 - '), so an OMP pane sitting at π > dir is classified idle by classifyTitleActivity but then rejected by isExplicitIdleSendTitle — the exact drift this shared helper prevents. It does not affect the wait fix in this PR, but the renderer file can import isPiIdleTitle the same way terminal-wait-detection.ts now does.

Technical details
# Renderer send-target gate left on the legacy prefix

## Affected sites
- `src/renderer/src/lib/agent-send-title-status.ts:8` — `PI_IDLE_PREFIX = '\u03c0 - '`
- `src/renderer/src/lib/agent-send-title-status.ts:34` — `title.startsWith(PI_IDLE_PREFIX)`
- consumed by `src/renderer/src/lib/running-agent-targets.ts:120` and `src/renderer/src/lib/notes-send-agent-targets.ts:39,47`

## Required outcome
- OMP state-marker idle titles (`\u03c0 > dir`, `OMP > dir`, wrapper-prefixed variants) should
  read as send-ready idle the same way they now read as wait-ready idle.

## Suggested approach (optional)
- Replace the local constant + `startsWith` with the shared `isPiIdleTitle` from
  `../../../shared/pi-state-title-marker`, mirroring `terminal-wait-detection.ts`.

## Open questions for the human
- Is the send path intentionally kept on the legacy rule, or is this just out of scope for the
  #24068 wait fix? If intentional, a comment stating why would stop the next reader "fixing" it.

Pullfrog  | Fix it ➔ | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

@coderabbitai

coderabbitai Bot commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

🧰 Additional context used
📚 Code guidelines (1)
AGENTS.md — auto-discovered
📝 Walkthrough

Walkthrough

Terminal wait detection now recognizes Pi/OMP idle state-marker titles through isPiIdleTitle. The shared predicate also recognizes legacy π - titles. Runtime records track whether a title was cleared by the stale-working timer. Explicit idle checks skip stale-cleared Pi idle titles. Tests cover idle, permission, and working markers, along with stale-cleared and agent-emitted titles.

Priority: ➖ Normal

Severity of issue fixed: Medium

Merge Risk: 🔵 Low · up to b2846

In a narrow case, a valid idle Pi/OMP title shown by the renderer may not be recognized as ready while the underlying OSC title was stale-cleared. The effect is a missed readiness signal, not data loss. Scope the guard to the OSC title before or soon after merge.

Security Architecture Review

Security architecture risk: 🔵 Low · up to b2846

The change distinguishes genuine idle titles from timer-generated ones. That distinction is preserved during live operation, but its behavior after restoration remains unresolved. The identified uncertainty is limited to the affected terminal.

Retained concerns

  • Low · security · inferred: The new stale-clear distinction is not represented in the recovery title contract. Restoration seeds lastTitle without assigning stale-clear provenance, and explicit-title evaluation can accept a seeded idle marker without a live-observation check. If recovery supplies a timer-generated Pi idle title, it may become authoritative after reset. That producer-to-recovery path remains unproven, so this is an inferred readiness-authority gap rather than a confirmed premature-readiness defect.
Security review details

Security Blast Radius

  • inferred — The traced title-to-readiness effects are scoped to the matching PTY, leaf and terminal handle. A process controlling its terminal output can supply OSC titles, but the inspected paths do not establish new authority over unrelated terminals or services.

Trust Boundaries and Controls

  • observed — Wait evaluation checks blocked-tail evidence before explicit idle titles. Explicit titles can produce strong readiness before the later working-status veto, making correct title provenance important. Delivery deliberately uses a blocked-blind evaluation and therefore should not be described as protected by that same blocked-tail check.

Hardening Proposals

  • proposed — Define recovery title authority explicitly: either preserve synthetic-title provenance across restoration or require fresh corroboration before a restored Pi marker becomes strong readiness evidence.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 4 functions across 8 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely identifies the primary change: recognizing Pi/OMP state-marker idle titles during terminal wait.
Description check ✅ Passed The description is complete and matches the repository template. It explains the user impact, implementation, rationale, linked issue, visual proof, testing, AI disclosure, scope, and checklist status…
Linked Issues check ✅ Passed Issue [#24068] requires a fresh OMP pane with title π > <label> to be recognized as ready. computeExplicitIdleStatusFromTitle now accepts Pi idle titles through isPiIdleTitle. isPiIdleTitle ac…
Out of Scope Changes check ✅ Passed The changed files support issue [#24068]. The shared title helper enables OMP idle detection. The stale-cleared state prevents a timer-generated idle-looking title from becoming false readiness eviden…
  • Fix all pre-merge checks with AI

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@drakeo338

Copy link
Copy Markdown
Contributor Author

Good catch, a π > dir title rewritten by the 3s stale timer no longer counts as idle for terminal wait (only one OMP emitted does), with a test in 2feeb29

@pullfrog pullfrog Bot 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.

ℹ️ No blocking issues — the stale-cleared guard is sound. A few consistency notes below.

Reviewed changes

  • Added a lastOscTitleStaleCleared provenance flag so a π > dir synthesized by main's 3s stale timer is no longer accepted as explicit idle evidence.
  • Wired the flag through the pty/leaf records, the renderer-publish rebuild, and the provider-generation reset.
  • Guarded hasExplicitIdleTitle and getAdoptedPtyExplicitIdleStatus against stale-cleared idle titles, with tests for both an agent-emitted and a synthesized π > dir.

ℹ️ Nitpicks

  • getAdoptedPtyExplicitIdleStatus (orca-runtime-resolve-exit-waiters.ts:223) gates on pty.lastOscTitleStaleCleared but tests a title returned by getAdoptedPtyTitle(pty) — the leaf's paneTitle or the tab title. The flag describes pty.lastOscTitle, so if those sources diverge a genuine idle could be suppressed; the pty branch of hasExplicitIdleTitle (same flag against pty.lastOscTitle) is the consistent one.
  • The rationale at tui-idle-evidence.ts:45-48 still warns that a bespoke provenance field "is silently dropped on any renderer publish and the verdict silently flips". This commit now stamps exactly such a field and depends on the explicit copy at orca-runtime-sync-window-graph.ts:147; worth rewording so the premise reads true.
  • applySeededAgentStatus (orca-runtime-maybe-hydrate-headless-from-renderer.ts:137,145) rewrites lastOscTitle without resetting lastOscTitleStaleCleared. I could not construct a reachable sequence that flips a genuine title to suppressed, but a one-line reset there preserves the invariant for future edits.

Pullfrog  | Fix all ➔ | Fix 👍s ➔ | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

@@ -69,6 +71,11 @@ export function hasExplicitIdleTitle(
// one dropped an explicit `Codex ready` to the tier-3 lane and delayed it by the
// whole quiescence window.
for (const title of [rendererTitle, record.lastOscTitle]) {
// Why: main's 3s stale timer rewrites OMP's static `π : dir` to `π > dir` mid-turn; only a
// `π > dir` the agent emitted itself is idle evidence.
if (record.lastOscTitleStaleCleared && title && getPiStateTitleStatus(title) === 'idle') {

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.

Please confirm the legacy exemption is intentional. The stale timer also synthesizes the legacy idle form — clearWorkingIndicators('⠋ π - cwd') returns π - cwd — but this guard only matches the state-marker form via getPiStateTitleStatus(title) === 'idle'. The identical predicate sits at orca-runtime-resolve-exit-waiters.ts:223.

Technical details
# Legacy `π - ` idle still counts as explicit idle when stale-cleared

## Affected sites
- `src/main/runtime/tui-idle-evidence.ts:76` — guard matches only `getPiStateTitleStatus(title) === 'idle'`
- `src/main/runtime/orca-runtime-resolve-exit-waiters.ts:223` — same predicate

## Required outcome
- Decide whether a stale-timer-synthesized legacy idle title (`π - cwd`, produced when `clearWorkingIndicators` strips the braille off `⠋ π - cwd`) should be excluded the same way `π > cwd` now is.

## Suggested approach (optional)
- If it should: gate on `isPiIdleTitle(title)` in both guards, and flip the `terminal-wait-pi-idle-title.test.ts` case that currently asserts legacy stays idle when stale-cleared.
- If legacy is intentionally exempt: a one-line comment stating why would stop the next reader "fixing" it.

## Open questions for the human
- Is legacy Pi's stale-clear the intended fallback idle signal while the state-marker stale-clear is not? `pi-state-title-marker.test.ts:42` shows `⠋ π - my-project` classifies as working and is cleared to the `π - ` idle form.

drakeo338 and others added 2 commits October 2, 2026 05:03
…al wait

terminal.wait --for tui-idle only accepted the legacy 'π - ' idle prefix, so
a Pi/OMP pane titled 'π > dir' (state-marker idle) was never seen as ready.
Add isPiIdleTitle next to the marker table so both Pi title protocols are
read from one place.

Fixes stablyai#24068.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Advanced

Run ID: 973ebc9e-eee4-44fa-ab38-0eb0701d3451

📥 Commits

Reviewing files that changed from the base of the PR and between 2feeb292c6b9dd70d79af3935d6ac34a7b1e5de0 and b28465c.

📒 Files selected for processing (3)
  • src/main/runtime/orca-runtime-apply-tracked-pty-title.ts
  • src/main/runtime/terminal-wait-detection.ts
  • src/main/runtime/tui-idle-evidence.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.

Comment thread src/main/runtime/tui-idle-evidence.ts

@pullfrog pullfrog Bot 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.

ℹ️ No new issues — the two commits were force-pushed onto main's rule-file readiness refactor and re-applied cleanly.

Reviewed changes

  • Rebased isPiIdleTitle (π > state-marker idle) onto terminal-wait-detection.ts's new rule-file engine. The explicit-idle gate still evaluates before the rule lane, and no rule-file title anchor matches π > (only pi.json's ^π - ), so the helper is still required and not redundant.
  • Re-applied the lastOscTitleStaleCleared guard through hasExplicitIdleTitle, getAdoptedPtyExplicitIdleStatus, and the leaf rebuild. Verified the refactor's new readAgentRuleVerdict weak lane cannot promote a stale-cleared π > to strong idle (the Pi/OMP title rule is weak + requiresQuiet), and getAdoptedPtyIdleStatus maps to the guarded getAdoptedPtyExplicitIdleStatus.
  • Confirmed the added test remains discriminating and the related suites pass: terminal-wait-pi-idle-title.test.ts, tui-idle-evidence.test.ts, agent-state-rules-engine.test.ts — 113 passed.

Pullfrog  | Fix it ➔ | View workflow run | Using deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏

@drakeo338

Copy link
Copy Markdown
Contributor Author

Closing this: #24295 gave OMP its own idle lane, which accepts π > dir once it has settled and the screen is clear of the setup wizard, so issue #24068 is covered on main and this change would now bypass that check.

@drakeo338 drakeo338 closed this Oct 2, 2026
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.

[Bug]: worker-start --agent omp fails at agent_readiness: OMP 18.4 idle title "π > dir" is not recognised as idle

1 participant