Proposal: decide where workflow phases (apply/archive/sync) are configured — schema.yaml, config.yaml, or both #1456
Description
Summary
OpenSpec has two places project guidance can live, and workflow phases (apply, archive, sync) are currently mapped into them inconsistently. We should decide the intended mapping deliberately and make the CLI surface follow it.
This is a design decision to schedule, not a bug. It came out of review on #1062 (which is fine to ship as-is) and it subsumes #1383.
The intended split
The distinction is about reuse, not about which fields exist where:
| Location | Scope | Meaning |
|---|---|---|
schema.yaml |
Global | Reusable across projects — how this kind of workflow works |
config.yaml |
Project-specific | How this project works |
Both are legitimate homes for phase guidance, and the likely end state is both — a global default in the schema, overridden or extended per project in config. What we don't have is a decided, documented mapping, or a merge/precedence rule between the two.
Where it's inconsistent today
apply is a phase block in schema.yaml:
# schemas/spec-driven/schema.yaml
apply:
requires: [tasks]
tracks: tasks.md
instruction: |
Read context files, work through pending tasks, mark complete as you go.archive guidance, after #1062, is a config namespace:
# openspec/config.yaml
operations:
archive:
guidance:
- Summarize the archive outcome before finishingsync has no configurable guidance in either place. So the same concept — "how should the agent conduct this phase" — has three different answers depending on which phase you ask about. #1383 asks for the schema.yaml half of this and is still open.
Already decided — not reopening
@TabishB settled the artifact-vs-operation distinction on #1062, and this issue takes it as given:
Artifact rule = what an output should look like
Operation guidance = optional advice for how to do some work
Skill = the built-in steps for doing the work
CLI check = something that must pass
Artifact rules "travel with the artifact" — archive receives the specs rules because archive happens to produce a spec, not because they are archive rules. operations.<phase>.guidance living in config.yaml was also his explicit call, implemented as specified in #1062. Neither is an open question here. What remains open is only whether phases also get a home in schema.yaml, and how the two would combine.
The CLI surface follows from it
openspec instructions [artifact] takes a positional documented as an artifact ID, but apply and (after #1062) archive are accepted there as reserved words. Artifact IDs come from user-editable openspec/schemas/<name>/schema.yaml, so the namespaces genuinely overlap: a project-local schema that defines an artifact named archive can no longer reach it — verified on the #1062 branch, main returns the artifact and the branch silently returns archive inputs instead, with no error.
Once the phase model is settled, the fix is small and non-breaking:
- rename the positional to
<target>in help/docs — it's a positional, so Commander matches by position and nothing users type changes - add
--operation <apply|archive|sync>as the unambiguous form, keeping the bare shorthand working - resolve phases from a namespace separate from artifact IDs so the collision can't happen
Open questions
- Do phases live in
schema.yaml,config.yaml, or both? - If both, what's the precedence/merge rule — does project config override the schema instruction, or append to it?
- Does
syncbecome a first-class phase alongsideapplyandarchive? - Does the phase block carry structure (
requires,tracks) likeapply:does, or only free-text guidance?
Note
@0xTab's read is that a configurator for this will expose the gaps in the mapping better than reasoning about it in the abstract, so this may be worth sequencing behind that work rather than designing up front.
Related
- feat(instructions): add runtime context and operation guidance #1062 — added
operations.<phase>.guidancetoconfig.yamlper @TabishB's spec; shipped as-is, this issue captures the deferred location question - Proposal: prepare → agent work → validate → confirm → finalize flow for archive #1460 — who executes archive (prepare → agent → validate → finalize); orthogonal to this issue, which is about where phases are configured
- Proposal: Instructions for archive/sync in schema.yml #1383 — asks for archive/sync instructions in
schema.yaml; this issue supersedes it
Activity
SuhaibAslam commentedon Jul 29, 2026
Intent reconciliation as an acceptance case for the operation model
I have a concrete workflow that may help answer the open questions in this
issue: reconcile implementation discoveries before archive.
User flow
non-goals, and success evidence.
the planning artifacts were written.
proposed decision.
The important distinction is that this is not more advice for
applyorarchive. It is a post-apply operation with a durable output and adeterministic precondition for archive.
Why the current schema cannot model this faithfully
The current artifact graph is a planning graph:
detectCompleted()insrc/core/artifact-graph/state.tstreats an artifactas complete when any file matching
generatesexists.generateApplyInstructions()insrc/commands/workflow/instructions.tschecksapply.requiresonly beforeapply, then loads every existing artifact as context.
ApplyPhaseSchemainsrc/core/artifact-graph/types.tssupports onepre-apply requirement list and an optional checkbox tracking file. It has no
post-apply output or operation dependency.
permits the user to proceed. The direct
openspec archivepath does not usethe artifact graph as an archive gate.
operations.<phase>.guidanceis explicitly advisory, so it cannot honestlyexpress "do not archive while decisions are unresolved."
A custom schema can create
intent.mdand an initially emptydecision-log.md, and its apply instruction can ask the agent to update theledger. It cannot make a later reconciliation artifact become ready only after
implementation or fail closed when archive is invoked directly. Claiming that
it can would turn a prompt convention into a false safety guarantee.
Smallest operation model that would cover the case
One possible shape is:
This is illustrative rather than a request to adopt these exact keys. The
required semantics are:
only file existence;
and JSON modes;
The durable reconciliation output could initially use file existence as its
completion signal, matching current artifact semantics. A later validation
contract could make content-level states such as
pendingandapprovedmachine-checkable, but that does not need to block agreement on the lifecycle
shape.
Relationship to the linked issues
apply,reconcile, andarchiveasfirst-class operations with a namespace separate from artifacts.
problem described there. Composition or explicit extension would let a
reconciliation layer build on
spec-driven.and an advisory pre-archive hook is not a deterministic gate. The use case
needs an operation precondition rather than arbitrary subprocess execution.
Suggested next decision
Before implementation, can maintainers confirm whether operation outputs and
operation-to-operation requirements belong in the phase model being considered
here? If yes, I can turn this acceptance case into an OpenSpec change proposal
and start with the namespace/readiness contracts before adding any
intent-specific schema.
Disclosure: drafted with assistance from Codex (GPT-5).