# Planning {#planning}


The spec is the most important artifact in the scafld workflow. A bad spec produces bad work regardless of how capable the agent is.


## Anatomy of a good spec {#anatomy-of-a-good-spec}


A spec answers five questions:

1. **What** are we building? (objectives)
2. **Why** are we building it? (summary, context)
3. **Where** does it change? (scope, files_impacted, touchpoints)
4. **How** do we know it works? (acceptance criteria)
5. **What must not break?** (invariants, out_of_scope)

If any of these are vague, the spec isn't ready.


## The planning loop {#the-planning-loop}


In planning mode, the agent follows the bundled planning contract unless the
project has added its own `.scafld/prompts/plan.md` override. It then runs a
structured exploration cycle:

1. **THOUGHT** -- interpret the request in repo terms, identify unknowns
2. **ACTION** -- search the codebase, read files, check diffs
3. **OBSERVATION** -- capture what was learned
4. **THOUGHT** -- update the spec, ask clarifying questions
5. **REPEAT** until all required fields are filled

The agent is in read-only mode during planning. It can explore anything but change nothing outside `.scafld/specs/`. If blocked by uncertainty, it leaves the spec as `status: draft` and records the unanswered question in the planning log or the latest harden round.

`scafld plan <task-id>` creates the draft. Run `scafld harden <task-id>` after
the draft is filled in to interrogate the contract before approval.


## Task sizing {#task-sizing}


| Size | Scope | Phases | When to use |
|------|-------|--------|-------------|
| `micro` | Single file, mechanical change | 1 | Rename, typo fix. Rarely needs a spec. |
| `small` | 2-3 files, well-understood change | 1-2 | Add a utility, fix a bug. |
| `medium` | Multiple files, some design decisions | 2-4 | New feature, refactor. |
| `large` | Cross-cutting, architectural impact | 4+ | Migration, new subsystem. |


## Writing objectives {#writing-objectives}


Objectives are outcomes, not activities:

```yaml
# Bad: describes activity
objectives:
  - "Refactor the auth module"

# Good: describes outcomes
objectives:
  - "Auth module uses stateless JWT instead of session cookies"
  - "All auth endpoints return standard error envelope on failure"
```

Each objective should be independently verifiable.


## Defining scope {#defining-scope}


Scope is a contract. In-scope items will change. Out-of-scope items will not be touched. This is what makes adversarial review concrete instead of vibe-based.

```yaml
scope:
  in_scope:
    - "JWT middleware in src/middleware/"
    - "Login and refresh endpoints in src/routes/"
  out_of_scope:
    - "User model or database schema"
    - "Frontend authentication flow"
```


## Phasing work {#phasing-work}


Each phase has its own acceptance criteria, so partial progress is measurable. Dependencies between phases enforce ordering.

````md
## Phase 1: Token generation

Goal: JWT creation and signing.

Status: pending
Dependencies: none

Changes:
- `src/auth/token.ts` — sign and verify JWTs using RS256.

Acceptance:
- [ ] `ac1_1` test: Token round-trips correctly.
  - Command: `npm test -- --grep 'token'`
  - Expected kind: `exit_code_zero`
  - Status: `pending`

## Phase 2: Auth middleware

Goal: Request validation pipeline.

Status: pending
Dependencies: phase1
````


## The planning log {#the-planning-log}


Records decisions made during spec creation. Uses a structured format:

````md
## Planning Log

- 2026-04-16T10:00:00Z - agent - Chose RS256 over HS256 for token signing.
  - Notes: Asymmetric keys allow verification without exposing the signing key.
````


## Risk assessment {#risk-assessment}


Risk level determines the default validation profile:

| Risk | Default profile | What it runs |
|------|----------------|--------------|
| `low` | `light` | Compile check + acceptance criteria |
| `medium` | `standard` | + targeted tests for changed surfaces, linter/typecheck/security checks when relevant |
| `high` | `strict` | + broader integration, boundary, or full-suite evidence when the changed surface warrants it |

Build acceptance should prove the task without turning every phase into a
repository-wide regression run. Prefer focused commands tied to the changed
files and workflows. Keep full-suite commands for release gates, pre-commit
checks, shared framework changes, or explicit operator requests.


## Common mistakes {#common-mistakes}


**Specs that are too vague.** "Improve performance" with no metrics. If the agent can interpret the objective three different ways, the spec has failed.

**Specs that are too prescriptive.** Dictating exact implementations line by line defeats the purpose. Specify the contract, not the algorithm.

**Skipping out_of_scope.** Without explicit boundaries, the agent will "helpfully" refactor adjacent code.


## Hardening {#hardening}


When a spec is finished but you want to stress-test it before approval, run `scafld harden <task-id>`. This enters HARDEN MODE: the agent challenges design and scope first, then audits paths, commands, acceptance timing, and rollback or repair shape. The design challenge asks why the plan exists, what underlying product or system problem it solves, which shared core/app contract owns the behavior, and whether API/MCP/CLI/provider/docs surfaces stay light adapters instead of separate implementations. If a question can be answered by exploring the codebase, the agent should inspect the code instead of asking. Harden records findings as observations. Open `blocks`, non-keep shape decisions, and required spec edits keep that harden round in `needs_revision`; advisories remain recorded without forcing another round. Provider-backed harden refuses another same-revision pass until the draft contract changes, but approval remains an explicit operator decision: revise true shape blockers, or run `scafld approve <task-id> --reason <reason>` when a finding is rejected as bookkeeping/advisory or overengineering. Harden is not a coverage matrix: once the spec names the governing invariant, shared owner, read model, chokepoint, and boundary that make behavior apply by construction, per-surface correctness belongs to build evidence and review unless a missing surface breaks that design. When the contract is sharp enough to execute, run `scafld harden <task-id> --mark-passed`. The round is recorded in `harden_rounds` for audit.

Hardening is operator-driven. A draft with no harden round can be approved, but
approving over incomplete, stale, failed, or `needs_revision` harden evidence
requires `--reason` and records the decision as `overridden`. Run harden on
high-risk or ambiguous specs; skip it on trivial or well-understood ones. See
[CLI reference](https://auscaster.com/scafld/docs/cli-reference.md#harden) for flags.
