Skip to content

refactor(cli): derive the common flag readers from the common-field table - #2292

Merged
thymikee merged 2 commits into
mainfrom
claude/audit-common-readers-derive
Sep 5, 2026
Merged

refactor(cli): derive the common flag readers from the common-field table#2292
thymikee merged 2 commits into
mainfrom
claude/audit-common-readers-derive

Conversation

@thymikee

@thymikee thymikee commented Sep 5, 2026

Copy link
Copy Markdown
Member

Summary

commonInputFromFlags and selectionOptionsFromFlags in
src/commands/cli-grammar/common.ts each hand-restated the common CLI
input keys as object literals, with no structural link to the
common-field table in commands/common-input-fields.ts that already
owns each key's schema, reader, client-options name, and audience.
Before, adding or reclassifying a common key meant remembering to also
touch both literals by hand — the exact failure mode --no-record
suffered in #1304/#1305. After, CommonInputFieldSpec carries a
flagKey/flagIn column, flagKey is required and typed against
CliFlags wherever flagIn is set (closing a gap where a row could
bind to a non-existent flag like cwd and silently read undefined
forever), and a new commonFlagProjection(flags, projection) helper
walks the table once for both readers.

Validation

Tested commit: 8d4cb08pnpm check:affected --run green locally (format, lint, typecheck, layering, fallow, build, vitest-related: 1656 tests).

  • The characterization test in common.test.ts ran green against the
    old literals and again unmodified against the table-derived version
    — deep-equal (key order changed, nothing consumes it). Extended the
    fixture so a row wrongly gaining flagIn shows an extra value
    instead of being compacted away; confirmed by temporarily adding
    flagIn to daemonBaseUrl (test failed) and flagKey: 'cwd' (tsc
    rejected it), then reverting both.
  • pnpm vitest run --project unit-core src/commands — 575 tests green.
  • pnpm check:layering — clean; the cli-grammar/common.ts
    commands/common-input-fields.ts import is intra-commands-zone.

Review notes

  • Deferred: selectionOptionsFromFlags still casts to SelectionOptions.
    Removing it needs common-input-fields.ts to import from
    cli-grammar/types.ts, reversing the one-way dependency; not worth
    it for a cast the characterization test already pins.

…able

commonInputFromFlags and selectionOptionsFromFlags in
src/commands/cli-grammar/common.ts each hand-restated the common input
key list as object literals. A key added to the common-field table in
commands/common-input-fields.ts (the schema/read/clientKey/audience
source of truth) had no structural link to either flag reader, so
keeping a new key flowing through the CLI depended on remembering to
touch both literals by hand (the failure mode #1304/#1305 hit for
--no-record).

Add a flagKey/flagIn column to CommonInputFieldSpec: flagKey names the
CliFlags property when its spelling differs from the row (only
deviceTarget, which reads flags.target), and flagIn lists which of the
two flag-derived projections ('input', 'selection') the row joins.
commonFlagProjection(flags, projection) walks the table once and
reuses the existing clientKey renaming (deviceTarget -> target) for
the 'selection' projection, matching commonToClientOptions's existing
convention. commonInputFromFlags and selectionOptionsFromFlags become
thin wrappers over that projection; COMMON_COMMAND_SUPPORTED_FLAG_KEYS
in flag-groups.ts is untouched, per its own documented reason for
staying separate.

Added src/commands/cli-grammar/common.test.ts as a characterization
test before touching the implementation: it feeds a CliFlags fixture
with every common flag set, and one with none set, and asserts the
literal objects both functions return. It passed unmodified against
both the old hand-written implementation and the new table-derived
one, proving the projections are byte-identical.

Validation: pnpm vitest run --project unit-core src/commands (575
tests, all green); pnpm check:quick (lint + typecheck) clean;
pnpm check:layering clean (cli-grammar/common.ts importing
commands/common-input-fields.ts is an intra-commands-zone import, not
core/daemon reaching into commands, so R2 commands-floor does not
apply).
Reviewer findings on the common-flag-reader refactor (9074367):

- P2: commonFlagProjection cast flags to Record<string, unknown> and
  fell back to `field.flagKey ?? key`, so a row could declare
  `flagIn` with a key that is not a CliFlags property at all (cwd,
  debug) and compile cleanly while reading undefined forever.
  CommonInputFieldSpec now requires `flagKey: keyof CliFlags`
  whenever a row declares `flagIn`; the cast and fallback are gone
  and commonFlagProjection reads `flags[field.flagKey]` directly.
  Verified red/green: temporarily adding `flagKey: 'cwd'` made tsc
  reject the table; reverted after confirming.

- P2: comments in common.ts and common-input-fields.ts claimed the
  table made a dropped common key "impossible" / that flagIn "rides
  structurally". A new common row that omits flagIn still silently
  joins neither projection, uncaught by any compiler check -- the
  flagKey fix narrows the failure mode, it doesn't close it. Reworded
  both comments to say what the table actually guarantees.

- P3: common.test.ts's ALL_COMMON_FLAGS fixture left daemonBaseUrl,
  daemonAuthToken, tenant, runId, and leaseId unset, so a row wrongly
  gaining `flagIn: ['input']` for one of them would still pass --
  compactRecord drops the unset value either way. Added
  NON_PROJECTED_COMMON_FLAGS with concrete values for those keys so
  such a row now surfaces as an extra key. Verified red/green:
  temporarily adding `flagIn: ['input']` to daemonBaseUrl failed the
  test; reverted after confirming.

- P3: flag-groups.ts's comment said the common-input-fields table
  declares only envFlagKeys; it now also declares flagKey/flagIn.
  Amended to name both columns.

Deferred one P3 (selectionOptionsFromFlags's cast to SelectionOptions)
with a note in .tmp/common-readers-pr-body.md -- fixing it would
import cli-grammar/types.ts back into common-input-fields.ts, reversing
the documented one-way dependency for a cast the characterization test
already pins.

No layering, fallow, or gate-manifest surface touched, so no separate
chore(gates) commit.

Checks: pnpm vitest run --project unit-core src/commands (575 tests,
green) and pnpm check:quick (lint + typecheck), both clean.
@github-actions

github-actions Bot commented Sep 5, 2026

Copy link
Copy Markdown

Size Report

Metric Base Current Diff
JS raw 2.61 MB 2.61 MB +230 B
JS gzip 878.8 kB 878.9 kB +110 B
npm bundled raw 2.61 MB 2.61 MB +230 B
npm bundled gzip 878.8 kB 878.9 kB +110 B
npm tarball 1.04 MB 1.04 MB +91 B
npm unpacked 3.52 MB 3.52 MB +230 B
npm clean-installed 3.52 MB 3.52 MB +230 B

npm unpacked components

Component Base Current Diff
JS / dist source 2.77 MB 2.77 MB +230 B
Apple runner source/project 544.4 kB 544.4 kB 0 B
Apple snapshot presentation source 33.8 kB 33.8 kB 0 B
Apple Simulator snapshot bridge source 30.5 kB 30.5 kB 0 B
macOS helper source 54.8 kB 54.8 kB 0 B
Android helper artifacts 43.3 kB 43.3 kB 0 B
Other package files 46.7 kB 46.7 kB 0 B

Startup median (7 runs, lower is better):

Scenario Base Current Diff
CLI --version 30.8 ms 31.5 ms +0.6 ms
CLI --help 81.9 ms 80.7 ms -1.1 ms

Top changed chunks:

Chunk Raw diff Gzip diff
dist/src/registry.js +230 B +113 B
dist/src/cli-help.js 0 B -1 B

Top changed packed files

Packed file Base Current Diff
dist/src/registry.js 171.8 kB 172.0 kB +230 B

@thymikee

thymikee commented Sep 5, 2026

Copy link
Copy Markdown
Member Author

Reviewed exact head 8d4cb0892948e3ef633caf9da01551e083908f21: clean. The common input table remains command/CLI-owned; flagKey: keyof CliFlags plus the discriminated flagIn mapping prevent invalid bindings while deriving both common-flag projections from one source. Characterization covers projected and deliberately unprojected flags and preserves the prior shapes. All applicable CI checks are green; no device evidence is owed for this refactor.

@thymikee thymikee added the ready-for-human Valid work that needs human implementation, judgment, or maintainer merge label Sep 5, 2026
@thymikee
thymikee merged commit d23346c into main Sep 5, 2026
18 checks passed
@thymikee
thymikee deleted the claude/audit-common-readers-derive branch September 5, 2026 17:05
@github-actions

github-actions Bot commented Sep 5, 2026

Copy link
Copy Markdown
PR Preview Action v1.8.1
Preview removed because the pull request was closed.
2026-09-05 17:05 UTC

thymikee added a commit that referenced this pull request Sep 5, 2026
* origin/main:
  perf: bundle runtime dependencies and report full install size (#2310)
  ci: avoid unrelated Apple runner cache invalidation (#2303)
  fix(web): preserve the backend ref so snapshot refs match actionable refs (#2283)
  test(daemon): session-open-url-prewarm through the request seam (#2304)
  test(daemon): session-devices-batch-runtime through the request seam (#2305)
  chore(gates): layering baselines ratchet against merge-base (#2299)
  test(daemon): one typed conformance helper for the daemon runtime suites (#2298)
  chore(layering): derive the contracts export inventory from package.json (#2297)
  perf: bundle tar-stream to reduce install footprint (#2286)
  docs: simplify agent context and resolve conflicting guidance (#2287)
  refactor(cli): let help resolve command aliases itself and retire R12 (#2293)
  refactor(commands): retire the navigation-only type projection (#2294)
  feat(runtime): route managed leases through contained transports (#2285)
  refactor(contracts): build unavailable runtime facts once (#2291)
  refactor(cli): derive the common flag readers from the common-field table (#2292)
  feat(daemon): add managed allocation operation journal (#2284)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-for-human Valid work that needs human implementation, judgment, or maintainer merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant