Skip to content

fix: resolve --spawned-by self for depth>0 workers (v0.0.8) - #17

Merged
araa47 merged 4 commits into
mainfrom
fix/ghost-l0-self-resolution
Mar 21, 2026
Merged

fix: resolve --spawned-by self for depth>0 workers (v0.0.8)#17
araa47 merged 4 commits into
mainfrom
fix/ghost-l0-self-resolution

Conversation

@araa47

@araa47 araa47 commented Mar 21, 2026

Copy link
Copy Markdown
Owner

Summary

  • Bug: Cursor L2+ workers using --spawned-by self (because ORCA_WORKER_NAME isn't set in Cursor's shell) would trigger ensure_l0_orchestrator, creating a ghost L0 entry. This caused the worker to appear as a separate root tree in orca list even though its state (depth, spawned_by) was correct.
  • Fix (layer 1): In cmd_spawn, before the L0 marker check, resolve self to the actual worker name when the calling pane matches a tracked worker with depth > 0. This prevents ensure_l0_orchestrator from being called at all.
  • Fix (layer 2): Defense-in-depth in ensure_l0_orchestrator itself — if the pane already belongs to a depth > 0 worker, return that worker's name instead of creating a new L0 entry.
  • Version bump: 0.0.7 → 0.0.8

Scenario reproduced

Expected:  openclaw (L0) → cog (L1) → fen (L2) → ash (L3)
Actual:    fen appeared as both L2 under cog AND a ghost L0 root with ash under it

fen was spawned correctly at depth=2 by cog, but when fen spawned ash using --spawned-by self (Cursor env has no ORCA_WORKER_NAME), ensure_l0_orchestrator auto-registered fen as a new L0 orchestrator.

Test plan

  • test_ensure_l0_returns_existing_worker_when_pane_matches_depth_gt0 — pane match on depth>0 worker returns existing name
  • test_ensure_l0_still_creates_l0_when_pane_has_no_worker — genuine L0 case still works
  • test_ensure_l0_returns_existing_l0_when_pane_matches_depth_0 — existing L0 pane match still works
  • test_resolve_self_to_depth_gt0_worker_by_pane — cmd_spawn resolution logic
  • test_resolve_self_unchanged_when_no_pane_match — genuine L0 fallback
  • test_full_chain_self_resolves_correctly_for_l2_worker — full openclaw→cog→fen→ash chain
  • All 623 existing tests pass (552 unit + 59 integration + 12 live)

Made with Cursor

…s (v0.0.8)

Cursor workers don't have ORCA_WORKER_NAME in their shell environment,
so they fall back to `--spawned-by self` even when running at L2+. This
caused ensure_l0_orchestrator to create a ghost L0 entry — the worker
appeared as a separate root tree in `orca list` despite having correct
depth/spawned_by in state.

Two-layer fix:
1. In cmd_spawn, resolve `self` to the existing worker name when the
   calling pane matches a tracked worker with depth > 0, before the L0
   marker check runs.
2. Defense-in-depth in ensure_l0_orchestrator: if the pane already
   belongs to a depth > 0 worker, return that worker's name instead of
   creating a new L0 entry.

Bump version to 0.0.8.

Made-with: Cursor
@github-actions

github-actions Bot commented Mar 21, 2026

Copy link
Copy Markdown

🧪 Coverage Report

Metric Coverage
Lines 87.47% (13175 lines, 1651 missed)
Functions 95.79%
Regions 87.73%
📄 Coverage by file
File Lines Functions Regions
cli.rs 89.52% 98.05% 90.87%
cli/mod.rs 77.58% 84.96% 77.19%
config.rs 94.94% 95.71% 94.35%
config/mod.rs 90.57% 90.00% 87.10%
daemon.rs 80.05% 92.47% 81.36%
daemon/mod.rs 42.12% 76.19% 40.05%
events.rs 99.44% 100.00% 97.63%
events/mod.rs 98.72% 100.00% 92.86%
main.rs 100.00% 100.00% 100.00%
names.rs 100.00% 100.00% 100.00%
names/mod.rs 100.00% 100.00% 100.00%
prompts.rs 100.00% 100.00% 100.00%
prompts/mod.rs 100.00% 100.00% 100.00%
spawn.rs 93.08% 96.43% 92.57%
spawn/mod.rs 90.69% 94.44% 88.74%
state.rs 98.09% 93.33% 96.13%
state/mod.rs 95.36% 87.50% 87.88%
tmux.rs 97.53% 100.00% 96.69%
tmux/mod.rs 93.59% 100.00% 91.99%
wake.rs 98.60% 100.00% 98.93%
wake/mod.rs 95.08% 100.00% 95.67%
worktree.rs 95.25% 100.00% 95.61%
worktree/mod.rs 84.76% 100.00% 83.91%

Coverage must not decrease. See CONTRIBUTING.md for policy.

araa47 added 3 commits March 21, 2026 16:01
- daemon: return 0 instead of panicking on fork() failure
- spawn: compile sh_quote regex once via LazyLock
- cli/spawn: consolidate depth_emoji into spawn, remove cli duplicate

Made-with: Cursor
@araa47
araa47 merged commit a3d55fc into main Mar 21, 2026
3 checks passed
@araa47
araa47 deleted the fix/ghost-l0-self-resolution branch March 21, 2026 08:10
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