callstack / callstack/agent-device

refactor(contracts): expand additive capability facts to the keyboard, gesture and clipboard families

Open
#2,443 3 comments 0 reactions 0 assignees View on GitHub
refactor
Dominant language
TypeScript
Stars
4.6k
Forks
299
Avg merge
10h 17m
Merged PRs (30d)
515

Description

Wave 2 child of #2409. Continues #2412 (pilot merged as #2420, `edbd96ea30`). The pilot's stop rule passed with seven unsupported-owner edits avoided against a floor of two, so expansion is authorized on the same terms, one family per PR.

## Purpose

Adding a capability to one platform stops forcing edits in the platforms that do not support it, for the next families where owners still write a denial out cell by cell.

## Baseline

On `main` at `41e2633f10`:

- The touch family is additive. `TouchRuntimeOperationFactsInput.unsupported` is a required family-level denial (`packages/contracts/src/touch-runtime.ts:88`), every operation input is optional, and `declared(fact) = fact ?? input.unsupported` (`:103`). An owner that leaves an operation blank gets the family's typed denial with the same reason and hint it would have written by hand.
- Every other multi-operation family is required-per-operation: `keyboardRuntimeOperationFacts` (`packages/contracts/src/keyboard-runtime.ts:46`, 3 operations), `gestureRuntimeOperationFacts` (`gesture-runtime.ts:74`, 5), `clipboardRuntimeOperationFacts` (`clipboard-runtime.ts:48`, 2), plus alert (4), snapshot (3), selector-observation (2), perf (7), audio-probe (4), application-lifecycle (9).
- Owners that write a whole family as unavailable today, cell by cell:
- keyboard: web (`packages/platform-web/src/runtime.ts:416`), webdriver (`packages/provider-webdriver/src/platform-runtime.ts:568`, raw keys without the builder), vega (`packages/platform-vega/src/runtime.ts:203`, raw keys). harmonyos implements 2 of 3.
- gesture: vega (`packages/platform-vega/src/runtime.ts:236`), web (`packages/platform-web/src/runtime.ts:401`).
- clipboard: harmonyos, web, vega.
- PR #2420's replay of an Apple-only touch operation: 16 files / 8 packages before, 5 files / 2 packages after.

## Required work

One PR per family, in this order: keyboard, gesture, clipboard.

1. Give the family builder the touch shape: a required `unsupported` cell on the input, optional per-operation inputs, `declared(fact) = fact ?? input.unsupported`. Owners that write raw keys (webdriver and vega for keyboard) move to the builder in the same PR, so the family has one entry point.
2. Owners that implement nothing in the family supply only `unsupported`; owners that implement part of it omit the rest. Reasons and hints are unchanged: the admission tests that assert each non-supporting platform's unavailable reason stay green with no edits.
3. Replay a single-platform addition on the new shape (add one operation to the family, implemented by one platform, the way #2420 replayed `tapElementSelector`). Record in the PR body the files the compiler forces before and after, and the count of unsupported-owner edits avoided.
4. Stop rule per family: fewer than two unsupported-owner edits avoided means that family is not merged. Post the measurement here and move to the next family.
5. Keep the guard PR #2420 restored after its first pass: an owner cannot lose an explicit cell silently. The family's exhaustive test (`keyboard-runtime.test.ts` and siblings) asserts the full fact shape for a fully-declared owner and for an `unsupported`-only owner.

## Acceptance, measurable from git

- Per family: the replayed addition touches contracts, the one implementing platform package, and tests. The other platform and provider packages are untouched.
- Per family: unsupported-owner edits avoided ≥ 2, recorded in the PR body.
- Typed denial unchanged: no edit in any test that asserts an unavailable reason for a non-supporting platform.
- Umbrella metric, measured with the frozen script on #2409: feat+fix commits touching ≥ 2 packages ≤ 10% over the first 100 feat+fix commits after the last family merges.

## Non-goals

- Blanket defaults across all families. The remaining six multi-operation families (alert, snapshot, selector-observation, perf, audio-probe, application-lifecycle) wait for this issue's measurements.
- A default that hides an unclassified capability or implies success.
- Single-operation families; there is nothing to make additive.

## Dependencies

None. Builds on #2420 (`edbd96ea30`).

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.