Skip to content

ADR-0006: Ops Site as Rendered Standing-Reference Surface

Status: Proposed (2026-05-19) Supersedes:Superseded by:


Context

By 19 May 2026 the system has accumulated standing knowledge in five separate places, each with a different cadence and audience:

  1. ADRs (docs/adr/) — design decisions
  2. Design note (docs/design/DESIGN_NOTE_v2_two_stage.md) — v0.5 architecture rationale
  3. Migrations (src/db/migrations/) — schema history
  4. v0.4 workbook (data/seed/ESG_Screening_Framework_v0.4.xlsx) — historical framework reference
  5. Slack #esg-screening — event log, pinned canonical-spec notes, handoffs, in-session updates

Plus three "operating model" documents in three more places:

  1. Project instructions on claude.ai — chat-session protocol
  2. .claude/CLAUDE.md in the repo — CC-on-VM protocol
  3. Pinned Slack notes — canonical hierarchy and other live conventions

Each chat session and CC-on-VM session opens with a context-reconstruction phase: read the latest Slack handoff, re-read the canonical-spec pin, re-derive the glossary (source vs signal_source, coverage vs confidence, etc.) from accumulated handoffs. This is a recurring tax on every session, and it grows as the system grows.

The recurring pattern is observable: handoffs grow longer because each one tries to compensate for the next session not having context — but each handoff is also one more thing to read at the start of the next session. The structure is fighting itself.

A standing-knowledge surface — rendered, navigable, gated — would absorb the "this is how the system is shaped" content and let handoffs shrink to "what changed since last time."

The Vextor project solved this same problem with ops.vextor.tech — a gated technical docs site. The ESG Screening project should mirror that pattern rather than re-invent.

Decision

Build an ops subdomain at ops.esg-screen.org that serves as the rendered standing-reference surface for the ESG Screening system.

Hosting and gating:

  • Cloudflare Pages, deployed from a separate repo (McMillanGrubb/esg-screen-ops)
  • Gated by the same Cloudflare Access app as esg-screen.org — add the subdomain to the existing app's policy. Single email allow list to maintain.
  • No new auth surface, no new credentials, no new monitoring.

Build approach:

  • Static site generator. Default to MkDocs with the Material theme unless ops.vextor.tech uses something different (in which case match it). Dense technical docs, dark mode out of the box, simple configuration.
  • Source in docs/*.md. One-file-per-page navigation structure.
  • GitHub Actions builds and deploys on push to main.

Content policy: render, not replace.

For each surface, where the canonical content lives. The ops site renders from these, never duplicates:

Surface Canonical source Build action
/decisions/NNNN-* docs/adr/NNNN-*.md in main repo Direct render
/reference/claudemd .claude/CLAUDE.md in main repo Direct render
/architecture/scoring ADR-0001 + DESIGN_NOTE_v2 Composed render
/architecture/data-model Migration files + hand-written narrative Composed render
/scrapers/register Hand-written register, mirrors signal_source table (Live view in product)
/ui/design-system ADR-0004 + ADR-0005 + base.css tokens Composed render
/glossary This site is canonical
/operating-model/* This site is canonical
/reference/v0.4-workbook The .xlsx file + hand-written change log Composed render

The two surfaces where the ops site IS canonical:

  • /glossary — terminology disambiguation lives here, nowhere else.
  • /operating-model/* — session protocol and handoff conventions live here, nowhere else.

Everything else, this site renders.

Live-data surfaces (/scrapers/register showing live source status, /scrapers/health showing recent run results) do not duplicate the product's /methodology page. The ops site's register page is intent and design; the product's methodology page is current state. Cross-link freely.

Consequences

Positive.

  • One canonical reference surface. Chat-session and CC-on-VM openers can read one page (the architecture overview) for orientation rather than re-reading every Slack handoff.
  • Handoffs can shrink. They become "since last time, X changed" rather than re-explaining methodology each cycle.
  • Glossary kills repeated terminology confusion (source vs signal_source and the rest).
  • Operating model consolidation. The same content currently in three places (project instructions, CLAUDE.md, pinned Slack notes) lives once, with the other three deferring.
  • Matches an existing operator pattern (Vextor ops site). Pattern familiarity, no new mental model.
  • Auth piggybacks on existing Cloudflare Access app. Zero new auth surface.

Negative.

  • One more thing to keep updated. If the ops site drifts from the underlying canonical sources, it becomes a worse problem than no ops site — confidently wrong.
  • Mitigation: render rather than replace. The ADR markdown files in the main repo stay the source; the ops site renders them. When an ADR is updated, the ops site rebuilds. The same applies for CLAUDE.md. Hand-written narrative pages (architecture overview, data model, ops intent) drift faster — these need explicit attention during cycles that change underlying behaviour.
  • Authoring discipline: every CC-on-VM cycle that lands a structural change must include a docs update in the same commit. Future practice; not enforced by tooling in v1.
  • Single static site, no version pinning. Looking at "the site as of three months ago" requires Git history navigation, not a UI feature. Acceptable v1 trade-off.

Hierarchy revision.

This ADR also revises the canonical hierarchy. The current pinned hierarchy is:

  1. ADRs
  2. Design note
  3. Migrations
  4. v0.4 workbook

The revised hierarchy includes the ops site as a rendered surface without changing priority:

Authoritative sources (priority order):
  1. ADRs
  2. Design note
  3. Migrations
  4. v0.4 workbook

Rendered surfaces (read these for navigability):
  - ops.esg-screen.org (this site) — renders the above plus glossary
    and operating-model content
  - Slack #esg-screening — event log, not authority

Canonical only on the ops site:
  - /glossary
  - /operating-model/*

The pinned Slack note will be updated to reflect this once the site is deployed.

Implementation.

  • New repo: McMillanGrubb/esg-screen-ops. MkDocs Material theme.
  • mkdocs.yml defines navigation.
  • docs/*.md files for each page.
  • GitHub Actions workflow: on push to main, build site and deploy to Cloudflare Pages.
  • Cloudflare Pages project: connected to repo, custom domain ops.esg-screen.org.
  • Cloudflare Access: add ops.esg-screen.org hostname to existing esg-screen.org Access app policy. Same OTP + 5-address allow list.
  • Initial content set: 13 pages produced 19 May (sitemap, home, glossary, session-protocol, handoff-template, canonical-hierarchy, architecture overview, data-model, scoring, stack, scraper register, scraper health, add-a-scraper, UI pages, design system, mock reference, decision log index).

Alternatives considered

  • Stay with Slack pinned notes plus per-session handoffs. The status quo. Doesn't solve the recurring context-reconstruction tax. Rejected.
  • Single big markdown file in the main repo (docs/HANDBOOK.md). Lighter to build but unwieldy at scale, no navigation, no search, every chat session would have to read the whole thing or grep for fragments. Rejected.
  • Wiki on GitHub. Inherits authentication from GitHub itself (already mixed with the gh-CLI pattern), no Cloudflare Access gating needed. But: wikis are second-class to repos for indexing, the page-edit UX is web-only, search is poor. Rejected in favour of a proper static site.
  • Notion or similar SaaS docs. Adds a non-self-hosted dependency with its own auth model, drifts further from the ADR-based source of truth, no straightforward render-from-markdown flow. Rejected.
  • Make the ops site the source rather than a rendered surface. Strongest argument for this is "one place, no duplication." The argument against is stronger: ADRs need to live with the code they describe, and the v0.4 workbook is an external artefact that shouldn't be transcribed. Render is the right move.
  • Build a /docs section on the product itself. Keeps everything on one domain, one auth, one deploy. But: product changes weekly, ops docs should change rarely; mixing them couples release cadences. Separate subdomain keeps cadences independent. Rejected.

References

  • Pattern source: ops.vextor.tech (operator-grade docs site, same shape)
  • The 19 May 2026 chat session that surfaced the context-reconstruction problem
  • Canonical-spec pinned note in #esg-screening
  • ADR README (docs/adr/README.md)