Repository navigation
fix(cli): bound periodic-report and content-ops JSON input - #6209
Conversation
periodic-report read its --*-json file or stdin in full, and content-ops read stdin in full, before parsing. Both now refuse input over 16 MiB before json.loads (loopx-project#6099, loopx-project#6089). - stdin is still read through the text stream, so its decoding is unchanged, but each chunk is charged by its encoded byte size; the reader stops at most one character past the budget. - periodic-report files are read as at most limit+1 bytes and then decoded as strict UTF-8, keeping the previous rejection of UTF-16, BOM-prefixed and invalid UTF-8 request files. - content-ops file inputs keep their current behavior; loopx-project#6089 scopes the bound to stdin. - regenerate the project registry I/O manifest for the four shifted periodic-report load_registry sites (line numbers only). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Lihua <78465742+LIHUA919@users.noreply.github.com>
loopx-agent
left a comment
There was a problem hiding this comment.
Reviewer: model_agent | gpt-6.1-sol | OpenAI | runtime_reported | reasoning_effort=xhigh
Exact reviewed head: 6209@3f0f4dfef1a1f6a78a62af9e6db2a156d8141a51; immutable base: be15bf4ffb3bf354fb255853a96f14b047874bb8. 已读五文件完整 diff、原调用者、两个 issue 和 #6100/#6091 的完整旧评审;按当前整体 PR 独立判断。
动机
通过文件、管道或嵌入式 main(argv) 输入 JSON 的周期报告和内容队列操作者。
以前输入会完整读入再解析;本次为报告文件和两类命令的 stdin 加上 16 MiB 保护,但嵌入式 UTF-16 或 utf-8-sig 文本流的 BOM 被逐块重复计算,恰好在上限内的合法请求被误拒绝。
普通 UTF-8 文件/管道和 StringIO 调用保留;超限在解析前拒绝。实际 16 MiB 的嵌入式有 BOM 文本流在 base 成功、head exit 1,仍需修复计数。
本轮限定既有 JSON 读取边界;content-ops 文件范围沿用原合同,不发送报告、不发布内容、不执行活跃配置写入。
独立规格来源(在实现之前读取):
spec_ref: https://github.com/loopx-project/loopx/issues/6099; https://github.com/loopx-project/loopx/issues/6089
spec_revision: 6099 updated 2026-10-10T07:37:20Z; 6089 updated 2026-10-10T07:01:25Z
以下 ID 用于标识原文没有编号的要求,不是新增 RFC 门槛。
- INPUT-FILE:#6099 的文件输入必须在解析前受限并清楚拒绝。当前有界二进制读取后严格 UTF-8 decode,真实文件 exact/over-limit 及编码反例成立。
- INPUT-STDIN:#6099/#6089 的 stdin 必须避免完整无界缓冲。普通 UTF-8 console 和文本 StringIO 的实际边界/超限拒绝成立。
- INPUT-COMPAT:#6091 原评审 和 #6100 原评审 要求保留原合法文本 main 调用者及文件 UTF-8 约定。文件与 StringIO 修复已独立验证;带 BOM 编码的嵌入式调用仍不满足,见下面的当前 blocker。
- INPUT-SCOPE:#6089 明确限定 stdin,不扩张为所有文件通用限制。真实 content-ops 文件 16 MiB+1 继续接受,符合原边界。
- INPUT-CENSUS:#6100 旧评审要求同步既有 registry IO 清单。四项已有记录只调整行号,当前原生语义检查通过。
改动思路
保留既有 CLI IO 适配器及下游 typed report/item owner,用局部读取器保护输入;不新增配置、权限、状态或能力。报告文件采用 cap+1 读取再按原来的严格 UTF-8 解码,避免旧尝试的自动编码检测漂移。
The current CLI IO adapters are sufficient. A bounded text reader preserves embedded callers and a strict UTF-8 file reader preserves the original decoding boundary. A global file policy would exceed content-ops issue scope; BOM accounting must be repaired within the reader.
当前 PR 的边界是既有读取器的大小保护与兼容性;最小修复是用连续编码状态计数字节,避免每个 chunk 重新生成 BOM,并保留文本/文件原来的解码约定。
复用调查:performance-diagnosis 的 loader 只处理有界二进制文件,external-research 使用另一上限且先读完整文本;均不能直接代表这里的兼容 stdin 合同。两个新增文本 helper 完全相同,修复时可以做小范围 transport 收敛,但两种能力的文件范围必须显式保留。不能为共享读取器顺便发明统一文件政策。
具体改动
必须修复的发现
[P2] Count BOM-bearing stdin as one continuous encoding stream — loopx/capabilities/periodic_report/cli.py:61,同样发生在 loopx/capabilities/content_ops/cli.py:64。
consumed += len(chunk.encode(encoding, errors)) 每次建立新 encoder。UTF-16 和 utf-8-sig 都会为每块重发 BOM(编码字节序标记),因此新计数不等于原 stdin 流的实际字节数。
独立真实公开入口 main(argv):使用 TextIOWrapper(BytesIO(raw), encoding=...),合法 report/queue 请求补空白至原始流恰好 16,777,216 字节;没有修改 MAX_INPUT_BYTES。两个命令在 immutable base 都 exit 0,在当前 head 都 exit 1 并返回 exceeds the 16777216-byte limit。UTF-8 对照组在两侧成功;更小边界测试也重现 UTF-16/UTF8-Sig 假阳性。
影响限定为明确传 argv 的嵌入式文本调用:shipped console entrypoint 会调用 pin_utf8_stdio(),本次独立 console 编码实验两侧都按其原 UTF-8 约定拒绝 UTF-16/BOM 字节,并没有证明 console 的相同兼容性回归。这个区别不消除既有 main(argv) 调用者的实际回归。
最小修复:在这两个读取器中保留连续 encoder 状态(含明确的最终 flush),或使用保留既有 decoder 的等价真实字节记账,避免逐块重复 BOM。不要通过删掉文本 fallback、改变文件编码规则或增大预算掩盖错误。回归用实际 main 入口测试 UTF-16/UTF8-Sig 的 below/exact/over-limit 与修复后恢复,并保留 console UTF-8、StringIO 控制组。
关键代码讲解
_read_stdin_text(periodic_report/cli.py:46):按剩余预算的四分之一读字符,使普通多字节文本不会先完整缓冲。文本 decoder 和 errors 沿用原流;当前问题位于其逐块编码记账,不是 report 状态机。_load_json_object(同文件:83):stdin 走上述读取器;文件读 cap+1、先拒绝超限,再严格 UTF-8 decode 和json.loads,最后沿用 dict 条件。原 command handler 的 profile/request/config 调用者继续复用它。_read_stdin_text/_load_json_object(content_ops/cli.py:49/75):同一字节保护覆盖原 stdin 读取调用;文件仍走原 UTF-8read_text。内容队列、item-transition、reference/聚合与 layout 参数的既有 owner 未改变。
生产增加 51 行;清单 4 项机械行号调整;测试增加 191 行。整个 PR 246 additions/7 deletions,不新增协议或 capability。新增测试比旧尝试更完整,覆盖 StringIO、UTF-8 多字节、strict UTF-8 文件和实际 subprocess,但其 UTF-8 fixtures 不会暴露 BOM encoder 的状态问题。
对主干的风险
独立 paired real-path harness 每侧 60 个调用,覆盖两能力的文件/stdin、正常/exact16 MiB/over-limit、空/非对象/坏 JSON、UTF16/BOM/坏 UTF8,以及显式 main 的文本 decoder。另有每侧 6 个 actual-cap 嵌入式调用和 6 个 console 编码调用。合法 report/queue 完整投影及哈希比较;超限坏 JSON 的 size error 先于解析;临时输入原字节不变,没有发送、内容发布或活跃状态写入。
旧评审三类问题不是凭作者声明销账:原合法 StringIO main 输入重新成立;报告文件保留 strict UTF-8,UTF16/BOM/非法 UTF8 两侧按原路径拒绝;当前 registry census 通过 full semantic smoke。但上述新的 INPUT-COMPAT 反例仍阻止本轮批准。
本地相关测试 head 90 passed / base 83 passed,无 skip;原生 premerge 5 项 direct、10 项 catalog、8 项 risk-profile 全通过,manual holds 为 0。主机 Node v24.21.0 下当前 TS/语义校验可执行,没有沿用作者旧环境 Node20 的失败归因。开发期语义 advisory 先执行,支持范围的新词汇候选为 0;空结果不证明兼容。
Ruff 两侧均只有同一个既有 E731 renderer lambda,从 base content_ops/cli.py:532 移到 head :553,语句和原因相同,不在本次读取器的因果路径;这是独立仓库清理/merge-readiness事项,不当成本次新增缺陷,也没有把 lint 写成全绿。初始测试命令引用不存在的路径而没有执行测试,已改为真实文件;100% 后历史 pytest 临时目录清理被中断,现已在独立 --basetemp 重跑相同 suites 并取得完整 exit 0。最初 console harness 假定输出沿用宿主 UTF-16 的错误已修正,当前结果明确保留 console UTF-8 边界。若含未知 note 或非 opaque source token 的合成内容条目被拒绝,两侧都拒绝;它们不作为合法内容恢复的证据。
没有查询、轮询或等待 GitHub CI。没有 default-off/opt-in 声明,没有新 actor lifecycle/权限/工作调度规则;这是强制输入拒绝条件,不能称为可忽略 guidance。新增限制通过 PR 说明、命名边界测试和明确 error 公开披露;无第一屏/新配置入口变化。
我的整体评价
REQUEST_CHANGES。两类读取器的保护和旧问题修复有实际价值,整体范围也合适,但同一合法、实际在预算内的嵌入式调用出现已复现回归,不能由当前绿色测试/canary覆盖。
未来相关重构检查:最近 owner 仍是这两个 IO adapters;连续编码记账是本 PR 必须完成的局部修复。相同 transport helper 可一起收敛,文件策略差异保留,不新增大框架、迁移格式或形式化 successor。修复后应重审整个 exact head、原文要求和正/反路径,不只跑最近一项反例。
English verdict: REQUEST_CHANGES — 6209@3f0f4dfef1a1f6a78a62af9e6db2a156d8141a51. INPUT-COMPAT remains unmet: stateless chunk.encode adds a BOM per chunk for UTF-16/UTF8-Sig, falsely rejecting valid embedded main(argv) inputs at the unchanged actual 16 MiB cap in both commands; the immutable base accepts them. Preserve decoder compatibility and use continuous byte accounting, with real-main boundary regressions. Console pins UTF-8 and is unaffected by this encoding-specific counterexample. Strict file decoding, StringIO, uncapped content file scope and census repair are independently verified. 90 head/83 base tests and all 5 direct/18 selected premerge checks pass; identical existing Ruff E731 is separate. No external delivery or GitHub CI was consulted.
Review of the bounded readers found that encoding each chunk on its own re-emits a byte-order mark per chunk for UTF-16 and utf-8-sig text streams. Embedded main(argv) callers passing such a stream at exactly the 16 MiB limit were refused although the stream fits. Keep one incremental encoder across all chunks (flushed at EOF) so the charge equals the stream's real byte size. Real main(argv) regressions cover UTF-8, UTF-16 and utf-8-sig one byte under, at, and one byte over the limit for both commands. Regenerate the registry I/O census for the shifted periodic-report line numbers. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Lihua <78465742+LIHUA919@users.noreply.github.com>
|
Thanks. The INPUT-COMPAT finding reproduced and is fixed in Fix (both readers): Regressions: Evidence:
Not re-run here: the Node-gated premerge canaries. This environment only has Node 20, so I am relying on your Node 24 run and CI for those. Helper placement: I kept the two helpers local rather than merging them into one shared transport helper, so this follow-up stays a single-purpose fix. If you would rather have them merged in this PR, I can do that. |
loopx-agent
left a comment
There was a problem hiding this comment.
Reviewer: model_agent; gpt-6.1-sol; OpenAI; runtime_reported; xhigh
Current exact head: 891ac8baae0b3a2c06137a94d323704776ba7ebb; base be15bf4ffb3bf354fb255853a96f14b047874bb8. Whole five-file PR reviewed independently.
动机
通过文件、管道或嵌入式 main(argv) 输入 JSON 的周期报告和内容队列操作者。 以前会先完整读入输入再解析;这次在报告文件和两类命令的标准输入上限制为16 MiB,超限时先返回清楚的大小错误。原先逐块重算 BOM 的错误也已修正,合法的带 BOM 文本在上限处仍能处理。 普通请求的报告/队列结果保持;超限输入在解析前拒绝;实际16 MiB UTF-8、UTF-16、带 BOM UTF-8 输入成功,缩小输入后重试成功。 本 PR 只修现有 JSON 输入边界;不改变下游报告/内容状态、发送权限、调度,也不为 content-ops 文件新增通用大小策略。
这对应 #6099 的报告文件/标准输入保护与 #6089 明确限定的内容标准输入问题。此前候选在 UTF-16、带 BOM UTF-8 的嵌入式调用中重复计算字节序标记,导致合法上限输入被拒绝;本轮重新核验整个 PR,同时验证这项修复,未继承旧结论。
规格快照:6099 updated 2026-10-10T07:37:20Z; 6089 updated 2026-10-10T07:01:25Z; pre-fix review 3f0f4d。兼容性要求另见原3f版本的具体评审。
改动思路
现有 capability CLI 的 Python I/O 适配器足以承担大小检查和编解码,不增加控制面、存储或权限 owner;复用标准库连续编码器修正 BOM 计数。 当前交付是既有读取器的大小保护和解码兼容性;两处文本读取器共享连续编码语义,报告文件保留严格 UTF-8,content 文件策略保持。
连续编码器跨所有 chunk 保留编码状态,EOF 时计入最终 flush;报告文件仅读取 cap+1 个原始字节,然后按原有严格 UTF-8 解码。console 入口原本固定 UTF-8,显式 main(argv) 可保留调用者 TextIOWrapper;两种边界分别测试。没有新增用户配置、命令或权限,因此现有前端/消息入口无需新增能力开关。
具体改动
- 两个
_read_stdin_text读取现有文本流,按编码后的字节累计,超限在json.loads前拒绝;当前使用一个codecs.getincrementalencoder,修掉逐块重新发出 BOM 的误计数。 periodic_report._load_json_object对文件实行16 MiB保护,保持 UTF-8、JSON object 和原来的错误转换。其 compose/profile/config/request 等现有调用者复用同一 loader。content_ops._load_json_object只给标准输入加保护;队列、item transition、layout 等既有调用者继续使用原来的类型化 owner,文件分支保持原行为。大小检查不授予发送、发布或 Goal 结算权限。- 两组测试补普通/临界/超限、StringIO、多字节和连续编码器案例;既有 registry I/O 清单只更新四个行号。总计5个文件 +314/-7,其中生产适配器59新增/3删除,测试251新增,没有新状态或通用框架。
按来源逐项验收:INPUT-FILE、INPUT-STDIN、INPUT-COMPAT、INPUT-SCOPE、INPUT-CENSUS 均已满足;这些标签对应未编号的 issue/兼容性要求,不是实现自行生成的验收。
对主干的风险
独立真实 CLI 使用原始报告/队列 owner,对 immutable base 与当前 head 运行相同60个案例。42个完整观察逐字相同,2个只差各自临时文件路径的非 object 错误,剩余16个为预期大小拒绝。正常/临界结果与严格文件解码保持;报告文件和两类 stdin 超限在解析前报大小错误,content 文件超限仍接受,避免把 stdin-only 问题扩成全局文件限制。
另外每侧26个真实 main(argv) 案例使用原始16 MiB限额:UTF-8、UTF-16、带 BOM UTF-8 在 below/exact/retry 成功;current head 的 over 被拒绝,缩小后能恢复进度。UTF-16 的 over 是一个完整字符即2字节,避免用截断编码制造无效反例。原3f版本的 source-pinned误拒绝证据保留,当前实际重放已通过。真实临时文件/文本流和原 owner 都参与,未替换后端或在活动 Goal 上故障测试。
当前353项相关测试通过,24项焦点测试是其子集;全 PR native canary 5项直接检查及18项选中检查通过,0 failure/manual hold,I/O 清单291 sites正确、先 advisory 后完整语义检查通过。Ruff 仍有一项既存 E731:base532/current557 是相同的 renderer lambda,未改其因果路径;独立记录为原有问题,不伪称所有 lint 通过。测试 harness 首次把中文放进受 opaque-token 限制的 content_ref,base/head 都正确拒绝;已修正 fixture并保留首失败,没有改产品规则。未查询/等待远端 CI。
我的整体评价
APPROVE。 对这项有界任务,效果预期正向:重复调用不会无界缓冲这些输入,合法编码不再被误拒绝,操作者可按清楚错误修正后继续。额外成本是局部 chunk 编码和两个小 helper,未引入持久状态、重复权限或更多操作步骤;未测实际 OOM 发生率、CPU收益或长期多 Agent 净成本,不作量化效率承诺。
未来维护 pass 发现两个读取 helper 的共享语义可在后续同边界变化时抽到小型 transport seam,并保留此次真实调用对照;现有规模与不同文件策略允许本次先保留,非阻塞建议,不新增仪式性任务。预算/作用范围/恢复均由现有 CLI owner 承担。
English verdict: APPROVE - 891ac8baae0b3a2c06137a94d323704776ba7ebb. The bounded-input task and BOM-accounting repair are verified through real paired CLI owners, actual16MiB below/exact/over/retry cases,353 related tests and5+18 premerge checks. Existing unrelated E731 remains disclosed; no CI, external effects or quantified long-run efficiency claim.
loopx-agent
left a comment
There was a problem hiding this comment.
Reviewer: model_agent | gpt-6.1-sol | OpenAI | runtime_reported | xhigh
精确 head:6209@3c7ac4f69d4a1696a641f5dbb4b947d40ea857fb;不可变基线:f7a5df016b8e0c99608427ee3b1e5a5556eb26d2。本次独立审查当前完整五文件 diff,不继承修复前或重基前的批准。
动机
通过文件、管道或嵌入式 main(argv) 输入 JSON 的周期报告和内容队列操作者。
以前大输入会完整读入再解析,可能耗尽内存;当前报告文件及两类命令的 stdin 在 16 MiB 边界拒绝超限,合法 BOM 文本流也不再被重复计费。
真实 16 MiB 的 UTF-8、UTF-16、utf-8-sig、UTF-32 文本流在上限内成功、超过上限拒绝;修正输入后原请求可继续。
本次限定既有 JSON 读取边界;content-ops 文件沿用原行为,不发送报告、不发布内容、不执行活跃配置写入。
改动思路
复用各 capability 的现有 IO 边界和严格解码,避免为一次读取修复增加协议、配置或第二个决策 owner。
两类 stdin 的有界读取、报告文件的有界严格 UTF-8 读取、四条现有 inventory 行号同步和对应回归构成当前完整边界。
入口仍是 CLI dispatch 或嵌入式 main(argv);读取完成后才交给原有 report/item 类型化规则。stdin 保留调用方的 text decoder,文件保留原严格 UTF-8。拒绝由原错误 envelope 返回,修正后重新执行原请求即可,不需要重新配置 Goal、扩大权限或人工同步状态。
考虑过共享二进制 loader,但它会丢失 StringIO 支持并可能扩大文件可接受编码。未来可把两个相同的 stdin 编码机制收敛为一个小内部 helper;本次保留局部 IO 边界,不引入通用文件策略或新兼容层。这个非阻塞简化建议不替代当前 BOM、读取上限和真实调用证据。
具体改动
规格在实现前读取:issue #6099 与 issue #6089。
spec_ref: https://github.com/loopx-project/loopx/issues/6099; https://github.com/loopx-project/loopx/issues/6089
spec_revision: 6099 updated 2026-10-10T07:37:20Z; 6089 updated 2026-10-10T07:01:25Z
原文没有编号验收 ID,使用实际标题:Expected behavior(#6099)implemented:有界读取、解析前清楚拒绝报告文件和 stdin;文件读取上限加一字节,decoded stdin 使用一个字符作为超限探针。Problem(#6089)implemented:内容命令只限制 stdin,不把文件读入改成统一全局策略。原严格文件解码及嵌入式文本流兼容性另由不可变基线对照核验。
完整 diff 为 +314/-7:两个 IO adapter、253 行回归以及四条现有 registry-I/O manifest 的行号同步。没有增加 schema、配置开关、UI、authority 或持久化规则。
关键代码讲解
periodic_report.cli._read_stdin_text:分块读当前 text stream,用同一个 incremental encoder 累计编码字节并在 EOF flush。BOM 只计一次,避免修复前每块重复收取 BOM 导致合法 exact-cap 请求被拒绝。periodic_report.cli._load_json_object:文件只读MAX_INPUT_BYTES+1,先拒绝超限,再严格 UTF-8 decode 和 JSON object 校验;不改成会自动接受 UTF-16 或 BOM 的json.loads(bytes)。content_ops.cli._load_json_object:只有-分支使用有界 stdin helper;原文件读取和各现有消费者继续使用原语义。
独立同一 harness 在基线和 head 各运行54组实际 CLI/嵌入式调用。41组完整输出 hash 相同;11组退出差异是预期超限拒绝,两组已超限且非法 JSON 的错误优先级改为 size error。以 issue 的拒绝要求运行固定 oracle 时,基线失败、当前 head 通过。输入构造复用原合法 request 类型;没有 mock 下游成功或编码计数结果。
对主干的风险
未发现当前阻塞问题。389项相关 capability/CLI/架构测试、5项 direct 和18项 native canary 检查、完整 semantic smoke 均通过。真实文件/管道覆盖正常、empty、array、malformed、非法 UTF-8、BOM 和超限;嵌入式四类 codec 覆盖真实16MiB下限、exact、over及拒绝后恢复。StringIO 的合法与拒绝路径也在现有回归中通过。
旧发现逐项复核:text-only stdin 没有被改成必须有 buffer;报告文件仍严格 UTF-8;已有 inventory site/分类完整保留;BOM 在本次当前 head 只收费一次。旧批准正文绑定的891ac8ba head不替代当前3c7ac4f完整审查。
保留一项既有 Ruff E731:同一个未修改 reference renderer lambda 在 base532/head557。相同命令、规则及表达式复现,不归因于本 PR。未放宽 lint、预算、inventory 或任何测试断言,未查询或等待 CI。
语义与 CI 对齐
复用现有 registry-I/O census owner,只同步四个已有 site 的行号;全树扫描通过。无新 shared vocabulary 或第二个状态决策源;semantic_alignment=aligned。输入上限是强制校验,不是建议。源码 advisory 无新支持的 vocabulary carrier,这个结果本身不证明语义等价。
stdin 经过 text decoder,探针最多读一个额外字符(本次验证的 codec 最多四字节);文件才是精确的一字节探针。未测试真实 Windows console device 或任意非常规有状态 codec,不宣称这个 helper 限制底层 decoder 的内部预取。没有新的安装/自动激活或 first-screen 改动。
我的整体评价
APPROVE,goal_achieved 指这次有界 IO 修复,未宣称完成父级 roadmap。long_horizon=improved、user_experience=improved:异常输入不再无限缓冲,合法输入与错误详情保持,拒绝后可恢复同一请求;没有多余配置、确认或权限变化。当前机制与问题规模匹配。已考虑共享 text helper 的有界简化,留作非阻塞维护建议,未要求无关迁移。评审不授予 merge 或 bypass 权限。
Motivation
Report and content-queue operators pass JSON through files, pipes or embedded main(argv). Previously an oversized source was buffered completely before parsing. The current head bounds report files and both stdin paths at16MiB, without repeatedly charging the BOM in otherwise legal embedded text streams. The same request succeeds again after correction. Content-ops file policy, report delivery, publishing and active configuration effects remain outside this repair.
Approach
The safeguard belongs to the existing capability IO adapters. It does not create a state or policy owner: accepted text still reaches the original typed report/item rules and failures use the existing CLI envelope. Text stdin retains its caller codec and errors; report files retain strict UTF-8. A binary-loader shortcut would lose text-only stream compatibility or broaden accepted file encodings. Consolidating the identical stdin mechanism into a small internal helper was considered as optional follow-up; a universal JSON loader or unrelated migration is unnecessary.
Concrete changes
The independent specification is issues6099 and6089 at the exact updated timestamps above, read before implementation. Their actual headings Expected behavior and Problem are implemented: bounded pre-parse refusal for report file/stdin and content stdin, with the latter's explicit file exclusion preserved. File intake reads cap+1 bytes; decoded stdin uses one extra character as its sentinel.
The full five-file change is +314/-7. _read_stdin_text uses one incremental encoder across all chunks and EOF flush; _load_json_object in periodic-report bounds binary intake before strict UTF-8 decoding; content-ops bounds only its stdin branch. Four existing census entries receive line-number updates. The linked exact-head symbols explain each behavior-bearing branch.
The same independent harness ran54 real CLI/embedded cases on each revision.41 full outputs match;11 exit changes implement the intended size refusal, while two malformed oversized diagnostics intentionally prioritize size. The fixed issue-derived refusal oracle fails on the base and passes on this head. Legal real16MiB UTF-8/UTF-16/utf-8-sig/UTF-32 inputs remain accepted at the cap. Tests construct inputs, not the postcondition under review.
Risks to main
No blocking finding remains.389 relevant tests,5 direct checks,18 native risk-selected checks and the full semantic smoke pass. Empty/array/malformed/invalid UTF-8/BOM inputs, oversized valid and malformed pipes/files, text-only stdin and retry after refusal were exercised. Each prior text-only, strict-file, census and repeated-BOM finding was independently reconciled at this current head.
The unchanged reference-renderer lambda still produces Ruff E731 at base532/head557 under the identical command and expression. No lint rule, scan, budget or assertion was relaxed. CI was not consulted. Existing vocabulary and registry-I/O ownership remain aligned; byte limits are enforced, not advisory. Native Windows console devices, arbitrary stateful codecs and decoder internal prefetch remain outside the evidence. The decoded-stream sentinel is a character, not a promise of physical cap+1-byte intake.
Overall assessment
APPROVE for the current exact head. This closes the bounded IO repair, improves sustained operation and the user's correction/retry journey, and preserves the existing typed rules, legal codecs, file scope and authority. The full change is proportionate. Optional stdin-helper consolidation is a non-blocking maintenance suggestion, not an invented acceptance gate. Review approval grants no merge/bypass authority.
English verdict: APPROVE — 3c7ac4f; current full diff and real boundary/recovery counterfactuals verified. Existing unrelated Ruff E731 and untested native console/codec dimensions disclosed; CI not consulted.
loopx-agent
left a comment
There was a problem hiding this comment.
Maintainer change request for current head 3c7ac4f69d4a1696a641f5dbb4b947d40ea857fb.
有界读取的方向保留,先前 BOM 修复和技术验收也保留。这里补充合并前的产品要求:16 MiB 可以作为默认保护值,但不应仅凭“足够宽裕”的假设变成合法业务输入无法调整的硬约束。当前 PR 的 Assumed 项明确没有给出请求大小或内存测量来支撑这个具体值;这不是声称已经观察到合法请求超限。
请在这两个 capability 的现有输入边界提供经过校验的上限调整方式,或给出能够支撑固定上限的真实负载依据和兼容性契约。优先采用简单的局部配置,保持默认有界、不提供隐式无限制回退,不必为此建立全仓库框架。
如果采用可配置上限,请补充默认值与非默认值的 below/exact/over 和缩小输入后恢复测试,并拒绝无效上限;保留连续编码的字节记账、报告文件严格 UTF-8,以及 content-ops 原有 stdin-only 文件作用范围。文档说明限制的是输入字节数,不是进程总内存上限。
English verdict: REQUEST_CHANGES. Retain bounded reads and the verified encoding fixes, but provide a controlled adjustment path for legitimate larger inputs, or evidence and an explicit compatibility contract justifying a fixed 16 MiB maximum. This is a maintainer product requirement; it does not replace the earlier technical review or claim additional tests were run here.
…ut limit Both capabilities keep 16 MiB as the default input bound, but a caller with a legitimately larger (or deliberately smaller) request can now pass --max-input-bytes N on each subcommand that reads JSON. The value must be a positive whole number of bytes; there is no unlimited setting, and invalid values are rejected by argparse before any input is read. periodic-report applies the limit to files and stdin; content-ops keeps its stdin-only scope. Encoded-byte accounting, the single BOM charge and strict UTF-8 request files are unchanged. The READMEs state that the limit counts input bytes, not process memory. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Lihua <1017343802@qq.com>
|
Thanks. Addressed in Change
Tests (
Other validation on
Not tested: Windows. This changes |
loopx-agent
left a comment
There was a problem hiding this comment.
Reviewer: model_agent; gpt-6.1-sol; OpenAI; runtime_reported; xhigh
动机
通过文件、管道或嵌入式文本流向周期报告和内容队列提供 JSON 的操作者。以前会先读完整输入再解析;上轮虽增加了 16 MiB 保护,却让合法大请求只能撞到固定上限。本轮允许调用者明确调整正整数上限,默认仍保护读取,超限后可缩小请求重试,也可为确实需要的大输入给出有限的更高额度。
当前真实 CLI 接受默认上限处的合法输入,拒绝多一个字节的输入;显式提高上限后合法大请求能完成,缩小请求后的下一次调用也能完成,普通请求结果与基线逐字一致。
该改动只约束输入大小,不保证进程总内存、解析成本或耗时;content-ops 的文件输入维持既有范围,不新增发送、账户、Goal 配置或持久状态权限。
改动思路
最近的 owner 是两个 capability 的 Python CLI I/O 适配器:这里处理字节、文本解码和 argparse,原有报告及内容状态规则继续由已有 owner 决定。没有新增 Python 控制面或通用能力开关;两处短小编码器虽相似,文件范围不同,不能借合并 helper 改成统一文件政策。
本 PR 完成既有输入入口的有限保护、编码兼容和调用者调整;配置仅为本次命令的 transport 参数,无安装或数据迁移。 输入错误由原有命令返回;恢复不要求改 Goal 或重新配置账户,调用者缩小数据或明确给出更高的有限上限,再执行原命令即可。保持单个连续编码器,避免每个分块重复计算 BOM;没有将文本 stdin 一律改成二进制接口。
具体改动
本次完整核验 head 864634f,相对 base f7a5df0 的七文件差分(+533/-25),包括两处运行时、两份文档、两份测试和 I/O 清单坐标。重新核验了新增参数和所有既有调用点,没有沿用上轮技术批准来跳过维护者的新要求。
验收依据为维护者对固定上限的评审,固定 review-5483354111。INPUT-BOUND(有限默认保护)、INPUT-ADJUST(明确正整数调整)、INPUT-COMPAT(文本编码/严格文件 UTF-8/内容 stdin 范围)、INPUT-RECOVER(边界、无效参数及纠错重试)是对该文字要求的映射,当前均已实现。它们不是新增 roadmap 承诺。
关键代码讲解
- 两处 _input_byte_limit 和 _add_input_limit 验证 --max-input-bytes N;省略时为 16777216,零、负数、小数、无穷值等无效输入在 argparse 边界退出。没有无限制模式。
- 两处 _read_stdin_text 保留流的 encoding/errors,用同一个增量编码器累计全部分块及最终字节,BOM 只计一次,超过 N 时先拒绝再解析。
- periodic-report::_load_json_object 对文件最多读取 N+1 原始字节,然后保持严格 UTF-8 和 JSON object 校验;七处加载调用都传递已解析的 N。
- content-ops::_load_json_object 只对 stdin 使用新上限,十处既有加载点覆盖五个解析入口;文件输入保持原行为,未把调整参数扩成新的文件政策。
独立对照直接跑两个不可变版本的真实 CLI,共 36 个报告/内容管道及文件场景。普通结果逐字一致;默认 16 MiB 合法输入通过、多一个字节拒绝;自定义精确边界通过、超限拒绝;提高上限后的合法大输入以及缩小后的下一次调用都成功;UTF-16 文件仍拒绝。另跑 CRLF 输入边界反例,没有发现换行造成实际 console 的计数逃逸。当前源码的 45 项聚焦测试和 366 项相关能力测试通过,后者覆盖现有 profile/store/trigger/reference/layout 调用,未查询 CI。
对主干的风险
新增默认上限会拒绝以前接受的大输入,这是已披露的有意行为变化;维护者指出的固定上限摩擦已由本次命令参数及恢复实测解决。保护仍为输入字节大小,字符串拼接、解码、JSON 对象和下游计算可以额外耗用内存与 CPU,因此没有把“有上限”描述为总内存保证或速度提升。
增量语义 advisory、完整 semantic-vocabulary smoke、生成 I/O 清单与 diff--check 通过。Ruff check 在 base 的 content CLI532 与 head581 报同一处未改动的 E731 lambda,保留该失败,并不宣称 lint 全绿。format--check 在 base 有一个既有文件未格式化,当前四个文件未格式化:其中三份为本轮新增格式差异,建议作者清理,作为非阻塞风格意见,不将其归为基线问题。相关大套件 basetemp 隔离,但子进程 TMP 继承系统缓存;没有用它冒充运行中 Goal、账户或长期效果验收。
我的整体评价
APPROVE。长程效果和体验在这个有界入口上是正向的:默认避免反复读入过量数据,合法大任务可明确选择有限成本,失败后能沿同一入口恢复,无需重复 Goal 配置。效率是减少无效读取及固定上限下的重建/拆分摩擦,尚无 RSS、吞吐或耗时比例实测,分块重编码也有成本,不能宣称量化净提速。
后续结构检查考虑了共享短小 transport helper,当前保留在最近 owner,避免顺手统一不同文件范围;不增加新框架或平行控制面。原有类型规则、权限和输出协议保留,仅扩展本地输入参数。当前批准不授权合并,也不自动撤销其他审查者意见;旧阻塞处置应单独读回。
English verdict: APPROVE
Exact head 864634f satisfies the maintainer's explicit finite input-limit adjustment requirement. Independent base/head CLI comparisons cover ordinary parity, default and custom boundaries, explicit raised legal work, strict file decoding and corrected retries; 45 focused and366 related tests pass. Existing lint and current formatting failures are retained separately. This is a bounded protection/usability improvement, not measured RSS, throughput or long-run efficiency evidence.
Goal And Delivered Outcome
Outcome basis / optional anchor: public issues [Bug]: periodic-report CLI reads unbounded JSON input #6099 and [Bug]: content-ops stdin JSON input is read without a size limit #6089. The earlier attempts, fix(periodic-report): bound JSON CLI input #6100 and fix(content-ops): bound stdin JSON input #6091, were closed after review asked for changes. This PR fixes the three blockers that review named.
Goal/source and gap:
periodic-reportread its--*-jsonfile or stdin in full beforejson.loads.content-opsdid the same for stdin (--item-json -,--input-json -). Neither had a size limit, so an oversized or endless input was buffered whole in memory.Observable before → after, with the validation row that proves it: before, a 16 MiB+1 pipe was buffered and then parsed (or failed to parse). After, both CLIs exit 1 with
<label> exceeds the 16777216-byte limitbefore any JSON parsing; input at exactly the limit still succeeds. Proven by thereal_entrypointandunitrows below.Issue/task and intended base: Closes [Bug]: periodic-report CLI reads unbounded JSON input #6099. Closes [Bug]: content-ops stdin JSON input is read without a size limit #6089. Base
main@be15bf4ff.Author Declaration
Implemented against
Expected behaviorsections of [Bug]: periodic-report CLI reads unbounded JSON input #6099 and [Bug]: content-ops stdin JSON input is read without a size limit #6089 as currently published, plus the three fixes requested in the review of fix(periodic-report): bound JSON CLI input #6100.periodic_report/cli.py::_load_json_objecttest_periodic_report_file_input_is_bounded_and_keeps_strict_utf8_read_stdin_textin both CLIstest_periodic_report_stdin_input_is_bounded_by_encoded_bytes,test_queue_status_cli_refuses_oversized_stdin_before_parsingcontent_ops/cli.py::_load_json_object_read_stdin_text(one incremental encoder, so a UTF-16 / utf-8-sig BOM is charged once)€case: 18 characters / 38 bytes refused at a 32-byte limit, with at most limit+4 bytes read;test_queue_status_main_reads_text_only_stdin_up_to_the_byte_limit;test_*_main_charges_a_stdin_bom_onceraw.decode("utf-8")beforejson.loadsloopx/semantics/project_registry_io_manifest_v1.json(4 line numbers only)scripts/generate_project_registry_io_manifest.py --checkperformance-diagnosis' existingMAX_INPUT_BYTES. No request-size or memory measurement supports it as a fixed ceiling, so callers can set a different positive limit with--max-input-bytes N(maintainer review on3c7ac4f69).Scope And Continuation
machine_configuration,value_connectors,issue_fix/cli_input,public_safe_outbound/scan_cli). If maintainers want one shared bounded reader, it should be a separate change with its own caller contract rather than widening this fix.Validation
864634fdf(this PR head; adds--max-input-bytes. Earlier revisions:3f0f4dfef,891ac8baa,3c7ac4f69)unitpassedtests/capabilities/test_periodic_report.py,tests/test_content_ops_queue_status.py: 45 passed. Covers file and stdin at exactly the limit, limit+1, multibyte stdin byte budget with bounded read, unchanged UTF-16/BOM/invalid-UTF-8 rejection, and--max-input-bytesbelow/exact/over, recovery after shrinking, raising the default, invalid values and content-ops file scope.real_entrypointpassedpython -m loopx.cli:periodic-report compose-run --request-json -andcontent-ops queue-status --item-json -accept a normal stdin request and exit 1 on a 16 MiB+1 pipe. In-processloopx.cli.main()for both commands with UTF-8, UTF-16 and utf-8-sig text streams, one byte under, at, and one byte over the limit. At the unchanged 16 MiB limit, an embedded BOM-bearing stream of exactly 16,777,216 bytes is accepted, and one byte over is refused.regression_paritypassedjson.loadsfails the strict-UTF-8 file test; per-chunkstr.encodefails the UTF-16 and utf-8-sig BOM tests while the UTF-8 control still passes.staticpassedgenerate_project_registry_io_manifest.py --check: current, 291 sites.generate_semantic_inventory.py --changed-from HEAD: 0 candidates.git diff --checkclean. Ruff adds no new findings over base.integrationpassedtests/capabilities/test_periodic_report*.py,tests/test_content_ops_*.py,tests/capabilities/test_content_reference.py,tests/test_cli_stdio_utf8.py) under Node.js 22.23.3: 374 passed.integrationpassedloopx canary premerge --from-git-diffagainst the merged main base: 19 selected checks, 0 failures, 0 manual holds.Frontend / Visual Evidence
Type of Change
LoopX Area
Technical Direction
Shared-authority RFC fixture impact
N/A
Boundary Checklist
.loopx/,.codex/goals/, and liveACTIVE_GOAL_STATE.md).none.Signed-off-bytrailer (git commit -s).This changes
loopx/**CLI behavior (a new input refusal), so it is left for maintainer review and merge.🤖 Generated with Claude Code