Skip to content

ORB-126: Print full terminal handles and retry timed-out terminal creation - #623

Merged
thomasluizon merged 1 commit into
mainfrom
feature/orb-126-print-full-terminal-handles-in-watch
Jul 28, 2026
Merged

ORB-126: Print full terminal handles and retry timed-out terminal creation#623
thomasluizon merged 1 commit into
mainfrom
feature/orb-126-print-full-terminal-handles-in-watch

Conversation

@thomasluizon

Copy link
Copy Markdown
Owner

Summary

  • Print complete Orca terminal handles in /watch, one terminal per line.
  • Retry only timed-out orca terminal create calls with three total attempts and bounded 1-second then 2-second backoff.
  • Require dependency prose to name a Linear issue before enforcing a missing blockedBy relation.
  • Extend the hermetic tools harness across full-handle rendering, retry recovery, bounded exhaustion, rollback, and dependency prose.

Closes ORB-126.

Decisions taken unattended

  • Kept terminal creation retries inside the existing worktree and branch lifecycle so no earlier launch step repeats.
  • Limited retries to Orca timeout codes or the measured Terminal creation timed out message. Other failures remain immediate.
  • Rendered multiple terminal handles on separate indented lines to preserve copyable values without changing output sections or liveness classification.
  • Required the dependency phrase to be followed by a Linear identifier, including common backtick, link, and issue ORB-N forms.

Verification

npm run lint
Tasks:    3 successful, 3 total
Cached:   3 cached, 3 total
Exit code: 0

npm run type-check
Tasks:    3 successful, 3 total
Cached:   3 cached, 3 total
Exit code: 0

npm run test
Tasks:    4 successful, 4 total
Cached:   0 cached, 4 total
Time:     5m4.678s
Exit code: 0

node tools/test-tools.mjs
PASS launch-worker.mjs: a terminal create timeout retries inside the same worktree and then succeeds
PASS launch-worker.mjs: terminal create timeout retries are bounded and preserve the timeout cause
PASS launch-worker.mjs: exhausting terminal create retries rolls back the one worktree and both branches
PASS worker-watch.mjs: the rendered terminal handle is complete and directly reusable
PASS check-ticket.mjs: ordinary prose does not imply a dependency: Cleanup runs after the terminal exits.
PASS check-ticket.mjs: ordinary prose does not imply a dependency: The launcher retries once the daemon is responsive.
PASS check-ticket.mjs: ordinary prose does not imply a dependency: The branch name depends on configuration, and startup can be blocked by a trust prompt.
PASS check-ticket.mjs: a named issue blocker still requires a blockedBy relation
ORBIT TOOLS GATE OK
Exit code: 0

node tools/check-dashes.mjs --files tools/check-ticket.mjs tools/launch-worker.mjs tools/test-tools.mjs tools/worker-watch.mjs
Exit code: 0

node tools/check-copy.mjs --check
Exit code: 0

One final tools-harness run first hit the existing wave-plan.mjs bounded-pool timing assertion at 5.61 seconds while all ORB-126 cases passed. It was rerun after concurrent load cleared and finished with ORBIT TOOLS GATE OK; no threshold or baseline was changed.

@vercel

vercel Bot commented Jul 28, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
orbit-ui-mobile-web Ignored Ignored Jul 28, 2026 1:14am

Request Review

@sonarqubecloud

Copy link
Copy Markdown

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review: PR #623

Scope: PR #623 in thomasluizon/orbit-ui-mobile (feature/orb-126-print-full-terminal-handles-in-watch -> main)
Recommendation: APPROVE

Summary

ORB-126 does three things to tools/: prints the full Orca terminal handle (not a 13-char
truncation) in worker-watch.mjs, adds a bounded retry (3 attempts, 1s then 2s backoff) around
orca terminal create timeouts in launch-worker.mjs, and tightens check-ticket.mjs's
dependency-prose heuristic so it only fires when the prose actually names a Linear identifier.
All four changed files are covered by new, hermetic tools/test-tools.mjs cases that exercise the
real decision paths (recovery, bounded exhaustion + rollback, the rendered handle, and the four
prose cases), and this PR's CI shows Lint / Type Check / Build / Harness Execution all green. One
concrete test gap survives review (Medium, dimension 15).

Findings

Critical

None.

High

None.

Medium

[MEDIUM] createTerminal's non-timeout immediate-fail path has no test case
· dimension: 15 (Harness changes need EXECUTED evidence)
· location: tools/launch-worker.mjs:279-288 (paired with tools/test-tools.mjs:513-536)
· issue: createTerminal has two failure branches: a timeout (retried up to MAX_TERMINAL_CREATE_ATTEMPTS) and any other orca terminal create failure, which is meant to fail(3, ...) immediately with no retry (if (!timedOut) fail(3, ...)). The new terminalCreateRetryCases() only stages a timeout-then-success sequence and a timeout x3 sequence; there is no case that returns a non-timeout error (e.g. { ok: false, error: { code: "worktree-not-found", message: "..." } }) on the first attempt and asserts it fails immediately (1 terminal create call, no backoff pause, no retry).
· risk: this is exactly the shape dimension 15 exists to catch: a branch with real behavior (immediate-fail vs. retry) that ships unexecuted. A future edit that accidentally widens timedOut's regex or drops the !timedOut guard (so every failure gets retried, including permanent ones like a missing worktree) would pass every existing case and only surface as a real launch silently retrying for ~3s before failing anyway.
· fix: add one terminalCreateRetryCases-style case with a single non-timeout ok:false payload and assert terminalCreates === 1, exit 3, and the failure message in stderr (no "retrying" line, no "failed after N attempts" wording).
· reference: .claude/skills/pr-review/rubric.md dimension 15 ("A new decision path added to a tool that already has coverage... needs its own case, not an extension of an existing assertion").

Low / Info

None posted (signal gate).

Subagents

Agent Verdict
parity-checker N/A - no apps/web/** or apps/mobile/** file changed
i18n-syncer N/A - no user-facing strings or i18n JSON changed
contract-aligner N/A - no packages/shared/src/types/* / endpoints.ts / orbit-api DTO changed
security-reviewer N/A - no orbit-api code changed
design-reviewer N/A - no apps/web/**, apps/mobile/**, or landing UI file changed

Validation

Phase 6 (/validate) skipped per scope instructions; Build/Unit Tests/SonarCloud run as separate
required CI checks on this PR.

Check Result
Lint (CI: PR Tests / Lint) PASS
Type check (CI: PR Tests / Type Check) PASS
Build (CI: PR Tests / Build) PASS
Harness Execution (node tools/test-tools.mjs + node .claude/hooks/test-hooks.mjs) PASS
Unit Tests (CI: PR Tests / Unit Tests) running at review time; PR body reports a local npm run test pass (4/4, 5m4.678s) as independent evidence
Guards.yml (Dash Ban, Copy Register, Suppressions Ratchet, Expo SDK Pin, Cross-Platform Parity, Skill and Agent Frontmatter) PASS

Deferred - N/A dimensions & files not verdicted

  • Dimension 8 (DESIGN.md/AI-slop) - N/A, diff touches only tools/**, no apps/* UI files.
  • Dimension 9 (Parity) - N/A, no apps/web/** or apps/mobile/** changed.
  • Dimension 10 (i18n) - N/A, no user-facing strings or locale JSON changed.
  • Dimension 11 (Contract drift + backward-compat) - N/A, no packages/shared/src/types/* or orbit-api DTO changed; not verifiable in CI regardless since the sibling orbit-api repo is not checked out in this session.
  • Dimension 12 (Security, API side) / Dimension 13 (Backend hard rules) - N/A, no orbit-api code in the diff; not verifiable in CI (sibling repo not checked out).
  • Dimension 14 (FEATURES.md parity) - N/A, internal agent-tooling change with no user-facing feature-surface effect.
  • All four changed files (tools/check-ticket.mjs, tools/launch-worker.mjs, tools/test-tools.mjs, tools/worker-watch.mjs) received a verdict; nothing in the diff was left unexamined.

What's good

  • The retry logic matches its own stated bound precisely: 3 attempts, backoff 1000 * attempt ms
    (1s then 2s), and the exhaustion path is proven end to end including rollback of the one worktree
    and both branches it created (tools/test-tools.mjs:529-536), not just the retry itself.
  • check-ticket.mjs's narrowed regex was validated against exactly the three false-positive
    sentences it exists to stop flagging, plus one true positive.
  • worker-watch.mjs's test distinguishes the full handle from the old truncated-then-space form
    with a negative assertion, the right level of care for a change that looks purely cosmetic and is
    easy to under-test.
  • The ORCA stub (orca-shim.cjs) extension (pruneRepo, object-shaped sequence entries) is a
    minimal, backward-compatible generalization; existing string-sequence callers are untouched.

Recommendation

Approve as-is. The one Medium finding (missing non-timeout-failure test case in
terminalCreateRetryCases) is a concrete, easily-added follow-up but does not block merge per the
rubric's signal gate (Medium is "fix soon; OK to merge with a tracked follow-up").

@thomasluizon
thomasluizon merged commit 328b934 into main Jul 28, 2026
28 checks passed
@thomasluizon
thomasluizon deleted the feature/orb-126-print-full-terminal-handles-in-watch branch July 28, 2026 01:25
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