fragJulia
Operations

SSOT discipline

Why docs.fragjulia.de is the single source of truth, how the changelog contract works, and how GitHub issue closure is gated on documentation.

Status: In force as of 2026-04-22. Enforced by: .github/workflows/docs-guard.yml (required check on every PR).

The principle

There is exactly one authoritative description of how fragJulia works, and it lives at https://docs.fragjulia.de (sourced from apps/docs/content/docs/ in this repo). Every behavior, policy, rule, or convention that a future contributor might need to know is documented there. Everything else — CLAUDE.md, DesignGUIDE/, session notes, OneDrive folders, chat transcripts — is either a redirect to the docs site or a local-ergonomics file, never a source of truth.

Why: We have historically accumulated authoritative-looking documents in many places (OneDrive, ~/.claude/files by dave/, scattered HANDOFF-*.md in the repo root, DesignGUIDE/). When the same fact lives in five places, four of them go stale within weeks and the fifth is ambiguous. A contributor who doesn't know the convention reads a stale file and ships a regression. SSOT is the only way out.

The changelog contract

Every PR that changes user-visible or operator-visible behavior ships with a changelog entry at apps/docs/content/docs/changelog/YYYY-MM-DD-<slug>.mdx. The entry states:

  1. What changed (one paragraph).
  2. Why (link to issue, RFC, or incident).
  3. Which docs pages were updated in the same PR.
  4. Any follow-ups or known gaps.

Frontmatter:

---
title: "2026-04-22 — <short description>"
description: "What changed and why."
date: 2026-04-22
pr: 1234
closes: [1000, 1001]
---

The closes: list names the GitHub issues this change fully resolves. That list is what the issue-closure audit (below) consumes.

Issue closure is gated on documentation

Rule: No GitHub issue is closed unless there is a changelog entry referencing it in closes:. An issue without a closing changelog entry is a ghost-fix — the code changed but the record didn't.

Enforcement (two layers):

  1. PR-time (blocking). docs-guard fails any PR that doesn't add a new file under apps/docs/content/docs/changelog/. Exception: the no-changelog label, which requires an explicit reason in the PR body (infra-only changes, reverts, typo fixes).
  2. Post-merge (audit). A daily cron scans closed issues. Any issue closed in the last 24 h whose closing commit/PR does not appear in any changelog entry's closes: array is tagged missing-changelog and surfaced in a weekly report.

Where the rule doesn't apply

  • Patient / clinical data (the bio-research / Julia case materials at ~/.claude/files by dave/bio-research/) is explicitly NOT public-docs-site content. That lives in a private memory directory, under separate redaction rules (see the [FOR: JULIA] redaction block there). Never migrate patient context into apps/docs/.
  • Secrets and credentials (Supabase keys, Stripe keys, PATs) live only in environment variables and the provider's own console. Never documented with values, only with location.
  • Personal ergonomics (editor settings, local shell aliases, session-specific notes) stay local. They are not canonical and should not propagate.

Migration of legacy documentation

The following legacy paths are being migrated into this site. They will be deleted once migration is complete:

Legacy locationDestinationStatus
DesignGUIDE/fragjulia-design-brief-v3.mdapps/docs/content/docs/design/Done — closed #646 2026-04-25
HANDOFF-2026-04-22-*.md (root + OneDrive)apps/docs/content/docs/operations/ or discardedPending
PLAN.md, LAUNCH-AUDIT-*.md (root)apps/docs/content/docs/operations/Pending
CLAUDE.md (repo root)Pointer only — operational contract stays localDone 2026-04-22

Any new file that would fit one of the legacy categories goes directly into the docs site — do not re-create the legacy paths.

Local clone discipline

Complementary to the SSOT rule: there is exactly one canonical clone of this repo, at C:\code\fragjulia. Multi-branch work uses git worktree, not additional clones. OneDrive, Documents\, Downloads\, and AppData\Temp\ are forbidden for working trees — the DRM/sync behavior on those paths corrupts .git indices.

See CLAUDE.md at the repo root for the local-rules mirror of this rule.

Source conflict resolution — the bounce process

When two sources give different answers (a doc says X, the code says Y, a PR body says Z), do not silently pick a winner. Stop, list the sources, and bounce the decision to the user. The source-tier hierarchy (Tier 1 = live runtime code; Tier 2 = SSOT docs; Tier 3 = merged PRs; Tier 4 = legacy/handoffs/chat) and the full bounce process are documented in decision-processes. Bounce is a governance step, not a coaching nicety: a silently-resolved conflict downstream of an SSOT change becomes a stale-doc incident the audit cron can't catch.

On this page