Skip to content

Design System Blueprint (Phase 0) — CVNTrade

Parent issue: #593 (Need → Design → MLOps → Release unified traceability) Phase: 0 — Blueprint (taxonomy, IDs, templates, repo structure) Date: 2026-04-23 Status: Draft — operator-signed on the 6 decisions below Supersedes: the flat documentation/ organization (converted to hierarchy below) Depends on: none (this IS the foundation for Phases 1-5)


0. Signed decisions (2026-04-23)

These 6 choices lock the shape of everything downstream. Any deviation needs a new ADR.

# Decision Value Rationale
D1 ID prefix CVN Unique to project, short, avoids collision with GitHub issue numbers
D2 Repo layout Option A — single repo, documentation/ subfolder Solo dev, avoid sync overhead
D3 OpenProject CE Kept (not scope-reduced) Enterprise-style delivery discipline is the point
D4 ADR migration All 63 ADRs migrated to per-file Clean break, no half-state
D5 Backfill of past objects No backfill (PRs, MLflow runs, past issues) Prohibitive effort vs value; clean cut-over starting 2026-04-23
D6 DVC Skip for now (evaluate in Phase 5+) MLflow+S3+Airflow cover 80% today; revisit when reproducibility gap bites

1. Vision + single traceability spine

From scattered tickets and orphan notebooks → a unified product/ML operating system where need, design, implementation, pipeline runs, and release decisions share the same business identifier.

Need → Epic → Story → Design → ADR → PR → Pipeline Run → Model Version → Backtest → Release

Every object downstream of a Need references the same root ID. Example:

  • CVN-N001 — the need ("reach F1=0.75 on binary BUY/NOT_BUY classification")
  • CVN-N001-EA — epic A ("label embargo + binary infrastructure")
  • CVN-N001-US3 — user story 3 ("ThresholdCalibrator integration in training path")
  • documentation/design/CVN-N001-design.md
  • documentation/adr/0063-ftf-mission-mode-binary.md
  • MLflow run tag: need_id=CVN-N001
  • Model Registry alias: origin_story=CVN-N001-US3
  • PR body: Closes CVN-N001-US3 · Design: CVN-N001-design.md · ADR: 0063

You can answer in one lookup: why is this model in prod? → follow the tag chain back to the Need.


2. Object taxonomy + ID schema

2.1 ID formats (authoritative)

Object Format Example Generated by
Need CVN-N<3-digit> CVN-N001 Operator at need creation; strictly sequential
Epic <need_id>-E<letter> CVN-N001-EA Operator at epic creation; A, B, C… per need
Story <need_id>-US<number> CVN-N001-US3 Operator; numbered per need (not per epic) so stories can be reassigned
Design doc <need_id>-design.md CVN-N001-design.md One design per need (split decisions into ADRs)
ADR <4-digit>-<kebab-slug>.md 0063-ftf-mission-mode-binary.md Continues from ADR-63; per-file from 0064 onwards
Release CVN-R<yyyymmdd>-<n> CVN-R20260423-01 Auto-generated; -n counter for same-day releases
Backtest CVN-BT-<run_id> CVN-BT-ftf_20260422_220929 Auto from FTF run_id prefix
MLflow run (native MLflow UUID) + tags Tags carry the CVN identifiers
Model version (native MLflow version) + alias Alias references origin story

2.2 Required metadata per object type

Mandatory fields the CI gate enforces. Missing = PR blocked.

Object Mandatory fields
Need doc need_id, title, problem, impact, kpis, out_of_scope, status
Epic epic_id, need_id, objective, arch_notes, owner, status
Story story_id, epic_id, acceptance_criteria, test_plan, status
Design doc need_id, authors, options_considered, decision, adr_ids[]
ADR adr_id, title, status, context, decision, invariants, alternatives_rejected
PR body must reference at least one of {need_id, epic_id, story_id} + design doc path
MLflow run need_id, git_sha, dataset_date_range (new tag schema)
Model Registry origin_story alias, training_run_id tag
Release note release_id, epics_closed[], models_promoted[], backtest_report_url

2.3 Cardinalities

Need (1) ──┬── (*) Epic
           ├── (*) Design doc (usually 1, can fork)
           ├── (*) ADR
           └── (*) Story ─── (*) PR ─── (*) MLflow run ─── (*) Model version ─── (*) Release

Release (1) ─── (*) Epic (closed) + (*) Model version (promoted)
  • A Need has ≥1 Epic and ≥1 Story. Epics are optional if the need is small.
  • ADRs are owned by the Need that introduced them but can be referenced by other Needs.
  • A Story can span multiple PRs. A PR must reference at least one Story (or Epic/Need for stand-alone scope).

3. Repo structure (Option A — single repo)

champollion/
├── mkdocs.yml                          (Phase 2 — MkDocs site config)
├── requirements-docs.txt               (Phase 2 — pinned mkdocs + plugins)
├── documentation/
│   ├── index.md                        (Phase 2 — MkDocs landing page)
│   ├── DESIGN_SYSTEM_BLUEPRINT.md     (this file)
│   ├── needs/
│   │   └── CVN-N001-f1-mission.md
│   ├── epics/
│   │   ├── CVN-N001-EA-label-embargo-binary-infra.md
│   │   └── CVN-N001-EB-threshold-calibrator.md
│   ├── stories/
│   │   ├── CVN-N001-US1-embargo-split.md
│   │   ├── CVN-N001-US2-f1-binary-hpo.md
│   │   └── CVN-N001-US3-threshold-calibrator-integration.md
│   ├── design/
│   │   └── CVN-N001-design.md
│   ├── adr/
│   │   ├── 0001-pas-de-zenml-pro.md
│   │   ├── 0002-pas-de-promotion-auto.md
│   │   ├── ...
│   │   └── 0063-ftf-mission-mode-binary.md
│   ├── releases/
│   │   └── CVN-R20260501-01.md
│   ├── templates/
│   │   ├── TEMPLATE_need.md
│   │   ├── TEMPLATE_epic.md
│   │   ├── TEMPLATE_story.md
│   │   ├── TEMPLATE_design.md
│   │   ├── TEMPLATE_adr.md
│   │   └── TEMPLATE_release_note.md
│   ├── architecture/
│   │   ├── index.md                     (Phase 2 — overview)
│   │   ├── workspace.dsl                (Phase 2 — Structurizr DSL, single source of truth)
│   │   └── workspace-reference.md       (Phase 2 — rendering options for workspace.dsl)
│   ├── ADR.md                           (becomes an INDEX after migration)
│   └── <existing flat docs>             (audited, migrated piece-by-piece to hierarchy above)
├── .github/
│   └── PULL_REQUEST_TEMPLATE.md         (enforces need_id + design link)
└── ...

Migration strategy for existing flat docs: - 63 ADRs: migrated in this PR (documentation/adr/*.md) - documentation/F1_80_MISSION_PLAN.md → becomes documentation/needs/CVN-N001-f1-mission.md + documentation/design/CVN-N001-design.md (Phase 1) - documentation/FTF_GUARDRAILS.md → stays as reference for now; may split into ADRs over time - Other flat docs: audited one by one, classified as Need / Epic / Design / ADR / architecture


4. Templates

Six templates live in documentation/templates/:

File Purpose Enforced fields
TEMPLATE_need.md New Need doc need_id, title, problem, impact, kpis, out_of_scope, status
TEMPLATE_epic.md Epic breakdown epic_id, need_id, objective, arch_notes, owner, status
TEMPLATE_story.md User story story_id, epic_id, acceptance_criteria, test_plan, status
TEMPLATE_design.md Design document need_id, authors, options_considered, decision, adr_ids
TEMPLATE_adr.md Architecture Decision Record adr_id, title, status, context, decision, invariants, alternatives_rejected
TEMPLATE_release_note.md Auto-generated release note release_id, epics_closed, models_promoted, backtest_report_url

And one GitHub PR template: .github/PULL_REQUEST_TEMPLATE.md — includes ## Linked work section requiring at least one CVN-* identifier and a link to the design doc.


5. Governance rules (enforced later in Phases 4+)

Phase 0 defines the rules. Phase 4 implements the CI gate.

Rule 1 — Every MLflow run carries: need_id, epic_id, story_id, git_sha, dataset_date_range. Promotion workflow refuses runs without these.

Rule 2 — Every PR body matches the regex CVN-N\d+ OR CVN-N\d+-(E[A-Z]|US\d+). CI gate fails the PR if none found. Exempt labels: docs:, trivial:, chore:.

Rule 3 — Every design doc lists adr_ids[] and these ADRs exist in documentation/adr/. Broken references fail CI.

Rule 4 — No model promotion without: Story closed + Backtest report attached + MLflow Registry alias referencing the origin story.

Rule 5 — Release notes are auto-generated from closed Epics + promoted Models over a date range. Not hand-written.


6. What this system gives us

Question Answer path
Why is this model in prod? Model version alias → MLflow tags → story_id → epic → need doc
What design justified this change? PR body → design doc path → versioned MkDocs entry
What does this release deliver? Release note → list of closed epics → per-epic backtest reports
Where did the training data come from? MLflow run tag dataset_date_range → OHLCV source → feature engineering pipeline commit
What invariants must I respect when editing X? File path → ADR index → relevant ADRs

Eliminates: floating tickets, orphan notebooks, disconnected ML runs, promotion based on a single global metric without business context.


7. Phased rollout (high-level recap of #593)

All phases track as sub-issues of #593. This blueprint is Phase 0's output.

Phase Deliverable Status Issue Est. effort Blocker
0 Blueprint + templates + ADR migration ✅ DONE PR #635 1.5 day
1 OpenProject CE Helm chart + CI deploy step ✅ DONE PR #638 · post-deploy tasks tracked in #636 3 days Phase 0 done
2 MkDocs site (docs.cvntrade.eu) + Structurizr workspace 🟡 IN PROGRESS (skeleton) #637 2 days Phase 0 done
3 MLflow tag schema enforcement + training code updates ⏸️ PENDING 2 days Phase 0 done
4 CI gate refusing PRs without need_id + design link ⏸️ PENDING 1 day Phase 0 done
5 Grafana "Release Traceability" dashboard + DVC evaluation ⏸️ PENDING 3 days Phases 3-4 done

Operator priority (2026-04-23): Phase 1 + Phase 2 first. Phases 3/4/5 follow.

Note on Phase 1 chart split: the OpenProject Helm chart ships with pre-req secret checks — openproject-db-secret + openproject-app-secret must exist before the deploy step runs. See infra/helm/openproject/README.md §Setup for the one-time operator tasks (create PG, generate + store secrets, configure DNS) that precede the first deploy.


8. Definition of done — Phase 0

  • D1-D6 decisions signed (§0)
  • This blueprint committed
  • 6 templates in documentation/templates/
  • PR template in .github/PULL_REQUEST_TEMPLATE.md
  • 63 ADRs migrated from documentation/ADR.mddocumentation/adr/*.md
  • documentation/ADR.md converted to an index (title → per-file link)
  • One sub-issue opened per Phase 1-5 with this doc as reference

9. Out of scope for Phase 0

  • Actual OpenProject deployment (Phase 1)
  • CI gate implementation (Phase 4)
  • Migration of non-ADR existing docs (deferred; audit in Phase 2)
  • Backfill of MLflow tags on past runs (D5 — no backfill)
  • DVC introduction (D6 — skip for now)

10. References

  • Parent issue: #593
  • Issues tracking Phases 1-5: (opened after this PR merges)
  • Related: #567 (observability), #583 (ML Platform v2), #592 (testing pyramid)
  • All 63 existing ADRs — migrated as part of this PR to documentation/adr/*.md