Commit Graph

8 Commits

Author SHA1 Message Date
姚章浩 4f8ee0a8c5 feat(version): 变更记录改固定四类,破坏性变化带发布文档链接
按项目方给的规则重做 CHANGELOG 与检查器(本轮不推、不打 tag、不部署):

- 条目形状:四个自定义必填节(改了什么/兼容性与迁移影响/怎么验收/已知问题)
  → 固定四类 Added/Changed/Fixed/Security;分类可省略,**不许空栏目**;每个版本块
  至少一个非空分类;`[Unreleased]` 段不得写日期。
- 破坏性变化:固定写在 Changed 里、以 `**破坏性**` 开头,**必须链接发布文档**;
  仓内 `docs/….md` 链接**对账**(不存在 ⇒ 红)。写在别的分类里也判红。
- 结构判据补强:非法日期、重复版本、顺序必须严格递减、前导零;围栏代码块里的
  `##`/`###` 不算标题;**块正文以任意二级标题为界**(「## 能力基线(未发布)」这类
  不带方括号的标题原先不是边界,会把后文算成上一节的内容 ⇒ 空栏目被兜成"有内容",
  夹具真的抓到了这个假绿)。
- tag 一致性:远端专属清单 `.ci-remote-tags` → `ls-remote` → 本地 refs 三级来源;
  **没核对远端就不许说校验成功**(CI/预检用 `--require-remote`,拿不到清单即红),
  非正式 tag(如本地 `x`)不当作发布版本、不判红,没有 tag 不判红。
- `0.1.0` 定为**未发布的能力基线**(远端无 tag、无 Release):改成不带方括号的
  「## 能力基线(未发布)」,不补造 tag/发布日期/发布事实。
- 过程记录迁出:审查轮次与命令输出 → `docs/archive/CI_接入留档.md`(原文保留);
  未合并事项 → `docs/BACKLOG.md`;补 `docs/RELEASE_RUNBOOK.md`(破坏性变化的链接目标,
  同时修掉 CHANGELOG 里指向不存在文档的悬空引用)。
- 发版预检:无版本基线时把「首个正式版本号由人指定」列成阻塞项(不再要求先有基线才能跑);
  打印破坏性变化条数;远端 tag 查不到时明说未核对并阻塞;不再硬读已删除的『已知问题』节。
- traps trap-5 口径修正:不是"不用 tag",而是"构建时不要用 git describe 取版本号"。

验证:check_changelog --self-test 全过;反仓夹具 80/0(含五条真改文件的结构负例、
六条只在临时仓库里造 tag 的场景);make verify 15/15 success。
2026-10-13 14:59:35 +08:00
姚章浩 9ad13a8c62 docs(agents): 留档短命试验分支的真实 CI 运行记录(run #16 失败 / #17 通过)
build / build (push) Successful in 48s
记录真实 run 链接、完整 SHA、14 项必需检查、预览 URL 与探测结果、通知入队与 ret=-2 的送达状态、run #16 暴露的 total_commits=0 缺陷,以及未验证项。分支 ci-trial-20261012 已在试验后删除,远端只剩 main。
2026-10-12 17:00:21 +08:00
姚章浩 257a8a187a fix(gate): total_commits<=0 视为未声明,范围以 Git 为准(真实新分支事件形状)
build / build (push) Successful in 1m22s
真实 Runner 首跑(run #16, ci-trial-20261012)发现:新分支推送时 Gitea 给 total_commits=0、commits 列表被截断(5 条),而 Git 范围 12 条;原先'声明条数 != Git 范围就拒绝'让门禁第一次真实运行就红,且与代码质量无关。改成 Git 范围是唯一权威:total_commits>0 才交叉核对(保留'声明6/列表1/Git2 ⇒ 拒绝'的判据),<=0 或缺失视为未声明并以 Git 范围为准,同时把'负载条数不可信、列表被截断'写进来源说明。--self-test 增加该形状(15 分支);traps 22 记录教训:负例要照真实负载的形状造。
2026-10-12 16:55:41 +08:00
姚章浩 91b674f278 docs(agents): 清掉 traps.md 文件末尾的多余空行(git diff --check 报的最后一处)
build / build (push) Failing after 4s
2026-10-12 16:52:44 +08:00
姚章浩 d167a2b937 fix(ci): 第一步改最小 bootstrap(空工作区可启动),新分支范围以默认分支为基准
空工作区启动:workflow 第一步不再调用仓内脚本(此时它还不存在,实测 rc=127),改成只用 runner 环境变量的最小 bootstrap:校验协议/凭据 → git init+remote add → 取事件完整 SHA → checkout → 断言 HEAD==事件 SHA;检出后才调用 ci_checkout.sh --post-checkout 做再断言与补取(默认分支引用、事件 before)。按任意 SHA fetch 在服务端默认不可用(服务器不允许请求未公开的对象),改成取分支历史 + --deepen 再核事件 SHA。新分支范围:after --not --remotes 会把刚 fetch 的同名远端分支(=after)当排除集、排除自身得到 0 条;改为以远端默认分支为基准 refs/remotes/origin/<default>..<after>,取不到基准就明确失败。新增 scripts/ci_chain_fixture.py:本地 HTTP git 服务 + 把 workflow 的 bootstrap run 块原样抽出来在空目录执行,正/负例 12 项断言。
2026-10-12 16:45:10 +08:00
姚章浩 75a6085844 docs(agents): traps 14-18(假检查/预览顺序/观察到的 context/协议降级/范围退化) 2026-10-12 11:15:18 +08:00
姚章浩 96ac67e744 docs(agents): traps 补 5 条、CHANGELOG 记这批 CI 改动的改了什么与怎么验收
新增陷阱(只追加、不复用旧号):
trap-8 gofmt -l 列出文件时退出码仍是 0(只看退出码=假绿);
trap-9 tar -C dir . 产生 . 根成员 ⇒ 预览 404 而流水线显示成功;
trap-10 依赖清单被静默改写(-mod=mod、缺锁回落 npm install);
trap-11 汇总把"未运行/被跳过"当"通过";
trap-12 事件 SHA 与检出 SHA 不一致;
trap-13 密钥扫描规则过宽 ⇒ 永远的假红,最后被人整条注释掉。
(trap-13 来自实做:第一版规则用很宽的字符类抓口令段,把 postgres://{u.quote(...)} 这类
 模板表达式和 *** 脱敏也当成密钥,四条全是假阳性。收窄口径并把这些形状钉进良性对照防回归。)

AGENTS.md 的现状表需要同步(写着"main 已启用分支保护",实测 GET /branch_protections = [])——
该文件受写入保护,本次未改,修正稿另存待批准后应用。

验证:python3 scripts/check_changelog.py 结构自检通过;make verify 全绿。
2026-10-12 00:11:10 +08:00
姚章浩 5f3a71cade feat(version): 版本号唯一来源 = CHANGELOG.md,并要求写清改了什么与怎么验收
build / build (push) Successful in 26s
背景:本仓此前没有任何版本/构建元信息 —— 没有 ldflags 注入、也没有产物可读的
版本号,"线上跑的是哪个提交"答不出来;"这次改了什么、怎么验收"也没有载体。

落地:
- CHANGELOG.md:**版本号的唯一来源**(正本 §6.1:版本号只准有一处)。刻意不放
  VERSION 文件、也不靠 git tag —— CI 是 `git fetch --depth 50`,取不到 tag,
  `git describe` 会静默退化。每个已发布版本必须有两节:### 改了什么 与 ### 怎么验收。
- scripts/version.py:从 CHANGELOG 顶部解析版本号;解析不到即非 0 退出(构建据此失败)。
- scripts/check_changelog.py:结构自检(两节齐、带日期、版本号不重复且严格递减、
  小节不为空),带 --self-test 反向自检。
- internal/version:三个构建期注入变量 + 契约测试(注入的号必须等于 CHANGELOG 顶部)。
- Makefile:build 带 -ldflags 注入;verify 增加 changelog-check 与 version-contract。
- Dockerfile:ARG VERSION/COMMIT_SHA/BUILD_TIME + ldflags(未透传时落 dev —— 故意显眼,
  好过看起来正常的假版本号)。
- CI:新增「版本与变更记录契约」步,并显式断言契约测试真的 PASS(被跳过的断言等于没有断言)。
- docs/提交规范.md(ci_gate.py 的报错文案一直在指它)、docs/agents/traps.md(7 条实测陷阱)。

验证(都真跑过):
- make version → 0.1.0;make changelog-check → 合规
- make version-contract → PASS;注入 9.9.9(CHANGELOG 里没有)→ FAIL(反向自检)
- 删掉真实 CHANGELOG 的「怎么验收」小节 → 报红(对真实文件做,不只是夹具)
- go build ./... 与 go vet ./internal/version/... 通过

未做(会与在审 PR #2 冲突,待其合并后在 main 上补):
- GET /version 端点(internal/httpapi/server.go)与 cmd/api 的 -version 开关
- compose.yaml 透传 build args(当前由 compose 构建的镜像会报 dev)

⚠️ 未跑 make verify 全量(含 go test ./... 与前端),CI 是本次的测试证据。
2026-10-10 18:13:24 +08:00