Add bounded context governance and task plan

This commit is contained in:
2026-08-20 15:15:16 +08:00
parent 2c814634c3
commit d4dec05c37
9 changed files with 2659 additions and 0 deletions

View File

@@ -0,0 +1,214 @@
# LinuxCNC Web/WASM 上下文治理与最小任务目录
**状态**:执行规范 v1.0
**适用基线**:LinuxCNC `2.10.0~pre0`;实际版本由 context lock 冻结
**生成器**:[`scripts/context_packet.py`](../scripts/context_packet.py)
**测试**:[`scripts/test_context_packet.py`](../scripts/test_context_packet.py)
本文件只解决两个问题:任务如何拆到可以持续接续的大小,以及一次任务交接究竟允许携带什么上下文。架构、功能范围、源文件关联和发布门禁分别以[技术路线](linuxcnc-web-wasm-technical-roadmap.md)、[源程序关联目录](linuxcnc-web-wasm-source-map.md)、[覆盖矩阵](linuxcnc-web-wasm-simulation-coverage.md)和[执行与交付策略](linuxcnc-web-wasm-execution-strategy.md)为准。本文件不复制这些文档的内容。
## 1. 不变量
1. 一个任务只有一个主工作流、一个里程碑、一个可验证结果和一个回滚点。跨三个以上工作流必须拆分。
2. 一个上下文包只有固定八段:`header`、`baseline`、`scope`、`contracts`、`evidence`、`risks`、`next`、`forbidden`。禁止追加 `history`、聊天记录或完整日志段。
3. 默认 profile 为 `feature`(4,096 tokens/16 KiB);里程碑任务才使用 `milestone`(8,192 tokens/32 KiB)。`doc` 和 `contract` 只在确有需要时使用。
4. `total_bytes` 同时限制序列化包和选中证据负载:`context_bytes = packet_bytes + selected_evidence_bytes`。`evidence_bytes` 是独立的证据总量上限,不能用文件数量替代。
5. 证据在生成阶段筛选。可选证据被排除时必须记录稳定 `reason_code`;必需证据无法容纳时生成失败,不输出部分成功包。
6. 交接只携带最新包、context lock 摘要、受影响 manifest ID 和可重跑命令。完整日志、golden 和差异报告只通过路径、大小和哈希引用。
### 1.1 包的分层读取
任务执行者按以下顺序读取,读到足够完成任务即停止:
| 层 | 内容 | 何时读取 | 预算归属 |
|---|---|---|---:|
| L0 | `context_id`、源码/工具链/schema 摘要、任务账本状态 | 每次开始和恢复 | `baseline` |
| L1 | 本任务目标、非目标、直接契约、受影响 manifest | 每次执行 | `header`/`scope`/`contracts` |
| L2 | 通过/失败测试摘要、差异首点、回滚点、下一步 | 执行中或交接 | `evidence`/`risks`/`next` |
| L3 | 完整日志、源码全文、golden 原件 | 只有需要定位时按路径读取 | 不进入包 |
L3 证据候选必须先给出 `path`、`bytes`、`sha256`、`kind`、`priority`、`required`;生成器按照必需、优先级、路径排序。读取清单不能包含未经过预算选择的路径。
## 2. 最小任务契约
任务描述必须能在一屏内完成审查,并使用以下字段。字段值是摘要或引用,不复制大段背景:
```yaml
id: INV-06a
title: 生成上下文包骨架
owner: WS-0
milestone: M0
profile: feature
objective: 固定八段包和稳定 packet_id
non_goals: [证据内容读取, manifest 扫描]
inputs: [context-lock.json, task-summary.json]
contracts: [context_packet.v1]
outputs: [packet.json]
tests: [test_context_packet.test_skeleton]
rollback: 删除生成物,保留输入锁
next: INV-06b
```
`objective` 必须是可观察结果;`non_goals` 防止任务吸收邻近工作;`inputs/contracts` 只列直接依赖;`outputs/tests` 必须能由 CI 重跑;`next` 最多三项。任务完成还需更新 manifest 状态和证据索引,但不把这些历史复制回包内。
## 3. 最小任务目录
下面的任务是执行单元,不是新的功能范围。原有大任务保留为父任务;实现时使用子任务 ID。每个子任务只拥有一条主要产物和一组直接测试。
### 3.1 M0:基线、清单和参考格式
| ID | 单一结果 | 直接输入 | 依赖 | Profile |
|---|---|---|---|---|
| INV-01a | 文档能力来源索引 | docs、source map | 无 | doc |
| INV-01b | 源码导出符号索引 | `src/emc/**`、`src/hal/**` | INV-01a | feature |
| INV-01c | 配置资源索引 | `configs/sim/**` | INV-01a | feature |
| INV-01d | 测试用例索引 | `tests/**`、`unit_tests/**` | INV-01a | feature |
| INV-02a | 规范化 source ID 和哈希 | INV-01a..d | contract |
| INV-02b | 依赖闭包和孤儿报告 | 规范化来源 | INV-02a | feature |
| INV-03a | context lock 文件 | 版本、工具链、schema | INV-02a | contract |
| INV-03b | context lock 校验器 | context lock | INV-03a | doc |
| INV-04a | native runner 输入接口 | sim 配置、测试索引 | INV-01c,d | contract |
| INV-04b | golden JSONL schema | runner 输入接口 | INV-04a | contract |
| INV-04c | 首个 divergent tick 报告 | native 输出 | INV-04b | feature |
| INV-05a | source→feature→task 图 | manifest、协议 | INV-02b | feature |
| INV-05b | 差异报告字段校验 | golden、manifest | INV-04b、INV-05a | doc |
| INV-06a | 固定八段包骨架 | context lock、任务摘要 | INV-03a | feature |
| INV-06b | 证据预算选择 | 候选证据清单 | INV-06a | feature |
| INV-06c | 排除原因和必需项失败 | 预算选择器 | INV-06b | doc |
### 3.2 M1:WASM 核心和最小运行闭环
| ID | 单一结果 | 直接输入 | 依赖 | Profile |
|---|---|---|---|---|
| CORE-01a | 独立构建目录和入口 | 编译锁 | INV-03a | contract |
| CORE-01b | 最小 posemath 编译 | posemath 源文件 | CORE-01a | feature |
| CORE-01c | TP/解释器最小链接 | TP、rs274 依赖 | CORE-01b | feature |
| CORE-02a | `sim_create/destroy` ABI | ABI 草案 | CORE-01a | contract |
| CORE-02b | `sim_load` 工作区入口 | INI/G-code 路径 | CORE-02a、FS-01a | feature |
| CORE-02c | `sim_step` 固定 tick | 状态结构 | CORE-02a | feature |
| CORE-02d | snapshot 导出/导入 | snapshot schema | CORE-02c | contract |
| CORE-02e | 错误码和行号映射 | rs274 错误 | CORE-01c | doc |
| RT-01a | 单会话 tick 队列 | `sim_step` | CORE-02c | feature |
| RT-01b | pause/abort/单步状态机 | tick 队列 | RT-01a | feature |
| FS-01a | 虚拟 POSIX 路径规则 | workspace 约束 | INV-02b | contract |
| FS-01b | open/read/write/stat | POSIX 规则 | FS-01a | feature |
| COM-01a | message envelope/schema | ABI 和错误码 | CORE-02a | contract |
| COM-01b | 命令 ack/result 路由 | envelope | COM-01a、RT-01a | feature |
| FE-01a | AppShell 和只读状态页 | protocol mock | COM-01a | doc |
| FE-01b | WorkerClient 超时/取消 | ack/result | COM-01b | feature |
### 3.3 M2-M3:核心行为、设备和恢复
| ID | 单一结果 | 直接输入 | 依赖 | Profile |
|---|---|---|---|---|
| CORE-03a | 基础 G/M 解释 golden | rs274 源和样例 | CORE-01c、INV-04b | feature |
| CORE-03b | O-word/参数/循环 | 解释器状态 | CORE-03a | feature |
| CORE-03c | remap 调用边界 | remap API | CORE-03b、PY-01a | contract |
| CORE-04a | 直线/圆弧 canonical | TP 源 | CORE-01c | feature |
| CORE-04b | 速度/加速度/拐角 | TP 配置 | CORE-04a | feature |
| CORE-05a | NML 命令/状态最小映射 | NML 消息清单 | CORE-02a、COM-01a | contract |
| CORE-05b | Task 状态快照 | NML 映射 | CORE-05a、CORE-02d | feature |
| CORE-06a | homing/软限位 | motion 状态 | CORE-02c | feature |
| CORE-06b | following error/急停 | motion 状态 | CORE-06a | feature |
| CORE-07a | trivkins 姿态 | kinematics ABI | CORE-02d | feature |
| CORE-07b | 非 trivkins 能力注册 | kinematics 清单 | CORE-07a | feature |
| CORE-08a | 工具表解析和快照 | tooldata 源和样例 | CORE-02b、FS-01b | feature |
| CORE-08b | 主轴/换刀/IO 状态 | iotask 消息 | CORE-05a、CORE-08a | feature |
| RT-02a | HAL pin/signal 图 | HAL 语法 | CORE-02c | feature |
| RT-02b | thread/function/addf 顺序 | HAL 图 | RT-02a | feature |
| RT-03a | 主轴/编码器/探针模型 | 虚拟设备 schema | RT-02b | feature |
| RT-03b | 限位/换刀故障注入 | 设备模型 | RT-03a | feature |
| RT-04a | ClassicLadder 解析 | ladder 输入 | RT-02a | feature |
| RT-04b | scan/寄存器/IO 顺序 | ladder 模型 | RT-04a、RT-02b | feature |
| FS-02a | journal prepare/commit | POSIX 工作区 | FS-01b | contract |
| FS-02b | 损坏记录和配额错误 | journal | FS-02a | feature |
| FS-03a | checkpoint 基线 | snapshot ABI | CORE-02d、FS-02a | feature |
| FS-03b | 增量重放和迁移 | checkpoint/journal | FS-03a | feature |
| PY-01a | Pyodide `linuxcnc/hal` 模块 | Python API 清单 | CORE-03a、FS-01b | feature |
| PY-01b | 资源/权限错误 | 虚拟模块 | PY-01a | doc |
| PY-02a | remap/filter 生命周期 | Python 回调契约 | CORE-03c、PY-01a | feature |
| PY-02b | VCP pin 回调和隔离 | VCP descriptor | PY-02a、RT-02a | feature |
| COM-02a | TaskLedger prepare/commit | operation schema | COM-01b、FS-02a | contract |
| COM-02b | 确认丢失对账 | TaskLedger | COM-02a | feature |
| COM-03a | 完整快照发布 | snapshot schema | CORE-02d、COM-01b | contract |
| COM-03b | 轨迹/HAL 流背压 | stream schema | COM-03a、RT-02b | feature |
| COM-04a | NML→Worker 命令映射 | NML 映射 | CORE-05a、COM-01a | contract |
| COM-04b | 状态/错误顺序 golden | message bus | COM-04a、INV-04b | feature |
| COM-05a | 能力/限制注册表 | 全量 manifest | INV-02b、CORE-07b | contract |
| COM-05b | 未支持能力解释 | 能力注册表 | COM-05a | doc |
### 3.4 M4-M5:前端、回归和发布
| ID | 单一结果 | 直接输入 | 依赖 | Profile |
|---|---|---|---|---|
| FE-03a | 工程选择/租约 | workspace API | FS-03b、COM-02a | feature |
| FE-03b | 刷新/Worker 重启恢复向导 | recovery events | FE-03a、COM-02b | feature |
| FE-04a | 编辑器诊断和当前行 | interpreter events | CORE-03a、COM-01b | feature |
| FE-04b | 轨迹预览与 golden 差异 | trajectory stream | FE-04a、COM-03b | feature |
| FE-05a | MDI/run/pause/abort | command schema | RT-01b、FE-01b | feature |
| FE-05b | jog/home/override 释放保护 | motion commands | FE-05a、CORE-06a | feature |
| FE-06a | 工具/IO/报警面板 | device events | RT-03b | feature |
| FE-06b | 主轴/换刀/探针恢复 | IO panel | FE-06a、CORE-08b | feature |
| FE-07a | HAL pin 图和命令控制台 | HAL snapshot | RT-02a、COM-03a | feature |
| FE-07b | scope/Ladder/日志回放 | sampled streams | FE-07a、RT-04b | feature |
| FE-08a | 轨迹和姿态非空渲染 | snapshot/trajectory | CORE-04a、CORE-07a | feature |
| FE-08b | 毛坯、坐标和最终姿态 | render state | FE-08a、COM-03b | feature |
| FE-09a | VCP descriptor 权限 | Python/VCP schema | PY-01a、COM-01a | contract |
| FE-09b | VCP 生命周期和异常隔离 | VCP runtime | FE-09a、PY-02b | feature |
| FE-10a | 虚拟列表和消息统计 | UI streams | FE-04b、FE-07b | feature |
| FE-10b | 帧预算和录制回放 | performance events | FE-10a、FE-08b | doc |
| COM-06a | 通讯/离线/租约 E2E | protocol + workspace | COM-02b、FE-03b | feature |
| COM-06b | 背压/未知消息/重启矩阵 | protocol streams | COM-03b、COM-06a | feature |
| REG-01a | 单入口 configs/sim 回归 | manifest、native runner | INV-02b、INV-04a | milestone |
| REG-01b | 全入口差异汇总 | 单入口报告 | REG-01a | feature |
| REG-02a | 失败样本保留和分类 | tests/unit_tests | INV-04a | feature |
| REG-03a | 断网/崩溃/配额矩阵 | FS-02b、FS-03b | feature |
| REG-03b | 回放终点一致性 | 连续/恢复 golden | REG-03a | feature |
| REG-04a | 浏览器通讯和离线 | Playwright | FE-03b、COM-02b | feature |
| REG-04b | 性能 P95/P99 报告 | 浏览器矩阵 | REG-04a | doc |
| REL-01a | 许可证和兼容报告 | 全量 manifest | REG-01b、REG-02a | doc |
| REL-01b | 迁移/回滚/离线包 | 发布候选产物 | REL-01a、REG-03b | milestone |
父任务只有在所有直接子任务完成且证据链闭合后才能更新状态。子任务之间不得共享未版本化的临时结构;需要共享时先建立 contract 子任务。
## 4. 交接和恢复
### 4.1 正常交接
1. 从 context lock 和父任务摘要生成新的 `packet_id`;只填本子任务的八段。
2. 用候选证据的实际字节数调用生成器。生成前就排除 `E1`-`E5`,输出后只接受 `budget.packet_bytes <= byte_limit` 且 `packet_bytes + selected_evidence_bytes <= byte_limit`。
3. 完成一步就更新 `evidence`、`risks`、`next`;不追加旧包全文。
4. 提交正文只写 `Context-ID`、`Context-Packet`、子任务 ID、测试命令和证据路径。
### 4.2 工具失败或确认丢失
以 `operation_id` 查询任务账本:`verified` 步骤只引用原证据,`unfinished` 从最近 checkpoint 继续,`unknown` 先对账。无法对账时标记 `blocked`,保留包和产物,不重放可能产生副作用的操作。
### 4.3 拆分停止线
出现任一条件立即拆分,而不是扩大 profile:上下文包超过 profile 80%、候选证据超过证据预算 80%、任务同时修改两个独立契约、测试需要读取三个以上大日志、或 `next` 不能写成三项以内的动作。拆分后的父任务只保留依赖图和摘要。
## 5. CI 检查
CI 在生成阶段执行以下检查,校验器只做复核:
```text
packet JSON 可解析
固定八段存在且无额外段
packet_id/context_id 与任务账本一致
budget.packet_bytes == UTF-8 序列化字节数
budget.packet_bytes <= byte_limit
budget.packet_bytes + budget.selected_evidence_bytes <= byte_limit
selected_evidence_bytes <= evidence_byte_limit
selected_evidence_files <= evidence_file_limit
所有排除项都有 E1-E5 reason_code
required 证据无法容纳时命令失败且不写输出
```
最小回归命令:
```bash
python3 -m unittest discover -s scripts -p 'test_*.py' -v
```
本规范的目标不是把所有信息压进一个更大的包,而是让每个任务只携带完成当前结果所需的最小、可重建、可审计上下文。