From ccb1b1ebe53eaa99da80accf73b6fd8c55ea1816 Mon Sep 17 00:00:00 2001 From: weichen Date: Mon, 14 Sep 2026 09:39:30 +0000 Subject: [PATCH] docs(remediation): design runtime data lifecycle --- .doc/ops/CURRENT.md | 4 +- ...ime-data-retention-and-migration-corpus.md | 147 +++++++++++++++ .../2026-09-14-runtime-data-lifecycle-plan.md | 56 ++++++ ...me-data-root-and-projection-remediation.md | 3 +- ...ecycle-and-migration-corpus-remediation.md | 171 ++++++++++++++++++ .doc/remediation/INDEX.md | 1 + .doc/remediation/gap-matrix.md | 2 +- .doc/status/FEATURE-MATRIX.md | 2 +- 8 files changed, 382 insertions(+), 4 deletions(-) create mode 100644 .doc/ops/research/2026-09-14-runtime-data-retention-and-migration-corpus.md create mode 100644 .doc/ops/short-term/2026-09-14-runtime-data-lifecycle-plan.md create mode 100644 .doc/remediation/2026-09-14-runtime-data-lifecycle-and-migration-corpus-remediation.md diff --git a/.doc/ops/CURRENT.md b/.doc/ops/CURRENT.md index 392442e2..a3c12a80 100644 --- a/.doc/ops/CURRENT.md +++ b/.doc/ops/CURRENT.md @@ -5,7 +5,7 @@ ## 焦点 -1. **RUNTIME-DATA-ROOT**: [dev 临时 worktree 数据根 split-brain](../audit/2026-09-14-dev-runtime-data-root-split-brain.md)(critical;当前 app/pi/cursor 挂到 `/tmp/as-dev-wf409-merge/data/dev*`,DB 仍为原 dev 卷;待批准后占槽恢复并系统整改) +1. **RUNTIME-DATA-ROOT**: [dev 临时 worktree 数据根 split-brain](../audit/2026-09-14-dev-runtime-data-root-split-brain.md)(critical;当前 app/pi/cursor 挂到 `/tmp/as-dev-wf409-merge/data/dev*`,DB 仍为原 dev 卷;整改包含[数据精简与迁移语料](../remediation/2026-09-14-runtime-data-lifecycle-and-migration-corpus-remediation.md)) 2. **CHAT-INTENT**: [对话意图运行时状态](../audit/2026-09-13-conversation-intent-runtime-state.md)(`fix/conversation-intent-state`;与文档账本运行时无关) 3. **CHAT**: [对话历史刷新](../audit/2026-09-13-chat-history-refresh-disappears.md)(认领仍 `in_progress`;gap 行已 PASS,以代码/handoff 为准收敛) @@ -49,6 +49,7 @@ | implementer_cursor | workflow-plan-409-frozen-and-optional-duties | fix/workflow-plan-409-frozen-and-optional-duties | .worktrees/fix-workflow-plan-409-frozen-and-optional-duties | workflow | done | | implementer_cursor | governance-action-level-authz | fix/governance-action-level-authz | .worktrees/fix-governance-action-level-authz | workflow | done | | Codex | dev-runtime-data-root-guard | fix/dev-runtime-data-root-guard | .worktrees/fix-dev-runtime-data-root-guard | infra-runtime-state | done | +| Codex | runtime-data-lifecycle-plan | fix/dev-runtime-data-root-guard | .worktrees/fix-dev-runtime-data-root-guard | infra-runtime-state | done | > 新任务开始前登记。`branch` 必须为 `feature/` 或 `fix/`,**禁止** `dev` / `test` / `main`。同一 `mutex` 同时仅一个 `in_progress`。 @@ -110,3 +111,4 @@ | 受控正文真实 UI 验收报告 | [../test-reports/2026-09-14-controlled-content-ui-acceptance.md](../test-reports/2026-09-14-controlled-content-ui-acceptance.md) | | dev 数据根 split-brain 审计 | [../audit/2026-09-14-dev-runtime-data-root-split-brain.md](../audit/2026-09-14-dev-runtime-data-root-split-brain.md) | | dev 数据根与投影系统整改 | [../remediation/2026-09-14-dev-runtime-data-root-and-projection-remediation.md](../remediation/2026-09-14-dev-runtime-data-root-and-projection-remediation.md) | +| 数据生命周期与迁移语料 | [../remediation/2026-09-14-runtime-data-lifecycle-and-migration-corpus-remediation.md](../remediation/2026-09-14-runtime-data-lifecycle-and-migration-corpus-remediation.md) | diff --git a/.doc/ops/research/2026-09-14-runtime-data-retention-and-migration-corpus.md b/.doc/ops/research/2026-09-14-runtime-data-retention-and-migration-corpus.md new file mode 100644 index 00000000..179f5c3e --- /dev/null +++ b/.doc/ops/research/2026-09-14-runtime-data-retention-and-migration-corpus.md @@ -0,0 +1,147 @@ +--- +title: "运行数据精简、迁移语料与演示数据保留策略" +created: 2026-09-14 +status: done +confidence: high +--- + +# 调研:运行数据精简、迁移语料与演示数据保留策略 + +## 结论 + +用户提出的“及时清理过往数据,只保留最新、有用且必要的一部分,并用保留数据验证迁移和重载”方向合理,尤其适合当前快速迭代期的 dev/test 环境。 + +但必须补充两个边界: + +1. 清理历史运行数据只能降低数据转换量和现场噪声,不能替代对受支持旧 schema 的迁移兼容;应把有价值的旧状态压缩成小型、可重复、脱敏的 migration corpus。 +2. 不应在当前库上逐表删除后继续使用;当前跨项目数据存在非完整级联和 DB/文件双事实源,优先采用“新库 + 新状态根 + 选择性导入 + 旧卷隔离”的蓝绿轮换。 + +## 当前数据画像 + +2026-09-14 只读现场: + +| 环境 | schema | 项目数/特征 | 文件状态 | 判断 | +|---|---:|---|---|---| +| dev | 33 | 366 个项目;149 active、217 planning;全部产生于 9 月 11–14 日 | 主仓 `data/dev` 约 100MB | 大量 PG/E2E 夹具,适合立即精简,但须先解决当前错误挂载事故 | +| test | 29 | 约 37 个项目 | 主仓 `data/test` 约 20KB | schema 落后且数据价值低,应改为可重建/短 TTL | +| main | 25 | 10 个历史 seed 项目,当前无受控文档 | 主仓 `data/main` 约 20KB | 不应用作日常迁移试验;清理需另行确认业务/展示用途 | +| shared KB | 独立 | 跨环境共享知识库 | `data/shared` | 不属于本方案的项目数据清理范围 | + +dev 主要表约有:`projects=366`、`chat_sessions=421`、`chat_messages=1923`、`task_runs=307`、`document_records=153`、`document_snapshots=283`、`document_change_events=257`。数据库总体不大,主要问题不是容量,而是数据来源混杂、迁移噪声和无法判定哪些记录应保留。 + +## 现有清理为何不能直接做 + +### 1. `DELETE projects` 不是完整项目删除 + +当前外键有 101 条,部分项目子表 CASCADE,但存在关键例外: + +- `task_runs.project_id` 是 `ON DELETE SET NULL`,项目删除后 run/event 仍可残留; +- `document_versions`、`document_snapshots`、`document_change_events`、`document_change_reports`、`document_agent_candidates` 依赖 `doc_id`/snapshot/version,但不完整依附 `projects`; +- `document_content_blobs` 与 `storage_blobs` 需要引用计数/mark-and-sweep,不能看到文件就删; +- 工作区、agent sessions、CAS 文件位于状态根,数据库 cascade 不会删除文件; +- notification/outbox/audit/lineage 的保留语义不同,不能一律级联。 + +所以简单删除项目会制造孤儿数据,反而加重后续迁移与排障成本。 + +### 2. 现有备份/恢复不足以支撑安全轮换 + +- `backup-system-db.sh` 只导出 PostgreSQL,不包含与之匹配的 `data/` 文件状态; +- `restore-system-db-drill.sh` 校验 dump 列表并运行迁移测试,但当前没有真正把 dump restore 到新隔离数据库; +- restore 未强制隔离目标,默认路径存在误触共享 dev 库的风险; +- 没有 dataset manifest、项目选择、文件 SHA inventory、脱敏、预期断言与导入校验; +- 备份脚本的凭证来源需要改成统一安全配置,不应保留脚本内默认值。 + +在这些缺口补齐前,不能用“有 dump”作为可删除证明。 + +## 建议的数据分类 + +| 类别 | 用途 | 典型内容 | 是否进入日常运行库 | 保留策略 | +|---|---|---|---|---| +| `operational-pinned` | 当前人工使用/正在排障 | 项目 143 等明确认领项目 | dev 可保留;main 按业务规则 | 显式 pin,禁止自动清理 | +| `demo-current` | 产品展示 | 每个正式工作流 1 个完整、可解释项目 | dev/demo 环境 | 只保留当前版本;新版验证后替换旧版 | +| `regression-golden` | 功能回归 | 文档版本、人工修订、并发冲突、reload 等完整链 | 隔离验收库,可选只读展示副本 | 小型、确定性、脱敏;按能力而非数量保留 | +| `migration-baseline` | 旧 schema → 当前 schema | 旧 release 的最小 DB + 匹配文件包 | 仅隔离迁移测试 | 最多保留 3 个 release 基线,滚动替换 | +| `ephemeral-test` | PG/E2E 单次运行 | 自动测试项目、会话、run、workspace | 每次独立数据库/状态根 | PASS 后立即删;FAIL 保留 3–7 天 | +| `quarantine` | 清理回滚与取证 | 被替换的完整卷/状态根 | 不挂载到运行容器 | 只读 7–14 天,恢复演练通过后销毁 | + +## 建议的最小保留集合 + +当前 dev 可先采用 6–10 个项目的上限,而不是按日期盲留: + +1. 项目 143:暂作旧数据/canonical repair/active workflow 回归样本;若含真实内容,不进入 Git,后续用脱敏等价 fixture 替换。 +2. 项目 6173:目前最新且证据完整的受控正文 UI 全链,含两份受控文档、V3/r2、并发、权限与 restart 验证,可作为当前回归/展示候选。 +3. 项目 6159:保留一个发布周期作为上一轮文档账本对照;6173 corpus 稳定后删除,避免永久重复。 +4. 三个正式工作流各生成 1 个 `demo-current`:`main`、`product_manager`、`test_manager`;必须由固定 seed/真实页面脚本可重建,不能依赖手工挑出的偶然状态。 +5. 1 个失败/异常样本不进入展示库,只进入隔离 `regression-golden`:覆盖 projection missing、hard-break、旧消息 scope、高 ID sequence 等历史风险。 + +最新项目不等于最有价值。选择评分应优先:证据完整度、覆盖的能力、是否可脱敏重建、DB/文件一致性、是否有预期断言;时间只作为同类样本的淘汰条件。 + +本轮已只读确认 143、6159、6173 共 5 份受控文档在主仓状态根的 `output.md` 均存在且 SHA 与 `document_records` 一致;这说明它们具备候选资格,但仍需通过敏感性、owner 和可恢复性审查后才能进入最终 retain allowlist。 + +## 迁移语料库策略 + +不保存每个 Goose 版本的整库。按产品 release 边界保留: + +- `oldest-supported`:当前承诺支持的最老 release; +- `previous-release`:上一发布版; +- `current-pre-upgrade`:本次上线前快照,下一次轮换为 previous。 + +当前建议先建立三个最小基线: + +- schema 25:文档账本前/早期治理状态,覆盖 main 当前落后路径; +- schema 28/29:文档 revision 首次引入后的状态,覆盖 test 当前路径; +- schema 32/33:canonical repair、task 状态和当前数据根契约。 + +这些基线应由迁移 fixture builder 在隔离库中构造或从已批准快照脱敏得到,不能直接把 main/test 的运行数据当测试资产。 + +每个 corpus package 必须包含: + +```text +manifest.json +database.dump +state.tar.zst +checksums.txt +assertions.yaml +``` + +manifest 至少记录 dataset 版本、source schema、目标 schema、生成 commit、storage identity、项目/会话/文档/run 数量、文件总数和 SHA、脱敏状态、过期时间;`assertions.yaml` 记录迁移后必须成立的版本、状态、正文 hash、序列与权限断言。 + +二进制 dump/状态包不进 Git;仓库只保留 manifest schema、fixture builder、脱敏规则、选择规则和非敏感断言。实际包放受控备份目录或对象存储。 + +## 每次发布的数据轮换模型 + +```text +旧运行库/状态根(只读) + │ export + manifest + checksums + ▼ +迁移语料构建区(脱敏/裁剪/恢复验证) + │ + ├── oldest-supported corpus + ├── previous-release corpus + └── current demo/regression corpus + │ + ▼ +新数据库 + 新状态根(latest schema) + │ import selected datasets + ▼ +工程门禁 + 页面验收 + rebuild/reload + │ PASS + ▼ +切换运行 identity;旧卷 quarantine 7–14 天后销毁 +``` + +这比在原 dev 库上大规模 DELETE 更适合当前阶段:新库天然消除未知孤儿,导入过程本身又验证了备份、迁移、文件配对、序列和重载。 + +## 风险边界 + +- main 真实业务数据不能套用 dev 的 7–14 天策略;须先定义业务、合规、审计和用户删除规则。 +- 项目 143 等真实内容不能直接固化为仓库 fixture;应保留 hash/结构特征并脱敏重建。 +- migration corpus 不能只有 happy path,否则清场后会失去发现 legacy bug 的能力。 +- 任何清理必须先完成隔离 restore,并验证数据库与文件包属于同一 storage identity。 +- 错误 `/tmp` 数据根属于当前事故证据;在 split-brain 恢复报告签字前不纳入普通清理。 + +## 建议动作 + +- 采用 [运行数据生命周期与迁移语料整改方案](../../remediation/2026-09-14-runtime-data-lifecycle-and-migration-corpus-remediation.md)。 +- 首轮只处理 dev;test 改为短 TTL 隔离环境;main 仅盘点,不删除;shared KB 排除。 +- 先实现 dataset inventory/export/restore/verify,再执行蓝绿精简,不先写清理 SQL。 diff --git a/.doc/ops/short-term/2026-09-14-runtime-data-lifecycle-plan.md b/.doc/ops/short-term/2026-09-14-runtime-data-lifecycle-plan.md new file mode 100644 index 00000000..9a358b17 --- /dev/null +++ b/.doc/ops/short-term/2026-09-14-runtime-data-lifecycle-plan.md @@ -0,0 +1,56 @@ +--- +title: "运行数据精简与迁移语料库方案" +status: done +created: 2026-09-14 +updated: 2026-09-14 +owner: Codex +branch: fix/dev-runtime-data-root-guard +worktree: .worktrees/fix-dev-runtime-data-root-guard +mutex: infra-runtime-state +--- + +# 运行数据精简与迁移语料库方案 + +## 目标 + +评估及时清理旧数据建议的合理性,并设计可恢复、可迁移验证、可展示且不污染长期环境的数据生命周期方案。 + +## 范围 + +- dev/test/main 数据量、schema、项目/文档/run 关系与文件状态; +- 备份/恢复、选择性导出、迁移 corpus、蓝绿轮换; +- retention 分类、TTL、quarantine、GC 和验收门禁。 + +## 非目标 + +- 不执行 DELETE/TRUNCATE/drop volume; +- 不修改数据库、文件正文或容器; +- 不清理 main/shared KB; +- 不把现有项目 ID 清单视作删除授权。 + +## 步骤 + +1. [x] 只读统计三环境 schema、项目/关键表规模和 dev 文件规模。 +2. [x] 审计项目外键闭包、revision/CAS/workspace 孤儿风险。 +3. [x] 审计现有 backup/restore drill 能力与隔离缺口。 +4. [x] 制定数据分类、最小保留集、migration corpus 和蓝绿轮换方案。 +5. [x] 更新父整改、CURRENT、gap 与 remediation 索引。 + +## 验收标准 + +- [x] 明确说明建议合理的条件和不能替代 migration 的边界。 +- [x] 首轮 retain 建议基于能力覆盖,不按时间盲留。 +- [x] 方案包含备份配对、真实 restore、选择性导入、reload/rebuild、rollback 和延迟销毁。 +- [x] 本轮未实施破坏性操作。 + +## 相关链接 + +- Research: [../research/2026-09-14-runtime-data-retention-and-migration-corpus.md](../research/2026-09-14-runtime-data-retention-and-migration-corpus.md) +- Remediation: [../../remediation/2026-09-14-runtime-data-lifecycle-and-migration-corpus-remediation.md](../../remediation/2026-09-14-runtime-data-lifecycle-and-migration-corpus-remediation.md) +- Test report: 待用户批准实施后创建 + +## 证据 / 备注 + +- dev schema 33 / 366 projects / 主仓状态约 100MB;test schema 29;main schema 25。 +- `DELETE projects` 无法完整清理 task run、revision ledger、blob 与文件状态。 +- 首选新 green DB/state root 导入 retain allowlist,旧 blue 只读隔离后延迟销毁。 diff --git a/.doc/remediation/2026-09-14-dev-runtime-data-root-and-projection-remediation.md b/.doc/remediation/2026-09-14-dev-runtime-data-root-and-projection-remediation.md index 24b5d950..3e767829 100644 --- a/.doc/remediation/2026-09-14-dev-runtime-data-root-and-projection-remediation.md +++ b/.doc/remediation/2026-09-14-dev-runtime-data-root-and-projection-remediation.md @@ -73,7 +73,7 @@ last_error_code, next_retry_at, updated_at | Wave 2 Compose 解耦 | dev/test/main/shared compose 的可变 bind 全部改为绝对 state-root 变量;为 app/pi/cursor 添加 storage UUID/环境标签;CI 检查 `docker compose config` 不出现工作树内 `data/` | 从两个不同 source roots 渲染 config,数据挂载 source 完全相同;代码 build context 可不同 | | Wave 3 启动与 readiness | 引入文件/DB storage identity;readiness 增加 `storage_ready`、`storage_id_match`、runner mount/identity;部署后脚本核对 container labels + mounts + sentinel + active-doc projection 摘要 | 错误空根启动被拒绝;本次 split-brain 复现实验 `/ready` 必须 503,不能再显示 healthy | | Wave 4 投影状态机 | ledger read 与兼容 projection 解耦;实现 projection outbox、幂等 projector、missing 安全重建、fork 隔离和结构化状态/告警 | DB commit 后 kill -9、只读目录、磁盘满、延迟重试均不丢 head;恢复后自动 aligned;fork 不被覆盖 | -| Wave 5 数据治理 | 清理/标注 dev 中历史临时 `work_dir`;真实项目、测试 fixture、临时 runner 目录分 namespace;增加 orphan/missing/fork 定期巡检和保留策略 | active 非模板文档 projection 100% 可解释;测试临时路径不污染生产统计;巡检报告可追溯 | +| Wave 5 数据治理 | 按[数据生命周期与迁移语料子方案](./2026-09-14-runtime-data-lifecycle-and-migration-corpus-remediation.md)执行蓝绿精简;真实项目、demo、migration corpus、临时测试分 namespace;增加 orphan/missing/fork 巡检与 TTL | dev 常驻 6–10 个可解释项目;受支持旧 schema corpus 可重复迁移;测试临时路径不污染运行库 | | Wave 6 验收与回滚演练 | 工程测试、容器 rebuild/recreate、宿主重启、真实 UI 修改/刷新/重登、双用户冲突、真实 PI 修改、回滚演练 | 下述验收矩阵全 PASS,报告归档后才恢复 FEATURE-MATRIX `done` 和 gap PASS | ## 即时恢复 Runbook(批准实施后执行) @@ -135,4 +135,5 @@ last_error_code, next_retry_at, updated_at - Audit: [dev rebuild 从临时 worktree 挂载空数据根](../audit/2026-09-14-dev-runtime-data-root-split-brain.md) - Short-term: [dev runtime data root guard 诊断与设计](../ops/short-term/2026-09-14-dev-runtime-data-root-guard.md) +- Data lifecycle: [运行数据生命周期与迁移语料库](./2026-09-14-runtime-data-lifecycle-and-migration-corpus-remediation.md) - gap-matrix 行: `RUNTIME-DATA-ROOT-SPLIT-BRAIN` diff --git a/.doc/remediation/2026-09-14-runtime-data-lifecycle-and-migration-corpus-remediation.md b/.doc/remediation/2026-09-14-runtime-data-lifecycle-and-migration-corpus-remediation.md new file mode 100644 index 00000000..393de773 --- /dev/null +++ b/.doc/remediation/2026-09-14-runtime-data-lifecycle-and-migration-corpus-remediation.md @@ -0,0 +1,171 @@ +--- +title: "运行数据生命周期与迁移语料库整改方案" +status: planned +created: 2026-09-14 +updated: 2026-09-14 +--- + +# 运行数据生命周期与迁移语料库整改方案 + +## 背景 + +合理性和当前数据画像见[调研](../ops/research/2026-09-14-runtime-data-retention-and-migration-corpus.md)。本方案是 [dev 数据根与投影整改](./2026-09-14-dev-runtime-data-root-and-projection-remediation.md) Wave 5 的详细子方案。 + +目标不是“为了省事删数据”,而是把不可控的历史运行库转化为: + +- 少量可展示、可解释的当前数据; +- 少量可重复、可断言的迁移/回归语料; +- 大量自动过期的隔离测试数据; +- 可恢复后再销毁的旧卷。 + +## 目标 + +1. dev 常驻项目控制在 6–10 个,均有 owner、用途、数据类别和过期/固定理由。 +2. test 不再积累跨轮测试数据;每轮使用独立 DB + state root,PASS 即删,FAIL 短期保留。 +3. 每次发布同时验证 clean install、受支持旧版本升级、选择性数据导入、reload/rebuild 和 rollback。 +4. 数据库 dump 与文件状态根成对归档,具备 storage identity、SHA manifest 和自动断言。 +5. 清理不产生孤儿 snapshot/run/blob/workspace,不误删共享 blob,不接触未授权 main/KB 数据。 + +## 数据保留策略 + +| 环境 | 常驻内容 | 自动过期 | 明确保留 | 禁止事项 | +|---|---|---|---|---| +| dev | 3 个 workflow demo + 2–4 个当前 regression + 明确人工项目 | 普通 E2E 24h;失败运行 7 天;上一版 demo 14 天 | pinned 项目、当前/上一 release 对照 | 不按 ID/目录 mtime 直接删除;不把真实内容提交为 fixture | +| test | 无长期业务项目 | PASS 立即销毁;FAIL 3–7 天 | 最近 1 次失败环境用于排障 | 不连接 dev/test 共享库跑 destructive test | +| main | 真实业务/正式展示 | 暂不自动过期 | 由产品、审计、合规规则决定 | 本方案不授权清理或测试写入 | +| shared KB | 法规知识库 | 独立策略 | 现有 KB 备份体系 | 不随项目数据轮换 | + +## 数据标识模型 + +新增数据集注册表或等价 SSOT: + +```text +dataset_id +class: operational_pinned | demo_current | regression_golden | + migration_baseline | ephemeral_test | quarantine +environment +source_schema / target_schema +source_commit +storage_identity +owner +retention_until +pinned_reason +contains_sensitive_data +manifest_uri / manifest_sha256 +status: building | verified | active | quarantined | expired | destroyed +``` + +项目至少增加 `dataset_id`、`data_origin`、`retention_until`、`pinned_at/pinned_reason`;自动测试创建项目时必须带 `ephemeral_test` origin 和 run namespace。未分类数据默认不可自动删除,而不是默认过期。 + +## 工具设计 + +### 1. `dataset inventory` + +只读生成候选清单:项目关系行数、doc/run/session IDs、workspace、CAS 引用、最后活动时间、生命周期、是否有 ledger/fork/missing、敏感级别、推荐动作。输出 JSON + Markdown;不接受模糊环境名。 + +### 2. `dataset export` + +按 dataset/project allowlist 导出关系闭包,不能只导 `projects` 表。必须同时打包: + +- project/chat/task/workflow/governance/document/revision/notification/outbox/audit 关系; +- 账本 blob 与受控/自由文档文件; +- file reference 指向的 CAS blob; +- workspace/agent session 中经 allowlist 认领的文件; +- schema/version/storage identity/count/SHA manifest。 + +导出后在隔离区执行脱敏;真实账号 token、auth sessions、credential、原始敏感附件默认剔除或替换。 + +### 3. `dataset restore --isolated-only` + +强制目标数据库名/端口/state root 满足隔离规则;拒绝 5433/5434/5435 及 `agent_system_dev|test|main`。实际执行 `pg_restore`,再导入文件包,不能只做 `pg_restore --list`。 + +恢复顺序:创建空库 → 恢复 source schema/data → 校验 source assertions → 执行 Goose up → 校验 target assertions → 重建 projection/index → restart/reload → 再次校验。 + +### 4. `dataset rotate` + +生成计划而不直接删除:`retain | replace | quarantine | destroy`。执行必须使用 manifest ID、期望 storage UUID 和确认短语;禁止 `--all`、模糊 glob、未解析环境变量。 + +### 5. `dataset gc` + +仅在数据库引用闭包和文件 manifest 都验证后执行: + +- 删除明确 dataset/project 的关系闭包; +- 清理无引用 document content blob/CAS blob; +- 清理已归属 workspace/session; +- `setval`/identity sequence 修复; +- 输出 before/after counts、孤儿检查与可恢复位置。 + +首轮 dev 推荐不在旧库运行 GC,而是蓝绿新建后切换;GC 用于后续小规模过期数据。 + +## 迁移测试矩阵 + +每个 release candidate 必须执行: + +| 测试轨 | 输入 | 验证重点 | +|---|---|---| +| Clean | 空 PostgreSQL + 空 state root | migrations 1→latest、官方 workflow seed、storage identity、ready | +| Oldest | `oldest-supported` corpus | 跨版本 backfill、约束、ID sequence、文档 legacy repair | +| Previous | `previous-release` corpus | 常规升级、API/UI 兼容、性能 | +| Hazard | 最小异常 corpus | hard-break、projection missing/fork、旧消息 scope、高 ID、pending run | +| Import | latest schema + selected demo/regression package | 关系闭包、文件 SHA、权限、通知、版本账本 | +| Reload | import 后 app/pi rebuild + restart + 宿主级重载 | storage identity、mount、task 恢复、正文/overlay | +| Rollback | 切换失败后接回 quarantine 旧卷 | RTO、旧 storage identity、无新写丢失 | + +迁移通过必须包含真实 restore,不接受仅跑 Goose 幂等测试;产品签字至少包含真实页面登录、项目列表、对话、文档打开/修改、刷新、退出重登和 rebuild 后恢复。 + +## 初次精简执行波次 + +| 波次 | 动作 | 完成判据 | +|---|---|---| +| D0 冻结与标注 | 先完成当前 split-brain 遏制;冻结 dev 写入;对 366 个项目 inventory;人工确认 pinned/敏感/owner | 100% 项目有建议动作;未分类项不删除 | +| D1 工具安全修补 | 移除备份脚本内默认凭证;backup 同时归档 DB+state;restore 强制 scratch 且真实恢复;加入 manifest/checksum/assertions | 恢复演练能从零创建隔离环境并通过 SHA/关系断言 | +| D2 构建 corpus | 建 schema 25、28/29、32/33 三个最小迁移包;构建 143 等价脱敏 hazard;选择 6173 current regression;6159 标记一周期过期 | 每包可重复生成/恢复,不依赖真实 main/test 数据 | +| D3 新建 green dev | latest schema 空库 + 固定新 state root;导入选中的 6–10 项;执行 projection/CAS/sequence/integrity 校验 | 无 orphan;active 文档 aligned;ready/storage identity PASS | +| D4 全链验收 | clean/oldest/previous/hazard/import/reload/rollback;真实页面和真实 PI 跑主链 | 报告区分工程、PG、PI、浏览器、restart/rebuild 证据 | +| D5 原子切换 | 切换 dev 到 green identity;原 blue DB/文件根转只读 quarantine | 新环境持续观察 24–72h,无新增 blocker,可一键回接 blue | +| D6 延迟销毁 | quarantine 满 7–14 天,再次 restore drill、差异确认、用户批准后销毁 | 记录销毁 manifest、范围、时间和不可恢复性;不得顺带清 main/KB | + +## 首轮建议保留/淘汰 + +### 保留 + +- 项目 143:临时 pinned,直到脱敏 legacy/hazard corpus 可替代。 +- 项目 6173:作为最新完整受控正文/版本/UI/restart 回归样本。 +- 项目 6159:作为 previous 对照保留一个发布周期,然后由 6173 替换。 +- 三正式工作流各一个新生成的确定性 demo;生成成功后不保留同类失败尝试。 +- 最近一次失败 E2E 的完整环境,最多 7 天,且与常驻 dev 隔离。 + +### 不直接保留 + +- 数百个无文档、无 run 或仅测试前置步骤的 planning/active 项目; +- 重复的 UI Round 中间项目和已由更新 PASS 覆盖的失败项目; +- 能由 unit/PG fixture 稳定重建的测试污染 workflow key、临时用户、session 和 run; +- 无引用 CAS/workspace,需在 mark-and-sweep 验证后删除。 + +该清单是初始建议,不是删除授权;最终 retain allowlist 应由 inventory 报告和用户确认生成。 + +## 验收标准 + +- [ ] dev 常驻项目 6–10 个,所有项目都有 dataset class/owner/retention。 +- [ ] 旧 366 项目对应的 blue DB+state 已成对备份并实际恢复成功。 +- [ ] green dev 从空库建成,选择性导入后 DB/file/storage UUID 一致。 +- [ ] 三个 migration baselines 与 hazard corpus 均能升到 latest 并通过断言。 +- [ ] 无 orphan task run、revision snapshot/version/event/report、CAS blob 或 workspace。 +- [ ] 项目 143/6173 页面打开、修改、刷新、重登、rebuild 后恢复 PASS。 +- [ ] 新测试数据带 TTL,PASS 后自动销毁,失败数据按策略到期。 +- [ ] test/main/shared KB 未被误操作;所有破坏性动作有精确 manifest 和延迟销毁记录。 + +## 不建议的方案 + +- 每次直接 `docker compose down -v` 再凭记忆重建:无法证明保留数据和文件配对完整。 +- 在 dev 库中写一份巨型级联 DELETE:当前关系与文件引用复杂,容易留下孤儿或误删共享 blob。 +- 只保留最新时间的项目:会丢失最有价值的旧 schema/hazard 覆盖。 +- 把整份真实旧库永久当 migration fixture:迁移慢、不可重复、可能含敏感数据。 +- 修改历史 Goose migration 迎合新空库:已发布迁移不可重写;修正必须新增 migration。 + +## 相关链接 + +- Research: [运行数据精简、迁移语料与演示数据保留策略](../ops/research/2026-09-14-runtime-data-retention-and-migration-corpus.md) +- Parent remediation: [dev 数据根隔离与投影自愈](./2026-09-14-dev-runtime-data-root-and-projection-remediation.md) +- Short-term: [运行数据生命周期方案](../ops/short-term/2026-09-14-runtime-data-lifecycle-plan.md) +- gap-matrix: `RUNTIME-DATA-ROOT-SPLIT-BRAIN` diff --git a/.doc/remediation/INDEX.md b/.doc/remediation/INDEX.md index 1ef2f73f..320fe23d 100644 --- a/.doc/remediation/INDEX.md +++ b/.doc/remediation/INDEX.md @@ -4,6 +4,7 @@ |------|------| | [gap-matrix.md](./gap-matrix.md) | 发布缺口 SSOT | | [2026-09-14-dev-runtime-data-root-and-projection-remediation.md](./2026-09-14-dev-runtime-data-root-and-projection-remediation.md) | 临时 worktree 错挂 dev 数据根、storage identity、readiness 与 projection outbox 系统整改 | +| [2026-09-14-runtime-data-lifecycle-and-migration-corpus-remediation.md](./2026-09-14-runtime-data-lifecycle-and-migration-corpus-remediation.md) | dev/test 数据精简、migration corpus、蓝绿换库、TTL 与延迟销毁方案 | | [2026-09-14-workflow-plan-409-frozen-and-optional-duties-remediation.md](./2026-09-14-workflow-plan-409-frozen-and-optional-duties-remediation.md) | 项目设置 409 冻结态守卫 + 非必需文档三权全有或全无 + 成员/门禁/权限一致性 | | [2026-09-14-controlled-content-canonical-hash-remediation.md](./2026-09-14-controlled-content-canonical-hash-remediation.md) | 项目 143 正文 canonical/raw 哈希漂移、错误语义与重复 hydration 整改 | | [2026-09-13-document-revision-reviewer-duty-sync.md](./2026-09-13-document-revision-reviewer-duty-sync.md) | UI-01 已分配 B=reviewer,受控文档 reviewer_id 硬编码 2,矩阵降为 viewer | diff --git a/.doc/remediation/gap-matrix.md b/.doc/remediation/gap-matrix.md index ddc172c2..30d3066c 100644 --- a/.doc/remediation/gap-matrix.md +++ b/.doc/remediation/gap-matrix.md @@ -57,7 +57,7 @@ | ID | 描述 | 状态 | 证据 | 计划动作 | |---|---|---|---|---| -| RUNTIME-DATA-ROOT-SPLIT-BRAIN | dev rebuild 从临时集成 worktree 解析 `./data/dev`,app/pi/cursor 挂到空 `/tmp` 数据根,而 PostgreSQL 沿用原持久卷;100 条非模板记录在当前容器根抽样均 missing,health/ready 仍 200 | **FAIL / CRITICAL** | [audit](../audit/2026-09-14-dev-runtime-data-root-split-brain.md)。项目 143 主仓文件、DB、ledger head SHA 一致,容器内同路径不存在;Compose working dir 与三容器 mount source 均为 `/tmp/as-dev-wf409-merge` | [remediation](./2026-09-14-dev-runtime-data-root-and-projection-remediation.md)。先占槽冻结/差异保全/恢复固定根,再实施绝对 state root、storage identity、readiness 和 projection outbox;恢复前禁止用 dev healthy 或文档 E2E 签字 | +| RUNTIME-DATA-ROOT-SPLIT-BRAIN | dev rebuild 从临时集成 worktree 解析 `./data/dev`,app/pi/cursor 挂到空 `/tmp` 数据根,而 PostgreSQL 沿用原持久卷;100 条非模板记录在当前容器根抽样均 missing,health/ready 仍 200 | **FAIL / CRITICAL** | [audit](../audit/2026-09-14-dev-runtime-data-root-split-brain.md)。项目 143 主仓文件、DB、ledger head SHA 一致,容器内同路径不存在;Compose working dir 与三容器 mount source 均为 `/tmp/as-dev-wf409-merge` | [runtime remediation](./2026-09-14-dev-runtime-data-root-and-projection-remediation.md) + [data lifecycle](./2026-09-14-runtime-data-lifecycle-and-migration-corpus-remediation.md)。先恢复固定根,再以蓝绿新库、最小迁移 corpus 和延迟销毁精简 dev;恢复前禁止用 dev healthy 或文档 E2E 签字 | | WORKFLOW-PLAN-FROZEN-OPTIONAL-DUTIES | active 项目仍展示可编辑职责表单,409 提示在长表单视口外;现有规划又不支持非必需文档“三权全空”,且后端缺少职责人在任成员复核 | **PASS(设置页)** | [audit](../audit/2026-09-14-workflow-plan-409-frozen-and-optional-duties.md);[test-report](../test-reports/2026-09-14-workflow-plan-409-frozen-and-optional-duties-test-report.md)。项目 143 只读 frozen、A full+none 激活、B partial 不发 PUT、C 零治理拒绝、双标签转 frozen、成员无配置入口、刷新后 143 仍 frozen | 真实 PI 生成 full/none 并走审批/阶段不阻塞未纳入本轮页面矩阵,不作为本 gap 关闭的替代证据,另立项 | | DOC-CONTENT-CANONICAL-HASH-DRIFT | 旧受控文档 bootstrap 裁剪 Markdown 双空格硬换行并将 canonical SHA 写入账本/DocGov,但未同步文件;正文读取把完整性冲突误报 404,lease/list sync 又放大并制造刷新后加载死锁 | **PASS(真实 UI)** | [audit](../audit/2026-09-14-project143-controlled-content-404.md);[UI report](../test-reports/2026-09-14-controlled-content-ui-acceptance.md)。代码已合 dev、schema 32、项目 143 定向 `migration_repair`;项目 143 `clean-run3` 与新项目 `full-chain-final` 主链及 restart 全部纯页面 PASS,目标 404=0 | [remediation](./2026-09-14-controlled-content-canonical-hash-remediation.md)。隔离 `TestReconcile_LegacyRepair_PG` 未执行,按用户“本轮只允许页面测试”的边界保留为工程测试债,不作为本轮 UI PASS 的替代证据 | | CHAT-HISTORY-REFRESH | 工作流激活后刷新,对话正文被阶段过滤器清空,但分类数量与锚点仍按全量返回 | **PASS** | [test-report](../test-reports/2026-09-13-chat-history-refresh-test-report.md);代码:`message_scope.go`、`chat_history_auth.go`、goose 00026/00027 | 真实 PI 刷新 E2E 待 dev 容器补录(自动化/PG 已 PASS) | diff --git a/.doc/status/FEATURE-MATRIX.md b/.doc/status/FEATURE-MATRIX.md index 43cc436d..d4799dc0 100644 --- a/.doc/status/FEATURE-MATRIX.md +++ b/.doc/status/FEATURE-MATRIX.md @@ -25,7 +25,7 @@ | 文档版本与修改认知 | 智能体版本边界、人工修订标记、任意版本比较、变更报告与负责人通知 | partial | [管理测试](../test-reports/2026-09-13-document-revision-management-test-report.md);[运行时 UI Round20](../test-reports/2026-09-14-document-revision-runtime-ui-test-report.md);[运行时审计](../audit/2026-09-13-document-revision-runtime-404.md);[ADR](../adr/2026-09-13-document-version-boundary.md) | **运行时 UI PASS**(6159 / V3/r2)。仍 `partial`:change report=`fallback`(真实 diff+lineage,非完整 PI 叙事)。系统级 `CHAT-INTENT` 见 gap-matrix | `docgov` | | 前端工作台 | 三栏 + 块文档 + SSE | partial | [test workbench](../test-reports/2026-09-08-three-column-workbench-and-block-document-test-report.md);[现场专项审计](../audit/2026-09-13-conversation-intent-runtime-state.md) | 错误卡片/任务进度/文档 busy 状态刷新恢复与人工抽检待完成 | `web` | | PI Runner / 配置链 | pi-agent + MiniMax 真实链路 | done | [test piagent](../test-reports/2026-09-13-codex-audit-p0-remediation-test-report.md);[container-env](../test-reports/2026-09-13-container-env-configuration-test-report.md) | — | `pi-agent` | -| 三环境运维 | dev/test/main + 共享 KB | partial | [PROJECT.md](../../PROJECT.md) §4;[数据根 split-brain 审计](../audit/2026-09-14-dev-runtime-data-root-split-brain.md) | dev app/pi/cursor 当前错挂 `/tmp` 空数据根且 readiness 假阳性;同类相对 bind 设计覆盖 test/main,须完成绝对 state root 与身份门禁 | `infra` | +| 三环境运维 | dev/test/main + 共享 KB | partial | [PROJECT.md](../../PROJECT.md) §4;[数据根 split-brain 审计](../audit/2026-09-14-dev-runtime-data-root-split-brain.md);[数据生命周期方案](../remediation/2026-09-14-runtime-data-lifecycle-and-migration-corpus-remediation.md) | dev 当前错挂 `/tmp` 空数据根且 readiness 假阳性;须完成绝对 state root/身份门禁,并以蓝绿换库将 366 个混杂项目收敛为 demo/regression/migration corpus + TTL 测试数据 | `infra` | | CI / E2E | PG 集成 + 真实 PI E2E | partial | [gap-matrix BUG-08](../remediation/gap-matrix.md);[test pg-ci](../test-reports/2026-09-12-pg-ci-soak-e2e-test-report.md);[运行时 UI Round20](../test-reports/2026-09-14-document-revision-runtime-ui-test-report.md) | CI `TEST_DATABASE_URL` 隔离库仍缺;文档运行时真实 UI 已按 UI_PHASE 分文件且 post-restart 断言最终 A1 正文。`-race` 全包并行 TempDir flake 为基建残留 | `ci` | ---