refactor(daemon): one capture-input builder and one admit-then-bind step
Summary
Behaviour-neutral cleanup around the request-bound snapshot capture path. No descriptor changes its platform execution, no contract surface is added, and no workspace package is touched — the diff is five source files plus one test-helper import path. Three things:
- One capture-input builder.
buildRuntimeCaptureInputmoves out ofsnapshot-runtime-binding.tsintosnapshot-runtime-capture-input.ts— the one place a daemon request becomes neutralCaptureSnapshotInput. Its parameter list is exactly whatsnapshot/diffpass; nothing speculative. - One named admit-then-bind step. The snapshot/diff resolver's admission sequence — side-effect-free facts inspection, refusal before any binding, then exactly one bind on the device the admission was minted for — becomes
admitAndBindSnapshotCapture, module-private. Same behaviour, one place. handlers/find.tssplits, 600 → 346 lines. It was already past the 300-line tripwire and answered three questions at once. The target-capture policy (interactive-only tree plus find's two sparse-recovery re-captures) and the match-resolution pipeline (locator/selector matching, on-screen preference, interactive ranking, the ambiguous-match error) move to focused modules. Pure refactor: identical behaviour, response shapes, capture path, and tests.
Scope note
This PR was re-scoped twice under review, each time correctly:
-
It began as the
findcutover. Declaringfinddevice-runtimeclaims its whole platform-execution projection (ADR 0019 §6), whilefind focusandfind typestill reach the device throughdispatchCommand— Wave 5 surfaces — and a third edge of the same class,find <q> get text→dispatchCommand(device, 'read'), is shared withget.findkeepsLEGACY_PLATFORM_EXECUTION, its capability bucket, itsrequireCommandSupported('find', …)admission, and itsHARMONYOS_SUPPORTED_COMMANDS/WEB_QUERY_COMMANDSentries. Rule id R35 is withdrawn from the cutover table entirely rather than left half-claimed, and stays reserved for find's real cutover. -
It then carried the selector capture seam, and then
CaptureSnapshotInput.signalwith its exportedcaptureSnapshotSignalhelper and Apple/Linux composition. Both are now gone, removed for the same reason: ADR 0019 §10 prohibits a facet PR with no consuming command, and §6 admits an early behaviour-neutral substrate only when it is dead-code clean.On the signal contract specifically: an earlier revision of this body carried it with a caveat that no caller set the field. Review escalated that caveat to a blocker, and rightly — an unset contract field means production exercises only the
undefinedbranch, and this PR could not carry a regression proving the per-poll abort and quiescence behaviour it claimed. The field, the helper, and the Apple/Linux composition sites now land in #1875 (wait), whoserunWithinWaitDeadlineis the route that actually sets it and which owns the regression proving the deadline aborts an in-flight capture, waits for it to quiesce, and producescapture-stalledrather thantarget-absent. The selector capture seam went to #1877 (get) on the same principle. Both were handed over as reviewed patches with design notes.
What remains has live production consumers today and is dead-code clean: check:production-exports is unchanged from main.
Validation
pnpm check:affected --run from a clean committed tree. Behaviour neutrality is carried by the existing suites rather than new assertions — snapshot, diff, and find keep their existing paths, and every touched command's test file is byte-identical to main, so they exercise the split find route unchanged. pnpm check:layering is green with the migrated-command list identical to main.
Tradeoffs and known gaps
- Both extractions have a single consumer today. They are named steps, not deduplication — the second caller is the selector family, arriving with
get.admitAndBindSnapshotCaptureis deliberately module-private so this PR does not grow the export surface;get's patch flips it to exported, a one-word change. - Source size: root production TypeScript +3,394 B, workspace-package production TypeScript +0 B. Of the root figure, +1,250 B is the
find.tsthree-way split (module headers, imports, exports — the unavoidable cost of a split the tripwire required) and +2,144 B the two extractions, of which roughly 1.4 kB is the capture-input builder moving rather than new code. Packaged deltas: see the CI Size report on this head rather than a local comparison. - No behaviour, CLI, help, or docs change, so nothing in
website/docs/**orskills/**was touched.
Touched files: 6. Scope narrowed three times; it never expanded.