mirror of
https://github.com/Fission-AI/OpenSpec.git
synced 2026-09-14 20:16:53 +08:00
6.8 KiB
6.8 KiB
Implementation Tasks — Add Interactive Show Command
Goals
- Add a top-level
showcommand with intelligent selection and type detection. - Add interactive selection to
change showandspec showwhen no ID is provided. - Preserve raw-first output behavior and existing JSON formats/filters.
- Respect
--no-interactiveandOPEN_SPEC_INTERACTIVE=0consistently.
1) CLI wiring
- In
src/cli/index.tsadd a top-level command:program.command('show [item-name]')- Options:
--json--type <type>where<type>ischange|spec--no-interactive- Allow passing-through type-specific flags using
.allowUnknownOption(true)so the top-level can forward flags to the underlying type handler.
- Action: instantiate
new ShowCommand().execute(itemName, options).
- Options:
- Update
change showsubcommand to accept--no-interactiveand pass it toChangeCommand.show(...). - Change
spec showsubcommand to accept optional ID (show [spec-id]), add--no-interactive, and pass to spec show implementation.
Acceptance:
openspec showexists and prints a helpful hint in non-interactive contexts when no args.- Unknown flags for other types do not crash parsing; they are warned/ignored appropriately.
2) New module: src/commands/show.ts
- Create
ShowCommandwith:execute(itemName?: string, options?: { json?: boolean; type?: string; noInteractive?: boolean; [k: string]: any })- Interactive path when
!itemNameand interactive is enabled:- Prompt: "What would you like to show?" →
changeorspec. - Load available IDs for the chosen type and prompt selection.
- Delegate to type-specific show implementation.
- Prompt: "What would you like to show?" →
- Non-interactive path when
!itemName:- Print hint with examples:
openspec show <item>openspec change showopenspec spec show
- Exit with code 1.
- Print hint with examples:
- Direct item path when
itemNameis provided:- Type override via
--typetakes precedence. - Otherwise detect using
getActiveChangeIds()andgetSpecIds(). - If ambiguous and no override: print error + suggestion to pass
--typeor use subcommands; exit code 1. - If unknown: print not-found with nearest-match suggestions; exit code 1.
- On success: delegate to type-specific show.
- Type override via
- Flag scoping and pass-through:
- Common:
--json→ forwarded to both types. - Change-only:
--deltas-only,--requirements-only(deprecated alias). - Spec-only:
--requirements,--no-scenarios,-r/--requirement. - Warn and ignore irrelevant flags for the resolved type.
- Common:
Acceptance:
openspec show <change-id> --json --deltas-onlymatchesopenspec change show <id> --json --deltas-onlyoutput.openspec show <spec-id> --json --requirementsmatchesopenspec spec show <id> --json --requirementsoutput.- Ambiguity and not-found behaviors match the
cli-showspec.
3) Refactor spec show into reusable API
- In
src/commands/spec.ts, extract show logic into an exportedSpecCommandwithshow(specId?: string, options?: { json?: boolean; requirements?: boolean; scenarios?: boolean; requirement?: string; noInteractive?: boolean }).- Reuse current helpers (
parseSpecFromFile,filterSpec, raw-first printing). - Keep
registerSpecCommandbut delegate tonew SpecCommand().show(...).
- Reuse current helpers (
- Update CLI spec show subcommand to optional arg and interactive behavior (see section 4).
Acceptance:
- Existing
spec showtests continue to pass. - New
SpecCommand.showcan be called fromShowCommand.
4) Backwards-compatible interactive in subcommands
src/commands/change.ts→ extendshow(changeName?: string, options?: { json?: boolean; requirementsOnly?: boolean; deltasOnly?: boolean; noInteractive?: boolean }):- When
!changeNameand interactive enabled: prompt fromgetActiveChangeIds()and show the selected change. - Non-interactive fallback: keep current behavior (print available IDs +
openspec change listhint, setprocess.exitCode = 1).
- When
src/commands/spec.ts→SpecCommand.showas above:- When
!specIdand interactive enabled: prompt fromgetSpecIds()and show the selected spec. - Non-interactive fallback: print the same error as existing behavior for missing
<spec-id>and set non-zero exit code.
- When
Acceptance:
openspec change showin non-interactive prints list hint and exits non-zero.openspec spec showin non-interactive prints missing-arg error and exits non-zero.
5) Shared utilities
- Extract
nearestMatchesandlevenshteinfromsrc/commands/validate.tsintosrc/utils/match.ts(exported helpers). - Update
ValidateCommandand newShowCommandto import fromutils/match.
Acceptance:
- Build succeeds with shared helpers and no duplication.
6) Hints, warnings, and messages
- Top-level
showhint (non-interactive no-arg):- Lines include:
openspec show <item>,openspec change show,openspec spec show, and "Or run in an interactive terminal.".
- Lines include:
- Ambiguity message suggests
--type change|specand the subcommands. - Not-found suggests nearest matches (up to 5).
- Irrelevant flag warnings for the resolved type (printed to stderr, no crash).
Acceptance:
- Messages match the
cli-showspec wording intent and style used elsewhere.
7) Tests
Add tests mirroring existing patterns (non-TTY simulation via OPEN_SPEC_INTERACTIVE=0).
test/commands/show.test.ts- Non-interactive, no arg → prints hint and exits non-zero.
- Direct item detection for change and for spec.
- Ambiguity case when both exist → error and suggestion for
--type. - Not-found case → nearest-match suggestions.
- Pass-through flags: change
--json --deltas-only, spec--json --requirements.
test/commands/change.interactive-show.test.ts(non-interactive fallback)- Ensure
openspec change showwithout args prints available IDs + list hint and non-zero exit.
- Ensure
test/commands/spec.interactive-show.test.ts(non-interactive fallback)- Ensure
openspec spec showwithout args prints missing-arg error and non-zero exit.
- Ensure
Acceptance:
- All new tests pass after build; no regressions in existing tests.
8) Documentation (optional but recommended)
- Update
openspec/README.mdusage examples to include the newshowcommand with type detection and flags.
9) Non-functional checks
- Run
pnpm buildand all tests (pnpm test). - Ensure no linter/type errors and messages are consistent with existing style.
Notes on consistency
- Follow raw-first behavior for text output: passthrough file content with no formatting, mirroring current
change showandspec show. - Reuse
isInteractiveanditem-discoveryhelpers for consistent prompting behavior. - Keep JSON output shapes identical to current
ChangeCommand.showandspec showoutputs.