# Markitect Workflow Definition Standard ## Purpose Markitect workflows describe repeatable Markdown-centered dataflow: ```text Markdown inputs -> extracted data products -> deterministic/assisted steps -> artifacts and Markdown outputs ``` The workflow standard is business-facing orchestration. It uses the internal extension framework for execution semantics, diagnostics, provenance, capabilities, and future policy gates, but it is not itself the extension framework. ## File Format A workflow can be either: - a YAML file - a Markdown file with a fenced YAML block tagged `workflow`, `markitect-workflow`, or `mkt-workflow` Example: ````markdown # Release Notes Workflow ```yaml workflow metadata: id: release-notes title: Release Notes intent: summary: Build release notes from accepted ADR decisions. inputs: adrs: glob: docs/adr/*.md extract: decisions: selector: sections[heading=Decision] outputs: release_notes: path: out/release-notes.md content: ${steps.render.markdown} steps: render: kind: template template: templates/release-notes.md data: decisions: ${sources.adrs.extracts.decisions} ``` ```` ## Top-Level Sections | Section | Required | Purpose | | --- | --- | --- | | `metadata` | recommended | Stable id, title, owner, version, tags, timestamps. | | `intent` | recommended | Why the workflow exists and what success means. | | `inputs` | yes | Markdown files, directories, globs, literal values, or future index references. | | `steps` | yes for processing | Deterministic or assisted operations over bound data. | | `outputs` | optional | Files/artifacts produced from step or source data. | | `dependencies` | optional | Workflow-level dependencies on files, workplans, contracts, or other workflows. | | `conditions` | optional | Preconditions or skip rules. First version records these for inspection. | | `artifacts` | optional | Named non-output products such as manifests, traces, or reports. | | `permissions` | optional | Declared filesystem/network/provider/capability requirements. | | `resources` | optional | CPU, memory, token, model, or storage expectations. | | `timeouts` | optional | Workflow and step timeout budgets. First version records these. | | `retry_policies` | optional | Retry rules by step kind or id. First version records these. | | `escalation_rules` | optional | When human approval or operator attention is needed. | | `observability` | optional | Events, trace detail, metrics, and audit expectations. | | `responsibilities` | optional | Human/agent/system boundaries for review, approval, and execution. | Unknown top-level sections are preserved as `extensions` in the loaded model so the standard can evolve without immediately breaking older runners. ## Metadata ```yaml metadata: id: release-notes title: Release Notes version: "1" owner: documentation tags: [adr, release] ``` `metadata.id` should be stable. It is used in diagnostics and provenance when available. ## Intent ```yaml intent: summary: Build release notes from accepted decisions. success_criteria: - One output file is generated. - Every accepted ADR contributes its decision section. ``` Intent is descriptive in the first implementation. Later policy and assessment layers may use it for review or LLM-assisted checks. ## Inputs Inputs are named source collections or literal values. ```yaml inputs: adrs: glob: docs/adr/*.md recursive: false where: frontmatter.status: accepted extract: decisions: selector: sections[heading=Decision] status: selector: frontmatter.status static_context: value: product: Markitect ``` Supported source fields: - `file`: one Markdown file - `path`: alias for `file` - `files`: list of Markdown files - `glob`: glob pattern relative to the workflow directory - `directory`: directory of Markdown files - `recursive`: recurse when using `directory` - `selector`: selector to collect matches - `extract`: named selector map - `metrics`: include document metrics - `frontmatter`: include frontmatter - `value`: literal structured value, no file parsing Each Markdown input produces a collection: ```yaml items: - path: docs/adr/001.md frontmatter: {...} metrics: {...} extracts: decisions: - "## Decision\n\n..." extracts: decisions: - "## Decision\n\n..." ``` ## Steps Steps are named operations. `steps` may be either a mapping or a list with `id`. ```yaml steps: render: kind: template template: templates/release-notes.md data: decisions: ${sources.adrs.extracts.decisions} ``` Common fields: - `kind`: step kind - `depends_on`: other step ids - `when`: condition expression, reserved for future execution gating - `optional`: do not fail the whole workflow when this step is skipped or blocked - `permissions`: step-level permissions - `timeout`: step-level timeout declaration - `retry`: step-level retry policy reference or inline rule - `responsibility`: `human`, `agent`, `system`, or `mixed` First implementation step kinds: | Kind | Purpose | | --- | --- | | `shape` | Resolve data bindings into a structured object. | | `extract` | Extract text from a source collection or document. | | `query` | Return query match envelopes from a source collection or document. | | `template` | Render a deterministic Markdown template. | | `compose` | Join Markdown strings or files into one Markdown document. | | `transform` | Apply deterministic Markdown transforms. | | `include` | Resolve include markers in Markdown. | | `contract_stub` | Generate a Markdown stub from a contract. | | `contract_check` | Check a Markdown document against a contract, optionally with runtime context. | | `form_state` | Evaluate UI-neutral field prefill, validation, and dynamic rules. | | `assisted` | Provider-neutral assisted step boundary, optional by default. | ## Data Bindings Workflow expressions use `${...}` references: ```yaml data: decisions: ${sources.adrs.extracts.decisions} summary: ${steps.render.markdown} ``` If a string is exactly one expression, the resolved value keeps its native type. If an expression appears inside a longer string, it is rendered as text. Supported roots: - `metadata` - `intent` - `sources` - `steps` - `artifacts` - `workflow` Path behavior: - dictionary keys use dot notation - numeric list indexes are supported - applying a field to a list maps that field over every dictionary item ## Outputs ```yaml outputs: release_notes: path: out/release-notes.md content: ${steps.render.markdown} ``` Supported output fields: - `path`: output path relative to `--output-dir` or workflow directory - `content`: Markdown/string/structured value to write - `template`: optional template path - `data`: data for template rendering - `artifact`: optional artifact name Output paths must stay within the output root. ## Assisted Steps Assisted steps define the boundary; they do not require a provider dependency: ```yaml review: kind: assisted optional: true prompt: prompts/review.md input: ${steps.render.markdown} data: rubric: concise release note review ``` When no assisted adapter is supplied: - optional assisted steps are skipped with a warning diagnostic - required assisted steps fail with an error diagnostic This keeps workflows runnable in deterministic environments. ## Permissions And Responsibilities Permissions and responsibilities are declarative in the first runner and become policy inputs for later access-control work. ```yaml permissions: filesystem: read: [docs, templates] write: [out] network: false assisted_generation: false policy: subject_from_token: examples/policy/netkingdom-claims.yaml policy_map: examples/policy/enterprise-policy-map.yaml required_assurance: mfa: true emergency_justification: INC-123 decision_log: .markitect/policy-decisions.jsonl flex_auth: resource_manifest: examples/policy/flex-auth-resource-manifest.yaml responsibilities: human: approves_outputs: true agent: may_run_deterministic_steps: true system: enforces_path_safety: true ``` ## Observability ```yaml observability: events: - workflow.started - step.completed - output.written trace: summary ``` Workflow runs return trace events and diagnostics in JSON/YAML output. Future backends can persist these events. ## Design Rules - Keep deterministic execution useful without providers. - Keep all outputs explainable through provenance and diagnostics. - Preserve unknown metadata rather than rejecting reasonable future extensions. - Make assisted, external, networked, or sensitive steps explicit. - Keep internal extension registration separate from business workflow orchestration.