Apache Maka 贡献指南:从 Issue 认领、本地构建到 PR 审查的完整工作流
2026/9/17 22:54:31 网站建设 项目流程

Apache Maka 贡献指南:从 Issue 认领、本地构建到 PR 审查的完整工作流

【免费下载链接】makaApache Maka (Incubating) is a high-performance agent workspace that keeps a complete record of everything it did.项目地址: https://gitcode.com/GitHub_Trending/mak/maka

Apache Maka(Incubating)是一个基于事件溯源(event sourcing)的 Agent 工作区,代码组织为 npm workspaces 多包仓库。本文基于官方贡献文档 CONTRIBUTING.zh-CN.md 整理,完整覆盖“找活干 → 环境搭建 → 本地构建与测试 → 推送前对齐 CI → 提 PR”的全链路,并结合.asf.yaml、pre-commit 钩子与 CI 工作流等仓库内实现细节,解释每条规则背后的机制,帮助你在提交第一个补丁前先理解这个仓库的质量门禁。

从哪里开始:任务来源与认领约定

贡献文档明确列出了最容易被合并的贡献类型:缺陷修复、模型供应商支持、测试、性能优化和文档。官方建议从 issue 的help wantedgood first issuebugenhancement标签中挑选任务,并留言认领。提 issue 使用Bug reportFeature request模板(仓库内对应 bug_report.yml 和 feature_request.yml);安全问题必须走 SECURITY.md 的私密流程,不要开公开 issue;提问、想法和不成熟的提案则发到 Discussions——它会自动同步到邮件列表,比 issue 更容易被看到。

两个容易踩坑的细节:

  1. 认领协议只认两个单词:若要自助认领一个尚未分配的 issue,评论正文必须只能是take这一个单词;评论untake解除自己的认领。其他任何认领文字都不会触发该工作流。仓库中对应的自动化实现是 take.yml。
  2. 决策分层:项目方向、治理和重大产品决策在实施前于开发邮件列表dev@maka.apache.org上公开讨论;实现层面的技术决策可以直接在 PR 中讨论。

人类责任与 AI 归因

这份贡献文档有一个显著特点:它显式定义了 Agent 参与贡献时的责任边界,这在 Apache 孵化项目中比较少见。

  • 每项贡献都有一名 human contributor of record:由人负责审阅、决定提交,并对准确性、来源和许可负责。Agent 可以自由 commit 和 push,但最终的审查与合并决定始终由人做出。
  • 每个 PR 必须声明生成式工具是否有实质贡献:有则注明工具名称。翻译、措辞整理、自动补全和拼写修正不算实质贡献。自动发送的消息必须表明身份。
  • Generated-bytrailer:AI 创作了贡献中的实质部分时,需要在每个受影响的 commit 上加Generated-by: <tool>trailer,并确保它在 squash 或 amend 后保留于最终 commit。AI 生成的实质内容遵循 ASF 生成式工具指南。

这一约定在 pull_request_template.md 中有落地:模板的 “## AI use” 小节要求二选一勾选(“No generative tool made a substantive contribution” 或 “Generative tooling made a substantive contribution”),并在选中后者时要求列出工具名称和作用范围,附注“给受影响的 commit 加 Generated-by trailer,并保证最终 squash commit 保留该 trailer”。

审查机制:一位独立 committer + 必过的 test 检查

main提的每个 PR 需要满足两个条件才能合并:一位作者之外的 committer 给出 approval,且必需的test检查通过。这套机制由 .asf.yaml 的protected_branches声明式强制执行:

protected_branches: main: required_pull_request_reviews: dismiss_stale_reviews: false required_approving_review_count: 1 required_status_checks: strict: false contexts: - test

这里的配置有几个值得注意的设计,文件中的注释解释得很清楚:

  • dismiss_stale_reviews: false:GitHub 在收到新 commit 时会丢弃旧 approval,但不会丢弃“请求修改”。如果开启 stale 丢弃,rebase 一次就要重新走一整轮 approval,而未解决的反对意见却原样存活——两半审查以不同速率衰减,代价不对称。
  • test是 CI 中唯一的无条件 job:ci.yml 把计划(planning)和验证放在同一个 job 里,文档类改动只付一次 runner 配额。注释特别警告:改名为其他名字、给 ci.yml 加 paths filter、或把工作拆回多个 job 让必需检查来自可被跳过的聚合器,都会让必需上下文在部分 PR 上永远不报告,从而冻结所有合并。
  • 分支按钮只留 squashenabled_merge_buttons中仅squash: true,且del_branch_on_merge: true。这也解释了为什么 PR 标题会成为落到main上的提交信息(见后文)。
  • 审查必须出自独立的人工判断:贡献文档明确写了“AI review 不算”。一个改动是否重大、获得的审查是否足够,由维护者认定。

另外,.asf.yaml还通过 rulesets 禁止删除或 force pushv*发布标签,并声明了releasenpm-publicationnightlyproduct-release等受保护环境作为签名密钥与 npm OIDC 的部署边界——这些不是贡献者日常接触的部分,但解释了发布流程为什么需要环境级人工复核。

环境要求

快速开始一节给出的硬性版本约束,与根 package.json 中的声明一致:

  • Node>=22.19.0(对应engines.node);
  • npm11.19.0(对应packageManager: "npm@11.19.0");
  • 若要开发Desktop Direct PeerPeer Mesh功能,还需要 Rust stable1.98或更高版本,以及 macOS 的 Xcode Command Line Tools 或 Windows 的 MSVC Build Tools。仓库内 gitoxide-helper 的 rust-toolchain.toml 固定channel = "1.98.0",而 runtime-host-peer 的 rust-toolchain.toml 使用stable,与文档描述吻合。

仓库共声明了 11 个 workspace(@maka/core@maka/storage@maka/mcp@maka/runtime@maka/runtime-host@maka/eval@maka/computer-usemaka-agent(CLI 包)、@maka/ui@maka/desktop@maka/website),架构总览见 ARCHITECTURE.zh-CN.md,Eval 的命令与 contract 见 packages/eval 目录下的文档。

构建与测试:为什么测试跑的是 dist

初始化与构建命令(注意注释:npm install 只在根目录跑,不要在某个 workspace 里跑):

git clone https://github.com/apache/maka.git cd maka npm install # 只在根目录装 —— 不要在某个 workspace 里跑 npm run build # 按依赖顺序构建全部 workspace npm --workspace @maka/core run test:dist

这里有两个机制值得展开:

1.npm run build是按依赖顺序串起来的。package.jsonbuild脚本的真实内容是一整条链:

core → storage → mcp → runtime → runtime-host → computer-use → eval → maka-agent → ui → desktop

因此“只有依赖都已构建好时,单独构建某个 workspace 才会成功——拿不准就从根目录构建”。链上任何一个 workspace 缺dist/,下游的 TypeScript 编译就会失败。

2. 测试跑的是编译产物,不是源码。每个 workspace 的test:dist脚本执行的是node --test作用于dist/**/*.test.js(例如 packages/cli/package.json 中"test:dist": "node --test \"dist/**/*.test.js\"",apps/desktop/package.json 中则针对dist/main/**/*.test.js加上若干脚本级测试)。也就是说test:dist覆盖的是最近一次构建的结果——如果你改了源码没重新构建,跑测试得到的结论是过期的。根目录的npm test会把两步都做掉:

# package.json 中: "test": "npm run build:test && node scripts/run-workspace-tests-parallel.mjs --concurrency=3", "build:test": "npm run clean && ... 各 workspace 依序 build ..."

build:test会先执行clean——由 clean-build.mjs 移除所有 workspace 的dist/和增量 tsbuildinfo。脚本头部的注释直言这是为了解决反复出现的 “tests pass on stale dist”(测试跑在陈旧的 dist 上)陷阱:“每次移除/重命名一个 export,旧 dist 都会存活,测试就会说谎。”

多 workspace 的并行调度由 run-workspace-tests-parallel.mjs 负责,其行为(来自脚本 JSDoc 与常量定义)包括:

  • --concurrency N限制并发,避免压垮小型 runner;--workspaces a,b只跑选定的 workspace;
  • 以每个 workspace 测试源码的字节数作为权重,最重的套件优先入队,防止短队列先抽干并发槽位;
  • 每个 workspace 默认15 分钟超时DEFAULT_WORKSPACE_TIMEOUT_MS = 15 * 60_000);
  • workspace 自己通过package.jsontest:dist决定如何跑测试,脚本只负责调度、进程驻留上限、失败报告和临时目录命名空间。

日常开发命令:

npm run dev # 带 HMR 的桌面应用 npm run cli:dev # TUI;`npm run cli:dev -- run "…"` 非交互地跑一个 Turn npm test # 全部 workspace,或:npm --workspace @maka/core run test:dist

从根package.json看,dev实际执行@maka/desktopdev:hmr(即node scripts/dev.mjs),cli:dev执行node packages/cli/dist/dev-cli.js;涉及 Peer 的变体是npm run dev:peer(会先触发prepare:runtime-host-peer构建 Rust 原生模块)。

推送前本地对齐 CI

贡献文档给出的推送前检查清单,逐条对应仓库里的真实实现:

npm run lint # biome lint . npm run format:check # biome format . npm run build # 全部 workspace 依序构建 npm run typecheck # npm run typecheck --workspaces --if-present npx knip --workspace apps/desktop # 未使用依赖/导出检查 npx knip --workspace packages/ui

其中lintformat:checktypecheck都是根package.json的脚本,分别对应biome lint .biome format .和跨 workspace 的tsc检查;knip 的两个 workspace 参数与 knip.json 中声明的apps/desktoppackages/ui两份 entry/project 配置一一对应——knip 只在这两个 workspace 做了完整入口声明,所以 CI 也只检查这两个。

除了手动跑,这些检查还有提交时的自动化版本:根package.jsonprepare脚本会执行 install-husky.mjs 安装 Git 钩子,而 .husky/pre-commit 钩子在每次 commit 时运行四项检查:

node scripts/biome-staged-check.mjs # 仅对 staged 文件跑 biome node scripts/asf-license-headers.mjs check-staged # 检查 Apache 许可头 node scripts/protocol-epoch-check.mjs --staged # Runtime Host 兼容 epoch 守卫 git diff --cached --check # 空白错误等

其中 protocol-epoch-check.mjs 的头部注释解释了它防的是一个真实 bug 类别:两个分支各自升级 Runtime Host 兼容 epoch 时写的是同一行同一段文本,git 三方合并不会报冲突,结果就是两个不兼容的协议宣称同一个 epoch。该检查在 PR 合并结果上与第一个父提交(base 分支)对比,不兼容的变更必须移动 epoch;pre-commit 的--staged模式只能对 HEAD 判断,最终裁决权在合并结果上。

提出 Pull Request

  • 模板必须在此基础上填写,不要整段替换。开 PR 时 GitHub 会自动填充 pull_request_template.md,包含Summary(含Fixes #N/Refs #N指引)、Verification(实际运行过的检查及其结果,未运行的相关检查要点名;用户可见的改动要附最轻量的证据:截图、录屏或命令输出)、AI use(二选一并注明工具与作用范围)和Checklist(测试覆盖该变更且无它时会失败;lint/format/typecheck/受影响套件本地通过;是否改变行为)。模板还提示:只有当 PR 改变审查、发布或运维方式时才加额外小节,并按真实风险命名(如 Breaking change、Rollout、Root cause)。
  • 命名遵循 Conventional Commits:分支名<type>/<描述>,PR 标题<type>(<scope>): <summary>。由于本仓库只允许 squash 合并(.asf.yaml中 merge/rebase 按钮均为 false),PR 标题就是落到main上的提交信息;仓库的git log里可以看到实际在用的 type 和 scope 集合。
  • 界面改动附截图或录屏:改前改后都要有。
  • 描述写短,用你自己的话——文档的原话是:如果需要很多段落,多半是这个 PR 太大了。

来源与许可的底线

贡献文档最后一条原则:只提交你有权贡献的内容,记录第三方来源、许可和必要署名;贡献以 Apache License 2.0 授权。仓库把这条原则也做成了可执行检查:根package.json提供check:asf-headers(由 asf-license-headers.mjs 实现,同时被 pre-commit 钩子以check-staged模式调用)、generate:third-party-notices/check:third-party-noticescheck:release等脚本,分别覆盖许可头、第三方声明和发布产物审计。如果你要引入新的第三方依赖,这些check:*脚本就是判断改动是否“完整”的现成标准。

小结

环节关键规则仓库内依据
找活干认领评论只能是take/untaketake.yml
AI 归因声明工具 +Generated-bytrailer 保留到最终 commitpull_request_template.md
合并门禁1 个外部 approval +test检查,squash-only.asf.yaml、ci.yml
环境Node ≥22.19.0,npm 11.19.0,Peer 需 Rust ≥1.98package.json
测试dist/产物;npm test= clean + build + 并行 test:distrun-workspace-tests-parallel.mjs
提交时biome staged、ASF 许可头、epoch 守卫、diff --check.husky/pre-commit
推送前lint / format:check / build / typecheck / knip(desktop、ui)根 package.json、knip.json

按这份流程走完一遍,你就具备了在这个仓库上提第一个可合并 PR 的全部知识:任务从带标签的 issue 来,环境在根目录一次性装好,构建与测试永远从dist/出发,推送前用四条命令加两次 knip 对齐 CI,PR 标题即最终提交信息。

【免费下载链接】makaApache Maka (Incubating) is a high-performance agent workspace that keeps a complete record of everything it did.项目地址: https://gitcode.com/GitHub_Trending/mak/maka

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询