phase.md frontmatter¶
Each phase lives in phases/<phase_name>.md under its skill directory. The YAML frontmatter declares only what the phase consumes — never what it produces, never which phase comes next (P1).
Schema¶
---
type: phase # always "phase"
name: <phase_name> # must match the filename (without .md)
input: <artifact_type> # required; what this phase consumes
role: <short_label> # optional; one-word role for events
can_finish: true # optional; allow terminating from here (default: false)
allowed_ops: [file, ask_user] # optional; Control IR op kinds this phase may use
# (default: ["file", "ask_user"]; [] means no ops)
preprocessor: # optional; deterministic pre-LLM steps
- run_skill:
skill: recall_memory
input: { type: ..., data: { ... } }
into: relevant_memories
- python:
module: stats
function: compute
mode: safe # safe | unsafe
output_schema: { ... }
---
Required fields¶
type— must bephase.name— string, identifies this phase in the skill'sgraph. Must match the filename.input— artifact type the phase reads. Either a single artifact name or a union (user_message | topic_input).
Optional fields¶
role— short label for event payload (e.g.planner,reviewer).can_finish— whentrue, the LLM may emitdecision="finish"from this phase. The OS validates the final artifact against the skill'sfinal_output_schema.preprocessor— chain of deterministic steps that run before the LLM call. Seereference/dsl/preprocessor.md(Phase 2).allowed_ops— list of Control IR op kinds this phase may emit (e.g.[file, lint]). The OS filters theavailable_control_opsadvertised to the LLM down to this set, and rejects any out-of-set op the LLM emits anyway withcontrol_ir_skipped: not_allowed_in_phase. Default:["file", "ask_user"]— file I/O plus user clarification, the common case. An explicit empty list ([]) means "no ops" (use this for pure routing/judging phases). The narrower the list, the less context spent on op descriptions and the less room the LLM has to drift outside the phase's intent. Meta-skills (skill_builder,skill_improver,skill_importer) consult the ContextFrame'sop_catalogfield — a reference list of every op kind the OS supports — to chooseallowed_opsvalues for the phases they generate.
Note: Phase-level
permissions:was removed in the skill-only permissions migration. Declare permissions at the skill-md frontmatter instead — see skill-md.md and permission-model.md.
What MUST NOT appear¶
- Output schema of any kind. Output is determined by the next phase's input or the skill's
final_output(P1). - The next phase name. The Skill graph owns transitions (P1).
- Control IR format descriptions. The OS injects available ops into the context frame (P8).
Body¶
The markdown body is the phase's instructions to the LLM. Cover:
- What to analyze, generate, or decide
- When to choose which next-phase candidate
- Domain-specific rules, examples, and edge cases
Avoid restating schemas, listing field names, or describing Control IR — these are runtime-injected.
Example¶
---
type: phase
name: outline
input: topic_input
role: planner
---
Produce three bullet points that capture the most important angles of
the topic. Each bullet should be a complete sentence — the next phase
will expand each into a paragraph, so vague bullets produce vague
paragraphs.
Avoid: meta-commentary, scope hedging, more than three bullets.
See also¶
- skill-md.md — Skill frontmatter
reference/dsl/preprocessor.md— preprocessor steps (Phase 2)- Concepts: principles P1, P8