# Lifecycle {#lifecycle}


scafld keeps workflow state visible in the filesystem and durable in the
session ledger. Specs move through `.scafld/specs/`; runtime evidence lives
under `.scafld/runs/`.


## States {#states}


| Status | Directory | Description |
|--------|-----------|-------------|
| `draft` | `drafts/` | Spec is being written and hardened. |
| `approved` | `approved/` | Human accepted the contract. Ready to execute. |
| `active` | `active/` | A build phase is open or phase evidence is being recorded. |
| `blocked` | `active/` | Attempted build evidence found a blocking failure. |
| `review` | `active/` | Work reached the adversarial review gate. |
| `completed` | `archive/YYYY-MM/` | Review passed and work was archived. |
| `failed` | `archive/YYYY-MM/` | Work was explicitly failed. |
| `cancelled` | `archive/YYYY-MM/` | Work was abandoned before completion. |

Typical path:

```text
draft -> approved -> active -> review -> completed
```

Hardening is tracked separately with `harden_status` so it can be repeated and
audited without inventing another lifecycle directory.


## Commands {#commands}


```bash
scafld plan add-auth
scafld harden add-auth
scafld harden add-auth --mark-passed
scafld validate add-auth
scafld approve add-auth
scafld build add-auth
# for manual acceptance, use the build command printed by handoff
scafld build add-auth --criterion <id> --disposition pass --evidence-digest <sha256> --actor <actor> --reason "what was verified"
# implement the opened phase, then repeat build until review
scafld build add-auth
scafld review add-auth
scafld finalize add-auth
```

`scafld review add-auth` is the provider/model gate. After it passes,
`scafld finalize add-auth` consumes the accepted review, runs acceptance against
deterministic tree facts, mints a signed receipt, archives the canonical spec,
and records completion. Finalize does not invoke a model. `scafld verify
<receipt> --target <commit-ish>` then replays the receipt as the CI merge wall.
See [CLI Reference](https://auscaster.com/scafld/docs/cli-reference.md) for the legacy `complete` command.

Failure paths:

```bash
scafld fail add-auth --reason "acceptance cannot be satisfied"
scafld cancel add-auth --reason "replaced by narrower task"
```


## Filesystem State {#filesystem-state}


```text
.scafld/specs/
  drafts/
  approved/
  active/
  archive/
    2026-05/
```

The directory a spec lives in matches its lifecycle status. You should be able
to answer "what is in flight?" with:

```bash
ls .scafld/specs/active
```


## Evidence Ordering {#evidence-ordering}


When a command changes runtime state, scafld writes the session first and then
projects the current state back into the Markdown spec.

That gives scafld one authority rule:

- session is the durable evidence source
- spec is the readable contract plus current projection
- handoff is transport for the next model voice

If the spec projection and session ever disagree, reconciliation should rebuild
the projected state from session evidence.


## Hardening {#hardening}


`harden_status` values:

- `not_run`
- `in_progress`
- `passed`
- `needs_revision`
- `overridden`
- `error`

`scafld harden <task-id>` opens a harden round while the spec is still a draft.
The active prompt asks the agent to record evidence-backed observations for
design, scope, paths, commands, acceptance timing, and rollback or repair shape.
Design comes first: the round should challenge shared ownership and keep
API/MCP/CLI/provider/docs surfaces as light adapters over common behavior. The
round is bound to the draft digest, so repeating harden without changing the
draft reuses or blocks on the existing round instead of stacking new rounds.
`scafld harden <task-id>
--mark-passed` verifies dimension coverage, anchors, and unresolved blocking
observations before recording that the draft survived hardening. Missing
dimensions, open blocking observations, and unresolved citations keep harden
not-ready and leave the round open.

Approving over incomplete, stale, failed, or `needs_revision` harden evidence
requires `scafld approve <task-id> --reason <reason>`. scafld records that
operator decision as `overridden`; real shape blockers should be fixed in the
draft and hardened again.

Approval remains explicit. Hardening makes the approval decision worth trusting.


## Review Gate {#review-gate}


`scafld review` moves work to the review gate and writes the challenger verdict.
`scafld finalize` refuses to archive until the latest review verdict is `pass`.

That separation is the core product stance: execution tries to finish the work;
adversarial review tries to break confidence in the work.


## Queries {#queries}


```bash
scafld status add-auth
scafld status add-auth --json
scafld status add-auth --json --no-context
scafld list
scafld list --json
scafld report
```

`status --json` is the right integration surface for wrappers. It reports the
current lifecycle state, next allowed follow-up command, and task material
projection without requiring the wrapper to scrape Markdown or invent a separate
change manifest. Agent entry should read full status or handoff once. Follow-up
polling can use `--no-context` after the same `spec_source.sha256` is already in
context; scafld keeps source path, digest, and byte count while omitting only the
markdown body.
