Contracts

creation-artifact-key.md

Contract — Mission-Creation artifact_kind (Q1)

Surface: resolve_configured_template(artifact_kind, project_dir, resolved_mission_type) (src/specify_cli/runtime/resolver.py:346).

Contract (code-verified, DD-03):

  • At mission create, the runtime requests the literal artifact_kind="spec" for every mission type (src/specify_cli/core/mission_creation.py:351-355, hardcoded, generic).
  • At /plan-setup, the runtime requests the literal "plan" (src/specify_cli/cli/commands/agent/mission_setup_plan.py:453-457).
  • There is no per-type/per-step derivation and no alias layer on the content-template side (decision.py:_ALIASES maps state→command-template via resolve_command, a different surface).

Resolution chain: resolve_configured_template("spec")resolved_mission_type.template_set.get("spec") → filename → 5-tier resolve_template. template_set is keyed on MissionStepTemplateRef.artifact_key.

Binding requirement (FR-007 / C-003 / C-010): each of documentation/research/plan MUST author a step whose template.artifact_key == "spec" (creatability) and one == "plan" (/plan-setup). Authoring any other key leaves the type uncreatable despite content. The hosting step and template_file are the per-type authoring choices; the key is fixed.

Fail-closed (C-001): a None projection or a missing key raises TemplateConfigurationError. Never relax the guard to "fix" creatability.

name-urn-resolution.md

Contract — Name↔URN Template Resolution (two lanes)

Requirement: FR-010, C-004. The filesystem↔URN duality is a compatibility contract, not one seam.

Lane 1 — resolve-by-name (unchanged, the creation path)

resolve_configured_template(artifact_kind)template_set[artifact_kind]filenameresolve_template(name) → 5-tier filesystem precedence (.kittify/overrides/templates/ > legacy > global-mission > global > package). The template_file filename is the override key.

Lane 2 — resolve-by-URN (new, graph-addressed)

template_catalog.resolve_template_by_id("template:<mission>/<name>") → splits <mission>/<name> → delegates to the same Stage-2 resolve_template. Uses the mission-qualified URN form.

Invariants

  • Equivalence: for an authored template, by-URN and by-name resolve to the same file (US3.2).
  • Override-wins on both lanes: a .kittify/overrides/templates/<file> override wins for the URN lane too (US3.3) — because both terminate in the same 5-tier resolve_template.
  • Do NOT collapse: the two lanes key on different identities (semantic artifact_kind vs mission-qualified URN); collapsing turns the name-keyed override chain into dead code.
  • Scope bound (FR-010): add the lane + equivalence test only; do NOT re-wire the name-based creation path.
  • Fence (C-002): the new URN code must never reference the scalar template_set surfaces (resolution.template_set, MissionTypeProfile.template_set, doctrine.template_set).