Skip to content

feat(runtime): share native ACP processes and scope reverse interactions - #177

Open
qiyuanhuakai wants to merge 6 commits into
feat/v090-acp-basefrom
feat/v090-acp-driver
Open

qiyuanhuakai wants to merge 6 commits into
feat/v090-acp-basefrom
feat/v090-acp-driver

Conversation

@qiyuanhuakai

Copy link
Copy Markdown
Owner

ACP observers need to share a native agent process without competing for its client connection or losing reverse-tool ownership when a UI disconnects. Add a runtime-owned ACP driver that keeps one client per configured agent instance, scopes observers and bounded replay to composite session identities, and keeps reverse file/terminal tools bound to the native process and trusted workspace.

Permissions and cancellation are durable controls tied to the original parent, lease, and process generation. Concurrent replies admit one winner; uncertain sends reconcile without automatic replay; replacing the native process invalidates old replies. Sequential native request-ID reuse stays parent-bound, while simultaneous outstanding-ID collisions close the source. Native capability mapping covers discovery, prompt/config/slash, fork/close, advertised concurrency, and managed authentication PTYs.

This atomic commit contains the 24 independently verified ACP files. It targets the fixed feat/v090-acp-base at 98a4474b540c1258c3e485ec98e013eff3d2047b. The shared WS fixture and inventory-map prerequisites are already in that base through #175 and #176.

The new independent whole-task gate is confirmed: 104 recorded surfaces and all nine applicable adversarial classes. Delivery rehashed 575 unique source/evidence files before and after commit, including 69 current sources, 66 original source bindings, the exact 24-file owned digest, and preserved historical/recursive proof.

Verification retained with exact source bindings:

  • node scripts/qa/runtime-v090.mjs --task 15 --case happy --out <artifact> and the matching --case failure invocation: 34 happy and 50 failure assertions, installed OpenCode/controlled stdio traces, managed PTYs, and durable SQL observations.
  • Eight additional protocol checks, 33 focused tests, and independent LSP diagnostics on the 25 captured files, including the now-committed WS fixture.
  • Original ACP build/type/full-run exit receipts: 4,896 tests passed, with six existing skips. These runs were source-matched and reused, not rerun for the inventory integration or git delivery.
  • Five actual inventory-checker cases in the new independent gate. The authentic DSH full JSON is reused only for byte-identical shared test inventory; ACP full-suite evidence remains its own original text log and actual exit receipts.

Limits: installed OpenCode 1.18.34 exposes 101 ACP sessions versus 102 native SQLite sessions, so its inventory remains explicitly partial; a conforming controlled ACP peer separately reaches complete exhaustion. Installed-native runs used private homes and an owned local model endpoint, with no paid inference or real-account login claim. UI/supervisor integration, actual oh-my-pi execution, installer/platform coverage, and true database/native atomicity are outside this task. The original uninstrumented full-suite WS failure's cause remains unproven.

Evidence: .omo/evidence/vis-v090/task-15/inventory-refinal-001/adversarial-verify.json (SHA256 1607a237507f16925f31180d88991ae147ba5f2486a0512e6ea96c058799821c) and .omo/evidence/vis-v090/task-15/delivery/delivery.json. Owned source digest: 9a646606552b8afdcfc11b418becdb14bd600f4b5500171c5159ea006ce88da1. CI for the published commit is recorded separately.

Copy link
Copy Markdown
Owner Author

AI 辅助源码审查(dot)

审查 head:e198723a79bc7e8a246ec71f364366e237ccee83
比较 base:98a4474b540c1258c3e485ec98e013eff3d2047b

以下为 24 个文件的 ACP 增量中发现的问题,不重复其他堆叠 PR 的发现。

[P2] 不同会话并发完成会竞争 process revision,遗留会话租约

acpMutations.js L267–298

agent 声明并发支持、不同 session 的两个 prompt 同时成功完成时,两者可读到相同 process authority revision。第一个 terminal CAS 重写共享 process 行,第二个收到 entity_revision。此处没有重读重试,而是进入 reconciling 并留下 session lease,之后该会话的新操作被 session_busy 拒绝。

最小复现得到一个 native-executed、一个 entity_revision,失败者 lease 仍存在。已核对实际 SQLite worker 同值写入也递增 revision,因此并非替身特有行为。建议确认 owner/generation/lease 仍属原操作后,只重试数据库收尾 CAS,不重发 native 操作,并覆盖跨会话并发完成测试。

[P2] 权限答复的幂等摘要遗漏 interaction identity

acpMutations.js L103–123、调用处 L88–104

同一 prompt 的两个不同权限请求,如果客户端复用答复 idempotency key 且 answer 相同,摘要因未纳入 input.interaction 而相同。第二次返回第一个请求的 already-completed,随后删除第二个 pending 项并发布 interaction.replied,却没有回复第二个 native RPC。

复现只回复 ID 7;ID 8 的 durable phase 仍为 pending,但可见 pending 列表为空,prompt 会继续等待。建议将 interaction identity 纳入摘要,这种跨请求复用应报 idempotency_mismatch,并补充专项测试。

[P2] 同一 prompt 内顺序复用 native request ID 被误判为重复

acpInteractions.js L31–37

权限请求答复后 RPC 层已释放 native ID,但 durable key 只由 scope、parent、native ID 组成。同一 prompt 后续复用该 ID,会命中旧记录并报 duplicate_native_request;内容变化还可能更早遇到 payload revision 冲突。

最小复现为答复 ID 7 后在同一 parent 接收新 ID 7,第二次失败。现有 QA 只覆盖不同 parent 的 ID 复用。建议每次接收生成独立 interaction identity,以 native ID 映射当前 outstanding 请求,同时保留对真正同时占用相同 ID 的拒绝。

[P2] 重试较早的配置操作会回滚当前缓存

acpExtensions.js L140–145

依次用 key A 将 model 设为 b、key B 设为 a,再重试 A。mutations.run 正确返回 A 的历史结果且不重新发送 native 操作,但此处无条件把历史 configOptions 注册为当前状态。

复现 native 实际值为 a,getSessionConfigOptions 却返回 b,只有两次 native 设置调用。建议 already-completed 路径仅返回历史结果,不覆盖最新状态,或用版本信息阻止旧快照覆盖,并测试延迟重复请求。

验证边界

已读完整增量、调用链、存储 CAS 实现及新增测试/QA。四个最小复现使用该 head 原始模块与内存 CAS 替身执行;未独立运行完整项目测试、真实数据库 worker 或 installed OpenCode 场景,作者报告不计为独立复验。

该 head CI 已核实 success。上述专项边界仍需回归覆盖;本审查不保证无其他缺陷。

Four defects on the shared native ACP process, each reproduced by
execution against the real runtime store before the fix.

Cross-session concurrent completion competed on the shared process
revision: the terminal CAS carried an authority guard read before the
native enqueue and never re-read it, so the loser was rejected with
entity_revision, left reconciling, and kept its session lease, after
which every later operation on that session was refused with
session_busy. The finishing CAS now re-reads its own authorities per
attempt and retries only the database write; the native operation is
never re-sent.

Permission replies collided across two different requests on one prompt:
the operation digest omitted input.interaction, so a reused idempotency
key with the same answer made the second reply report the first
request's result and drop its own pending interaction while the native
RPC went unanswered. The digest now carries the interaction identity, so
the cross-request reuse fails with idempotency_mismatch instead of
silently succeeding.

Sequential reuse of a native request ID inside one prompt was misjudged
as a duplicate, because the durable interaction key was derived from an
ID the RPC layer had already released. Identity is now minted per
receipt and the native ID only guards the currently outstanding request
through a generation-scoped occupancy row, so genuinely concurrent
same-ID occupancy is still refused.

Retrying an older config operation rolled back the current cache, since
an already-completed replay registered its historical configOptions as
live state without any native call. The register is now skipped on the
already-completed path.

Each fix has a named test that goes red then green, including one where
the two permission callers are otherwise identical so only the digest
can tell them apart, and one proving the native-ID guard still rejects
concurrent occupancy.

Copy link
Copy Markdown
Owner Author

AI 辅助增量复核(dot)

审查 head:33f96318f10ba0e6cb6cb997152d6fb70ceddd5d
上次审查 head:e198723a79bc7e8a246ec71f364366e237ccee83
PR base:98a4474b540c1258c3e485ec98e013eff3d2047b

本次只复核新增修复提交的 4 个文件及其调用链;#175 → #176 的前置内容仍已包含在 base,不重复计为本次改动。对照上次评论,两项已修复,两项仍存在更窄的边界缺口。

[P2] 并发收尾固定重试四次,仍可留下已成功执行的会话租约

acpMutations.js L273–304

重读 authority 解决了原先两个会话竞争的复现,但每次 terminal CAS 仍会重写共享 process 行,且最多尝试四次。agent 声明并发支持、多个已获得各自租约的 prompt 集中完成时,其他会话可以连续四次推进该 revision,使最后一个已完成的 native 操作仍落入 reconciling 并保留租约。

独立隔离验证先逐一让各会话进入 native 执行,再统一完成:4 个会话全部收尾;5 个时得到 4 个 native-executed 和 1 个 entity_revision;8 个时留下 4 个租约。失败会话的下一次操作均返回 session_busy,native 调用次数始终等于会话数。这是原问题的残留范围,不是要求重发 native 请求。

建议消除同一 process 的无意义 revision 竞争,或串行化/可靠调度数据库收尾,在重新验证 generation、owner 和原租约后完成它;仅增加固定重试次数仍会留下同类窗口。补充至少五个已在途会话同时完成的回归。

[P2] native 答复已经发出后立即复用 ID,仍被误判为占用

acpInteractions.js L133–145、拒绝分支 L40–44

rpc.reply() 已向 peer 写出结果并释放 RPC 层的 native ID,但 occupancy 要等整个 mutations.run() 的异步数据库收尾结束后才删除。peer 收到第一条答复后,立即在同一 prompt 内发起同 ID 的下一次权限请求,会命中尚未释放的 occupancy,收到 -32603 / duplicate_native_request,而不是生成新的 pending 权限。

使用该 head 的实际 process manager、RPC 模块及受控 stdio 子进程,暂缓首个回复的 terminal CAS,已观察到线序:ID 7 成功答复 → peer 再发 ID 7 → ID 7 错误答复;第二项没有进入可见 pending。无额外 CAS 暂停的 RPC 隔离用例也复现。新增顺序复用测试 L275–283先等待整个 respond(),因此没有覆盖 peer 实际可发送下一条请求的时点。

建议把 occupancy 的生命周期与 native 答复发送完成对齐,或让新 receipt 等待上一条已发送回复的收尾;同时保留对真正同时 outstanding 的重复 ID 的拒绝。

已核实的修复

  • 旧第 2 项:摘要纳入 interaction identity 后,同 answer、同 idempotency key 的不同权限请求返回 idempotency_mismatch,第二项仍保持 pending,未误发 native 回复。
  • 旧第 4 项:A→B→重试 A 不再覆盖最新 config 缓存,native 配置调用仍只有两次。
  • 两会话收尾、完全等待 respond 后的 ID 复用、真正并发占用同 ID 的拒绝,在独立隔离用例中均符合预期;上述两项残留需要额外时序覆盖。

验证与生产边界

执行前已核对所用源码与该 head 的 Git blob。独立验证使用原模块、保持事务/CAS/intent/异步交错语义的内存 SQLite 存储替身;stdio 复现使用实际 process manager/RPC 与受控 peer。真实 runtimeStore 在本环境因 tmpfs/overlayfs 不在其文件系统白名单内而无法启动,因此不宣称实际数据库 worker、完整 Vitest 或 installed OpenCode 已独立通过。作者原有证据也不计为本次独立执行。

精确 head 的 CI已核实终态 success。结论针对本 PR 的 runtime ACP 驱动;UI/supervisor 生产接线仍是 PR 明示的范围外事项,不据此声称现有 UI 已走这些路径。本复核不保证无其他缺陷。

…lign occupancy with reply completion

The terminal CAS carried the shared acp-process row as a guard, rewriting a
byte-identical value whose only effect was a revision bump. With more in-flight
completions than the retry budget, a completed native operation stayed
reconciling with its session lease held (5 sessions: 4 executed + 1
entity_revision; 8 sessions: 4 leases left, all later operations session_busy).
That row is no longer part of the CAS: the generation is re-validated per
attempt and the synchronous assertCurrent() sits immediately before the commit,
and a completion only writes its own operation, lease and interaction rows.

The occupancy row outlived the native reply, so a peer re-using a freed ID
inside the same prompt was refused with duplicate_native_request. The reply now
ends the occupancy's effective lifetime: respond() and settleParent() mark the
key in the same block as rpc.reply(), and receive() only rejects a same-ID
receipt whose request is still outstanding.

Two regressions cover both timings, including the moment the peer can actually
send. The retry budget is unchanged.

Copy link
Copy Markdown
Owner Author

AI 辅助增量复核(dot)

审查 head:af82d881db38d26012113b33331844c9393ba0a1
上次审查 head:33f96318f10ba0e6cb6cb997152d6fb70ceddd5d
PR base:98a4474b540c1258c3e485ec98e013eff3d2047b

本次仅复核新增提交的 3 个文件及相关调用链;base 未变,#175/#176 的继承内容不重复计入。对照上次补充评论:多会话收尾复现已转绿;权限 ID 即时复用的常规时序也已改善,但仍有下面这个跨 receipt 清理窗口。

[P2] 旧回复收尾会清除新一轮回复的 answered 标记,第三次复用 ID 仍失败

acpInteractions.js L99–108、接收判定 L46–53

answered 按可复用的 occupancy key 保存,但 release(A) 即使发现 durable occupancy 已属于另一条 interaction,仍无条件删除该 key 的 answered 标记。下面的合法交错会使第三次权限请求被误拒绝:

  1. A(native ID 7)答复已发出,A 的 terminal CAS 尚未完成。
  2. peer 复用 ID 7 发出 B;B 成功进入 pending,随后 B 的答复也已发出,但 B 的数据库收尾仍在进行。
  3. A 此时完成收尾,读取到 occupancy 的 interactionId 属于 B,进入 L100 分支并删掉 B 刚写入的 answered 标记。
  4. peer 在收到 B 答复后再次使用 ID 7 发出 C;C 命中 B 尚存的 occupancy,却找不到 answered 标记,收到 -32603 / duplicate_native_request,没有产生可见 pending 权限。

已通过该 head 的实际 process manager、RPC 模块与受控 stdio 子进程复现:两次 ID 7 成功答复,随后第三次 ID 7 收到上述错误;只产生两个 pending 事件。测试通过暂缓 A/B 的 terminal CAS 控制收尾顺序,peer 的三次请求在原生线路上均依次等待前一次答复,不是同时 outstanding 的重复请求。

建议让 answered 标记绑定具体 receipt/interactionId,例如保存 occupancy → 已答复 interactionId;接收时核对当前占用记录的 owner,旧 receipt 的清理只移除自己拥有的标记。对“不属于本 receipt”的 occupancy 不应删除后继 receipt 状态。补充上述 A/B 收尾重叠的三轮同 ID 回归;新增测试 L395–414先等 A 的 respond 完整结束才答复 B,因此没有覆盖这个交错。这属于上次 ID 复用问题剩余的更窄范围。

本次核实的修复

  • terminal CAS 不再重写共享 process 行后,重新运行 4/5/8 个已在途会话集中完成的隔离用例:全部 native-executed,没有遗留租约,每个会话后续操作均成功,native 调用未重复。上次该项复现已关闭。
  • A 答复已发出而 A 的数据库收尾未结束时,下一条 B 现已能够成功进入 pending;上述 stdio 复现也验证了这一点。剩余缺口是 A 清理误删 B 标记。
  • 权限答复幂等摘要、旧配置重试、完整收尾后的顺序复用,以及真正并发 ID 占用拒绝的既有隔离检查仍通过。

验证边界与 CI

已校验所用 33 个源码文件与该 head 的 Git blob 一致。独立执行使用原模块和保留事务/CAS/intent/异步语义的内存 SQLite 存储替身;stdio 验证使用真实 process manager/RPC 与受控 peer。实际数据库 worker 在本环境仍受 tmpfs/overlayfs 文件系统白名单限制;未独立运行完整 Vitest、installed OpenCode 或 UI/supervisor 生产接线,作者和 CI 的测试不计为独立重跑。

当前 head 的 CI提交此评论时 Validate 已成功,完整 workflow 仍在运行。结论限于本次增量及已执行场景,不保证无其他缺陷。

@qiyuanhuakai

Copy link
Copy Markdown
Owner Author

针对 10-16 07:57 增量复核(head af82d881db38d26012113b33331844c9393ba0a1)逐条回复。

跨 receipt 清理窗口(P2)—— 真实缺陷,已修复。
本机 ext4 真实 SQLite worker 复现确认:暂缓 A/B 两次回复的 terminal CAS,A 的收尾先于 B 完成时,第三次同 ID 请求抛 conflict: duplicate_native_request,只产生两个 pending 事件(RED 实测,与复核描述一致)。
根因:answered 是以 occupancy key 为键的集合,release(A) 在发现 durable occupancy 已属于 B 时仍无条件删除该 key 的 answered 标记,把 B 刚写入的标记清掉。
修复提交 c8f9b01e:标记改为 occupancy → interactionId 的映射(bridge/runtime/drivers/acpInteractions.js L23);接收判定要求“当前占用记录所属 interaction 的答复已在线上”才允许复用(L53);release 只删除属于自己的标记(L104-113)。peer 的三次同 ID 请求依次得到 pending,native 回复 [7,7,7],三轮 A/B 收尾重叠的回归已加入 app/runtime/drivers/acpPr177.test.ts;修复前该回归以 duplicate_native_request 失败,修复后通过。

该轮已核实的修复(terminal CAS 不再重写共享 process 行、A 收尾未结束时 B 可进入 pending、幂等摘要纳入 interaction identity、配置重试不覆盖最新状态)在本机全量运行中保持通过:npx vitest run app/runtime/drivers/ → 18/18 passed(含 4/5/8 会话集中完成用例;5/8 会话用例本机耗时超过默认 5s 上限,以 20s 超时运行通过,属本机磁盘性能,非逻辑问题)。

Array.isArray does not narrow away a readonly Json[] union member, so the
false branch still admitted the array and value.phase failed to typecheck.
Assert the shape through an explicit predicate, as the other Json consumers
in this tree do.
@qiyuanhuakai

Copy link
Copy Markdown
Owner Author

第四轮复核(审查 head b152b055c,已超过受审 head af82d881db):P2「旧回复收尾会清除新一轮回复的 answered 标记,第三次复用 ID 仍失败」在当前 head 已修复,该路径不再可达。未新推修复——修复已在 head 内,本轮只做独立验证。

修复就在当前 head。 git merge-base --is-ancestor c8f9b01ed b152b055c → 是。受审的「release(A) 无条件删除 answered 标记」写法已不存在:当前 bridge/runtime/drivers/acpInteractions.js 中 answered 是 occupancy key → interactionId 的映射(L23-27,注释即写明该语义);接收判定只在「当前占用记录所属 interaction 的答复已在线上」时才允许同 ID 复用、否则拒绝(L52-54);release() 以 own = answered.get(receipt.occupancy) === key 守卫,仅删除属于自己的标记(L101-113)。A/B 收尾重叠时 A 的清理读到 occupancy 属于 B,own 为假,B 的标记保留,第三次同 ID 请求因此能进入 pending。

独立 RED/GREEN(本机实测,未引用作者证据)。 在 head 工作区把修复前源码(af82d881d 的 acpInteractions.js,仅此一个文件)换入后运行新增回归 an older receipt finalization does not clear a newer receipt answered mark:第三次同 ID 请求与复核描述一致地失败——expected [ 'duplicate_native_request', … ] to deeply equal [ 'ok', [ 7, 7, 7 ], 3 ](native 回复 [7,7],只产生两个 pending 事件)。换回当前 head 源码后同测试通过。

门禁(当前 head)。 npx vitest run app/runtime/drivers/acpPr177.test.ts --testTimeout=20000 → 8/8 passed;npx vitest run app/runtime/drivers/ --testTimeout=20000 → 18/18 passed。默认 5s 超时下 5/8 会话集中完成用例会超时,20s 超时通过,属本机磁盘性能,与已披露一致。head CI(run 39050332360)Validate pass。

未验证。 未启动真实 ACP CLI 与真实 SQLite worker 环境外的完整全量套件;本机存储替身/受控 stdio 之外的场景未覆盖。

结论:该 P2 在当前 head 关闭。

@qiyuanhuakai

Copy link
Copy Markdown
Owner Author

第五轮完整复核(审查 head b152b055c):对 #177 全部三轮审查的每一项 finding 逐项对照当前 head 独立复验,结论:七项全部已在当前 head 修复,无遗留未解决项。未新推修复——所有修复均已在 head 内,本轮只做独立验证。

复核方式。 本轮自写独立探针(probe-pr177.test.ts,9 项,与产品自有测试文件不共享任何代码),驱动真实 createRuntimeStore(真实 SQLite worker)与真实 acpMutations.js / acpInteractions.js / acpExtensions.js。每项 finding 另做 RED 对照:把对应文件的修复前版本换入后探针必须转红,以证明探针真能检出该缺陷而非空过。

第一轮 4 项

  1. 并发完成竞争 process revision、遗留会话租约 — 已修复。修复前(e198723a7 的 acpMutations.js)实测 ['entity_revision','native-executed'] 且租约残留、后续操作 session_busy;当前 head 为 ['native-executed','native-executed']、两个租约均为 null、后续操作 ok。另跑 2/5/8 会话集中完成,并在每个终局 CAS 注入一次 revision 冲突:全部 native-executed、无租约残留、native 调用各恰好 1 次。
  2. 幂等摘要遗漏 interaction identity — 已修复。修复前第二项不报 mismatch;当前 head 实测 ['native-executed','idempotency_mismatch',[7],['replied','pending'],1]。
  3. 同 prompt 内顺序复用 native ID 被误判为重复 — 已修复。当前 head 实测 ['ok',[7,7],7,true]。
  4. 重试较早的配置操作回滚当前缓存 — 已修复。当前 head 实测 ['native-executed','native-executed','already-completed',['session/set_config_option:b','session/set_config_option:a'],'a'],native 配置调用仍只有两次。

第二轮 2 项残留

  1. 并发收尾固定重试四次仍留下租约 — 已修复。终局 CAS 已不再把共享 process 行写入 guard(acpMutations.js L268-294),改为每 attempt 复核 generation;8 会话 + 注入冲突探针全绿。
  2. native 答复已发出后立即复用 ID 仍被误判为占用 — 已修复。修复前(33f96318f)转红;当前 head 实测 [['ok'],[7],true,'ok',[7,7]]。

第三轮 1 项残留

  1. 旧回复收尾会清除新一轮回复的 answered 标记,第三次复用 ID 仍失败 — 已修复。修复前(af82d881d)实测 [2,'duplicate_native_request',[7,7],2],与复核描述逐字一致;当前 head 实测 [2,'ok',[7,7,7],3],"新 receipt 先收尾"的相反时序同样通过。

未过度收紧:真正并发占用同一 native ID 仍被拒绝 [['duplicate_native_request','ok'],1,1]。

门禁(当前 head):vitest run app/runtime --testTimeout=20000 → 19 文件 297 通过;oxlint app/runtime bridge/runtime → 0 error 0 warning;vue-tsc --noEmit → exit 0。5/8 会话集中完成用例本机耗时约 5.5s,已按已披露方式以 20s 超时运行通过;默认 5s 下会超时,属本机磁盘性能、非逻辑缺陷,未记为问题。

未验证:未启动真实 ACP CLI / installed OpenCode / live SSH/Slurm;未跑全仓 vitest(仅 app/runtime);未做 vite build 与浏览器 QA。已知非阻塞 flake(runtimeGit 200-workspace、kimiWebWsProxy 502)在 app/runtime 之外,本轮未触及。

结论:#177 全部七项 finding 在当前 head b152b055c 关闭。

receive() cleared the answered mark for an occupancy key before the new
receipt's claim was durable. When the previous receipt's release() landed
inside that window it saw own === false and swept the very occupancy row
the claim's CAS was preconditioned on, so a legitimate native-ID reuse was
rejected with an internal entity_revision instead of being admitted.

The occupancy emptied by that sweep is exactly the state in which re-use is
allowed, so the claim is now retried (bounded, re-reading the occupancy and
the process guard); a row still held by another receipt keeps rejecting as
duplicate_native_request, and a genuinely concurrent same-ID claim is
unchanged.

Regression: a claim parked under the previous release sweep still admits
the reused native ID. RED before the fix: [true, 'entity_revision', 1];
GREEN after: [true, undefined, 2].

Copy link
Copy Markdown
Owner Author

AI 辅助增量静态复核(dot)

审查 head:1d5aa436a9564cdb9e52b9262bd534d6fa9ac958
增量起点:b152b055c1c7803467e48cd23454e181a7c6b85e
PR base:98a4474b540c1258c3e485ec98e013eff3d2047b

本次仅有一个新提交、两个变更文件;base 未变,继承的 #175/#176 内容及此前 ACP 修复不重复计入本次增量。

已核实的实质变更

acpInteractions.js L49–98 为新 receipt 的 claim 增加了最多四次尝试:遇到 revision conflict 且重新读取的 occupancy 已空时,刷新 process authority 后重新读取并提交;仍被占用时返回 duplicate_native_request,耗尽尝试时返回 concurrent_update。

这针对旧 receipt 的 release 清空 occupancy、恰好使新 claim 的预期 revision 失效的窗口。旧实现对已空的 occupancy 直接重新抛出 entity_revision;当前源码已明确改为上述有界重试。对照了 release、authority 和 compareRecord 的调用契约,确认重试会重新取得 guard,而非复用失败的 revision。

新增回归 L632–739 将第二次 claim 暂停到第一次回复收尾完成之后,再放行并检查第二次 receive 成功且产生两个 pending 事件。测试源码覆盖意图与本次改动一致,建议保留该定点时序回归。

CI 与覆盖边界

该 head 的 CI 39269775600 已 completed / success:Validate 的 lint/type-check、tests、web build 均成功,全部 Electron/Bridge 安装器任务及 Complete CI 成功;Publish draft release 为 skipped。

本次结论来自只读 diff、相关源码/测试对照及 GitHub CI 状态;没有独立执行权限/RPC 竞争复现、真实 SQLite/ACP CLI 或完整测试套件。此前受限的安全复现未重试,也没有借用作者评论中的 RED/GREEN 或“七项全部关闭”作为我的独立验证。本次未形成可独立核实的新缺陷,不将静态确认与 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.

1 participant