---
phase: 03-server-documentation-schemas
verified: 2026-05-04T12:00:00Z
status: human_needed
score: 6/6 must-haves verified
overrides_applied: 0
re_verification:
  previous_status: gaps_found
  previous_score: 5/6
  gaps_closed:
    - "Phase 4 packages/protocol/ can import tools/protocol-doc/output/protocol.ts verbatim under TypeScript strict mode"
  gaps_remaining: []
  regressions: []
human_verification:
  - test: "Run scripts/verify-phase-3.mjs end-to-end on a Linux (ubuntu-latest) host with LF line endings"
    expected: "All 14 steps exit 0; final 'verify-phase-3: OK (14 steps green)' message"
    why_human: "Plan 09 SUMMARY explicitly defers canonical proof to first post-merge CI run on ubuntu-latest because Windows local execution surfaces upstream CRLF/LF drift in protocol-doc:verify and save-format-doc:verify (one-sided LF normalization). Cannot validate steps 2-11 from this Windows worktree. Step count updated from 12 to 14 (Plans 10 and 11 added tsc strict steps)."
---

# Phase 3: Server Documentation & Schemas Verification Report

**Phase Goal:** Every server feature, the reversed 39dll wire protocol, the `.bno`/`.bnb`/`.bnu` save schemas, the persistence-layer ADR, the canonical-snapshot ADR, and the closed parity-feature checklist all exist and are locked at phase end.
**Verified:** 2026-05-04T12:00:00Z
**Status:** human_needed
**Re-verification:** Yes — after gap closure (Plans 10, 11, 12 landed)

## Goal Achievement

### Observable Truths (mapped to ROADMAP Success Criteria + SDOC requirements)

| # | Truth (Roadmap SC) | Status | Evidence |
|---|---------------------|--------|----------|
| 1 | SC1 / SDOC-01: `docs/extracted-server/` documents every server feature (account/auth, world simulation, persistence, chat, room management, packet protocol, admin tooling) | VERIFIED | 11 hand-authored subsystem MDs present (account-auth, world-simulation, persistence, chat, room-management, packet-protocol, admin-anti-port, client-server-bridge, message-board, unknown-actions-status, README) totalling 1,476 lines + SUBSYSTEM-MAP.json (300 lines) partitioning all 135 server scripts + 58 objects into exactly one of 10 keys; `pnpm lint:subsystem-mds` exits 0 with "11 MDs validated; partition deterministic-clean"; `pnpm catalog:verify:server` exits 0 |
| 2 | SC2 / SDOC-02: 39dll wire protocol documented as complete opcode table — every c2s and s2c message — derived from `write*`/`read*` call order in extracted Master GML | VERIFIED | `docs/extracted-server/protocol.{json,md}` shipped with 22 opcodes; every row carries `gml_origin[] >= 1` entry; login-response opcode 8 modeled as discriminated union per branch-coverage caveat; `pnpm lint:protocol` exits 0 with "22 opcodes validated"; scanner traces sendmessage→clearbuffer→writeX in extracted/server-5-4 |
| 3 | SC3 / SDOC-03: `.bno`/`.bnb`/`.bnu` save formats documented as field-by-field schemas, derived from extracted GML `file_text_*` call sequence (per D-08 errata) | VERIFIED | `docs/extracted-server/save-formats.{json,md}` shipped with 9 formats; every row carries `load_script` + `save_script` citations (or null with disposition reason for archived); MB_Log.bnb sectioned grammar with @TOPIC/@REPLY markers; A1/A2/A3/A7 ground-truth verification in tools/save-format-doc/GROUND-TRUTH.md; D-08 errata locked in decomp/wiki/16 + PITFALLS §A5 with `pnpm lint:wiki-errata` exit 0; `pnpm lint:save-formats` exits 0 with "9 formats validated" |
| 4 | SC4 / SDOC-04: ADR for persistence layer (SQLite + Litestream vs Postgres) committed | VERIFIED | `docs/adr/0002-persistence-layer.md` (263 lines) Michael Nygard format; locks better-sqlite3 12.9.0 + Drizzle 0.45.2 + drizzle-kit 0.31.10 + Litestream 0.3.13; `pnpm lint:adr:0002` exits 0; cites >=4 specific signals from save-formats.json + persistence.md; Postgres rejection with 4 reasons; 3 forcing functions enumerated; OPS-03 v2 migration path preserved |
| 4b | SC4 / SDOC-06: Canonical-snapshot ADR (`enlyzeam-current` vs `enlyzeam-archive` vs `local-current`) committed | VERIFIED | `docs/adr/0003-canonical-snapshot.md` (256 lines) locks `legacy/servers/enlyzeam-current/` whole; per-snapshot disposition table present; legacy-credentials staging pipeline documented (localList.txt -> legacy_credentials_staging -> first-login argon2id rehash -> row drop); 4 forcing functions; D-03 older-extraction rejection; `pnpm lint:adr:0003` exits 0 |
| 5 | SC5 / SDOC-05: Closed parity-feature checklist committed and locked at phase end (every feature done / deferred / rejected) | VERIFIED | `docs/extracted-server/parity-checklist.{json,md}` shipped; 69 rows, distribution: 7 in-phase-6 (CLI-08 MVP slice), 36 in-phase-7, 9 deferred-stage-8, 17 rejected-with-reason; every row carries originating_gml + originating_opcodes + originating_save_fields + subsystem; cross-resolution validated (every opcode reference resolves to protocol.json; every save-field filename resolves to save-formats.json filename_pattern); 7 admin commands rejected with modernized_replacement intent names; `pnpm lint:parity-checklist` exits 0 with disposition counts logged + "69 rows validated" |
| 6 | Phase 4 contract: Generated TS contracts (`output/protocol.ts`, `output/save-formats.ts`) are importable verbatim under project strict-mode TypeScript | VERIFIED | Plans 10 + 11 landed: emitters de-duplicate field names (occurrence 2+ renamed `name_2`, `name_3` with `@gmlName` JSDoc preserving wire identity); `readonly Array<T>` on object types replaced with `ReadonlyArray<T>`. Regenerated artifacts committed. Standalone `tsc --noEmit --strict --noUncheckedIndexedAccess --exactOptionalPropertyTypes output/protocol.ts` exits 0 (zero errors; was 18+). Same flag set against `output/save-formats.ts` exits 0 (zero errors; was 11+). Plan 12 wires both as steps 6-7 of `scripts/verify-phase-3.mjs` (labels "Plan 10: tsc strict — protocol.ts" and "Plan 11: tsc strict — save-formats.ts"). Both tsconfig.json `include` arrays extended to cover `output/*.ts`. `scripts/verify-phase-3.test.mjs` `expectedLabels` updated to length 14. |

**Score:** 6/6 truths verified

### Gap Closure Evidence (re-verification focus)

The single failing gap from the prior verification (Truth #6 — Phase 4 strict-mode import contract) is closed. Specific evidence per check requested:

| Check | Result |
|-------|--------|
| `tsc --noEmit --strict --noUncheckedIndexedAccess --exactOptionalPropertyTypes output/protocol.ts` (run in tools/protocol-doc) | Exit 0 — zero errors |
| `tsc --noEmit --strict --noUncheckedIndexedAccess --exactOptionalPropertyTypes output/save-formats.ts` (run in tools/save-format-doc) | Exit 0 — zero errors |
| `scripts/verify-phase-3.mjs` contains label `Plan 10: tsc strict — protocol.ts` | CONFIRMED — line 33 |
| `scripts/verify-phase-3.mjs` contains label `Plan 11: tsc strict — save-formats.ts` | CONFIRMED — line 38 |
| `tools/protocol-doc/tsconfig.json` includes `"output/*.ts"` | CONFIRMED — `"include": ["cli.ts", "src/**/*.ts", "tests/**/*.ts", "output/*.ts"]` |
| `tools/save-format-doc/tsconfig.json` includes `"output/*.ts"` | CONFIRMED — same pattern |
| `scripts/verify-phase-3.test.mjs` `expectedLabels.length === 14` | CONFIRMED — 14 entries in array; strict count assertion at line 54 |
| `scripts/verify-phase-3.mjs` total step entries | CONFIRMED — 14 entries (grep count) |
| De-dup in `output/protocol.ts`: `p_spr_2`, `uinv_get_2`, `hxbridge_2`, `mb_topic_2`, `mb_topic_3`, `mb_total_2` | CONFIRMED — all present with `@gmlName` JSDoc |
| De-dup in `output/save-formats.ts`: `mb_topic_2`, `mb_topic_3` in `SaveMbLogBnb.topic.topics` | CONFIRMED — renamed fields present |
| `ReadonlyArray<T>` used (not `readonly Array<T>`) for nested array types in save-formats.ts | CONFIRMED — `ReadonlyArray<{...}>` at lines 23, 35, 81, 146 |

### Required Artifacts

| Artifact | Expected | Status | Details |
|----------|----------|--------|---------|
| `docs/extracted-server/protocol.json` | 39dll opcode table (>=1 c2s + >=1 s2c, gml_origin per row) | VERIFIED | 22 opcodes, all with gml_origin, sorted-keys deterministic |
| `docs/extracted-server/protocol.md` | Rendered opcode table with AUTOGEN blocks | VERIFIED | 397 lines, 3 AUTOGEN blocks (opcodes-c2s, opcodes-s2c, mvp-opcodes) |
| `docs/extracted-server/save-formats.json` | Per-format grammar with file_text_* citations | VERIFIED | 9 formats, deterministic, PII-safe (synthetic fixtures) |
| `docs/extracted-server/save-formats.md` | Rendered with AUTOGEN blocks | VERIFIED | 237 lines, 5 AUTOGEN blocks |
| `docs/extracted-server/parity-checklist.json` | Closed scope-lock for Phase 7 PAR-08 | VERIFIED | 69 rows, 4 dispositions, cross-resolution clean |
| `docs/extracted-server/parity-checklist.md` | Rendered with AUTOGEN blocks | VERIFIED | 164 lines, 3 AUTOGEN blocks |
| `docs/extracted-server/SUBSYSTEM-MAP.json` | Deterministic 135-script + 58-object partition | VERIFIED | 10 keys including synthetic `misc`; zero-orphan, zero-overlap |
| 11 subsystem MDs at `docs/extracted-server/*.md` | Hand-authored narratives covering every server feature | VERIFIED | All 11 present; admin-anti-port carries CLAUDE.md hard rule #3 + 7 modernized intents |
| `docs/extracted-server/0001_baseline.sql` | drizzle-kit-emitted DDL byte-identical to migrations source | VERIFIED | 8 CREATE TABLE statements; byte-equal to tools/db-schema/migrations/0001_baseline.sql |
| `docs/adr/0002-persistence-layer.md` | Michael Nygard format ADR locking persistence stack | VERIFIED | 263 lines, all 4 sections present, lint-adr --no-matrix passes |
| `docs/adr/0003-canonical-snapshot.md` | Michael Nygard format ADR locking snapshot choice | VERIFIED | 256 lines, all 4 sections present, lint-adr --no-matrix passes |
| `tools/protocol-doc/output/protocol.ts` | Phase 4 packages/protocol consumes verbatim | VERIFIED | De-duped emitter; tsc --strict exits 0; `@gmlName` JSDoc preserves wire identity for duplicate GML fields |
| `tools/save-format-doc/output/save-formats.ts` | Phase 4 SRV-10/11 imports verbatim | VERIFIED | De-duped emitter; ReadonlyArray fix; tsc --strict exits 0 |
| `tools/protocol-doc/src/emit/typescript.ts` | De-duplicates field names per scope | VERIFIED | Occurrence counter per scope; renames as `name_2`, `name_3` (Plan 10) |
| `tools/save-format-doc/src/emit/typescript.ts` | De-duplicates field names; no invalid readonly | VERIFIED | Per-scope dedup in emitGrammarBody; ReadonlyArray<T> used (Plan 11) |
| `tools/db-schema/src/tables.ts` | 8-table Drizzle schema | VERIFIED | 8 exports; 50/50 columns SOURCE-cited; 18 vitest tests pass |
| `tools/db-schema/migrations/0001_baseline.sql` | drizzle-kit-emitted baseline DDL | VERIFIED | 8 CREATE TABLE; idempotent re-emit reports "No schema changes" |
| `scripts/verify-phase-3.mjs` | Composite gate orchestrator (14 steps) | VERIFIED | 14 steps total (was 12); steps 6-7 are tsc strict checks for Plans 10 + 11; fail-fast diagnostic preserved |
| `scripts/verify-phase-3.test.mjs` | Smoke test asserts 14 labels in order | VERIFIED | expectedLabels.length === 14; strict count assertion + order-preserving check |
| `tools/protocol-doc/tsconfig.json` | include covers output/*.ts | VERIFIED | `"include": [..., "output/*.ts"]` |
| `tools/save-format-doc/tsconfig.json` | include covers output/*.ts | VERIFIED | `"include": [..., "output/*.ts"]` |
| `.github/workflows/verify-phase-3.yml` | CI gate triggering on Phase 3 path filter | VERIFIED | Workflow file structurally valid (smoke test confirms structure) |
| 6 lint scripts | wiki-errata, protocol, save-formats, subsystem-mds, parity-checklist, adr (and chained adrs) | VERIFIED | All exit 0 against committed artifacts on local Windows host |

### Key Link Verification

| From | To | Via | Status | Details |
|------|-----|-----|--------|---------|
| tools/protocol-doc/cli.ts | src/emit/index.ts | import { runCatalog, runRegenAutogen, runVerify } | WIRED | Verified import + cli wiring |
| tools/protocol-doc/src/emit/index.ts | extracted/server-5-4/scripts/ | scanner readdirSync + readFileSync | WIRED | Plan 02 SUMMARY: 22 opcodes detected on real data |
| docs/extracted-server/protocol.json | tools/protocol-doc/output/protocol.ts | deterministic re-emit (with de-dup) | WIRED | Re-emit succeeds; tsc --strict exits 0 (gap closed) |
| tools/protocol-doc/scripts/lint-protocol.mjs | docs/extracted-server/protocol.json | JSON.parse + per-row schema check | WIRED | Exits 0 with 22 opcodes validated |
| tools/save-format-doc/cli.ts | src/emit/index.ts | runCatalog/runRegenAutogen/runVerify | WIRED | Verified import wiring |
| tools/save-format-doc/src/scanner/format-trace.ts | extracted/server-5-4/scripts/ | readdirSync + readFileSync line-scan for file_text_open_* | WIRED | 9 formats detected, A3 17-script delta confirmed |
| docs/extracted-server/save-formats.json | tools/save-format-doc/output/save-formats.ts | deterministic re-emit (with de-dup + ReadonlyArray fix) | WIRED | Re-emit succeeds; tsc --strict exits 0 (gap closed) |
| tools/db-schema/src/tables.ts | docs/extracted-server/0001_baseline.sql | drizzle-kit generate + byte-copy | WIRED | `pnpm lint:schema-sync` exits 0 (byte-equal) |
| docs/extracted-server/parity-checklist.json | docs/extracted-server/protocol.json + save-formats.json | originating_opcodes + originating_save_fields cross-resolution | WIRED | Lint resolves every reference into target file's primary-key set |
| docs/adr/0002-persistence-layer.md | save-formats.json + tables.ts + 0001_baseline.sql | References section + Decision rationale | WIRED | 30 unique reference matches found |
| docs/adr/0003-canonical-snapshot.md | tools/db-schema/src/tables.ts (legacy_credentials_staging) | Decision legacy-credentials-pipeline | WIRED | 9 grep hits for `legacy_credentials_staging`; 6 hits for argon2id/read-once-then-purge |
| scripts/verify-phase-3.mjs | tools/protocol-doc output/protocol.ts | pnpm -C tools/protocol-doc exec tsc --noEmit --strict ... | WIRED | Step label "Plan 10: tsc strict — protocol.ts" at line 33 |
| scripts/verify-phase-3.mjs | tools/save-format-doc output/save-formats.ts | pnpm -C tools/save-format-doc exec tsc --noEmit --strict ... | WIRED | Step label "Plan 11: tsc strict — save-formats.ts" at line 38 |

### Data-Flow Trace (Level 4)

Phase 3 ships documentation + schema artifacts (no runtime services). The "data" here is the extracted GML -> derived JSON -> derived TS/MD pipeline. Confirmed:

| Artifact | Data Source | Source Produces Real Data | Status |
|----------|-------------|----------------------------|--------|
| protocol.json | extracted/server-5-4/scripts/ + objects/ via opcode-trace scanner | YES — 22 opcodes detected, every row has gml_origin >=1 | FLOWING |
| save-formats.json | extracted/server-5-4/scripts/ via format-trace scanner + tools/save-format-doc/fixtures/ for samples | YES — 9 formats with grammar + >=1 sample_records each (8 of 9; archived debug-log row legitimately has 0) | FLOWING |
| parity-checklist.json | SDOC-01 H2 headings + protocol.json + save-formats.json + FEATURES.md inventory | YES — 69 rows derived, cross-resolution clean | FLOWING |
| 0001_baseline.sql | tables.ts via drizzle-kit generate | YES — 8 CREATE TABLE statements, 50 columns | FLOWING |
| protocol.ts | protocol.json via emit/typescript.ts (de-dup emitter) | YES — de-duped deterministic emit; tsc --strict exits 0 | FLOWING |
| save-formats.ts | save-formats.json via emit/typescript.ts (de-dup + ReadonlyArray emitter) | YES — de-duped deterministic emit; tsc --strict exits 0 | FLOWING |

### Behavioral Spot-Checks

| Behavior | Command | Result | Status |
|----------|---------|--------|--------|
| Wiki-errata regression guard | `pnpm lint:wiki-errata` | exit 0, "file_text_* errata present in both targets" | PASS |
| Protocol opcode lint | `pnpm lint:protocol` | exit 0, "22 opcodes validated" | PASS |
| Save-formats lint | `pnpm lint:save-formats` | exit 0, "9 formats validated" | PASS |
| Subsystem-MD lint | `pnpm lint:subsystem-mds` | exit 0, "11 MDs validated; partition deterministic-clean" | PASS |
| Parity-checklist lint | `pnpm lint:parity-checklist` | exit 0, disposition counts: 7/36/9/17, 69 rows validated | PASS |
| Schema-sync lint | `pnpm lint:schema-sync` | exit 0 | PASS |
| Source-comments lint | `pnpm lint:source-comments` | exit 0, "50 columns, all SOURCE-cited" | PASS |
| ADRs chained lint | `pnpm lint:adrs` | exit 0 (0001 + 0002 + 0003 all validated) | PASS |
| TS strict compile of generated protocol contract | `tsc --noEmit --strict --noUncheckedIndexedAccess --exactOptionalPropertyTypes output/protocol.ts` (in tools/protocol-doc) | Exit 0 — zero errors | PASS (gap closed) |
| TS strict compile of generated save-formats contract | `tsc --noEmit --strict --noUncheckedIndexedAccess --exactOptionalPropertyTypes output/save-formats.ts` (in tools/save-format-doc) | Exit 0 — zero errors | PASS (gap closed) |
| verify-phase-3.mjs step count | 14 step entries in `steps` array | 14 confirmed by grep count | PASS |
| verify-phase-3.test.mjs expectedLabels.length | 14 labels declared | 14 entries in array at lines 17-32 | PASS |
| Composite verify gate (full, Linux canonical) | `pnpm verify:phase-3` on ubuntu-latest | NOT RUN — deferred to first CI run; Windows host has CRLF/LF drift | SKIP — needs CI |

### Requirements Coverage

| Requirement | Source Plan | Description | Status | Evidence |
|-------------|-------------|-------------|--------|----------|
| SDOC-01 | 03-01, 03-04 | docs/extracted-server/ documents every server feature | SATISFIED | 11 subsystem MDs + SUBSYSTEM-MAP.json + asset-catalog server-tree all committed; lint-subsystem-mds passes |
| SDOC-02 | 03-02 | Reversed 39dll wire protocol as opcode table | SATISFIED | 22 opcodes in protocol.json; gml_origin per row; lint-protocol passes |
| SDOC-03 | 03-03, 03-06 | .bno/.bnb/.bnu schemas as field-by-field grammars | SATISFIED | save-formats.json (9 formats); D-08 errata locked; A1/A2/A3/A7 ground-truth verified; tables.ts/0001_baseline.sql for DB shape |
| SDOC-04 | 03-06, 03-07 | Persistence-layer ADR | SATISFIED | docs/adr/0002-persistence-layer.md committed; lint-adr:0002 passes |
| SDOC-05 | 03-05 | Closed parity-feature checklist | SATISFIED | parity-checklist.json with 69 rows; cross-resolution validated; MVP coverage exact |
| SDOC-06 | 03-08 | Canonical-snapshot ADR | SATISFIED | docs/adr/0003-canonical-snapshot.md; enlyzeam-current locked; legacy-credentials pipeline documented |

All 6 requirement IDs from PLAN frontmatter accounted for. No orphaned requirements.

### Anti-Patterns Found

| File | Line | Pattern | Severity | Impact |
|------|------|---------|----------|--------|
| tools/asset-catalog/scripts/lint-parity-checklist.mjs | 257-296 | Exit logic inside dynamic import().then(); no .catch handler | Warning | Per CR-03; lint can pass with errors > 0 in pathological conditions |
| tools/protocol-doc/src/scanner/opcode-trace.ts | 329, 394 | Mutating outer for-loop counter from inside inner block | Warning | Per CR-04; fragile control flow; double-emission risk on truncated input |
| tools/protocol-doc/src/scanner/opcode-trace.ts | 251-267 | Off-by-one + no brace-depth tracking in branch detection | Warning | Per WR-01; landmine if Phase 4 ever uses `branches` flag for codec selection |
| tools/save-format-doc/scripts/lint-save-formats.mjs | 166-177 | PII regex denylist — misses `pwd`, `u_pwd`, email, IP patterns | Warning | Per WR-04; the actual GML field name `u_pwd` is not in the denylist |
| (multiple) | (per CR-03/04, WR-01..07) | Various code-review findings (non-blocker) | Info/Warning | See 03-REVIEW.md — CR-01/CR-02 closed by Plans 10+11; 4 warnings + 4 info remain |

Note: CR-01 (protocol.ts duplicate identifiers) and CR-02 (save-formats.ts duplicate identifiers + readonly modifier) are CLOSED. No blocker anti-patterns remain.

### Human Verification Required

#### 1. Linux CI run of `pnpm verify:phase-3`

**Test:** Push the merged Phase 3 branch and observe the first GitHub Actions run of `.github/workflows/verify-phase-3.yml` on `ubuntu-latest`.
**Expected:** All 14 verify steps green; final `verify-phase-3: OK (14 steps green)`; post-condition `git diff --exit-code docs/extracted-server/ tools/db-schema/migrations/` exits 0.
**Why human:** Plan 09 SUMMARY explicitly defers canonical green proof to first post-merge CI run. Windows host has CRLF/LF drift that affects `protocol-doc:verify` and `save-format-doc:verify` (one-sided LF normalization in `runVerify`). Cannot validate steps 2-11 from this Windows worktree. Step count is now 14 (not 12 as originally deferred) due to Plans 10 + 11.

### Gaps Summary

All six observable truths are now VERIFIED. The single blocking gap from the prior verification is closed:

- Plans 10 + 11 fixed the de-duplication logic in both emitters and regenerated the output artifacts. Standalone `tsc --noEmit --strict --noUncheckedIndexedAccess --exactOptionalPropertyTypes` exits 0 against both `output/protocol.ts` and `output/save-formats.ts`.
- Plan 12 wired the two tsc checks as canonical steps 6-7 in `scripts/verify-phase-3.mjs`, updated the test's `expectedLabels` to length 14, and extended both tsconfig.json `include` arrays to cover `output/*.ts` so the internal TS build also covers the generated contracts.

One item remains for human verification: the canonical end-to-end `pnpm verify:phase-3` run must complete on a Linux host (ubuntu-latest CI) to confirm no CRLF/LF drift in the round-trip verify steps. This was deferred at Plan 09 and remains deferred — it is not a code defect but a platform-parity confirmation.

---

_Verified: 2026-05-04T12:00:00Z_
_Verifier: Claude (gsd-verifier)_
