The schemas every prompt must respect

Five contracts hold the workflow together: the file that bridges the workflow to the host project (app.md), the template that seeds it (app.template.md), the per-host workflow-params file (_code_workflow/config.json), the file that scopes a single job (JOB.md), and the chat shape every dispatched stage returns to the orchestrator (STAGE_HANDOFF).

APP_CONTRACT — what app.md must contain

app.md is the only project-specific file the workflow reads (D-21, D-36). Every prompt under _processes/** opens with the literal directive "Read app.md first." and stops if the file is missing or is the bootstrap placeholder. Post-D-36, app.md describes the host project only; workflow-internal parameters moved out to _code_workflow/config.json.

The 12 section concerns

#ConcernMust answer
1IdentityProject name and short description.
2Canonical context filesPointers to the project's pre-existing top-level rules / doc-map files.
3Tech stackBackend, frontend, database, containers, key libraries.
4Directory mapWhere source code, docs, tests, fixtures, configuration live.
5Coding patternsThe project's settled conventions (DI, naming, base classes, etc.).
6Security rulesWhat every change must respect (input validation, credentials policy, etc.).
7Common commandsBuild, cache, migrate, deploy commands the agents must run.
8Test frameworkFramework name + how to invoke it. Used by the test stage.
9Documentation conventionsWhere docs live and the rules for updating them. Used by the document stage.
10Domain glossaryProject-specific terms agents need to know.
11Never-do listHard prohibitions for any agent acting on this project.
12Agent reading rulesHost-routing rules: which host docs each kind of work / each stage must read before acting. Pointer-first. Added per D-39.

A separate Sub-agent runtimes section was once a candidate concern in the pre-D-36 contract; it was removed entirely when workflow-internal runtime declarations moved to _code_workflow/config.json. The genuine 12th concern is Agent reading rules (D-39).

How it's enforced

Portability — port the workflow in one file — Copy _code_workflow/ to a new project, rewrite app.md (and create config.json from config.example.json), and the entire workflow runs. No code change in _processes/.

Source: _processes/00_app/APP_CONTRACT.md (moved from _processes/_shared/schemas/ by D-36).

app.template.md — the starting point for app.md

A paste-as-starting-point template the init agent reads when drafting a host's app.md (D-36). Pre-D-36 the skeleton was embedded inside APP_CONTRACT.md → ## Skeleton; D-36 extracted it into its own file so init has a dedicated template artifact, mirroring _processes/_shared/templates/ for JOB, PROGRESS, PLAN, NOTES.

Source: _processes/00_app/app.template.md (new file, D-36).

_code_workflow/config.json — workflow runtime params

A small per-host JSON file holding workflow-internal parameters that are not host facts — specifically, which sub-agent runtimes are available in the current developer's environment (D-36). The file is gitignored; the schema is documented by the checked-in _code_workflow/config.example.json.

Schema

{
  "runtimes": {
    "claude": true,
    "codex": false
  }
}
Why split out of app.md (D-36) — app.md describes the project. config.json describes the developer's machine. The split lets app.md remain a clean host-facts-only file, while runtime availability moves to a gitignored file with a checked-in example.

Source: _code_workflow/config.example.json; _processes/00_app/app-init.prompt.md and _docs/DECISIONS.md → D-36.

JOB_CONTRACT — what JOB.md must contain

Every job has exactly one JOB.md at the root of its folder. This is the scoping contract and mandate: it states what the job is, how it should run, and what success looks like.

Document layout

JOB.md is one markdown document with two top-level halves:

  1. A structured header (closed-set fields the agents parse).
  2. A free-text mandate body (prose; no required sub-sections).

Required header fields

# <slug> — <title>

**Workflow version:** 0.15
**Type:** <type>
**Preset:** <preset path or short name>
**Created:** <YYYY-MM-DD>
**Status:** <queue name — informational only>
**Base branch:** <base branch, default main>
**Target branch:** <feature/<slug>, or N/A>

## Git
- Create branch: yes|no
- Validate against main: yes|no
- Commit: yes|no
- Push: yes|no                          # standalone step between commit and PR (D-82)
- PR: yes|no
- PR target branch: branch-name|blank   # merge-INTO target; blank ⇒ production (0.14, D-63)

## Stages
- [ ] clarify
- [ ] brainstorm
- [ ] plan
...
- [ ] review     (disabled)
- [ ] validate

## Approval gates
- after_creation: yes|no
- after_clarify: yes|no
- after_brainstorm: yes|no
- before_plan: yes|no
- before_execution: yes|no
- before_commit: yes|no
- before_pr: yes|no

## Per-stage config

### KISS mode
- Enabled: yes                         # optional; job-level, feature-only; omitted when off (D-77)

### Brainstorm
- Mode: dual_consolidate|solo|none
- Agents: claude|codex|claude, codex
- Consolidator: claude|codex          # dual_consolidate only; default claude (D-30)

### Plan
- Multi-phase: yes|no

### Test
- Unit: yes|no

### Validate
- Agent: claude|codex                 # runtime validate dispatches to; default claude (D-38)

### Document
- Internal: yes|no

### Loop-back
- Max iterations: 3                    # optional; absent = default 3; per-job loop-back cap (D-59)
                                      # counts accepted rounds of either route — full or light-fix (D-83)

## Expected artifacts
- <path or description>

## Git semantics (0.14, D-63) — Base branch = the branch the job branch is cut FROM (default main); the header's Target branch = the job branch itself; PR target branch = the branch the PR merges INTO (blank ⇒ production). Commit: yes / PR: yes are honoured by the shared git landing (_processes/_shared/git-landing.md): post-validate in the orchestrator's §I Completion for pipeline jobs, inline for action-layer jobs — one commit per landing, gated by before_commit / before_pr, remote-aware fallback off GitHub, and the workflow never merges a PR. Validity rules: PR: yes requires Commit: yes and Push: yes (both refused at creation/bootstrap). Push (D-82) is a standalone landing step between commit and PR: it pushes the job branch to origin on every remote host, whether or not a PR is requested — before D-82 the only push was a sub-step of the GitHub PR path, so jobs on other hosts were never pushed. An absent Push: line resolves by PR (PR: yes ⇒ yes), so pre-D-82 jobs land unchanged and no version bump was needed. Off GitHub the PR itself is surfaced as a credential-free PR-creation link from the host table (Azure DevOps pullrequestcreate, GitHub/GHE compare URL, generic instruction otherwise).

Closed vocabularies

FieldAllowed values
Stages (pipeline)clarify · brainstorm · plan · execute · test · document · review · validate (canonical order — review precedes validate since 0.12, D-59)
Layers / shapes (D-45)layer: pipeline · action · operation; shape: pipeline · singlet · orchestrator · op-card (action is a layer, not a stage)
Approval gatesafter_creation · after_clarify · after_brainstorm · before_plan · before_execution · before_commit · before_pr
Brainstorm modedual_consolidate · solo · none
Brainstorm consolidatorclaude · codex — dual_consolidate only; default claude; independent of the two writer runtimes (D-30).
Validate agentclaude · codex — only when validate is enabled; default claude; dispatched to a Claude general-purpose sub-agent, or run via codex exec, respectively (D-38, D-56).
Action kindsecurity · find_issues · doc_drift · revalidate · custom · operation_record — only on action-layer / operation-record jobs (D-44, D-45; revalidate added in 0.13 per D-61 — the whole-app/scoped soundness sweep audit kind).
Typefeature · bug · brainstorm · doc_revalidate · app_plan (layer pipeline) · audit · quick_fix · doc_upkeep · doc_create · codereview_fix (layer action) · operation op-cards app-init · app-update · app-install · claude-agents-md-files · promote · extend · quick_fix_collab (+ reserved non-intake operation_record) (D-44–D-50; claude-agents-md-files D-66/D-67; app_plan D-76)
Stage handoff Completiondone · partial · blocked · awaiting_user_input (D-29)
Markdown only (D-2) — No YAML front-matter, no JSON, no separate workflow.yaml. Every consumer in v1 is an LLM; structured markdown headings are sufficient.

Source: _processes/_shared/schemas/JOB_CONTRACT.md; History: _processes/_shared/schemas/JOB_CONTRACT.history.md

STAGE_HANDOFF — the chat shape every dispatched stage returns

Since 0.11 (D-56, superseding D-40) the orchestrator is a pure conductor — it dispatches every enabled stage as a sub-agent and writes the shared job-root state itself. Each dispatched stage (clarify, plan, execute, test, document, validate, plus the brainstorm and review helpers) returns this structured handoff, which the orchestrator verifies against the artifacts on disk before recording it in PROGRESS.md. (D-56 restored this name from the D-40-era HELPER_HANDOFF.md and widened the Stage vocabulary back to all eight stages.)

Required fields

FieldTypeMeaning
Stageclarify · brainstorm · plan · execute · test · document · review · validateWhich dispatched stage produced the handoff (D-56 widened this back to all eight stages).
Completiondone | partial | blocked | awaiting_user_inputHow the helper exits. awaiting_user_input is normal workflow (not a fault, not a user-visible stop): the helper returns a Questions for user block, and the orchestrator relays via AskUserQuestion then re-dispatches (D-29).
ArtifactsList of paths (job-relative)Files the stage produced or updated. The orchestrator verifies each exists on disk.
Decisions to recordList of one-line stringsEach entry becomes one line under PROGRESS.md → Decisions.
BlockersList of one-line stringsNon-empty list = orchestrator stops the run.
Handoff narrativeOne sentenceBecomes one line under PROGRESS.md → Handoff notes.

Optional / conditional fields

FieldWhen usedMeaning
Verdictclarify, test, validate, review; consolidate when relevantMirrors the stage artifact's closed-vocabulary verdict.
Next action hintany stageOptional sentence the orchestrator may write as the next action.
Notes for downstreamany stageForward-looking notes the orchestrator commits to root note.md.
Key findingsany stageDurable sourced discoveries the orchestrator commits to root key-findings.md.
Loop-back requestreview BLOCKED_PENDING_REWORK or validate FAILStructured re-entry request consumed by the orchestrator's loop-back engine.
Rework classificationreview only, and only meaningful with BLOCKED_PENDING_REWORK (D-83)Optional Candidate route (light-fix · full-loop) / Finding IDs (1–2 R<NNN> blockers) / Reason. A routing claim, never an authorization: the orchestrator validates it itself against seven conditions before choosing the light-fix route, and anything absent, malformed, over-broad or unverifiable falls back to the unchanged full loop-back.
Questions for userrequired when Completion: awaiting_user_inputQuestions the orchestrator relays, then injects back into the same stage on re-dispatch.
Proposed JOB.md Mandate-body rewriteclarify onlyFull proposed Mandate-body replacement; clarify stays read-only and the orchestrator applies it.
Stage start time / Stage end timeany stage (0.15, D-70)The stage's self-measured start / end as an ISO-8601 UTC Z instant. Optional report-only: the orchestrator prefers a well-formed field, else falls back to its own dispatch/verify boundary stamp — it owns the clock and writes the ## Timing rows (sole-writer invariant intact).
Phase timesexecute only (0.15, D-70)A list of phase <N>: <start> → <end> per-phase spans refining the nested execute timing rows; each entry validated/falls back independently.

Example handoff

Stage: brainstorm
Completion: done
Artifacts:
  - 02_brainstorm/consolidated.md
Decisions to record:
  - Adopted the unified main-runner approach over the two-prompt split
  - Folded in 2 user-locked answers on the cache-eviction policy
Blockers: (none)
Handoff narrative: Consolidated the Claude + Codex brainstorms; one contested
  decision relayed to the user and folded in before the write.

User-question relay (D-29)

When a dispatched helper needs a user decision before it can produce its final artifact, it returns Completion: awaiting_user_input with a Questions for user block (numbered id, one-paragraph prompt, optional options, optional recommendation). The orchestrator asks the user verbatim, captures the answers, and re-dispatches the same helper to the same runtime with a fenced user_answers block injected:

```user_answers
- id: Q1
  prompt: <verbatim prompt from the prior handoff>
  answer: <verbatim user response>
```

The .lock stays in place; the loop iterates (cumulative across rounds, no fixed cap) until the stage returns Completion: done. Dispatched stages never invoke their runtime's own question facility. The relay is not a user-visible stop (only approval gates are). Used by clarify on ambiguity, the brainstorm consolidate helper, and the Codex review/validate helper — every case routes back through the orchestrator's own AskUserQuestion (D-56).

Why single-writer

If both the orchestrator and dispatched helpers wrote PROGRESS.md, the file would collect duplicate lines, conflicting [x] marks, and stale Next action text — and resume would become fragile. Single ownership eliminates the entire class of bug.

Source: _processes/_shared/schemas/STAGE_HANDOFF.md

## Timing — honest wall-clock time tracking (0.15, D-70)

Since 0.15 (D-70) every job records honest wall-clock time tracking in PROGRESS.md. For the whole job and each timed sub-task — every pipeline stage, plus each execute phase nested under it — the workflow records a start and end instant (ISO-8601 UTC Z), a derived duration in the compact Xh Ym Zs form (zero units omitted, seconds always shown), and an overall Job: total. It surfaces two ways at once: each completed ## Stages line gains a compact (HH:MM:SSZ → HH:MM:SSZ, <dur>) parenthetical after the existing — YYYY-MM-DD, and a new roll-up ## Timing section (after ## Stages) lists every sub-task's full instants + duration plus the Job: row.

## Stages
- [x] clarify — 2026-06-23 (09:14:32Z → 09:18:05Z, 3m 33s)
...

## Timing

- Job:       2026-06-23T09:12:00Z → 2026-06-23T11:40:18Z (2h 28m 18s wall-clock)
- clarify:   2026-06-23T09:14:32Z → 2026-06-23T09:18:05Z (3m 33s)
- execute:   2026-06-23T09:40:00Z → 2026-06-23T10:55:00Z (1h 15m 00s)
  - phase 1: 2026-06-23T09:40:00Z → 2026-06-23T10:02:00Z (22m 00s)
  - phase 2: 2026-06-23T10:02:00Z → 2026-06-23T10:55:00Z (53m 00s)
- validate:  2026-06-23T11:30:00Z → 2026-06-23T11:40:18Z (10m 18s)

The Job: span is honest wall-clock — it includes any time the job sat paused at an approval gate, so it exceeds hands-on time by design. The orchestrator is the authoritative clock (date -u +'%Y-%m-%dT%H:%M:%SZ' at each dispatch/verify boundary) and the sole writer of the block; stages only report their times through the optional STAGE_HANDOFF time fields (Stage start time / Stage end time / Phase times), which the orchestrator prefers when well-formed and otherwise falls back to its own boundary stamp. On a re-run (question-relay re-dispatch, resume, loop-back re-open) the orchestrator preserves the first recorded start, overwrites only the end, and recomputes the duration. Action-layer jobs carry an orchestrator-written shape-scaled block (a Job: row, plus per-phase rows for audit and per-fix rows for quick_fix where cheap); operation-record jobs carry a Job-only row the authoring ops agent self-stamps within the D-54 carve-out.

Read-tolerant back-compat (D-18) — An old date-only stage line (- [x] clarify — 2026-06-23, no parenthetical) is valid with unknown times, and an absent ## Timing block is valid. Times are never back-filled onto already-4_done/ or pre-0.15 jobs; the migration is purely additive (bump the version line).

Source: _processes/_shared/schemas/JOB_CONTRACT.md (§ ## Timing); _docs/DECISIONS.md → D-70.