<!--
  AUTO-GENERATED from scripts/lib/sdd-utils.js (DESIGN_DOC_RULES, SPEC_HEADER_RULES)
  and scripts/lib/sdd-rules.js (DECISION_LOG_RULES, PENDING_CONFLICT_RULES,
  VISION_RULES, DECISION_LEDGER_RULES).
  Do NOT edit this file by hand. To change the schema, edit the source constant in
  the corresponding module and regenerate:

    node scripts/lib/print-schema.js design            --markdown > scripts/lib/sdd-schemas/design.md
    node scripts/lib/print-schema.js spec              --markdown > scripts/lib/sdd-schemas/spec.md
    node scripts/lib/print-schema.js decision-log      --markdown > scripts/lib/sdd-schemas/decision-log.md
    node scripts/lib/print-schema.js pending-conflict  --markdown > scripts/lib/sdd-schemas/pending-conflict.md
    node scripts/lib/print-schema.js vision            --markdown > scripts/lib/sdd-schemas/vision.md
    node scripts/lib/print-schema.js decision-ledger   --markdown > scripts/lib/sdd-schemas/decision-ledger.md

  tests/scripts/sdd-schemas-fresh.test.js asserts this file stays in sync with the
  source — a stale copy will fail CI.
-->

# decision-log Schema

Canonical path: `<brainstorming-output-dir>/decision-log.<ext>`

The file lives inside brainstorming's date-stamped output directory
(`docs/plans/<spec-id>/<YYYY-MM-DD>[-suffix]/`). The wire format (YAML, strict
markdown table, etc.) is a deliberately unspecified implementation choice — pinning
the format in the contract would over-constrain the implementation and freeze a
swappable detail. The contract is the field shape and machine-parseability.

## Required Fields per Row

All four fields MUST be present in every Q&A row. Missing any one field is an ERROR.

| Field | Type | Description |
|---|---|---|
| `q_id` | string | Stable identifier, unique within a single brainstorming session. Refiner Phase 6 looks up rows by q_id for deterministic citation without LLM re-interpretation. |
| `question` | string | The question text the brainstormer asked the user. Used for context when refiner cites a row. |
| `user_answer_verbatim` | string | Verbatim user answer (no paraphrasing). Refiner Phase 6 cites this content directly; paraphrasing would introduce LLM judgment into what is meant to be a mechanical lookup. |
| `deferral_signal` | boolean | True iff user_answer_verbatim matches a canonical deferral phrase (case-insensitive, trimmed). Refiner MUST NOT treat a deferred axis as authorization for a concrete MUST (fr-rf-013). |

## q_id Uniqueness Rule

`q_id` unique per brainstorming session; duplicate q_id within a session is ERROR.

## Row Addressability

Rows MUST be addressable by `q_id`. Lookup is a deterministic
operation on the parsed structure — no LLM re-interpretation. Refiner's Phase 6
mechanical authorization check iterates over every `<trace>` element citing a Q&A
row by `q_id` and verifies the cited content appears in that row's
`user_answer_verbatim`.

## Deferral-Signal Canonical Phrases

When `user_answer_verbatim` matches any of the following phrases (case-insensitive,
trimmed), `deferral_signal` MUST be set to `true`:

- `use defaults`
- `covered.`
- `skip`
- `you decide`

Additional phrases MAY be recognized by implementations. The list above is the minimum
required set per `fr-cc-if-008-ac4`.

## Examples

The schema-shape examples below illustrate the field contract. The wire format (YAML shown here) is one of several permitted choices; the contract is the field shape, not the wire encoding.

### Valid example

Three Q&A rows with distinct `q_id`s, mixing `deferral_signal=true` and `deferral_signal=false`:

```yaml
- q_id: q1
  question: "Which auth provider should the v2 spec target?"
  user_answer_verbatim: "Auth0 — we already have an org account."
  deferral_signal: false

- q_id: q2
  question: "Should refresh tokens rotate on every use?"
  user_answer_verbatim: "use defaults"
  deferral_signal: true

- q_id: q3
  question: "What is the session inactivity timeout?"
  user_answer_verbatim: "30 minutes."
  deferral_signal: false
```

### Invalid examples

1. Duplicate `q_id` within a session — `q1` reused for two different questions. Error: "duplicate q_id within a brainstorming session is ERROR" (per `q_id_uniqueness`).

```yaml
- q_id: q1
  question: "First question."
  user_answer_verbatim: "Answer A."
  deferral_signal: false

- q_id: q1   # ← duplicate; MUST be q2
  question: "Second question."
  user_answer_verbatim: "Answer B."
  deferral_signal: false
```

2. Missing `deferral_signal` field. Error: "decision-log row missing required field: deferral_signal".

```yaml
- q_id: q1
  question: "Should we cache?"
  user_answer_verbatim: "yes, redis"
  # deferral_signal omitted ← ERROR
```

3. Missing `user_answer_verbatim` field. Error: "decision-log row missing required field: user_answer_verbatim".

```yaml
- q_id: q1
  question: "Should we cache?"
  # user_answer_verbatim omitted ← ERROR
  deferral_signal: false
```

## Enforcement Authority

`scripts/lib/sdd-rules.js` — `DECISION_LOG_RULES` is the canonical source of truth
(re-exported via `scripts/lib/sdd-utils.js` for facade access). Validators built in
`fr-sd-014` read from that constant. If this document disagrees with the constant,
the constant wins and this document is wrong (file a bug).
