docs(tasks): stop making the product owner hand-copy a 40-hex SHA
migrate-staging-database 的 deploy_sha 挡的是「迁移必须钉在真正过了门禁的 修订上」:格式校验、查该 SHA 有没有成功的 backend-quality-gate 运行、与 staging head 比对后把纯文档前进的判定交给背书过的 controller。这三条不能丢。 但产品手填的那个值,恰恰就是「最新一个过了门禁的 staging 提交」——机器能 自己算,而且需要的 API 查询在同一步里已经写好了。改成:留空即自动解析, 填了就完全走原路径(回滚与迁移到更早修订的唯一手段)。解析出来后仍然照常 跑一遍全部校验,两条路径共用同一套门。 范围比看上去小:Deploy Staging 在门禁通过后由 backend-quality-gate 自动 dispatch,正常根本不用点;真正每次都要手填的只有 Migrate Staging Database 一个按钮。 生产两个按钮保持手填。它们额外要 allow_rollback / recovery_reference / restore_verified,设计意图就是逼人说清楚要发什么;在生产省掉这步不是便利, 是拆护栏。 AGENTS.md §2.7 禁止代理改 workflow,产品本次明确授权,已写进决策记录, 否则执行方会拒改;授权范围仅限本单点名的文件与改动。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0155nFCgCHtoA7jhSDGmZmMu
This commit is contained in:
co-authored by
Claude Fable 5
parent
ebd6175b40
commit
de47c06d97
@@ -229,6 +229,7 @@
|
||||
| `TASK-readonly-pages-fix-20260916.md` | `PROGRESS-readonly-pages-fix-20260916.md` | 三份只读页单的验收修复:**BUG-710** 七政 `ketu_mode`/`sidereal_mode` 收了请求却从不传给引擎,`calculation.ketu_mode` 回写请求值而非实际值(实测请求 descending-node 仍返回 apogee 盘,无警告);**BUG-711** 星历单断言 sidebar 不得含 `/ephemeris`,与星盘单按任务书添加的入口直接冲突,staging 现在是红的;**BUG-712** `ephemeris_events` golden 存全精度浮点跨机不稳,且 golden 缺失时自动重建。另附部署缺口:`deployment.gitCommit` 仍是 `2d7698ea`。BUG 段 710+ | 待验收 | `codex/readonly-pages-fix-20260916` |
|
||||
| `TASK-chart-page-blocking-open-20260915.md` | `PROGRESS-chart-page-blocking-open-20260915.md` | **P1**:星盘页开一次要等很久且常常只给一句「过一会儿再打开」。实测引擎五个调用合计 0.75 秒、mapper 13 种形态零抛出——瓶颈在 `/chart` 是动态路由 + 侧栏改成硬文档跳转,整页 SSR 等完 1 串 4 并才开始画,白屏最长 45 秒(BUG-716);`postEngine` 把 429/500/超时/坏 JSON 全碾成 `null` 且零日志,两种性质相反的故障共用一句文案(BUG-715);开页并行打两个重计算限流端点(配额 2)、无缓存,且「打开即有」印在失败页上(BUG-717)。**串行在 readonly-pages-fix 之后** | 待验收 | `codex/chart-page-blocking-open-20260915` |
|
||||
| `TASK-rectification-title-repair-migration-20260915.md` | — | BUG-699 / 704 的数据修补写成了 Node 脚本(要 `SCHEMA_DATABASE_URL`),但 `Migrate Staging Database` 只跑 `migrator` 应用 SQL 迁移、不执行任意脚本——产品没有任何按钮能修自己那批错名字的会话。脚本里本来就是纯 SQL,搬进一次性迁移即可复用现成按钮。生产停在 `7b620c7a`(无 `use-rectification-surface.ts`),where 自然匹配 0 行,是 no-op | 待领取 | `codex/rectification-title-repair-migration-20260915` |
|
||||
| `TASK-staging-dispatch-autofill-sha-20260915.md` | — | `Migrate Staging Database` 每次都要手抄 40 位 SHA,而那个值恰恰是「最新一个过门禁的 staging 提交」——机器能自己算,查询代码那一步里就有。改成留空自动解析、填了仍走原路径(回滚用),三条安全属性一条不丢。**产品 2026-09-15 明确授权修改该 workflow,执行方不得以 AGENTS.md §2.7 拒改**;生产两个按钮保持手填,那是护栏不是麻烦 | 待领取 | `codex/staging-dispatch-autofill-sha-20260915` |
|
||||
| `TASK-api-server-decomposition-20260916.md` | `PROGRESS-api-server-decomposition-20260916.md` | **重构单(串行在 qizheng 单之后)**:把业务逻辑搬出 `JyotishAPIHandler`。核心不是行数,是全仓 3 处靠 `JyotishAPIHandler.__new__` 伪造空壳 handler 借方法(`consultation_workflow_service` ×2、`capture_report_blocked_repairs_golden`、`local_accuracy_report`,MCP 也走这条),依赖方向反了、handler 没有 `headers`/`wfile` 随时可炸。四阶段:拆 `__new__` 后门 → 抽 ≥150 行业务方法 → `do_POST`/`do_GET` 改路由表 → 重新冻结行数 baseline(余量 300→50)。纯搬运不改行为,`test_api_server_security.py` 3841 行断言一条不许改。预计 11,314 → 约 9,230 行。BUG 段 710+ | 待领取 | — |
|
||||
|
||||
## 命名与归档
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
# TASK · `Migrate Staging Database` 不再要求手填 SHA
|
||||
|
||||
- 日期:2026-09-15
|
||||
- 基线 commit:`origin/staging` @ `ebd6175b`
|
||||
- 执行分支:`codex/staging-dispatch-autofill-sha-20260915`
|
||||
- 影响面:`.gitea/workflows/migrate-staging-database.yml`(以及可选的 `deploy-staging.yml` 手动表单)
|
||||
|
||||
---
|
||||
|
||||
## 1. 产品诉求(原话)
|
||||
|
||||
> 我不想手填 sha 了,反人类,能不能改一下。
|
||||
|
||||
---
|
||||
|
||||
## 2. 先说清楚这个 SHA 在挡什么(不能直接删)
|
||||
|
||||
`.gitea/workflows/migrate-staging-database.yml` 的第一步 `Validate current staging revision and successful gate` 用 `inputs.deploy_sha` 做三件事:
|
||||
|
||||
1. 格式校验:必须是 40 位小写十六进制。
|
||||
2. **查这个 SHA 上有没有跑成功过 `backend-quality-gate`**(`event=push`、`branch=staging`、`conclusion=success`)。查不到就 `no successful exact-SHA staging quality gate run found` 并退出。
|
||||
3. 读当前 `staging` head。若输入 ≠ head,标记 `head_check=deferred`——因为纯文档推送不触发门禁,staging 合法地会领先于最后一个被门禁验过的 SHA;是不是「纯文档前进」留给后面那份**门禁背书过的** controller bundle 里的 `deploy/is-docs-only-range.sh` 判定。
|
||||
|
||||
**它的作用是:把迁移钉在一个真正过了门禁的修订上。** 这个属性一条都不能丢。
|
||||
|
||||
但——**产品手填的那个值,恰恰就是「最新一个过了门禁的 staging SHA」**。这是一个机器可以自己算出来的量,而且算它需要的 API 查询**这一步里已经写好了**。让人肉去查、去复制、去粘贴 40 位十六进制,纯粹是把机器的活交给了人。
|
||||
|
||||
## 3. 范围比看上去小
|
||||
|
||||
| workflow | 现在要不要手填 | 本单是否处理 |
|
||||
| --- | --- | --- |
|
||||
| **`Migrate Staging Database`** | **要**,且没有任何自动触发 —— **这就是痛点** | **是** |
|
||||
| `Deploy Staging` | 表单里要,但**正常情况下不用点**:`backend-quality-gate.yml` 在门禁通过后会自己 dispatch 它(并同时传 `deploy_sha` 与 `gate_run_id`) | 可选,见任务 2 |
|
||||
| `Deploy Production` / `Migrate Production Database` | 要 | **否**,见 §4.2 |
|
||||
|
||||
所以真正每次都要手填的,只有**一个**按钮。
|
||||
|
||||
---
|
||||
|
||||
## 4. 决策记录
|
||||
|
||||
### 4.1 产品明确授权修改 workflow
|
||||
|
||||
`AGENTS.md` §2.7 写着「不改 `.gitea/workflows/**`……这三件事只由产品负责人触发」。**产品负责人在 2026-09-15 主动要求改这一条**,本单据此授权执行方修改 `.gitea/workflows/migrate-staging-database.yml`。
|
||||
|
||||
**执行方不得以 §2.7 为由拒改**,但授权范围**仅限本单点名的文件与改动**:把 `deploy_sha` 变成可选并在留空时自动解析。其余 workflow、其余步骤一律不动。
|
||||
|
||||
### 4.2 生产两个按钮**保持手填**,这是故意的
|
||||
|
||||
`Deploy Production` 与 `Migrate Production Database` 除了 SHA 还要求 `allow_rollback`、`recovery_reference`、`recovery_created_at`、`restore_verified` —— 这些输入的设计意图就是**逼你把「我要发什么」说出来**。`AGENTS.md` §1.4 也把生产部署定为手动流程。
|
||||
|
||||
**在生产上省掉这步打字不是便利,是拆掉护栏。** 本单不碰它们。若之后产品仍觉得生产也烦,另开一单单独评估。
|
||||
|
||||
### 4.3 自动解析的定义
|
||||
|
||||
留空时,workflow 自己解析出的 SHA = **`staging` 分支上、最新一个有成功 `backend-quality-gate` 运行的提交**。
|
||||
|
||||
这与产品手工查找的对象逐字相同,因此三条安全属性全部原样保留:仍然要求存在成功的精确 SHA 门禁运行(现在是"由这个条件选出来的");仍然做 head 比对与 `head_check=deferred`;仍然把纯文档前进的判定交给背书过的 controller。
|
||||
|
||||
---
|
||||
|
||||
## 5. 硬红线
|
||||
|
||||
1. **只改 `workflow_dispatch.inputs` 与第一步 `Validate current staging revision and successful gate` 的解析逻辑。** 该步骤输出的三个值(`sha` / `gate_run_id` / `head_check`)语义与格式不得改变;**后面所有步骤一行都不许动**。
|
||||
2. **不得放宽任何校验**:40 位格式校验保留;"必须存在成功的精确 SHA 门禁运行"保留;`head_check=deferred` 的分支与注释保留;`is-docs-only-range.sh` 的下游判定保留。
|
||||
3. **不得改 `deploy-production.yml` / `migrate-production-database.yml`**(§4.2)。
|
||||
4. **不得改 `backend-quality-gate.yml`**,包括它自动 dispatch `deploy-staging` 的那一段。
|
||||
5. **手填仍然必须可用**:填了值就走原路径(这是回滚和"迁移到某个更早修订"的唯一手段)。留空才自动解析。
|
||||
6. 自动解析失败(查不到任何成功门禁运行、API 报错)时**必须硬失败并给出人话原因**,不得回退成"用 staging head"——head 可能根本没过门禁。
|
||||
7. `concurrency.group: staging-mutation` 不动。
|
||||
|
||||
---
|
||||
|
||||
## 6. 任务分解
|
||||
|
||||
### 任务 1 · `migrate-staging-database.yml`:SHA 变可选
|
||||
|
||||
**1.1** 输入改为:
|
||||
|
||||
```yaml
|
||||
deploy_sha:
|
||||
description: 留空=自动用最新一个通过门禁的 staging 提交;填写=迁移到指定的 40 位 SHA(回滚用)
|
||||
required: false
|
||||
type: string
|
||||
```
|
||||
|
||||
**1.2** 第一步开头加解析分支:
|
||||
|
||||
- `DEPLOY_SHA` 非空 → **完全走现在的逻辑**,一行不改。
|
||||
- `DEPLOY_SHA` 为空 → 查 `actions/runs?branch=staging&event=push&status=success`,按现有那段 `jq` 的同一套过滤条件(`.path | split("@")[0] | endswith("backend-quality-gate.yml")`、`head_branch == "staging"`、`event == "push"`、`conclusion == "success"`)取 **`id` 最大**的一条,其 `head_sha` 即为解析结果;随后**继续走原有的全部校验**(格式、gate 查找、head 比对)。
|
||||
|
||||
**注意**:解析出来之后不要跳过第 2 步的门禁查找。让它照常再查一遍——多一次 API 调用,换"两条路径走同一套校验",值得。
|
||||
|
||||
**1.3** 在日志里显式打印一行,例如:`resolved deploy_sha=<sha> (latest gated staging commit)`。**产品需要在日志里看到自己到底迁移了哪个修订。**
|
||||
|
||||
**1.4** 解析不到时的失败信息要是人话,例如:`staging 上还没有任何通过门禁的提交,先等门禁跑完再迁移`。
|
||||
|
||||
**验收标准**
|
||||
|
||||
- 留空运行:日志里有 `resolved deploy_sha=…`,后续步骤与手填同一 SHA 时的行为逐步一致。
|
||||
- 手填运行:行为与改动前**完全一致**。
|
||||
- 手填一个没过门禁的 SHA:仍然被拒。
|
||||
- staging 上不存在成功门禁运行时留空运行:硬失败,信息可读。
|
||||
|
||||
### 任务 2 · `deploy-staging.yml`(可选,产品可要可不要)
|
||||
|
||||
同样把 `deploy_sha` 改成可选 + 自动解析。**收益较低**——门禁通过后它会被自动 dispatch,手动表单只在重跑或回滚时用;而回滚场景本来就要手填。
|
||||
|
||||
`allow_rollback` **保持 required**:自动解析出的永远是最新修订,不构成回滚;真要回滚就得手填 SHA 并显式勾选。
|
||||
|
||||
做不做由执行方看改动成本决定,**结论写进 PROGRESS**。
|
||||
|
||||
### 任务 3 · 文档
|
||||
|
||||
- `deploy/README.md`:把 staging 迁移那一节改成「直接点 Run,SHA 留空即可;只有回滚到更早修订才需要填」,并写明生产两个按钮**仍然必须手填**及其理由。
|
||||
- `docs/tasks/PROGRESS-staging-dispatch-autofill-sha-20260915.md`:改了哪些行、两条路径各自的验证记录。
|
||||
- **不新增 BUG 编号**(这是运维易用性改动,不是缺陷)。当前最大 BUG-717。
|
||||
- 不动 `CHANGELOG.md`(用户可见行为无变化)。
|
||||
|
||||
---
|
||||
|
||||
## 7. 让步顺序
|
||||
|
||||
1. 若 Gitea 的 `workflow_dispatch` 在这个版本上不支持 `required: false` 的空字符串(部分版本会传空串而非缺省),**改用"填 `latest` 三个字母表示自动"** 而不是留空。目的一样:不用打 40 位。哪种可行写进 PROGRESS。
|
||||
2. 任务 2 做不了就不做,不阻塞任务 1。
|
||||
3. **绝不让步**:不得放宽门禁校验;不得改生产两个 workflow;不得改 `backend-quality-gate.yml`;手填路径必须保留可用。
|
||||
|
||||
---
|
||||
|
||||
## 8. 开工前置命令
|
||||
|
||||
```bash
|
||||
cd /workspace/Jyotisha
|
||||
git status -sb | head -1
|
||||
git fetch origin --prune
|
||||
git worktree add -b codex/staging-dispatch-autofill-sha-20260915 \
|
||||
.worktrees/staging-dispatch-autofill-sha-20260915 origin/staging
|
||||
cd .worktrees/staging-dispatch-autofill-sha-20260915
|
||||
sed -n '36,90p' .gitea/workflows/migrate-staging-database.yml # 要改的那一步
|
||||
```
|
||||
|
||||
⚠️ **这一单改的是部署管线本身。** 改完必须确认 YAML 能被 Gitea 正确解析——一个语法错误会让按钮直接消失。推之前本地跑一次 `python3 -c "import yaml,sys; yaml.safe_load(open('.gitea/workflows/migrate-staging-database.yml'))"` 之类的校验。
|
||||
|
||||
交付:`git push origin HEAD:staging`,推完核对远端 SHA,**并确认 Gitea 上这个 workflow 仍然出现在列表里、表单能打开**。
|
||||
|
||||
---
|
||||
|
||||
## 9. 产品侧验证(改完之后)
|
||||
|
||||
1. Gitea → `Migrate Staging Database` → **SHA 留空** → Run。
|
||||
2. 在日志第一步看 `resolved deploy_sha=…`,确认它就是你以为的那个提交。
|
||||
3. 后面照常。
|
||||
Reference in New Issue
Block a user