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
Spec Kit identifies contributed commands, templates, scripts, and hooks primarily by name. Names can collide across artifact kinds and source layers, and a name alone cannot reliably link a resolved artifact-stack layer to the exact manifest contribution that supplied it. Consumers such as preset info --json, extension info --json, and specify artifact need stable contribution identifiers and a join key that works across reinstalls and machines.
Proposed Solution
Introduce computed, opaque id fields for every command, template, script, and hook returned by public manifest/info APIs, plus a lookupId field on every resolved artifact-stack layer.\n\nFor named artifacts, derive IDs using:\n\ntext\n{layer}:{sourceId}:{kind}:{name}\n\n\nUse core, preset, or extension for layer; _ for the core source ID; and the preset or extension manifest ID for other sources. Use command, template, script, or hook for kind. Examples include preset:speckit.core:command:speckit.plan, extension:speckit.git:template:pr-body, and core:_:command:speckit.constitution.\n\nFor hooks, use {eventName}:{command} as the name component. If duplicate event/command hook entries are valid, add an appropriate stable discriminator or reject duplicates; do not use array position.\n\nCompute IDs at read, serialization, or resolution time rather than persisting them in authored or installed manifests. lookupId must exactly match the originating contribution's id. Preserve existing name-based behavior and document IDs as opaque strings.
Alternatives Considered
Install-time UUIDs are unsuitable because they differ across machines and reinstalls. Existing names are insufficient because they collide across sources and kinds. Content hashes are unsuitable because IDs would change whenever artifact content is edited. Array indexes are unsuitable for hooks because reordering entries would change their IDs.\n\nDo not use the existing integration manifest as the ID source; it tracks installed file hashes and paths rather than manifest contribution identity.
Component
Specify CLI (initialization, commands)
AI Agent (if applicable)
No response
Use Cases
A wizard can read an artifact stack and follow each layer's lookupId to the full contribution detail without re-parsing manifests.\n2. Developers on different machines can use identical IDs when reporting or diagnosing a contribution.\n3. Tooling can hash or cache resolved compositions using sets of lookupId values.\n4. Future JSON output for preset info, extension info, and specify artifact can expose consistent cross-references.
Acceptance Criteria
Document the layer:sourceId:kind:name grammar and lookupId relationship in extensions/EXTENSION-API-REFERENCE.md and the preset API/manifest reference.\n- [ ] Public manifest/info representations expose computed id values for commands, templates, scripts, and hooks.\n- [ ] Hook IDs are deterministic and collision-free without install paths or list indexes.\n- [ ] Resolved artifact-stack layers expose lookupId equal to the corresponding contribution's id.\n- [ ] Identical manifest coordinates produce identical IDs across processes, machines, project locations, and reinstalls.\n- [ ] IDs do not depend on artifact contents, timestamps, manifest hashes, archive paths, or installation directories.\n- [ ] Existing name fields and name-based resolution remain unchanged.\n- [ ] Tests cover every source layer and artifact kind, hook uniqueness, resolver repeatability, lookup round-trips, and backward compatibility.
Additional Context
This request defines the ID contract only. Adding the JSON output surfaces themselves for preset info --json, extension info --json, or specify artifact is out of scope and will be handled separately. Changing precedence, resolution, installation, or uninstall behavior is also out of scope. Relevant implementation areas include the extension manifest schema and validation and PresetResolver composition handling. IDs must not expose install paths, secrets, or connection strings.
Problem Statement
Spec Kit identifies contributed commands, templates, scripts, and hooks primarily by
name. Names can collide across artifact kinds and source layers, and a name alone cannot reliably link a resolved artifact-stack layer to the exact manifest contribution that supplied it. Consumers such aspreset info --json,extension info --json, andspecify artifactneed stable contribution identifiers and a join key that works across reinstalls and machines.Proposed Solution
Introduce computed, opaque
idfields for every command, template, script, and hook returned by public manifest/info APIs, plus alookupIdfield on every resolved artifact-stack layer.\n\nFor named artifacts, derive IDs using:\n\ntext\n{layer}:{sourceId}:{kind}:{name}\n\n\nUsecore,preset, orextensionforlayer;_for the core source ID; and the preset or extension manifest ID for other sources. Usecommand,template,script, orhookforkind. Examples includepreset:speckit.core:command:speckit.plan,extension:speckit.git:template:pr-body, andcore:_:command:speckit.constitution.\n\nFor hooks, use{eventName}:{command}as the name component. If duplicate event/command hook entries are valid, add an appropriate stable discriminator or reject duplicates; do not use array position.\n\nCompute IDs at read, serialization, or resolution time rather than persisting them in authored or installed manifests.lookupIdmust exactly match the originating contribution'sid. Preserve existing name-based behavior and document IDs as opaque strings.Alternatives Considered
Install-time UUIDs are unsuitable because they differ across machines and reinstalls. Existing names are insufficient because they collide across sources and kinds. Content hashes are unsuitable because IDs would change whenever artifact content is edited. Array indexes are unsuitable for hooks because reordering entries would change their IDs.\n\nDo not use the existing integration manifest as the ID source; it tracks installed file hashes and paths rather than manifest contribution identity.
Component
Specify CLI (initialization, commands)
AI Agent (if applicable)
No response
Use Cases
lookupIdto the full contribution detail without re-parsing manifests.\n2. Developers on different machines can use identical IDs when reporting or diagnosing a contribution.\n3. Tooling can hash or cache resolved compositions using sets oflookupIdvalues.\n4. Future JSON output forpreset info,extension info, andspecify artifactcan expose consistent cross-references.Acceptance Criteria
layer:sourceId:kind:namegrammar andlookupIdrelationship inextensions/EXTENSION-API-REFERENCE.mdand the preset API/manifest reference.\n- [ ] Public manifest/info representations expose computedidvalues for commands, templates, scripts, and hooks.\n- [ ] Hook IDs are deterministic and collision-free without install paths or list indexes.\n- [ ] Resolved artifact-stack layers exposelookupIdequal to the corresponding contribution'sid.\n- [ ] Identical manifest coordinates produce identical IDs across processes, machines, project locations, and reinstalls.\n- [ ] IDs do not depend on artifact contents, timestamps, manifest hashes, archive paths, or installation directories.\n- [ ] Existingnamefields and name-based resolution remain unchanged.\n- [ ] Tests cover every source layer and artifact kind, hook uniqueness, resolver repeatability, lookup round-trips, and backward compatibility.Additional Context
This request defines the ID contract only. Adding the JSON output surfaces themselves for
preset info --json,extension info --json, orspecify artifactis out of scope and will be handled separately. Changing precedence, resolution, installation, or uninstall behavior is also out of scope. Relevant implementation areas include the extension manifest schema and validation andPresetResolvercomposition handling. IDs must not expose install paths, secrets, or connection strings.