Commit Graph

12 Commits

Author SHA1 Message Date
hermes 43b1e423fe fix(qa): 规范化邮件调度测试并声明其外部依赖
build / build (push) Successful in 1m11s
gofmt 修正;该集成测试需要一次性库与测试密钥,按仓库约定在 test-scope.json 声明为可选未运行。
2026-10-26 10:01:14 +08:00
姚章浩 533db535f1 feat(qaops): 接入真实模型补缺任务与总表看板
build / build (push) Successful in 1m12s
按已确认需求提供独立安全模型配置、真实探测、正式字典字段评估与原问题译中,持久批次支持只补空白、暂停恢复、有限重试、幂等和逐字段依据。覆盖固定规则、本地语言、组织关联与主表有效看板共用治理侧读模型,保留源生产和冻结历史。

验证:完整 make verify 退出0,702项Go与329项前端通过;默认118项外部/隔离集成明确跳过,另跑完整镜像及组织隔离PG竞态。12并发、输入漂移、过期租约、暂停/恢复及有限重试通过。用户授权的百炼 deepseek-v4.1-flash 完成真实后台与浏览器评估/翻译;552行、16列、11块看板及完整PNG、独立配置页测试/保存、重开恢复和零JS异常通过。仅非业务样本外发,自动处理关闭,原payload不变。

上线前治理库已做导出快照原生备份并真实恢复,60表行数与17个QA表内容哈希一致;不修改DobotAI生产或隧道。本提交时尚未部署,线上验收须独立完成。
2026-10-19 14:29:49 +08:00
姚章浩 3e7fcce0b1 feat(qa-ops): 持久本地问答副本与安全答案预览
build / build (push) Successful in 1m11s
新增迁移50与每5分钟/手动持久同步,API只读本地;同步失败保留、权限阻断、租约与质量失效原子激活。
保留全量稳定分页/固定列,已存质量批量读取,元数据不反复解压长答案;详情安全Markdown与原文。

已运行整仓 make verify、源与副本隔离PG -race、真实只读源及隔离浏览器。
实际同步2525条;固定窗口640条本地中位1.46秒,对照直接源33.10秒。
停worker、缺源凭据、重启API后仍可查询;未更新8088,未修改生产原问答。
2026-10-18 19:10:47 +08:00
姚章浩 4b3aaff321 feat(qa-ops): 完成复检留档与人工复核闭环
治理侧保存输入观测版本、自动复检及人工复核历史,输入变化失效、版本冲突和幂等重放不覆盖人工记录。批量质量数量使用完整筛选元数据,未采集原文不伪造快照,延迟旧扫描不回退新输入。

验证:全仓 make verify 退出码0,Go656及前端253通过;五包竞态、源/组织/质量隔离PG、真实只读源和隔离网页读回复核通过。默认91个可选集成跳过不计通过。未接AI模型,不写DobotAI源库,未推送、未合并、未部署。
2026-10-17 22:37:26 +08:00
姚章浩 56b8cabed9 feat(qaops): 接入问答组织补全与区域使用统计 2026-10-17 19:02:13 +08:00
姚章浩 cc4906b6a9 feat(qaops): 接通网页通讯录持久化同步与后台接管 2026-10-17 17:36:07 +08:00
姚章浩 dab74b706b feat(qaops): 增加版本化部门区域归属配置与预览 2026-10-17 11:39:38 +08:00
姚章浩 fd04bf7886 feat(qaops): 接入独立只读问答查询与治理覆盖复检 2026-10-17 09:04:19 +08:00
姚章浩 0974d8dfa2 feat(version-history): 「版本记录」页 —— 追踪远端 main 全部提交(只读 + 管理员手动同步)
build / build (push) Successful in 57s
按已确认的契约实现(口径见 docs/VERSION_HISTORY.md):

- **版本号口径(只给有证据的)**:注释 tag + tag 指向该提交 + 该提交内 CHANGELOG 顶部三者一致 ⇒ 正式版本;
  tag 之后的提交按 `<主>.<次>.<自该 tag 的提交数>` 显示开发号(与 scripts/version.py **同规则**);
  证据不足 ⇒ 「历史提交 · 短SHA」+ 原因码,**不补造版本号**。完整 SHA 是唯一身份、版本号不是唯一键
  (tag 之后两条并行分支各自的第 1 个提交都算 0.1.1 ⇒ 两条都保留,用短 SHA 区分)。
- **迁移 000046**:version_history_commits(提交记录,主键 repo_key+commit_sha)+ version_history_sync_runs
  (同步状态)。快照 = 一次同步:抓完并与 X-Total-Count 对账通过才切换;失败不切换快照、不清空历史、
  last_success_at 不动(页面显示"上次同步失败(原因)· 仍展示上次成功数据");「同步成功」≠「历史完整」。
- **只读客户端(匿名,不使用任何凭据)**:白名单 origin + 固定仓库、拒绝任意 URL 与跨主机重定向、
  响应上限 5MB / 超时 15s、仅 5xx/429 退避重试(最多 3 次);逐页抓到短页为止;每次全量扫 tag
  ⇒ 旧提交后补的 tag 会更新既有记录(不新增第二行)。
- **接口**(三个都登记进 api/openapi.yaml):GET /api/v1/build-info(viewer)、
  GET /api/v1/version-history(viewer;游标绑定快照,过期返回 409 cursor_expired;不返回伪造 total)、
  POST /api/v1/version-history/sync(admin;并发同步复用同一作业,靠 IdempotencyKey)。
- **「当前运行」只认精确匹配**:产物注入的完整 SHA 命中某条记录才标该条;开发构建显式标注"开发构建";
  没有可用标识 ⇒ "当前运行版本未知";**不拿最新 main / 最新 tag 顶替**,CI 成功不等于已部署。
- **前端**:一级菜单第 5 项(版本记录)+ 时间线页面(全部/正式/开发/历史四段筛选、正文展开、
  加载更多、760px 单列无横向溢出、提交正文与变更记录按纯文本渲染);无打 tag / 发布 / 部署入口。

新增配置(留空即未接线,页面降级):VERSION_HISTORY_GITEA_BASE_URL / _REPO / _ALLOWED_ORIGINS /
_HTTP_TIMEOUT / _MAX_PAGES。

验证:`make verify` 15/15 success(tests-go 578 通过 / 0 失败;tests-web 209 通过 / 0 失败);
新增 Go 用例 30(版本口径与图遍历 12、客户端守卫 6、同步编排 5、接口 7);前端新增 18(组件 10 + 客户端 8);
真实仓库匿名快照拉取(`VERSION_HISTORY_LIVE_BASE_URL=… go test -run TestLiveSyncAgainstRealRepository`):
抓到 113 条与 X-Total-Count 一致、v0.1.0 是注释 tag 且目标与 `git rev-parse v0.1.0^{commit}` 一致、
开发号逐个等于 `git rev-list --count v0.1.0..<sha>`(正式 1 / 开发 22 / 历史 90)。
2026-10-13 19:40:19 +08:00
姚章浩 7a9d51cc70 fix(version): 正式构建核证据 + 预检分"建议/就绪" + CI 就绪按必需 context
按要求补三项(本轮不推、不打真实 tag、不部署;全部用临时仓库与假对象验):

1) 正式构建身份不能只认 --release:
   - 新增 release_evidence():核①完整 40 位 SHA ②**指向该提交的注释 tag** v<版本号>
     ③该提交里 CHANGELOG 顶部版本一致。缺任一条 ⇒ rc=2,身份退回 development 并把
     release_blocked 的原因写进 JSON(给机器读,也给人看)。
   - version.py --self-test:六条负例(有版本无 tag / unknown SHA / 短 SHA / tag 指错提交 /
     轻量 tag / 版本不一致)+ 证据齐正例,**tag 全部在 mktemp 临时仓库里创建**。
   - Go 侧新增 TestReleaseBuildRequiresEvidence:release 构建必须 CommitSHA 完整且
     v<ReleaseVersion> 是**注释 tag** 并指向该提交(独立于 Python 的二次复核)。

2) 发布预检区分"准备建议"与"发布就绪":
   - 新增纯函数 readiness(facts) → (是否就绪, 阻塞项, 建议);输出分两段。
   - **就绪要求候选版本已写进目标提交**(version_in_commit:查 git show <sha>:CHANGELOG.md,
     工作区写了没提交不算);首发按**显式指定版本**处理,**不把"记录里有这个版本"当已发布**
     (已发布的证据是 tag,不是记录条目)。
   - 预检**不执行、也不在输出里推荐自动发布路径**(正式发版由人按 docs/RELEASE_RUNBOOK.md)。

3) CI 就绪判据:必需 context 集合来自 .gitea/required-contexts.txt(缺失/为空 ⇒ 没有策略 ⇒
   阻断,不用观察到的状态顶替);**全部 success 才通过**,失败/缺项/pending/查询异常一律阻断。
   Release 查询加 release_state():**只有 HTTP 404 才算不存在**,403/5xx/超时算查询异常 ⇒ 阻断。

验证:version.py --self-test 绿;release_preflight --self-test 绿(就绪判定 19 个分支 +
临时仓库验证 git show 语义 + 五个 HTTP 码语义);go test 三态(未注入 SKIP / 开发 PASS /
自称正式 RED);反向夹具 83/0(含临时仓库 go test 六例、预检"记录未进提交"两态);
make verify 15/15 success。
2026-10-13 15:26:49 +08:00
姚章浩 05144309c3 feat(version): 构建身份(release_version/build_kind/display_version),无基线也放行
解决"开发构建沿用已发布版本号,分不清开发版与正式版":

- 新增 `scripts/version.py --identity`:release_version(无基线即空)/ build_kind /
  commit_sha(完整 40 位)/ display_version / built_at。显示规则:发布 `X.Y.Z`、
  开发 `X.Y.Z-dev+g<短SHA>`、无基线 `dev+g<短SHA>`、什么都拿不到 `dev`。
- `build_kind=release` 只认**显式发布上下文**(`BUILD_KIND=release` / `--release`);
  声明发布构建却没有已发布版本 ⇒ 拒绝(rc=2)。普通 main 构建永远是 development,
  **不许只显示上一正式版本号、不许自称正式版**。
- Go 侧 `internal/version` 加 ReleaseVersion/BuildKind/DisplayVersion()/IsRelease()/Info(),
  原 Number/CommitSHA/BuildTime 语义不变(向后兼容);契约测试改成:发布构建必须等于
  CHANGELOG 顶部、开发构建必须是 dev 形状;`make verify` 的 contracts 项新增
  **负例**「自称正式版 ⇒ 必须红」(只有正例的契约会被静默掏空)。
- 构建接线:Makefile/Dockerfile/ci_checks `--internal-build` 统一走 identity;
  Makefile 的 `make version` 打印身份 JSON;Dockerfile 新增 RELEASE_VERSION/BUILD_KIND。
- `tests-go` 的"按设计跳过"声明补上 `TestDevBuildDoesNotClaimRelease`(它的强制点在 contracts)。

验证:go test 三态实测(未注入 SKIP、开发身份 PASS、自称正式版 FAIL);
--internal-build 产出并打印 dev+g<sha>;--internal-identity 契约项 rc=0;
make verify 15/15 success;反向夹具 80/0。
2026-10-13 14:59:36 +08:00
姚章浩 88da069e1f ci(checks): 必需与可选测试按声明区分,未声明就跳过的用例判红
test-scope.json 提供声明:package/test 至少给一个、必须给 reason 与 owner、package 级要写 expected_skips(跳过数涨了要重新声明)、review_by 过期即失效。文件缺失或解析不了 = 声明不出来 ⇒ 不许默认放行。
2026-10-12 11:15:18 +08:00