Skip to content

refactor: close the daemon platform boundary - #2072

Merged
thymikee merged 3 commits into
refactor/daemon-platform-androidfrom
refactor/daemon-platform-lifecycle
Aug 27, 2026
Merged

refactor: close the daemon platform boundary#2072
thymikee merged 3 commits into
refactor/daemon-platform-androidfrom
refactor/daemon-platform-lifecycle

Conversation

@thymikee

@thymikee thymikee commented Aug 27, 2026

Copy link
Copy Markdown
Member

Summary

Finish #1739's terminal daemon boundary: readiness and lifecycle mechanics, Android/Web durable cleanup, Apple runner resources, selector probing, and recording health now resolve through focused root owners. Production src/daemon has zero imports of src/platforms or concrete platform packages and has been removed from the R3 seam.

Add R65, a tracked-production AST gate that rejects static, dynamic, type-only, TS import types, re-exports, CommonJS/TS require forms, template literals, and statically constructed platform specifiers. The planted-red suite also proves comments, ordinary strings, tests, and non-daemon files do not create false positives.

Closes #1739.

Validation

The terminal scan moved from 38 edges across 15 files to zero. Descriptor checks remain at zero legacy execution modes and zero production capability buckets. The full 196-test layering suite passes with src/daemon removed from R3.

Focused readiness, teardown, request-lock, recording-health, selector, session refresh, and sessionless cleanup tests pass (107 assertions across the final slice). Two Luna-max adversarial reviews found no lifecycle P0-P2 issues and drove closure of four syntactic gate bypass classes.

The complete affected run passed format, lint, typecheck, layering, fallow, build/package, Node integration, and provider integration. It reached 458/459 related files and 3,429/3,430 tests; the only failure was an unrelated Apple-runner concurrency test exceeding its 5-second timeout under full load, then passing alone in 149 ms. Native and coverage lanes remain GitHub-authoritative.

The complete stack touches 57 files and is +288 net production lines; most additions are typed owner seams and the terminal AST gate. No docs or skills changed because command behavior is unchanged. HarmonyOS perf remains unsupported and receives no new implementation.

@thymikee
thymikee force-pushed the refactor/daemon-platform-lifecycle branch from 31192d8 to 3148b3d Compare August 27, 2026 07:41
@thymikee thymikee changed the title refactor/daemon platform lifecycle refactor: close the daemon platform boundary Aug 27, 2026
@github-actions

github-actions Bot commented Aug 27, 2026

Copy link
Copy Markdown

Size Report

Metric Base Current Diff
JS raw 2.47 MB 2.48 MB +4.6 kB
JS gzip 831.0 kB 833.0 kB +2.0 kB
npm tarball 954.8 kB 956.1 kB +1.3 kB
npm unpacked 3.31 MB 3.31 MB +4.6 kB

npm unpacked components

Component Base Current Diff
JS / dist source 2.63 MB 2.63 MB +4.6 kB
Apple runner source/project 581.1 kB 581.1 kB 0 B
macOS helper source 54.8 kB 54.8 kB 0 B
Android helper artifacts 0 B 0 B 0 B
Other package files 45.3 kB 45.3 kB 0 B

Startup median (7 runs, lower is better):

Scenario Base Current Diff
CLI --version 29.8 ms 29.7 ms -0.0 ms
CLI --help 79.8 ms 81.7 ms +1.8 ms

Top changed chunks:

Chunk Raw diff Gzip diff
dist/src/internal/daemon.js +2.7 kB +594 B
dist/src/session2.js +681 B +191 B
dist/src/runner-client.js -145 B -60 B
dist/src/perf-runtime-plan.js -11 B +6 B
dist/src/snapshot.js -1 B -2 B

Top changed packed files

Packed file Base Current Diff
dist/src/agent-browser-tool.js 11.4 kB 5.8 kB -5.5 kB
dist/src/agent-browser-lifecycle.js 0 B 4.0 kB +4.0 kB
dist/src/internal/daemon.js 107.5 kB 110.2 kB +2.7 kB
dist/src/owned-process-reaper.js 0 B 2.0 kB +2.0 kB
dist/src/tool-provider.js 4.2 kB 3.4 kB -809 B
dist/src/tool-provider2.js 3.4 kB 4.2 kB +809 B
dist/src/session2.js 215.7 kB 216.4 kB +681 B
dist/src/device-isolation.js 0 B 275 B +275 B
dist/src/session-runtime-admission.js 1.6 kB 1.9 kB +246 B
dist/src/snapshot-runtime-binding.js 6.6 kB 6.4 kB -241 B

@thymikee
thymikee force-pushed the refactor/daemon-platform-lifecycle branch from 3148b3d to a4d28bd Compare August 27, 2026 07:46
@thymikee
thymikee force-pushed the refactor/daemon-platform-lifecycle branch from a4d28bd to d1c7971 Compare August 27, 2026 07:55
@thymikee

Copy link
Copy Markdown
Member Author

P1: R65 proves zero direct import edges, but #1739’s terminal condition is broader: every surviving daemon platform branch/tag must be enumerated and identifier-only, never selecting behavior. This head still selects Android snapshot-helper cleanup and Web browser cleanup in src/daemon/session-teardown.ts, and Apple runner cleanup in src/daemon/handlers/snapshot-session.ts. R65 only scans import specifiers, so all three semantic dispatches pass; the PR supplies neither the required residual-branch inventory/justifications nor a semantic guard. Move the selection behind focused root-runtime/bound-runtime cleanup operations that accept neutral device/session input, then add planted-red proof for the residual semantic boundary (or an explicit identifier-only allowlist) before claiming terminal closure or closing #1739. The direct-edge gate itself is sound and green; #2071 also remains an open stack dependency.

@thymikee

thymikee commented Aug 27, 2026

Copy link
Copy Markdown
Member Author

Re-reviewed head d1c7971. The only material delta is the rebase/eager-closure budget update; the P1 semantic platform-selection finding remains unresolved (src/daemon/session-teardown.ts still selects Android/Web cleanup and src/daemon/handlers/snapshot-session.ts selects Apple cleanup). R65 is unchanged. This is not ready.

@thymikee
thymikee force-pushed the refactor/daemon-platform-lifecycle branch from d1c7971 to 374879e Compare August 27, 2026 09:38
@thymikee

thymikee commented Aug 27, 2026

Copy link
Copy Markdown
Member Author

Addressed in a41a147. Android snapshot-helper, Web browser, Apple sessionless cleanup, and runner-retention selection now live behind the root-composed PlatformResourceCleanup contract; daemon teardown only orchestrates neutral operations. R65 guards cleanup orchestrators semantically and covers platform predicates, tags, destructuring, static/type/dynamic/re-export/require/createRequire/triple-slash imports. The planted daemon cleanup violation was observed red and the rebased layering gate passes.

@thymikee
thymikee force-pushed the refactor/daemon-platform-lifecycle branch 2 times, most recently from 6d0e239 to 96ca4d5 Compare August 27, 2026 09:51
@thymikee
thymikee force-pushed the refactor/daemon-platform-lifecycle branch from 96ca4d5 to a41a147 Compare August 27, 2026 09:58
@thymikee

thymikee commented Aug 27, 2026

Copy link
Copy Markdown
Member Author

Addressed in a1873f6. Android snapshot-helper, Web browser, Apple sessionless cleanup, and runner-retention selection now live behind the root-composed PlatformResourceCleanup contract; daemon teardown only orchestrates neutral operations. R65 guards cleanup orchestrators semantically and covers platform predicates, tags, destructuring, static/type/dynamic/re-export/require/createRequire/triple-slash imports. The planted daemon cleanup violation was observed red and the rebased layering gate passes.

@thymikee
thymikee force-pushed the refactor/daemon-platform-lifecycle branch from a41a147 to a1873f6 Compare August 27, 2026 10:01
@thymikee

Copy link
Copy Markdown
Member Author

[P2] Preserve synchronous cleanup methods in the unavailable fallback

unavailablePlatformResourceCleanup wraps every property in an async Proxy function, but retainExecutionHostAfterClose is deliberately synchronous and session-close-lifecycle-teardown branches on its boolean result without awaiting it. When platform-resource cleanup is unavailable, that call therefore returns a truthy Promise (and rejects asynchronously) instead of false, so the daemon can incorrectly retain the execution host and emit an unhandled rejection. Please replace the async-only Proxy with an explicit typed unavailable implementation (or otherwise preserve each method's sync/async contract) and add a missing-injection regression that exercises the synchronous retention decision.

@thymikee

Copy link
Copy Markdown
Member Author

Re-reviewed the rewritten head: the previously reported synchronous unavailable-cleanup P2 remains unresolved. The only delta is an unrelated daemon-runtime lifecycle-shutdown test mock; unavailablePlatformResourceCleanup still returns an async Proxy function for the synchronous retainExecutionHostAfterClose method. The requested typed fallback and missing-injection synchronous-retention regression are still required. Exact-head CI is queued/in progress.

@thymikee
thymikee force-pushed the refactor/daemon-platform-lifecycle branch from a1873f6 to d5eb2f0 Compare August 27, 2026 10:18
@thymikee

Copy link
Copy Markdown
Member Author

Addressed in d5eb2f0. The missing PlatformResourceCleanup fallback is now an exact typed object: its three async methods reject, while retainExecutionHostAfterClose throws synchronously. I added a production-router regression that omits the injection and proves close returns INTERNAL_ERROR before teardown or dispatch. I also fixed both prior coverage-shard failures: orientation now injects the existing Android observation fixture instead of reaching real ADB through a retired mock path, and the lock-serialization poll has a CI-safe timeout. Local validation: full pnpm test:coverage:ci passed (1,169 files, 8,718 tests, 90.57% lines), focused coverage tests passed, and format, lint, typecheck, and layering passed.

@thymikee
thymikee force-pushed the refactor/daemon-platform-lifecycle branch from d5eb2f0 to ae3cb6c Compare August 27, 2026 10:26
@thymikee

Copy link
Copy Markdown
Member Author

Follow-up coverage fix is now on ae3cb6c9c5. The remaining shard-1 failure was the test-level default 5s timeout racing the newly widened inner vi.waitFor budget; the serialization test now has an explicit 15s total budget while retaining 5s assertion waits. The exact regression passed locally in 724ms. The earlier full local pnpm test:coverage:ci run remains green (1,169 files / 8,718 tests; 88.59% statements, 80.63% branches, 91.68% functions, 90.57% lines). I am watching both replacement coverage shards on this exact head.

@thymikee
thymikee force-pushed the refactor/daemon-platform-lifecycle branch from ae3cb6c to 57b29e4 Compare August 27, 2026 10:36
@thymikee

Copy link
Copy Markdown
Member Author

Final coverage follow-up is on 57b29e4595. The second shard-1 failure showed the test was still waiting for start-scroll merely to release the scroll callback; under coverage load, screenshot had ended but that scheduling handshake could exceed 5s. I removed that circular handshake. Screenshot remains explicitly blocked, scroll completes immediately once it acquires the lock, and the final ordered trace plus maxActive === 1 still proves cross-session serialization. Validation on this exact code: the focused test passes under V8 coverage (1.06s), and full pnpm test:coverage:ci passes 1,169 files / 8,718 tests at 88.60% statements, 80.63% branches, 91.68% functions, 90.58% lines.

@thymikee

Copy link
Copy Markdown
Member Author

The synchronous PlatformResourceCleanup fallback P2 is resolved on this head: the typed unavailable object preserves the sync/async method contracts, and the production-handler close regression would fail against the former async Proxy. However, this exact head is not ready because Coverage (1) fails in the changed request-router-screenshot serialization regression: scrollResponse.ok is false at line 281. The log does not expose the returned error, so this needs an exact-head reproduction or added assertion diagnostics followed by a green coverage run before readiness.

@thymikee
thymikee force-pushed the refactor/daemon-platform-lifecycle branch from 57b29e4 to b1ba32d Compare August 27, 2026 11:00
@thymikee

Copy link
Copy Markdown
Member Author

Fixed the remaining screenshot serialization failure. scrollResponse.ok was false because the test runtime omitted the newly required Android observation seam; the correction now lives in #2071's shared fixtures and this PR has been restacked on it (b1ba32d5cf).

Exact #2072-head validation:

  • full pnpm test:coverage:ci: 1,169 files and 8,718 tests passed, plus fuzz worker
  • coverage: 88.58% statements / 80.61% branches / 91.67% functions / 90.57% lines
  • request-router-screenshot.test.ts: 16/16 passed, including same-device cross-session serialization
  • isolated late-teardown reproduction suite: 17/17 passed

The full affected run passed every product assertion but encountered 10 late Vitest module-runner teardown errors under host contention after 3,760 passing assertions; the exact implicated suite passed immediately in isolation.

@thymikee

Copy link
Copy Markdown
Member Author

Re-reviewed the replacement head. The prior Coverage failure is addressed without weakening the serialization invariant: the lock test and its ordering assertions are unchanged, while router tests that do not exercise Android state now receive an explicitly benign observation fixture instead of accidentally reaching real ADB state. Platform-state tests still inject their behavior-specific fixtures, and production still composes the real adapter. I found no new code issue. Exact-head coverage and several CI/native lanes are still running.

@thymikee thymikee added the ready-for-human Valid work that needs human implementation, judgment, or maintainer merge label Aug 27, 2026
@thymikee
thymikee merged commit c794c11 into main Aug 27, 2026
26 of 39 checks passed
@thymikee
thymikee deleted the refactor/daemon-platform-lifecycle branch August 27, 2026 11:11
@github-actions

Copy link
Copy Markdown
PR Preview Action v1.8.1
Preview removed because the pull request was closed.
2026-08-27 11:12 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.

refactor(daemon): platform-free daemon — broader migration waves (successor to #1696)

1 participant