[Feature]: Add artifact, optional, and handoffs to the command manifest schema #4209
Description
Problem Statement
ExtensionCommand and preset command entries model fields such as type, name, file, description, and strategy, but do not expose artifact (the repo-relative output path a command produces), optional (whether a flow can skip it), or handoffs (declarative follow-on commands).
handoffs currently lives in command frontmatter and is stripped by several markdown integrations, including Forge. This forces downstream consumers such as wizard UIs, flow runners, and pipeline visualizers to re-parse markdown frontmatter and prevents these semantics from being consistently available through the command manifest model.
Proposed Solution
Add optional artifact, optional, and handoffs fields to extension and preset command manifest entries:
commands:
- name: speckit.plan
file: commands/speckit.plan.md
description: "..."
artifact: specs/{feature}/plan.md
optional: false
handoffs:
- to: speckit.tasks
when: "plan.status == 'done'"
message: "Ready to break plan into tasks"Parse command frontmatter during manifest loading and merge its handoffs into the command entry when the manifest does not declare them. If both sources provide handoffs, the manifest value takes precedence.
Keep handoffs in the in-memory model, while continuing to strip it on the Forge export path. Define how the existing frontmatter shape (label, agent, prompt, send) maps to or coexists with the manifest shape (to, when, message). In other words, add handoffs to the normalized in-memory command model and JSON output. Accept an explicit manifest declaration as an optional override, but derive it from command frontmatter when absent. Authors should not need to duplicate handoffs in both files.
Alternatives Considered
- Leave
handoffsfrontmatter-only and require consumers to parse it. Rejected because downstream consumers would duplicate parsing. - Derive
artifactfrom the command file. Rejected because a command may produce multiple artifacts or none. - Bump
schema_versionwithout a compatibility strategy. Current validators use exact-version matching, so a bump would reject existing manifests. Prefer an additive change under the current version unless compatibility policy is deliberately changed.
Component
Specify CLI (initialization, commands)
AI Agent (if applicable)
Not applicable
Use Cases
- A wizard renders a Spec-Driven Development pipeline graph by walking
handoffsedges without opening markdown files. - A flow runner shows a skip action for commands with
optional: trueand refuses to auto-skip mandatory commands. - An audit joins a command's
artifactpath to files in the repository.
Acceptance Criteria
- Extension and preset command schemas accept optional
artifact(string),optional(bool, defaultfalse), andhandoffs(list of{to, when?, message?}). - The manifest loader merges command-file frontmatter
handoffswhen the manifest does not declare its own value. - Manifest-declared
handoffstakes precedence over frontmatter. - Forge export continues to strip
handoffsfrom exported frontmatter. -
artifactis validated as repo-relative;handoffs[].toresolves to a known command;optionalis validated as a boolean. - The schema-version decision is recorded, with backward-compatible behavior for existing manifests.
- Valid and malformed manifest entries, frontmatter merge precedence, and Forge stripping are covered by the implementation verification.
- The manifest schema and
handoffssemantics are documented in the relevant existing documentation.
Additional Context
Impacts preset info --json / extension info --json, which are tracked separately.
Relevant implementation locations include src/specify_cli/extensions/__init__.py, src/specify_cli/presets/__init__.py, src/specify_cli/_utils.py::relative_extension_path_violation, and src/specify_cli/integrations/forge/__init__.py. Existing command frontmatter examples include templates/commands/plan.md.
Activity
github-actions commentedon Aug 19, 2026
Feature assessment — artifact-optional-handoffs · Stage 1/5: Intake
Idea Intake: Add artifact, optional, and handoffs to command manifest schema
Idea (as captured)
Restated
The command manifest schema currently omits three semantically meaningful fields (
artifact,optional,handoffs) that downstream consumers (wizard UIs, flow runners, visualizers) need without re-parsing markdown frontmatter. The proposal is to promote these fields into the manifest model and merge them from frontmatter during loading as a fallback.Origin & Context
handoffssemantics;handoffsis also stripped by the Forge integration export path, making it unavailable there entirely. The issue notes this blockspreset info --json/extension info --json.First-Glance Unknowns
handoffsin the manifest — does it mirror the frontmatter shape (label,agent,prompt,send) or adopt a different shape (to,when,message)?]handoffs[].tobe validated as resolving to a known command at manifest-load time, and if so, what happens when the target command is provided by a not-yet-installed extension?]schema_version? The issue notes current validators use exact-match; a version bump would break existing manifests.]handoffsonly, or shouldartifactandoptionalalso be mergeable from frontmatter?]github-actions commentedon Aug 19, 2026
Feature assessment — artifact-optional-handoffs · Stage 2/5: Research
Idea Research: Add artifact, optional, and handoffs to command manifest schema
Users & Demand
preset info --json/extension info --jsonis called out explicitly, indicating active work downstream that needs this data in the manifest. — [source: issue [Feature]: Add artifact, optional, and handoffs to the command manifest schema #4209] (confidence: high, cited)handoffsfrom exported frontmatter (src/specify_cli/integrations/forge/__init__.py, lines 5, 87, 192–203), confirming a real integration-level gap. — [source: codebase inspection] (confidence: high, cited)handoffsdot-notation agent references to hyphens during processing (cline/__init__.py:134,junie/__init__.py:129), showing fragmented per-integration parsing of frontmatter semantics. — [source: codebase inspection] (confidence: high, cited)Prior Art
handoffsalready exists in all core command templates as frontmatter:templates/commands/plan.md,specify.md,constitution.md,tasks.md,clarify.mdall carryhandoffs:blocks withlabel,agent,prompt,sendkeys. — [source: codebase inspection] (confidence: high, cited)name,file,aliasesfor command entries (ExtensionManifest._validate(), lines 440–509 ofsrc/specify_cli/extensions/__init__.py). Noartifact,optional, orhandoffsfields are present in the schema. — [source: codebase inspection] (confidence: high, cited)optionalkey already appears in hook entries (lines 4970, 5198, 5275 ofextensions/__init__.py), showing the concept is used in adjacent parts of the manifest. Adding it to command entries is consistent with existing patterns. — [source: codebase inspection] (confidence: high, cited)schema_version = "1.0"uses exact-match validation (if self.data["schema_version"] != self.SCHEMA_VERSION: raise). Adding new optional fields is additive under the current version and does not require a bump if existing manifests without these fields remain valid. — [source: codebase inspection + issue [Feature]: Add artifact, optional, and handoffs to the command manifest schema #4209] (confidence: high, cited)relative_extension_path_violation()insrc/specify_cli/_utils.pyalready provides path-safety validation for manifest file references and can be reused or adapted forartifactpath validation. — [source: codebase inspection] (confidence: high, cited)handoffsinto the manifest was found in the visible codebase history. — [source: codebase inspection] (confidence: medium, assumption for non-visible history)Market & Context
handoffsshape (label,agent,prompt,send) is idiosyncratic to Spec Kit. The proposed manifest shape (to,when,message) is different. Both coexisting without a defined mapping increases complexity. — [source: issue [Feature]: Add artifact, optional, and handoffs to the command manifest schema #4209 + codebase] (confidence: medium, cited)Data & Constraints
_validate_provided_artifacts()method already handles a similar additive-but-validated pattern for template/script entries — a direct precedent for extending validation. — [source: codebase inspection] (confidence: high, cited)handoffs[].tocross-reference resolution creates an install-order problem: the referenced command may be in an extension not yet installed. The issue acknowledges this without mandating hard failures. — [source: issue [Feature]: Add artifact, optional, and handoffs to the command manifest schema #4209] (confidence: high, cited)Evidence Against the Idea
handoffsshapes must coexist during any transition period. Defining their mapping or migration path adds design complexity that the issue leaves partially open. — [source: issue [Feature]: Add artifact, optional, and handoffs to the command manifest schema #4209 + codebase] (confidence: medium, cited)schema_versionexact-match validation could be a risk if any consumer does strict unknown-key rejection on command dicts — no such consumer was found in the current codebase scan. — [source: codebase inspection] (confidence: low, cited)handoffs[].toresolution, backward-compatibility policy recording, and docs updates — more than a simple schema field addition. — [source: issue [Feature]: Add artifact, optional, and handoffs to the command manifest schema #4209] (confidence: medium, cited)Gaps & Open Questions
handoffsshapes (label/agent/prompt/sendvsto/when/message) need a canonical decision before implementation.]artifactpath validation reuserelative_extension_path_violation()or use a repo-root-relative validator?]handoffs[].toreference resolution be a warning or hard error when the target command is absent?]Sources
src/specify_cli/extensions/__init__.py(codebase, local)src/specify_cli/presets/__init__.py(codebase, local)src/specify_cli/_utils.py(codebase, local)src/specify_cli/integrations/forge/__init__.py(codebase, local)src/specify_cli/integrations/cline/__init__.py(codebase, local)src/specify_cli/integrations/junie/__init__.py(codebase, local)templates/commands/plan.md,tasks.md,specify.md,constitution.md,clarify.md(codebase, local)github-actions commentedon Aug 19, 2026
Feature assessment — artifact-optional-handoffs · Stage 3/5: Problem
Problem Definition: Add artifact, optional, and handoffs to command manifest schema
Problem Statement
The Spec Kit command manifest schema does not expose three semantically meaningful fields —
artifact(what a command produces),optional(whether it can be skipped), andhandoffs(follow-on commands) — forcing downstream consumers (wizard UIs, flow runners, pipeline visualizers) to re-parse markdown frontmatter and causinghandoffsto be silently lost on the Forge export path.Affected Users & Stakeholders
handoffsin frontmatter only, with no guarantee it survives integration-specific export paths.handoffs,artifact, andoptionalsemantics; they cannot rely on the manifest alone.preset info --json,extension info --json) blocked on manifest model completeness.Goals
artifact,optional, andhandoffsas optional fields on command entries, making them available to any manifest consumer without frontmatter re-parsing.handoffsare merged into the in-memory manifest model as a fallback when the manifest does not declare them, so existing command templates retain theirhandoffssemantics without manifest changes.handoffstake precedence over frontmatter-derived ones.handoffsfrom exported frontmatter (no behavior change on the Forge path).Non-Goals
handoffsto manifest declarations.handoffsexecution (flow runner behavior).Success Metrics
handoffspresent in in-memory model for all existing core command templates without manifest file changes. (baseline:handoffsonly accessible by parsing frontmatter; qualitative)Cost of Inaction
Downstream tooling building on
extension info --json/preset info --jsonmust implement independent frontmatter parsers, duplicating parsing logic and validation. Thehandoffssemantics are lost entirely on the Forge path. As more integrations add ad-hochandoffshandling (as Cline and Junie already do), the divergence compounds and refactoring cost grows.Open Questions
handoffsshapes (label/agent/prompt/sendfrom frontmatter vs. the issue's proposedto/when/messagefor the manifest) need a defined mapping or a decision to use a single canonical shape.]handoffs[].totarget validation be a warning or a hard error at manifest-load time when the referenced command is not installed?]artifactpath validation reuserelative_extension_path_violation()or use a repo-root-relative validator?]github-actions commentedon Aug 19, 2026
Feature assessment — artifact-optional-handoffs · Stage 4/5: Concept
Concept: Add artifact, optional, and handoffs to command manifest schema
Options
Option A — Additive manifest fields with frontmatter merge
artifact(string),optional(bool, defaultfalse), andhandoffs(list) as optional command-entry fields inExtensionManifest._validate()and the equivalent preset command schema. During manifest loading, parse the command file's frontmatter and merge itshandoffsblock into the command entry when the manifest does not declare one; manifest-declaredhandoffstakes precedence. Adopt the frontmatter's existinglabel/agent/prompt/sendshape as the canonical in-memory representation, since all current templates use it (theto/when/messageshape from the issue is treated as a migration-target or alias to be resolved during spec). Validateartifactas a repo-relative path usingrelative_extension_path_violation()or a similar guard. Validateoptionalas boolean. Validatehandoffs[].agentas a string with soft resolution (warn, not error, when the referenced command is not installed). Forge stripping behavior is unchanged.handoffssemantics survive the Forge path via the in-memory model; additive change keeps backward compatibility. Sacrifices — twohandoffsshapes need a canonical decision before implementation; frontmatter parsing at manifest-load time adds an I/O step.handoffsshape. Load-time performance for large extension sets (tens to hundreds of commands) with the added frontmatter-read step.Option B — Manifest fields only, no frontmatter merge
handoffsautomatically. Extension authors must explicitly add these fields to theirextension.yml. No frontmatter reading at manifest-load time.Option C — Do nothing / document the workaround
handoffsand leave the manifest schema as-is.extension info --json, continues duplication, does not fix the Forge data-loss issue.Recommendation
Option A. It fully addresses the stated problem, is additive and backward-compatible, and the frontmatter-merge step is consistent with existing integration patterns in the codebase (multiple integrations already read frontmatter). The canonical
handoffsshape decision should be the first resolved question in the specification phase to avoid mid-implementation redesign. Option B is a viable fallback if frontmatter-merge load-time overhead is found to be unacceptable — but this should be measured, not assumed.Out of Scope (for the recommended option)
handoffshandoffsto manifest YAMLhandoffsprocessing beyond what the manifest model update naturally subsumesAssumptions to Validate
label/agent/prompt/sendhandoffsshape can be canonicalized; theto/when/messageshape from the issue body is a design sketch, not a hard requirement.handoffs[].agentreference resolution is acceptable.relative_extension_path_violation()is a suitable validator for theartifactfield, or a repo-root-relative variant can be added alongside it.github-actions commentedon Aug 19, 2026
Feature assessment — artifact-optional-handoffs · Stage 5/5: Decision — verdict go
Decision: Add artifact, optional, and handoffs to command manifest schema
Scorecard
handoffs,artifact,optionalare absent from the manifest model;handoffsis silently stripped on the Forge path; Cline and Junie each independently re-parse it.extension info --json). Broader external user signal is limited but the internal need is unambiguous.handoffsdata loss on Forge, and growing per-integration divergence. The fix is additive and backward-compatible.optionalfield pattern already exist. Main rabbit hole (canonicalhandoffsshape) is identified and resolvable at spec time.handoffsshapes (manageable by deciding canonical shape first), load-time I/O for frontmatter merge (acceptable for typical sizes; should be measured). No unmitigated blocking risk found.Verdict & Rationale
Go. The problem is real and well-evidenced from the codebase. A shaped, bounded option exists (Option A), the implementation path is clear in two known files, and the change is additive under the current schema version. Evidence strength meets the
adequatethreshold: the primary signal is internal codebase need and an explicit downstream blocker, which is sufficient for a schema improvement of this scope. The two principal open questions (canonicalhandoffsshape;artifactvalidator scope) are design decisions to resolve at the start of specification, not blockers to proceeding.If go — Handoff to
/speckit.specifyartifact,optional, orhandoffs, forcing consumers to re-parse frontmatter and causinghandoffsto be lost on the Forge export path.artifact,optional,handoffs) with frontmatter-handoffsmerge at manifest-load time; manifest-declared values take precedence.ExtensionManifest._validate()(src/specify_cli/extensions/__init__.py) and the equivalent preset command schema (src/specify_cli/presets/__init__.py); frontmatter merge forhandoffsduring manifest loading; Forge stripping behavior preserved; backward compatibility for existing manifests (schema_version = "1.0"additive); schema-version decision record; documentation updates.handoffspresent in in-memory model for existing core templates without manifest file changes.handoffsshape — unify on existing frontmatterlabel/agent/prompt/sendor adoptto/when/message? Document the decision.]handoffs[].to/agentresolution — warning or error when the referenced command is not installed?]artifactpath validation — reuserelative_extension_path_violation()as-is or add a repo-root-relative variant?]artifactandoptionalalso be mergeable from frontmatter, or is the frontmatter merge scoped tohandoffsonly?]mnriem commentedon Sep 16, 2026
The underlying tooling use case is worth clarifying, but the agent-independent command files remain available on the filesystem. Forge strips
handoffsfrom its exported representation; it does not remove that metadata from the original command.Could you show a concrete consumer requirement that cannot be met by resolving the effective command through the preset/extension stack and reading its existing metadata? Spec Kit already has shared frontmatter parsing, so consumers need not each implement their own parser.
A normalized metadata API may still be useful, but that is different from needing new manifest declarations and another precedence rule. Please distinguish that convenience from information that is genuinely unavailable.
Please also describe the separate requirements for
artifactandoptional; their inclusion is not justified by how an integration exports existing handoffs.Let’s establish those gaps before agreeing on a schema change, while preserving the intentional integration-specific export behavior.
Drafted for @mnriem with assistance from GitHub Copilot (model: GPT-6 Astra; interactive comment drafting).
claude: converge stops when a pass adds no task above LOW (#141)