Lifecycle
This lifecycle is an optional OAT layer. Interop-only users can skip it.
OAT lifecycle order:
- Discovery (
oat-project-discover) - Spec (
oat-project-spec) - Design (
oat-project-design) - Plan (
oat-project-plan) - Implement (
oat-project-implement) - Review loop (
oat-project-review-provide/oat-project-review-receive) - Summary (
oat-project-summary) — generatessummary.mdas institutional memory;oat-project-pr-finalandoat-project-completeauto-refresh it when missing or stale - PR (
oat-project-pr-progress/oat-project-pr-final) — setspr_openstatus - Revision loop (
oat-project-revise) — optional; accepts post-PR feedback - Documentation sync (
oat-project-document) — optional; reads project artifacts and code evidence to identify docs needing updates, checks for missing coverage of newly shipped capability areas, and auto-runsoat-pjm-update-repo-referencebefore scanning docs only when the PJM capability is available and this repository has adopted PJM - Complete (
oat-project-complete)
Shortcut: oat-project-next reads project state and invokes the correct next skill automatically — use it instead of remembering which skill comes next. Complements oat-project-progress (which is read-only diagnostic).
Full spec-driven design supports three interaction modes: collaborative, selective collaborative, and draft-and-review. Selective collaborative drafts routine sections silently and presents high-risk or uncertain sections for live review. Quick-start lightweight design stays simpler and offers only collaborative or draft-and-review. See Design Modes for details.
For a one-page view of where people approve and what runs automatically in each mode, see Approvals and Automation.
Quick Look
- What it does: explains the end-to-end lifecycle for tracked OAT projects, including alternate quick, lite, brief, goal, and import lanes.
- When to use it: when you need the actual project execution model, not just a high-level overview of workflow mode.
- Primary entry points:
oat-project-new,oat-project-quick-start,oat-project-lite,oat-project-brief,oat-project-goal,oat-project-import-plan,oat-project-implement
Lifecycle Map
This map shows the spec-driven default. The quick, lite, brief, goal, import, and capture lanes each skip part of it — see Lane diagrams below. Lite, brief, and goal in particular have no discovery, spec, or design step at all.
Post-implementation flow
Implementation closeout has one authoritative order:
- Run final implementation verification.
- Pass the mandatory final lifecycle review.
- Resolve and disposition the configured
oat-project-implementexit gate. - Run the configured pre-approval sequence.
- Record final HiLL approval when the final phase is a checkpoint.
- Run the configured post-approval sequence.
- Check the journal (
oat project journal check --at implement-preflight), then mark implementation complete and emit the implementation success output.
The configured exit gate is independent from the mandatory lifecycle review,
root-owned phase reviews, and optional oat_phase_review_gate. It must reach an
allowed and fresh disposition before pre-approval work starts. A
not_configured resolution is recorded explicitly as allowed/no_gate; it is
not inferred from missing state, and a null, missing, or unrecognized resolver
result fails closed as unresolved instead.
A later substantive change makes an allowed result stale, test-only changes
included. Only an operator can keep it fresh, by recording an append-only
exit-gate waiver for the exact commits; agents never issue one. An autonomous
run that finds a stale result persists stale and starts a new gate run; it
refuses only an attempted waiver write. The summary and PR description list every waiver.
After implementation closeout finishes:
- Summary (
oat-project-summary) — generatessummary.mdas institutional memory from project artifacts; PR-final and completion will auto-refresh it if you have not already run it or if it is stale - Documentation (
oat-project-document) — optional sync of project docs; decides whether repo-reference refresh should run before docs analysis using two independent checks, and should recommend new docs pages/directories when the shipped work introduces a capability area that the docs app does not already cover - PR (
oat-project-pr-final) — creates PR description (auto-refreshessummary.mdfirst when needed, then uses it as source), setsoat_phase_status: pr_open, and tracks actual PR existence withoat_pr_status/oat_pr_url - Revision loop (
oat-project-revise) — accepts post-PR feedback:- Inline feedback creates
p-revNrevision phases withprevN-tNNtask IDs - GitHub PR feedback delegates to
oat-project-review-receive-remote - Review artifacts delegate to
oat-project-review-receive - After revision tasks complete, state returns to
pr_open
- Inline feedback creates
- Complete (
oat-project-complete) — acceptspr_openorcomplete(anin_progressproject is routed back tooat-project-implement, because the journal andstate.mdmust agree at completion), auto-refreshessummary.mdbefore closeout when needed, and archives when selected by the workflow preference or completion prompt. Before any completion write it runs the read-onlyoat project closeout-check: a configured, autonomous, or lite closeout whoseoat_post_implement_sequencesnapshot is missing, malformed, or incomplete stops and routes back tooat-project-implement, andoat project complete-staterefuses the same state. There is no override for that invariant. Completion then refreshes the journal's Final Summary andsummary.mdprose from observed facts, runs the summary staged, and validates the journal withoat project journal check --at completionbefore any roll-up, seal, archive or lifecycle write; a refusal stops completion with the reason, line and owner, andcomplete-staterechecks the same evaluator before its write. A journal-only override line under## Deviations from Plan / Designcan cover an authorized gap such as lost commit evidence, never the closeout invariant; see the CLI reference and Project Artifacts.
Project-recap gate (non-lite)
The final-closeout orchestrator re-reads persisted recap intent after final
review and configured pre-approval summary and documentation steps, but before
final HiLL approval. A persisted skip suppresses manifest discovery and the
entire generation flow. A persisted generate decision reuses a fresh satisfied
package or invokes oat-explainer-kit § Generate.
Fresh means the package identifies this project and recipe, has outcome built
or built-needs-review, passes the complete package guard, and records source
hashes for the current approved inputs. Wrong-project, wrong-recipe, stale,
failed, and incomplete packages do not qualify.
The flow bundles approved evidence, lets the host agent author one page,
verifies it at the best available browser rung, and records the package.
built-needs-review satisfies generation and does not block approval. In
autonomy, an unsatisfied run is retried once; a second failure persists
skip/failed_attempt, which closeout consumes without another bundle or
authoring pass. Reports and summary.md preserve the actual outcome, run path,
or skip reason.
Lite skips this gate entirely. Lite sets PROJECT_RECAP_REACHABLE=false and
does not resolve recap intent, inspect recap runs, invoke oat-explainer-kit,
or run the terminal-outcome guard. It proceeds from the required reviews through
its stored optional steps to pr and sequence completion.
Lite mode collapses the default pre-approval sequence to PR creation only.
oat-project-pr-final builds the body directly from the lite plan and
implementation.md; summary and documentation remain explicit lite opt-ins,
and retro is not added to the lite closeout sequence.
Completion archive behavior
On completion, OAT treats archive handling as an explicit closeout choice:
- When archiving is selected, the local archive is written to
.oat/projects/archived/<project>/. - Every completion that will actually archive — any durable (
sharedorsynced) project with archive selected — keeps theactiveProjectpointer until the archive returns a validated receipt, and only then clears it.localprojects are never durable and never archive, so they clear the pointer immediately, as does any completion that declines archive. An archive failure therefore leaves the pointer intact and the completion directly resumable. See Picking Up a Project for the post-archive resume and its manual recovery path. - When archiving is disabled or declined, durable projects remain at their
active path. Synced completion still finalizes and pushes the project ref,
commits the discovery record as
complete, retains the checkout and ref, and keeps any recap governed by its manifest and package verification without a separate closeout evidence push. - For a synced project, closeout first finalizes the project artifacts and
pushes them to
refs/oat/projects/<project>. Archive then requires a clean, fully pushed checkout; copies it without the.gitpointer orreviews/; seals configured durable exports; transitions terminal reachability torefs/oat/completed/<project>; removes the nested checkout; and deletes the tracked JSON record in the parent lifecycle commit. This order keeps SHA-pinned PR links valid without leaving active discovery state behind. - A completed-only ref and a completed ref plus same-SHA active alias are both valid terminal shapes. The active alias is inert: list omits it and pull/open reject it. Differing SHAs are a hard mismatch with recovery guidance.
- If
.oat/config.jsonenablesarchive.s3SyncOnCompleteand setsarchive.s3Uri, completion requires the S3 upload of a dated snapshot such as<archive.s3Uri>/<repo-slug>/projects/20260401-<project>/to succeed before terminal record/ref cleanup. A failed configured upload leaves retry identity intact and does not claim closeout. - If
.oat/config.jsonsetsarchive.awsProfileand/orarchive.awsRegion, those values are forwarded to everyawsinvocation triggered by completion (preflight checks +aws s3 sync) and override any ambient shellAWS_PROFILE/AWS_DEFAULT_PROFILE/AWS_REGION/AWS_DEFAULT_REGIONvalues. The repo's archive-scoped credentials are treated as deliberate intent so users don't have to unset shell env vars before running completion. Seeconfig-and-local-statefor the full precedence chain. - If
.oat/config.jsonsetsarchive.summaryExportPath, completion copiessummary.mdto<archive.summaryExportPath>/20260401-<project>.md. - Missing or unusable AWS CLI configuration blocks synced terminal cleanup when S3 durability is configured; when S3 sync is not configured, it is not part of the durability requirement.
oat repo archive synccan later sync all archived projects, or one named archived project, back down from S3, materializing each snapshot into the local bare archive tree under its full local name (generation 2 of<project>restores to<project>-g2, never over generation 1). Archive names follow one contract,<project>[-gN][-<scope>]locally and<YYYYMMDD>-<project>[-gN][-<scope>]in S3, where-<scope>appears only when another scope's archive already held the unqualified name. An unnamed sync restores the latest dated snapshot of every local archive. A named sync takes an exact snapshot name first, then a full generation name such as<project>-g2or<project>-g2-local, then a generation family:<project>-<scope>restores that scope's latest generation, and the base<project>restores every family of the project (the unqualified one and each scope-qualified one) at its latest generation, then latest date. A project whose own name ends in-gNor-<scope>reads as that generation or qualifier, so its name can resolve to the same archive directory as a shorter-named project's; sync it by exact snapshot name to remove the ambiguity.- Persisted archive metadata binds the snapshot to the source-ref SHA, allowing an interrupted closeout or legacy complete record to resume without rematerializing an active project. Dashboard and list surfaces omit fully retired projects and report precise cleanup or ref-mismatch diagnoses for remaining legacy state.
oat project linkscontinues to render full-SHA links through the completed ref.oat project pruneis a separate destructive choice that removes terminal ref reachability but preserves local and S3 archive snapshots.
Absorbed-project retirement sweep
Retiring a project that a later project absorbed is a semantic claim, not a filesystem operation. Deleting or archiving the old scaffold does not make the roadmap stop promising its work, so completion checks the claim against the prose that still makes it.
When a quick or lite project consolidates earlier scaffolds, the workflow that
scaffolds it (oat-project-quick-start or oat-project-lite) records
absorbed_projects and absorbed_backlog_ids in that project's state.md
frontmatter, with the same field shapes in both modes. Those two fields are the
only inputs the sweep takes.
Inside the project-log completion gate — after the log status probe and before the roll-up and seal — completion searches the active planning surfaces for each absorbed slug and backlog ID, and for future-oriented ownership language tied to them:
.oat/repo/pjm/roadmap.md(the Now/Next/Later lanes and the sequencing map).oat/repo/pjm/current-state.md- the Curated Overview in
.oat/repo/pjm/backlog/index.md - the scope-nested
state.mdof projects that are still active, under the configured projects root, skipping thearchivedtree and any project already recorded as complete
The sweep is advisory. A raw match is never a hard block on closeout: each hit
becomes a named finding carrying a recorded disposition: fixed in the same run,
accepted as historical with a reason, or — in an autonomous run — recorded as
deferred advisory. Prose that clearly describes
past state is exempt, so a dated history entry, a retro, a decision record, or a
changelog line reads as evidence rather than a stale claim.
Placement is the point. Dispositions are appended to the project log before the
roll-up, so the roll-up summarizes them and the completion seal remains the
final entry — no project-log append ever follows the seal. Three variations
change where and how the dispositions are recorded: an autonomous run records
each finding as a deferred advisory warning and continues, a project with no log reports them in the
final completion summary, and a resumed completion whose log already
carries a seal runs report-only and appends nothing.
A resume detects that seal from oat project log check, which reports a
sealed field, rather than by re-reading the log. The invariant is enforced in
the CLI: replaying the seal reports already-appended and leaves exactly one
seal entry; a replay recognized by its own idempotency key reports
already-appended even on a sealed log (nothing is appended), and every
append carrying new content is refused with status: "sealed" and a non-zero
exit.
Repositories that never adopted PJM skip the sweep with a one-line note. A missing planning surface degrades the sweep, never the closeout.
Phase status: pr_open
After oat-project-pr-final runs, state.md shows oat_phase_status: pr_open. This signals:
- The project is in its post-PR review posture
- The project is NOT done — agents should not start a new project
- Next steps:
oat-project-revise(for feedback) oroat-project-complete(when approved)
Actual PR existence is tracked separately from oat_phase_status:
oat_pr_statusrecords whether the PR is merely ready to create, open, closed, or mergedoat_pr_urlrecords the tracked PR URL when a PR exists
This distinction matters during completion: oat-project-complete can skip the "Open a PR?" prompt when oat_pr_status: open is already present.
Auto-review at HiLL checkpoints
When workflow.autoReviewAtHillCheckpoints is enabled or plan.md frontmatter sets oat_auto_review_at_hill_checkpoints, completing a HiLL checkpoint automatically runs the extra lifecycle review scoped to every implementation phase not already covered by a passed whole-phase code review, through the just-completed checkpoint. Mid-implementation multi-phase reviews use inclusive phase-range scopes such as p02-p03; the final implementation checkpoint uses code final. The review uses auto-disposition mode (low findings auto-converted to fix tasks, no user prompts). The preference is unset by default; interactive implementation asks with "no" suggested, while autonomous non-lite implementation forces it on. Legacy autoReviewAtCheckpoints and oat_auto_review_at_checkpoints are still read as fallbacks. This does not control Tier 1 per-phase oat-reviewer gates.
Approval-aware post-implementation sequencing
workflow.postImplementSequence can use the legacy string values or a structured
{ preApproval, postApproval } value. After final verification, final review,
and an allowed, fresh implementation exit-gate disposition, OAT snapshots the
effective sequence, runs ordered pre-approval steps, records final HiLL
approval, and only then runs post-approval steps. The snapshot is restart-safe:
an incomplete sequence routes back to implementation and resumes from its first
incomplete step.
Structured sequences accept summary, document, pr, and retro.
retro is post-approval only: placing it in preApproval invalidates the
structured value. This placement lets the retrospective include the final
approval and feedback tail while still running before project completion
freezes lifecycle artifacts. The legacy string mappings are unchanged and do
not add a retro step.
When a pending post-approval retro step runs, OAT dispatches
oat-project-retro in generate mode. Applying repo improvements and filing
tracker items remain separately consented through interactive confirmation or
workflow.retro.* configuration.
oat-project-next checks oat_implement_exit_gate before every normal
post-implementation route. Missing, pending, blocked, malformed, or stale state
routes back to oat-project-implement even when oat_phase_status is
complete or pr_open. Only an allowed, fresh disposition can continue to
summary, documentation, PR, or project completion.
Retrospective completion safety net
Before an interactive completion closes the project,
oat-project-complete checks for
{PROJECT_PATH}/references/project-retro.md. If the artifact is missing, it
offers to generate one before completion. If the artifact exists, completion
does not offer another retro; it may note unsettled promotion or filing
registers. Non-interactive completion skips this offer, so autonomous
generation occurs only through an explicitly configured post-approval retro
step.
Phase-review setup during planning
Spec-driven, quick, and import planning run one shared setup after stable phase
IDs exist and before the plan artifact review. Lite omits this planning-time
setup and prompt, while its built-in implementation phase and final reviews
remain required. The target probe qualifies only
an explicitly configured, enabled, and available review target, then offers all
phases, selected phases, or disabled. Existing explicit
oat_phase_review_gate values are preserved unchanged without re-prompting.
Probe failure, no qualifying target, non-interactive execution, or user decline
leaves phase review disabled. Provider native plan mode inherits this behavior
through the import-plan lane.
Implementation modes
oat-project-implement v2.0 dispatches one subagent per phase (not per task). Capability detection at skill start selects a tier, locked for the run:
- Tier 1 (subagents): native subagent dispatch via Claude Code, Cursor, or Codex with spawn authorization.
- Tier 2 (guarded sequential execution): orchestrator reads the agent files and uses a target-preserving route when native subagents are unavailable or authorization is declined.
A concrete managed reviewer remains bound across both tiers. Codex uses the
exact registered role or a child pinned to the resolved model and effort;
Claude launches the exact generated providers.claude.dispatchArgs.variant
for an effort-pinned target and passes providers.claude.dispatchArgs.model
only for a legacy model-only target; Cursor launches the exact
providers.cursor.dispatchArgs.variant native reviewer variant. Retries
preserve that complete target. Tier 2 does not authorize a target downgrade.
Inline review is allowed only with verified equivalent host controls, or for
explicit inherit/default behavior or the documented managed-uncapped reviewer
base-role exception; otherwise the review blocks.
Within either tier, parallelism is expressed as plan metadata:
- Sequential (default): plans with no
oat_plan_parallel_groupsfield, or with an empty array. Phases run in plan order on the orchestration branch. - Parallel groups: phases listed together in
oat_plan_parallel_groupsrun concurrently in worktrees (Tier 1 only) and merge back to the orchestration branch in plan order. Groups themselves execute sequentially.
See Implementation Execution for the full execution model — tier detection, bounded fix loop, fan-in, merge-conflict handling, dry-run, and resumption.
Review receive behavior
oat-project-review-receivenow presents a findings overview before asking for any disposition decisions.- Findings are shown with stable IDs by severity (
C*,I*,M*,m*) so follow-up choices map clearly to specific items. - For each finding, the receive step summarizes the reviewer note, adds agent analysis, and gives a recommendation (convert now vs defer with rationale).
- When a scope reaches the three-cycle review cap, the receive step dispatches a complexity review and adds simplify to the dispositions the operator can choose. Every other budget exhaustion in the lifecycle (the orchestration retry limit, the final review cap, and a gate's
maxAttempts) runs the same review before escalating.
Alternate lifecycle lanes
Quick lane steps
oat-project-quick-start(adaptive discovery — provide a project name and optional description; if only the name is provided, quick-start asks for the missing description before discovery. Well-understood requests synthesize quickly, exploratory requests invest in solution space exploration. Before scaffolding, the skill checks inherited git state and asks whether to commit, proceed, or abort when the worktree is already dirty.)- Decision point: straight to plan, optional lightweight
design.md, or promote to spec-driven - Implement:
oat-project-implement(sequential by default; parallel whenoat_plan_parallel_groupsis declared) oat-project-review-provide/oat-project-pr-final- Optional
oat-project-promote-spec-drivento backfill spec-driven lifecycle artifacts in-place
Lite lane steps
oat-project-literuns one batched interview, authors a single-phaseplan.mdwith validation criteria, and pauses once for approval- Implement:
oat-project-implementruns the single phase without HiLL checkpoint prompts - Pass the mandatory final review, then route directly to
oat-project-pr-final - Optional
oat project promote <project-path> --to quickwhen the work no longer fits one sitting
Brief lane steps
oat-project-briefruns a design-aligned interview in readiness rounds, writes one Project Brief inplan.md(Goal, numbered Outcomes, Approach, Constraints and Out of Scope, Decisions, Known Unknowns, Delivery endpoint and authority, and## Phase pNN:blocks with Intent and Exit evidence), commits it, runs the independent artifact review and any configuredoat-project-briefgate, and asks for one approval- Implement:
oat-project-implementexecutes one phase-unit at a time (or a declared parallel group), opening### Task pNN-tNNexecution records inimplementation.mdas work happens and recording each phase's**Base:**and**Head:**anchors - A fresh independent review of each phase on its anchored range, then the final review, whose scope comes from the anchors; completion is audited against the brief's Outcomes
oat-project-pr-final, through the same post-implementation sequence as quick- Optional
oat project promote <project-path> --to quickwhen you want a maintained task plan instead
Goal lane steps
oat-project-goalruns the brief interview for the whole outcome, writes one Project Brief whose## Milestonestable assigns every phase to exactly one milestone (| m01 | p01, p02 |), runs the artifact review and any configuredoat-project-goalgate, asks for one approval, and activates the first milestone- Implement:
oat-project-implementexecutes the active milestone's phase-units as brief does, then runs the milestone closeout, whoseexitgate runs before the integrated review oat-project-review-providereviews the milestone ascode mNN: <ordered phases>;oat-project-review-receivemoves a clean review to deliveryoat-project-pr-progresschecks the evidence withoat project delivery check, registers the delivery (dNN) inoat_deliveries, and opens its pull requestoat-project-goalre-aligns atdelivered: it refreshes delivery observations, captures learnings, amends the brief with the next milestone, takes the amendment through review and approval, and activates it once the previous delivery reaches its agreed endpoint- Repeat from step 2 per milestone; when the user declares the goal met,
oat-project-goalrecords an exhaustive outcome audit,oat-project-pr-finalregisters terminal deliveries for any accepted phases no delivery covers, andoat-project-completecloses out once every accepted phase is covered - Optional
oat project promote <project-path> --to quickat a settled delivery boundary
Import lane steps
oat-project-import-plan(checks inherited git state before import scaffolding so sync-generated or unrelated dirty files do not silently roll into project bookkeeping)- Implement:
oat-project-implement(sequential by default; parallel whenoat_plan_parallel_groupsis declared) oat-project-review-provide/oat-project-pr-final- Optional
oat-project-promote-spec-drivento switch project mode to spec-driven lifecycle
Lane diagrams
Spec-Driven workflow lane
During the Design step, oat-project-design asks how to work through the document unless a mode was selected by argument, environment, or workflow.designMode. The three full-design choices are collaborative, selective collaborative, and draft-and-review.
Before a plan is marked ready for implementation, planning resolves the current
provider's dispatch policy from workflow.dispatchPolicy.mode and
workflow.dispatchPolicy.policy, or from project state.md frontmatter. The
legacy workflow.dispatchCeiling.providers.<provider> config and
oat_dispatch_ceiling frontmatter remain compatibility inputs for capped
managed policies. If no policy is configured and the session is interactive,
planning asks once and stores the answer as oat_dispatch_policy;
non-interactive planning with an unresolved policy is not implementation-ready
and blocks at the planning boundary until the resolver succeeds. Implementation
preflight retains the same defensive check, but it is not the first place an
unresolved plan fails. Uncapped is explicit managed selection with no maximum
cap; Inherit Host Defaults is separate and means OAT does not select model or
effort controls.
Quick lane
Quick lane lightweight design intentionally keeps a smaller collaborative/draft choice. Selective collaborative becomes available only after promotion into the full spec-driven design lane.
When a plan gate is configured, quick-start persists its outcome as
oat_quick_start_gate in project state (see
Gate approval records).
oat-project-next and oat-project-progress report that record; quick plan
readiness stays the only routing rule for quick plans.
Quick-start follows the same dispatch policy rule at the plan boundary: capture
the policy when interactive, persist oat_dispatch_policy to project state, and
avoid any mid-implementation policy prompt. Legacy dispatch-ceiling state is
still read as compatibility capped-policy input, but new quick-start selections
should use the dispatch-policy names, including explicit Uncapped and
Inherit Host Defaults.
Lite lane
Lite keeps planning and validation in plan.md. The interview selects a
minimal, product, technical, or both content shape and records the
rationale. Product Behavior is required for user-visible changes; Technical
Design is required for cross-module, data/state-format, or consumed-contract
changes. It has no separate discovery, spec, or design artifact, skips
implementation HiLL prompts, and routes a passed final review directly to PR
creation. Summary and documentation run only when enabled through the
lite-specific post-implementation sequence.
Each task chooses evidence proportionate to its risk instead of requiring one test-first recipe. Behavioral changes need a proof that fails without the change; refactors default to characterization-first when existing coverage is insufficient; documentation-only work may use formatting, link, spelling, or build checks. UI changes require visual proof. In autonomous runs, available computer-use capability performs that proof; otherwise execution stops at an explicit proof boundary.
Promoting a lite project to quick
When lite work outgrows one sitting, oat project promote <project-path> --to quick
converts it in place. Each artifact has a different fate: the authored lite plan
is moved to references/lite-plan.md, a new discovery.md is derived
from its five core sections plus any adaptive Product Behavior and Technical
Design, a fresh quick template takes over the plan.md path, and state.md
is rewritten to quick mode.
The project slug, directory, and branch are untouched, so history and any open
work continue uninterrupted. oat_ready_for is stamped on both discovery.md
and state.md; the quick-start recommender reads artifact readiness, so
consumers must preserve both. Promotion refuses rather than half-applying: a
non-lite project, an existing references/lite-plan.md, invalid authored
sections, an unresolved scope, or an unreadable template each return a stable
categorical reason and exit non-zero. See
CLI Reference for the full refusal contract.
Brief lane
A brief project has one authored artifact: the Project Brief in plan.md.
Each ## Phase pNN: block is one phase-unit with **Intent:**,
**Exit evidence:**, and **Provisional:** lines; only the next phase must
be concrete, and the agent may add, split, or reorder phases inside the
approved outcomes, constraints, and authority. Progress counts phase-units, and
a phase counts as complete only when the root writes **Status:** completed
under it in implementation.md after its review and any selected gate settle.
Tasks are execution records written as work happens, never a plan, so they
never change progress totals.
Each phase records **Base:** before work starts and **Head:** when its work
ends. Reviews take their range from those anchors rather than from commit
messages; invalid or contradictory anchors stop and route to
oat-project-reconcile. A fix after a later phase has started becomes an
appended p-revN revision phase. The shared rules live in the bundled brief
contract (oat-project-brief/references/brief-contract.md).
Promoting a brief project to quick
oat project promote <project-path> --to quick converts a brief in place, and
there is no reverse direction. Accepted phases keep their completed execution
records as quick tasks (or get one synthesized Accepted via phase evidence
task against the phase head), active phases keep their completed records, and
pending or provisional phases stay taskless. The command lists the phases that
still need tasks in oat_promotion_pending_phases, and quick plan readiness
stays false until oat-project-quick-start authors them. The brief's
sections are rendered into discovery.md and the original is archived to
references/brief-archive.md.
Promotion writes nothing and refuses with a categorical reason when
references/brief-archive.md already exists (brief-archive-exists), a
journal phase is extracted (extracted-phases), the brief has no parseable
phases (invalid-brief-plan), or an accepted phase has neither a completed
record nor a **Head:** anchor to synthesize from (missing-phase-head, which
lists the refused phases).
Goal lane
A goal project is a brief project delivered in milestones. The Project Brief
carries a ## Milestones table (| Milestone | Phases |) in which every
phase, including appended p-revN revision phases, belongs to exactly one
milestone; oat project validate-plan reports membership errors as goal-
codes. Each milestone is approved through its own plan gate carrier in
state.md (oat_milestone_gates.mNN.plan): the first approval also marks
plan.md complete, and every later amendment is approved only by the next
milestone's carrier.
Milestone delivery. For goal the end of the brief ladder is reordered: the
milestone's exit gate runs at closeout before the integrated review, and
queued fixes invalidate both, so the gate runs again before the next review.
The integrated review names its milestone (or delivery) and the exact ordered
phase set, for example code m01: p01, p02, p-rev1; that set is never derived
from a first–last range. oat-project-pr-progress registers a delivery only
when oat project delivery check --subject <mNN|dNN> reports status: ok,
writing the oat_deliveries entry (registering) before it creates the pull
request so an interrupted run resumes by gh pr list instead of opening a
duplicate.
Freshness. Evidence keeps the revision actually reviewed. Commits after it
count as bookkeeping only when they touch the project's tracking files in
permitted ways (routing, progress, evidence, project-log appends); a code
change, an edit to approved brief content such as Outcomes or a phase's Intent,
or a substantive change followed by its revert stales the delivery.
oat project delivery refresh observes each member pull request with
gh pr view and records staleness; it never writes milestone status or
recovery. Because the project branch is the delivery's head branch, do not
push a brief amendment while that delivery is still open.
Recovery. Stale evidence on the active milestone's delivery returns it to
reviewing. Fixes or inline feedback for an older milestone open an
oat_goal_recovery record targeting that milestone and delivery, scheduling a
p-revN phase in its row, while the active milestone, its status and the
execution pointer stay untouched.
Re-alignment and the end. At delivered, oat-project-goal refreshes the
observations, writes one learnings entry, amends the brief with the next
milestone, and runs the review, gate and approval for the amendment; it may do
all of that while a merged endpoint is pending, but it activates the next
milestone only once refresh observes the previous delivery at its endpoint.
When the user declares the goal met, the declaration is recorded in
implementation.md and state.md gets oat_goal_status: declared_met and an
exhaustive outcome audit: every phase accepted, extracted, deferred or
retired, every numbered outcome bound to its exact text. Terminal closeout
requires the declaration, the audit and delivery coverage of every accepted
phase; oat-project-pr-final registers one terminal delivery per milestone
that still has uncovered phases, all sharing the head branch's pull request.
oat-project-complete then opens no further pull request, even with
workflow.createPrOnComplete: true, because the deliveries already cover the
work.
Promoting a goal project to quick
oat project promote <project-path> --to quick accepts a goal project only at
a settled delivery boundary: the active milestone is delivered, every
registry entry is at_endpoint or superseded, and no recovery is pending.
It otherwise refuses without writing, with goal-milestone-active,
goal-recovery-pending, or goal-delivery-unsettled (which lists the open or
registering deliveries, and also covers an empty registry). A settled goal
promotes like a brief, and the archive references/brief-archive.md carries
the delivery history (registry, milestone gates and outcome audit) after the
original brief. oat-project-quick-start resumes the promoted project.
Import lane
Capture lane
Retroactive project creation for work done outside the OAT project workflow. Common scenario: mobile/cloud sessions where you brainstorm and implement with an agent, then want to open a PR and review from your desktop.
Entry point: /oat-project-capture (skill-only, no CLI command — requires agent conversation context).
Key differences from other lanes:
- No plan generation — the work is already done; the scaffold-created
plan.mdtemplate is kept but not authored - Discovery from conversation —
discovery.mdcaptures intent and decisions from the agent's conversation context, not from requirements analysis - Implementation from commits —
implementation.mdis populated from commit history with SHAs, not from executing plan tasks - Lifecycle state is user-chosen — user decides whether the project is ready for review or still in progress
Artifact progression
discovery.md -> spec.md -> design.md -> plan.md -> implementation.md -> summary.md
Quick lane progression:
discovery.md -> [design.md (optional lightweight)] -> plan.md -> implementation.md
Lite lane progression:
plan.md -> implementation.md -> pr/*.md (summary.md and documentation are opt-in)
Import lane progression:
references/imported-plan.md -> plan.md -> implementation.md (spec.md/design.md optional)
Capture lane progression:
discovery.md (from conversation) + implementation.md (from commits) — no forward-looking artifacts
Operational rules
- Keep
state.md,plan.md, andimplementation.mdsynchronized. - For a synced project, publish lifecycle artifact writes with
oat project push; do not stage.oat/projects/synced/<project>/on the parent branch. - On arrival, run
oat project pullbefore reading a synced project's state. - Stop at configured HiLL checkpoints.
- Do not move lifecycle forward when required review gates are unresolved.
- Project entry skills (
oat-project-new,oat-project-quick-start, andoat-project-import-plan) surface inherited dirty git state before scaffolding. If the dirty list includes.oat/sync/manifest.json,.claude/,.cursor/, or.codex/, the skill calls out that those paths are typically sync output and offers Commit now, Proceed anyway, or Abort.
Reducing lifecycle friction with workflow preferences
The lifecycle has several interactive prompts that power users often answer the same way every time — HiLL checkpoint behavior, archive on complete, auto-create PR, post-implementation chaining, final review execution model, and re-review scope narrowing. These can be configured once via workflow.* preference keys and respected automatically by skills.
See the Workflow preferences section in the Configuration guide for the full list of keys and how to set them. Workflow preferences resolve through repo-local > repo-shared > user > default; there is no generic workflow environment layer. Individual skills may separately read environment controls such as OAT_DESIGN_MODE. Set personal defaults at user scope and override per-repo when needed.
Active project resolution
- Active project state is stored in
.oat/config.local.json(activeProject, repo-relative path). - Projects root is stored in
.oat/config.json(projects.root) and can be read viaoat config get projects.root. - Workflow skills prefer
oat config get activeProject/oat config get projects.rootrather than reading pointer files directly.
Capability availability versus repository adoption
Lifecycle skills that touch repository project-management state make two separate checks, and both must hold before any PJM write:
- Capability availability —
oat tools has project-managementanswers whether the PJM skills and templates are installed and complete at project or user scope. Since packs default to user scope, this is usually satisfied by a user-scope install with no repository footprint. - Repository adoption —
oat pjm doctor --jsonanswers whether this repository adopted PJM. Branch on itsadoption.statefield:declaredandinferred-legacyallow repository PJM writes;partial-initializationandnonestop withoat pjm initas the recovery.
Pack presence is never treated as evidence of repository adoption. A skill that
finds the capability available but the repository unadopted reports the
actionable oat pjm init stop instead of scaffolding implicitly. See
Install vs. initialize.
Brainstorming integration with the project lifecycle
oat-brainstorm (in the brainstorm tool pack) interacts with the project lifecycle in two distinct ways: it can seed a brand new project from a brainstorming conversation when no project is active, or fold back into an active project when one is.
Seeding a new project from a brainstorm
When the brainstorming destination is "promote to a new OAT project", the dispatcher confirms a project slug and one of five modes: lite, brief, goal, quick, or spec-driven. For Quick and Spec-Driven projects, it runs oat project new <slug> --mode <mode> and writes discovery.md directly from the brainstorming payload — Initial Request, Solution Space with approaches considered, Chosen Direction, Key Decisions, and Open Questions. It writes only discovery.md (never a partial design.md), then points to oat-project-quick-start or oat-project-design without auto-chaining. For Lite projects, it instead seeds the five sections in plan.md, leaves discovery.md and design.md absent, and points to oat-project-lite. For Brief projects, it writes the payload to a research note under references/research/, leaves the scaffolded plan.md for the brief interview, and points to oat-project-brief. Goal projects arrive the same way and point to oat-project-goal, which authors the brief and its milestone split.
This is a parallel entry path into all five lanes, not a new lane. Quick and Spec-Driven users arrive at oat-project-quick-start or oat-project-design with discovery already populated; Lite users arrive at oat-project-lite with the single-phase plan already seeded; Brief and goal users arrive at oat-project-brief or oat-project-goal with the brainstorm payload saved as a research note under references/research/ and the scaffolded plan.md left for the interview.
Folding back into an active project
When oat-brainstorm fires while a project is active, it offers a 3-way picker before any pack-filtered destination shows up:
- Related to the project → for Lite, fold the synthesis into
plan.mdimmediately above## Phase 1and hand off tooat-project-lite; for Brief, fold it intoplan.mdimmediately above the first## Phaseheading so the receiving skill integrates it as new or amended phases; Goal folds intoplan.mdthe same way, never editing the## Milestonestable, and hands off tooat-project-goal(oroat-project-implementinside the active milestone's approved scope); for Quick and Spec-Driven, use the most-specific upstream artifact (design.mdif it exists, otherwisediscovery.md) and hand off tooat-project-quick-startoroat-project-plan. Any mode with an open PR hands off tooat-project-revise. The fold-back commit is safety-gated: a preflightgit status --porcelain -- "$ARTIFACT_PATH"checks for dirty state, staging is exactlygit add -- "$ARTIFACT_PATH"(never-A, never globs), and the handoff prompt only prints after the scoped commit succeeds. - Independent of the project → the active project is acknowledged but doesn't constrain the picker; brainstorm routes through its standard pack-filtered terminal-state options (new project, backlog item, idea, doc-to-path, inline).
- Related but supplementary → write a brainstorming reference file at
.oat/projects/<scope>/<project>/brainstorming/YYYY-MM-DD-<topic>.md, alongsidepr/andreviews/. No lifecycle artifact is touched.
The fold-back path is what makes "we got to plan and realized the design missed something" recoverable mid-project: the upstream artifact gets updated and committed cleanly, then the user re-runs plan authoring with a "don't refresh, integrate" context that preserves review-table state.
Reference artifacts
.oat/projects/<scope>/<project>/spec.md.oat/projects/<scope>/<project>/design.md.oat/projects/<scope>/<project>/plan.md.oat/projects/<scope>/<project>/implementation.md
Choosing lifecycle controls
OAT has four separate controls that are easy to confuse. Each one adds a different kind of check:
- Planning checkpoints hold a spec-driven project after discovery and after design until a person approves.
- Implementation checkpoints (HiLL checkpoints) pause implementation after chosen phases until a person approves.
- Artifact review loops have the same agent session check a generated plan or analysis and fix clear problems before handing it on.
- Gates send the work to a second agent CLI, preferably running a different family of models, and turn its findings into a pass or a fail.
None of these replaces the code reviews that run after every implementation phase and before closeout; those run whatever you choose here.
Decide in this order: first the workflow mode, then the design interaction mode, then the checkpoint frequency.
- If your team needs to approve the architecture before any code is written, choose a spec-driven project for its planning checkpoints, or add a gate to a planning skill.
- If you want to steer implementation after risky phases, choose implementation checkpoints for those phases.
- If a plan or analysis will be handed to another workflow, keep its artifact review loop on.
- If a high-risk change needs a reviewer from a different model family, add a gate and check which reviewer it actually used. Adding more reviews makes a run slower; it does not by itself make them independent.