---
name: docs-folder-structure
description: "docs/ was reorganised into topic folders on 2026-07-30 — where every new .md file must go, and the relative-link rule."
metadata:
  node_type: memory
  type: project
  originSessionId: 31d30fcb-2664-4d91-b2c6-59dc12185e0f
  modified: 2026-07-30T13:43:29.833Z
---

`docs/` was reorganised on 2026-07-30 from 71 loose root files into topic folders.
**Never drop a new .md at the `docs/` root** — only cross-cutting documents
(roadmap, project summary, `README.md`, `DEVELOPER_COMMAND_REFERENCE.md`) live
there. Two files broke that rule until 2026-08-31 —
`FORENSIC INVESTIGATION.md` and `FORENSIC_INVESTIGATION_v2.md`, both AI Auto
Scan traces — and are now
`docs/scanner/ai_auto_scan_forensic_investigation_2026-08-27.md` and
`…_v2_2026-08-27.md`. The space in the first filename is the reason to notice
the rule: a path with a space needs quoting in every script that touches it. Index: `docs/README.md`, with sub-indexes at `docs/v2/README.md` and
`docs/confidence_engine/README.md`.

**`docs/DEVELOPER_COMMAND_REFERENCE.md` is generated and must never be edited
by hand.** `backend/tools/generate_developer_command_reference.py` writes it by
reading the repository — argparse parsers by AST, CI gates out of `run_all.sh`,
migrations out of their `Migration(...)` literals, tests by walking the tree —
and CI gate 11 regenerates it and fails on any difference. An edit made in the
file is reverted by the next generation. Change the source of a command (its
parser, its docstring, `run_all.sh`) and regenerate:

    python backend/tools/generate_developer_command_reference.py

| New document | Folder |
|--------------|--------|
| Frozen interface/schema contract, or an amendment | `docs/v2/spec/` |
| Phase kickoff / completion report / acceptance review | `docs/v2/phases/` |
| Strategy or filter specification / ratification | `docs/v2/strategy/` |
| Pre-implementation governance review or verification | `docs/v2/governance/` |
| **Research-governance rule, protocol, or framework amendment** | `docs/v2/governance/research/` |
| **Campaign record, pre-registration, GO/NO-GO pack, manifest** | `docs/v2/governance/research/registry/` |
| Architecture baseline, inventory, readiness assessment | `docs/v2/architecture/` |
| **Operational runbook — how a running system is deployed, scheduled, monitored** | `docs/v2/operations/` |
| **Screenshots evidencing an operations surface** | `docs/v2/operations/screenshots/<surface>_<date>/` — one dated folder per validation pass, beside the report that cites it |
| Replay evidence, performance measurement, optimisation result | `docs/v2/validation/` |
| **A validation *run* — the JSON, Markdown, HTML and certificate** | `backend/logs/validation/` — **generated, never committed to `docs/`.** The corpus holds the *citation* ([RG-15](v2/governance/research/RG-15_validation_gate.md) §4); writing run artefacts into `docs/` would put generated data inside the thing that checks generated data |
| Campaign phase report (the evidence itself) | `docs/v2/validation/systematic/` |
| Position-exit policy, any stage of its chain | `docs/policy/<Policy Name>/` |
| A decision worth recording permanently | `docs/adr/` (next free number) |
| AI-scanner behaviour or UI integration, **including a forensic investigation of a scan** | `docs/scanner/` |
| **Frontend presentation-layer design — redesign proposal, design system, CSS isolation, responsive/accessibility plan** | `docs/v2/ui/` (added 2026-08-16) |
| **One session's paper-trading report** | `docs/paper_trading_report/DD_MMM_YYYY.md` — **generated, never hand-written** (added 2026-08-17) |

`docs/confidence_engine/` is the closed V1 investigation (phases 1–15) — append
nothing. Its phase numbers are a **separate sequence** from V2's; V1 "Phase 13"
≠ V2 Phase 13 ([[v2-phase13-optimisation]]).
`docs/v2/v2_optimisation_research_principles.md` sits above the v2 subfolders
because it governs all of them ([[v2-optimisation-principles]]).

**Two folders mention "UI", and the split is by *subject*, not by language.**
`docs/scanner/` owns how the **AI scanner behaves** and the rules a client must
honour when rendering it — SL-01's billing boundary, `signals[].confirmable`, why
the Confirm Trade predicate may not be recomputed in a browser. `docs/v2/ui/` owns
how a **surface looks**: redesign proposals, design systems, CSS isolation,
responsive and accessibility plans. A rule that constrains what a client is allowed
to decide goes to `docs/scanner/`; a document about type scales, glass, breakpoints
or rollback goes to `docs/v2/ui/`. Index: [v2/ui/README.md](v2/ui/README.md).

**`docs/paper_trading_report/` is written by a command, one file per session.**
`python -m generate_paper_trading_report` reads the evidence
`shadow_mode attach-outcomes` and `shadow_mode replay-signals` recorded and
writes `DD_MMM_YYYY.md`. It **never overwrites** — a re-run on the same day
appends the IST wall-clock time (`17_Aug_2026_160501.md`), because the first file
is the only record of what the evidence said before a back-fill, and "the report
changed after I back-filled the contract" is a finding. Nothing reads the folder,
so no gate depends on the path, but `backend/generate_paper_trading_report/
output.py` writes it — change one and change the other.

**A report run from the Daily Shadow Operations console does not come here.**
`docs/paper_trading_report/` is where a *terminal* run writes, and
`output.REPORT_DIR` is unchanged. The 15:44 step of the daily workflow passes
`--markdown-out` and names the file itself, so both of a session's reports land
in that session's own directory —
`shadow_evidence/console/daily/<date>/<INDEX>/paper-trading-report.md` beside
`…report.json`. A re-run writes `paper-trading-report_YYYYMMDD_HHMMSS.md`
beside the first for the same reason a re-run here writes
`DD_MMM_YYYY_HHMMSS.md`: the first file is the only record of what the evidence
said before a back-fill. Nothing in `docs/` is written by the console.

**There is one research folder now.** `docs/v2/governance/research/` is the
**Research Governance Framework** (RG-01…RG-13, less RG-14) — the rules every
campaign follows, ratified 2026-08-02 ([[v2-research-governance-framework]]).
`docs/v2/research/` documented the Research Workbench *software* and was removed
on 2026-08-31 with the software, along with `datasets/` and `programme/` inside
this folder, which were generated by packages that no longer exist. The account
is [v2/architecture/v2_research_infrastructure_retirement_2026-08-30.md](v2/architecture/v2_research_infrastructure_retirement_2026-08-30.md).

Campaign evidence still lives in `docs/v2/validation/systematic/`; the registry
only links to it, never copies it. Closed-campaign artefacts are checksummed —
`backend/scripts/ci/check_research_archive_integrity.sh` fails if one is edited,
so moving or renaming a file listed in a campaign manifest requires regenerating
that manifest and recording it in the campaign's ERRATA. **That gate outlived
the research code and matters more for it**: it is now the only thing standing
between the closed campaigns' evidence and an unrecorded edit.

**Links are relative to the document's own folder** (`../spec/…`,
`../../../backend/…`) — a repo-root-relative `backend/foo.py` will not resolve.
Retired V1 sources are under `backend/retired_files/`. Every internal link
resolved as of 2026-07-30; keep it that way when moving files.

Three functional dependencies exist on doc paths:
`backend/tools/generate_developer_command_reference.py` **writes**
`docs/DEVELOPER_COMMAND_REFERENCE.md` and CI gate 11 compares it — moving or
renaming that file breaks the gate;
`backend/scripts/ci/check_v2_config_schema_sync.sh` reads
`docs/v2/spec/v2_spec_05_config_schema.md` — moving that file breaks CI; and
`backend/scripts/ci/check_research_archive_integrity.sh` reads every
`*.manifest.sha256` under `docs/v2/governance/research/registry/` and the paths
listed inside them.

There were five. `backend/dataset_programme/paths.py` resolved the `datasets/`
tree and `backend/research_platform/paths.py` **parsed four documents as
sources** — and so made renaming a *heading* a build failure. Both went with
their packages on 2026-08-31, and nothing now reads a section anchor out of a
governance document. Backend docstrings still cite doc paths, so a rename means
a repo-wide grep.
