Step 1: Issue Selection

The single biggest predictor of whether your Capstone ships is the issue you pick in the first few days. Pick something too large and you will still be tracing KVM_RUN exits in week three. Pick something already half-fixed and you will burn days before a maintainer points it out. Pick something you cannot reproduce and you have nothing to build on.

A good Capstone issue is real (open, maintainer-acknowledged), tractable (fixable in a focused diff, not a redesign), reproducible (you can make it fail on demand), and matched to your level (it lives in a subsystem you traced in Levels 1–9). This step is how you find one with gh, score it, and claim it without stepping on anyone.


Goal

Leave this step with one issue number you can defend as the right choice, a public claim comment, a written scope estimate, and a feature branch. Everything downstream assumes the issue is well-chosen; an hour of selection discipline saves a week of thrash.


Where the Issues Live

Everything is on GitHub, and you will drive it from the terminal with gh — never trust a cached screenshot of the issue list, because the label vocabulary and the open set drift. Authenticate first (gh auth status), then:

REPO=firecracker-microvm/firecracker

# The whole open issue list, newest first.
gh issue list --repo $REPO --state open --limit 50

# Scoped, approachable work — start here.
gh issue list --repo $REPO --label "good first issue" --state open

# Confirmed defects with observable wrong behavior — the best Capstone fuel.
gh issue list --repo $REPO --label "Type: Bug" --state open --limit 50

# See the live label vocabulary (it changes; do not hard-code it from this page).
gh label list --repo $REPO --limit 100 | rg -i "bug|enhancement|good first|status|priority|kani"

Note: Firecracker's label scheme uses prefixed labels like Type: Bug, Type: Enhancement, Status: Awaiting review, Priority: ..., plus good first issue, Kani (formal verification), and Roadmap: ... (verify the exact strings with gh label list on your day — they evolve). Match on what the list actually returns, not on what this guide remembers.

The label subset that matters for a Capstone:

Label (verify exact string)What it means for you
good first issueA maintainer scoped it to be approachable. Start here.
Type: BugA defect with observable wrong behavior. Best Capstone fuel.
Type: EnhancementA feature request. Small, well-specified ones are fine; large ones are not.
Status: Awaiting reviewOn an issue, often means a maintainer wants discussion/PRs.
KaniA formal-verification (model-checking) task. Excellent if you did the relevant Level work; a steep first Capstone otherwise.
Roadmap: ...Large planned features. Avoid for a Capstone.

What Makes an Issue Tractable

Score a candidate against these before you claim it. The sweet spot is a Type: Bug (ideally also good first issue) where a maintainer has already written "this is wrong because X; the fix is probably around SomeStruct::some_fn." That comment is gold — a pre-validated root-cause hypothesis you get to confirm and implement.

SignalGoodBad
Blast radius1–3 files in one module (vmm/src/devices/..., vmm/src/vmm_config/..., the API server)Spans vmm, firecracker, jailer, and a rust-vmm dep
SurfaceA wrong value, a missing API validation, an off-by-one in a virtqueue, a bad error message, a flaky test"Add PCI hotplug," "rework the device manager"
ReproducibilityA curl/config-file sequence or a pytest makes it fail every time"Sometimes under 20x oversubscription in production"
AgreementA maintainer confirmed it is a bug and hinted at the fix siteOpen question whether it is even a bug
Attack surfaceFix shrinks or holds surface; no new syscalls, no new deviceAdds an emulated device or widens the seccomp allow-list
BWC exposureNo API contract or snapshot-format change, or a clearly versioned oneChanges the snapshot layout or a REST field with no compatibility story
Test reachabilityYou can name the pytest in tests/integration_tests/ that would assert the fix"Only reproduces on a specific host CPU at scale"

Categories that age well as Capstones

  • An API validation gap. A field on /machine-config, /drives/{id}, /network-interfaces/{id}, or /balloon accepts a value it should reject, and the failure surfaces deep in the builder or a device instead of at the edge with a clear 400. Fix lives near rpc_interface.rs / vmm_config/ validation. Small, user-visible, testable. See the API server deep dive and Stage 4.
  • An error-message / diagnostics defect. Firecracker returns the wrong error variant, or a message omits the field an operator needs. Low blast radius, genuinely appreciated. See Level 8 Lab 3 and Stage 3.
  • A virtio edge case. A block or net device mishandles a specific descriptor chain, a zero-length write, a feature-negotiation corner, or a rate-limiter boundary. Contained in one devices/virtio/<dev>/ module. See the virtqueues deep dive and Stage 7.
  • A flaky integration test rooted in a real race. A tests/ test that fails ~1 in N because of a missing wait or a genuine ordering bug in the VMM. Both are good — be honest in your root-cause doc about which it is. See Level 5 Lab 4 and Stage 9.
  • A snapshot-compatibility nit. A field added without a version bump, or a device's Persist state that doesn't round-trip. Deeper, extremely instructive. See the snapshotting deep dive and Stage 8. Pick this only if you did the Level 9 snapshot lab.

Categories to avoid for a first Capstone

  • Anything Roadmap: ..., or a feature that adds a device or widens the attack surface — "QEMU has it" is not an argument here, and the bar is high. Read the minimal-device-model philosophy to understand why.
  • New REST endpoints, new snapshot fields, new seccomp syscalls — each carries a compatibility or security story that is its own multi-week skill.
  • Pure performance issues with no correctness component ("make boot faster"). Proving no regression across architectures is a discipline of its own — see Stage 10.
  • Anything where two maintainers disagree in-thread about whether to fix it. You do not want to land in the middle of that as your first contribution.

Check It Is Not Already Taken

Before you invest a day reproducing, spend five minutes confirming nobody is on it — with gh, not by eyeballing the web page:

REPO=firecracker-microvm/firecracker
N=<issue-number>

# Read the full thread, including assignees and the latest comments.
gh issue view $N --repo $REPO --comments

# Is there already a PR referencing it? (PRs that say "Fixes #N" link automatically,
# but search the body/title too, since not everyone uses the keyword.)
gh pr list --repo $REPO --state open --search "$N in:title,body"
gh pr list --repo $REPO --state all  --search "$N in:title,body" --limit 20

Then judge:

  1. Assignee / "I'll take this". If someone is assigned or recently said they're working on it, move on.
  2. An open PR. If a non-stale PR references the issue, the work is taken.
  3. A stale PR. Months of silence, author gone? You may comment offering to pick it up — but say so explicitly and wait for a maintainer's nod.
  4. The date. A good first issue opened two days ago may have three people circling silently. An issue open for months with a maintainer "PRs welcome" is much safer.

Match It to Your Level

This is the part the OpenSearch capstone can't teach you — Firecracker bugs are stratified by subsystem, and the issue roadmap's 12 stages map directly to the Levels you completed. Pick an issue whose subsystem you have already traced:

If the issue is about…You should have done…Deep dive to reopen
API field validation / error variantsLevel 3, Level 8API server
Threading / channel / event loopLevel 3VMM threading model
vCPU run loop, CPUID/MSR, a VM-exit edgeLevel 4vCPU run loop & VM exits
Boot / cmdline / guest memory layoutLevel 6The boot sequence
virtio block/net/vsock/balloon/rngLevel 7virtqueues, virtio-block
seccomp / jailerLevel 9seccomp filtering, the jailer
snapshot / Persist / UFFDLevel 9snapshotting

If the issue lives in a subsystem you have not traced, that is not the Capstone — it is a reason to go do that Level first, or to pick a different issue. The Capstone tests applying what you know, not learning a subsystem cold under time pressure.


Claim It

Firecracker does not require formal assignment to start, but claiming politely prevents duplicate work and signals seriousness. Comment via gh:

gh issue comment $N --repo $REPO --body "I'd like to work on this. Plan: reproduce \
it deterministically with a config-file boot (or a failing pytest in \
tests/integration_tests/), trace through <subsystem>, and open a PR with an \
integration test. Anything I should know about the intended fix direction or any \
snapshot/API-compatibility constraints before I start?"

That comment claims the issue, shows you already have a plan, names the subsystem (proving you read the code), and explicitly invites a maintainer to redirect you before you spend days. It also surfaces the two questions Firecracker reviewers care most about up front: compatibility and attack surface.

Warning: Do not comment "Can I work on this?" and then vanish for a week. That locks an issue in social limbo and annoys maintainers more than anything else. If you claim it, start within a day or two — or un-claim it.

See design-via-github for how to read a thread for the maintainers' real intent.


Scope Estimation and Reproducibility Pre-Check

Write a one-paragraph scope estimate for yourself before you commit, and save it to capstone-work/scope.md. Answer:

  • How many files do I expect to touch? Grep the symbols named in the issue — do not trust the issue's own file references, locate them yourself:
    rg -n "the_function_or_struct_from_the_issue" src/
    
    If the answer is "dozens across crates," reconsider.
  • Is there an API or snapshot contract change? If yes, there is a compatibility story (a versioned field, a Persist migration). Fine for week two; not ideal for the first thing you touch. See compatibility.
  • Does it touch the attack surface? A new syscall means a resources/seccomp/ change with a security argument. Budget extra and read seccomp-filtering.
  • Can I name the test that proves the fix? If you cannot imagine the pytest assertion, you do not understand the bug yet. Keep reading the thread and the code.

Then do a 30-minute reproducibility smoke test now (the full job is Step 2):

# Build current main once, so the smoke test is honest.
tools/devtool build
# If the issue is API/boot-shaped, start FC and try the exact curl/config from the issue.
# If it is internals-shaped, find the nearest test and try to make an assertion fail:
rg -n "<Component>" tests/integration_tests/

If you cannot make it misbehave in 30 minutes, note that. A bug you cannot reproduce in week one is a bug you may never reproduce — and an irreproducible Capstone is a dead Capstone. If the issue says "only on Firecracker v1.X with these settings," check out that tag (git checkout v1.X.0) and try exactly that.


Selection Rubric

Score your candidate out of 10 before committing. Pick one that scores ≥ 7.

Criterion012
Maintainer confirmed it is a real bug/taskUntriaged, unclearSome discussionConfirmed + fix hint
Blast radiusMany modules / cross-crate2–4 files, one module1–2 files, one component
ReproducibilityCan't make it failFails sometimesDeterministic repro in reach
Compatibility / attack-surface riskNew device / syscall / snapshot field, no planVersioned contract changeNo contract or surface change
Test reachability + level matchCan't imagine the test / unknown subsystemIntegration test onlyClear pytest + a subsystem you traced

A 9–10 is a near-ideal first Capstone. A 7–8 is solid and slightly stretchy. Below 7, keep looking — gh issue list is long and a better candidate is usually one search away.


Deliverable for Step 1

  • A chosen issue number #N, scoring ≥ 7 on the rubric.
  • A claim comment posted via gh issue comment with a brief plan naming the subsystem and asking about compatibility/attack surface.
  • A one-paragraph scope estimate in capstone-work/scope.md.
  • A 30-minute reproducibility smoke-test result noted (did it misbehave?).
  • A feature branch off main: git checkout -b fix/issue-N-short-description.

Rubric Hooks

This step feeds Reproduction (your smoke test is the seed of the deterministic repro) and Communication (the claim comment is the first thing a maintainer sees of you). A vague claim or an unverified "it should be reproducible" caps both dimensions. See the evaluation rubric.


Validation / Self-check

Before advancing to Step 2:

  1. You can state, in one sentence, the wrong behavior the issue describes — not the desired behavior, the wrong one.
  2. You confirmed with gh that no open or recent PR already fixes it.
  3. You posted a claim comment and ideally got a maintainer acknowledgement.
  4. You grepped the symbols named in the issue and the touch count is small.
  5. You can name the subsystem and the matching Level/deep dive.
  6. Your scope estimate honestly fits a 2–3 week budget with no contract/surface change you can't handle.
  7. You have a feature branch checked out and capstone-work/ ready.

Then go to Step 2: Reproduction.