diff --git a/specs/GH374/product.md b/specs/GH374/product.md new file mode 100644 index 00000000..31187f2b --- /dev/null +++ b/specs/GH374/product.md @@ -0,0 +1,88 @@ +# Product specification: option alias pairing convention + +## Summary + +Define one contributor convention for representing equivalent option spellings in hand-written command specs. Equivalent short, long, and alternate long spellings belong in one `name` array; genuinely different options remain separate entries. Document the convention in the repository's contributor-facing documentation without requiring a corpus-wide migration. + +## Problem + +The schema accepts an option `name` as either one string or an array of strings, but the repository does not explain when contributors should use each form. Both patterns are common in `command-signatures/json/`: 14,269 option entries use an array and 38,457 use a string. As a result, contributors and reviewers must infer whether a newly added long form should be grouped with an existing short form. + +The same ambiguity affects `exclusiveOn`. Existing specs variously reference one alias or every alias of a conflicting option. Although `exclusiveOn` is not enforced by the runtime today, inconsistent references make specs harder to review and would make future enforcement ambiguous. + +## Desired behavior + +### Representing option aliases + +An option entry represents one semantic option. Its `name` field follows these rules: + +1. Use a string when the target command and platform expose only one documented spelling. +2. Use one array for every documented spelling that is fully equivalent: the spellings have the same meaning, argument shape, repeatability, and other option metadata. Put short aliases first, followed by long aliases in the command's documented order. +3. Include multiple long synonyms in that same array when they are equivalent. For example, `["-q", "--quiet", "--silent"]` is one option. +4. Use separate option entries when spellings differ in semantics, accepted arguments, applicability, or metadata. Similar descriptions or names alone do not make options aliases. +5. Do not invent aliases. In particular, a BSD/macOS-oriented spec may legitimately retain a short-only string when the targeted command does not provide a GNU long form. A long form should be paired only after its support and intended platform coverage have been verified. + +Equivalent aliases must not be duplicated as separate entries merely to give each spelling its own `name` string. + +### Referencing aliases from `exclusiveOn` + +`exclusiveOn` contains literal option spellings, not logical option identifiers. Each entry must therefore list every alias a user could type for each conflicting semantic option. + +For two mutually exclusive paired options, the convention is: + +```json +[ + { + "name": ["-L", "--files-without-match"], + "exclusiveOn": ["-l", "--files-with-matches"] + }, + { + "name": ["-l", "--files-with-matches"], + "exclusiveOn": ["-L", "--files-without-match"] + } +] +``` + +When adding a verified long form to an existing short-only option: + +1. Replace the option's scalar `name` with an array containing the existing short form and the new long form. +2. Search the same command or subcommand for every `exclusiveOn` that references the existing short form and add the new long form beside it. +3. Review the changed option's own `exclusiveOn` list and ensure it includes every alias of each conflicting option. +4. Keep mutual relationships symmetric when the command describes the options as mutually exclusive. + +These updates are local to the option and its relationships. Contributors are not required to normalize unrelated options or files. + +### Documentation location + +The canonical convention will live in `README.md`, under the existing "JSON Command Signatures" section. This is the public, human-facing entry point that already explains where hand-written specs live, whereas `AGENTS.md` is architecture-oriented and `.agents/skills/add-command-spec/SKILL.md` is an execution workflow consumed primarily by agents. + +The implementation should add a short pointer from the option-authoring portion of `.agents/skills/add-command-spec/SKILL.md` to the canonical README section. This keeps agents on the same workflow without duplicating the rule. No new contributor file is warranted for one focused convention, and `AGENTS.md` should continue to point agents to the repository skills rather than duplicate authoring details. + +## User-visible impact + +This is contributor documentation. It makes new and edited specs more predictable to author and review, but it does not change completion rendering, parsing, or runtime option exclusivity. + +## Acceptance criteria + +- `README.md` states when to use a scalar `name`, when to use one alias array, and when similar spellings require separate entries. +- The documentation covers equivalent short/long aliases and multiple long synonyms, with concrete JSON examples. +- The documentation states that `exclusiveOn` must contain every literal alias of each conflicting option. +- The documentation gives the required update sequence for adding a long form to a short-only option, including affected peer `exclusiveOn` lists. +- The documentation explicitly says not to invent GNU long forms for BSD/macOS-oriented specs or other command variants that do not support them. +- Migration of existing specs is explicitly opportunistic; landing the convention does not require a corpus-wide rewrite. +- `.agents/skills/add-command-spec/SKILL.md` points to the canonical README convention without maintaining a second copy. +- The documentation notes that `exclusiveOn` is currently parsed but not enforced and does not promise runtime behavior. +- The implementation changes contributor documentation only; it does not modify command JSON, Rust source, generators, or generated specs. + +## Out of scope + +- Rewriting existing specs to conform to the convention. +- Adding missing aliases to any command, including the `du` change discussed in #372. +- Changing the JSON schema or runtime `Opt` representation. +- Implementing, validating, or otherwise changing runtime handling of `exclusiveOn`. +- Adding automated lint or formatting enforcement for the convention. + +## Open questions + +1. Should the runtime eventually carry `exclusiveOn` into `Opt` and enforce it? Recommendation: track this as a separate behavior change because it needs runtime semantics, compatibility analysis, and tests. +2. Should a future presubmit check enforce alias grouping and complete `exclusiveOn` references? Recommendation: first apply the written convention opportunistically and evaluate false positives across platform-specific and imported specs before adding automation. diff --git a/specs/GH374/tech.md b/specs/GH374/tech.md new file mode 100644 index 00000000..2d63fe5a --- /dev/null +++ b/specs/GH374/tech.md @@ -0,0 +1,57 @@ +# Technical specification: option alias pairing convention + +## Current implementation + +`CommandOption.name` accepts one string or many and deserializes both forms into `Vec` in `completion-metadata/src/fig_types.rs:167`. `CommandOption.exclusive_on` is independently deserialized as `Vec` in `completion-metadata/src/fig_types.rs:190`. + +When a `CommandOption` becomes a runtime `Opt`, every value in `name` is copied to `Opt.exact_string`, but `exclusive_on` is not copied (`completion-metadata/src/fig_types.rs:485`). Runtime short- and long-hand collections then classify each value in `Opt.exact_string` with `is_short_hand_flag` and `is_long_hand_flag` (`completion-metadata/src/signature.rs:94` and `completion-metadata/src/signature.rs:101`). + +The repository demonstrates both intended alias grouping and the undocumented inconsistency: + +- `command-signatures/json/head.json:10` groups equivalent short and long spellings; `command-signatures/json/head.json:30` includes the multi-long `-q`/`--quiet`/`--silent` option. +- `command-signatures/json/grep.json:101` references both aliases of a paired conflicting option in `exclusiveOn`. +- `command-signatures/json/du.json:89` defines `-d` as a short-only option and peer relationships refer only to `-d`. +- `command-signatures/json/df.json:12` combines aliases in one option while its exclusivity relationships use literal individual spellings. +- `README.md`, `AGENTS.md`, and `.agents/skills/add-command-spec/SKILL.md` do not currently define an alias-pairing convention. + +No runtime code reads `exclusive_on` after deserialization. The only Rust construction outside the type itself initializes it as empty in `command-signatures/src/powershell_autogenerator/to_fig_types.rs:141`. + +## Documentation changes + +Implementation is limited to two documentation edits: + +1. Add an "Option aliases and exclusivity" subsection to `README.md` beneath "JSON Command Signatures". It will be the canonical source and include: + - the scalar-versus-array decision rules; + - short/long and multi-long examples; + - the criteria for separate entries; + - the complete-alias rule for `exclusiveOn`; + - the steps for adding a long form to a short-only option; + - the platform-support caveat and opportunistic-migration policy; + - a note that `exclusiveOn` is currently unenforced. +2. Add a concise link in Step 2 of `.agents/skills/add-command-spec/SKILL.md` directing option authors to the README subsection before creating or editing options. + +`AGENTS.md` remains unchanged because it already directs agents editing command signatures to repository skills. A new contributor document would add another discovery path and split a convention that fits the README's existing hand-written-spec overview. + +## Data and API impact + +There are no schema, serialization, API, or runtime data changes. The documented array form is already accepted, and the convention does not alter how `Opt.exact_string` is populated or how flags are classified. + +## Edge cases + +- **Multiple aliases of one kind:** Multiple short aliases or multiple long aliases can share an array when all option behavior and metadata are identical. +- **Similar but non-equivalent options:** Keep them separate if any argument, semantic, availability, or metadata distinction exists. +- **Platform-specific commands:** Document only aliases verified for the spec's intended command variant. The convention does not make GNU aliases mandatory for BSD/macOS targets. +- **Mixed-platform specs:** If an alias is not valid across the spec's intended coverage, contributors must first make an explicit scope decision rather than infer an alias from another implementation. +- **Existing inconsistency:** Do not touch unrelated entries. Normalize an existing entry only when it is already being changed and the command's behavior is verified. +- **Mutual exclusion:** List all aliases on both sides when exclusivity is bidirectional; do not infer symmetry when the command's behavior is directional. +- **Currently unenforced metadata:** Treat complete `exclusiveOn` lists as authored metadata and future-compatible documentation, not as evidence that Warp currently suppresses or rejects conflicting options. + +## Validation strategy + +Because implementation is documentation-only: + +1. Review every JSON example for valid syntax and consistency with the stated rules. +2. Confirm README anchors and the skill's relative link resolve in the repository. +3. Run `git diff --check` to catch whitespace errors. +4. Confirm the implementation diff contains only `README.md` and `.agents/skills/add-command-spec/SKILL.md`. +5. No Rust build, command-spec formatting, generator verification, or UI test is required unless implementation expands beyond the approved documentation scope.