Skip to content

feat(handoff): lossless ordered shards for over-budget project-agent handoff - #4444

Open
fengyin-solo wants to merge 2 commits into
loopx-project:mainfrom
fengyin-solo:codex/project-agent-handoff-shards
Open

fengyin-solo wants to merge 2 commits into
loopx-project:mainfrom
fengyin-solo:codex/project-agent-handoff-shards

Conversation

@fengyin-solo

Copy link
Copy Markdown

Summary

  • Project-agent handoffs have a fixed 16 line / 1800 character interface budget. The old overflow pass compacted the command block and then deleted whole sections by fixed prefixes (Agent 待办候选, 材料上下文, 交付观测, 交付合同), and returned a still-over-budget text when deletion was insufficient: receivers lost content silently and could not tell whether more existed.
  • This PR replaces the lossy section drop with lossless ordered fragmentation in a new typed module loopx/control_plane/handoff/handoff_fragments.py:
    • split_handoff_text returns the input verbatim with no envelope when it fits; over-budget text becomes shards, and shard 0 keeps the existing project_agent_handoff position and field semantics.
    • Every shard starts with one <!--loopx-handoff ... --> envelope carrying a content-derived stable set id, i/n sequence, a per-shard payload checksum, the previous-shard hash chain, and the full-content SHA-256.
    • reassemble_handoff_shards / restore_handoff_text validate every payload, set consistency, sequence/hash chain, and full digest. Missing shard, out-of-order delivery, duplicate/conflicting import, foreign-set shard, or altered content fail with explicit typed error codes (missing, out_of_order, duplicate, set_mismatch, integrity, digest, ...).
    • HandoffShardCollector accumulates imports idempotently: same set/index/checksum is a no-op, so regenerating the same handoff yields byte-identical shards and re-import never duplicates fragments.
    • Fenced command blocks are never split open: an unfinished fence is closed and re-opened with strip-only markers so every shard stays fence-balanced; over-long single lines prefer safe whitespace breaks with hard-cut fallback via continuation markers. Reassembly restores the original byte-for-byte.
  • build_review_packet exposes project_agent_handoff_fragments plus a compact handoff_fragment_manifest only when fragmented; the full packet and handoff-only markdown render every shard, and handoff-only JSON passes both fields through. When the handoff fits the budget, text, packet, and JSON payload are byte-identical to before (no envelope, no new keys).
  • Contract documentation updated in docs/status-data-contract.md.

Issue Or Task

  • Closes #
  • Contributor task ID: T003 (lossless project-agent handoff overflow handling)

Validation

  • Tested revision: 9f16df079 runtime commit / 7a04a3e70 docs commit, rebased onto upstream/main (503991dd2)
  • Run state: finished
  • Input classes: synthetic, public_fixture
Check kind Result Public-safe evidence / limitation
unit passed pytest tests/test_handoff_fragments.py — 38 tests: split/restore, missing/out-of-order/tamper/chain/digest errors, stable regeneration, idempotent import, over-long spaced/unbreakable/unicode lines, fenced block splitting across shards, budget matrix, packet and handoff-only integration, within-budget compatibility.
regression_parity passed pytest tests/control_plane/test_cli_output_budget.py tests/test_cli_entrypoint.py tests/test_cli_argument_diagnostics.py tests/test_manager_context_handoff.py tests/architecture/test_control_plane_import_boundaries.py together with the new tests — 196 passed; existing review-packet fixtures (including the dense over-line-count case that uses command-block compaction) produce identical single-text handoffs.
regression_parity passed python3 examples/control_plane/review-packet-cli-smoke.py and review-packet-handoff-context-smoke.py — both pass; the smoke's compactness/forbidden-marker assertions still hold for shard 0, and CLI review-packet markdown/JSON/handoff-only paths carry fragmented handoffs.
static passed ruff check clean on all changed/new files; loopx check public-boundary scan on all changed paths (via canary).
real_entrypoint passed loopx canary premerge --from-git-diff: catalog canaries 9/9, risk-profile smokes 8/8, public boundary 1/1, 18/18 total, 0 failures. Includes hot-path interface budget, CLI output budget regression, and status/quota/review-packet parity smokes.
  • Coverage and gaps: the new module is pure Python and exercised at both the unit and real build_review_packet/CLI smoke boundaries with synthetic oversized commands and within-budget fixtures. No persistence, quota, scheduler, frontend, or benchmark surface changes; no real backend gate applies. Over-budget scenarios only arise from unusually large inputs (e.g. an oversized approved agent_command), which existing product fixtures never hit.

Frontend / Visual Evidence

  • UI impact: none
  • Before: N/A (no dashboard/website/desktop surface changes; CLI text envelope renders as an HTML comment)
  • After: N/A
  • States and viewports shown: N/A
  • Source data: synthetic

Type Of Change

  • Bug fix
  • New feature
  • Breaking change
  • Refactoring (no functional changes)
  • Documentation update
  • Test update

LoopX Area

  • Control plane (goals, todos, quota, scheduler, registry, runtime)
  • Benchmark boundary (adapters, runners, verifiers, scoring, evidence)
  • Capability or extension (providers, adapters, skills)
  • Public docs or presentation surface (README, protocols, dashboard)
  • Build, packaging, installer, or CI
  • Host or runtime integration

Technical Direction

  • Core control-plane hardening

  • Long-horizon benchmark evidence

  • Operator surface and IM integration

  • Shared Goal Authority and cross-host coordination

  • Architecture and research incubator

  • Target base branch: main (huangruiteng/loopx)

  • Direction tracker or promotion unit: N/A

Shared-authority RFC fixture impact

N/A — no TypeScript control-plane or shared Goal Authority surface is changed.

  • Production-scale fixture schema: N/A
  • Semantic dimensions changed, or reviewed no-impact rationale: N/A
  • Provider conformance arms run: N/A
  • Read-only legacy/file/PostgreSQL three-arm rehearsal: N/A

Boundary Checklist

  • Neither the diff nor this PR body/comments/attachments disclose private state, credentials, raw traces or verifier output, internal links, or local machine paths (including .loopx/, .codex/goals/, and live ACTIVE_GOAL_STATE.md).
  • I did not duplicate maintainer-owned benchmark work unless a maintainer split out a public issue for it.
  • I kept the change scoped to the linked issue/task.
  • I completed the visual evidence section for UI changes, or marked UI impact none.
  • Every commit includes a DCO Signed-off-by trailer (git commit -s).

Project-agent handoffs have a fixed 16 line / 1800 character interface
budget. The old overflow pass first compacted the command block and then
deleted whole sections by fixed prefixes, returning an over-budget text
when deletion was insufficient: receivers lost content silently and
could not tell whether more existed.

Replace the lossy section drop with ordered, independently verifiable
shards in control_plane/handoff/handoff_fragments.py:

- split_handoff_text returns the input verbatim (no envelope) when it
  fits; over-budget text becomes shards, and shard 0 keeps the existing
  project_agent_handoff position and field semantics;
- each shard carries an envelope with a content-derived stable set id,
  i/total sequence, per-shard payload checksum, previous-shard hash
  chain, and full-content SHA-256;
- reassemble_handoff_shards/restore_handoff_text validate every
  payload, set consistency, the hash chain, and full digest, failing
  explicitly on missing, out-of-order, duplicate/conflicting, foreign-
  set, or tampered shards;
- HandoffShardCollector imports shards idempotently (same set/index/
  checksum is a no-op), so regeneration and re-import never duplicate
  fragments;
- fenced command blocks are never split open (strip-only close/reopen
  markers balance every shard), and over-long single lines wrap at safe
  whitespace boundaries with hard-cut fallback via continuation
  markers, restoring byte-for-byte;
- build_review_packet exposes project_agent_handoff_fragments plus a
  compact handoff_fragment_manifest only when fragmented; full packet
  and handoff-only markdown render every shard, and handoff-only JSON
  passes the fragments through. Within-budget output is byte-identical.

Tests cover split/restore, missing/out-of-order/tamper/digest errors,
idempotent regeneration and import, over-long lines and fence
splitting, a budget matrix, packet/handoff-only integration, and the
within-budget compatibility shape.

Signed-off-by: fengyin-solo <292015025+fengyin-solo@users.noreply.github.com>
Describe the lossless overflow protocol: shard 0 keeps the existing
project_agent_handoff semantics, continuation shards use a stable
content-derived set id with index/total, per-shard checksum, hash chain,
and full digest, and receivers fail explicitly on missing, out-of-order,
duplicate, or tampered shards. Document fence close/reopen and line
continuation handling, idempotent re-import, and byte-identical output
within the 16 line / 1800 character budget.

Signed-off-by: fengyin-solo <292015025+fengyin-solo@users.noreply.github.com>

@huangruiteng huangruiteng left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

动机

超预算 handoff 之前是有损的:fit_project_agent_handoff_budget 会先压缩最后一段 bash 块,然后按前缀逐组丢掉 Agent 待办候选材料上下文:交付观测:交付合同:,删完仍然超预算就照样返回那份超预算文本。把交付合同/交付观测丢掉,项目 Agent 就会按不完整的契约干活,所以"不要再丢内容"这个方向我认同。本 head 改成:整段归一化后(只做无损的 bash 块压缩)切成带信封的有序分片,project_agent_handoff 放第 0 片,其余进 project_agent_handoff_fragments。方向没问题,但改的是对接收端可见的输出契约,有两处必须先收口。

改动思路

新增 loopx/control_plane/handoff/handoff_fragments.py:信封行 <!--loopx-handoff v=1 id=… i=… n=… c=… p=… d=…--> 承载内容派生的 set id、序号/总数、单片校验和、前片哈希链与全文 digest;packer 保证围栏不被切开、超长行用续行标记折行;读取侧提供 parse_handoff_shard/is_handoff_shard_text/reassemble_handoff_shards/restore_handoff_text/HandoffShardCollector/extract_handoff_shards/build_handoff_shard_manifest,并在编码末尾用自校验保证逐字节可逆。review_packet.py 里旧的丢段函数被删除,改由 normalize_project_agent_handoff_text + split_handoff_text 承担;cli_commands/status.py 让 handoff-only markdown 打印全部分片,JSON 额外暴露 fragments 与 manifest。

具体改动

  • loopx/control_plane/handoff/handoff_fragments.py(新,736 行):信封、packer/折行、解析与校验、collector、extractor、manifest。
  • loopx/review_packet.py(+92/-26):删除 fit_project_agent_handoff_budget,新增 normalize_project_agent_handoff_textprepare_project_agent_handoff_shardsrender_handoff_only_text;packet 侧 agent_text = handoff_shards[0](第 711-712 行)。
  • loopx/cli_commands/status.py(+21):handoff-only JSON 透传 project_agent_handoff_fragments/handoff_fragment_manifest(143-145),markdown 走 render_handoff_only_text(898-905)。
  • docs/status-data-contract.md(+27/-2):登记分片契约与逐字节可逆承诺。
  • tests/test_handoff_fragments.py(+560,新文件):32 个测试覆盖分片、缺失/乱序/篡改/重复、围栏与续行。

关键代码讲解

  1. split_handoff_texthandoff_fragments.py:285):未超预算时原样返回 [text](无信封),超预算才分片;每片生成后再核对 len(shard.split("\n")) <= 16len(shard) <= 1800,最后 reassemble_handoff_shards(shards) != text 就抛错——编码器自校验,这点做得扎实。
  2. review_packet.py:711-712handoff_shards = split_handoff_text(prepared_agent_text)agent_text = handoff_shards[0]。这一行决定了 project_agent_handoff/handoff_text 的语义在超预算时从"完整文本"变成"第 0 片"
  3. review_packet_handoff_only_payloadstatus.py:128-129,143-145):handoff_text 复制的就是 project_agent_handoff,即第 0 片。

对主干的风险

阻塞项 1(P1,接收端契约没跟上,且校验入口不可达)。我用真实 CLI 做了反事实:live loopx-meta 的 handoff 是 14 行/1370 字符(未超预算,--handoff-only 输出与 head 之外无差异);把它加上 必读成员交付合同 三行变成 17 行/1541 字符后,markdown 输出分成 2 片(shard 0 = 15 行/1569 字符,shard 1 = 4 行/272 字符),而可执行的 ```bash 命令落在第 2/2 片;JSON 里 handoff_text/`project_agent_handoff` 只等于 shard 0。但 `skills/loopx-project/SKILL.md:700` 仍写着"JSON 返回带 `handoff_text` 的 minimized handoff",`:710` 仍把 `给项目 Agent` 说成 "the executable handoff context"——本 PR 只更新了 `docs/status-data-contract.md`,没更新这个接收端 skill。全仓 `rg` 的结果是:`reassemble_handoff_shards`/`restore_handoff_text`/`HandoffShardCollector`/`extract_handoff_shards` 除了本模块与单测没有任何调用方,也没有 CLI 入口,所以转发文案里承诺的"收齐全部 N 片并按序号校验通过后再执行;缺片、乱序或内容改动都会明确报错"在接收端其实不可达:我把只含 shard 0 的 `handoff_text` 交给 `restore_handoff_text` 会抛 `code=missing`,可接收 Agent 没有任何 shipped 途径走到这一步,若它直接按字段执行,则既没有命令、也没有报错。最小修复二选一:(a) 补一个接收端可用的 verify+restore 入口(例如文档化的 `loopx review-packet --restore-handoff`)并写进 skill;(b) 分片时把 `handoff_text`/`project_agent_handoff` 显式标成"不可单独执行",并同步改 `skills/loopx-project/SKILL.md` 与转发文案,让按 skill 行动的 Agent 不可能只执行第 0 片。

阻塞项 2(P1,改动落在 CLI 契约上却没有真实入口级验证)examples/control_plane/review-packet-cli-smoke.py 本 PR 未改动,它的 dense fixture 在 head 上仍是 13 行/1319 字符(未分片),所以"markdown 打印多片""JSON 新增 project_agent_handoff_fragments + handoff_fragment_manifest"这两条被改动的契约在 CLI/契约层零覆盖;新覆盖全在 tests/test_handoff_fragments.py(560 行、合成超行文本)。我实测:pytest tests/test_handoff_fragments.py → 38 passed;review-packet-cli-smoke.pyruntime-handoff-status-read-path-smoke.pyplatform-migration-material-registry-smoke.py 均通过——正因为它们都不触发分片。本仓库对 status/packet 这类表面的改动要求比单元测试更强的证据。最小修复:在 public CLI smoke 补一个超预算 case(断言 markdown 的分片段、JSON 的 fragments+manifest、以及一次可校验的重组),并把 loopx canary premerge --from-git-diff 的结果贴到 PR 评论。

P3(体量与触发条件):736 行新模块 + 560 行单测,而触发条件(16 行/1800 字符)在仓库现有 fixture 与 live goal 上都没有被观察到(loopx-meta 14 行、dense fixture 13 行,我只在人为加三行后才触发)。同时旧的丢段回落被整体删除,packet 路径不再有任何更简单的兜底。建议把"验证的一半"(collector/extractor/manifest/transport markers)留到真有接收端调用点再上,或保留现有单文本行为作为第一层、只在仍超预算时才分片;已上线的部分请让每个 helper 都有活的调用方。

其余非阻塞观察:ENVELOPE_CHAR_RESERVE=200 相对实际信封长度(我构造的两片分别是 142/157 字符)是保守的,我的 hostile 用例没有出现预算越界;分片标题行只出现在后续片上并写作「交接分片 2/2」,第 0 片没有对应标题,读者容易误判第 0 片是完整文本;splitter 对以信封前缀/续行标记开头的正文是 fail-closed,这一点只写在模块 docstring 里,没有写进接收端文档。

我的整体评价

REQUEST_CHANGES。无损 relay 的方向我认同,实现本身也自洽:信封把 set id 绑到内容 digest,每片校验和 + 前片哈希链 + 全文 digest 齐全,围栏不被切开、超长行可逆折行,编码末尾还有逐字节自校验,未超预算路径与既有 smoke 全绿。但这次改的是 review-packet/handoff 对接收端可见的输出契约:超预算时 project_agent_handoff/handoff_text 不再是可直接执行的完整文本(命令跑到最后一片),而接收端既没有 skill/文案更新、也没有任何 shipped 的校验或重组入口;同时被改动的 CLI 契约没有任何真实入口级覆盖。收口建议很小:补接收端入口或显式声明不可单独执行 + 更新 skill,补一个 CLI 超预算 case 并跑 canary premerge;如果想更保守,也可以按上面 P3 收缩成"单文本优先、仅必要时分片"。改完后请让我按新的 exact head 再做一次复审。

English verdict: REQUEST_CHANGES at 7a04a3e. Keeping over-budget handoffs lossless is the right goal, and the relay implementation is internally consistent (content-derived set id, per-shard checksum, previous-shard hash chain, full-content digest, fence-safe packing, byte-exact encoder self-check; 38 focused tests pass and the in-budget path is unchanged in a live CLI run). The problem is the receiving contract: for an over-budget handoff, project_agent_handoff/handoff_text become shard 0 only. In my probe of a realistic 17-line handoff the executable ```bash command lands in shard 2/2, so the documented minimized field is not executable, while skills/loopx-project/SKILL.md still presents that field and the 给项目 Agent section as the executable handoff and was not updated by this PR. The promised explicit shard errors are also unreachable from the receiver surface: reassemble_handoff_shards/restore_handoff_text/HandoffShardCollector/extract_handoff_shards have no caller outside this module and its tests, and no CLI entry point exists. Secondly, the changed CLI contract has no entry-point coverage: review-packet-cli-smoke.py was not updated and its dense fixture stays in budget (13 lines / 1319 chars), so the new markdown shard sections and the new JSON fragment fields are covered only by unit tests over synthetic text. Please add a receiver-reachable verify+restore surface (or mark the field non-executable and update the skill), add an over-budget CLI smoke case, and post loopx canary premerge results, then I will re-review the new exact head.

@huangruiteng

Copy link
Copy Markdown
Collaborator

RFC 对齐补充评审

评审对象:7a04a3e700989204116410af7fe6b0a4aead27ef。RFC 参考版本:当前 main4f33d5ac6f63a00028cd8ac6815c03c15d17e154

本次按请求补充 RFC 定位与交付顺序;已有完整评审仍对应同一 head,正式 REQUEST_CHANGES 结论保持不变。以下不重复发起一次相同提交的全面审计,也不把未来 RFC 验收项全部追加为本 PR 阻塞项。

动机

保留超预算交接中的约束、材料和交付要求,符合强能力管家与语义交接 RFC §5.4:投影应披露遗漏,不能静默删除用户约束。不过该节同时要求小而适配任务的投影,以及可实际读取的完整材料。逐字重组解决文本传输完整性,只能作为语义交接的一个基础环节。

改动思路

建议将本 PR 定位为 现有 review-packet 的无损传输与兼容性修复。新增 Python codec 可以留在现有 handoff 边界;本次没有接管 Todo、claim、lease 或 request 状态机,没必要为了目录名或未来 M2 而增加 Python↔TypeScript 往返。

管家 RFC §11/§11.1允许独立的格式/投递修复先于通用协作重构交付。因而本 PR 不必等待 M2 双消费者、M3 自动回传或共享存储提升;也不应以分片功能完成来宣告这些里程碑已完成。

具体改动

本次对照了现有评审、PR 描述及相关源码:

  • handoff_fragments.py 提供分片、校验、重组、collector、extractor 与 manifest;review_packet.py 生成第 0 片和 continuation shards。
  • cli_commands/status.py 在 handoff-only JSON 透传分片,在 Markdown 渲染全部分片;契约文档和 focused tests 是另外两个修改面。
  • 当前 project_agent_handoff / handoff_text 在分片时仍只承载第 0 片;skills/loopx-project/SKILL.md 仍描述 minimized handoff_text 和 executable handoff。重组工具的调用仍局限于新模块内部与单测。已有接收端契约问题尚未通过新提交修复。

按 RFC 节奏建议这样收口:

阶段 建议与验收边界
本 PR:补齐已有阻塞项 接收端必须能明确识别不完整交接,并有文档化、实际可调用的校验/恢复路径;同步 managed skill 与字段说明,去掉“第 0 片保持完整字段语义”的误导。新增真正触发溢出的 CLI case,覆盖 Markdown、JSON、完整恢复,以及仅收到第 0 片时的明确拒绝/不可执行反馈。继续保留未超预算输出兼容性。
本 PR:有界整理建议 按实际接收路径决定是否需要 collector、自由文本 extractor 等入口;接入的保留,没有真实调用或明确兼容契约的可延后。不要单纯因新增行数大或合成输入才触发就否定这项修复;检验的是完整的生产者→接收者路径是否值得这些代码。无损 codec 的边界用 prepared text 说明清楚,避免把前置命令归一化也称为原始输入逐字保留。
M2:语义请求与接收方评估 在已有 request/brief/authority 边界上接入语义上下文;分片 set id 仅用于同一内容的重组,不得成为业务 request id、任务去重键或授权凭据。相同文字的两次独立请求必须保留各自义务,接收方 assessed/adopted 也不能由 checksum 成功推断。
M3:完整结果与渠道恢复 通过现有 outbox/return route 证明长结果、重启与不确定投递能够恢复;再验证实际渠道是否保留 HTML 注释信封,以及附件或分段传输的可读性。不要在本 PR 引入新投递账本或承诺已支持 Lark/跨主机恢复。

M2 的身份与回执边界来自§5.6:内容哈希不能合并独立请求,传输、评估、执行和答案送达是独立事实。未来如迁移这些状态规则,再执行TS 迁移 RFC §5的 owner/删除旧规则/桥接成本证明;纯传输 codec 不需要伪装成一次状态机迁移。

对主干的风险

当前主要风险仍是完整文本字段变成首片后,旧接收方式可能遗漏约束或命令,以及真实 CLI 溢出路径的证据不足。这里的“收齐再执行”需要落实到接收路径;仅写提示不能声称已有机器强制保证。

还有两项非阻塞的演进约束:

  1. 每片满足 16 行 / 1800 字符,并不能证明整组投影仍然紧凑。后续优先复用有权限且能解析的材料引用,披露未读取内容;不要默认把全部分片注入每个 Turn。管家 RFC A14 的跨主机材料可读性需要单独验证,本次 codec 测试不覆盖它。
  2. 已交付的 Stage A继续由 handoff prepare/inspect/adopt 和现有 Todo authority 管理所有权;分片校验成功不能替代当前 revision、claim/lease 或 transfer grant。无需在这里再建一套接管机制。

结合刚合并的语义词汇 M0,下一修订更新到当前基线时,应检查新增协议常量是否使生成 inventory 过期,并运行 python3.11 examples/semantic-vocabulary-drift-smoke.py;需要时随源码更新 inventory。不要为本 PR 提前实施 M1–M4 全部词汇迁移。

我的整体评价

保留 REQUEST_CHANGES,支持修复接收闭环后作为独立传输改进交付。 先完成既有接收端兼容与 CLI 验证,再把请求身份/语义评估、自动回传分别放进 M2/M3。未来重构检查的具体边界是 codec 与协作状态机:当前建议收敛到真实调用,避免增加第二个请求或权威状态 owner。

验证说明:本次是同一 exact head 的 RFC 补充,对照了远端讨论、上述版本化 RFC、字段投影及调用点;没有重新运行全面测试,没有生成新的全面审计或合并资格结论。先前测试结果见原评审,不能当作下一修订的验证。按本 Goal 配置,本次未查询、轮询或等待 CI;接收端与本地验证缺口仍需补齐。

English verdict: REQUEST_CHANGES remains at 7a04a3e. This RFC alignment supplement preserves the existing exact-head review: complete receiver compatibility and real over-budget CLI coverage first. Keep sharding a bounded transport codec; reserve semantic request identity/assessment for M2 and durable result return for M3. RFCs and source call sites were inspected; tests were not rerun and CI was not consulted.

@huangruiteng

Copy link
Copy Markdown
Collaborator

Change request:把交接上下文从 Review Packet 中分离,补齐可用的接收路径

对应 head:7a04a3e700989204116410af7fe6b0a4aead27ef

这是维护者针对长期 handoff 方向提出的具体修订要求,补充已有 REQUEST_CHANGES,并细化上一条 RFC 意见本次希望包含一次有界的职责重构,而不止增加分片恢复命令。 这是明确的设计范围调整,不是声称在同一 head 上又复现了一个新的运行时缺陷。

动机

当前 build_review_packet 同时组装 Goal 状态、给人的判断与 gate 提示、给 Agent 的交接上下文、执行命令和最终 Markdown。#4444 在这段已经渲染的文本上增加分片协议,改善了内容丢失,却进一步把交接绑定到“生成 Review Packet → 人复制 → Agent 执行”的旧入口。

长期 handoff 要支持有上下文的工作委派、接收方重新评估、会话替换和结果回传。因此需要调整依赖方向:交接上下文有自己的组装边界,Review Packet 消费它来生成人工可读投影,传输层再按渠道需要编码。 review-packet 可以保留为兼容 CLI 和人工评审视图,但不应拥有通用工作请求、交接状态或执行授权。

依据:handoff RFC §5.2–5.6。该 RFC 已要求区分应用、协作语义和运行时/渠道适配,现有模块位置是迁移输入。

改动思路

建议本次交付路径如下;方框表示职责,不要求照此创建同名模块或公共 schema:

现有 Goal/Todo/决策/材料来源
          ↓
共同的交接上下文组装边界
          ├── Review Packet:给人的状态、判断与展示
          └── Agent handoff:给接收方的完整上下文
                         ↓
                 渠道渲染 / 必要时分片
                         ↓
                 接收端校验与恢复
                         ↓
                 接收方按现有权限继续处理

这里的“共同”必须由真实的 full packet 与 handoff-only 路径消费。不要仅搬一个函数、保留两份事实推导,也不要为未来消费者建立空框架。接收端恢复成功只证明内容完整,不代表已接受工作、获得 claim/lease 或可直接执行其中的命令。

具体改动

CR1:提取上下文组装职责,保留 Review Packet 的展示职责

请先列出 project_agent_sectionbuild_review_packet、handoff-only payload/rendering 的生产者与消费者,再在最近的现有 handoff 边界提取一个内部的、有类型的上下文表示及其组装逻辑。

  • 从当前实际使用的信息出发,保留目标与来源、必读材料、当前工作/约束、交付要求、候选下一步或命令及其适用边界。复用现有结构与引用,不复制 Todo、Vision、权限或进度的事实源。
  • 同一上下文同时供完整 Review Packet 和 handoff-only 使用。完整 Review Packet 额外添加给人的判断/gate 部分;handoff-only 无需先构造完整人工评审文本再裁剪。
  • 不通过解析 材料上下文:交付合同: 等文案前缀来识别或删除语义。调整文案不应改变保留哪些约束。
  • 本次只需覆盖现有调用使用的内容。不要提前补全通用 request schema、持久化 brief store、协作状态机或第二套任务数据库。
  • 普通交接的描述不要自动继承“必须由人再批准”的前提;已有 operator-gate 场景保留其真实限制,也不扩大既有权限。

完成标准: 状态/上下文事实只有一个组装来源,两个现有输出路径均消费它;旧的重复组装逻辑在本 PR 删除,调用关系与职责可以从源码直接看清。

CR2:分片属于传输;修正完整文本字段的语义

当前 project_agent_handoff / handoff_text 在溢出时成为第 0 片,文档仍说保持同样字段语义。这一兼容性声明必须修正。

  • 未超预算时保留现有文本、JSON 形状及行为。
  • 溢出时,旧的“完整交接文本”消费路径必须得到完整内容,或明确拒绝这个不支持的表示,不能成功返回一个容易被当作完整交接的首片。只添加 manifest 或另一处提醒,不能证明忽略新字段的旧消费者已经安全。
  • 请在上述兼容原则内选择一种明确方案,说明旧消费者会看到什么、新消费者如何获取所有片。若需要显式选择新表示或版本化输出,请随真实入口与测试一并提供;不要求为此建立通用版本协商框架。
  • 16 行 / 1800 字符保留为当前接口/单片预算,不作为长期上下文的总语义容量。每片合规不能被报告成整组内容已满足原来的总输出预算。
  • “逐字无损”明确以哪份文本为基准:当前 splitter 接收的是 prepared text;前置命令归一化与传输重组是不同步骤。
  • set_id/checksum 仅表示内容与传输完整性,不表示请求身份、发送者认证、接收方接受或执行授权。相同文本的两个独立工作请求不能因内容哈希相同而被业务去重。

完成标准: 完整交接、单片和恢复结果在契约上不混淆;未收齐内容的兼容消费者没有“成功收到完整交接”的假象。

CR3:交付接收方实际能用的校验/恢复入口

请提供一个已文档化、可以由接收 Agent 调用的真实入口,并在 managed skill 中写出可运行步骤。它应属于 handoff 的内容接收职责;不要仅因当前生产者是 review-packet 就把恢复协议继续绑定到人工评审概念。

具体命令拼写可以沿用仓库注册模式;若选用现有 handoff CLI 家族,请清楚区分内容恢复与已交付的 prepare/inspect/adopt 所有权流程。

  • 接收实际生产者输出的完整分片集,校验并恢复完整交接文本。
  • 缺片、混入其他集合、内容篡改等返回可操作的明确错误;不要输出可误认为完整成功结果的半份文本。
  • 顺序与重复策略保持明确:直接有序恢复与 collector 幂等导入若允许不同行为,分别说明并测试,避免同时声称“重复总是错误”和“重复总是无操作”。
  • 恢复入口只处理内容,不自动执行命令、不申请或转移 claim、不修改 Todo、不自动启动会话。
  • skills/loopx-project/SKILL.md 同步描述完整/分片表示、收集与恢复步骤,以及恢复后的现有权限检查。不要以“模型看到警告就会遵守”代替可用的校验入口。
  • collector、自由文本 extractor 等 helper 只保留真实接收路径需要的部分;没有活调用或明确兼容需要的部分可删除/延后。已有 focused tests 中证明实际编码边界的内容仍值得保留。

完成标准: 一个接收方仅凭 shipped CLI/skill 即可恢复合法交接,识别不完整输入;无需临时写 Python 去导入内部函数。

CR4:补齐 RFC replacement map 与公开操作说明

请更新 handoff RFC §5.9 的替换表及中英文镜像,明确登记 review_packet.py

现有职责 本次/后续归属 迁移完成条件
交接上下文组装 本次提取到现有 handoff 边界 full packet 与 handoff-only 共用,旧重复规则删除
人工判断、gate 展示、Review Packet 渲染 保留为展示适配器 不拥有通用 handoff 状态或另行赋予权限
长度控制、分片/重组 当前渠道适配 可用接收入口与完整性、兼容性验证通过
请求身份、评估、结果与恢复关系 后续 M2/M3 的统一协作边界 按相应阶段独立验收,不能由分片测试替代

同时修正 docs/status-data-contract.md、managed skill、受影响的 CLI help,以及 PR 描述的字段兼容性和交付范围。用户入口检查请列出 CLI、实际复制/展示该内容的前端或其他渠道消费者;确实不受影响的给出调用依据。仅测试 CLI 时,不宣称已验证 Lark、跨主机或所有 Markdown 渲染器的注释保留行为。

对主干的风险

CR5:按真实消费路径补验证

新增测试应先从下面这些语义要求写出预期,再测试实现。不要把实现生成的内容反过来当作唯一 oracle。

用例 必须证明的结果
未超预算 与 base 的匹配 fixture 比较,既有文本、字段和行为不变
实际构造的超预算上下文 使用独立写明的合成约束与交付要求,使它们分布在不同片;通过真实 CLI 输出→真实接收入口恢复后,约束、要求及命令内容均保留
完整 Markdown 与 JSON 路径 二者提供同一份交接内容;给人的 gate 问题不混入 Agent handoff
仅收到首片 明确失败/不完整,不冒充完整交接、不执行任何命令
缺片、混集、篡改 接收入口给出对应错误;不得返回成功的部分交接
乱序与重复 符合声明的直接恢复/collector 策略;内容去重不被宣称为业务请求去重
文案变化 修改展示标题或标签,不改变结构化约束是否被保留
权限与状态 成功恢复仍是内容操作,不改变现有 Todo/claim/lease/gate;不把校验成功展示为任务已接受

复用并扩展 examples/control_plane/review-packet-cli-smoke.py 等现有拥有该路径的验证;至少有真实 CLI 进程覆盖生产与接收,而非全部 monkeypatch 在内部 helper 上。不要把大段 unit cases 机械复制成另一个超大 smoke。

下一 head 请运行相关 focused tests、现有 packet/CLI 回归,以及 loopx canary premerge --from-git-diff 或明确映射到上述风险的等效本地验证集。更新到当前基线时,检查语义词汇 inventory/drift 验证是否需要随源码刷新。PR 验证评论记录 exact base/head、修改面、命令、通过结果、失败/跳过与证据边界。本 Goal 不查询或等待 CI;本地失败和缺失证据仍需明确处理。

我的整体评价

REQUEST_CHANGES 保持。建议把“上下文组装职责分离 + 明确的兼容表示 + 接收端闭环 + 聚焦验收”作为一个可独立交付的修订。 它共享同一个修改原因,属于本 PR 合适的配套重构。

本次不要求实现通用 M2 状态机、M3 自动回传、跨主机持久化、历史召回、新 artifact 服务或整体 TypeScript 迁移。纯文本/投影逻辑可以保留 Python;未来真正迁移协作状态决策时,再按 TS 迁移 RFC证明单一 owner、旧规则删除与桥接成本。

也不要求现在删除 review-packet 这个已存在的命令:保留它作为人工评审/复制入口,同时让长期 handoff 可以独立演进。相关权限转移继续复用 Stage A 已交付契约,不在 codec 内重新实现。

请在下一修订说明中逐项回复 CR1–CR5,给出实现位置与验证结果;实现选择可以不同,只要满足上述可观察契约。这条评论是具体修订要求,不是新一轮测试通过或合并资格证明。

English verdict: REQUEST_CHANGES remains at 7a04a3e. Please extract the existing handoff-context assembly from Review Packet presentation, preserve legacy compatibility without exposing shard 0 as a complete handoff, ship a receiver-accessible verify/restore path, update the RFC replacement map and managed skill, and validate real producer-to-receiver CLI flows. Keep this a bounded refactor; generic M2/M3 lifecycle, ownership transfer, and storage migration remain separately qualified work. This comment specifies the requested revision; it does not claim new test execution or consult CI.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants