{"owner":"h2oai","repo":"h2o-3","hasSkills":true,"hasMcp":false,"mcpConfig":null,"found":["CLAUDE.md"],"skills":{"CLAUDE.md":"# CLAUDE.md\n\nThis file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.\n\n## Build Commands\n\n### Quick Build (Skip Tests)\n```bash\n./gradlew --parallel clean build -x test\n# Or use the Makefile shortcut:\nmake\n```\n\n### Full Build (With Tests)\n\nMost probably cannot run on laptop.\n\n```bash\n./gradlew syncSmalldata    # Download test data from S3\n./gradlew build\n```\n\n### Run H2O Locally\n```bash\njava -jar build/h2o.jar\n# Access UI at http://localhost:54321\n```\n\n## Testing\n\n### Java Tests\nH2O uses a custom multi-node testing framework (not standard JUnit runners):\n\n- **Single-node cluster tests**: `./gradlew :h2o-algos:testSingleNode`\n- **Multi-node cluster tests**: `./gradlew :h2o-algos:testMultiNode`\n- **Single JVM tests**: `./gradlew :h2o-algos:testSingleNodeOneProc`\n\nTest files are located in:\n- `h2o-core/src/test/java/` - Platform tests\n- `h2o-algos/src/test/java/` - Algorithm tests (e.g., `hex/tree/gbm/GBMTest.java`)\n\n**Running a single test class**: Use the `test.single` property:\n```bash\n./gradlew :h2o-algos:testSingleNode -Dtest.single=GBMTest\n```\n\n## Module Architecture\n\n### Core Dependencies\n```\nh2o-genmodel (standalone POJO/MOJO scoring)\n    ↓\nh2o-core (distributed computing engine, DKV, REST API framework)\n    ↓\nh2o-algos (ML algorithms: GBM, GLM, DL, RF, etc.)\n    ↓\nh2o-automl (AutoML functionality)\n    ↓\nh2o-app (assembly: aggregates core + algos + web UI)\n```\n\n### Key Modules\n- **h2o-core**: Distributed key-value store (DKV), REST API infrastructure, Frame/Vec/Chunk data structures, MRTask framework\n- **h2o-algos**: Machine learning algorithms (all extend `hex.ModelBuilder`)\n- **h2o-web**: Flow web UI (Node.js-based, compiled into resources)\n- **h2o-genmodel**: Standalone model scoring (no H2O runtime dependencies)\n- **h2o-bindings**: Generates Python/R client bindings from REST schemas\n- **h2o-persist-{hdfs,s3,gcs}**: Storage backends for distributed file systems\n\n### Extension Modules\n- **h2o-ext-xgboost**: XGBoost integration\n- **h2o-ext-target-encoder**: Target encoding for categorical features\n- **h2o-automl**: Automated machine learning\n\n## Distributed Architecture\n\n### Key Concepts\n\n**DKV (Distributed Key-Value Store)**:\n- Every object has a home node determined by consistent hashing of its `Key`\n- Access via `DKV.put(key, value)` and `DKV.get(key)`\n- The cloud \"locks\" via Paxos before first DKV write to prevent mid-computation node joins\n\n**Vec/Chunk Data Distribution**:\n- `Vec`: Distributed column of data (conceptually like a database column)\n- `Chunk`: Contiguous subset of a Vec (typically 1K-1M rows)\n- All Vecs in a `Frame` share a `VectorGroup` ensuring chunk alignment\n- Same-numbered chunks across different Vecs have identical row ranges for efficient row-wise iteration\n\n**MRTask (Map/Reduce)**:\n- Extends `MRTask` and override `map(Chunk c)` and optionally `reduce(MRTask mrt)`\n- Call `.doAll(frame)` or `.dfork(frame)` to execute\n- Computation moves to data (not vice versa)\n- Results reduce up a tree back to the initiating node\n\n**Iced Serialization**:\n- All distributed objects extend `Iced<T>` for auto-generated serialization\n- `Keyed<T>` extends Iced and adds DKV key management\n- Schemas extend Iced and provide versioned REST API DTOs\n\n### Node Communication\n- UDP for heartbeats and small messages\n- TCP for bulk data transfer\n- Nodes form a peer-to-peer cluster (no master node for data distribution)\n\n## REST API Structure\n\n### Handler-Route-Schema Pattern\n1. **Routes** (`water.api.Route`): Map HTTP endpoints to handler methods\n2. **Handlers** (`water.api.Handler`): Process requests with signature `(int version, Schema schema)`\n3. **Schemas** (`water.api.Schema`): Versioned DTOs that translate between API and internal Iced objects\n4. **RequestServer**: Central routing engine\n\n### Algorithm Registration\nAlgorithms auto-register REST endpoints at startup:\n- Each algorithm's constructor with `startup_once=true` creates a singleton prototype\n- `RegisterAlgos.java` instantiates all algorithms during H2O initialization\n- Each algorithm gets standardized endpoints: `/3/ModelBuilders/<algo>`, `/3/Grid`, etc.\n\n### Adding New REST Endpoints\n1. Create Schema class extending `water.api.Schema`\n2. Create Handler class extending `water.api.Handler`\n3. Register route in handler via `@Route` annotation or programmatically\n4. Schema fields with `@API` annotation become public API parameters\n\n## Algorithm Implementation\n\n### ModelBuilder Pattern\nAll algorithms extend `hex.ModelBuilder<M, P, O>`:\n- `M`: Model class (extends `hex.Model`)\n- `P`: Parameters class (extends `hex.Model.Parameters`)\n- `O`: Output class (extends `hex.Model.Output`)\n\n### Key Methods to Override\n- `init()`: Validate parameters, check data compatibility\n- `trainModelImpl()`: Core training logic (runs on worker nodes)\n- `compute2()`: Orchestrates distributed training via MRTask\n\n### Example Structure\n```java\npublic class MyAlgo extends ModelBuilder<MyAlgoModel, MyAlgoModel.MyAlgoParameters, MyAlgoModel.MyAlgoOutput> {\n  @Override public void init(boolean expensive) {\n    super.init(expensive);\n    // Validate parameters\n  }\n\n  @Override public void trainModelImpl() {\n    // Core training logic\n  }\n}\n```\n\n### Model Scoring\nModels implement `score0(double[] data, double[] preds)` for row-by-row prediction.\nFor production deployment:\n- **POJO**: Java code generated via `model.download_pojo()`\n- **MOJO**: Binary format via `model.download_mojo()` (more compact, faster)\n\n## Common Development Workflows\n\n### Adding a New Algorithm\n1. Create `MyAlgo.java` extending `ModelBuilder` in `h2o-algos/src/main/java/hex/`\n2. Implement nested `MyAlgoModel`, `MyAlgoParameters`, `MyAlgoOutput` classes\n3. Add algorithm instantiation to `water.api.RegisterAlgos` with `startup_once=true`\n4. Add tests in `h2o-algos/src/test/java/hex/myalgo/`\n5. Rebuild: `./gradlew :h2o-algos:build`\n\n### Modifying Core Data Structures\nBe cautious when modifying:\n- `water.fvec.Vec`, `water.fvec.Chunk`: Core data structures used everywhere\n- `water.DKV`: Distributed key-value operations\n- `water.H2O`: Cluster management and lifecycle\n\nThese changes can have wide-reaching implications across all algorithms.\n\n### Debugging Distributed Code\n- H2O tests spawn multiple JVMs that form a cluster\n- Logs are in `build/` with names like `h2o_<node_ip>_<port>.log`\n- Enable verbose logging: `-Dlog.level=DEBUG` or `-Dlog.level=TRACE`\n- Use `Log.info()`, `Log.warn()`, `Log.err()` (not `System.out`)\n\n### Building Documentation\n```bash\n./gradlew clean && ./gradlew build -x test && (export DO_FAST=1; ./gradlew dist)\nopen target/docs-website/h2o-docs/index.html\n```\n\n## Git Workflow\n\n### Branch Naming\nIf working on a GitHub issue, include the issue number and GitHub username if provided:\n```bash\ngit checkout -b githubusername-gh-1234_add_new_feature\n```\n\n### Pull Requests\n- New code requires unit tests (runits for R, pyunits for Python, JUnits for Java)\n- PR title should include GitHub issue number: \"GH-1234: Added new feature\"\n- PRs trigger Jenkins CI tests automatically\n- All tests must pass before merge\n\n#### prCheck Rules (enforced by `gradle/prCheck.gradle`)\n1. Always have a GitHub issue before starting work (otherwise you cannot know which branch to start from).\n2. The GitHub issue must have a milestone assigned. If it does not, consult the team for a suitable fix version.\n3. If the milestone ends with `.1`, the change targets the `master` branch. All other changes target the current fix release branch, prefixed `rel-` (e.g. `rel-3.46.0`).\n4. Assign the issue to the H2O-3 project and move it to the \"In Progress\" state.\n5. Include the GitHub issue number (`GH-XXXX`) in at least one commit message. Not checked by CI, but expected.\n6. The PR title must include the issue number, and the PR description must link the issue, e.g. `GH-4200: Adding support for Factorization Machines`. This is checked by CI.\n7. If a PR is intentionally not tied to an issue (docs-only cleanups, tooling tweaks), append **`[nocheck]` at the end** of the title — e.g. `Document PR conventions in CLAUDE.md [nocheck]`. `gradle/prCheck.gradle` skips validation when it sees the marker anywhere in the title, but keep it at the end by convention so reviewers read the actual change first. Target the **current fix release branch** (e.g. `rel-3.46.0` today, `rel-3.48.0` once that line is cut) — not `master` — so the change ships in the upcoming release and flows forward into master on the next merge. Target `master` only when the change is inherently master-only.\n\n#### Updating an open PR\n- **Prefer new commits over force-push.** Once a PR is under review, add follow-up commits (`git commit`, `git push`) so reviewers see the incremental diff and GitHub preserves comment anchors.\n- **Use force-push only for genuine history surgery** — rebasing onto a different base branch, resolving a merge conflict before first review, or dropping a committed secret. Not for squashing or amending typos that already landed on the remote.\n- Squashing can happen at merge time via the GitHub \"Squash and merge\" button if the maintainer prefers a single commit.\n\n#### PR description style\n- **Be brief.** One short paragraph or a handful of bullets. A reviewer should understand the what and the why in under 30 seconds.\n- **Focus on the change and its motivation** — what problem this solves, which CVE/bug it fixes, which user-visible behaviour shifts.\n- **Link the issue** (`Closes #N` or similar) so GitHub auto-closes it on merge.\n- **Do not include test-suite results or CI stats** (`All 42 tests passing`, `20/20 green`, runtime numbers, coverage deltas). Tests passing is assumed; CI reports them.\n- **Do not include meaningless stats** (file counts, LOC changes, \"refactored 5 classes\"). The diff shows them.\n- **Do not narrate the process** (`first I tried X, then Y`, `I investigated…`). Ship the conclusion.\n- **Screenshots / logs only when they add information** the reviewer can't get from the diff (UI changes, runtime traces for a bug reproduction).\n\n#### Issue hygiene\nWhen creating or editing a GitHub issue:\n- **Don't paste information that already lives elsewhere** (CVE advisories, long error logs, full stack traces). Summarise in a couple of sentences and link the source.\n- **Fix version belongs in the milestone, not the description.** Never write `Fix version: 3.46.0.11` in the body — set the milestone field instead (`gh issue edit N --milestone \"3.46.0.11\"`).\n- **Assignee is required** (checked by `prCheck`). Set it when you open the issue.\n- **Project is required** (checked by `prCheck`). Add the issue to the `H2O OSS (H2O-3)` project (project number 112).\n- **Labels**: add one when it's obvious (`bug`, `feature`, `docs`, `dependencies`, …). Skip if unclear. **CVE or security-related tasks must carry the `Security Vulnerability` label.**\n- **Relationships**: if a PR already exists for the issue, link it from the Development section of the issue UI.\n- **Project fields** (see `H2O OSS (H2O-3)` side panel): fill what you know — `Status` (set to `In Progress` once work starts), `Customer`, `Support ticket`, `CVEs fixed` (comma-separated CVE IDs), `Complexity` (Story Points 1-5, see scale below), `Private notes`. Leave blank rather than guessing.\n\n#### Issue fields & triage\nApplies to both new issues you open and existing ones you review.\n\n**Before triaging, always read the project-side fields.** `gh issue view` shows labels / milestone / assignees but **not** custom project fields (`Customer`, `Support ticket`, `CVEs fixed`, `Complexity`, linked PRs, etc.). Those are only visible via `gh project item-list 112 --owner h2oai --format json | jq '.items | map(select(.content.number == N)) | .[0]'`. Skipping this step is how you wrongly conclude an issue is actionable-less when it actually has a support ticket, customer, or open PR attached.\n\n**For existing issues — consider closing when:**\n- You're ~80% sure it's outdated.\n- Nobody can still understand what the issue is about.\n- There's a closed support ticket referenced in the comments.\n- Before closing: assign the project and link the support ticket in the project details.\n- Default to closing rather than asking clarifying questions.\n- **Never close an issue without explicit confirmation from the user first.** Closing is visible to others and reopening is annoying; always propose the close action and wait for a go-ahead.\n\n**For any issue you keep open (or create):**\n- **Assignee** — set a current owner, or clear it if the previous owner no longer works on H2O-3.\n- **Labels** — add what fits:\n  - algo family (`GBM`, `GLM`, `XGBoost`, …),\n  - `Security Vulnerability` (required for any CVE / security task),\n  - `question`, `good_first_issue`, `docs`, `dependencies`, `Build`, …\n  - Optionally a type label: `bug`, `feature`, or a `Task` tag.\n  - **Do not use customer-specific labels on the issue itself** — customer info belongs in the project `Customer` field.\n- **Project** — add the issue to `H2O OSS (H2O-3)` (project number 112). Required by `prCheck`.\n- **Complexity (Story Points)** — fill the project field on a 1–5 scale:\n  - **1** — good first issue.\n  - **2-3** — understandable requirement, just time and effort for an in-house developer (example: [#7518](https://github.com/h2oai/h2o-3/issues/7518)).\n  - **4** — requires study, time, and effort, but no new infrastructure (example: new algorithm like HDBSCAN / KNN, or dropping support for a Python version).\n  - **5** — requires study, time, effort, **and** new infrastructure (example: XGBoost on Windows, adding a new Java / R / Python version).\n\n### Commit Messages\nFollow the existing style seen in recent commits (concise, descriptive).\n\n## Python/R Client Development\n\n### Regenerating Bindings\nAfter modifying REST API schemas:\n```bash\n./gradlew :h2o-bindings:build\n```\nThis regenerates Python and R client code in `h2o-py/h2o/` and `h2o-r/h2o-package/R/`.\n\n## Environment Setup Notes\n\n### Required Software\n- **JDK**: 1.8+ (Java 8 or later)\n- **Node.js**: For building Flow UI\n- **Python**: 3.6+ with `pip` (for Python bindings and build tools)\n- **R**: 3.1+ with packages: RCurl, jsonlite, statmod, devtools, roxygen2, testthat\n- **Gradle**: Via `gradlew` wrapper (auto-downloaded)\n\n### Running Tests Requirements\n- Minimum 8GB RAM (16GB recommended)\n- Tests spawn 5 JVMs forming an H2O cluster\n- Use `-x test` to skip during builds if system resources are limited\n\n## Hadoop Builds\n\nTo build H2O-on-Hadoop assemblies:\n```bash\nexport BUILD_HADOOP=1\n./gradlew build -x test\n```\n\nAssemblies created in `target/` for various Hadoop distributions (CDH, HDP, MapR, EMR).\n\nTo build only specific distributions:\n```bash\nexport BUILD_HADOOP=1\nexport H2O_TARGET=hdp2.6,cdh6.3\n./gradlew build -x test\n```\n\n## Building H2O Assemblies\n\nThis project builds two main assemblies:\n\n### Main Assembly -- part of DockerHub h2o-open-source-k8s and python backend. Should be same as build/h2o.jar\nThe **main assembly** (`h2o-assemblies/main`) is the full-featured H2O distribution with all standard components.\n\n**Build command:**\n```bash\n./gradlew :h2o-assemblies:main:build\n```\n\n**Output location:**\n- `h2o-assemblies/main/build/libs/h2o.jar`\n\n**Key features:**\n- Full H2O Application with all standard components\n- Includes web UI, parsers (Avro, Parquet), persistence layers (S3, GCS, HDFS, HTTP)\n- Contains Hadoop dependencies and Kubernetes support\n- Uses Jetty 9 with full feature set\n- Main class: `water.H2OApp`\n\n### Steam Assembly\nThe **steam assembly** (`h2o-assemblies/steam`) is a secure, minimal H2O distribution for use with H2O Steam.\n\n**Build command:**\n```bash\n./gradlew :h2o-assemblies:steam:build\n```\n\n**Output location:**\n- `h2o-assemblies/steam/build/libs/h2o.jar`\n\n**Key features:**\n- Secure deployment optimized for H2O Steam integration\n- Uses minimal Jetty 9 configuration\n- Excludes h2o-jaas-pam module for security\n- Includes persistence layers with reduced Hadoop footprint\n- Main class: `water.H2OApp`\n\n### Build Both Assemblies\nTo build both assemblies at once:\n```bash\n./gradlew :h2o-assemblies:main:build :h2o-assemblies:steam:build\n```\n\n**Notes:**\n- Both assemblies use the Gradle Shadow plugin to create fat jars\n- Both include security fixes and vulnerability patches via dependency constraints\n- The standard build (`./gradlew build`) excludes these assemblies by default\n- See `h2o-assemblies/main/build.gradle` and `h2o-assemblies/steam/build.gradle` for full dependency details\n\n## Code Commenting Guidelines\n\nWhen writing or modifying code, follow these commenting principles:\n\n### DO:\n- **Comment code blocks**: Add comments that explain the purpose, logic, or reasoning behind a block of code\n- **Comment complex logic**: Explain non-obvious algorithms, business rules, or intricate operations\n- **Comment \"why\" not \"what\"**: Focus on the reasoning and context rather than describing what the code literally does\n- **Add context**: Explain assumptions, constraints, or important background information\n\n### DON'T:\n- **Avoid line-by-line comments**: Don't add comments after each line of code\n- **Don't state the obvious**: Avoid commenting self-explanatory method names or trivial operations\n- **Don't redundant comments**: If the code is clear and readable, additional comments may not be needed\n\n### Examples:\n\n#### ❌ Bad (over-commenting):\n```java\nint count = 0; // Initialize count to zero\nfor (int i = 0; i < items.size(); i++) { // Loop through items\n    count++; // Increment count\n}\nreturn count; // Return the count\n```\n\n#### ✓ Good (block-level comment when needed):\n```java\n// Calculate total items for billing reconciliation.\n// Note: This excludes cancelled orders per business rules in JIRA-1234\nint count = 0;\nfor (int i = 0; i < items.size(); i++) {\n    if (!items.get(i).isCancelled()) {\n        count++;\n    }\n}\nreturn count;\n```\n\n#### ✓ Good (no comment needed for obvious code):\n```java\npublic void saveUser(User user) {\n    userRepository.save(user);\n}\n```\n"},"files":{"CLAUDE.md":"# CLAUDE.md\n\nThis file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.\n\n## Build Commands\n\n### Quick Build (Skip Tests)\n```bash\n./gradlew --parallel clean build -x test\n# Or use the Makefile shortcut:\nmake\n```\n\n### Full Build (With Tests)\n\nMost probably cannot run on laptop.\n\n```bash\n./gradlew syncSmalldata    # Download test data from S3\n./gradlew build\n```\n\n### Run H2O Locally\n```bash\njava -jar build/h2o.jar\n# Access UI at http://localhost:54321\n```\n\n## Testing\n\n### Java Tests\nH2O uses a custom multi-node testing framework (not standard JUnit runners):\n\n- **Single-node cluster tests**: `./gradlew :h2o-algos:testSingleNode`\n- **Multi-node cluster tests**: `./gradlew :h2o-algos:testMultiNode`\n- **Single JVM tests**: `./gradlew :h2o-algos:testSingleNodeOneProc`\n\nTest files are located in:\n- `h2o-core/src/test/java/` - Platform tests\n- `h2o-algos/src/test/java/` - Algorithm tests (e.g., `hex/tree/gbm/GBMTest.java`)\n\n**Running a single test class**: Use the `test.single` property:\n```bash\n./gradlew :h2o-algos:testSingleNode -Dtest.single=GBMTest\n```\n\n## Module Architecture\n\n### Core Dependencies\n```\nh2o-genmodel (standalone POJO/MOJO scoring)\n    ↓\nh2o-core (distributed computing engine, DKV, REST API framework)\n    ↓\nh2o-algos (ML algorithms: GBM, GLM, DL, RF, etc.)\n    ↓\nh2o-automl (AutoML functionality)\n    ↓\nh2o-app (assembly: aggregates core + algos + web UI)\n```\n\n### Key Modules\n- **h2o-core**: Distributed key-value store (DKV), REST API infrastructure, Frame/Vec/Chunk data structures, MRTask framework\n- **h2o-algos**: Machine learning algorithms (all extend `hex.ModelBuilder`)\n- **h2o-web**: Flow web UI (Node.js-based, compiled into resources)\n- **h2o-genmodel**: Standalone model scoring (no H2O runtime dependencies)\n- **h2o-bindings**: Generates Python/R client bindings from REST schemas\n- **h2o-persist-{hdfs,s3,gcs}**: Storage backends for distributed file systems\n\n### Extension Modules\n- **h2o-ext-xgboost**: XGBoost integration\n- **h2o-ext-target-encoder**: Target encoding for categorical features\n- **h2o-automl**: Automated machine learning\n\n## Distributed Architecture\n\n### Key Concepts\n\n**DKV (Distributed Key-Value Store)**:\n- Every object has a home node determined by consistent hashing of its `Key`\n- Access via `DKV.put(key, value)` and `DKV.get(key)`\n- The cloud \"locks\" via Paxos before first DKV write to prevent mid-computation node joins\n\n**Vec/Chunk Data Distribution**:\n- `Vec`: Distributed column of data (conceptually like a database column)\n- `Chunk`: Contiguous subset of a Vec (typically 1K-1M rows)\n- All Vecs in a `Frame` share a `VectorGroup` ensuring chunk alignment\n- Same-numbered chunks across different Vecs have identical row ranges for efficient row-wise iteration\n\n**MRTask (Map/Reduce)**:\n- Extends `MRTask` and override `map(Chunk c)` and optionally `reduce(MRTask mrt)`\n- Call `.doAll(frame)` or `.dfork(frame)` to execute\n- Computation moves to data (not vice versa)\n- Results reduce up a tree back to the initiating node\n\n**Iced Serialization**:\n- All distributed objects extend `Iced<T>` for auto-generated serialization\n- `Keyed<T>` extends Iced and adds DKV key management\n- Schemas extend Iced and provide versioned REST API DTOs\n\n### Node Communication\n- UDP for heartbeats and small messages\n- TCP for bulk data transfer\n- Nodes form a peer-to-peer cluster (no master node for data distribution)\n\n## REST API Structure\n\n### Handler-Route-Schema Pattern\n1. **Routes** (`water.api.Route`): Map HTTP endpoints to handler methods\n2. **Handlers** (`water.api.Handler`): Process requests with signature `(int version, Schema schema)`\n3. **Schemas** (`water.api.Schema`): Versioned DTOs that translate between API and internal Iced objects\n4. **RequestServer**: Central routing engine\n\n### Algorithm Registration\nAlgorithms auto-register REST endpoints at startup:\n- Each algorithm's constructor with `startup_once=true` creates a singleton prototype\n- `RegisterAlgos.java` instantiates all algorithms during H2O initialization\n- Each algorithm gets standardized endpoints: `/3/ModelBuilders/<algo>`, `/3/Grid`, etc.\n\n### Adding New REST Endpoints\n1. Create Schema class extending `water.api.Schema`\n2. Create Handler class extending `water.api.Handler`\n3. Register route in handler via `@Route` annotation or programmatically\n4. Schema fields with `@API` annotation become public API parameters\n\n## Algorithm Implementation\n\n### ModelBuilder Pattern\nAll algorithms extend `hex.ModelBuilder<M, P, O>`:\n- `M`: Model class (extends `hex.Model`)\n- `P`: Parameters class (extends `hex.Model.Parameters`)\n- `O`: Output class (extends `hex.Model.Output`)\n\n### Key Methods to Override\n- `init()`: Validate parameters, check data compatibility\n- `trainModelImpl()`: Core training logic (runs on worker nodes)\n- `compute2()`: Orchestrates distributed training via MRTask\n\n### Example Structure\n```java\npublic class MyAlgo extends ModelBuilder<MyAlgoModel, MyAlgoModel.MyAlgoParameters, MyAlgoModel.MyAlgoOutput> {\n  @Override public void init(boolean expensive) {\n    super.init(expensive);\n    // Validate parameters\n  }\n\n  @Override public void trainModelImpl() {\n    // Core training logic\n  }\n}\n```\n\n### Model Scoring\nModels implement `score0(double[] data, double[] preds)` for row-by-row prediction.\nFor production deployment:\n- **POJO**: Java code generated via `model.download_pojo()`\n- **MOJO**: Binary format via `model.download_mojo()` (more compact, faster)\n\n## Common Development Workflows\n\n### Adding a New Algorithm\n1. Create `MyAlgo.java` extending `ModelBuilder` in `h2o-algos/src/main/java/hex/`\n2. Implement nested `MyAlgoModel`, `MyAlgoParameters`, `MyAlgoOutput` classes\n3. Add algorithm instantiation to `water.api.RegisterAlgos` with `startup_once=true`\n4. Add tests in `h2o-algos/src/test/java/hex/myalgo/`\n5. Rebuild: `./gradlew :h2o-algos:build`\n\n### Modifying Core Data Structures\nBe cautious when modifying:\n- `water.fvec.Vec`, `water.fvec.Chunk`: Core data structures used everywhere\n- `water.DKV`: Distributed key-value operations\n- `water.H2O`: Cluster management and lifecycle\n\nThese changes can have wide-reaching implications across all algorithms.\n\n### Debugging Distributed Code\n- H2O tests spawn multiple JVMs that form a cluster\n- Logs are in `build/` with names like `h2o_<node_ip>_<port>.log`\n- Enable verbose logging: `-Dlog.level=DEBUG` or `-Dlog.level=TRACE`\n- Use `Log.info()`, `Log.warn()`, `Log.err()` (not `System.out`)\n\n### Building Documentation\n```bash\n./gradlew clean && ./gradlew build -x test && (export DO_FAST=1; ./gradlew dist)\nopen target/docs-website/h2o-docs/index.html\n```\n\n## Git Workflow\n\n### Branch Naming\nIf working on a GitHub issue, include the issue number and GitHub username if provided:\n```bash\ngit checkout -b githubusername-gh-1234_add_new_feature\n```\n\n### Pull Requests\n- New code requires unit tests (runits for R, pyunits for Python, JUnits for Java)\n- PR title should include GitHub issue number: \"GH-1234: Added new feature\"\n- PRs trigger Jenkins CI tests automatically\n- All tests must pass before merge\n\n#### prCheck Rules (enforced by `gradle/prCheck.gradle`)\n1. Always have a GitHub issue before starting work (otherwise you cannot know which branch to start from).\n2. The GitHub issue must have a milestone assigned. If it does not, consult the team for a suitable fix version.\n3. If the milestone ends with `.1`, the change targets the `master` branch. All other changes target the current fix release branch, prefixed `rel-` (e.g. `rel-3.46.0`).\n4. Assign the issue to the H2O-3 project and move it to the \"In Progress\" state.\n5. Include the GitHub issue number (`GH-XXXX`) in at least one commit message. Not checked by CI, but expected.\n6. The PR title must include the issue number, and the PR description must link the issue, e.g. `GH-4200: Adding support for Factorization Machines`. This is checked by CI.\n7. If a PR is intentionally not tied to an issue (docs-only cleanups, tooling tweaks), append **`[nocheck]` at the end** of the title — e.g. `Document PR conventions in CLAUDE.md [nocheck]`. `gradle/prCheck.gradle` skips validation when it sees the marker anywhere in the title, but keep it at the end by convention so reviewers read the actual change first. Target the **current fix release branch** (e.g. `rel-3.46.0` today, `rel-3.48.0` once that line is cut) — not `master` — so the change ships in the upcoming release and flows forward into master on the next merge. Target `master` only when the change is inherently master-only.\n\n#### Updating an open PR\n- **Prefer new commits over force-push.** Once a PR is under review, add follow-up commits (`git commit`, `git push`) so reviewers see the incremental diff and GitHub preserves comment anchors.\n- **Use force-push only for genuine history surgery** — rebasing onto a different base branch, resolving a merge conflict before first review, or dropping a committed secret. Not for squashing or amending typos that already landed on the remote.\n- Squashing can happen at merge time via the GitHub \"Squash and merge\" button if the maintainer prefers a single commit.\n\n#### PR description style\n- **Be brief.** One short paragraph or a handful of bullets. A reviewer should understand the what and the why in under 30 seconds.\n- **Focus on the change and its motivation** — what problem this solves, which CVE/bug it fixes, which user-visible behaviour shifts.\n- **Link the issue** (`Closes #N` or similar) so GitHub auto-closes it on merge.\n- **Do not include test-suite results or CI stats** (`All 42 tests passing`, `20/20 green`, runtime numbers, coverage deltas). Tests passing is assumed; CI reports them.\n- **Do not include meaningless stats** (file counts, LOC changes, \"refactored 5 classes\"). The diff shows them.\n- **Do not narrate the process** (`first I tried X, then Y`, `I investigated…`). Ship the conclusion.\n- **Screenshots / logs only when they add information** the reviewer can't get from the diff (UI changes, runtime traces for a bug reproduction).\n\n#### Issue hygiene\nWhen creating or editing a GitHub issue:\n- **Don't paste information that already lives elsewhere** (CVE advisories, long error logs, full stack traces). Summarise in a couple of sentences and link the source.\n- **Fix version belongs in the milestone, not the description.** Never write `Fix version: 3.46.0.11` in the body — set the milestone field instead (`gh issue edit N --milestone \"3.46.0.11\"`).\n- **Assignee is required** (checked by `prCheck`). Set it when you open the issue.\n- **Project is required** (checked by `prCheck`). Add the issue to the `H2O OSS (H2O-3)` project (project number 112).\n- **Labels**: add one when it's obvious (`bug`, `feature`, `docs`, `dependencies`, …). Skip if unclear. **CVE or security-related tasks must carry the `Security Vulnerability` label.**\n- **Relationships**: if a PR already exists for the issue, link it from the Development section of the issue UI.\n- **Project fields** (see `H2O OSS (H2O-3)` side panel): fill what you know — `Status` (set to `In Progress` once work starts), `Customer`, `Support ticket`, `CVEs fixed` (comma-separated CVE IDs), `Complexity` (Story Points 1-5, see scale below), `Private notes`. Leave blank rather than guessing.\n\n#### Issue fields & triage\nApplies to both new issues you open and existing ones you review.\n\n**Before triaging, always read the project-side fields.** `gh issue view` shows labels / milestone / assignees but **not** custom project fields (`Customer`, `Support ticket`, `CVEs fixed`, `Complexity`, linked PRs, etc.). Those are only visible via `gh project item-list 112 --owner h2oai --format json | jq '.items | map(select(.content.number == N)) | .[0]'`. Skipping this step is how you wrongly conclude an issue is actionable-less when it actually has a support ticket, customer, or open PR attached.\n\n**For existing issues — consider closing when:**\n- You're ~80% sure it's outdated.\n- Nobody can still understand what the issue is about.\n- There's a closed support ticket referenced in the comments.\n- Before closing: assign the project and link the support ticket in the project details.\n- Default to closing rather than asking clarifying questions.\n- **Never close an issue without explicit confirmation from the user first.** Closing is visible to others and reopening is annoying; always propose the close action and wait for a go-ahead.\n\n**For any issue you keep open (or create):**\n- **Assignee** — set a current owner, or clear it if the previous owner no longer works on H2O-3.\n- **Labels** — add what fits:\n  - algo family (`GBM`, `GLM`, `XGBoost`, …),\n  - `Security Vulnerability` (required for any CVE / security task),\n  - `question`, `good_first_issue`, `docs`, `dependencies`, `Build`, …\n  - Optionally a type label: `bug`, `feature`, or a `Task` tag.\n  - **Do not use customer-specific labels on the issue itself** — customer info belongs in the project `Customer` field.\n- **Project** — add the issue to `H2O OSS (H2O-3)` (project number 112). Required by `prCheck`.\n- **Complexity (Story Points)** — fill the project field on a 1–5 scale:\n  - **1** — good first issue.\n  - **2-3** — understandable requirement, just time and effort for an in-house developer (example: [#7518](https://github.com/h2oai/h2o-3/issues/7518)).\n  - **4** — requires study, time, and effort, but no new infrastructure (example: new algorithm like HDBSCAN / KNN, or dropping support for a Python version).\n  - **5** — requires study, time, effort, **and** new infrastructure (example: XGBoost on Windows, adding a new Java / R / Python version).\n\n### Commit Messages\nFollow the existing style seen in recent commits (concise, descriptive).\n\n## Python/R Client Development\n\n### Regenerating Bindings\nAfter modifying REST API schemas:\n```bash\n./gradlew :h2o-bindings:build\n```\nThis regenerates Python and R client code in `h2o-py/h2o/` and `h2o-r/h2o-package/R/`.\n\n## Environment Setup Notes\n\n### Required Software\n- **JDK**: 1.8+ (Java 8 or later)\n- **Node.js**: For building Flow UI\n- **Python**: 3.6+ with `pip` (for Python bindings and build tools)\n- **R**: 3.1+ with packages: RCurl, jsonlite, statmod, devtools, roxygen2, testthat\n- **Gradle**: Via `gradlew` wrapper (auto-downloaded)\n\n### Running Tests Requirements\n- Minimum 8GB RAM (16GB recommended)\n- Tests spawn 5 JVMs forming an H2O cluster\n- Use `-x test` to skip during builds if system resources are limited\n\n## Hadoop Builds\n\nTo build H2O-on-Hadoop assemblies:\n```bash\nexport BUILD_HADOOP=1\n./gradlew build -x test\n```\n\nAssemblies created in `target/` for various Hadoop distributions (CDH, HDP, MapR, EMR).\n\nTo build only specific distributions:\n```bash\nexport BUILD_HADOOP=1\nexport H2O_TARGET=hdp2.6,cdh6.3\n./gradlew build -x test\n```\n\n## Building H2O Assemblies\n\nThis project builds two main assemblies:\n\n### Main Assembly -- part of DockerHub h2o-open-source-k8s and python backend. Should be same as build/h2o.jar\nThe **main assembly** (`h2o-assemblies/main`) is the full-featured H2O distribution with all standard components.\n\n**Build command:**\n```bash\n./gradlew :h2o-assemblies:main:build\n```\n\n**Output location:**\n- `h2o-assemblies/main/build/libs/h2o.jar`\n\n**Key features:**\n- Full H2O Application with all standard components\n- Includes web UI, parsers (Avro, Parquet), persistence layers (S3, GCS, HDFS, HTTP)\n- Contains Hadoop dependencies and Kubernetes support\n- Uses Jetty 9 with full feature set\n- Main class: `water.H2OApp`\n\n### Steam Assembly\nThe **steam assembly** (`h2o-assemblies/steam`) is a secure, minimal H2O distribution for use with H2O Steam.\n\n**Build command:**\n```bash\n./gradlew :h2o-assemblies:steam:build\n```\n\n**Output location:**\n- `h2o-assemblies/steam/build/libs/h2o.jar`\n\n**Key features:**\n- Secure deployment optimized for H2O Steam integration\n- Uses minimal Jetty 9 configuration\n- Excludes h2o-jaas-pam module for security\n- Includes persistence layers with reduced Hadoop footprint\n- Main class: `water.H2OApp`\n\n### Build Both Assemblies\nTo build both assemblies at once:\n```bash\n./gradlew :h2o-assemblies:main:build :h2o-assemblies:steam:build\n```\n\n**Notes:**\n- Both assemblies use the Gradle Shadow plugin to create fat jars\n- Both include security fixes and vulnerability patches via dependency constraints\n- The standard build (`./gradlew build`) excludes these assemblies by default\n- See `h2o-assemblies/main/build.gradle` and `h2o-assemblies/steam/build.gradle` for full dependency details\n\n## Code Commenting Guidelines\n\nWhen writing or modifying code, follow these commenting principles:\n\n### DO:\n- **Comment code blocks**: Add comments that explain the purpose, logic, or reasoning behind a block of code\n- **Comment complex logic**: Explain non-obvious algorithms, business rules, or intricate operations\n- **Comment \"why\" not \"what\"**: Focus on the reasoning and context rather than describing what the code literally does\n- **Add context**: Explain assumptions, constraints, or important background information\n\n### DON'T:\n- **Avoid line-by-line comments**: Don't add comments after each line of code\n- **Don't state the obvious**: Avoid commenting self-explanatory method names or trivial operations\n- **Don't redundant comments**: If the code is clear and readable, additional comments may not be needed\n\n### Examples:\n\n#### ❌ Bad (over-commenting):\n```java\nint count = 0; // Initialize count to zero\nfor (int i = 0; i < items.size(); i++) { // Loop through items\n    count++; // Increment count\n}\nreturn count; // Return the count\n```\n\n#### ✓ Good (block-level comment when needed):\n```java\n// Calculate total items for billing reconciliation.\n// Note: This excludes cancelled orders per business rules in JIRA-1234\nint count = 0;\nfor (int i = 0; i < items.size(); i++) {\n    if (!items.get(i).isCancelled()) {\n        count++;\n    }\n}\nreturn count;\n```\n\n#### ✓ Good (no comment needed for obvious code):\n```java\npublic void saveUser(User user) {\n    userRepository.save(user);\n}\n```\n"},"items":[{"name":"CLAUDE.md","path":"CLAUDE.md","title":"CLAUDE.md","content":"# CLAUDE.md\n\nThis file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.\n\n## Build Commands\n\n### Quick Build (Skip Tests)\n```bash\n./gradlew --parallel clean build -x test\n# Or use the Makefile shortcut:\nmake\n```\n\n### Full Build (With Tests)\n\nMost probably cannot run on laptop.\n\n```bash\n./gradlew syncSmalldata    # Download test data from S3\n./gradlew build\n```\n\n### Run H2O Locally\n```bash\njava -jar build/h2o.jar\n# Access UI at http://localhost:54321\n```\n\n## Testing\n\n### Java Tests\nH2O uses a custom multi-node testing framework (not standard JUnit runners):\n\n- **Single-node cluster tests**: `./gradlew :h2o-algos:testSingleNode`\n- **Multi-node cluster tests**: `./gradlew :h2o-algos:testMultiNode`\n- **Single JVM tests**: `./gradlew :h2o-algos:testSingleNodeOneProc`\n\nTest files are located in:\n- `h2o-core/src/test/java/` - Platform tests\n- `h2o-algos/src/test/java/` - Algorithm tests (e.g., `hex/tree/gbm/GBMTest.java`)\n\n**Running a single test class**: Use the `test.single` property:\n```bash\n./gradlew :h2o-algos:testSingleNode -Dtest.single=GBMTest\n```\n\n## Module Architecture\n\n### Core Dependencies\n```\nh2o-genmodel (standalone POJO/MOJO scoring)\n    ↓\nh2o-core (distributed computing engine, DKV, REST API framework)\n    ↓\nh2o-algos (ML algorithms: GBM, GLM, DL, RF, etc.)\n    ↓\nh2o-automl (AutoML functionality)\n    ↓\nh2o-app (assembly: aggregates core + algos + web UI)\n```\n\n### Key Modules\n- **h2o-core**: Distributed key-value store (DKV), REST API infrastructure, Frame/Vec/Chunk data structures, MRTask framework\n- **h2o-algos**: Machine learning algorithms (all extend `hex.ModelBuilder`)\n- **h2o-web**: Flow web UI (Node.js-based, compiled into resources)\n- **h2o-genmodel**: Standalone model scoring (no H2O runtime dependencies)\n- **h2o-bindings**: Generates Python/R client bindings from REST schemas\n- **h2o-persist-{hdfs,s3,gcs}**: Storage backends for distributed file systems\n\n### Extension Modules\n- **h2o-ext-xgboost**: XGBoost integration\n- **h2o-ext-target-encoder**: Target encoding for categorical features\n- **h2o-automl**: Automated machine learning\n\n## Distributed Architecture\n\n### Key Concepts\n\n**DKV (Distributed Key-Value Store)**:\n- Every object has a home node determined by consistent hashing of its `Key`\n- Access via `DKV.put(key, value)` and `DKV.get(key)`\n- The cloud \"locks\" via Paxos before first DKV write to prevent mid-computation node joins\n\n**Vec/Chunk Data Distribution**:\n- `Vec`: Distributed column of data (conceptually like a database column)\n- `Chunk`: Contiguous subset of a Vec (typically 1K-1M rows)\n- All Vecs in a `Frame` share a `VectorGroup` ensuring chunk alignment\n- Same-numbered chunks across different Vecs have identical row ranges for efficient row-wise iteration\n\n**MRTask (Map/Reduce)**:\n- Extends `MRTask` and override `map(Chunk c)` and optionally `reduce(MRTask mrt)`\n- Call `.doAll(frame)` or `.dfork(frame)` to execute\n- Computation moves to data (not vice versa)\n- Results reduce up a tree back to the initiating node\n\n**Iced Serialization**:\n- All distributed objects extend `Iced<T>` for auto-generated serialization\n- `Keyed<T>` extends Iced and adds DKV key management\n- Schemas extend Iced and provide versioned REST API DTOs\n\n### Node Communication\n- UDP for heartbeats and small messages\n- TCP for bulk data transfer\n- Nodes form a peer-to-peer cluster (no master node for data distribution)\n\n## REST API Structure\n\n### Handler-Route-Schema Pattern\n1. **Routes** (`water.api.Route`): Map HTTP endpoints to handler methods\n2. **Handlers** (`water.api.Handler`): Process requests with signature `(int version, Schema schema)`\n3. **Schemas** (`water.api.Schema`): Versioned DTOs that translate between API and internal Iced objects\n4. **RequestServer**: Central routing engine\n\n### Algorithm Registration\nAlgorithms auto-register REST endpoints at startup:\n- Each algorithm's constructor with `startup_once=true` creates a singleton prototype\n- `RegisterAlgos.java` instantiates all algorithms during H2O initialization\n- Each algorithm gets standardized endpoints: `/3/ModelBuilders/<algo>`, `/3/Grid`, etc.\n\n### Adding New REST Endpoints\n1. Create Schema class extending `water.api.Schema`\n2. Create Handler class extending `water.api.Handler`\n3. Register route in handler via `@Route` annotation or programmatically\n4. Schema fields with `@API` annotation become public API parameters\n\n## Algorithm Implementation\n\n### ModelBuilder Pattern\nAll algorithms extend `hex.ModelBuilder<M, P, O>`:\n- `M`: Model class (extends `hex.Model`)\n- `P`: Parameters class (extends `hex.Model.Parameters`)\n- `O`: Output class (extends `hex.Model.Output`)\n\n### Key Methods to Override\n- `init()`: Validate parameters, check data compatibility\n- `trainModelImpl()`: Core training logic (runs on worker nodes)\n- `compute2()`: Orchestrates distributed training via MRTask\n\n### Example Structure\n```java\npublic class MyAlgo extends ModelBuilder<MyAlgoModel, MyAlgoModel.MyAlgoParameters, MyAlgoModel.MyAlgoOutput> {\n  @Override public void init(boolean expensive) {\n    super.init(expensive);\n    // Validate parameters\n  }\n\n  @Override public void trainModelImpl() {\n    // Core training logic\n  }\n}\n```\n\n### Model Scoring\nModels implement `score0(double[] data, double[] preds)` for row-by-row prediction.\nFor production deployment:\n- **POJO**: Java code generated via `model.download_pojo()`\n- **MOJO**: Binary format via `model.download_mojo()` (more compact, faster)\n\n## Common Development Workflows\n\n### Adding a New Algorithm\n1. Create `MyAlgo.java` extending `ModelBuilder` in `h2o-algos/src/main/java/hex/`\n2. Implement nested `MyAlgoModel`, `MyAlgoParameters`, `MyAlgoOutput` classes\n3. Add algorithm instantiation to `water.api.RegisterAlgos` with `startup_once=true`\n4. Add tests in `h2o-algos/src/test/java/hex/myalgo/`\n5. Rebuild: `./gradlew :h2o-algos:build`\n\n### Modifying Core Data Structures\nBe cautious when modifying:\n- `water.fvec.Vec`, `water.fvec.Chunk`: Core data structures used everywhere\n- `water.DKV`: Distributed key-value operations\n- `water.H2O`: Cluster management and lifecycle\n\nThese changes can have wide-reaching implications across all algorithms.\n\n### Debugging Distributed Code\n- H2O tests spawn multiple JVMs that form a cluster\n- Logs are in `build/` with names like `h2o_<node_ip>_<port>.log`\n- Enable verbose logging: `-Dlog.level=DEBUG` or `-Dlog.level=TRACE`\n- Use `Log.info()`, `Log.warn()`, `Log.err()` (not `System.out`)\n\n### Building Documentation\n```bash\n./gradlew clean && ./gradlew build -x test && (export DO_FAST=1; ./gradlew dist)\nopen target/docs-website/h2o-docs/index.html\n```\n\n## Git Workflow\n\n### Branch Naming\nIf working on a GitHub issue, include the issue number and GitHub username if provided:\n```bash\ngit checkout -b githubusername-gh-1234_add_new_feature\n```\n\n### Pull Requests\n- New code requires unit tests (runits for R, pyunits for Python, JUnits for Java)\n- PR title should include GitHub issue number: \"GH-1234: Added new feature\"\n- PRs trigger Jenkins CI tests automatically\n- All tests must pass before merge\n\n#### prCheck Rules (enforced by `gradle/prCheck.gradle`)\n1. Always have a GitHub issue before starting work (otherwise you cannot know which branch to start from).\n2. The GitHub issue must have a milestone assigned. If it does not, consult the team for a suitable fix version.\n3. If the milestone ends with `.1`, the change targets the `master` branch. All other changes target the current fix release branch, prefixed `rel-` (e.g. `rel-3.46.0`).\n4. Assign the issue to the H2O-3 project and move it to the \"In Progress\" state.\n5. Include the GitHub issue number (`GH-XXXX`) in at least one commit message. Not checked by CI, but expected.\n6. The PR title must include the issue number, and the PR description must link the issue, e.g. `GH-4200: Adding support for Factorization Machines`. This is checked by CI.\n7. If a PR is intentionally not tied to an issue (docs-only cleanups, tooling tweaks), append **`[nocheck]` at the end** of the title — e.g. `Document PR conventions in CLAUDE.md [nocheck]`. `gradle/prCheck.gradle` skips validation when it sees the marker anywhere in the title, but keep it at the end by convention so reviewers read the actual change first. Target the **current fix release branch** (e.g. `rel-3.46.0` today, `rel-3.48.0` once that line is cut) — not `master` — so the change ships in the upcoming release and flows forward into master on the next merge. Target `master` only when the change is inherently master-only.\n\n#### Updating an open PR\n- **Prefer new commits over force-push.** Once a PR is under review, add follow-up commits (`git commit`, `git push`) so reviewers see the incremental diff and GitHub preserves comment anchors.\n- **Use force-push only for genuine history surgery** — rebasing onto a different base branch, resolving a merge conflict before first review, or dropping a committed secret. Not for squashing or amending typos that already landed on the remote.\n- Squashing can happen at merge time via the GitHub \"Squash and merge\" button if the maintainer prefers a single commit.\n\n#### PR description style\n- **Be brief.** One short paragraph or a handful of bullets. A reviewer should understand the what and the why in under 30 seconds.\n- **Focus on the change and its motivation** — what problem this solves, which CVE/bug it fixes, which user-visible behaviour shifts.\n- **Link the issue** (`Closes #N` or similar) so GitHub auto-closes it on merge.\n- **Do not include test-suite results or CI stats** (`All 42 tests passing`, `20/20 green`, runtime numbers, coverage deltas). Tests passing is assumed; CI reports them.\n- **Do not include meaningless stats** (file counts, LOC changes, \"refactored 5 classes\"). The diff shows them.\n- **Do not narrate the process** (`first I tried X, then Y`, `I investigated…`). Ship the conclusion.\n- **Screenshots / logs only when they add information** the reviewer can't get from the diff (UI changes, runtime traces for a bug reproduction).\n\n#### Issue hygiene\nWhen creating or editing a GitHub issue:\n- **Don't paste information that already lives elsewhere** (CVE advisories, long error logs, full stack traces). Summarise in a couple of sentences and link the source.\n- **Fix version belongs in the milestone, not the description.** Never write `Fix version: 3.46.0.11` in the body — set the milestone field instead (`gh issue edit N --milestone \"3.46.0.11\"`).\n- **Assignee is required** (checked by `prCheck`). Set it when you open the issue.\n- **Project is required** (checked by `prCheck`). Add the issue to the `H2O OSS (H2O-3)` project (project number 112).\n- **Labels**: add one when it's obvious (`bug`, `feature`, `docs`, `dependencies`, …). Skip if unclear. **CVE or security-related tasks must carry the `Security Vulnerability` label.**\n- **Relationships**: if a PR already exists for the issue, link it from the Development section of the issue UI.\n- **Project fields** (see `H2O OSS (H2O-3)` side panel): fill what you know — `Status` (set to `In Progress` once work starts), `Customer`, `Support ticket`, `CVEs fixed` (comma-separated CVE IDs), `Complexity` (Story Points 1-5, see scale below), `Private notes`. Leave blank rather than guessing.\n\n#### Issue fields & triage\nApplies to both new issues you open and existing ones you review.\n\n**Before triaging, always read the project-side fields.** `gh issue view` shows labels / milestone / assignees but **not** custom project fields (`Customer`, `Support ticket`, `CVEs fixed`, `Complexity`, linked PRs, etc.). Those are only visible via `gh project item-list 112 --owner h2oai --format json | jq '.items | map(select(.content.number == N)) | .[0]'`. Skipping this step is how you wrongly conclude an issue is actionable-less when it actually has a support ticket, customer, or open PR attached.\n\n**For existing issues — consider closing when:**\n- You're ~80% sure it's outdated.\n- Nobody can still understand what the issue is about.\n- There's a closed support ticket referenced in the comments.\n- Before closing: assign the project and link the support ticket in the project details.\n- Default to closing rather than asking clarifying questions.\n- **Never close an issue without explicit confirmation from the user first.** Closing is visible to others and reopening is annoying; always propose the close action and wait for a go-ahead.\n\n**For any issue you keep open (or create):**\n- **Assignee** — set a current owner, or clear it if the previous owner no longer works on H2O-3.\n- **Labels** — add what fits:\n  - algo family (`GBM`, `GLM`, `XGBoost`, …),\n  - `Security Vulnerability` (required for any CVE / security task),\n  - `question`, `good_first_issue`, `docs`, `dependencies`, `Build`, …\n  - Optionally a type label: `bug`, `feature`, or a `Task` tag.\n  - **Do not use customer-specific labels on the issue itself** — customer info belongs in the project `Customer` field.\n- **Project** — add the issue to `H2O OSS (H2O-3)` (project number 112). Required by `prCheck`.\n- **Complexity (Story Points)** — fill the project field on a 1–5 scale:\n  - **1** — good first issue.\n  - **2-3** — understandable requirement, just time and effort for an in-house developer (example: [#7518](https://github.com/h2oai/h2o-3/issues/7518)).\n  - **4** — requires study, time, and effort, but no new infrastructure (example: new algorithm like HDBSCAN / KNN, or dropping support for a Python version).\n  - **5** — requires study, time, effort, **and** new infrastructure (example: XGBoost on Windows, adding a new Java / R / Python version).\n\n### Commit Messages\nFollow the existing style seen in recent commits (concise, descriptive).\n\n## Python/R Client Development\n\n### Regenerating Bindings\nAfter modifying REST API schemas:\n```bash\n./gradlew :h2o-bindings:build\n```\nThis regenerates Python and R client code in `h2o-py/h2o/` and `h2o-r/h2o-package/R/`.\n\n## Environment Setup Notes\n\n### Required Software\n- **JDK**: 1.8+ (Java 8 or later)\n- **Node.js**: For building Flow UI\n- **Python**: 3.6+ with `pip` (for Python bindings and build tools)\n- **R**: 3.1+ with packages: RCurl, jsonlite, statmod, devtools, roxygen2, testthat\n- **Gradle**: Via `gradlew` wrapper (auto-downloaded)\n\n### Running Tests Requirements\n- Minimum 8GB RAM (16GB recommended)\n- Tests spawn 5 JVMs forming an H2O cluster\n- Use `-x test` to skip during builds if system resources are limited\n\n## Hadoop Builds\n\nTo build H2O-on-Hadoop assemblies:\n```bash\nexport BUILD_HADOOP=1\n./gradlew build -x test\n```\n\nAssemblies created in `target/` for various Hadoop distributions (CDH, HDP, MapR, EMR).\n\nTo build only specific distributions:\n```bash\nexport BUILD_HADOOP=1\nexport H2O_TARGET=hdp2.6,cdh6.3\n./gradlew build -x test\n```\n\n## Building H2O Assemblies\n\nThis project builds two main assemblies:\n\n### Main Assembly -- part of DockerHub h2o-open-source-k8s and python backend. Should be same as build/h2o.jar\nThe **main assembly** (`h2o-assemblies/main`) is the full-featured H2O distribution with all standard components.\n\n**Build command:**\n```bash\n./gradlew :h2o-assemblies:main:build\n```\n\n**Output location:**\n- `h2o-assemblies/main/build/libs/h2o.jar`\n\n**Key features:**\n- Full H2O Application with all standard components\n- Includes web UI, parsers (Avro, Parquet), persistence layers (S3, GCS, HDFS, HTTP)\n- Contains Hadoop dependencies and Kubernetes support\n- Uses Jetty 9 with full feature set\n- Main class: `water.H2OApp`\n\n### Steam Assembly\nThe **steam assembly** (`h2o-assemblies/steam`) is a secure, minimal H2O distribution for use with H2O Steam.\n\n**Build command:**\n```bash\n./gradlew :h2o-assemblies:steam:build\n```\n\n**Output location:**\n- `h2o-assemblies/steam/build/libs/h2o.jar`\n\n**Key features:**\n- Secure deployment optimized for H2O Steam integration\n- Uses minimal Jetty 9 configuration\n- Excludes h2o-jaas-pam module for security\n- Includes persistence layers with reduced Hadoop footprint\n- Main class: `water.H2OApp`\n\n### Build Both Assemblies\nTo build both assemblies at once:\n```bash\n./gradlew :h2o-assemblies:main:build :h2o-assemblies:steam:build\n```\n\n**Notes:**\n- Both assemblies use the Gradle Shadow plugin to create fat jars\n- Both include security fixes and vulnerability patches via dependency constraints\n- The standard build (`./gradlew build`) excludes these assemblies by default\n- See `h2o-assemblies/main/build.gradle` and `h2o-assemblies/steam/build.gradle` for full dependency details\n\n## Code Commenting Guidelines\n\nWhen writing or modifying code, follow these commenting principles:\n\n### DO:\n- **Comment code blocks**: Add comments that explain the purpose, logic, or reasoning behind a block of code\n- **Comment complex logic**: Explain non-obvious algorithms, business rules, or intricate operations\n- **Comment \"why\" not \"what\"**: Focus on the reasoning and context rather than describing what the code literally does\n- **Add context**: Explain assumptions, constraints, or important background information\n\n### DON'T:\n- **Avoid line-by-line comments**: Don't add comments after each line of code\n- **Don't state the obvious**: Avoid commenting self-explanatory method names or trivial operations\n- **Don't redundant comments**: If the code is clear and readable, additional comments may not be needed\n\n### Examples:\n\n#### ❌ Bad (over-commenting):\n```java\nint count = 0; // Initialize count to zero\nfor (int i = 0; i < items.size(); i++) { // Loop through items\n    count++; // Increment count\n}\nreturn count; // Return the count\n```\n\n#### ✓ Good (block-level comment when needed):\n```java\n// Calculate total items for billing reconciliation.\n// Note: This excludes cancelled orders per business rules in JIRA-1234\nint count = 0;\nfor (int i = 0; i < items.size(); i++) {\n    if (!items.get(i).isCancelled()) {\n        count++;\n    }\n}\nreturn count;\n```\n\n#### ✓ Good (no comment needed for obvious code):\n```java\npublic void saveUser(User user) {\n    userRepository.save(user);\n}\n```\n","category":"root","tokens":4491}]}