/ CONTRIBUTING.md
CONTRIBUTING.md
1 # Contributing to Oxyjen 2 3 First off, **thank you** for considering contributing to Oxyjen! 4 5 This project is built in public and community-driven. Whether you're fixing a typo, adding a feature, or just providing feedback - every contribution matters. 6 7 --- 8 9 ## Table of Contents 10 11 - [Code of Conduct](#code-of-conduct) 12 - [How Can I Contribute?](#how-can-i-contribute) 13 - [Getting Started](#getting-started) 14 - [Development Workflow](#development-workflow) 15 - [Pull Request Process](#pull-request-process) 16 - [Coding Guidelines](#coding-guidelines) 17 - [Project Structure](#project-structure) 18 - [Current Priorities](#current-priorities) 19 - [Recognition](#recognition) 20 21 --- 22 23 ## Code of Conduct 24 25 ### Our Pledge 26 27 We are committed to providing a welcoming and inspiring community for everyone. Please be respectful, constructive, and kind. 28 29 ### Unacceptable Behavior 30 31 - Harassment, trolling, or insulting comments 32 - Personal or political attacks 33 - Publishing others' private information 34 - Any conduct that would be inappropriate in a professional setting 35 36 ### Enforcement 37 38 If you experience or witness unacceptable behavior, please report it by opening an issue or contacting [@11divyansh](https://github.com/11divyansh). 39 40 --- 41 42 ## How Can I Contribute? 43 44 ### 1. Reporting Bugs 45 46 Found a bug? Help us fix it! 47 48 **Before submitting:** 49 - Check if the bug has already been reported in [Issues](../../issues) 50 - Make sure you're using the latest version 51 52 **How to report:** 53 1. Go to [Issues](../../issues/new) 54 2. Use the "Bug Report" template if available 55 3. Provide: 56 - Clear title (e.g., "Executor throws NPE when graph is empty") 57 - Description of what happened vs what you expected 58 - Steps to reproduce 59 - Java version, OS, and Oxyjen version 60 - Code snippet if possible 61 - Stack trace or error message 62 63 **Example:** 64 ````markdown 65 **Title:** Executor crashes when NodeContext is null 66 67 **Description:** 68 The Executor throws NullPointerException when NodeContext is null, 69 but it should throw a more descriptive error. 70 71 **Steps to Reproduce:** 72 1. Create a Graph with one node 73 2. Call executor.run(graph, input, null) 74 3. NPE is thrown 75 76 **Expected:** IllegalArgumentException with message "NodeContext cannot be null" 77 **Actual:** NullPointerException 78 79 **Environment:** 80 - Oxyjen v0.1.0 81 - Java 11 82 ```` 83 84 --- 85 86 ### 2. Suggesting Features 87 88 Have an idea? We'd love to hear it! 89 90 **Before suggesting:** 91 - Check [Issues](../../issues) and [Discussions](../../discussions) for similar ideas 92 - Consider if it aligns with [Oxyjen's vision](README.md#-my-vision-for-oxyjen) 93 94 **How to suggest:** 95 1. Go to [Issues](../../issues/new) or [Discussions](../../discussions/new) 96 2. Use "Feature Request" label 97 3. Provide: 98 - Clear title describing the feature 99 - Use case - what problem does it solve? 100 - Proposed solution 101 - Alternative solutions you considered 102 - Code examples (if applicable) 103 104 **Example:** 105 ````markdown 106 **Title:** Add support for conditional node execution 107 108 **Use Case:** 109 I want to run different nodes based on previous outputs. 110 E.g., if sentiment is negative, run escalation node, 111 else run standard response node. 112 113 **Proposed Solution:** 114 ```java 115 Graph pipeline = GraphBuilder.named("conditional") 116 .addNode(new SentimentNode()) 117 .addConditionalBranch( 118 condition: ctx -> ctx.get("sentiment").equals("negative"), 119 ifTrue: new EscalationNode(), 120 ifFalse: new StandardNode() 121 ) 122 .build(); 123 ``` 124 125 **Alternatives:** 126 - Use separate graphs for each branch 127 - Implement logic inside node (but this mixes concerns) 128 ```` 129 130 --- 131 132 ### 3. Contributing Code 133 134 This is where the magic happens! Here's how to contribute code: 135 136 --- 137 138 ## Getting Started 139 140 ### Prerequisites 141 142 - **Java 11+** (Java 17+ recommended) 143 - **Maven 3.6+** 144 - **Git** 145 - Your favorite IDE (IntelliJ IDEA, Eclipse, VS Code) 146 147 ### Fork & Clone 148 149 1. **Fork the repository** 150 - Click "Fork" button on [GitHub](https://github.com/11divyansh/OxyJen) 151 152 2. **Clone your fork** 153 ````bash 154 git clone https://github.com/YOUR_USERNAME/OxyJen.git 155 cd OxyJen 156 ```` 157 158 3. **Add upstream remote** 159 ````bash 160 git remote add upstream https://github.com/11divyansh/OxyJen.git 161 ```` 162 163 4. **Verify remotes** 164 ````bash 165 git remote -v 166 # origin https://github.com/YOUR_USERNAME/OxyJen.git (fetch) 167 # origin https://github.com/YOUR_USERNAME/OxyJen.git (push) 168 # upstream https://github.com/11divyansh/OxyJen.git (fetch) 169 # upstream https://github.com/11divyansh/OxyJen.git (push) 170 ```` 171 172 ### Build & Test 173 ````bash 174 # Build the project 175 mvn clean install 176 177 # Run tests 178 mvn test 179 180 # Run specific test 181 mvn test -Dtest=ExecutorTest 182 183 # Skip tests (not recommended!) 184 mvn clean install -DskipTests 185 ```` 186 187 **Expected output:** 188 ```` 189 [INFO] BUILD SUCCESS 190 [INFO] Total time: 5.234 s 191 ```` 192 193 --- 194 195 ## Development Workflow 196 197 ### Step 1: Create a Branch 198 199 **Always create a new branch for your work. Never commit directly to `main`.** 200 ````bash 201 # Update your local main 202 git checkout main 203 git pull upstream main 204 205 # Create feature branch 206 git checkout -b feature/your-feature-name 207 208 # Or for bug fixes 209 git checkout -b fix/bug-description 210 ```` 211 212 **Branch naming conventions:** 213 - `feature/add-openai-integration` - New features 214 - `fix/executor-null-pointer` - Bug fixes 215 - `docs/improve-readme` - Documentation 216 - `refactor/simplify-context` - Code refactoring 217 - `test/add-executor-tests` - Adding tests 218 219 ### Step 2: Make Your Changes 220 221 **Write clean, focused code:** 222 - One feature/fix per branch 223 - Keep changes small and reviewable 224 - Write tests for new functionality 225 - Update documentation if needed 226 227 **Example workflow:** 228 ````bash 229 # Make changes to files 230 vim src/main/java/io/oxyjen/core/Executor.java 231 232 # Run tests frequently 233 mvn test 234 235 # Add files 236 git add src/main/java/io/oxyjen/core/Executor.java 237 238 # Commit with clear message 239 git commit -m "feat: add retry logic to Executor" 240 ```` 241 242 ### Step 3: Keep Your Branch Updated 243 ````bash 244 # Fetch latest changes from upstream 245 git fetch upstream 246 247 # Rebase your branch on latest main 248 git rebase upstream/main 249 250 # If conflicts occur, resolve them, then: 251 git add . 252 git rebase --continue 253 ```` 254 255 ### Step 4: Push Your Changes 256 ````bash 257 # Push to your fork 258 git push origin feature/your-feature-name 259 260 # If you rebased, you might need force push 261 git push origin feature/your-feature-name --force-with-lease 262 ```` 263 264 --- 265 266 ## Pull Request Process 267 268 ### Before Opening a PR 269 270 **Checklist:** 271 - [ ] Code builds successfully (`mvn clean install`) 272 - [ ] All tests pass (`mvn test`) 273 - [ ] Added tests for new features 274 - [ ] Updated documentation (JavaDocs, README) 275 - [ ] Followed [coding guidelines](#coding-guidelines) 276 - [ ] Commits are clean and descriptive 277 - [ ] Branch is up-to-date with `main` 278 279 ### Opening a PR 280 281 1. Go to [Pull Requests](../../pulls) 282 2. Click "New Pull Request" 283 3. Select: 284 - **base:** `11divyansh/OxyJen` → `main` 285 - **compare:** `YOUR_USERNAME/OxyJen` → `feature/your-feature` 286 4. Fill in the template: 287 ````markdown 288 ## Description 289 Brief description of what this PR does. 290 291 ## Related Issues 292 Fixes #123 293 Relates to #456 294 295 ## Changes Made 296 - Added retry logic to Executor 297 - Updated Executor tests 298 - Added JavaDoc for new methods 299 300 ## Testing 301 - [ ] Unit tests added/updated 302 - [ ] Manual testing completed 303 - [ ] All tests pass locally 304 305 ## Screenshots (if applicable) 306 [Add screenshots for UI changes] 307 308 ## Checklist 309 - [ ] Code builds successfully 310 - [ ] Tests pass 311 - [ ] Documentation updated 312 - [ ] Follows coding guidelines 313 ```` 314 315 ### PR Review Process 316 317 1. **Automated checks run** (if CI is set up) 318 2. **Maintainer reviews** within 24-48 hours 319 3. **You address feedback** by pushing new commits 320 4. **Approval & merge** once everything looks good 321 322 **During review:** 323 - Be open to feedback 324 - Ask questions if something is unclear 325 - Make requested changes promptly 326 - Be patient and professional 327 328 **After merge:** 329 - Your branch will be deleted (automatically or manually) 330 - You'll be credited in release notes 331 - Your name will be added to Contributors list 332 333 --- 334 335 ## Coding Guidelines 336 337 ### Java Style 338 339 **Follow standard Java conventions:** 340 ````java 341 // Good 342 public class OpenAIClient { 343 private final String apiKey; 344 345 public OpenAIClient(String apiKey) { 346 this.apiKey = Objects.requireNonNull(apiKey); 347 } 348 349 /** 350 * Sends a chat completion request to OpenAI. 351 * 352 * @param request The chat request 353 * @return The response from OpenAI 354 * @throws IOException if network error occurs 355 */ 356 public ChatResponse chat(ChatRequest request) throws IOException { 357 // Implementation 358 } 359 } 360 361 // Bad 362 public class openAIClient { 363 String apiKey; // Not final, not private 364 365 public openAIClient(String key) { 366 apiKey = key; // No null check 367 } 368 369 // No JavaDoc 370 public ChatResponse chat(ChatRequest request) { 371 // Implementation 372 } 373 } 374 ```` 375 376 ### Code Quality Rules 377 378 **1. Naming** 379 - Classes: `PascalCase` (e.g., `OpenAIClient`, `NodeContext`) 380 - Methods/variables: `camelCase` (e.g., `processInput`, `apiKey`) 381 - Constants: `UPPER_SNAKE_CASE` (e.g., `MAX_RETRIES`) 382 - Packages: `lowercase` (e.g., `io.oxyjen.core`) 383 384 **2. Methods** 385 - Keep methods short (<50 lines ideally) 386 - One responsibility per method 387 - Use descriptive names (avoid abbreviations) 388 ````java 389 // Good 390 public String formatResponse(String raw) { 391 String trimmed = trim(raw); 392 String escaped = escapeHtml(trimmed); 393 return addMetadata(escaped); 394 } 395 396 // Bad 397 public String fmt(String r) { 398 return doStuff(r); 399 } 400 ```` 401 402 **3. Error Handling** 403 - Use specific exceptions 404 - Provide helpful error messages 405 - Don't swallow exceptions 406 ````java 407 // Good 408 if (input == null) { 409 throw new IllegalArgumentException( 410 "Input cannot be null. Provide a valid input string." 411 ); 412 } 413 414 // Bad 415 if (input == null) { 416 throw new Exception("error"); 417 } 418 ```` 419 420 **4. JavaDoc** 421 - Document all public classes and methods 422 - Explain WHY, not just WHAT 423 - Include `@param`, `@return`, `@throws` 424 ````java 425 /** 426 * Executes a graph pipeline with the given input. 427 * 428 * <p>This method runs each node sequentially, passing the output 429 * of one node as the input to the next. If any node fails, execution 430 * stops and an exception is thrown. 431 * 432 * @param graph The pipeline to execute 433 * @param input The initial input for the first node 434 * @param context Shared context for all nodes 435 * @param <I> Type of initial input 436 * @param <O> Type of final output 437 * @return The output from the last node in the pipeline 438 * @throws RuntimeException if any node fails during execution 439 */ 440 public <I, O> O run(Graph graph, I input, NodeContext context) { 441 // Implementation 442 } 443 ```` 444 445 **5. Tests** 446 - Write tests for new features 447 - Use descriptive test names 448 - Follow Arrange-Act-Assert pattern 449 ````java 450 @Test 451 void executorShouldThrowExceptionWhenGraphIsEmpty() { 452 // Arrange 453 Graph emptyGraph = new Graph("empty"); 454 NodeContext context = new NodeContext(); 455 Executor executor = new Executor(); 456 457 // Act & Assert 458 assertThrows(IllegalStateException.class, () -> { 459 executor.run(emptyGraph, "input", context); 460 }); 461 } 462 ```` 463 464 --- 465 466 ## Project Structure 467 ```` 468 OxyJen/ 469 ├── src/ 470 │ ├── main/ 471 │ │ └── java/ 472 │ │ └── io/oxyjen/ 473 │ │ ├── core/ # Core classes 474 │ │ │ ├── Executor.java 475 │ │ │ ├── Graph.java 476 │ │ │ ├── GraphBuilder.java 477 │ │ │ ├── NodePlugin.java 478 │ │ │ └── NodeContext.java 479 │ │ ├── llm/ # LLM integrations (v0.2+) 480 │ │ ├── tools/ # Tool integrations (v0.3+) 481 │ │ └── util/ # Utilities 482 │ └── test/ 483 │ └── java/ 484 │ └── io/oxyjen/ 485 │ └── core/ # Tests mirror main structure 486 ├── examples/ # Example usage(not added yet) 487 ├── docs/ # Documentation 488 ├── pom.xml 489 ├── README.md 490 ├── CONTRIBUTING.md 491 └── LICENSE 492 ```` 493 494 **Where to add your code:** 495 - New LLM provider → `src/main/java/io/oxyjen/llm/` 496 - New utility → `src/main/java/io/oxyjen/util/` 497 - New example → `examples/`(not added yet) 498 - Tests → Mirror the main structure in `src/test/` 499 500 --- 501 502 ## Current Priorities 503 504 ### High Priority (v0.2 - Next 1-2 Weeks) 505 506 **Help wanted on these tasks:** 507 508 #### 1. OpenAI Integration 509 **Goal:** Add ChatGPT support with streaming 510 511 **Tasks:** 512 - [ ] Create `OpenAIClient` with HTTP client 513 - [ ] Implement chat completions endpoint 514 - [ ] Add streaming support (Server-Sent Events) 515 - [ ] Create `OpenAIChatNode` implementing `NodePlugin` 516 - [ ] Add token counting 517 - [ ] Write comprehensive tests 518 - [ ] Add example usage in `examples/` 519 520 **Resources:** 521 - [OpenAI API Docs](https://platform.openai.com/docs/api-reference/chat) 522 - Use `java.net.http.HttpClient` (Java 11+) 523 524 **Related:** [Issue #1](../../issues/1) *(create this issue)* 525 526 --- 527 528 ### Medium Priority (v0.3+) 529 530 - [ ] Async execution with `CompletableFuture` 531 - [ ] DAG (Directed Acyclic Graph) support 532 - [ ] Conditional branching 533 - [ ] Retry logic with exponential backoff 534 - [ ] Circuit breaker pattern 535 - [ ] Performance benchmarking 536 537 ### Good First Issues 538 539 **New to the project? Start here:** 540 541 - [ ] Add examples 542 - [ ] Improve JavaDoc coverage 543 - [ ] Write unit tests for existing classes 544 - [ ] Fix typos in documentation 545 - [ ] Add inline code comments for complex logic 546 - [ ] Create utility methods (e.g., `StringUtils`, `JsonUtils`) 547 548 **Look for issues labeled:** `good-first-issue` or `help-wanted` 549 550 --- 551 552 ## Recognition 553 554 **All contributors are valued and recognized:** 555 556 ### Contributors List 557 Your name will be added to: 558 - README Contributors section 559 - Release notes for the version you contributed to 560 - GitHub's Contributors page 561 562 ### Special Recognition 563 - **First-time contributors** get a special shoutout 564 - **Significant contributions** get highlighted on social media 565 - **Regular contributors** may be invited as collaborators 566 567 ### Hall of Fame (Coming Soon) 568 We'll track: 569 - Most commits 570 - Most issues resolved 571 - Most helpful reviewer 572 - Best documentation 573 574 --- 575 576 ## Questions? 577 578 **Need help or have questions?** 579 580 - **Discussions:** [Start a discussion](../../discussions) 581 - **Issues:** [Check existing issues](../../issues) 582 - **Email:** *(Add your email if you want)* 583 - **Twitter:** *(Add your Twitter if you want)* 584 585 **Don't be shy!** No question is too basic. We're all learning together. 586 587 --- 588 589 ## Additional Resources 590 591 - [Java Code Conventions](https://www.oracle.com/java/technologies/javase/codeconventions-contents.html) 592 - [How to Write a Git Commit Message](https://chris.beams.io/posts/git-commit/) 593 - [GitHub Flow](https://guides.github.com/introduction/flow/) 594 595 --- 596 597 ## Thank You! 598 599 Every contribution, no matter how small, makes Oxyjen better. 600 601 **You're helping build the future of AI orchestration in Java.** 602 603 --- 604 605 *This document is a living guide. If you see ways to improve it, please submit a PR!*