Route snapshot capture sources through one platform-neutral router

Aperta
#4,205 1 commento 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
5/5
Tempo stimato
Più di una settimana
Idoneità per principianti
5/100
Tipo di issue
Refactoring
Chiarezza
Abbastanza chiara
Stato di attività
Attiva
Stack tecnologico
android, ios, macos, typescript
Ambito
mobile, tooling

Direzione di ricerca

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.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

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.

Lingua principale
TypeScript
Stelle
5.3k
Fork
377
Merge medio
13h 18m
PR unite (30g)
653

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di callstack/agent-device

Tutte le issue di callstack/agent-device

Issue simili

Altre issue su TypeScript

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.