-
Notifications
You must be signed in to change notification settings - Fork 4
docs: 贡献规范落地 —— CONTRIBUTING + Docs Gate 门禁 + PR 模板(Refs #137) #138
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
johnnyzhang-eng
wants to merge
1
commit into
1024XEngineer:main
from
johnnyzhang-eng:docs/contributing-and-docs-gate
Closed
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| --- | ||
| name: windup-contrib | ||
| description: Windup 仓库的贡献规范(分支/commit/PR/Issue/文档去向)。在准备提 PR、建分支、写 commit、往仓库新增或修改 md 文件、要写设计或架构文档、要决定"这份文档该进仓还是进 Issue"时加载。规范全文在仓库根目录 CONTRIBUTING.md,本文件只是索引。 | ||
| --- | ||
|
|
||
| # Windup 贡献规范(索引) | ||
|
|
||
| **规范全文见仓库根目录 `CONTRIBUTING.md`。现在就去读它,本文件不含规则。** | ||
|
|
||
| 规范放在 `CONTRIBUTING.md` 而不是这里,是因为它要给全体贡献者看——不用 Claude Code 的人、GitHub 网页上开 PR 的人也得能读到。本 skill 的唯一作用是让 Claude 在该加载规范的时刻自动指过去。 | ||
|
|
||
| ## 读之前先知道三件事 | ||
|
|
||
| 1. **规则分三层**:CI 自动拦的 / 只能靠自觉的 / 需要人判断的。**第三层不要代答**,把问题列给人。 | ||
| 2. **最容易违反的是 `CONTRIBUTING.md` 的 2.1「工程文档不入仓」**。往仓库加任何 `.md` 之前先读那一节。默认是**不入仓**。 | ||
| 3. **不假报通过**:说"跑通了"必须说清跑了什么,没跑就写"未跑 + 原因"。 | ||
|
|
||
| ## 配套 | ||
|
|
||
| - 执行器是个人 skill `windup-preflight`——它跑机械检查、列可预测追问,规则引用 `CONTRIBUTING.md` 而不复述。 | ||
| - 冲突时以 `CONTRIBUTING.md` 为准;它与营规范原文或评审者当场意见冲突时以后者为准,并回写 `CONTRIBUTING.md`。 |
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| <!-- 完整规范见仓库根目录 CONTRIBUTING.md。下面每项后括号里的 §N 指向那份文档的对应小节。 --> | ||
|
|
||
| ## 变更内容 | ||
| <!-- 做了什么。一两句说清,别复述 diff --> | ||
|
|
||
|
|
||
| ## 关联 | ||
| Refs # | ||
| <!-- stack 在未合并 PR 之上的,写明:本分支 stack 在 #NN 之上,合并后会 rebase(§2.3) --> | ||
|
|
||
|
|
||
| ## 为什么这么做 | ||
| <!-- 关键决策带「备选方案 + 选择 + 理由」;只写结论会被追问 --> | ||
|
|
||
|
|
||
| ## 本地验证 | ||
| <!-- 如实写跑了什么、结果如何。"跑通"要说清跑了哪些;没跑的写「未跑 + 原因」,不要假报通过(§2.7) --> | ||
|
|
||
| 后端: | ||
| - [ ] `uv run ruff check .` | ||
| - [ ] `uv run lint-imports` | ||
| - [ ] `uv run pytest -q` → N passed | ||
|
|
||
| 前端: | ||
| - [ ] `npm run lint` / `typecheck` / `test` / `build` | ||
|
|
||
|
|
||
| ## 自检 | ||
|
|
||
| - [ ] 从自己 fork 提交,未在主仓建分支(§2.2) | ||
| - [ ] 已 rebase,不落后主线(§2.3) | ||
| - [ ] 改动范围与关联 Issue 一致,未夹带(§2.4) | ||
| - [ ] **本 PR 新增/修改的 `.md` 都不是工程文档**(§2.1)——设计、架构决策、模块拆分、接口设计说明、AI 生成的 plan/spec 一律进 Issue。确实是用户文档的,打 `user-doc` label | ||
| - [ ] 无 PII:正文、diff、截图、日志路径里没有真实姓名 / 雇主 / 地理位置(§2.5) | ||
| - [ ] 工程卫生:无框架默认图标 / 未引用资源,新增依赖分类正确 | ||
| - [ ] 动了 `pyproject.toml` / `package.json` 的,lock 已同步 | ||
|
|
||
| ### 若改了数据模型 / 契约 | ||
| - [ ] 每个新字段能自证存在必要性(能由别处推导的已删) | ||
| - [ ] **带单位的字段写明了单位和符号约定**(跨端各写一套会静默出错) | ||
| - [ ] 枚举取值宽度跨层一致;同一实体的 ID 类型跨端统一 | ||
| - [ ] 机制固定在正确的抽象层级;命名已落到代码字段名 | ||
| - [ ] 未对齐点已显式记录——**结论写进代码旁的 README/MODULES.md(一两行 + Issue 链接),论证过程进 Issue**(§2.1 边界情况) | ||
|
|
||
| ### 若是修复 | ||
| - [ ] 写清旧行为为什么错、新行为为什么对 | ||
| - [ ] 补了**能复现原 bug** 的回归测试——最好用旧实现做过控制样本,确认它在修复前真的会红 | ||
| - [ ] 已检查同类问题是否存在于其它分支 / 模块;存在则单独开 Issue,不在本 PR 扩范围 | ||
|
|
||
| ### 若回复了机器审 | ||
| - [ ] 每条都用修复的 commit hash 闭环;不认同的写明理由,没有沉默跳过(§2.7) | ||
|
|
||
|
|
||
| ## 待对齐 / 已知未决 | ||
| <!-- 跨端契约缺口、口径未定的点。有就在这列,并说明是否已开对齐 Issue、对接人是谁 --> |
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 这个没有必要吧; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,142 @@ | ||
| name: Docs Gate | ||
|
|
||
| # 工程文档不入仓:设计/架构决策类文档写进 Issue(靠 Issue 描述区编辑历史做版本管理), | ||
| # 不 commit 成仓库里的 md。本门禁只拦最明确的两类位置,其余一律放行—— | ||
| # 设计原则是「宁可漏拦,不可误拦」,误伤别人正常工作的门禁会被直接关掉。 | ||
| # | ||
| # 拦什么: | ||
| # - docs/** 下新增或修改的 md | ||
| # - 仓库根目录新增的 md | ||
| # 不拦什么(故意的): | ||
| # - 删除文件(把文档搬走正是我们想要的) | ||
| # - 子目录里的 md(frontend/**、backend/** 的 README / MODULES.md 等,团队约定要留在代码旁) | ||
| # - 允许清单里的路径(见下方 ALLOW 逻辑) | ||
| # - 打了豁免 label 的 PR | ||
| # | ||
| # 规范全文:CONTRIBUTING.md 第 2.1 节 | ||
|
|
||
| on: | ||
| pull_request: | ||
| # labeled / unlabeled 也触发,这样加完豁免 label 无需手动 re-run | ||
| types: [opened, synchronize, reopened, labeled, unlabeled] | ||
| paths: | ||
| - 'docs/**' | ||
| - '*.md' | ||
|
|
||
| concurrency: | ||
| group: docs-gate-${{ github.ref }} | ||
| cancel-in-progress: true | ||
|
|
||
| permissions: | ||
| contents: read | ||
|
|
||
| jobs: | ||
| check-docs: | ||
| name: Engineering docs stay in Issues | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v7 | ||
| with: | ||
| fetch-depth: 0 # 需要完整历史来算 merge-base | ||
|
|
||
| - name: Check for engineering docs committed to the repo | ||
| env: | ||
| # 用 env 传参,避免 ${{ }} 直接插值进 shell 造成命令注入 | ||
| BASE_REF: ${{ github.base_ref }} | ||
| # PR 当前的 label 列表(JSON 数组) | ||
| PR_LABELS: ${{ toJSON(github.event.pull_request.labels.*.name) }} | ||
| run: | | ||
| set -euo pipefail | ||
|
|
||
| # ── 0. label 豁免 ────────────────────────────────────── | ||
| # 确实该入仓的用户文档,打上这个 label 即放行。 | ||
| # 只认 user-doc,不认 Documented——后者是打在 Issue 上的生命周期状态 | ||
| # (用户文档已提供),不是 PR 属性,借来当门禁开关会把两套语义搅在一起。 | ||
| EXEMPT_LABELS='user-doc' | ||
| for lbl in $EXEMPT_LABELS; do | ||
| if printf '%s' "$PR_LABELS" | jq -e --arg l "$lbl" 'index($l) != null' >/dev/null 2>&1; then | ||
| echo "豁免:PR 带 label '$lbl',跳过检查。" | ||
| exit 0 | ||
| fi | ||
| done | ||
|
|
||
| # ── 1. 取出本 PR 的改动清单 ──────────────────────────── | ||
| git fetch --no-tags origin "$BASE_REF" | ||
| BASE=$(git merge-base "origin/$BASE_REF" HEAD) | ||
| echo "检查范围: $BASE..HEAD" | ||
| echo "" | ||
|
|
||
| flagged="" | ||
|
|
||
| while IFS=$'\t' read -r status path rest; do | ||
| [ -n "${path:-}" ] || continue | ||
| # 重命名/复制的记录是 R100<TAB>旧路径<TAB>新路径,取新路径 | ||
| case "$status" in | ||
| R*|C*) path="${rest:-$path}"; status="A" ;; | ||
| esac | ||
| # 删除永远放行:把文档搬去 Issue 正是我们想要的动作 | ||
| case "$status" in | ||
| D*) continue ;; | ||
| esac | ||
|
|
||
| # ── 2. 允许清单 ───────────────────────────────────── | ||
| case "$path" in | ||
| README.md|CONTRIBUTING.md|CHANGELOG.md|LICENSE|LICENSE.md|SECURITY.md|CODE_OF_CONDUCT.md) | ||
| echo "allow(仓库元文件): $path"; continue ;; | ||
| .github/*|.github/**) | ||
| echo "allow(CI 与仓库模板): $path"; continue ;; | ||
| .claude/*|.claude/**) | ||
| echo "allow(agent 工具配置): $path"; continue ;; | ||
| docs/user/*|docs/user/**|docs/guide/*|docs/guide/**|docs/usage/*|docs/usage/**) | ||
| echo "allow(用户文档目录): $path"; continue ;; | ||
| esac | ||
|
|
||
| # ── 3. 判定 ───────────────────────────────────────── | ||
| case "$path" in | ||
| docs/*) | ||
| # docs/ 下新增或修改都拦 | ||
| flagged="${flagged} - ${path} (${status})"$'\n' | ||
| continue ;; | ||
| */*) | ||
| # 子目录里的 md 不拦(README / MODULES.md 等按团队约定留在代码旁) | ||
| continue ;; | ||
| *.md) | ||
| # 根目录:只拦新增,已有的存量文件修改放行 | ||
| if [ "$status" = "A" ]; then | ||
| flagged="${flagged} - ${path} (新增于仓库根目录)"$'\n' | ||
| fi | ||
| continue ;; | ||
| esac | ||
| done < <(git diff --name-status "$BASE" HEAD) | ||
|
|
||
| # ── 4. 报告 ─────────────────────────────────────────── | ||
| if [ -z "$flagged" ]; then | ||
| echo "" | ||
| echo "OK:本 PR 没有把工程文档写进仓库。" | ||
| exit 0 | ||
| fi | ||
|
|
||
| echo "" | ||
| echo "::error::检测到疑似工程文档进入仓库" | ||
| echo "" | ||
| echo "以下文件被拦下:" | ||
| printf '%s' "$flagged" | ||
| echo "" | ||
| echo "规范:设计 / 架构决策 / 模块拆分 / 接口契约说明 / AI 生成的 plan 与 spec" | ||
| echo " 写进 Issue 正文(版本靠 Issue 描述区的编辑历史,定稿后只读),不 commit 进仓库。" | ||
| echo " 细则见仓库根目录 CONTRIBUTING.md 第 2.1 节。" | ||
| echo "" | ||
| echo "三种放行方式,任选其一:" | ||
| echo " 1) 内容搬进对应 Issue,然后 git rm 掉这些文件,PR 描述写「内容已迁到 #NN」;" | ||
| echo " 2) 这确实是【用户文档】(讲怎么用,不讲为什么这么设计)" | ||
| echo " → 给本 PR 打 label 'user-doc',本检查会自动重跑并放行;" | ||
| echo " 3) 属于长期该入仓的用户文档目录 → 放到 docs/user/ 或 docs/guide/ 下。" | ||
| echo "" | ||
| echo "本门禁刻意保守:只拦 docs/** 与根目录新增 md,子目录 README / MODULES.md 一律不管。" | ||
| echo "" | ||
| echo "如果上面某个文件在 main 上明明已经存在,那不是它真的被新增,是你的分支落后了——" | ||
| echo "本检查按 merge-base 算差异,陈旧的 base 会把「早就在 main 上的文件」算成新增。" | ||
| echo "先 git fetch upstream && git rebase upstream/main,本检查会自动放行。" | ||
| echo "" | ||
| echo "如果它误伤了你的正常工作,请开 Issue 说明,别绕过后就不提——门禁自身的问题要单独修。" | ||
| exit 1 |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这里看起来只是给 claude 添加了 skill,缺少其他 agents 的专属目录;
常用的做法是添加一个 .agents 目录(因为绝大多数的 agents 遵循该规范),其余的特殊情况比如 claude 可以通过软连接的方式实现。