Repository navigation
refactor(settings): derive permission vocabulary from one declaration #2614
Description
refactor(settings): derive permission vocabulary from one declaration
Purpose and evidence
Adding all in PR #2363 (e656ff158a5c7641564106c73ea4e9b787244b9f) updates two PermissionTarget unions, a target array, parser comparisons, usage text and CLI membership. These independently maintained declarations make one vocabulary change span unrelated projections.
Evidence: contract declarations, public client type, CLI validation.
Required behavior
- In the existing settings contract, declare readonly collections for the current permission vocabularies and derive their union types. Preserve the current mobile/macOS subsets: a shared declaration must not widen what any surface accepts.
- Derive parser membership, public client permission types, CLI membership and permission-name usage fragments from those collections. Public client derivation must use type-only imports: do not introduce runtime loading of
settings.tsand itsAppErrordependency through the client type surface. Preserve existing exports, normalization, accepted values, errors and ordering of help text. - Keep platform-native permission mappings and device support checks in their existing owners. A name existing in the vocabulary does not imply platform support.
Illustrative declaration shape (names are not prescribed): type MobilePermissionTarget = (typeof MOBILE_PERMISSION_TARGETS)[number]; public client types may compose the existing mobile and macOS subsets.
Scope and exclusions
Own packages/contracts/src/settings.ts, client-settings.ts, src/commands/capture/settings.ts, and their direct tests/consumers. No new package, registry, schema framework, compatibility re-export, platform behavior change or Maestro support-policy redesign. #2544 already tracks moving the Maestro adapter; that move is unrelated.
Completion and validation
- Characterize the existing accepted/rejected names per surface, case/whitespace normalization and error/help strings before refactoring. Use fixed expected data, not expectations derived from the new collection.
- Both exported types retain their current assignability, including the macOS-only names where currently accepted.
- Replay a temporary vocabulary addition with no backend implementation: type/parser/CLI membership/help projections update from the owning collection without edits to parallel lists. Remove the temporary value before publication and record the before/after independently edited declarations.
- Existing settings/CLI tests and
pnpm check:affected --runpass. Followdocs/agents/testing.md; no device behavior changes are intended. - Delete superseded declarations; report the actual reduction. Stop and report if sharing forces acceptance widening or an import cycle.
Dependencies and readiness
Blocked by: #2363 landing. Re-audit its merged result before implementation; do not implement against pre-#2363 main or modify that PR independently. This is a follow-up, not a merge blocker. No matching implementation issue was found in the current tracker; #2410 concerns command-option declarations, not this repeated settings vocabulary.
Effort: S–M. Risk: low–medium (public type subsets and validation semantics).
Activity
refactor(settings): derive the permission vocabulary from one declara…
refactor(settings): derive the permission vocabulary from one declara…
thymikee commentedon Sep 16, 2026
Done on main via #2625 (merged 2026-09-15,
aba54b4cc6).Re-audited against the issue:
packages/contracts/src/settings.tsis the single declaration; parser membership, help fragments, the CLI membership set and the public client type derive from it, and the client derivation isimport typeonly (noAppErroron the client runtime path). Mobile/macOS subsets are preserved; nothing widened. Net production change is −7 lines with the parallel lists gone; the +386 lines are fixed-literal characterization tests.The "blocked by #2363" ordering was inverted in practice, but harmlessly: #2363's current head (
efe33f439b) is rebased past #2625 and addsallin exactly one place, which is the payoff this issue asked for. Its remaining conflict is CHANGELOG.md only.