Skip to content

refactor(apple): name runner lease compatibility facts - #3445

Merged
thymikee merged 1 commit into
mainfrom
refactor/runner-lease-legacy-facts
Oct 11, 2026
Merged

thymikee merged 1 commit into
mainfrom
refactor/runner-lease-legacy-facts

Conversation

@thymikee

@thymikee thymikee commented Oct 11, 2026 •

Copy link
Copy Markdown
Member

Summary

  • Each optional RunnerLease field documents the release that started writing it and what its absence means. Fallbacks that exist only for older releases say when they can be deleted (leaseOwnerHoldsDeviceClaims for < v0.21.0, leasedRunnerEndpoint for < v0.21.25).
  • Removes the device-wide xcodebuild sweep (buildRunnerSessionXctestrunDeviceCleanupPattern). It matched only session-<device>-<port> names from before v0.17.1 (no owner token), so it never reached a launch from a later release. Cleanup now always targets the artifact path a lease recorded; an empty lease signals nothing.
  • runnerStartTime is string | null (normalization already turned absence into null).
  • Drops a stale header note about a daemon-client sweep literal that no longer exists.

Validation

  • pnpm check:affected --run: pass (406 test files).

View guided diff Turn on auto-fix

Each optional lease field now states the release that started writing it
and what its absence means; the device-claim gate reads through a named
predicate that says when it can go.

Remove the device-wide xcodebuild sweep. It matched only session names
from before v0.17.1, which carry no owner token; every later launch is
reached through the artifact path its lease recorded.

runnerStartTime is always present after normalization, so the type no
longer admits undefined.
@github-actions

Copy link
Copy Markdown
Contributor

Size Report

Metric Base Current Diff
Installed (including dependencies) 5.17 MB 5.17 MB -121 B
Package (unpacked) 5.17 MB 5.17 MB -121 B
Package (download) 1.55 MB 1.55 MB -62 B

Startup median (7 runs, lower is better):

Scenario Base Current Diff
CLI --version 26.3 ms 27.1 ms +0.7 ms
CLI --help 75.8 ms 77.6 ms +1.8 ms

@cubic-dev-ai cubic-dev-ai 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.

2 issues found across 10 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="packages/platform-apple/src/runner/runner-lease.ts">

<violation number="1" location="packages/platform-apple/src/runner/runner-lease.ts:56">
P3: `classifyRunnerLease` still passes `ownerStartTime` to `classifyOwnerLiveness`, so absence of this field skips only the directory check, not PID-reuse detection. Describe the fallback as checking the PID and recorded start time.</violation>

<violation number="2" location="packages/platform-apple/src/runner/runner-lease.ts:223">
P2: The empty-lease early return drops the only sweep that could reach a stray xcodebuild whose lease file is absent, unreadable, or corrupt. `cleanupLeasedRunnerProcesses` is the sole remaining cleanup path and always requires a parsed lease with an artifact path, so a runner orphaned between xcodebuild launch and lease write (e.g. daemon SIGKILLed mid-startup), or a lease file that fails `normalizeRunnerLease`, is never signaled. This matches the PR's stated intent, but it is still a coverage regression worth confirming: previously `cleanupRunnerXcodebuildProcesses({ deviceId })` reclaimed that case device-wide, and `runner-disposal.ts` now early-returns without a `xctestrunPath` artifact pattern.</violation>
</file>

Reply with feedback, questions, or to request a fix.

View guided diff | Turn on auto-fix | Re-trigger cubic

await cleanup.cleanupRunnerXcodebuildProcesses({ deviceId });
return;
}
if (state.type === 'empty') return;

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.

P2: The empty-lease early return drops the only sweep that could reach a stray xcodebuild whose lease file is absent, unreadable, or corrupt. cleanupLeasedRunnerProcesses is the sole remaining cleanup path and always requires a parsed lease with an artifact path, so a runner orphaned between xcodebuild launch and lease write (e.g. daemon SIGKILLed mid-startup), or a lease file that fails normalizeRunnerLease, is never signaled. This matches the PR's stated intent, but it is still a coverage regression worth confirming: previously cleanupRunnerXcodebuildProcesses({ deviceId }) reclaimed that case device-wide, and runner-disposal.ts now early-returns without a xctestrunPath artifact pattern.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At packages/platform-apple/src/runner/runner-lease.ts, line 223:

<comment>The empty-lease early return drops the only sweep that could reach a stray xcodebuild whose lease file is absent, unreadable, or corrupt. `cleanupLeasedRunnerProcesses` is the sole remaining cleanup path and always requires a parsed lease with an artifact path, so a runner orphaned between xcodebuild launch and lease write (e.g. daemon SIGKILLed mid-startup), or a lease file that fails `normalizeRunnerLease`, is never signaled. This matches the PR's stated intent, but it is still a coverage regression worth confirming: previously `cleanupRunnerXcodebuildProcesses({ deviceId })` reclaimed that case device-wide, and `runner-disposal.ts` now early-returns without a `xctestrunPath` artifact pattern.</comment>

<file context>
@@ -198,10 +220,7 @@ export async function prepareRunnerLeaseForStartup(
-    await cleanup.cleanupRunnerXcodebuildProcesses({ deviceId });
-    return;
-  }
+  if (state.type === 'empty') return;
   if (state.type === 'busy') {
     if (isSameStateDirRunnerLease(state.lease)) {
</file context>

ownerStartTime: string | null;
/**
* The owner's AGENT_DEVICE_STATE_DIR. Absent when the owner had none, and on leases written before
* v0.17.10; either way the owner is judged by its pid alone.

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.

P3: classifyRunnerLease still passes ownerStartTime to classifyOwnerLiveness, so absence of this field skips only the directory check, not PID-reuse detection. Describe the fallback as checking the PID and recorded start time.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At packages/platform-apple/src/runner/runner-lease.ts, line 56:

<comment>`classifyRunnerLease` still passes `ownerStartTime` to `classifyOwnerLiveness`, so absence of this field skips only the directory check, not PID-reuse detection. Describe the fallback as checking the PID and recorded start time.</comment>

<file context>
@@ -39,47 +39,71 @@ export function runnerOwnerToken(): string {
   ownerStartTime: string | null;
+  /**
+   * The owner's AGENT_DEVICE_STATE_DIR. Absent when the owner had none, and on leases written before
+   * v0.17.10; either way the owner is judged by its pid alone.
+   */
   ownerStateDir?: string;
</file context>
Suggested change
* v0.17.10; either way the owner is judged by its pid alone.
* v0.17.10; either way liveness uses the PID and recorded start time, without a state-directory check.

@thymikee

Copy link
Copy Markdown
Member Author

This PR is ready to merge at 3d554ab. I found no problems in the code, and CI is green with 19 of 19 checks passing. I did not run tests or typecheck locally and relied on CI. No conflicts. Nothing else blocks the merge.

Not blocking: you can take or leave these. Startup no longer runs the pkill sweep on xcodebuild when no lease is present, so a runner from v0.17.0 or earlier is no longer signalled before a new launch. The PR body says this, but the CHANGELOG does not, so one CHANGELOG line would help. Also, one line in the verifyLeaseRunnerPidIdentity doc block in runner-lease.ts runs past the wrap width of the rest of the block.

On the open review threads, one still applies and is a wording fix only. The owner comment at runner-lease.ts:56 says "pid alone", but PID-reuse detection also uses the start time (#3445 (comment)). One does not apply, so please resolve it: the removed sweep only matched pre-v0.17.1 names, so no supported release loses cleanup (#3445 (comment)).

I could not tell whether any production path writes a lease whose xctestrunPath is a plain Runner.xctestrun. Either way, the old fallback for such a lease only matched pre-v0.17.1 names, so behavior for supported releases is the same.

@thymikee thymikee added the ready-for-human Valid work that needs human implementation, judgment, or maintainer merge label Oct 11, 2026
@thymikee
thymikee merged commit ca178a4 into main Oct 11, 2026
19 checks passed
@thymikee
thymikee deleted the refactor/runner-lease-legacy-facts branch October 11, 2026 18:53
@github-actions

Copy link
Copy Markdown
Contributor
PR Preview Action v1.8.1
Preview removed because the pull request was closed.
2026-10-11 18:53 UTC

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-for-human Valid work that needs human implementation, judgment, or maintainer merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant