Skip to content

Latest commit

 

History

History
158 lines (113 loc) · 13.1 KB

project-board.md

File metadata and controls

158 lines (113 loc) · 13.1 KB
uid contributing.project-board
title Surgewave Project Board

Surgewave Project Board

The roadmap, in-flight work, and bug triage all live on the Surgewave Project board. This page explains the fields and views — it doesn't replace ROADMAP.md, which still carries the narrative description of each track.

Fields

Field Values Used for
Status Backlog · Next up · In progress · In review · Done Kanban swim-lane
Milestone (built-in) the repo's open work sections M<n> — <theme> (M1 … M6) The ordered section the ticket belongs to — see Milestones and releases. Every ticket has one; a ticket outside a section's themes goes to the next section. Unset is rendered as "Later" in ROADMAP.md.
Area broker · clustering · protocol · storage · security · streams · connect · schema · ai · cli · control · observability · plugin-sdk · docs · site · multi Component filter
Track kafka-compat · performance · ai-pipelines · cluster-correctness · transport · plugin-distribution Multi-phase initiatives that span releases
Project Effort Low · Medium · High Sizing
Effort, Priority (fields exist but carry no options) Unused today. sync-project.mjs still tries to set Priority, which is where its !! Missing option Priority=P1 warnings come from — either add the options or drop them from the script.
Type (native issue field, not a board field) Bug · Task · Feature What it is. Set on the issue itself (org-level GitHub issue types), searchable as type:Bug. Replaced the former kind:* label family and the board's Kind field — do not re-create either.

The ticket vocabulary, the same in every Küstenlogik repository

Where What Values
Type (built-in issue type) What the ticket is Bug · Feature · Task — every issue carries exactly one; the former kind:* labels are retired
Priority (org issue field, on the issue) The order within a section Urgent (now — blocks or burns) · High (this section) · Medium (the next section) · Low (someday)
Effort (org issue field) Planned size Low (a day or less) · Medium (days) · High (a week or more — split it)
Effort (actual) (board field) What it turned out to be, set at Done the same scale — plan next to actual, per issue (Bowire's design)
Milestone (built-in) The ordered work section M<n> — <themes>; a sibling repo mirrors the product's sections as its own milestones
Release (board field, where the board has one) The version a ticket shipped in vX.Y, stamped at the cut; empty while planned
Area (board field) The component per product (terrain, workbench, broker, …); the area:* label says the same for issue search
Status (board field) Where the work sits in the flow Backlog · Next up · In progress · In review · Done
Assignee Who holds it never empty — unassigned means nobody decided
Parent issue (built-in sub-issues) Belongs to / depends on an epic's slices are its sub-issues; "follow-up of #N" in the text is not a link

Order inside a section is the Priority field, read by the roadmap generator; manual sorting on a board is the order of one view and nothing else — not on the ticket, not in the API, gone when the view is regrouped. Use it for the last fine ordering within a priority, never instead of one.

Milestones and releases

Since 2026-09-19 (the convention was rolled out from Bowire) milestones and release versions are decoupled:

  • A milestone is an ordered work section — M1 — Hygiene: CI, dependencies, licences, M2 — Multi-tenancy & data mesh, … Its description is one short statement of the themes it contains and ends with the scope rule: "Scope fixed on : a ticket belongs here if it falls under one of these themes — otherwise into the next section. The section gets its version number only at the release cut." A section does not grow: a ticket outside its themes goes to the next section, or a new section is opened behind the last. Every ticket gets a milestone when it is created.
  • A release gets its version number when it is cut, by content (SemVer). A finished section is the release as a rule; a second section that finished at the same time may ride along. The tag names the sections it ships in its message — git tag -a v0.6.0 -m "Surgewave v0.6.0 — M1 — Hygiene …" — and scripts/resolve-milestone.mjs reads them for the release title and the drafted notes (falling back to a v<base> — … milestone for old tags, then to the frontmost complete section). After the cut the milestone is closed with "Shipped in v0.6.0".
  • Release due = the frontmost open milestone has no open ticket, CI is green, no pull request is open. node scripts/resolve-milestone.mjs v<next> says which section that is.

Recommended views

The board ships with the default All items view. The four views below mirror how Akka.NET's v1.6 project is structured — they need ~30 seconds each to configure in the UI (clone the default view, change layout + grouping):

🗺 Roadmap

  • Layout: Roadmap
  • Group by: Milestone
  • Filter: Status ≠ Done
  • Use for: "What is targeted for v1.6?" — the public-facing release plan

📋 Board

  • Layout: Board
  • Group by: Status
  • Filter: Milestone = current (the frontmost open section)
  • Use for: Operational kanban — what's currently moving

🧩 By Area

  • Layout: Board
  • Group by: Area
  • Filter: Status ≠ Done
  • Use for: Drill-down per component ("show me everything security")

🐛 Bugs

  • Layout: Table
  • Filter: type:Bug
  • Sort by: Priority ↑ then Status ↑
  • Use for: Triage backlog, regardless of milestone

Conventions

  • One field per concept: Milestone is the which section (and thereby the when), Track is the grouped initiative across releases, Area is the component. They overlap deliberately — Milestone is enforced (the bar for shipping), Track is editorial (Auth Phase A / B / C).
  • area:* / track:* labels duplicate board fields on purpose: GitHub issue search needs labels (is:open label:area:security). Project filters need fields. Those two families are kept in sync so an issue is findable from either side. This does not extend to the nature of the work — that is the native issue Type (type:Bug), which exists exactly once and must not be mirrored back into a label.
  • roadmap label flags items that are tracked on the board. Throwaway bug reports don't need it.
  • community-vote label marks feature requests where reactions on the issue are read as priority signal. Don't comment "+1" — react with 👍.
  • PRs close issues via Closes #N so Status flips to Done automatically and the item drops off the active views.

Maintenance

  • New issue created via Convert from Markdown (in the issue editor) or Create issue — the board adds it as Backlog by default.
  • Status transitions: Backlog → Next up → In progress → In review → Done. The last two are driven by PR state where possible.
  • Milestones are managed in Settings → Issues → Milestones. When a milestone closes, its issues move out of the Roadmap view automatically.

Milestone title = release theme

Every milestone's title carries the release headline directly: vX.Y[.Z] — <theme>. The theme is the same one that lands on the GitHub Release once the milestone tags, and it shows in the Project board's Roadmap view as the group heading (since Projects v2 reads the milestone title verbatim).

Format examples that work well:

  • v1.7 — new protocol plugins
  • v1.8 — AI workbench
  • v1.9 — AI for security
  • v1.10 — gRPC Connect

One concept per release. Themes are 2-5 words, concrete enough that a reader knows what the cycle is about (gRPC Connect beats protocol expansion). Avoid +-joined dual themes — if a cycle is gathering two big buckets, split them into two milestones instead of bundling. Splitting forces a decision about which bucket is the actual focus; bundling defers it.

Why pre-commit a theme at planning time: the headline defines what the cycle is about — what we'd be embarrassed to ship without. It anchors the milestone discussion ("does this issue serve the theme?"), avoids the retrospective scramble of summarising whatever happened to land, and gives the team a one-line elevator pitch through the cycle. Mid-cycle pivots are fine — rename the milestone (GitHub keeps the audit trail).

Mechanical consequences:

  • release.yml parses the matching milestone's title when creating the GitHub Release and uses the <theme> tail as vX.Y.Z — <theme>. No hand-editing of the release title required.
  • scripts/generate-roadmap.mjs renders the full title as the section heading in ROADMAP.md so the offline view matches the Project board.
  • The milestone description stays free-form for slip context, stakeholder hints, &c. — no machinery parses it.
  • If the milestone title is bare (v2.0 with no — <theme> tail), the release falls back to a bare vX.Y.Z title and the roadmap section shows no theme — so missing themes are visible by their absence rather than crashing the pipeline.

CLI ergonomics caveat: gh issue list --milestone v2.0 no longer matches when the milestone is renamed to v2.0 — <theme> — gh matches the full title verbatim. Either use the full title, or look up by milestone number (--milestone <N>).

Automation

The roadmap is wired to maintain itself once an issue lands with label:roadmap:

Event What happens
New issue with roadmap label .github/workflows/add-to-project.yml attaches it to the Project (Status defaults to Backlog)
Issue closed roadmap-sync.yml regenerates ROADMAP.md from the Project + commits
Issue title / label / milestone change same — roadmap-sync.yml re-renders
PR merged that uses Closes #N Status flips to Done via Project workflow (UI-side, see below)
Daily 05:23 UTC Safety-net roadmap-sync.yml cron

One-time setup (single PAT, org-secret)

add-to-project.yml and Surgewave.Bootcamp/notify-surgewave.yml share one organization secret BOWIRE_DISPATCH_TOKEN. The default GITHUB_TOKEN can't write to org-level Projects nor dispatch into sibling repos, so a PAT is required either way — but only one.

  1. Create a fine-grained PAT — Settings → Developer settings → Personal access tokens → Fine-grained.
    • Resource owner: Kuestenlogik
    • Repository access: Kuestenlogik/Surgewave + all sibling Surgewave.* repos (Bootcamp, Templates, VulnDb, Protocol., Sdk.)
    • Repository permissions: Contents: R/W, Issues: Read, Pull requests: Read
    • Organization permissions: Projects: Read and write
  2. Save as organization secret BOWIRE_DISPATCH_TOKEN in Kuestenlogik org settings → Secrets → Actions → New organization secret. Repository access: "Selected repositories" → tick every Surgewave.* repo.
  3. Both workflows pick it up automatically; nothing per-repo to configure.

Project-side workflows (UI-only)

Configure once in the Project UI — these aren't exposed via API yet, so they live alongside the GitHub Action workflow files.

  1. Open https://github.com/orgs/Kuestenlogik/projects/4 → ⚙ Settings → Workflows
  2. Item closed → enable → Set status to Done.
  3. Pull request merged → enable → Set status to Done.
  4. Auto-add to project → leave disabled for Kuestenlogik/Surgewave (the GitHub Action above handles that with the label filter). For sibling Surgewave.* repos that don't carry the workflow file, enable Auto-add with filter repo:Kuestenlogik/<RepoName> label:roadmap is:issue,pr.

Sibling-repo wiring options (Project-side auto-add vs Action-side label-filter vs back-fill) are picked per-repo; the Project-side default works for most cases.

Migration from ROADMAP.md

The pilot batch lives on the board now (6 items from In progress + Next up). ROADMAP.md is unchanged for the moment. Once the board's daily feel is validated, the plan is:

  1. Migrate the rest of ROADMAP.md to issues, one per ### heading.
  2. Trim ROADMAP.md to a ~30-line index that points at the board and the In progress + Next up highlights, regenerated periodically from the board.
  3. The marketing site's roadmap.html pulls from the Project's GraphQL API (cached as site/_data/roadmap.yml via a GitHub Action) so visitors see live data without the page making a network call.

Rollback plan: closing the issues and deleting the project + milestones restores the previous "ROADMAP.md is the only source" state. The labels stay — they're useful regardless.