Skip to content

[Feature]: Add artifact, optional, and handoffs to the command manifest schema #4209

Description

@nicolehaugen

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 handoffs frontmatter-only and require consumers to parse it. Rejected because downstream consumers would duplicate parsing.
  • Derive artifact from the command file. Rejected because a command may produce multiple artifacts or none.
  • Bump schema_version without 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

  1. A wizard renders a Spec-Driven Development pipeline graph by walking handoffs edges without opening markdown files.
  2. A flow runner shows a skip action for commands with optional: true and refuses to auto-skip mandatory commands.
  3. An audit joins a command's artifact path to files in the repository.

Acceptance Criteria

  • Extension and preset command schemas accept optional artifact (string), optional (bool, default false), and handoffs (list of {to, when?, message?}).
  • The manifest loader merges command-file frontmatter handoffs when the manifest does not declare its own value.
  • Manifest-declared handoffs takes precedence over frontmatter.
  • Forge export continues to strip handoffs from exported frontmatter.
  • artifact is validated as repo-relative; handoffs[].to resolves to a known command; optional is 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 handoffs semantics 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

  1. github-actions commented on Aug 19, 2026

    @github-actions
    Contributor

    Feature assessment — artifact-optional-handoffs · Stage 1/5: Intake

    Idea Intake: Add artifact, optional, and handoffs to command manifest schema

    Idea (as captured)

    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: add optional artifact, optional, and handoffs fields to extension and preset command manifest entries. Parse command frontmatter during manifest loading and merge its handoffs into the command entry when the manifest does not declare them. Manifest-declared handoffs takes precedence.

    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

    • Raised by: @nicolehaugen
    • Trigger: Downstream tooling (wizard UIs, flow runners, pipeline visualizers) must re-parse markdown frontmatter to obtain handoffs semantics; handoffs is also stripped by the Forge integration export path, making it unavailable there entirely. The issue notes this blocks preset info --json / extension info --json.

    First-Glance Unknowns

    • [NEEDS CLARIFICATION: What is the exact schema shape for handoffs in the manifest — does it mirror the frontmatter shape (label, agent, prompt, send) or adopt a different shape (to, when, message)?]
    • [NEEDS CLARIFICATION: Should handoffs[].to be 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?]
    • [NEEDS CLARIFICATION: What is the backward-compatibility strategy for schema_version? The issue notes current validators use exact-match; a version bump would break existing manifests.]
    • [NEEDS CLARIFICATION: Should the frontmatter-merge path be scoped to handoffs only, or should artifact and optional also be mergeable from frontmatter?]

    Generated by 💡 Assess a Feature Request by Installing and Running Spec Kit for issue #4209 · 510 AIC · ⌖ 19.3 AIC · ⊞ 38.1K · ◷

  2. github-actions commented on Aug 19, 2026

    @github-actions
    Contributor

    Feature assessment — artifact-optional-handoffs · Stage 2/5: Research

    Idea Research: Add artifact, optional, and handoffs to command manifest schema

    • Slug: artifact-optional-handoffs
    • Created: 2026-08-19
    • Evidence confidence (overall): high

    Users & Demand

    • Extension authors and downstream tool builders are affected. The issue author (@nicolehaugen) identifies three concrete consumer types: wizard UIs, flow runners, and pipeline visualizers. — [source: issue [Feature]: Add artifact, optional, and handoffs to the command manifest schema #4209] (confidence: high, cited)
    • The blocking of preset info --json / extension info --json is 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)
    • Forge integration already strips handoffs from 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)
    • Cline and Junie integrations transform handoffs dot-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

    • handoffs already exists in all core command templates as frontmatter: templates/commands/plan.md, specify.md, constitution.md, tasks.md, clarify.md all carry handoffs: blocks with label, agent, prompt, send keys. — [source: codebase inspection] (confidence: high, cited)
    • The manifest currently validates only name, file, aliases for command entries (ExtensionManifest._validate(), lines 440–509 of src/specify_cli/extensions/__init__.py). No artifact, optional, or handoffs fields are present in the schema. — [source: codebase inspection] (confidence: high, cited)
    • The optional key already appears in hook entries (lines 4970, 5198, 5275 of extensions/__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() in src/specify_cli/_utils.py already provides path-safety validation for manifest file references and can be reused or adapted for artifact path validation. — [source: codebase inspection] (confidence: high, cited)
    • No prior rejected attempt to promote handoffs into the manifest was found in the visible codebase history. — [source: codebase inspection] (confidence: medium, assumption for non-visible history)

    Market & Context

    Data & Constraints

    • The manifest stores commands as plain Python dicts; unknown keys are not explicitly rejected (only specific keys are validated), so additive fields are unlikely to break loading of existing manifests. — [source: codebase inspection] (confidence: high, cited)
    • The _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[].to cross-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

    • Two handoffs shapes 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)
    • Strict schema_version exact-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)
    • Scope risk: acceptance criteria include handoffs[].to resolution, 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

    • [NEEDS CLARIFICATION: The two handoffs shapes (label/agent/prompt/send vs to/when/message) need a canonical decision before implementation.]
    • [NEEDS CLARIFICATION: Should artifact path validation reuse relative_extension_path_violation() or use a repo-root-relative validator?]
    • [NEEDS CLARIFICATION: Should handoffs[].to reference resolution be a warning or hard error when the target command is absent?]

    Sources

    • Issue [Feature]: Add artifact, optional, and handoffs to the command manifest schema #4209 (host: github.com, policy: allowlisted)
    • 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)

    Generated by 💡 Assess a Feature Request by Installing and Running Spec Kit for issue #4209 · 510 AIC · ⌖ 19.3 AIC · ⊞ 38.1K · ◷

  3. github-actions commented on Aug 19, 2026

    @github-actions
    Contributor

    Feature assessment — artifact-optional-handoffs · Stage 3/5: Problem

    Problem Definition: Add artifact, optional, and handoffs to command manifest schema

    • Slug: artifact-optional-handoffs
    • Created: 2026-08-19
    • Inputs used: intake.md | research.md

    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), and handoffs (follow-on commands) — forcing downstream consumers (wizard UIs, flow runners, pipeline visualizers) to re-parse markdown frontmatter and causing handoffs to be silently lost on the Forge export path.

    Affected Users & Stakeholders

    • Users: Extension authors — they must maintain handoffs in frontmatter only, with no guarantee it survives integration-specific export paths.
    • Users: Tooling builders (wizard UIs, flow runners, pipeline visualizers) — they must implement per-consumer frontmatter parsing to obtain handoffs, artifact, and optional semantics; they cannot rely on the manifest alone.
    • Stakeholders: Spec Kit maintainers — fragmented parsing logic across integrations (Forge strips, Cline/Junie transform) creates maintenance surface and divergence risk.
    • Stakeholders: @nicolehaugen — driving downstream tooling (preset info --json, extension info --json) blocked on manifest model completeness.

    Goals

    • The manifest schema exposes artifact, optional, and handoffs as optional fields on command entries, making them available to any manifest consumer without frontmatter re-parsing.
    • Frontmatter handoffs are merged into the in-memory manifest model as a fallback when the manifest does not declare them, so existing command templates retain their handoffs semantics without manifest changes.
    • Manifest-declared handoffs take precedence over frontmatter-derived ones.
    • Forge continues to strip handoffs from exported frontmatter (no behavior change on the Forge path).
    • The change is additive and backward-compatible; existing manifests load without error.
    • The schema-version decision is documented.

    Non-Goals

    • Migrating existing frontmatter handoffs to manifest declarations.
    • Changing Forge, Cline, or Junie integration behaviors beyond what is needed to support the new fields.
    • Defining the full runtime semantics of handoffs execution (flow runner behavior).
    • Building the wizard UI, flow runner, or pipeline visualizer that will consume these fields.

    Success Metrics

    • All three fields accessible via the Python manifest model for command entries. (baseline: none of these fields are in the model; qualitative)
    • Frontmatter handoffs present in in-memory model for all existing core command templates without manifest file changes. (baseline: handoffs only accessible by parsing frontmatter; qualitative)
    • Existing manifests (without the new fields) load without warnings or errors after the change. (regression metric)
    • Forge export tests continue passing. (regression metric)

    Cost of Inaction

    Downstream tooling building on extension info --json / preset info --json must implement independent frontmatter parsers, duplicating parsing logic and validation. The handoffs semantics are lost entirely on the Forge path. As more integrations add ad-hoc handoffs handling (as Cline and Junie already do), the divergence compounds and refactoring cost grows.

    Open Questions

    • [NEEDS CLARIFICATION: The two handoffs shapes (label/agent/prompt/send from frontmatter vs. the issue's proposed to/when/message for the manifest) need a defined mapping or a decision to use a single canonical shape.]
    • [NEEDS CLARIFICATION: Should handoffs[].to target validation be a warning or a hard error at manifest-load time when the referenced command is not installed?]
    • [NEEDS CLARIFICATION: Should artifact path validation reuse relative_extension_path_violation() or use a repo-root-relative validator?]

    Generated by 💡 Assess a Feature Request by Installing and Running Spec Kit for issue #4209 · 510 AIC · ⌖ 19.3 AIC · ⊞ 38.1K · ◷

  4. github-actions commented on Aug 19, 2026

    @github-actions
    Contributor

    Feature assessment — artifact-optional-handoffs · Stage 4/5: Concept

    Concept: Add artifact, optional, and handoffs to command manifest schema

    • Slug: artifact-optional-handoffs
    • Created: 2026-08-19
    • Recommended option: Option A — Additive manifest fields with frontmatter merge

    Options

    Option A — Additive manifest fields with frontmatter merge

    • Sketch: Add artifact (string), optional (bool, default false), and handoffs (list) as optional command-entry fields in ExtensionManifest._validate() and the equivalent preset command schema. During manifest loading, parse the command file's frontmatter and merge its handoffs block into the command entry when the manifest does not declare one; manifest-declared handoffs takes precedence. Adopt the frontmatter's existing label/agent/prompt/send shape as the canonical in-memory representation, since all current templates use it (the to/when/message shape from the issue is treated as a migration-target or alias to be resolved during spec). Validate artifact as a repo-relative path using relative_extension_path_violation() or a similar guard. Validate optional as boolean. Validate handoffs[].agent as a string with soft resolution (warn, not error, when the referenced command is not installed). Forge stripping behavior is unchanged.
    • Appetite: medium (weeks)
    • Trade-offs: Wins — consumer tooling gets a clean manifest API without frontmatter re-parsing; handoffs semantics survive the Forge path via the in-memory model; additive change keeps backward compatibility. Sacrifices — two handoffs shapes need a canonical decision before implementation; frontmatter parsing at manifest-load time adds an I/O step.
    • Rabbit holes: Deciding the canonical handoffs shape. 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

    • Sketch: Add the three fields to manifest schema validation but do NOT merge frontmatter handoffs automatically. Extension authors must explicitly add these fields to their extension.yml. No frontmatter reading at manifest-load time.
    • Appetite: small (days)
    • Trade-offs: Wins — simpler implementation; no dual-shape ambiguity; no added I/O. Sacrifices — existing core command templates and community extensions get no benefit without manual manifest updates; does not meet the acceptance criterion for frontmatter merge.
    • Rabbit holes: None on the implementation side, but this option does not satisfy the full requirement.

    Option C — Do nothing / document the workaround

    • Sketch: Document that consumers should parse frontmatter for handoffs and leave the manifest schema as-is.
    • Appetite: small (days)
    • Trade-offs: Wins — zero implementation risk. Sacrifices — does not unblock extension info --json, continues duplication, does not fix the Forge data-loss issue.
    • Rabbit holes: None, but this option does not address the core problem.

    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 handoffs shape 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)

    • Runtime flow execution semantics for handoffs
    • Migrating existing command template frontmatter handoffs to manifest YAML
    • Changes to Cline, Junie, or other integration-specific handoffs processing beyond what the manifest model update naturally subsumes
    • Building the wizard UI, flow runner, or pipeline visualizer

    Assumptions to Validate

    • Adding a frontmatter-read step at manifest-load time is acceptable in terms of performance for typical extension sets.
    • The existing label/agent/prompt/send handoffs shape can be canonicalized; the to/when/message shape from the issue body is a design sketch, not a hard requirement.
    • Soft validation (warn, not error) on handoffs[].agent reference resolution is acceptable.
    • relative_extension_path_violation() is a suitable validator for the artifact field, or a repo-root-relative variant can be added alongside it.

    Generated by 💡 Assess a Feature Request by Installing and Running Spec Kit for issue #4209 · 510 AIC · ⌖ 19.3 AIC · ⊞ 38.1K · ◷

  5. github-actions commented on Aug 19, 2026

    @github-actions
    Contributor

    Feature assessment — artifact-optional-handoffs · Stage 5/5: Decision — verdict go

    Decision: Add artifact, optional, and handoffs to command manifest schema

    • Slug: artifact-optional-handoffs
    • Decided: 2026-08-19
    • Verdict: go
    • Artifacts reviewed: intake.md | research.md | problem.md | concept.md

    Scorecard

    Criterion Rating Justification
    Problem validity strong Real gap confirmed by codebase inspection: handoffs, artifact, optional are absent from the manifest model; handoffs is silently stripped on the Forge path; Cline and Junie each independently re-parse it.
    Evidence strength adequate Codebase evidence is high-confidence and directly cited. User-demand signal comes from one issue with a clearly identified internal downstream blocker (extension info --json). Broader external user signal is limited but the internal need is unambiguous.
    Value vs. inaction strong Cost of inaction is concrete: duplicated frontmatter parsing in downstream tooling, silent handoffs data loss on Forge, and growing per-integration divergence. The fix is additive and backward-compatible.
    Feasibility / appetite strong Option A is a bounded medium-appetite change in two well-understood files. Path-validation utilities and the optional field pattern already exist. Main rabbit hole (canonical handoffs shape) is identified and resolvable at spec time.
    Strategic fit strong Directly improves the Spec Kit manifest model's machine-readability, unblocks tracked downstream work, and aligns with making extension metadata available without bespoke per-consumer parsing.
    Risk posture adequate Key risks identified — dual handoffs shapes (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 adequate threshold: 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 (canonical handoffs shape; artifact validator scope) are design decisions to resolve at the start of specification, not blockers to proceeding.

    If go — Handoff to /speckit.specify

    • Problem: The command manifest schema does not expose artifact, optional, or handoffs, forcing consumers to re-parse frontmatter and causing handoffs to be lost on the Forge export path.
    • Chosen approach: Option A — additive manifest fields (artifact, optional, handoffs) with frontmatter-handoffs merge at manifest-load time; manifest-declared values take precedence.
    • In scope: Adding and validating the three fields in ExtensionManifest._validate() (src/specify_cli/extensions/__init__.py) and the equivalent preset command schema (src/specify_cli/presets/__init__.py); frontmatter merge for handoffs during manifest loading; Forge stripping behavior preserved; backward compatibility for existing manifests (schema_version = "1.0" additive); schema-version decision record; documentation updates.
    • Out of scope: Runtime flow execution semantics; existing template frontmatter migration; Cline/Junie integration changes; wizard UI / flow runner / pipeline visualizer.
    • Success metrics: All three fields accessible via the Python manifest model; existing manifests load without error; Forge export tests pass unchanged; frontmatter handoffs present in in-memory model for existing core templates without manifest file changes.
    • Carried-forward open questions:
      • [NEEDS CLARIFICATION: Canonical handoffs shape — unify on existing frontmatter label/agent/prompt/send or adopt to/when/message? Document the decision.]
      • [NEEDS CLARIFICATION: handoffs[].to/agent resolution — warning or error when the referenced command is not installed?]
      • [NEEDS CLARIFICATION: artifact path validation — reuse relative_extension_path_violation() as-is or add a repo-root-relative variant?]
      • [NEEDS CLARIFICATION: Should artifact and optional also be mergeable from frontmatter, or is the frontmatter merge scoped to handoffs only?]

    Generated by 💡 Assess a Feature Request by Installing and Running Spec Kit for issue #4209 · 510 AIC · ⌖ 19.3 AIC · ⊞ 38.1K · ◷

  6. added
    feature-goFeature assessment verdict: go — ready to hand off to /speckit.specify
    on Aug 19, 2026
  7. assigned and unassigned on Aug 20, 2026
  8. mnriem commented on Sep 16, 2026

    @mnriem
    Collaborator

    The underlying tooling use case is worth clarifying, but the agent-independent command files remain available on the filesystem. Forge strips handoffs from 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 artifact and optional; 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).

  9. added
    author-needs-infoMissing detail needed to assess — supply requested info
    and removed
    feature-goFeature assessment verdict: go — ready to hand off to /speckit.specify
    on Sep 16, 2026
  10. added
    triage-can-waitVerdict: valid and in-scope but deprioritized; held behind the evidence gate
    on Oct 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    author-awaitingWaiting on author responseauthor-needs-infoMissing detail needed to assess — supply requested infoenhancementfeature-assessRun the Spec Kit idea-assessment pipeline on this feature requestfeature-needs-clarificationFeature assessment verdict: needs clarificationtriage-can-waitVerdict: valid and in-scope but deprioritized; held behind the evidence gate

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions