---
phase: 3
slug: server-documentation-schemas
status: draft
nyquist_compliant: false
wave_0_complete: false
created: 2026-05-03
---

# Phase 3 — Validation Strategy

> Per-phase validation contract for feedback sampling during execution.

---

## Test Infrastructure

| Property | Value |
|----------|-------|
| **Framework** | vitest 4.1.5 (per Phase 1/2 tool convention) |
| **Config file** | `tools/protocol-doc/vitest.config.ts`, `tools/save-format-doc/vitest.config.ts` (Wave 0 installs) |
| **Quick run command** | `pnpm -C tools/protocol-doc test` / `pnpm -C tools/save-format-doc test` |
| **Full suite command** | `pnpm test` (workspace root, runs all tool tests + lint-adr + lint-parity-checklist + verify subcommands) |
| **Estimated runtime** | ~30 seconds |

---

## Sampling Rate

- **After every task commit:** Run `pnpm -C <tool> test` for the modified tool, or `pnpm lint:adr` / `pnpm lint:parity-checklist` for doc-only commits
- **After every plan wave:** Run `pnpm test` (full workspace suite)
- **Before `/gsd-verify-work`:** Full suite must be green AND `pnpm -C tools/protocol-doc verify` AND `pnpm -C tools/save-format-doc verify` (re-emit deterministically and diff = empty)
- **Max feedback latency:** 30 seconds

---

## Per-Task Verification Map

> Filled by gsd-planner during planning. One row per task. `command` must be deterministic and runnable from repo root. Wave 0 marks the row when the file does not yet exist.

| Task ID | Plan | Wave | Requirement | Threat Ref | Secure Behavior | Test Type | Automated Command | File Exists | Status |
|---------|------|------|-------------|------------|-----------------|-----------|-------------------|-------------|--------|
| 3-01-01 | 01 | 1 | SDOC-01 (wiki errata) | — | N/A | doc-lint | `pnpm lint:wiki-errata` | ❌ W0 | ⬜ pending |
| 3-02-01 | 02 | 1 | SDOC-02 | — | N/A | unit | `pnpm -C tools/protocol-doc test` | ❌ W0 | ⬜ pending |
| 3-02-02 | 02 | 1 | SDOC-02 | — | N/A | regen | `pnpm -C tools/protocol-doc verify` | ❌ W0 | ⬜ pending |
| 3-03-01 | 03 | 1 | SDOC-03 | — | N/A | unit | `pnpm -C tools/save-format-doc test` | ❌ W0 | ⬜ pending |
| 3-03-02 | 03 | 1 | SDOC-03 | — | N/A | regen | `pnpm -C tools/save-format-doc verify` | ❌ W0 | ⬜ pending |
| 3-04-01 | 04 | 3 | SDOC-01 | — | N/A | doc-lint | `pnpm lint:subsystem-mds` | ❌ W0 | ⬜ pending |
| 3-05-01 | 05 | 4 | SDOC-06 | T-3-05 (silent-feature drop) | every legacy feature classified `present` / `deferred` / `rejected-with-reason` | doc-lint | `pnpm lint:parity-checklist` | ❌ W0 | ⬜ pending |
| 3-06-01 | 06 | 4 | SDOC-03, SDOC-04 | T-3-06 (drift between grammar + schema) | schema column-set traces row-for-row to a save-format-doc row | unit | `pnpm -C tools/db-schema test` | ❌ W0 | ⬜ pending |
| 3-06-02 | 06 | 4 | SDOC-04 | — | N/A | migration | `pnpm -C tools/db-schema drizzle-kit generate --check` | ❌ W0 | ⬜ pending |
| 3-07-01 | 07 | 5 | SDOC-04 | — | N/A | adr-lint | `pnpm lint:adr` | ✅ (Phase 2) | ⬜ pending |
| 3-08-01 | 08 | 6 | SDOC-05 | — | N/A | adr-lint | `pnpm lint:adr` | ✅ (Phase 2) | ⬜ pending |
| 3-09-01 | 09 | 7 | SDOC-01..06 | — | N/A | gate | `pnpm verify:phase-3` (composite: regen verify + lint suite + parity-checklist green) | ❌ W0 | ⬜ pending |

*Status: ⬜ pending · ✅ green · ❌ red · ⚠️ flaky*

> Planner MUST refine these rows once the actual task IDs are emitted. The shape above reflects the 9-plan layout from RESEARCH.md §Plan Layout.

---

## Wave 0 Requirements

- [ ] `tools/protocol-doc/` — vitest scaffold, fixture GML snippet, `verify` subcommand
- [ ] `tools/save-format-doc/` — vitest scaffold, fixture `file_text_*` GML snippet, `verify` subcommand
- [ ] `tools/db-schema/` — drizzle-kit + better-sqlite3 install, vitest config (per CLAUDE.md hard rule #6 + D-21: no new TS outside `tools/` before Phase 4)
- [ ] `scripts/lint-wiki-errata.mjs` — fails build when `decomp/wiki/16-bno-bnb-notes.md` mentions `file_bin_*` without `file_text_*` correction
- [ ] `scripts/lint-subsystem-mds.mjs` — fails build when any `docs/extracted-server/*.md` lacks the required frontmatter (subsystem, scripts, opcodes-ref, save-formats-ref)
- [ ] `scripts/lint-parity-checklist.mjs` — fails build when any row has `disposition` outside `{present, deferred, rejected-with-reason}` or missing `subsystem`/`reason` fields
- [ ] `scripts/verify-phase-3.mjs` — composite gate runs all the above + tool `verify` subcommands, returns non-zero on any drift

*Existing Phase 2 `lint-adr` is reused unchanged for the two new ADRs.*

---

## Manual-Only Verifications

| Behavior | Requirement | Why Manual | Test Instructions |
|----------|-------------|------------|-------------------|
| Opcode-table completeness sanity-check | SDOC-02 | LLMs cannot enumerate "every opcode" without missing branches; reviewer must sample 5 opcodes and trace them back to script:line | Pick 5 opcode rows at random from `docs/extracted-server/protocol/opcodes.md`; for each, open the cited GML script at the cited line and confirm the `write*`/`read*` sequence matches |
| Parity-checklist completeness review | SDOC-06 | Silent-feature drop is the dominant phase risk; manual review surfaces things the lint cannot (missing rooms, NPC dialog branches, secret commands) | Cross-read `docs/extracted-server/parity-checklist.md` against `extracted/server-5-4/scripts/` directory listing and `docs/extracted-engine/` Phase 2 inventory; flag any subsystem with no rows |
| Canonical-snapshot ADR — divergence accepted | SDOC-05 | Picking the canonical revision is a judgment call (which snapshot we trust); reviewer confirms the rationale is accurate | Read ADR 0003; confirm the divergence examples cited match what is actually in `legacy/open-source-release/` vs older revisions |

---

## Validation Sign-Off

- [ ] All tasks have `<automated>` verify or Wave 0 dependencies
- [ ] Sampling continuity: no 3 consecutive tasks without automated verify
- [ ] Wave 0 covers all MISSING references
- [ ] No watch-mode flags (CI must exit, not hang)
- [ ] Feedback latency < 30s
- [ ] `nyquist_compliant: true` set in frontmatter

**Approval:** pending
