# 需求:规则校验统一承载-员工本机同闸并回流缺口(服务端-push-闸另行评估)

状态: accepted(2026-10-20 老板 10-19 直投;第一步零服务端改动可先做)
归属: 公司基建
来源: boss 直投(会话)
日期: 2026-10-19
建议: 做,老板 10-19 会话直投「公司层面怎么保持校验统一,目前只能老板电脑校验」;取证结论=判据已同源(rules audit 无机器闸,员工 clone 到手就能跑同一把抬版闸+引用体检),缺的是承载位置与结果回流,不是第二套判据。两步走:第一步零服务端改动,员工本机或日循环跑同闸并把缺口回流;第二步 NAS 侧 push 前拦截属架构级,需先做承载 spike 与专人维护,不在本轮。

## 现状

**判据已经同源,缺的是「谁跑」和「结果去哪」。**

- `ops/onboard.py` 的 `rules audit`(抬版闸+引用体检)对机器没有任何要求:全文「仅老板本机」四处都在
  自述文字里(模块 docstring `ops/onboard.py:14`、常量注释 `ops/onboard.py:36`、函数 docstring
  `ops/onboard.py:1183`、help 文案 `ops/onboard.py:1473`),代码中无 hostname/store 判定。
  员工 clone 到手跑同一条命令,判的是同一把闸 ⇒ 不存在「员工那套判据更松」的分叉。
- 现有承载三处,没有一处落在员工机器上:①`ops/rules_check.py` 的 CHECK_REPOS 是 17 条 `D:/` 绝对路径、
  `ops/rules_check.py:20` 的 ENGINE 硬编码老板本机;②日循环只在老板机器一晚一次;③`app_admin` 仓的
  `scripts/release.mjs` 只在发版那一刻、只覆盖有发版的仓。⇒ 员工机器落后/悬空指针当天无人知。
- NAS 侧取证(2026-10-19 全部只读实测):
  - Forgejo = 容器 `1Panel-gitea-C0Xq`,镜像 `commitgo/gitea-ee:27.3.8`,HTTP 13000 / SSH 1222;
    `GET /api/v1/version` 回 `{"version":"27.3.8"}`,`GET /api/v1/settings/api` 正常回包。
  - `GET /api/v1/repos/xlkj/company/actions/runners` 回 404。**口径声明**:company 是私有仓,匿名 404
    分不清「Actions 未开」与「无权限」,此条不作定级依据;同类漏计形态还有 Actions 页需登录态才可见。
  - `/data/gitea/conf/app.ini` 里 grep 不到 `[actions` 段;`docker ps -a` 里没有任何 act_runner 容器
    ⇒ 「push 自动跑机检」的前提(有 runner)当前不成立。
  - 可插位置确实存在:`/data/git/repositories/xlkj/company.git/hooks/pre-receive` 是
    `# AUTO GENERATED BY GITEA, DO NOT MODIFY` 并转调 `gitea hook ... pre-receive`,同级有
    `pre-receive.d/` 投递目录(现仅 Forgejo 自己的 `gitea` 一份);容器内 `/usr/bin/python3` 在,
    但 `git` 不在 PATH(`command -v git` 无输出)⇒ 想在服务端跑仓内闸,得自己解决检出与工具链。
- 旁证(他人票,2026-10-16 实测,同这台容器):《NAS-Gitea-EE-27.3.4-管理侧两个坏端点》记着
  `gitea admin user create / generate-access-token --raw --scopes / list` 都正常,坏的是 CLI 删号 panic 与
  `GET /api/v1/admin/users/{u}` 405 ⇒ 第二步若要给 runner 注册 token,通道是现成的,别按「引擎侧全坏」估工。
- 另一个真缺口(与统一校验同批):Qoder 全局规则副本实测 41983 B > 32768 B 装载上限——闸跑得再绿,
  员工 harness 读不进去仍是零。

## 方案

**第一步(零服务端,可即刻做):**

- 1a 员工侧让闸自己跑:把 `rules audit` 纳入 `python ops/onboard.py verify` 的一步(员工上岗验收自带同一把闸)。
  同批要改掉四处「仅老板本机」的自述文案(见现状第一条):闸本身对机器无要求,写着「仅老板本机」等于
  劝退唯一能让员工自证的动作——文案与承载不符,正是本轮引用体检要灭的那一类。
  红线不动:任何 hook 只许 `check`,禁止 `pull`;audit 在员工机只判红、写的是本地 `ops/data/rules-audit.json`(gitignore)。
  工作量 ≈ 0.5 人日(改 `cmd_verify` + 先红测试 + `docs/工程规范/ONBOARDING-STANDARD.md` 补口径;不动全局规则正本故不抬版)。
- 1b 结果回流:最小形态=员工把一行读数贴进 worklog(近乎零成本);正规形态=日报/驾驶舱出「机器 → 闸状态」
  清单,但采集要有载体(谁把本机读数送到公司能看到的地方),那部分依赖第二步的通道,先按最小形态起步。
  工作量 0.5~1 人日(只做贴读数=0.5;做采集面须另定方案)。

**第二步(NAS 侧统一承载,架构级:先 spec + spike,不在本轮实施):**

- 2a 选型两条:(i)push 闸——往各仓 `pre-receive.d/` 投脚本,风险是文件落容器可写层、升级重建即丢,
  必须由部署脚本从仓内正本幂等补装,且要解决容器内无 `git`;(ii)Actions——部署 act_runner 容器 +
  `.forgejo/workflows/*.yml` 跑 `rules audit`,前置是先用一个 spike 仓实测该实例 Actions 到底开没开。
- 2b 粗估:runner 路线 ≈ 2~3 人日(runner 容器 + 注册 token + workflow + 每日验证);
  pre-receive 路线 ≈ 3~5 人日且含 NAS 维护纪律(容器重建后自动补装),不建议先做。
- 2c 交付判据:一次「改正文不抬版」或「载体积悬空指针」的 push,在**员工机器上**当场被拦,
  而不是等老板次日日循环报红。

## 验收标准

- [ ] 员工机器(非老板本机)跑 `python ops/onboard.py verify`,输出含抬版闸/引用体检一条读数,判红退 2,且不改写员工 harness(红线复验:hook 与代码里无 `rules pull`)
- [ ] 存在一份「机器 → 闸状态」可见清单(日报或驾驶舱任一),至少覆盖老板本机 + 1 台员工机
- [ ] 服务端承载若推进:先有 spec(选型结论 + 容器重建丢负载的处置),再落 runner/pre-receive,并 spike 实测「故意推一处不抬版的改动被拒」
- [ ] 第二步未落地前,任何随仓载体文案不得写「push 即被拦」之类的超承诺(口径同 2026-10-19 引用体检)
