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.
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.mddocumentation/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.md→documentation/adr/*.md -
documentation/ADR.mdconverted 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