ADR-023: Codeberg-centric workflow
Context
Project management state was scattered across four stores:
- Allium specs — behavioral requirements and
deferredmarkers used as feature lifecycle flags - roadmap.yaml — feature lifecycle status, edited manually to mark features complete
- Documentation pages —
:::note[Planned — Phase N]admonitions removed manually per feature - Session context JSON — intra-session task tracking with its own status enum
Sync between them was manual and relied on Claude following a ceremony checklist. Small fixes bypassed the workflow entirely, causing silent drift. The gap scan in implementation-workflow.md existed to detect this drift, but ran only when explicitly triggered. The developer lost overview of what was done, where things stood, and what needed doing next.
Decision
Codeberg becomes the single operational truth for all work tracking.
Sources of truth
| Concern | Authority | Derived |
|---|---|---|
| Feature lifecycle | Codeberg issues + milestones | roadmap.yaml, feature pages |
| Behavioral specification | Allium specs (in-repo) | LLM enforcement |
| Documentation content | Hand-written docs | Starlight site |
| Plans and designs | Codeberg issue attachments | Ephemeral .claude/plans/ |
Structure
Issues and milestones are the primary interface for feature lifecycle, bugs, chores, and design decisions.
Labels encode classification and state:
Kind/*— Feature, Bug, Enhancement, Chore, Documentation, SecurityStatus/*— Blocked, Deferred, Abandoned, Needs InfoPriority/*— Critical, High, Medium, Low
Milestones map to phases (1–6) plus parallel tracks and a Backlog milestone for deferred work.
Derived artifacts
roadmap.yaml becomes a derived artifact maintained by CI after each merge — never edited manually. The sync job reads closed issues and open milestones to update status fields.
Feature pages inherit their status from roadmap.yaml via generate-features.ts. Planned markers are removed by the CI sync job, not by hand.
Allium specs retain behavioral and process specification only. Feature lifecycle tracking (deferred markers used as lifecycle flags) moves to Codeberg labels. Allium deferred markers continue to flag unspecified behavior only.
Session context
Session context tracks “working on issue #42” instead of carrying independent task status. The task list in the session JSON becomes a scratchpad for the current work session, not a source of truth.
CI pipeline
- Blast radius analysis — on PRs, report which allium rules and doc pages are affected
- Status sync — post-merge job: close issues, update roadmap.yaml, remove planned markers
- Zombie patrol — weekly job: detect issues referenced in allium or docs but closed without sync
Consequences
Positive
- Single place to check project status — open the milestone, see what remains
- CI prevents drift; no manual ceremony needed between implementation and documentation
- Issue templates capture context (problem, acceptance criteria, references) consistently
- Attachment-based plans are discoverable alongside their issue
- Session context becomes lighter — tracks location, not global status
Negative
- One-time migration effort: open issues for all in-flight work, close completed work
- Dependency on Codeberg API availability for CI sync jobs
deferred-features.alliumis deleted; historical record moves to closed issues withStatus/Deferredlabel
Neutral
- The implicit gap scan ceremony in
implementation-workflow.mdis superseded by the CI blast radius job — the same checks run automatically on every PR
Supersedes
The implicit workflow defined in .claude/rules/implementation-workflow.md: manual gap scan ceremony, manual roadmap updates, manual planned marker removal.
Related
- ADR-002: Bun runtime and workspaces — runtime context
- Design document attached to Codeberg issue #1