Skip to content

Commit 7886fee

Browse files
AlexStocksOmX
andauthored
fix(resp): eliminate declaration-driven aggregate allocation (#406)
* docs(planning): define RESP allocation guardrails Record the approved parser resource-limit design, TDD execution steps, and the transition from merged PR #388 to the RESP-LIMITS-001 implementation card. Constraint: This commit changes planning and recovery-facing documentation only; runtime behavior remains unchanged. Confidence: High; the scope follows exact main source inspection and Redis 8.8.1 parser evidence. Scope-risk: Low; only task-specific design, plan, STATE, and KANBAN files are included. Tested: git diff --cached --check; placeholder scan; Requirement and task identifier scan. Not-tested: Runtime tests are deferred to the implementation commit. Co-authored-by: OmX <omx@oh-my-codex.dev> * fix(resp): bound aggregate parser allocations Reject aggregate declarations above the Redis 8.8.1 INT_MAX boundary and cap initial Array, Map, Set, and Push capacity at 1024 entries so unauthenticated input cannot directly request an unbounded Vec allocation. Add regression coverage for exact boundary overflow, i64 capacity overflow, and the maximum accepted declaration without changing existing null or incomplete-frame semantics. Constraint: This commit changes only the RESP parser and its in-file tests; bulk payload and connection buffer limits remain separate work. Confidence: High; the original test failed with capacity overflow and passed after the shared capacity guard was applied. Scope-risk: Low; normal aggregate parsing is unchanged and all four allocation sites use one private helper. Tested: Windows and WSL cargo test -p resp; Windows and WSL target Clippy; cargo fmt --all -- --check; git diff --check. Not-tested: Full workspace and process-level network suites were not rerun because no network, storage, Cargo, or server code changed. Co-authored-by: OmX <omx@oh-my-codex.dev> * fix(resp): bound aggregate nesting depth Reject aggregate nesting beyond 128 levels before entering Array, Map, Set, or Push parsing so capped per-layer allocations and the recursive call stack cannot still grow without bound. Add deterministic coverage for the 1024-entry capacity policy and the 128/129 nesting boundary, and correct the implementation plan exact-test commands and validation record. Constraint: Bulk payload limits and total per-connection parser buffer limits remain separate work; no network, authentication, Cargo, storage, or command behavior is changed. Confidence: High; the new nesting regression failed on the previous PR Head, passed after the shared depth guard, and an independent second review found no remaining finding. Scope-risk: Low; the depth is threaded only through the four existing recursive aggregate parsers and the guard returns through the existing protocol-error path. Tested: Windows and WSL cargo test -p resp (65 unit, 20 integration); Windows and WSL target Clippy; cargo fmt --all -- --check; git diff --check. Not-tested: Full workspace and process-level network suites were not rerun because no network, storage, Cargo, server, or authentication code changed. Co-authored-by: OmX <omx@oh-my-codex.dev> * fix(resp): avoid declaration-driven aggregate allocation Start aggregate containers empty so incomplete untrusted declarations cannot reserve element storage. Keep the Redis INT_MAX length check and the 128-level nesting guard, and measure parser-phase allocations in regression tests. Constraint: Scope remains limited to Issue #395 B1 and the five authorized RESP task paths. Confidence: High; the allocation regressions failed on the previous Head and pass with zero parser-phase allocation on Windows and WSL. Scope-risk: Actual payload size and total connection-buffer limits remain separate follow-up work. Tested: Windows and WSL cargo test -p resp; Windows and WSL cargo clippy -p resp --all-targets -- -D warnings -D clippy::unwrap_used; cargo fmt --all -- --check; git diff --check. Not-tested: Full workspace and native RocksDB suites because this change is confined to the resp crate. Co-authored-by: OmX <omx@oh-my-codex.dev> * docs(planning): record independent RESP allocation PR Update the active branch, PR number, publication history, and final-state instructions after the narrow verified fix moved to PR #406 instead of overwriting externally updated PR #404. Constraint: This commit changes only STATE and KANBAN publication records. Confidence: High; PR #406 and its initial Head were queried directly from GitHub. Scope-risk: None for runtime behavior; the two overlapping PRs still require maintainer reconciliation. Tested: cargo fmt --all -- --check; git diff --check; gh pr view 406. Not-tested: Runtime suites were not rerun because this commit changes planning documents only. Co-authored-by: OmX <omx@oh-my-codex.dev> --------- Co-authored-by: OmX <omx@oh-my-codex.dev>
1 parent cbc2895 commit 7886fee

5 files changed

Lines changed: 533 additions & 50 deletions

File tree

.planning/KANBAN.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
# Kiwi Kanban
22

3-
> 更新日期:2026-07-30
3+
> 更新日期:2026-07-31
44
>
55
> 当前里程碑:M1 Redis 8.8.1 Cache OFF compatibility foundation
66
>
7-
> 当前 task:PR `#388` implementation(`feat/rocksdb-build-accel-and-prd`);已验证远端 Base `0f8d96238860a5c29a5582e461e4cdeb974431b3`、Head `b47cb1eebe098e2d4d2d784020dc283a8d026d28`
7+
> 当前 task:`RESP-LIMITS-001` implementation(`codex/fix-resp-aggregate-allocation`);基线 `main` at `cbc28958f261ae049d67a8b4a9d904d794b37726`
88
>
99
> 当前运行模式:Cache OFF
1010
>
@@ -14,7 +14,7 @@
1414

1515
| ID | 工作项 | Requirement / Gate 关系 | 当前状态 |
1616
|---|---|---|---|
17-
| `PR388-001` | C/C++ sccache 构建接入、跨平台回归探针、PRD/用户故事及 review 一致性修复 | `REQ-STABILITY-003``REQ-WORK-001``REQ-WORK-003``REQ-WORK-005`;跨平台构建修复只维护 G6 CI 的可执行性与证据条件,不构成 Gate 通过证据 | 本地针对性验证通过并形成提交;远端发布状态和新 Head CI 结果以 PR/checks/threads 实时查询为准 |
17+
| `RESP-LIMITS-001` | 限制未认证 RESP Array/Map/Set/Push 声明长度、消除声明驱动预分配并限制嵌套深度 | `REQ-COMPAT-002``REQ-COMPAT-006``REQ-WORK-003` | 独立 PR `#406` 已创建;与宽范围 PR `#404` 重叠,零声明预分配修复已通过 Windows/WSL 验证和独立复审,待最终状态提交、push 和新 Head CI |
1818

1919
## Ready for a separate implementation task
2020

@@ -37,6 +37,7 @@
3737
| ID | 工作项 | Evidence | 状态 |
3838
|---|---|---|---|
3939
| `M1-001-T1` | Redis 8.8.1 exact compatibility manifest | PR `#372`;final Head `6a692bc195f96327296296977a100af301deaf01`;merge commit `9e91707d774ad367d682e23677dcef79ecb14338` | 已合并到 `main` |
40+
| `PR388-001` | C/C++ sccache 构建接入、跨平台回归探针、PRD/用户故事及 review 一致性修复 | PR `#388`;final Head `1ee8c916a55d03d02a250ed95af83712fa14a742`;2026-07-30 merged | 已合并到 `main` |
4041

4142
## Frozen unaccepted drafts
4243

@@ -89,7 +90,7 @@
8990

9091
## WIP 与授权规则
9192

92-
- 同一时间只允许一个 implementation card 处于 In Progress;当前为 `PR388-001`,planning/docs task 不得隐式持有 implementation card。
93+
- 同一时间只允许一个 implementation card 处于 In Progress;当前为 `RESP-LIMITS-001`,planning/docs task 不得隐式持有 implementation card。
9394
- 规划批准不授权修改 source、tests、build scripts 或 CI,也不授权 stage/commit/push 实现文件。
9495
- 从 planning 转 implementation 必须创建新 Codex task、TaskId、worktree、dirty allowlist 和 recovery checkpoint;不能只把 recovery mode 从 `planning` 改成 `implementation`
9596
- 冻结草稿不得覆盖、续写、清理或回退;后续实施只读参考并重新审计。

.planning/STATE.md

Lines changed: 43 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,46 @@
11
# Kiwi 当前状态
22

3-
> 更新时间:2026-07-30
3+
> 更新时间:2026-07-31
44
>
55
> 当前 task 类型:implementation
66
>
7-
> 当前 PR:`#388``feat/rocksdb-build-accel-and-prd`
7+
> 当前 PR:`#406``codex/fix-resp-aggregate-allocation`
88
>
9-
> 已验证远端快照:Base `main` at `0f8d96238860a5c29a5582e461e4cdeb974431b3`;Head `b47cb1eebe098e2d4d2d784020dc283a8d026d28`
9+
> 实现基线:`main` at `cbc28958f261ae049d67a8b4a9d904d794b37726`
1010
>
11-
> 状态:PR `#388` 在 2026-07-30 复检时为 OPEN;本轮 review fix 已形成提交,发布状态、checks 和 review threads 必须实时查询
11+
> 状态:独立 PR `#406` 已创建;零声明预分配修复已通过本地双平台验证和独立复审,最终 Head/checks 以 GitHub 实时查询为准
1212
>
13-
> 当前范围:修复 C/C++ sccache 的 Windows 编译器回归和重复 `target` 缓存,补充自动回归探针,并统一版本化 PRD、用户故事与项目状态
13+
> 当前范围:拒绝超出 Redis 8.8.1 整数边界的 RESP 聚合长度,消除 Array/Map/Set/Push 的声明驱动预分配,并限制递归嵌套深度
1414
>
15-
> Requirement 边界:`REQ-STABILITY-003``REQ-WORK-001``REQ-WORK-003``REQ-WORK-005`;跨平台构建修复只维护 G6 CI 的可执行性与证据条件,不构成任何稳定性 Gate 已通过的证据
15+
> Requirement 边界:`REQ-COMPAT-002``REQ-COMPAT-006``REQ-WORK-003`
1616
1717
## 当前目标
1818

19-
PR `#388` 是与 PR `#383` 规划任务分离的 implementation task。其既有范围是在 CI 与 `scripts/dev.sh` 中为 RocksDB C/C++ 编译接入 sccache,并新增由权威规划文档综合出的 PRD 与用户故事。本轮 review fix 处理 Windows compiler wrapper 回归、重复缓存、自动回归探针、文档 Requirement 映射、Hot Tier 授权边界和当前项目状态问题
19+
本 task 修复 Issue #395 B1 中已经由源码确认的未认证 RESP 聚合类型无界预分配问题。客户端声明长度不得触发 `Vec` 预分配;超出 Redis 8.8.1 `INT_MAX` 边界的声明返回协议错误,合法聚合容器只随成功解析出的元素增长,聚合递归最多为 128 层
2020

21-
本 task 不实现 Redis Oracle provenance,不接受旧六文件 Oracle 草稿,也不启动 Embedded Redis Hot Tier。PR `#388` 的合并、CI 通过或 M7 Ready 均不能替代 Oracle implementation task 或 Hot Tier implementation task 的单独授权
21+
本 task 不处理实际流入的超大 bulk 或连接累计 buffer 限额,不修改 PR #402 的文档,不处理 Issue #395 的其他条目,也不实现 Redis Oracle provenance 或 Embedded Redis Hot Tier
2222

2323
## 当前授权边界
2424

2525
允许:
2626

27-
- 在本轮 review fix 中修改 `.github/workflows/ci.yml``scripts/dev.sh``scripts/tests/test-dev-sccache-env.sh``docs/prd.md``docs/personas-and-user-stories.md``.planning/STATE.md``.planning/KANBAN.md`
28-
- 执行 Markdown、链接、Requirement/Decision ID、一致性和 Git diff 等只读检查
29-
- 记录已经发生并可验证的 PR/Base/Head 历史;瞬时 checks、threadsdirty ownership 继续实时查询
27+
- 修改 `src/resp/src/parse.rs`、本 task 的设计/计划`.planning/STATE.md``.planning/KANBAN.md`
28+
- 运行 resp crate 单测、Clippy、格式检查、Git diff 检查及与 changed surface 对应的验证
29+
- commit、push 并创建以 `main` 为 base 的独立 PR;发布后实时查询 checks 和 review threads
3030

3131
禁止:
3232

33-
- 修改 Cargo、生产源码、Oracle provenance 实现、Hot Tier 实现或其他未授权路径
33+
- 修改 Cargo、网络/认证逻辑、其他生产源码、PR #402 文档、Oracle provenance Hot Tier 实现
3434
- 在旧 `redis-8.8.1-stability-foundation` worktree 继续、暂存、提交、push、清理或回退六文件实现草稿。
3535
- 把旧草稿的绿色测试、审查或真实构建准备表述为方案 A 已实现。
3636
- 扩大到 Embedded Redis Hot Tier、Redis fork、动态库、loader、Cache ON 或组合发行实现。
37-
- 在未获授权时 commit、push、merge、rebase、Resolve 或回复 GitHub review thread。
37+
- merge、rebase、Resolve 或回复 GitHub review thread。
3838

3939
## 已确认决定
4040

4141
- PR `#383` 已于 2026-07-28 合并:final Head `42c16bef899385bd2e1b1e16e2e0202d4a614590`,merge commit `58030e1331655546ea4547a9a94efc493534ef7d`;它只完成 Oracle 方案 A 的规划闭环。
42-
- PR `#388` 是独立 implementation task,不得继承或隐式扩大 PR `#383` 的 Oracle 实施授权。
42+
- PR `#388` 已于 2026-07-30 合并;本 task 是从最新 `main` 创建的独立 implementation task。
43+
- RESP 聚合长度上限采用 Redis 8.8.1 的 `INT_MAX`;合法声明采用零预分配,容量只随成功解析出的元素增长。
4344
- `D011`:Redis Oracle required provenance 采用 verifier fresh-checkout independent rebuild 和 exact binary hash equality。
4445
- `D012`:规划 task 与实施 task 分离;规划批准不授权源码实现,提前产生的实现草稿冻结。
4546
- Redis 8.8.1 tag `8.8.1` / commit `77b6c308396c9700672390a210143a8496fb4b10` 是唯一兼容和 Oracle 基线。
@@ -60,11 +61,11 @@ PR `#388` 是与 PR `#383` 规划任务分离的 implementation task。其既有
6061
- 规划状态:方案 A 的 15 路径 planning-only Diff 已由 PR `#383` 合并;final Head `42c16bef899385bd2e1b1e16e2e0202d4a614590`,merge commit `58030e1331655546ea4547a9a94efc493534ef7d`
6162
- 实施状态:未在已接受边界中开始。
6263
- 实施入口:`docs/superpowers/plans/2026-07-28-redis-8.8.1-trusted-oracle-provenance.md`
63-
- 启动条件:另开专用于 Oracle provenance 的 implementation task,从包含本规划的 clean commit 创建新 worktree,保存新 TaskId 和 recovery checkpoint;当前 PR `#388` 不满足或替代该条件。
64+
- 启动条件:另开专用于 Oracle provenance 的 implementation task,从包含本规划的 clean commit 创建新 worktree,保存新 TaskId 和 recovery checkpoint;当前 RESP parser task 不满足或替代该条件。
6465

6566
## 冻结实现草稿
6667

67-
相关但不属于当前 PR `#388` dirty ownership:
68+
相关但不属于当前 RESP parser task dirty ownership:
6869

6970
```text
7071
Worktree:
@@ -98,22 +99,37 @@ D:\test\github\kiwi\.worktrees\redis-8.8.1-stability-foundation\.codex\recovery\
9899
- PR `#372` 的合并状态、final Head 和 `main` merge commit 已实时确认。
99100
- PR `#383` 已合并;其规划提交只涉及 15 个 planning/docs 路径,并从 Task 1 合并后的 `main` 重放,未带入 Cargo、脚本、CI 或实现路径。
100101
- 旧六文件草稿 worktree 已只读核对,并继续冻结。
101-
- PR `#388` 的远端审查快照为 Base `0f8d96238860a5c29a5582e461e4cdeb974431b3`、Head `b47cb1eebe098e2d4d2d784020dc283a8d026d28`;本轮 review fix 已形成提交,当前发布状态须通过 GitHub 实时查询。
102-
- `wsl.exe --cd /mnt/d/test/github/review/kiwi-pr-388/source -- bash scripts/tests/test-dev-sccache-env.sh`:7 个 Windows/Unix/compiler 场景全部 PASS。
103-
- WSL Python/PyYAML 解析 `.github/workflows/ci.yml`:8 个 job 可解析,手写 `actions/cache``target` owner 为 0,compiler regression probe 恰有 1 个 CI step。
104-
- 文档一致性探针:59 个使用中的 `REQ-*`、4 个 `D*` 均能在权威文件解析,Markdown 表格结构通过。
105-
- `git diff --check`:通过;暂存区为空。当前环境没有 `shellcheck``actionlint`,未执行这两项。
102+
- PR `#388` 已于 2026-07-30 合并,final Head `1ee8c916a55d03d02a250ed95af83712fa14a742`
103+
- 本 task 已确认 `RespParse` 在认证前可达;Array/Map/Set/Push 均把未受信任的 `i64` 长度直接传给 `Vec::with_capacity`
104+
- Redis 8.8.1 exact tag 的 multibulk parser 拒绝大于 `INT_MAX` 的声明值,并把初始 argv 分配限制为 1024。
105+
- TDD 红灯:原实现解析 `i64::MAX` 聚合头时发生 `capacity overflow`,回归断言失败。
106+
- 首版 Windows/WSL `cargo test -p resp`:62 个单元测试、20 个集成测试通过。
107+
- Windows 与 WSL `cargo clippy -p resp --all-targets -- -D warnings -D clippy::unwrap_used`:通过。
108+
- `cargo fmt --all -- --check``git diff --check`:通过。
109+
- 首版实现提交:`b10c85cd694032ae86f7a07a02d192142ab32d7f`;PR:`#404`。独立 review 前的远端 Head 为该提交,checks 当时仍在运行。
110+
- 独立 review 在 `94694d81173ad9443f903bf44881efcbdaae4700` 发现:重复最大合法聚合头仍可叠加每层 1024 槽位的预分配;测试侧分配探针实测单个合法头申请 73,754 字节,128 层未完成头申请 9,440,512 字节,后者每增加 10 个单字节分片会累计申请约 94 MB。
111+
- 分配 TDD 红灯:四种最大合法声明头的 allocation regression 在首个 Array 头以 73,754 字节失败;128 层 regression 以 9,440,512 字节失败。
112+
- 分配 TDD 绿灯:四种聚合声明改为 `Vec::new()` 后,同一组 2 个 allocation regression 通过,容量只由成功解析元素的 `push` 增长。
113+
- 深度 TDD 红灯:旧实现把 129 层完整 Array 嵌套解析为成功结果;exact 测试实际运行 1 个用例并按预期失败。
114+
- 深度 TDD 绿灯:统一 128 层门禁后,同一 exact 测试实际运行 1 个用例并通过。
115+
- 当前工作区 Windows 与 WSL `cargo test -p resp`:各 66 个单元测试、20 个集成测试通过;WSL 使用任务专属 Linux target。
116+
- 当前工作区 Windows 与 WSL `cargo clippy -p resp --all-targets -- -D warnings -D clippy::unwrap_used`:通过。
117+
- 当前工作区 `cargo fmt --all -- --check``git diff --check`:通过。
118+
- 零声明预分配修复已完成独立规格复审:生产实现无 Critical/Important;测试阈值最初可能放过小容量预分配的 Minor 已改为预留输入 buffer 后严格断言解析阶段零分配,并由同一审查者确认闭环。
119+
- 最终实现提交:`e82c4496484ee8d42694d950436b517bfe2669da`。原 PR `#404` 在本轮 push 前被外部更新为宽范围 Head `334a235a95c50ca1cdd71927e459a2c6ac5e5bb0`;未 force-push 覆盖,窄范围修复改由独立 PR `#406` 发布。
106120
- checks、review threads 和 PR 状态不在本文件中缓存;任何当前结论必须重新查询 GitHub。
107121

108122
PR `#383` 的结果只证明 Oracle 规划闭环,不证明方案 A 已实现;PR `#388` 也不改变该结论。
109123

110124
## 下一条安全动作
111125

112-
1. 对本轮七个 task-owned 路径执行 shell 回归、workflow YAML、Markdown、引用、Requirement/Decision ID、Git diff 和路径边界检查。
113-
2. 本轮 push 已获得单独授权;发布后重新查询新 Head 的 checks。Resolve 或回复 review thread 仍须对应的单独授权,不得把已发布提交表述为 CI 已验证内容。
114-
3. PR `#383` 的规划历史保持不变,旧六文件 Oracle 草稿继续冻结。
115-
4. 只有用户另开 Oracle provenance implementation task 后,才从包含方案 A 的 clean `main` 创建新 worktree、TaskId 和 recovery checkpoint,并先执行真实 Redis 双 checkout reproducibility 门禁。
116-
5. Hot Tier 继续 Frozen;Gate PASS 后仍须用户明确批准一个单独的 implementation task。
126+
1. 提交并 push PR #406 编号和分支状态对账。
127+
2. push 后重新查询最终 Head 的 checks、评论和 review threads;不得把 #404 或旧 Head 的 CI 结果作为 #406 的最终状态。
128+
3. 若最终 Head checks 未完成,只报告 pending,不给可 Merge 结论。
129+
4. 不 Resolve 或回复 #402/#404/#406 review thread,不 merge PR。
130+
5. PR `#383` 的规划历史保持不变,旧六文件 Oracle 草稿继续冻结。
131+
6. 只有用户另开 Oracle provenance implementation task 后,才从包含方案 A 的 clean `main` 创建新 worktree、TaskId 和 recovery checkpoint,并先执行真实 Redis 双 checkout reproducibility 门禁。
132+
7. Hot Tier 继续 Frozen;Gate PASS 后仍须用户明确批准一个单独的 implementation task。
117133

118134
## 恢复检查
119135

@@ -127,7 +143,7 @@ Get-Content -Raw docs\personas-and-user-stories.md
127143
if (Test-Path .codex\recovery\ACTIVE.md) { Get-Content -Raw .codex\recovery\ACTIVE.md }
128144
git status --porcelain=v2 --branch --untracked-files=all
129145
git diff --cached --name-only
130-
gh pr view 388 -R arana-db/kiwi --json state,baseRefOid,headRefOid,statusCheckRollup,reviewDecision
146+
gh pr list --repo arana-db/kiwi --head codex/fix-resp-aggregate-allocation --json number,state,baseRefName,headRefOid,statusCheckRollup,reviewDecision
131147
```
132148

133149
如果 branch、HEAD、task type 或 dirty ownership 与 recovery 记录不同,先报告差异,不得自动 checkout、restore、reset、stash、clean 或覆盖文件。

0 commit comments

Comments
 (0)