# Documentation Audit — Design

**Date:** 2026-06-03
**Status:** Approved (brainstorming complete) → ready for writing-plans
**Branch:** `docs/documentation-audit` (off `master` @ `c6d9b20`)

## Goal

Perform an in-depth audit of the **live reference documentation** to ensure
accuracy and completeness, correcting issues in place and writing
documentation for every shipped-but-undocumented feature.

## Decisions

These were settled during brainstorming and are not open for re-litigation in
the plan:

| Dimension | Decision |
|---|---|
| **Corpus** | Live reference docs only — top-level `docs/*.md` current-reference set, `docs/drivers/*.md`, `README.md`, `CLAUDE.md` (32 files). Excludes `docs/v1`, `docs/v2`, `docs/plans`, `docs/reqs`, `docs/v3`, `looseends.md`. |
| **Output mode** | Fix in place, single pass → corrected docs + a change summary (delivered in chat, not committed). |
| **Checks** | All four dimensions: structural integrity, stale-status reconciliation, code-reality cross-check, completeness gaps. |
| **Gap handling** | Fill **every** gap — write documentation for all undocumented shipped features, small or large. |
| **Approach** | C — deterministic baseline → code-first inventory → grouped vertical passes. |

## Out of scope

- Historical tiers (`v1/`, `v2/`, `plans/`, `reqs/`, `v3/`, `looseends.md`) — they
  are point-in-time records and are not edited.
- The XML doc-comment pass (handled separately by the `/fixdocs` run on branch
  `chore/fixdocs-xml-doc-comments`).
- Code changes. This is a documentation effort. If the audit finds a genuine
  **code** bug, it is *flagged in the summary, not fixed*.
- Secrets must never be introduced into docs: `sql_login.txt`, `pki/`, and the
  dev gateway API key stay out of any committed file.

## Corpus & subsystem grouping

Phase 1 runs one full-depth pass per group (G1–G4). G5 is the Phase-2
reconciliation group.

| Group | Files |
|---|---|
| **G1 — Server core & data path** | `OpcUaServer.md`, `AddressSpace.md`, `ReadWriteOperations.md`, `IncrementalSync.md`, `VirtualTags.md`, `ScriptedAlarms.md`, `AlarmTracking.md` |
| **G2 — Drivers** | `docs/drivers/`: `README.md`, `Galaxy.md`, `FOCAS.md`, + 7 `*-Test-Fixture.md` (`AbLegacy`, `AbServer`, `FOCAS`, `Modbus`, `OpcUaClient`, `S7`, `TwinCAT`) |
| **G3 — Security & operational** | `security.md`, `Redundancy.md`, `Reservations.md`, `ServiceHosting.md`, `StatusDashboard.md` |
| **G4 — Client & CLI tooling** | `Client.CLI.md`, `Client.UI.md`, `DriverClis.md`, `Driver.{Modbus,AbCip,AbLegacy,S7,TwinCAT,FOCAS}.Cli.md` |
| **G5 — Index & root (reconcile last)** | `docs/README.md`, `CLAUDE.md` |

**Already-suspected findings** (the design accounts for them; verify during the pass):

- Top-level `AlarmTracking.md` may be **orphaned** — the README index links to
  `v1/AlarmTracking.md`, not the top-level file. Resolve in G1.
- `StatusDashboard.md` is a **stub pointer** (superseded by `v2/admin-ui.md`).
  Resolve in G3.
- `CLAUDE.md` references both `docs/security.md` and `docs/Security.md` — a
  **case mismatch** that works on macOS but breaks on the Linux docker host.
  Resolve in G5.

## Phase 0 — deterministic baseline + code-first inventory

Two transient working artifacts produced **before any doc is edited**, kept
under a scratch dir and **not committed** (lesson from the fixdocs run, where
`OtOpcUa-docs-*.md` cluttered the repo root):

**(a) Structural checker.** Walks all 32 docs, extracts every markdown link and
inline source path (`src/...`, `docs/...`, `scripts/...`, `tests/...`), and
resolves each against the filesystem. Output: broken links / dead paths / case
mismatches. Deterministic and re-runnable — it is also the Phase-2 exit gate.

**(b) Feature inventory from source.** Enumerated from code, *not* docs, so
"fill every gap" has ground truth:

- **Drivers** — the driver projects under `src/Drivers/` (+ the
  `Historian.Wonderware` sidecar).
- **Capabilities** — the `Core.Abstractions` interfaces (`IReadable`,
  `IWritable`, `ITagDiscovery`, `ISubscribable`, `IAlarmSource`,
  `IHistoryProvider`, `IHostConnectivityProbe`, `IPerCallHostResolver`).
- **Config surface** — `appsettings.json` sections + bound Options classes
  (Security, Authentication.Ldap, Redundancy, MxAccess, …) and documented env
  vars (`OTOPCUA_ROLES`, …).
- **CLI surface** — command verbs + flags from the `System.CommandLine`
  definitions in the client + 6 driver CLIs.
- **Security profiles** — the values `SecurityProfileResolver` actually
  resolves.

Diffing the inventory against the docs yields the completeness worklist (what
ships but is not documented) and grounds the code-reality cross-check.

## Phase 1 — per-group fix methodology

Each group is a vertical pass. For every doc in the group, all four dimensions
are applied in order, then the group is committed together:

1. **Structural** — apply the doc's Phase-0 link/path findings: repair broken
   links, repoint moved `src/...` paths to current locations, fix case
   mismatches, resolve orphans (re-link, merge, or retire), replace stub
   pointers with real content or a correct pointer.
2. **Stale-status** — locate state words / banners (`blocked`, `pending`,
   `not yet`, `planned`, `TODO`, `as of <date>`) and reconcile each against
   current reality (source + git history + known facts: v2 feature-complete,
   native alarms verified working). Rewrite to present-tense truth or delete if
   obsolete.
3. **Code-reality cross-check** — verify every technical claim (namespace,
   class, file, `appsettings` key, env var, CLI verb/flag, described behavior)
   against the Phase-0 inventory and a direct source read. **Fixes go to the
   doc to match the code, never the reverse.** A genuine code bug is flagged in
   the summary, not changed.
4. **Completeness** — take this group's slice of the inventory diff and write
   the missing docs: small inline additions for a missing key/flag, new
   sections or whole new pages for an undocumented driver/subsystem. Every new
   page is linked from its index (`README.md` / `drivers/README.md`).

**Hard scope rule:** edits land only in the 32 in-scope files. If an in-scope
doc links into an out-of-scope tier and the *target moved*, fix the **link in
the live doc** — never edit the historical artifact.

## Phase 2 — reconciliation & validation

**Cross-doc reconciliation (G5):** `docs/README.md` index integrity (every
listed doc exists and is correctly described; newly written docs are added),
"superseded by" pointers correct, and `CLAUDE.md` reconciled against reality
(the `security.md`/`Security.md` casing, retired-project notes, the docs it
names as canonical).

**Validation — the audit's "tests" are two re-runnable gates plus review:**

- **Structural gate** — re-run the Phase-0 checker → **zero** broken links /
  dead paths / case mismatches.
- **Completeness gate** — re-run the inventory diff → every shipped feature is
  documented, or each deliberate exclusion is listed with a reason.
- **Spot-verification** — a sample of code-reality fixes re-checked against
  source with `file:line` citations in the summary.
- Each group is a reviewable commit; nothing touches code, secrets, or
  out-of-scope tiers.

## Output

The change summary (in chat, not committed): fixes grouped by dimension, the
list of new docs written for completeness, and any code bugs flagged-not-fixed.

## Brainstorming task references

Native tasks created during brainstorming: #53 (explore), #54 (clarify), #55
(approaches), #56 (present design), #57 (write design doc), #58 (transition to
writing-plans).
