You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Both preset list and extension list emit human-formatted text only; there is no --json. Verified on main: preset_list() and preset_info() in presets/_commands.py take zero optional arguments (no flag anywhere in the file), same for extension _commands.py. Consumers (wizard UI, external tooling, CI checks) have to regex-scrape stdout. The speckit-wizard-canvas extension does exactly this in composition/preset-order.mjs::parsePresetListOutput, and the file's header comment explicitly notes:
"The CLI's specify preset list command prints installed presets in precedence order (first line = winner). That IS the precedence."
Beyond the missing --json, list_installed() in each registry omits fields consumers need:
Presets (presets/__init__.py:4049-4088) return template_count + tags only — no command_count, no script_count. The single template_count is misleading because presets contribute commands and scripts in separate manifest.commands / manifest.scripts lists.
author is dropped on the read path in both registries. The field exists in the manifest (and is even a filter parameter in the catalog search code path at extensions/__init__.py:4127), but neither list_installed() includes it in its return dict.
Neither surface exposes the structured source (see companion "Record structured provenance for installed presets and extensions" issue). The registry stores it; the read path drops it.
Proposed Solution
Add --json to both commands. The output is a JSON array of objects:
Preset objects omit hooks from provides (presets don't contribute hooks). The provides counts are integers, one per manifest kind. Ordering in the JSON array is the same precedence order the text output already uses (so parsePresetListOutput becomes JSON.parse(stdout) on the wizard side). Update list_installed() in both registries to compute the missing counts from the manifest fields landed by #4010 and to surface author.
Alternatives Considered
Emit YAML. Rejected — the whole point is to let the wizard drop js-yaml.
Emit only new fields via a separate list --extra flag. Rejected — every consumer would then need two calls.
Leave counts flat (command_count, hook_count) rather than grouping into provides. Rejected — mixes wire shape with the composition/stack view (filed separately as specify artifact), where the grouped shape is required.
Component
Specify CLI (initialization, commands)
AI Agent (if applicable)
Not applicable
Use Cases
speckit-wizard-canvas replaces composition/preset-order.mjs regex parser with JSON.parse(execFileSync("specify", ["preset", "list", "--json"])).
A CI job asserts "the speckit.constitution preset is installed and enabled at priority ≥ 100" with jq, no text parsing.
External catalog UIs query extension list --json to reconcile installed vs. remotely-available extensions by id + source.catalog.
Support triage: paste specify preset list --json output into a bug report for exact reproduction context.
Acceptance Criteria
specify preset list --json and specify extension list --json emit a JSON array to stdout with id, name, description, version, author, priority, enabled, source, provides for each entry.
Extension provides includes commands, templates, scripts, hooks integer counts. Preset provides includes commands, templates, scripts integer counts (no hooks).
source is the structured object from the companion provenance issue (or { "kind": "local" } for legacy records).
Array order matches the existing text-output precedence order (documented as authoritative in composition/preset-order.mjs).
Non-zero exit code and stderr JSON {"error": "..."} on failure so consumers can distinguish success from empty-array success.
Tests: JSON schema round-trip, count parity with the text output, missing-field defaults (author: null), legacy installed.json read.
Docs: preset list / extension list sections in the CLI reference show the --json shape.
Additional Context
Direct replacement for plugins/spec-kit-copilot-wizard/extensions/speckit-wizard-canvas/composition/preset-order.mjs in github/spec-kit-copilot. Depends on the companion "Record structured provenance for installed presets and extensions" issue.
Problem Statement
Both
preset listandextension listemit human-formatted text only; there is no--json. Verified onmain:preset_list()andpreset_info()inpresets/_commands.pytake zero optional arguments (no flag anywhere in the file), same for extension_commands.py. Consumers (wizard UI, external tooling, CI checks) have to regex-scrape stdout. Thespeckit-wizard-canvasextension does exactly this incomposition/preset-order.mjs::parsePresetListOutput, and the file's header comment explicitly notes:Beyond the missing
--json,list_installed()in each registry omits fields consumers need:extensions/__init__.py:3399-3427) returncommand_count+hook_countonly — no template or script counts, even thoughmanifest.templatesandmanifest.scriptsexist post-[Feature]: Allow extensions to declare templates and scripts in their manifest #4010.presets/__init__.py:4049-4088) returntemplate_count+tagsonly — nocommand_count, noscript_count. The singletemplate_countis misleading because presets contribute commands and scripts in separatemanifest.commands/manifest.scriptslists.authoris dropped on the read path in both registries. The field exists in the manifest (and is even a filter parameter in the catalog search code path atextensions/__init__.py:4127), but neitherlist_installed()includes it in its return dict.source(see companion "Record structured provenance for installed presets and extensions" issue). The registry stores it; the read path drops it.Proposed Solution
Add
--jsonto both commands. The output is a JSON array of objects:{ "id": "speckit.git", "name": "SpecKit Git", "description": "Git-flow helpers", "version": "1.2.0", "author": "…", "priority": 100, "enabled": true, "source": { "kind": "catalog", "catalog": "speckit-official" }, "provides": { "commands": 4, "templates": 2, "scripts": 1, "hooks": 3 } }Preset objects omit
hooksfromprovides(presets don't contribute hooks). Theprovidescounts are integers, one per manifest kind. Ordering in the JSON array is the same precedence order the text output already uses (soparsePresetListOutputbecomesJSON.parse(stdout)on the wizard side). Updatelist_installed()in both registries to compute the missing counts from the manifest fields landed by #4010 and to surfaceauthor.Alternatives Considered
js-yaml.list --extraflag. Rejected — every consumer would then need two calls.command_count,hook_count) rather than grouping intoprovides. Rejected — mixes wire shape with the composition/stack view (filed separately asspecify artifact), where the grouped shape is required.Component
Specify CLI (initialization, commands)
AI Agent (if applicable)
Not applicable
Use Cases
speckit-wizard-canvasreplacescomposition/preset-order.mjsregex parser withJSON.parse(execFileSync("specify", ["preset", "list", "--json"])).speckit.constitutionpreset is installed and enabled at priority ≥ 100" withjq, no text parsing.extension list --jsonto reconcile installed vs. remotely-available extensions byid+source.catalog.specify preset list --jsonoutput into a bug report for exact reproduction context.Acceptance Criteria
specify preset list --jsonandspecify extension list --jsonemit a JSON array to stdout withid,name,description,version,author,priority,enabled,source,providesfor each entry.providesincludescommands,templates,scripts,hooksinteger counts. Presetprovidesincludescommands,templates,scriptsinteger counts (nohooks).list_installed()in both registries is updated to compute the missing per-kind counts from the current manifest schema, including entries landed by [Feature]: Allow extensions to declare templates and scripts in their manifest #4010.sourceis the structured object from the companion provenance issue (or{ "kind": "local" }for legacy records).composition/preset-order.mjs).{"error": "..."}on failure so consumers can distinguish success from empty-array success.author: null), legacyinstalled.jsonread.preset list/extension listsections in the CLI reference show the--jsonshape.Additional Context
Direct replacement for
plugins/spec-kit-copilot-wizard/extensions/speckit-wizard-canvas/composition/preset-order.mjsingithub/spec-kit-copilot. Depends on the companion "Record structured provenance for installed presets and extensions" issue.