Issue Triage Policy

June 5, 2026 · View on GitHub

This document describes how issues and pull requests are routed, prioritised and closed in scpn-quantum-control. It exists so that a first-time contributor knows when to expect a response and what a given label means.

Closes audit item B11.

Cadence

Triage runs weekly, on Tuesday 09:00 CET. Off-week issues are still read; they just might not get a label or owner until Tuesday.

Emergencies (hardware campaigns in-flight, a published release regressing, a security disclosure) bypass the weekly cadence — ping protoscience@anulum.li directly and the owner will reply within 24 hours.

Label taxonomy

Every triaged issue gets one label from each of three axes.

Kind (what it is)

LabelApplied when
bugThe code does not match documented or obvious behaviour.
enhancementNew feature, new API surface, new algorithm.
questionUser cannot get a thing to work; not clear whether it's a bug.
docsDocs are wrong, missing, or unclear.
infrastructureCI, packaging, release process, dependency management.
securityVulnerability, hardening, supply-chain concern.
scienceClaim correctness, reproducibility of a published number, Gap-2 / Gap-3 work.

Priority (how urgent)

LabelSLA responseSLA closureTypical examples
P0-critical24 h7 daysData corruption, security leak, release blocker.
P1-high3 days30 daysWrong scientific number, hardware campaign regression.
P2-medium1 week90 daysUsability annoyance, missing feature with a workaround.
P3-lowTriaged weeklyNo SLANice-to-have, cosmetic, speculative.

Status (where it is)

LabelMeaning
triageAuto-applied to every new issue until triaged.
needs-infoWaiting on reporter for a reproducer, log, or clarification. Stale after 30 days → closed with a polite note.
acceptedTriaged, prioritised, an owner may or may not be assigned yet.
in-progressSomeone is actively working on it. The owner commits to closing it or flipping it back to accepted within 30 days.
blockedBlocked on external dependency (IBM quota, upstream library bug, CEO decision).
good-first-issueSafe entry point for a new contributor.
help-wantedOwner exists but welcomes parallel work.
duplicateClosed with a link to the original.
wontfixClosed by maintainer with a reason that goes in the close comment.

Routing

New issues are routed to an owner by subsystem:

AreaOwner
hardware/ (IBM Runtime, Heron, pennylane adapter)Miroslav Šotek
analysis/ (DLA parity, Koopman, BKT)Miroslav Šotek
bridge/ (Kuramoto-XY, SSGF)Miroslav Šotek
qsnn/ (spiking)Miroslav Šotek
CI / packagingAny maintainer
Rust engine (scpn_quantum_engine)Any maintainer
DocsAny maintainer

(As of 2026-04-17 there is a single maintainer. Additional owners will be listed here as collaborators join.)

Closure criteria

An issue is closed when one of the following is true:

  • The fix lands on main and a test locks in the expected behaviour.
  • A follow-up task is queued in the roadmap and linked in the issue.
  • The maintainer decides wontfix and explains why in the close comment.
  • The reporter has not responded to a needs-info request for 30 days.

Closed issues remain indexed and searchable. Re-opening is welcome when new evidence arrives.

Security disclosures

Security issues use private vulnerability reporting in GitHub Security Advisories, not the public issue tracker. See SECURITY.md and .well-known/security.txt for the disclosure process. Response SLA is 24 hours; fix SLA scales with severity per docs/THREAT_MODEL.md.

PR review

Pull requests get the same triage treatment as issues, plus:

  • CI green is a pre-condition for merge. A red CI is blocking feedback; comments can still land.
  • Maintainer review is typically ≤ 72 hours on P0 / P1, ≤ 1 week on P2, weekly cadence on P3.
  • The required authorship line is required on every commit (see CONTRIBUTING.md).

Stale-bot policy

No stale-bot. Issues that rot do so deliberately — we'd rather leave a real bug open than auto-close it and lose the signal. The needs-info 30-day close is the one automated exception.


Worked examples per label

Abstract label definitions are easy to misapply. These examples are drawn from issues opened against this repository (or identical patterns we expect), with the final labels and closure trajectory.

Example: bug + P0-critical + in-progress

"Running scripts/phase1/run_dla_parity.py --L 4 on a freshly cloned repo raises ModuleNotFoundError: scpn_quantum_engine even after pip install -e '.[rust]'."

Labelling:

  • Kindbug: the documented install path is broken.
  • PriorityP0-critical: blocks reproducibility of the published Phase 1 numbers.
  • Statustriageacceptedin-progress.

Response SLA: 24 h to acknowledge, 7 days to fix. Typical fix trajectory: reproduce on a clean VM, identify whether the [rust] extra is actually building the wheel (a maturin develop vs pip install -e .[rust] mismatch is the usual culprit), land the fix plus a regression test that runs on a fresh venv in CI.

Example: enhancement + P2-medium + accepted

"Please add a --seed flag to scripts/phase1/run_dla_parity.py so two independent runs can start from the same classical initial state."

Labelling:

  • Kindenhancement: new CLI surface.
  • PriorityP2-medium: workaround exists (edit the script directly), but the request is reasonable for reproducibility.
  • Statusaccepted, no owner — up for grabs.

Closure trajectory: a contributor picks it up, adds the flag plus a regression test that the same seed produces the same JSON result, merges. The issue closes automatically on the merge commit reference.

Example: question + P3-low + needs-info

"Is the DLA parity asymmetry reproducible on ibm_brisbane?"

Labelling:

  • Kindquestion: user is asking, not reporting.
  • PriorityP3-low: the Phase 1 campaign ran on ibm_kingston; extending to a second machine is interesting science but not a release blocker.
  • Statustriageneeds-info: ask whether the user has run the reproducer themselves, what ZNE settings they used, and how many shots.

If the reporter does not respond in 30 days, the needs-info timer auto-closes the issue with a polite pointer to re-open when data arrives. If they respond with concrete numbers, the issue flips to science + P2 for investigation.

Example: security + P0-critical (reported privately)

Never appears in the public tracker. See SECURITY.md. The flow is:

  1. Private disclosure via GitHub Security Advisory draft.
  2. Maintainer acknowledges within 24 h.
  3. CVSS score is computed against docs/THREAT_MODEL.md; High and Critical get a private branch with a tight timeline (fix within 7 days or 30 days depending on CVSS).
  4. Coordinated disclosure: advisory is published alongside the fix commit; the reporter is credited unless they opt out.
  5. A public post-mortem lands in <private-local-record> (gitignored while in draft, promoted to the public SECURITY_INCIDENTS.md after 90 days).

Example: docs + P3-low + good-first-issue

"docs/pipeline_performance.md §21 still references the pre-v0.9 function name build_kuramoto_coupling; it was renamed to build_knm_paper27 in v0.9.0."

Labelling:

  • Kinddocs.
  • PriorityP3-low: no user harm, just staleness.
  • Statusgood-first-issue: a single-line grep-and-replace PR is a classic newcomer entry point.

Closure: the contributor submits a PR, CI confirms the page builds under mkdocs build --strict, maintainer merges within a week.

Example: infrastructure + P1-high + blocked

"Dependabot wants to bump qiskit from 1.4 to 2.3 but our qiskit-ibm-runtime pin caps at 1.x."

Labelling:

  • Kindinfrastructure.
  • PriorityP1-high: dep drift is a security surface.
  • Statusblocked: we cannot take the bump until qiskit-ibm-runtime 2.x lands and we migrate. Tagged with a blocked-by:upstream-runtime-2.x sub-label.

The issue stays open. Triage revisits weekly to check whether the upstream blocker has moved.

Example: science + P1-high + in-progress

"docs/pipeline_performance.md reports 95 % coverage for the surface-code module but my local run shows 63 %."

Labelling:

  • Kindscience (reproducibility of a claim).
  • PriorityP1-high: wrong scientific number.
  • Statusacceptedin-progress.

Closure: reproduce locally, identify whether the stale number is in the doc (doc fix) or the code regressed (code fix). Either path lands a coverage-regression test so the same drift is detected earlier next time.

Label combinations and what they mean

Not every combination is sensible. This matrix documents the ones we use and calls out a few that would signal a labelling mistake.

Kind × PriorityMeaning
bug × P0Release blocker. Stops everything else.
bug × P1Confirmed incorrect behaviour, workaround exists.
bug × P2Edge-case bug a small fraction of users hit.
bug × P3Curiosity bug — observed, but no user is blocked.
security × P0Active vulnerability, coordinated disclosure.
security × P1Hardening gap, no active exploit.
enhancement × P0Invalid combination. If an enhancement is P0, it is actually a bug. Re-label.
enhancement × P1Strategic feature with a committed timeline.
question × P0Invalid combination. Either the user is blocked (bug) or they are asking about something low-priority. Re-label.
science × P0Published number is wrong. Retract + fix.
docs × P0Rare but valid. Used when a security procedure doc is wrong in a way that could lead users to leak credentials.

Flow diagrams

Textual flow for the modal path of an issue:

new issue

triage label auto-applied

Tuesday 09:00 CET (or emergency escalation)

+---------------------+
| Kind decided        |
| Priority assigned   |
| Owner assigned      |
+---------------------+

status: accepted
  ↓            (reporter clarification needed?)
  ├── yes → needs-info → (30 days) → auto-close
  ├── no

status: in-progress
  ↓            (blocked externally?)
  ├── yes → blocked (weekly re-check)
  ├── no

fix lands on main + test

issue closes (auto-referenced by commit)

For pull requests, the flow is identical except the "fix lands" step becomes "CI green + maintainer review + merge".

Response time tracking

We do not run a response-time bot. The SLA table above is a policy commitment, not a bot-enforced deadline. The expectation is that a maintainer glances at the triage queue once a day. The GitHub notifications inbox counts as the queue.

If the response SLA slips, the maintainer's next action is to acknowledge late and offer a concrete next step — never silently keep the timer running.

Collaborators and access

As of 2026-04-17 the repository has one maintainer (Miroslav Šotek) with write access, plus Dependabot and GitHub Actions automation scoped to repository operations.

Paths toward further collaborator access:

  1. Contribute three merged PRs that each add a test.
  2. Request maintainer access in an issue; the CEO decides on a case-by-case basis.
  3. Collaborators are listed publicly in .github/CODEOWNERS.

Escalation

If the weekly-triage cadence is missed for more than two weeks in a row, or if an open P0-critical has not been responded to in 72 hours, escalate in this order:

  1. Second maintainer (when one exists).
  2. CEO email: protoscience@anulum.li.
  3. Public tweet tagging the maintainers (last-resort path, only after the first two have had 24 hours to respond).

Relationship to other docs

  • CONTRIBUTING.md — what a contributor does before opening an issue or PR (linting, coverage, required authorship line).
  • SECURITY.md — private disclosure flow; triage entry point for any security label.
  • docs/THREAT_MODEL.md — severity calibration for security issues.
  • docs/falsification.md — where a science label is tested against a documented falsification criterion.
  • docs/language_policy.md — which compiled-language tier a new compute function should use.
  • ROADMAP.md — where P2 / P3 enhancements are staged when they are accepted but not yet scheduled.

Changing this policy

Update this file in the same commit that changes the triage behaviour (label rename, SLA change, routing update). A documentation-only PR that does not change policy is not needed — edit this file directly and land on main.

Intentionally not covered

  • Code of Conduct — the project Code of Conduct lives in CODE_OF_CONDUCT.md; triage does not enforce it, the maintainer does.
  • Commercial licensing questions — those go to protoscience@anulum.li directly, not the issue tracker.
  • Research collaboration inquiries — same as above.
  • Job applications — we are not hiring; please do not open an issue asking.

Revision history

DateChange
2026-04-17Initial policy (closes audit item B11).
2026-04-17Worked examples, label combination matrix, and flow diagrams added under documentation-standard remediation.