Workflow

Planning

Writing effective specs

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

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

In planning mode, the agent reads the project-owned .scafld/prompts/plan.md template and 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

SizeScopePhasesWhen to use
microSingle file, mechanical change1Rename, typo fix. Rarely needs a spec.
small2-3 files, well-understood change1-2Add a utility, fix a bug.
mediumMultiple files, some design decisions2-4New feature, refactor.
largeCross-cutting, architectural impact4+Migration, new subsystem.

Writing objectives

Objectives are outcomes, not activities:

# 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

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.

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

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

## 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

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

## 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 level determines the default validation profile:

RiskDefault profileWhat it runs
lowlightCompile check + acceptance criteria
mediumstandard+ full test suite, linter, typecheck, security scan
highstrict+ per-phase boundary checks

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

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 interrogates the draft one question at a time, walking down the design tree and resolving upstream decisions before downstream ones. If a question can be answered by exploring the codebase, it should inspect the code instead of asking. 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 optional and operator-driven. scafld approve does not require it. Run it on high-risk or ambiguous specs; skip it on trivial or well-understood ones. See CLI reference for flags.