Capstone Project

The Capstone is the bridge from "I have read the OpenSearch codebase" to "I have shipped a non-trivial fix that an OpenSearch maintainer merged into main." Everything in Levels 1–9 was preparation. This is the work.

You will pick one real, open issue from github.com/opensearch-project/OpenSearch/issues, reproduce it against a current build, trace the failure through the codebase, identify the root cause, write a minimum-diff fix with deterministic tests, get it through ./gradlew precommit and the gradle-check CI, open a Pull Request, sign your commits off under the DCO (git commit -s — OpenSearch has no CLA), respond to review rounds, land the change, and write it up so the next person can learn from your investigation.

OpenSearch contribution is GitHub-native. There is no JIRA, no patch file emailed to a list, no Apache ID. You fork, branch, push, open a PR, sign off, add a CHANGELOG.md entry, and iterate in the PR conversation until a maintainer merges and the backport bot cherry-picks to the release branches. Keep that model in your head — every step below assumes it.

This chapter is the table of contents. The ten step-chapters that follow are the work itself.


Prerequisites

Do not start the Capstone until you can answer "yes" to every one of these:

  • Levels 1–9 complete. You can read RestSearchAction, TransportSearchAction, IndexShard, InternalEngine, the coordination layer (Coordinator, MasterService / cluster-manager service, ClusterApplierService), and at least one allocation decider, without a guide open. If those names are not familiar, go back to Level 4 and the deep dives.
  • You can build from source. ./gradlew assemble succeeds on your machine, and ./gradlew :server:test --tests "org.opensearch.cluster.ClusterStateTests" finishes green. Some flakes are normal — see the flaky-test discussion.
  • You have run a cluster from source. ./gradlew run brings up a single node with REST on localhost:9200, and you have hit it with curl.
  • You have run an InternalTestCluster test. ./gradlew :server:internalClusterTest --tests "*ClusterHealthIT" (or any *IT) goes green, so you know the multi-node in-JVM harness works on your box.
  • You have a GitHub account with DCO configured. You can git commit -s and the Signed-off-by: line carries your real name and the email tied to your GitHub account. (The DCO check on the PR matches the sign-off email to a commit author — get this right once, locally, before you ever push.)
  • You have read the contribution hygiene files in the repo: CONTRIBUTING.md, DEVELOPER_GUIDE.md, and TESTING.md.

If any of these is "no," stop. Go back. The Capstone is unforgiving of partial preparation — you will spend three weeks confused instead of three weeks shipping.

Note: OpenSearch renamed the master node role and many APIs to cluster manager for inclusive language (the old master terms survive as deprecated aliases). Throughout the Capstone, write cluster manager (formerly master) the first time you reference it in any artifact, then use "cluster manager." Reviewers notice.


The 10-Step Flow

flowchart TD
    A[Step 1: Issue Selection] --> B[Step 2: Reproduction]
    B --> C[Step 3: Execution Path Analysis]
    C --> D[Step 4: Root Cause Identification]
    D --> E[Step 5: Implementation]
    E --> F[Step 6: Testing]
    F --> G[Step 7: Validation]
    G --> H[Step 8: Pull Request Preparation]
    H --> I[Step 9: GitHub Documentation]
    I --> J[Step 10: Engineering Write-Up]
    G -.precommit fail.-> E
    F -.test fail.-> E
    D -.hypothesis wrong.-> C
    H -.review round.-> E
    I -.gradle-check red.-> F

The dotted arrows are the loops you will actually run. Nobody gets root cause right on the first hypothesis. Nobody passes precommit on the first push. Nobody clears review in one round. Plan for two or three iterations through Steps 4–9 before the merge button turns green.


Deliverables

By the time you mark the Capstone done, every one of these artifacts exists:

#ArtifactLives in
1Failing reproducer test (a JUnit test that fails on main without your fix and passes with it)server/src/test/... or server/src/internalClusterTest/...
2Root-cause document (200–500 words, with file-path citations)capstone-work/root-cause.md in your fork
3Minimum-diff fix branchA branch on your fork of opensearch-project/OpenSearch
4Unit tests (OpenSearchTestCase; AbstractWireSerializingTestCase if serialization changed)The relevant src/test/java
5Integration tests (OpenSearchIntegTestCase / InternalTestCluster) if end-to-end behavior changedserver/src/internalClusterTest/java/...
6Validation report (./gradlew precommit, spotlessJavaCheck, affected-module tests)capstone-work/validation.md
7GitHub Pull Request against opensearch-project/OpenSearch:main, DCO-signedhttps://github.com/opensearch-project/OpenSearch/pulls
8CHANGELOG.md entry under ## [Unreleased ...] (Added / Changed / Fixed)CHANGELOG.md in your branch
9Issue updated and linked (Fixes #NNNN), labels and backport label as appropriatehttps://github.com/opensearch-project/OpenSearch/issues/NNNN
10Engineering write-up (500–1000 words: problem, investigation, design, alternatives, lessons)Personal blog, the forum, or the PR itself

Every one. No exceptions. The write-up is not optional — it is how the community (and your future self) learns from your investigation. See Step 10.

Use a - [ ] checklist to track them:

  • Failing reproducer test committed and confirmed red on main
  • capstone-work/root-cause.md written
  • Minimum-diff fix on a feature branch
  • Unit tests cover every trigger condition
  • Integration / REST-YAML tests if behavior is end-to-end
  • capstone-work/validation.md with a green precommit
  • DCO-signed PR opened against main
  • CHANGELOG.md entry added
  • Issue linked with Fixes #NNNN, labels set
  • Write-up published

100-Point Rubric Summary

The full rubric lives in evaluation-rubric.md. Headline:

AreaWeight
Problem articulation (symptom vs. root cause, trigger conditions)20
Execution-path mastery (file-path citations, accurate diagram)20
Implementation quality (minimum diff, conventions, BWC, no scope creep)20
Testing (unit + integration, deterministic, trigger coverage)15
Review responsiveness (addresses comments, iteration cadence)10
Documentation (issue/PR hygiene, CHANGELOG, write-up)10
Community interaction (forum/Slack/PR etiquette, handoff hygiene)5

Tier thresholds:

  • 80+ — credible OpenSearch contributor. You can sustain a steady PR flow.
  • 90+ — maintainer-ready. You are doing work a MAINTAINERS.md reviewer would do without hand-holding.
  • 95+ — TSC-track. You are leading work others want to follow, across repos.

You will self-grade in Step 10. Be honest. Inflated self-grades are visible from orbit the moment a maintainer reads your PR.


Timeline

The Capstone is a 4–6 week effort if you have one focused evening per weekday plus weekend mornings. Less than that and you risk losing context between sessions — which is far more expensive than people expect for cluster-state and coordination code.

WeekStepsHours
11–2: Pick an issue, build a deterministic reproducer10–15
23–4: Trace the execution path, identify root cause12–18
35–6: Implement the fix, write unit + integration tests12–18
47–8: Validate locally, open the DCO-signed PR8–12
58–9: Review iteration — two or three rounds is normal6–10
610: Write-up, issue cleanup, retrospective4–6

If you blow past six weeks, that is a signal — not a failure. Either the issue is larger than it looked (pause and renegotiate scope in the issue thread), or you are stuck on a specific step (ask on the forum or in #community on Slack). See Communication Channels.


Success Indicators

You will know it is working when:

  1. A maintainer comments "LGTM" / approves the PR, and gradle-check is green.
  2. Your fix appears in git log origin/main with your Signed-off-by: line, and the backport bot opens a follow-up PR onto 2.x.
  3. The issue you claimed flips to closed via Fixes #NNNN, with your name on the merge.
  4. Your write-up gets traffic — forum replies, a question from another contributor, a maintainer pointing the next person at it.
  5. The next time you pick an issue, you reach root cause in days, not weeks.

You will know it is failing when:

  1. You are still editing files in Step 5 with no failing test in hand from Step 2.
  2. Your PR description says "I think this might fix it."
  3. You have not run ./gradlew precommit in over a week.
  4. You are arguing in PR comments instead of changing code or asking questions.
  5. CI (gradle-check) has been red for days and you are pushing "fix CI" commits blind instead of reproducing the failure locally.

If you spot a failure signal, do not push through. Stop, reread the relevant step chapter, and reset.


How to Use This Chapter

Read all ten step-chapters once, end-to-end, before you start Step 1. You need the shape of the whole journey in your head — Step 4 (root cause) makes choices that Step 6 (testing) depends on; Step 8 (PR) assumes you have artifacts from Steps 2 and 7; Step 9 assumes your tests cleared CI. Skim now, deep-read each as you arrive at it.

Then go to Step 1: Issue Selection. Pick the issue. The clock starts when you comment "I'd like to work on this" on the GitHub issue.


Validation / Self-check

Before starting Step 1, confirm:

  1. You can produce, from memory, the source path of RestSearchAction, TransportSearchAction, IndexShard, InternalEngine, and Coordinator.
  2. ./gradlew assemble completes against your local clone.
  3. ./gradlew run brings up a node and you have curled localhost:9200/_cluster/health.
  4. ./gradlew :server:internalClusterTest --tests "*ClusterHealthIT" passes.
  5. git commit -s produces a correct Signed-off-by: line with your GitHub email.
  6. You have a capstone-work/ directory in your fork ready for root-cause.md and validation.md.
  7. You have skimmed every step-chapter once.
  8. You have set aside 4–6 calendar weeks with a realistic time budget.
  9. You have read CONTRIBUTING.md, DEVELOPER_GUIDE.md, and TESTING.md.