fix: address ds-review-bot v7 findings on the merged image-input head

- gate model selection on steering-placement image carriers from enqueue
  until their steering/message event publishes; release the gate when an
  admission ends idle without publication (both behaviorally asserted)
- reject session.updateQueue edits carrying non-text blocks at the RPC
  boundary (queue edits cannot bypass image admission)
- extend the durable-directory walk past a first-created DSH_HOME to the
  deepest pre-existing ancestor
- strip Windows-style separators from attachment display names on POSIX
- verify attachment reads with a header-only probe (digest already proves
  the bytes decoded fully at admission); document the read path
- make SessionInputShell.addImages refusal observable and keep workspace
  transfers/composer intake from leaking refused drafts
- own ONE recursive image walk (dsh-llm contentHasImage) across apiproxy,
  pi-ai, compact-basic, and the DeepSeek text-only assertion
- drop the redundant canonical-base64 regex and the no-op role read
- move AttachmentId/AttachmentError out of types.ts (brand.ts/error.ts);
  document why AttachmentError does not extend HarnessError
- document the hard attachments inject in both consumer READMEs
This commit is contained in:
creatixchu
2026-07-30 14:34:08 +08:00
parent 97cf33b7e0
commit 0d1250f743
37 changed files with 335 additions and 140 deletions

View File

@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/bug-fix/2026-07-29-atomic-web-image-admission.md
2026-07-29-atomic-web-image-admission.md: 7b2f7aeb43ca1393cdab3abe35916964bc47f0c9
2026-07-29-atomic-web-image-admission.zh.md: 5a04d2e599744dfe9f92eb64a6c828161c46bf6e
2026-07-29-atomic-web-image-admission.md: c09d376f101a41994df3a10c22c06da4e59f06f6
2026-07-29-atomic-web-image-admission.zh.md: 8785f7489b0c433cba43a1747533b1d38aada3d3

View File

@@ -12,7 +12,7 @@ Image prompt admission and `session.selectModel` each read session modality stat
Each live Web agent has one private promise chain shared by image-bearing prompt admission and model selection. A failed operation settles its caller normally and leaves the chain usable. Text-only prompts bypass the chain because they cannot change the modality constraint.
The pending-inbox mirror marks a prompt as claimed at dequeue and retains it until the matching `user/message` or `steering/message` event publishes. If admission ends without publishing, the next dequeue or the transition to idle retires the claimed entry; inbox discard retires the listed work, and session disposal retires every remaining entry. Model selection checks that mirror plus `Session.deriveMessages()`, which is the current model-visible history after compaction.
The pending-publication set records a queued occurrence at dequeue and a steering occurrence already at enqueue (steering items never enter the queued UI mirror), and retains each until its matching `user/message` or `steering/message` event publishes. If admission ends without publishing, the transition to idle retires the entries; inbox discard retires the listed work, and session disposal retires every remaining entry. Model selection checks that set, the queued UI mirror, and `Session.deriveMessages()`, which is the current model-visible history after compaction.
Provider adapters remain the final enforcement boundary. The host ordering only prevents its mutable route and pending image state from contradicting each other before request assembly.

View File

@@ -12,7 +12,7 @@ Status: implemented
每个活跃 Web agent(智能体)都有一条私有 promise 链,由包含图片的提示词准入与模型选择共享。操作失败会照常传递给调用方,且不会使该链失效。纯文本提示词绕过该链,因为它们不会改变模态约束。
待处理 inbox 镜像会在提示词出队时将其标记为已认领,并保留到匹配的 `user/message` 或 `steering/message` 事件发布。若准入结束时未发布事件,下一次出队或转为空闲状态会移除已认领的条目;inbox 丢弃会移除列出的工作项,会话 dispose(资源释放)则会移除所有剩余条目。模型选择会检查该镜像以及 `Session.deriveMessages()`;后者表示压缩后模型当前可见的历史。
待发布集合会在排队条目出队时记录它,而 steering 条目在入队时即被记录(steering 条目从不进入排队 UI 镜像),并各自保留到匹配的 `user/message` 或 `steering/message` 事件发布。若准入结束时未发布事件,转为空闲状态会移除这些条目;inbox 丢弃会移除列出的工作项,会话 dispose(资源释放)则会移除所有剩余条目。模型选择会检查该集合、排队 UI 镜像以及 `Session.deriveMessages()`;后者表示压缩后模型当前可见的历史。
提供方适配器仍是最终的强制检查边界。宿主的顺序控制仅用于避免其可变路由与待发布图片状态在请求组装前彼此矛盾。