首页
/ CodeWhale 贡献者开发指南:本地验证门禁、快速迭代循环与 PR 落地(Harvest)流程

CodeWhale 贡献者开发指南:本地验证门禁、快速迭代循环与 PR 落地(Harvest)流程

2026-09-05 10:43:24作者:曹令琨Iris

CodeWhale 是一个用 Rust 编写的终端编码 Agent,本仓库的 CONTRIBUTING.md 不仅是一份贡献规范,更是一套可执行的开发工程手册:它规定了从 Rust 1.88+ 环境搭建、fmt/clippy/test 三级验证门禁,到 nextest 加速的本地快速循环、低内存机器构建配方、多 worktree 构建缓存隔离的完整做法,并详细说明了 PR 如何以“直接合并”或“Harvest(收割)”两种路径落地、贡献者署名如何被机器可读取地保留。读完本文,你能够按仓库实际门禁独立跑通一条完整的贡献流水线:本地修改 → 快速局部验证 → 全量权威门禁 → 提交符合署名规范的 PR。

环境要求与开发环境搭建

CodeWhale 贡献工作的第一道门槛是工具链。CONTRIBUTING.md 列出的前置条件为:

  • Rust 1.88 或更高版本(edition 2024)
  • Cargo 包管理器
  • Git

这一要求不是随意设定的。Cargo.toml 中可以看到工作区级别声明了 edition = "2024"rust-version = "1.88",并且注释说明了原因:Rust 1.88 稳定了 if/while 条件中的 let_chains,代码库大量依赖这一特性,通过 rust-version 字段让旧工具链的用户得到清晰的“package requires rustc 1.88+”报错,而不是难以理解的 E0658 错误。此外,rust-toolchain.toml 将工具链固定在 stable 通道。

环境搭建步骤:

# 1. Fork 仓库后克隆你自己的 fork
git clone https://gitcode.com/GitHub_Trending/de/Codewhale
cd CodeWhale

# 2. 构建项目
cargo build

# 3. 运行全部测试
cargo test --workspace --all-features

# 4. 以开发配置运行
cargo run --bin codewhale

注意第 4 步的 --bin codewhale:它指向的是 crates/cli 中的二进制(codewhale-cli crate 声明了 [[bin]] name = "codewhale",入口为 crates/cli/src/main.rs),即分发器门面(dispatcher facade),而不是 crates/tui 中的交互式 TUI 二进制 codewhale-tui。这一点在后文“工作区结构”一节还会展开。

代码风格与测试放置规范

代码风格

  • 提交前运行 cargo fmt 保证格式一致
  • 运行 cargo clippy 并处理所有警告
  • 遵循 Rust 命名约定(函数/变量用 snake_case,类型用 CamelCase)
  • 为公共 API 添加文档注释

工作区在 Cargo.toml 中用 [workspace.lints.rust]warnings = "deny" 固化了“CI 已通过 RUSTFLAGS: -Dwarnings 执行的策略”,成员 crate 通过 [lints] workspace = true 选择加入。也就是说,普通的 cargo check(不带额外参数)就与 CI 的警告门禁一致,这不是文档约定,而是写进 manifest 的机制。

测试放置

  • 为新功能编写测试
  • 确保既有测试全部通过:cargo test --workspace --all-features
  • 单元测试与被测代码同置(标准 Rust #[cfg(test)] 模块),集成测试放在所属 crate 的 tests/ 目录下(例如 crates/tui/tests/crates/state/tests/
  • 仓库根目录的 tests/ 目录不被使用

最后一条是明确的反模式警告:不要往仓库根放测试,每个 crate 自管自己的测试资产。

Push 前的验证门禁

这是贡献文档中最硬核的部分:每次 push 之前必须运行以下命令,它们与 CI 在 PR 上强制执行的内容一致——本地通过意味着 PR 的各验证通道(lane)也应当通过:

cargo fmt --all -- --check
cargo clippy --workspace --all-features --locked -- \
  -D warnings \
  -A clippy::uninlined_format_args \
  -A clippy::too_many_arguments \
  -A clippy::unnecessary_map_or \
  -A clippy::collapsible_if \
  -A clippy::assertions_on_constants
cargo test --workspace --all-features --locked

三条命令的含义:

  1. cargo fmt --all -- --check:只检查不重写,作为门禁时任何格式偏差都会导致失败。
  2. cargo clippy ... -D warnings:把所有警告提升为错误,但同时用 -A 放行五个既有噪音较多的 lint(uninlined_format_argstoo_many_argumentsunnecessary_map_orcollapsible_ifassertions_on_constants)——这个放行清单是 CI 的真实配置,照抄即可,无需自己猜测。
  3. cargo test --workspace --all-features --locked:全特性、锁定依赖图的全量测试,是权威(authoritative)测试门禁。

Release lane 的更严格 clippy

Release 通道运行更严格的 clippy:额外加 --all-targets,把 test、bench、example 目标也纳入 lint。文档特别提醒:只跑 --all-features 会漏掉一些在 release 通道才会失败的 lint,因此在请求 review 或做 release 相关工作之前,应使用这个更完整的形态:

cargo clippy --workspace --all-targets --all-features --locked -- \
  -D warnings \
  -A clippy::uninlined_format_args \
  -A clippy::too_many_arguments \
  -A clippy::unnecessary_map_or \
  -A clippy::collapsible_if \
  -A clippy::assertions_on_constants

这一点也被固化进了 PR 模板:.github/PULL_REQUEST_TEMPLATE.md 的 Testing 部分要求勾选 cargo fmt --all -- --checkcargo clippy --workspace --all-targets --all-features --locked(在 CI 放行清单下无警告)、cargo test --workspace --all-features --locked 三项,并在注释中指明“准确的门禁命令(含 clippy 放行清单)见 CONTRIBUTING.md 的 Pre-push verification”。Checklist 里还有一条值得注意:“Harvested/co-authored credit uses a GitHub numeric noreply address”——署名地址格式是模板级检查项,后文会解释为什么。

快速本地循环:dev-cargo / dev-test 脚本与 nextest

上面那套全量门禁是 CI 的标准,但不是每次编辑都需要它。文档给出的理由很直白:crates/tui 是一个约 75 万行的巨型 crate(当前对 crates/tui/src 的实测已经约 85.7 万行),保持循环速度的关键在于“不要不必要地重复构建它”。完整的数字与推理在 docs/BUILD_PERFORMANCE.md 中。推荐的快速循环:

# 1. 先做类型检查(首次构建后只需几秒;无 codegen、无链接)
scripts/dev-cargo.sh check -p codewhale-tui

# 2. 只跑改动附近的测试(一个 crate、一个 filter)
scripts/dev-test.sh tui fleet_setup
# 或者按源文件映射:
scripts/dev-test.sh crates/tui/src/elapsed.rs

# 3. 跑整个 crate 的单测套件。scripts/dev-test.sh 在已安装 nextest 时
#    会使用 nextest(每个测试一个进程、所有核心占满、慢测试点名;
#    约 100 秒 vs libtest 的约 270 秒)。
cargo install cargo-nextest --locked      # 只需一次
scripts/dev-test.sh tui
scripts/dev-cargo.sh nextest run --workspace --all-features --locked

# 4. Push 前,按 CI 的方式跑权威门禁:
cargo test --workspace --all-features --locked

dev-cargo.sh / dev-test.sh 到底做了什么

两个脚本都是 /bin/sh 实现,可以查看源码确认行为:

  • scripts/dev-cargo.sh 是“日常编译入口”。它 source 了 scripts/dev-cache.sh 应用可移植缓存拓扑(下文详述),并额外导出 RUST_MIN_STACK=16777216——注释说明这是为了匹配 CI 和产品端的 16 MiB 属主线程栈,避免本地 cargo test/nextest 在默认约 2 MiB(Windows 约 1 MiB)栈上直接 abort。
  • scripts/dev-test.sh 把“工作区区域或源文件路径”映射为最快的 cargo/nextest 调用。运行 scripts/dev-test.sh --list 可以看到完整的区域表:agentapp-servercliconfigcorestatetui 等每个区域对应一条 cargo test -p codewhale-<crate> --lib --lockedcrates/tui/src/ 下的子目录还会进一步映射到 tui::tools::core::commands:: 等过滤前缀,crates/tui/tests/integration/ 映射到 tui-integration 区域。当 cargo-nextest 在 PATH 上时,运行阶段自动换成 cargo nextest run(同二进制、每测试一进程);用 CODEWHALE_DEV_NEXTEST=0 可强制回退到 libtest。

nextest 配置与权威门禁的关系

.config/nextest.toml 已经处理了并行带来的竞争问题,因此对全工作区直接 cargo nextest run 是安全的。查看 .config/nextest.toml 可以看到关键配置:

  • slow-timeout = { period = "30s" }:超过 30 秒的测试被点名,贡献者能看到时间去向;
  • retries = 0fail-fast = false:flaky 测试被视为 bug 报告而不是要掩盖的东西;
  • 三个 test-group 用于约束会竞争外部资源的集成测试:spawns-binaries(拉起真实 codewhale 二进制、等待服务启动截止的测试,max-threads = 3)、telemetry-contract(遥测契约测试,max-threads = 1,因为其 fixture 的进程内互斥锁无法序列化 nextest 的每测试一进程 worker)、exec-persistent-service(等待真实子进程 pid 文件的测试,并行负载下文件迟迟不出现,max-threads = 1 串行执行,注释明确“串行它们;不要丢弃这些测试”)。

文档同时划清了边界:nextest 不运行 doctest,权威的 cargo test 门禁才运行;且测试不得依赖“与另一个测试在同一进程运行”这一假设(nextest 给每个测试独立进程);如果某个测试需要 rustls 加密 provider,应像生产启动时那样在该测试内自行安装。

低内存机器与交叉编译构建

在小于 16 GB 内存的机器上(或交叉编译,例如面向 OHOS),文档要求一次只跑一个 rustc:

  • 设置 CARGO_BUILD_JOBS=1(或 -j1
  • 一次只构建一个 crate
  • 测试用 --lib,绝不用 --workspace/--all-targets

文档给出的内存数字:tui 库自身的 rustc 需要约 6 GB,其单元测试构建约 8 GB;而 cargo test --workspace 会把两者同时调度——这正是社区成员在 Windows 上为 OHOS 交叉编译时报告的“两个各约 4 GB 的 rustc 进程”形态(RSS 统计因 OS 而异,但形态相同)。

docs/BUILD_PERFORMANCE.md 的 “Low-memory build recipe (machines with < 16 GB, cross-builds)” 一节给出了完整配方:

# 一次一个 rustc:tui lib 与其单元测试构建不再重叠
export CARGO_BUILD_JOBS=1            # 或: cargo build -j1 ...
# 只构建你正在工作的 crate,且只构建其库:
cargo build -p codewhale-tui
cargo test  -p codewhale-tui --lib -- <filter>
# 小机器上不要用 --workspace/--all-targets;一次一个 crate
# (scripts/dev-test.sh <area> 会挑选最窄的命令)
# 可选:如果 8 GB 的单元测试构建仍然太多(更慢):
export CARGO_PROFILE_DEV_CODEGEN_UNITS=4   # 峰值约 6 GB,墙钟时间约 +40%
# 交叉构建(如 OHOS)继承同样数字:给 cargo/ohrs 调用加 -j1,
# 构建 release profile——它不带测试模块,峰值低于单元测试构建

多 worktree 的构建缓存隔离

在多个 worktree 中工作时,不要默认共享同一个 CARGO_TARGET_DIR:两个 cargo 会在同一个 target 上 flock 并相互串行化。文档指出的解决方案是 scripts/dev-cargo.sh / scripts/dev-test.sh,它们让每个工作区拥有自己的 Cargo build-dir——位于 ${CODEWHALE_CACHE_ROOT:-${XDG_CACHE_HOME:-$HOME/.cache}/codewhale} 之下的 {workspace-path-hash} 子目录。

读取 scripts/dev-cache.sh 可以确认这套拓扑的完整语义:

  • 缓存根默认是 ${XDG_CACHE_HOME:-$HOME/.cache}/codewhale,可用 CODEWHALE_CACHE_ROOT 覆盖(没有机器专属默认值);
  • CODEWHALE_DEV_CACHE 控制模式:auto/1/force 走隔离 build-dir,local 保留 ./target0 什么都不做;CODEWHALE_DEV_CACHE=local 即文档所说的“想留在 ./target 时”的开关;
  • Cargo 1.91 之前回退到 per-workspace 的 CARGO_TARGET_DIR 指纹目录,1.91+ 使用 build.build-dir{workspace-path-hash} 模板;
  • sccache 仅在增量编译已关闭(CARGO_INCREMENTAL=0CODEWHALE_SCCACHE=1)且 sccache 在 PATH 上时才包装 rustc——“缺失的二进制是打印出来的回退,不是错误”;
  • 脚本还会检查缓存卷的剩余空间:冷构建 build-dir 约 6 GB,低于 15 GiB(阈值可用 CODEWHALE_DEV_CACHE_MIN_FREE_GIB 调整)会在构建开始前告警,而不是构建失败后才发现。

文档还给出一个例外:单一共享 CARGO_TARGET_DIR 仅对串行化的 trunk 工作有效。

平台绑定检查与本地 git hooks

有些检查是平台绑定的,或有意排除在普通变更之外。文档的建议是“按它们回答的风险来选择,而不是把每个可用套件都当作仪式”:

  • TUI 可见行为在真实终端中按受影响的尺寸与交互路径验收。原来的全屏 PTY 断言套件已被移除——它冻结了布局与文案,却遗漏了产品质量。
  • 长时间运行的进程验收应使用密封的本地 home、本地 fixture 和真实二进制;记录终端尺寸、输入、可见结果与任何文件系统副作用,而不是再加全屏 golden 文件。
  • OCRimage_ocr)使用 macOS Vision 框架或本地安装的 tesseract;其平台特定路径以 cfg(target_os = "macos") 门控并依赖宿主工具。
  • Seatbelt 沙箱测试仅在 macOS 运行(模块级 cfg(target_os = "macos"))。

本地 git hooks 是可选的

本仓库不安装 git hooks,也不存在 hook 安装器;CI 才是被强制的门禁。如果你想要一个运行上述命令的本地 pre-push hook(.git/hooks/pre-pushgit config core.hooksPath),可以自己加,但任何本地 hook 必须满足约束:

  • hook 绝不允许 push、打 tag、发布、部署、修改凭据或重写工作树(不允许自动修复提交或静默修改文件)。它只能验证与报告;
  • 为已知且书面记录的原因绕开自己的 hook(例如把进行中的工作推到自己的 fork 分支),用 git push --no-verify 并在 PR 描述中说明。绕开本地 hook 不等于门禁通过——CI 仍然会跑,且被绕开的门禁绝不能被报告为已通过;
  • 发布(tag、GitHub Releases、crates/npm 工件)是独立的、需要 owner 批准的门禁。本地 hook 或本地绿色运行都不授权任何发布步骤。

提交信息:Conventional Commits 与 AI 协作署名

提交信息使用 conventional commits,文档给出了完整的前缀表:

前缀 用途
feat: 新功能
fix: 缺陷修复
docs: 文档变更
refactor: 代码重构
test: 新增或更新测试
chore: 维护任务

示例:feat: add doctor subcommand for system diagnostics

文档对 AI 辅助提交持明确态度:AI 助手的 co-author trailer 是被允许的,使用助手是受欢迎的、无需披露,CI 也不再拒绝自动追加的 Co-authored-by: <some tool> 行。真正在意的是——做事的人类必须被署名,因为 Co-authored-by 会进入 GitHub 的贡献图谱。如果你想去掉自动追加的行,可以用交互式 rebase:

git rebase -i origin/main   # 逐条 reword,删除 Co-authored-by 行

给人 co-author 是自由的,但地址必须是对方的 GitHub 关联地址(id+login@users.noreply.github.com),否则署名不被记录。这个细节的动机在后文的 Harvest 流程中还会再次出现。

最后一条约定与 Harvest 机制直接挂钩:当某个提交从社区 PR 收割代码时(见下文),提交正文中应包含 Harvested from PR #N by @author 行——一个自动关闭工作流会监视这个模式,并带着署名关闭被引用的 PR,让贡献者得到“自己的工作已发货”的明确信号。

你的贡献如何落地:Direct Merge 与 Harvest 两条路径

CodeWhale 遵循一个“land what's useful, credit the contributor(落地有用的,署名贡献者)”的模型,它有时会出乎新贡献者的预期。落地有两条路径。

路径 1 — 直接合并

如果你的 PR 范围清晰、通过 CI、不触碰信任边界面(auth / sandbox / publishing / branding)、且与 main 无冲突,维护者会直接合并。这是小型缺陷修复和测试完善的功能新增最常见的结果。

路径 2 — Harvest(收割)

如果 PR 体积大、混合了范围、与 main 冲突、或需要“维护者自己打磨比与贡献者来回沟通更快”的润色,维护者可能把有用的 commit 或 hunk 收割main 上的新 commit,而不是直接合并 PR。这不是拒绝——它意味着你的代码落地了。

发生这件事时的契约:

  • 被收割 commit 的信息包含 Harvested from PR #N by @your-handle。这一行就是契约:它是你的署名,也是你的贡献已发货的信号;
  • 如果维护者复制或改写了你的代码,被收割 commit 在可能时保留原作者身份:要么在 cherry-pick 时保留 commit 作者,要么添加 Co-authored-by: Name <id+login@users.noreply.github.com> trailer。这是让 GitHub 的贡献界面识别“超出文字署名”的东西。文档同时告诫维护者:应使用 .github/AUTHOR_MAP(该文件在本仓库中存在,见 .github/AUTHOR_MAP),或运行 gh api users/<login> --jq '"\(.id)+\(.login)@users.noreply.github.com"',而不是从贡献者的机器上复制原始的、.local 的或旧式 noreply 邮箱——docs/AGENT_ETHOS.md 中同样强调“不要把 .local、占位符、bot/工具或原始第三方邮箱用于人类贡献者的署名”;
  • 下个 release 的 CHANGELOG.md 条目以 handle 署名你;
  • 自动关闭工作流会用模板化的感谢与指向 main 上 commit 的链接关闭你的 PR。

当维护者手工关闭一个被收割的 PR 时,关闭评论遵循固定模板(PR #2634 设定的模式):

Closing with harvest credit, @handle — <what landed> landed via
<commit sha(s) or PR #N>. <If work remains:> The remainder is tracked
in #NNN — follow-ups welcome there.
Thank you for <one specific thing the contribution got right>.

三个必需元素:贡献者的 handle、其工作落地的确切 commit 或 PR、以及(当 PR 包含比落地更多的内容时)剩余工作的跟踪 issue。被收割的 PR 永远不会被一个光秃秃的 “superseded” 关闭。

让下一次贡献走 Direct-Merge 路径

想让未来的贡献走更快的直接合并路径,杠杆最高的四件事:

  1. PR 保持单一目的。 每个 PR 一个缺陷修复;一个功能一个 PR。不要把重构和功能混在一起。
  2. 开 PR 前、CI 反馈后都 rebase 到当前 main 冲突会把即使很小的变更也逼进 harvest 路径。
  3. 为新行为附测试。 维护者经常收割没有测试的 PR,因为自己加测试比向贡献者索要更快。
  4. 没有事先维护者签核,避开信任边界面。 这包括 auth/凭据流程、沙箱策略、发布/release 管道,以及 prompts/ 内容。未经事先讨论就触碰这些的 PR,即使实现良好,也不太可能被直接合并。

分层与 EPIC 规模的工作流

有些架构工作对单个 PR 来说太大,但仍需按依赖层级构建。针对这类变更的工作流:

  1. 当工作横跨多个 PR 时,从跟踪 issue 或 EPIC 开始。命名计划中的切片,并说明每个切片暂时不打算关闭什么。
  2. 每个实现 PR 只聚焦一个行为边界。
  3. 下层仍在移动时,后续层可以留在你的 fork 或开成 draft PR。栈式 PR 的标题或描述应写明 Draft / depends on #NNNN
  4. 下层落地、分支 rebase 到当前 main、且 PR 以 main 为目标之前,依赖型 PR 不具备合并评审条件。
  5. PR 正文应说明:它建立在哪个更早的 PR 上、范围内有什么、明确排除什么、引用哪些 issue、运行了哪些本地命令。
  6. 仅当切片完全满足某个 issue 时才用 Closes #...;PR 推进了一个宽泛 issue 但留有后续工作时,用 Refs #... 并附简短的 (partial) 说明。
  7. 评审期间使用结构化 commit 没问题。维护者可能在合并时 squash 或 harvest,贡献者署名通过作者身份、co-author trailer、changelog 条目或 PR/issue 评论保留。当合并 commit 本身携带 Harvested from PR #N by @author 行时,该 PR 会以 rebase 或 merge commit 而非 squash 合并,使该行完整到达 main 并触发自动关闭署名。

请求合并评审前,分层 PR 应满足:

  • 已 rebase 到当前 main
  • 标记为 ready for review 而非 draft
  • 聚焦一个行为边界
  • PR 正文中有本地命令证据
  • CI 绿色,或剩余红色通道有清晰解释
  • 若变更了配置或 schema 行为,有往返(round-trip)或迁移保留测试覆盖
  • 除非真正关闭,否则把宽泛 issue 标记为 partial

对分层工作,有用的 PR 描述形状:

Summary:
Scope:
Not in this slice:
Builds on:
Issues:
Validation:

Stewardship 分支

大型重构与架构工作在到达 main 之前先暂存于 codex/v0.9.0-stewardship 分支。该分支存在的意义:让多层系列(如命令组重构)可以针对稳定基础逐层落地、用其 parity harness 验证,然后通过周期性的 stewardship 合并流入 main——而不是让每一层去追 main 的日常变更。

对贡献者意味着:

  • 分层/EPIC 规模的重构 PR 应以 codex/v0.9.0-stewardship 为基础并指向该分支(可参考 #2888 的模型)。普通缺陷修复和功能仍指向 main
  • 维护者周期性地把 stewardship 分支合并进 main;你的工作带着完整历史与署名到达 main
  • 不确定用哪个基础时,在跟踪 issue 中询问——凡是多 PR 系列以外的一切,默认都是 main

贡献门禁与 Agent 辅助改进

贡献门禁

CodeWhale 对社区前门使用维护者管理的贡献门禁;维护者与协作者自动绕过。门禁工作流默认 dry-run / 仅评论模式,让维护者先观察信号再改变贡献者流程。维护者姿态记录在 docs/AGENT_ETHOS.md:自动化应当降低负担,同时让善意贡献者被看见、被署名、能够继续帮忙。

Issue 永远不会被贡献门禁自动关闭。未批准的外部 issue 会收到一条要求补充复现细节的简短欢迎语,然后保持开放等待维护者分诊——CodeWhale 依赖真实用户的真实边缘情况,issue 入口应保持温暖开放。

PR 不同,因为它们可能触碰代码、CI、发布管道、auth、沙箱、provider 策略等信任边界面。PR 门禁可以在维护者认为需要这种安全控制时从 dry-run 切换为强制执行,但应把它当作评审负载控制,而非对贡献者质量的评判。在启用 PR 强制执行之前,应把 allowlist 播种得足够宽,覆盖不应被这次上线打扰的活跃外部贡献者。

Allowlist 的作用域:

  • pr:username 允许 pull request
  • issue:username 允许 issue
  • all:username 两者都允许

维护者可以在 PR 上评论 /lgtm 授予 PR 访问,或在 issue 上评论 /lgtmi 授予 issue 访问。裸命令 lgtmlgtmi 出于兼容性也被接受,但带前缀的形态更受推荐——在普通评审讨论中更难被误触发。

批准不直接编辑 main:批准工作流会开一个小的 allowlist 更新 PR,使新条目在生效前可被评审。如果 PR 门禁误伤了优秀贡献者,走同样的批准流程恢复:评论 /lgtm、合并生成的 allowlist PR、再重新打开受影响的 PR;如果 GitHub 不允许重新打开已关闭的 PR,则在 allowlist PR 合并后请贡献者重新提交。

Agent 辅助改进

CodeWhale 允许自己帮助改进自己,但贡献仍必须被塑造成适合人类评审的形态。推荐的工作流来自私有 codewhale-ops 仓库中的递归自我改进提示:从全新的 fork 或分支运行它,让 agent 只找到一个小的摩擦点,一个补丁之后停止。DeepSeek V4 Pro 是当前这个循环的参考路径,但任何已配置的 provider 都可以——评审形态比 provider 更重要。

agent 与维护者都应遵循 docs/AGENT_ETHOS.md 中的 stewardship 姿态:用自动化产出证据、验证和窄补丁,最终社区决策保留给人类评审。有用的产出不是“改进想法”,而是:具体的复现、最小的 diff、聚焦的检查、以及解释权衡的 PR 描述。未经事先维护者签核,不要用 agent 触碰 auth、凭据、沙箱策略、发布/release 管道、provider 策略、遥测、赞助、品牌或全局 prompt。

工作区结构:你的改动落在哪里

CodeWhale 是一个 Cargo workspace。文档说明当前的运行主体与大部分 TUI、引擎、工具代码位于 crates/tui/src/,较小的工作区 crate 提供正在被逐步抽取出来的共享抽象。文档给出的结构表:

crates/
├── tui/           codewhale-tui 二进制(交互式 TUI + 运行时 API)
├── cli/           codewhale 二进制(分发器门面)
├── app-server/    HTTP/SSE + JSON-RPC 传输
├── core/          Agent 循环 / 会话 / 轮次管理
├── protocol/      请求/响应分帧
├── config/        配置加载、profile、环境变量优先级
├── state/        SQLite 线程/会话持久化
├── tools/        类型化工具规格与生命周期
├── mcp/          MCP 客户端 + stdio 服务器
├── hooks/        生命周期 hooks(stdout/jsonl/webhook)
├── execpolicy/   审批/沙箱策略引擎
├── agent/        模型/provider 注册表

对照当前 Cargo.toml 的 workspace members 可以看到,工作区实际还包含 build-supportcommand-contractlanepathsreleasesecretstelemetryworkflowworkflow-js 等 crate——scripts/dev-test.sh --list 的区域表与之一一对应,新增 crate 后脚本区域表就是判断“我的改动该跑哪条最窄测试命令”的可靠索引。文档进一步指向 docs/ARCHITECTURE.md 了解这些 crate 之间的活数据流,包括自底向上的构建顺序。

default-members = ["crates/cli"] 这一配置解释了为什么裸 cargo build 只构建 cli 侧、以及 cargo run --bin codewhale 跑起来的是分发器而不是 TUI。

典型的 PR 形态

结构良好的 PR 遵循一致的形态。文档列举了近期的范例:

  • #386/init 命令:新的 crates/tui/src/commands/groups/project/init.rs 模块、项目类型检测、AGENTS.md 生成、commands/mod.rs 中的命令注册、本地化字符串;
  • #389 — 内联 LSP 诊断:crates/tui/src/lsp/ 中的 LSP 子系统、crates/tui/src/core/engine/lsp_hooks.rs 的引擎钩子、配置开关、测试覆盖;
  • #387 — 自更新:新的 crates/cli/src/update.rs 模块、CLI 子命令注册、HTTP 下载 + SHA256 校验 + 原子二进制替换;
  • #393/share 会话 URL:新的 crates/tui/src/commands/groups/project/share.rs、HTML 渲染、gh gist create 集成、命令注册;
  • #343/#346 — (v0.8.5)运行时线程/轮次时间线与持久任务管理器重构。

这些路径均可在当前仓库中直接查看:crates/tui/src/commands/groups/project/ 下确实存在 init.rsshare.rscrates/tui/src/lsp/ 目录包含 client.rsdiagnostics.rsregistry.rscrates/cli/src/update.rs 也在列。典型规模:每个 PR 触及 1–3 个新文件,修改 2–5 个既有文件做接线(注册表、dispatch 匹配、本地化),并新增或更新测试。变更被限制在单个功能或修复内——如果你发现相关的、需要额外做的工作,开一个单独的 issue,而不是扩大 PR 范围。提交前,运行“Push 前的验证门禁”一节的命令。

提交变更、Issue 与安全披露

提交变更的标准流程

  1. main 创建功能分支:git checkout -b feat/your-feature
  2. 做出修改并提交
  3. 运行 push 前验证命令(见上文门禁一节,含更严格的 release clippy 形态)
  4. 推送分支并创建 Pull Request
  5. 在 PR 描述中清晰描述变更

PR 指南

  • 开 PR 时使用 .github/PULL_REQUEST_TEMPLATE.md 模板——它包含评审者预期的 Summary、Testing 与 Checklist 部分
  • PR 聚焦单一变更
  • 需要时更新文档
  • 为新功能添加测试
  • 请求评审前确保 CI 通过

报告 Issue

报告 issue 时使用模板:

Issue 报告应包含:操作系统与版本、Rust 版本(rustc --version)、codewhale 版本(codewhale --version)、复现步骤、预期与实际行为、相关错误信息或日志。

安全

如果发现安全漏洞,不要开公开 issue。见 SECURITY.md:鉴于 codewhale 是拥有文件操作、shell 执行与网络访问权限的编码 agent,漏洞需通过 GitHub 私有 advisory 或带 [SECURITY] 主题前缀的邮件私下报告;且只有最新稳定版接收安全补丁,旧版本不回填。

行为准则与许可证

保持尊重与包容,欢迎所有背景和经验水平的贡献者,完整条款见 CODE_OF_CONDUCT.md。按照 LICENSE 的 MIT 许可,向 codewhale 提交贡献即表示同意你的贡献以 MIT 许可发布。

关于贡献的疑问,随时开一个 issue 讨论即可。

登录后查看全文
热门项目推荐
相关项目推荐