Skip to content

ADR-0069 — OpenProject is the project orchestrator (work pulled from versions, closed when version closes)

Status: active Date: 2026-04-27 Introduced by: ADR-52 (committee auditability), ADR-68 (committee = default review channel), Issue #723 Supersedes: none


Context

The development process documented in CLAUDE.md (steps 1-13) starts at "create a GitHub issue". In practice this has produced two failure modes:

  • Drift between intent and action — the operator picks the next thing to work on from chat scrollback or memory, not from a board. Within ~2 weeks the actual sequence of merged PRs no longer matches what the user thought was being worked on.
  • No sprint cadence — gates that the epic plan said would happen "after the quick-win bundle" never had a concrete trigger. Decisions slipped because no calendar event forced them.

We have OpenProject deployed (openproject.cvntrade.eu, helm chart infra/helm/openproject/) with the full Need → Epic → Story → Release hierarchy populated for the active mission (CVN-N001 F1). On 2026-04-27 we structured the F1_buy boost initiative as Epic CVN-N001-EE with 11 Stories (CVN-N001-EE-S01S11) and assigned them to 9 OpenProject versions (= sprints): F1B-S0-Prereqs, F1B-S1-QW-PhaseA, F1B-S2-QW-PhaseB, F1B-S3-QW-PhaseC-Eval, F1B-S4-BigBet-Gate, F1B-S5-BigBet-Impl, F1B-S6-Sequence, F1B-Pre-Live, F1B-Backlog.

The infrastructure is in place; the discipline is not. This ADR makes the discipline explicit and binding.

Decision

Every unit of dev work MUST start by picking a Story from the OpenProject roadmap of an open version, and MUST end by closing the Story (and, when the last Story closes, by closing the version).

The OpenProject roadmap is the system of record for "what is in flight" — not chat, not memory, not issue lists.

The trigger flow is:

Phase Action OP state transition
Pick Choose a Story from the active version's roadmap Story status NewIn progress
Implement Follow CLAUDE.md steps 1-12 (issue, plan, review, code, PR, merge, CI, system test)
Validate Confirm DoD : PR merged on main, CI green, system test passed, validation note in GH issue
Close Story Set Story status to Closed in OP, comment with PR / commit references Story In progressClosed
Close version When all Stories in the version are Closed AND the version's gate (per epic doc) is met, close the version via OP UI (Settings → Versions → Edit → Status closed) Version openclosed
Roll-over Run §16.4 retrospective, open the next version, repeat

A "Story" in this ADR is any work-package of type Story in OpenProject — typically one Story = one GH issue = one PR per CLAUDE.md dev process.

Invariants

  • Every Story has a GitHub issue linked — the github_issue_url custom field MUST be set on the Story (already enforced by scripts/openproject_import_gh.py). A Story without a GH issue cannot be picked.
  • Every PR description carries the Story's cvn_id — e.g. CVN-N001-EE-S01 — so the Story-to-PR link is unambiguous and the closure trigger is automatic. Same convention as ADR-68 §15 for committee sessions.
  • Single-WIP per developer — at most one Story is In progress per developer at any time. Switching off a Story without closing it requires moving it back to New with a comment explaining why (interruption is a context tax, not a hidden one).
  • Versions are scoped to an Epic — naming convention <epic-shortname>-<phase>-<descriptor> (e.g. F1B-S1-QW-PhaseA). A version that mixes Stories from multiple Epics defeats the per-Epic gate review.
  • Closing a version is a deliberate ritual, not a side-effect — even when the last Story closes, the version stays open until the operator explicitly verifies the gate (per the Epic's §4 acceptance criteria) and writes a one-line closure note in the version description (see OPERATIONS §16.4).
  • A Backlog version is the only place Stories without dates live — VETO / deferred-indef. Stories belong here. Pulling work from Backlog requires written justification (issue comment) since by definition it sits outside the planned cadence.
  • Hot-fixes follow the same flow — if a production incident requires an unplanned PR, create a Story marked [hotfix] in the currently open version. No exception, no shortcut.

Alternatives rejected

  • GitHub Projects — no native parent / child Need → Epic → Story → Release hierarchy, no per-Need cumulative progress, no first-class version concept. Would require us to rebuild the OP data model in YAML.
  • Linear / Jira / Shortcut — additional vendor, additional cost, additional auth surface. OP is already deployed and self-hosted on the cluster.
  • Plain documentation/epics/*.md + manual tracking tables — describes the work but does not orchestrate it. Operator still has to remember what to pick next, which is the failure mode this ADR addresses. The markdown epic files remain (they hold the design rationale and gates) but they no longer drive sequencing.
  • Pick whatever, align in chat — informal mode the project ran on for ~6 months. Drifted within 2 weeks every time.

Consequences

  • Positive: roadmap is the single source of truth — drift between agreed plan and actual sequence surfaces immediately when a Story sits in the wrong version.
  • Positive: gate reviews happen at predictable points (end of each version) instead of "when the operator remembers".
  • Positive: each Story closure rolls progress to its Epic + Need automatically via OP relations — Need-level dashboards are now meaningful.
  • Positive: synergistic with ADR-68 — committee plan_review runs at version-start, pr_review per Story, experiment_review at version-close gate.
  • Negative: ~2 minutes overhead per Story start (open OP, change status, link branch). Acceptable given the drift cost.
  • Negative: requires the operator to keep OP versions current. Stale versions defeat the purpose; the §16.4 retrospective ritual is the mitigation.
  • Neutral: GitHub remains the source of truth for code, PRs, CI, CodeRabbit. OP only owns which Story is being worked on, not the code itself.

Rollback

This ADR is process, not code — rollback = remove this file and revert the CLAUDE.md / OPERATIONS.md edits introduced by issue #723. The OpenProject versions and Story assignments stay (they are descriptive metadata regardless of policy). Only the discipline layer goes away.

If the discipline proves systematically wasteful (e.g., > 30 % of Stories require version reassignment within their planned sprint over a sample of ≥ 30 Stories), revisit the version-naming convention or the sprint length before retiring the policy.

References

  • ADR-52 — Auditabilité des sessions du comité d'experts (sister discipline)
  • ADR-57 — ADRs in English
  • ADR-68 — Expert Committee = default review channel (sister discipline)
  • CLAUDE.md §Process de développement — steps 0 (pick) and 14 (close Story / version)
  • documentation/OPERATIONS.md §16 — Sprint orchestration runbook
  • scripts/openproject_import_gh.py — issue → Story import, idempotent
  • documentation/F1_BUY_BOOST_PLAN.md + documentation/epics/CVN-N001-EE-f1-buy-boost.md — first epic structured under this discipline (9 versions, 11 Stories)
  • infra/helm/openproject/README.md — chart and admin setup
  • Issues : #593 (OpenProject infra Phase 1), #723 (this ADR)