| 1 | # Contributing to codewhale |
| 2 | |
| 3 | Thank you for your interest in contributing to codewhale! This document provides guidelines and instructions for contributing. |
| 4 | |
| 5 | ## Getting Started |
| 6 | |
| 7 | ### Prerequisites |
| 8 | |
| 9 | - Rust 1.88 or later (edition 2024) |
| 10 | - Cargo package manager |
| 11 | - Git |
| 12 | |
| 13 | ### Setting Up Development Environment |
| 14 | |
| 15 | 1. Fork and clone the repository: |
| 16 | ```bash |
| 17 | git clone https://github.com/YOUR_USERNAME/CodeWhale.git |
| 18 | cd CodeWhale |
| 19 | ``` |
| 20 | |
| 21 | 2. Build the project: |
| 22 | ```bash |
| 23 | cargo build |
| 24 | ``` |
| 25 | |
| 26 | 3. Run tests: |
| 27 | ```bash |
| 28 | cargo test --workspace --all-features |
| 29 | ``` |
| 30 | |
| 31 | 4. Run with development settings: |
| 32 | ```bash |
| 33 | cargo run --bin codewhale |
| 34 | ``` |
| 35 | |
| 36 | ## Development Workflow |
| 37 | |
| 38 | ### Code Style |
| 39 | |
| 40 | - Run `cargo fmt` before committing to ensure consistent formatting |
| 41 | - Run `cargo clippy` and address all warnings |
| 42 | - Follow Rust naming conventions (snake_case for functions/variables, CamelCase for types) |
| 43 | - Add documentation comments for public APIs |
| 44 | |
| 45 | ### Testing |
| 46 | |
| 47 | - Write tests for new functionality |
| 48 | - Run the tests near your change (see [Fast local loop](#fast-local-loop)); |
| 49 | CI runs the whole suite on every pull request |
| 50 | - Colocate unit tests beside the code they cover (standard Rust `#[cfg(test)]` |
| 51 | modules), and add integration tests under the owning crate's `tests/` |
| 52 | directory (for example `crates/tui/tests/` or `crates/state/tests/`). The |
| 53 | repository root `tests/` directory is not used |
| 54 | |
| 55 | ### Pre-push verification |
| 56 | |
| 57 | These are the commands CI runs on every pull request. You do not need all |
| 58 | of them before every push: run `cargo fmt`, then check and test the crates |
| 59 | you touched (see [Fast local loop](#fast-local-loop)). Run the full set |
| 60 | locally when a change spans many crates, or let CI run it for you: |
| 61 | |
| 62 | ```bash |
| 63 | cargo fmt --all -- --check |
| 64 | cargo clippy --workspace --all-features --locked -- \ |
| 65 | -D warnings \ |
| 66 | -A clippy::uninlined_format_args \ |
| 67 | -A clippy::too_many_arguments \ |
| 68 | -A clippy::unnecessary_map_or \ |
| 69 | -A clippy::collapsible_if \ |
| 70 | -A clippy::assertions_on_constants |
| 71 | cargo test --workspace --all-features --locked |
| 72 | ``` |
| 73 | |
| 74 | The release lane runs a stricter clippy that also lints test, bench, and |
| 75 | example targets. Use this form for release-bound work, because |
| 76 | `--all-features` alone skips lints that will fail the release lane later: |
| 77 | |
| 78 | ```bash |
| 79 | cargo clippy --workspace --all-targets --all-features --locked -- \ |
| 80 | -D warnings \ |
| 81 | -A clippy::uninlined_format_args \ |
| 82 | -A clippy::too_many_arguments \ |
| 83 | -A clippy::unnecessary_map_or \ |
| 84 | -A clippy::collapsible_if \ |
| 85 | -A clippy::assertions_on_constants |
| 86 | ``` |
| 87 | |
| 88 | #### Fast local loop |
| 89 | |
| 90 | The full gate above is what CI enforces, but you do not need it for every |
| 91 | edit. `crates/tui` is a ~750k-line crate, so the loop that stays fast is |
| 92 | the one that avoids rebuilding it more than necessary (numbers and the |
| 93 | reasoning are in [`docs/BUILD_PERFORMANCE.md`](docs/BUILD_PERFORMANCE.md)): |
| 94 | |
| 95 | ```bash |
| 96 | # 1. Type-check first (seconds after the first build; no codegen, no link). |
| 97 | scripts/dev-cargo.sh check -p codewhale-tui |
| 98 | |
| 99 | # 2. Run only the tests near your change (one crate, one filter). |
| 100 | scripts/dev-test.sh tui fleet_setup |
| 101 | # or: scripts/dev-test.sh crates/runtime/src/elapsed.rs |
| 102 | |
| 103 | # 3. Run a whole crate's unit suite. scripts/dev-test.sh uses nextest when |
| 104 | # it is installed (one process per test, all cores busy, slow tests |
| 105 | # named; ~100 s here vs ~270 s with libtest). |
| 106 | cargo install cargo-nextest --locked # once |
| 107 | scripts/dev-test.sh tui |
| 108 | scripts/dev-cargo.sh nextest run --workspace --all-features --locked |
| 109 | |
| 110 | # 4. The authoritative gate, exactly as CI runs it on your PR: |
| 111 | cargo test --workspace --all-features --locked |
| 112 | ``` |
| 113 | |
| 114 | `.config/nextest.toml` already serializes the PTY suite and bounds the |
| 115 | integration tests that spawn the real binary, so `cargo nextest run` is |
| 116 | safe to use on the whole workspace (nextest does not run doctests; the |
| 117 | authoritative `cargo test` gate does). Tests must not depend on running in |
| 118 | the same process as another test (nextest gives every test its own |
| 119 | process); if a test needs the rustls crypto provider, install it in that |
| 120 | test as production does at startup. |
| 121 | |
| 122 | On a machine with less than 16 GB of RAM (or when cross-compiling, e.g. |
| 123 | for OHOS), build one rustc at a time: `CARGO_BUILD_JOBS=1` (or `-j1`), one |
| 124 | crate at a time, `--lib` for tests, never `--workspace`/`--all-targets`. |
| 125 | The tui library needs ~6 GB for its own rustc and its unit-test build ~8 GB; |
| 126 | `cargo test --workspace` runs both at once. Numbers and the full recipe: |
| 127 | [`docs/BUILD_PERFORMANCE.md`](docs/BUILD_PERFORMANCE.md#low-memory-build-recipe-machines-with--16-gb-cross-builds). |
| 128 | |
| 129 | If you work in several worktrees, do **not** share one `CARGO_TARGET_DIR` |
| 130 | by default: two cargos on the same target flock and serialize. Use |
| 131 | `scripts/dev-cargo.sh` / `scripts/dev-test.sh`, which give each workspace |
| 132 | its own Cargo `build-dir` (`{workspace-path-hash}` under |
| 133 | `${CODEWHALE_CACHE_ROOT:-${XDG_CACHE_HOME:-$HOME/.cache}/codewhale}`). |
| 134 | `CODEWHALE_DEV_CACHE=local` keeps `./target` if you want that. |
| 135 | `sccache` wraps rustc only when incremental compilation is already off |
| 136 | (`CARGO_INCREMENTAL=0` or `CODEWHALE_SCCACHE=1`) and `sccache` is on |
| 137 | `PATH`; a missing binary is a printed fallback, not an error. Override |
| 138 | the cache root with `CODEWHALE_CACHE_ROOT` — there is no machine-specific |
| 139 | default. A single shared `CARGO_TARGET_DIR` remains valid only for |
| 140 | serialized trunk work. See |
| 141 | [`docs/BUILD_PERFORMANCE.md`](docs/BUILD_PERFORMANCE.md). |
| 142 | |
| 143 | Some checks are platform-bound or intentionally excluded from an ordinary |
| 144 | change. Choose them for the risk they answer rather than treating every |
| 145 | available suite as ritual. Visible TUI behavior is accepted in the actual |
| 146 | terminal at the sizes and interaction path affected by the change; the former |
| 147 | full-screen PTY assertion suite was removed because it froze layout and copy |
| 148 | while missing product quality. |
| 149 | |
| 150 | - **Long-running process acceptance** should use a sealed local home, local |
| 151 | fixtures, and the real binary. Record the terminal size, inputs, visible |
| 152 | result, and any filesystem side effect instead of adding a full-screen |
| 153 | golden. |
| 154 | - **OCR** (`image_ocr`) uses the macOS Vision framework or a locally |
| 155 | installed `tesseract`; its platform-specific paths are |
| 156 | `cfg(target_os = "macos")`-gated and depend on host tooling. |
| 157 | - **Seatbelt sandbox** tests are macOS-only (`cfg(target_os = |
| 158 | "macos")` at the module level) and do not run elsewhere. |
| 159 | |
| 160 | #### Local git hooks are optional |
| 161 | |
| 162 | This repository does not install git hooks, and no hook installer |
| 163 | exists; CI is the enforced gate. If you want a local `pre-push` hook |
| 164 | that runs the commands above, add it yourself (`.git/hooks/pre-push` or |
| 165 | `git config core.hooksPath`). Constraints for any local hook: |
| 166 | |
| 167 | - A hook must never push, tag, publish, deploy, mutate credentials, or |
| 168 | rewrite the working tree (no auto-fix commits or silent file |
| 169 | modification). It may only verify and report. |
| 170 | - To bypass your own hook for a knowingly documented reason (for |
| 171 | example, pushing work-in-progress to your own fork branch), use |
| 172 | `git push --no-verify` and say so in the PR description. Bypassing a |
| 173 | local hook does not make the gates pass — CI still runs them, and a |
| 174 | bypassed gate must never be reported as a passing one. |
| 175 | - Release publication (tags, GitHub Releases, crates/npm artifacts) is a |
| 176 | separate, owner-approved gate. Neither local hooks nor a green local |
| 177 | run authorize any publication step. |
| 178 | |
| 179 | ### Commit Messages |
| 180 | |
| 181 | Use clear, descriptive commit messages following conventional commits: |
| 182 | |
| 183 | - `feat:` New feature |
| 184 | - `fix:` Bug fix |
| 185 | - `docs:` Documentation changes |
| 186 | - `refactor:` Code refactoring |
| 187 | - `test:` Adding or updating tests |
| 188 | - `chore:` Maintenance tasks |
| 189 | |
| 190 | Example: `feat: add doctor subcommand for system diagnostics` |
| 191 | |
| 192 | **Changelog entries are written on `main` at merge time, not in PRs.** Do not |
| 193 | edit `CHANGELOG.md` or `crates/tui/CHANGELOG.md` on a branch: every PR |
| 194 | touching them re-conflicts with every other PR touching them. The release |
| 195 | manager writes one batched "receipts" commit per merge session, and |
| 196 | `./scripts/sync-changelog.sh` keeps the packaged slice in sync. A PR that |
| 197 | carries changelog hunks will be asked to strip them |
| 198 | (`git checkout origin/main -- CHANGELOG.md crates/tui/CHANGELOG.md`). |
| 199 | |
| 200 | One exception is enforced by CI: a `feat:` commit whose message mentions an |
| 201 | issue (`#N`) must add `#N` to `CHANGELOG.md` in the same PR |
| 202 | (`scripts/release/check-feature-release-notes.sh`). To avoid touching the |
| 203 | changelog, put issue numbers in the PR description instead of in `feat:` |
| 204 | commit messages; the maintainer writes the entry at merge time. |
| 205 | |
| 206 | **AI-assistant co-author trailers are fine.** Using an assistant is welcome and |
| 207 | needs no disclosure, and CI no longer rejects an auto-appended |
| 208 | `Co-authored-by: <some tool>` line. What we do care about is that the humans who |
| 209 | did the work are named — `Co-authored-by` feeds the GitHub contribution graph. |
| 210 | Remove an auto-appended line only if you want to: |
| 211 | |
| 212 | ```bash |
| 213 | git rebase -i origin/main # reword each commit, delete the Co-authored-by line |
| 214 | ``` |
| 215 | |
| 216 | Co-author a *person* freely; the address must be their GitHub-linked one |
| 217 | (`id+login@users.noreply.github.com`) or the credit does not register. |
| 218 | |
| 219 | When a commit harvests code from a community PR (see "How Your Contribution |
| 220 | Lands" below), include a `Harvested from PR #N by @author` line in the commit |
| 221 | body. An auto-close workflow watches for this pattern and closes the |
| 222 | referenced PR with credit so the contributor gets a clear signal that |
| 223 | their work shipped. |
| 224 | |
| 225 | ## How Your Contribution Lands |
| 226 | |
| 227 | We follow a deliberate "land what's useful, credit the contributor" model |
| 228 | that occasionally surprises new contributors. Two paths: |
| 229 | |
| 230 | ### Path 1 — Direct merge |
| 231 | |
| 232 | If your PR is well-scoped, passes CI, doesn't touch the trust-boundary |
| 233 | surface (auth / sandbox / publishing / branding), and doesn't conflict |
| 234 | with main, a maintainer merges it directly. This is the most common |
| 235 | outcome for small bug fixes and well-tested feature additions. |
| 236 | |
| 237 | ### Path 2 — Harvest |
| 238 | |
| 239 | If your PR is large, mixes scope, conflicts with main, or needs polish |
| 240 | that's faster for the maintainer to apply than to round-trip with the |
| 241 | contributor, the maintainer may **harvest** the useful commits or hunks |
| 242 | into a new commit on `main` rather than merging the PR directly. This is |
| 243 | **not a rejection** — it means your code landed. |
| 244 | |
| 245 | When this happens: |
| 246 | |
| 247 | - The harvested commit's message includes `Harvested from PR #N by |
| 248 | @your-handle`. This is the contract: that line is your credit and the |
| 249 | signal that your contribution shipped. |
| 250 | - If the maintainer copies or adapts your code, the harvested commit also |
| 251 | keeps attribution with the original author identity when possible: either by |
| 252 | preserving the commit author on a cherry-pick or by adding a |
| 253 | `Co-authored-by: Name <id+login@users.noreply.github.com>` trailer. This is |
| 254 | what lets GitHub's contribution surfaces recognize more than prose credit. |
| 255 | Maintainers should use `.github/AUTHOR_MAP`, or run |
| 256 | `gh api users/<login> --jq '"\(.id)+\(.login)@users.noreply.github.com"'`, |
| 257 | rather than copying raw, `.local`, or old-style noreply emails from a |
| 258 | contributor's machine. |
| 259 | - The `CHANGELOG.md` entry for the next release credits you by handle. |
| 260 | - The auto-close workflow closes your PR with a templated thank-you and |
| 261 | a link to the commit on `main`. |
| 262 | |
| 263 | When a maintainer closes a harvested PR by hand, the closing comment |
| 264 | follows this template (the pattern set on PR #2634): |
| 265 | |
| 266 | ```text |
| 267 | Closing with harvest credit, @handle — <what landed> landed via |
| 268 | <commit sha(s) or PR #N>. <If work remains:> The remainder is tracked |
| 269 | in #NNN — follow-ups welcome there. |
| 270 | Thank you for <one specific thing the contribution got right>. |
| 271 | ``` |
| 272 | |
| 273 | Three required elements: the contributor's handle, the exact commits or |
| 274 | PRs where their work landed, and — when the PR contained more than what |
| 275 | landed — a tracking issue for the remainder. A harvested PR is never |
| 276 | closed with a bare "superseded". |
| 277 | |
| 278 | To make a future contribution land via the faster Direct-Merge path |
| 279 | instead of the Harvest path, the highest-leverage things you can do are: |
| 280 | |
| 281 | 1. **Keep PRs single-purpose.** One bug fix per PR; one feature per PR. |
| 282 | Don't mix a refactor with a feature. |
| 283 | 2. **Rebase onto current `main` before opening the PR**, and after CI |
| 284 | feedback. Conflicts force the harvest path even when the change is |
| 285 | small. |
| 286 | 3. **Include tests** with new behavior. The maintainer often harvests |
| 287 | PRs without tests because adding the test is faster than asking the |
| 288 | contributor for one. |
| 289 | 4. **Avoid the trust-boundary surface** without prior maintainer |
| 290 | sign-off. That includes auth/credential flows, sandbox policy, |
| 291 | publishing/release plumbing, and `prompts/` content. PRs that touch |
| 292 | these without prior discussion are unlikely to merge directly even |
| 293 | when the change is well-implemented. |
| 294 | |
| 295 | ## Layered and EPIC-Sized Work |
| 296 | |
| 297 | Some architecture work is too large for one PR but still needs to be built in |
| 298 | dependent layers. For those changes, use this workflow: |
| 299 | |
| 300 | 1. Start with a tracking issue or EPIC when the work spans multiple PRs. Name |
| 301 | the intended slices and state what each slice is not trying to close yet. |
| 302 | 2. Keep each implementation PR focused on one behavior boundary. |
| 303 | 3. Later layers may stay in your fork or open as draft PRs while the lower |
| 304 | layer is still moving. Draft stacked PR titles or descriptions should say |
| 305 | `Draft / depends on #NNNN`. |
| 306 | 4. A dependent PR is not ready for merge review until the lower layer has |
| 307 | landed, the branch has been rebased onto current `main`, and the PR targets |
| 308 | `main`. |
| 309 | 5. The PR body should identify which earlier PR it builds on, what is in scope, |
| 310 | what is explicitly out of scope, which issues it references, and which local |
| 311 | commands were run. |
| 312 | 6. Use `Closes #...` only when the slice fully satisfies an issue. Use |
| 313 | `Refs #...` with a short `(partial)` note when the PR advances a broad issue |
| 314 | but leaves follow-up work. |
| 315 | 7. Structured commits are fine during review. Maintainers may squash or harvest |
| 316 | at merge time, with contributor credit preserved through authorship, |
| 317 | co-author trailers, changelog entries, or PR/issue comments. When the merge |
| 318 | commit itself carries a `Harvested from PR #N by @author` line, that PR is |
| 319 | merged with rebase or a merge commit rather than squashed, so the line |
| 320 | reaches `main` intact and the auto-close credit fires. |
| 321 | |
| 322 | Before asking for merge review on a layered PR, check that it is: |
| 323 | |
| 324 | - rebased onto current `main` |
| 325 | - marked ready for review, not draft |
| 326 | - focused to one behavior boundary |
| 327 | - backed by local command evidence in the PR body |
| 328 | - green in CI, or has any remaining red lane clearly explained |
| 329 | - covered by round-trip or migration-preservation tests when it changes config |
| 330 | or schema behavior |
| 331 | - referencing broad issues as partial unless it really closes them |
| 332 | |
| 333 | For layered work, a useful PR description shape is: |
| 334 | |
| 335 | ```text |
| 336 | Summary: |
| 337 | Scope: |
| 338 | Not in this slice: |
| 339 | Builds on: |
| 340 | Issues: |
| 341 | Validation: |
| 342 | ``` |
| 343 | |
| 344 | ## Which branch to target |
| 345 | |
| 346 | **`main`, for everything.** There is no separate staging branch. An earlier |
| 347 | version of this guide pointed layered refactors at `codex/v0.9.0-stewardship`; |
| 348 | that branch no longer exists, so please ignore any instruction you find |
| 349 | elsewhere to base work on it. |
| 350 | |
| 351 | For a multi-PR series or anything that will collide with other in-flight work, |
| 352 | maintainers may land your branch on an `integration/<topic>-<pr>-<date>` branch |
| 353 | first and merge from there. That is our bookkeeping, not extra work for you — |
| 354 | you still open the PR against `main`, and your commits reach `main` with their |
| 355 | history and authorship intact. |
| 356 | |
| 357 | **We do not expect you to rebase around our churn.** If your PR conflicts only |
| 358 | because `main` moved while it was in review, say so and a maintainer resolves |
| 359 | it. If your branch is in a fork we cannot push to, we land the resolved merge |
| 360 | on an integration branch rather than asking you to redo the work. |
| 361 | |
| 362 | ## Contribution Gate |
| 363 | |
| 364 | Codewhale uses a maintainer-managed contribution gate for the community front |
| 365 | door. Maintainers and collaborators bypass this gate automatically. The gate |
| 366 | workflows default to dry-run / comment-only mode so maintainers can observe the |
| 367 | signal before changing contributor flow. |
| 368 | |
| 369 | The maintainer posture is documented in |
| 370 | [docs/AGENT_ETHOS.md](docs/AGENT_ETHOS.md): automation should reduce load while |
| 371 | keeping good-faith contributors seen, credited, and able to keep helping. |
| 372 | |
| 373 | Issues are never auto-closed by the contribution gate. Unapproved external |
| 374 | issues receive a short welcome note that asks for reproduction details and then |
| 375 | remain open for maintainer triage. Codewhale depends on real edge cases from |
| 376 | real users, so issue intake should stay warm and open. |
| 377 | |
| 378 | Pull requests are different because they can touch code, CI, release plumbing, |
| 379 | auth, sandboxing, provider policy, and other trust-boundary surfaces. The PR |
| 380 | gate can be switched from dry-run to enforcement when maintainers decide they |
| 381 | need that safety control, but it should be treated as a review-load control, |
| 382 | not a judgment on contributor quality. Before enabling PR enforcement, seed the |
| 383 | allowlist broadly enough for active external contributors who should not be |
| 384 | interrupted by the rollout. |
| 385 | |
| 386 | The allowlist is scoped: |
| 387 | |
| 388 | - `pr:username` allows pull requests. |
| 389 | - `issue:username` allows issues. |
| 390 | - `all:username` allows both. |
| 391 | |
| 392 | A maintainer can approve someone by commenting `/lgtm` on a pull request for PR |
| 393 | access, or `/lgtmi` on an issue for issue access. The exact bare commands |
| 394 | `lgtm` and `lgtmi` are also accepted for compatibility, but the prefixed forms |
| 395 | are preferred because they are harder to trigger accidentally in ordinary review |
| 396 | discussion. |
| 397 | |
| 398 | Approvals do not edit `main` directly. The approval workflow opens a small |
| 399 | allowlist update PR so the new entry is reviewable before it takes effect. |
| 400 | |
| 401 | If the PR gate fires on a good contributor incorrectly, use the same approval |
| 402 | flow to restore them: comment `/lgtm`, merge the generated allowlist PR, then |
| 403 | reopen the affected pull request. If GitHub will not allow the closed PR to be |
| 404 | reopened, ask the contributor to resubmit after the allowlist PR is merged. |
| 405 | |
| 406 | ## Agent-Assisted Improvements |
| 407 | |
| 408 | Codewhale is allowed to help improve Codewhale, but the contribution still has |
| 409 | to be shaped for human review. The recommended workflow is the recursive self-improvement prompt |
| 410 | in the private `codewhale-ops` repo: run it |
| 411 | from a fresh fork or branch, let the agent find exactly one small friction point, |
| 412 | and stop after one patch. DeepSeek V4 Pro is the reference path for this loop |
| 413 | today, but any configured provider works — the review shape matters more than |
| 414 | the provider. |
| 415 | |
| 416 | Agents and maintainers should follow the stewardship posture in |
| 417 | [docs/AGENT_ETHOS.md](docs/AGENT_ETHOS.md): use automation for evidence, |
| 418 | verification, and narrow patches while keeping the final community decision |
| 419 | human-reviewed. |
| 420 | |
| 421 | The useful output is not "ideas for improvement." The useful output is a |
| 422 | specific reproduction, a minimal diff, focused checks, and a PR description that |
| 423 | explains the trade-off. Do not use an agent to touch auth, credentials, sandbox |
| 424 | policy, publishing/release plumbing, provider policy, telemetry, sponsorship, |
| 425 | branding, or global prompts without prior maintainer sign-off. |
| 426 | |
| 427 | ## Project Structure |
| 428 | |
| 429 | Codewhale is a Cargo workspace with one Engine implementation in |
| 430 | `crates/tui/src/core/engine/`. The public `codewhale` executable links the |
| 431 | TUI/runtime library; interactive sessions, noninteractive runs and the Runtime |
| 432 | API share that Engine. |
| 433 | |
| 434 | | Path | Purpose | |
| 435 | | --- | --- | |
| 436 | | `crates/cli/` | Public command entrypoint, configuration commands and runtime dispatch | |
| 437 | | `crates/tui/` | Interactive terminal, Engine, tools, Runtime API and embedded local web client | |
| 438 | | `crates/core/`, `crates/protocol/`, `crates/state/` | Request construction, session/turn types, protocol framing and persistence | |
| 439 | | Other `crates/` | Shared configuration, credentials, telemetry, hooks, workflow and packaging support; see each Cargo manifest | |
| 440 | | `web/` | Public Next.js website and documentation; separate from the embedded Runtime web client | |
| 441 | | `telemetry-ingest/` | Telemetry service, schemas and service tests | |
| 442 | | `extensions/`, `integrations/` | Editor integration and external-service bridges | |
| 443 | | `npm/`, `packaging/`, `nix/` | npm wrappers/SDK and platform installation definitions | |
| 444 | | `computer/snapshots/` | Cloud Computer image definitions, pinned independently of the source checkout | |
| 445 | | `deploy/` | Deployment templates consumed by setup scripts, including Tencent Lighthouse services | |
| 446 | | `fleets/`, `workflows/` | Distributed Fleet definitions and workflow examples | |
| 447 | | `brand/` | Source artwork and generated brand variants used by the README, website and terminal | |
| 448 | | `docs/` | User/developer documentation, schemas, fixtures and referenced release material | |
| 449 | | `scripts/`, `.github/`, `.cnb.yml` | Development, validation, CI and release tooling | |
| 450 | | `patches/` | Vendored dependency fixes, including their licensing files | |
| 451 | |
| 452 | Generated files that the product embeds or validates, such as model catalogs, |
| 453 | website facts and schemas, remain tracked with their generators. Platform |
| 454 | mirrors such as `.winget/` are retained when their packaging tools require them. |
| 455 | Keep local critique output, temporary verification reports and personal |
| 456 | operator instructions outside the tracked product tree; describe the change |
| 457 | and its validation in the pull request. Do not copy workspace-level operator |
| 458 | `AGENTS.md` or `CLAUDE.md` files into this repository. |
| 459 | |
| 460 | See [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) for the runtime data flow and |
| 461 | [the build guide](docs/BUILD_PERFORMANCE.md) for crate dependencies and local |
| 462 | verification. |
| 463 | |
| 464 | ## Submitting Changes |
| 465 | |
| 466 | 1. Create a feature branch from `main`: |
| 467 | ```bash |
| 468 | git checkout -b feat/your-feature |
| 469 | ``` |
| 470 | |
| 471 | 2. Make your changes and commit them |
| 472 | |
| 473 | 3. Run the pre-push verification commands (see |
| 474 | [Pre-push verification](#pre-push-verification) above for the exact |
| 475 | gate and the stricter release clippy form) |
| 476 | |
| 477 | 4. Push your branch and create a Pull Request |
| 478 | |
| 479 | 5. Describe your changes clearly in the PR description |
| 480 | |
| 481 | ## Pull Request Guidelines |
| 482 | |
| 483 | - Use the [pull request template](.github/PULL_REQUEST_TEMPLATE.md) when opening |
| 484 | a PR — what and why, the issue line, and how you tested it |
| 485 | - The PR description needs one issue line, checked by CI |
| 486 | (`.github/workflows/pr-issue-link.yml`): `Closes #N` (or `Fixes` / |
| 487 | `Resolves`) when the PR finishes the issue, `Refs #N` for related or partial |
| 488 | work, or `No-Issue: <one-line reason>`. Never write a negated closing |
| 489 | keyword such as "does not close #N": GitHub closes the issue anyway, so CI |
| 490 | rejects it |
| 491 | - If you add a new layer, module, or abstraction, say which one it replaces |
| 492 | or deletes |
| 493 | - Keep PRs focused on a single change |
| 494 | - Update documentation if needed |
| 495 | - Add tests for new functionality |
| 496 | - Ensure CI passes before requesting review |
| 497 | |
| 498 | ## Shape of a Typical PR |
| 499 | |
| 500 | A well-structured PR follows a consistent pattern. Recent exemplars include: |
| 501 | |
| 502 | - **#386** — `/init` command: new `crates/tui/src/commands/groups/project/init.rs` module, project-type detection, |
| 503 | AGENTS.md generation, command registration in `commands/mod.rs`, localization strings. |
| 504 | - **#389** — Inline LSP diagnostics: LSP subsystem in `crates/tui/src/lsp/`, engine hooks in |
| 505 | `crates/tui/src/core/engine/lsp_hooks.rs`, config toggle, test coverage. |
| 506 | - **#387** — Self-update: new `crates/cli/src/update.rs` module, CLI subcommand registration, |
| 507 | HTTP download + SHA256 verification + atomic binary replacement. |
| 508 | - **#393** — `/share` session URL: new `crates/tui/src/commands/groups/project/share.rs`, HTML rendering, |
| 509 | `gh gist create` integration, command registration. |
| 510 | - **#343/#346** — (v0.8.5) Runtime thread/turn timeline and durable task manager refactors. |
| 511 | |
| 512 | Typically each PR touches 1–3 new files, modifies 2–5 existing files for wiring |
| 513 | (registries, dispatch matches, localization), and adds or updates tests. Changes |
| 514 | are scoped to a single feature or fix — if you discover related work that needs |
| 515 | doing, open a separate issue rather than expanding the PR scope. |
| 516 | |
| 517 | Before submitting, run the commands in |
| 518 | [Pre-push verification](#pre-push-verification). |
| 519 | |
| 520 | ## Reporting Issues |
| 521 | |
| 522 | When reporting issues, please use one of the issue templates: |
| 523 | |
| 524 | - [Bug report](.github/ISSUE_TEMPLATE/bug_report.yml) — for reproducible problems |
| 525 | or regressions |
| 526 | - [Feature request](.github/ISSUE_TEMPLATE/feature_request.yml) — for ideas and |
| 527 | improvements |
| 528 | |
| 529 | The forms ask for what a report needs (`codewhale --version`, OS, how you got |
| 530 | Codewhale, and steps to reproduce). Questions go to |
| 531 | [Discussions](https://github.com/codewhale-hq/CodeWhale/discussions) or |
| 532 | [Discord](https://discord.gg/37gfS3ksug). |
| 533 | |
| 534 | ## Security |
| 535 | |
| 536 | If you discover a security vulnerability, please do **not** open a public issue. |
| 537 | See [SECURITY.md](.github/SECURITY.md) for the responsible disclosure process and |
| 538 | contact information. |
| 539 | |
| 540 | ## Code of Conduct |
| 541 | |
| 542 | Be respectful and inclusive. We welcome contributors of all backgrounds and |
| 543 | experience levels. See [CODE_OF_CONDUCT.md](.github/CODE_OF_CONDUCT.md) for the full |
| 544 | code of conduct. |
| 545 | |
| 546 | ## License |
| 547 | |
| 548 | By contributing to codewhale, you agree that your contributions will be licensed under the MIT License. |
| 549 | |
| 550 | ## Questions? |
| 551 | |
| 552 | Feel free to open an issue for any questions about contributing. |
| 553 |