Route snapshot capture sources through one platform-neutral router

Offen
#4,205 1 Kommentar 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Maintainer antworten meist innerhalb von 1 Tag

Dieses Issue hat noch niemand übernommen.

Bewertung

Schwierigkeit
5/5
Geschätzter Aufwand
Über eine Woche
Anfängerfreundlichkeit
5/100
Issue-Typ
Refactoring
Klarheit
Größtenteils klar
Aktivitätsstatus
Aktiv
Tech-Stack
android, ios, macos, typescript
Bereich
mobile, tooling

Rechercherichtung

Start with the iOS route core in packages/platform-apple/src/snapshot-route.ts and its failure policy in snapshot-route-failure-policy.ts, then the constant ports in packages/platform-apple/src/runner-runtime.ts. The ADR decision on Android's system-UI annotation and SurfaceProof must land before any code moves, and the work is blocked by #4182 on unmerged runner layers. Done means one router in packages/capture-kit serves all channels, with no constant-filled ports and the existing route tests passing unchanged.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Beschreibung

refactor

Purpose

Snapshot capture source selection must be one product rule for every platform and provider. Today the rule exists only for iOS, in packages/platform-apple/src/snapshot-route.ts, and each channel fills the route's ports with placeholders. Android, macOS, web, WebDriver and Revyl each have one hard-wired source with no shared fallback, refusal or proof vocabulary. Producer facts live in about six owners.

Current state (evidence)

  • The iOS route core: packages/platform-apple/src/snapshot-route.ts (probes, target resolution, acquisition, one fallback, identity stamping, warnings) and snapshot-route-failure-policy.ts (refusal scope).
  • The runner channel (#4182) fills the route's ports with constants: isDiscoveryPending: () => false, targetFreshness: 'cached', systemSurfacePresent: async () => 'unknown' (packages/platform-apple/src/runner-runtime.ts). The route reads them at snapshot-route.ts (discovery wait, cached-target refresh, presence probe).
  • Eligibility is split: isEligible in the route, the observe-only bypass in runner-runtime.ts bindBridgeSnapshot, and the preferredBackend verdict pin in packages/capture-kit/src/snapshot-quality-verdict.ts → stable-capture.ts.
  • Producer facts: packages/contracts/src/ios-snapshot.ts, three producer-keyed tables in packages/capture-kit/src/ios-snapshot-acquisition.ts, packages/kernel/src/snapshot.ts (SnapshotProvenance), packages/command-runtime/.../stable-capture.ts, producer switches in packages/command-runtime/src/commands/capture/runtime/snapshot.ts. Revyl's Android tree is labeled appium-source, the same name WebDriver uses for iOS.
  • Single-source platforms: Android packages/platform-android/src/snapshot-capture.ts, macOS packages/platform-apple/src/os/macos/surface-snapshot.ts, Revyl packages/provider-revyl/src/snapshot.ts, WebDriver packages/provider-webdriver/src/webdriver-ios-snapshot.ts.
  • validateTarget is duplicated in snapshot-source/adapter.ts and runner-snapshot-bridge.ts. Three fallback settlers exist: runFallback, runSurfaceFallback, captureOffRoute.
  • ADR 0004 is about 60 KB. docs/adr/FORMAT.md asks for about 8 KB.

Required behavior

  1. A new ADR, "Snapshot capture source routing", states the rule for all platforms. ADR 0004 keeps only the iOS facts (bridge, runner plan, system-surface hosts) and drops its amendment history.

  2. One platform-neutral router in packages/capture-kit owns: the source plan (plan(input) returns the source and the reason), one fallback per capture, the per-target generation circuit, the refusal table (capture scope vs generation scope), occlusion proof, identity stamping, and warnings. It imports no platform package.

  3. Each platform or provider declares its channels. A channel declares only what it has. A channel never fills a port with a constant.

    type SurfaceProof = (device, signal) =>
      Promise<'clear' | Readonly<{ occluded: string }> | 'unproven'>;
    type SourceChannel<T> = Readonly<{
      producer: SnapshotProducer;
      acquire(req: { target: T; hint; signal }): Promise<SourceOutcome>;
      resolveTarget(device, app, signal): Promise<T>;
      refreshTarget?(device, app, signal): Promise<T>;   // replaces targetFreshness
      awaitDiscovery?(device, signal): Promise<void>;    // replaces isDiscoveryPending
      proof: 'none' | SurfaceProof;                      // replaces the presence/foreground pair
      supports: { customActions: boolean; observeOnly: boolean; pinnedBackend: boolean };
    }>;
    
  4. iOS local, iOS provider (Limrun runner channel), Android, macOS and web route through the router. A single-source platform is the one-channel case.

  5. One producer registry in packages/contracts, declared with satisfies Record<SnapshotProducer, ProducerFacts> (channel, truncation, residue, quiet time, ref-namespace owner). The producer union is platform-neutral. Every other producer table derives from the registry.

  6. The refusal fixture contracts/fixtures/ios-snapshot-bridge-refusals.json (#4182) becomes the router's refusal table input for every channel that emits typed refusals.

Completion conditions

  • git grep finds no route port filled by a constant (() => false, async () => 'unknown') and no targetFreshness.
  • A layering rule fails when the router module imports a platform or provider package.
  • A repo guard fails when a producer in the registry has no production emitter.
  • A repo guard fails when an ADR cites a file path or test name that does not exist.
  • Existing route behavior tests pass unchanged against the router, for the guest and runner channels.
  • Live check: local iOS Simulator, Limrun iOS, local Android emulator. Each capture names the same producer and fallback warnings as before the change.
  • The new ADR is accepted, and ADR 0004 is under about 15 KB.

Dependencies

Blocked by: #4182 (runner-served bridge and refusal fixture), which is stacked on the unmerged Limrun runner layers (stack/limrun-native-runner).
Open question: whether Android's system-UI annotation fits the SurfaceProof port. Decide this in the ADR before code moves.

Vorherrschende Sprache
TypeScript
Sterne
5.3k
Forks
377
Ø Merge
14 Std. 6 Min.
Gemergte PRs (30 T.)
650

Entwicklungsumgebung

Erste Schritte

  1. Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
  3. Forken Sie das Repository und arbeiten Sie in einem Branch.
  4. Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.

Mehr aus callstack/agent-device

Alle Issues in callstack/agent-device

Ähnliche Issues

Weitere Issues zu TypeScript

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.