Skip to content

fix(managed-agent): reconcile approval delivery and concurrent session titles - #13682

Merged
yiliang114 merged 31 commits into
mainfrom
fix/hosted-approval-redelivery
Oct 11, 2026
Merged

yiliang114 merged 31 commits into
mainfrom
fix/hosted-approval-redelivery

Conversation

@yiliang114

@yiliang114 yiliang114 commented Oct 8, 2026 •

Copy link
Copy Markdown
Collaborator

What this PR does

Recover accepted Workspace approval answers after dispatcher attachment-cache loss with the default recovery configuration. Keep Harness-disabled replicas from claiming pending deliveries, while allowing them to settle answers whose committed journal already proves a final outcome. Renew approval claims during slow attachment or answer delivery.

Keep public and Harness Session titles consistent under concurrent rename requests and ambiguous HTTP results. Each admitted attempt has a durable, increasing revision; the final journal write fences older attempts, and a stored delivery repairs a lost reply without appending a second title. A FAILED same-key retry remains usable after a newer rename succeeds. Both inline and recovery requests claim before remote I/O; expired owners cannot retire a replacement owner's receipt. Fresh disabled or unsupported Harness requests and Unicode-only titles are refused before admission. A named superseded conflict remains HTTP409 at the public boundary. Workspace migration counts unfinished title work even after the public command fails. Rename replay probes avoid missing-row gap locks while retaining tenant and Session serialization.

Why it's needed

wenshao's round-9 verification of #13163 found accepted approvals stuck after cache loss, disabled replicas taking claims they cannot deliver, and concurrent renames leaving the public and private titles different. This PR handles these related follow-ups together. A SQL completion guard alone cannot prevent an older remote write from finishing last.

While an admitted write remains uncertain, recovery and lifecycle/migration barriers are retained. A permanently unavailable Harness is an explicit external blocker; a later refusal or retry count is not proof that an earlier remote write never committed. This is the owner-confirmed contract.

Current conflict repair: 638b97984214 additively merges main d35277c, and ab1af693957b renumbers the rename-delivery migration from V66 to V67 because main's V66 is now the agent-definition digest (#13530). The upgrade history retains V67 rename delivery, V60 child workspace and upstream V62 task cancellation; rename SQL and both migration guards remain intact. The approval/rename patch scope is unchanged. Fresh focused verification and new-head CI are attributed separately in the acceptance record. Formal human approval and an authorized merge remain outstanding.

Reviewer Test Plan

How to verify

  • Answer a pending Workspace approval after losing the dispatcher attachment cache while the Broker keeps running (verified-workspace-recovery-enabled=false), e.g. the answer lands on another replica. Expect the original operation to complete, the Action to be decided, and the expected file effect to occur once. A Workspace READER remains refused; an authorized second OPERATOR can answer the owner’s approval, and same-responder replay returns the same operation. This item does not cover a dispatcher restart (TERM/SIGKILL), where the attachment cache and the embedded Broker restart together: there the answer is still delivered, but the Harness then logs recovery blocked: Runtime Broker returned HTTP 404 (runtime_session_not_found) and the Turn stays RUNNING until cancelled. That wedge is pre-existing — an unapproved plain tool Turn across the same restart wedges identically on base and head — so it is not a regression of this PR, and no open issue currently carries it; the adjacent tracked work is Runtime Broker: a restarted Broker can neither adopt nor retire a local-process worker #12766 / Runtime Broker: an execution in flight at host reboot pins the LOST binding forever #12670, and fix(managed-agent): #13163 follow-ups: cold-cache cancel and deferred review suggestions #13269 explicitly disclaims the restart case.

  • Let a Harness-disabled replica recover a shared database. A requested answer keeps its claim and retry schedule; an answer whose journal Action has already ended can settle without a Harness call. Hold enabled delivery beyond its initial lease and confirm another replica cannot take over while the worker renews it.

  • Hold an accepted rename before its final journal transaction, let its request time out after sending, and complete a different-key rename through another replica. Release the older request and expect both durable titles to remain the newer title. Retry the FAILED original key and expect a fresh revision that can become the latest title.

  • Lose the reply after the latest private title is committed. Expect scheduled recovery to complete its public receipt without a manual retry or another title record. Verify this also works for the first rename of an empty bound or unbound Session. Replaying a completed key produces no new write; changed content under that key still conflicts.

  • While the latest title delivery is unfinished, close, archive, delete, cwd change and Workspace migration refuse admission, even if the public command is FAILED. Once delivery completes, admission can proceed.

  • Refuse a fresh rename on a disabled or old-protocol Harness before creating a command/delivery; the Session can still close. A healthy inline delivery cannot be claimed immediately by a peer. After lease expiry and takeover, stale or null-owner cleanup leaves the replacement receipt unchanged. An invalid reply after sending remains recoverable.

  • Submit Unicode-only titles (NBSP, FEFF, U+2007 or U+202F). Expect 400 invalid_title, no rename command or delivery, and continued close admission. A title containing visible text preserves its exact Unicode content. A contract-valid Harness 409 session_mutation_superseded stays public409; unrelated conflicts and ambiguous failures keep the dependency error path.

Evidence (Before & After)

Actual source CLI tmux captures show the WriteFile permission, its real file effect and /rename updating display and isolated storage. Actual source WebShell UI allowed an approval after connector cache loss and a controlled private503; the real scheduler recovered the same operation without another first-action response. A second composer submission rejected WriteFile and Edit and left the file unchanged. API rename plus actual Refresh displayed the same durable title. See the acceptance record for images and exact source/provider boundaries.

Before: round 9 recorded repeated attachment conflicts, claims by a disabled replica, and settled public/private title divergence. After: focused SDK, Core, Hosted route and Spring regressions cover the contracts above. Controlled real Spring/H2 + current Node Harness probes exercise cross-replica delayed writes, an actual SDK deadline with remote work still alive, automatic lost-reply recovery, and cache-loss approval delivery with a real worker file effect. The separate acceptance comment records the delivered commit, exact results, initial failed probes and negative controls.

Tested on

OS Status
🍏 macOS ✅ Focused native checks and real local HTTP paths
🊟 Windows ⚠ïļ Not locally tested; CI reported separately
🐧 Linux ⚠ïļ Not locally tested; CI reported separately

Environment

Java 21, Node 22+, source CLI and current compiled Core/Java SDK, two Spring contexts sharing H2, independent local Brokers and an authorized mount. The approval provider and transport failures are controlled fixtures; the HTTP, journal, scheduler and worker paths are real. UI/TUI evidence remains attributed to61449726; later main integrations and this conflict repair have separately attributed focused verification and CI. It does not relabel the earlier runtime evidence as a new run.

Risk & Scope

  • The two stores are separate transactions. Titles may temporarily differ while delivery is pending; durable recovery establishes equality for the latest admitted attempt. Unfinished delivery blocks lifecycle sealing, cwd changes and Workspace migration. Admitted work stays pending when a later dependency/protocol refusal cannot prove that earlier requests never wrote; no retry cap discards ambiguous outcomes.
  • Flyway V67 sits above main’s highest applied version (V66 managed session agent-definition digest), so a database already migrated by current main applies it in order instead of failing Flyway validation, and it adds one latest rename-delivery row per Session. The earlier colliding versions were unmerged; the table and delivery contract are unchanged. Fenced writes require Hosted title protocol 1. Deploy the updated Harness and SDK/server together; mixed old rename writers are outside the ordering guarantee. The SDK refuses an unsupported Harness before sending a versioned mutation.
  • Actual source-browser and tmux acceptance is covered above. Local observations use H2 and a controlled provider; real-model, production-database and packaged-CLI acceptance are not claimed. The broader follow-up backlog in fix(managed-agent): #13163 follow-ups: cold-cache cancel and deferred review suggestions #13269 remains open; this PR addresses the approval and rename contracts described here.
  • Linked, synchronized designs: rename delivery / äļ­æ–‡, and approval delivery / äļ­æ–‡.

Linked Issues

Follow-up to #13163 and the approval/rename findings in #13269.

äļ­æ–‡čŊŽ

æ”đåŠĻ

åœĻéŧ˜čŪĪæĒåĪé…į―Ūäļ‹ïžŒæĒåĪč°ƒåšĶå™ĻäļĒåĪąé™„į€įž“å­˜åŽå·ēå—į†įš„ Workspace åŪĄæ‰đį­”åĪã€‚į́į”Ļ Harness įš„å‰Ŋ朎äļčŪĪédžåū…投递äŧŧåŠĄïžŒä―†čƒ―æ đæŪå·ē提äšĪ journal čŊæ˜Žįš„įŧˆæ€į›īæŽĨįŧ“įŪ—į­”åĪã€‚é™„į€æĒåĪæˆ–į­”åĪæŠ•é€’įž“æ…Ēæ—ķ持įŧ­įŧ­į§ŸïžŒé˜ēæ­Ēæ­Ģåļᅧ•递čĒŦå…ķäŧ–å‰Ŋ朎æŽĨįŪĄã€‚

čŪĐåđķ发æ”đ名和äļįĄŪåŪšįš„ HTTP įŧ“果最įŧˆäŋæŒå…Žå…ąæ ‡éǘäļŽ Harness 标éǘäļ€č‡ī。æŊæŽĄå—ᐆæ‹Ĩ有持äđ…递åĒžį‰ˆæœŽïž›æœ€įŧˆ journal 写å…Ĩ拒įŧæ—§į‰ˆæœŽïžŒæŒäđ…æŠ•递čĄĨé―äļĒåĪąå›žåŒ…č€Œäļčŋ―åŠ įŽŽäšŒæĄæ ‡éǘčŪ°å―•ã€‚čūƒæ–°įš„æ”đ名åŪŒæˆåŽïžŒåŽŸ FAILED åđ‚į­‰é”Ūäŧčƒ―äŧĨæ–°į‰ˆæœŽé‡čŊ•。同æ­ĨčŊ·æą‚äļŽæĒåĪčŊ·æą‚éƒ―先čŪĪéĒ†å†æ‰§čĄŒčŋœįŦŊ I/Očŋ‡æœŸæ‰€æœ‰č€…äļčƒ―é€€äž‘æ–°æ‰€æœ‰č€…įš„å›žæ‰§ã€‚æ–°į́į”Ļ或äļæ”Ŋ持协čŪŪįš„ Harness čŊ·æą‚äŧĨ及įšŊ Unicode įĐšį™―æ ‡éǘåœĻå—į†å‰čĒŦ拒įŧïž›åļĶæ˜ŽįĄŪ superseded 错čŊŊį įš„å†ēįŠåœĻ兎垀æŽĨåĢäŋæŒ409。Workspace čŋį§ŧåœĻå…Žå…ąå‘―äŧĪåĪąčīĨ后äŧįŧŸčŪĄæœŠåŪŒæˆæ ‡éǘå·Ĩä―œïž›æ”đ名重æ”ūæŽĒæĩ‹į§ŧé™ĪįžšåĪąčĄŒįš„é—ī隙锁äŋį•™į§Ÿæˆ·å’Œ Session äļēčĄŒåŒ–ã€‚

原因

wenshao åŊđ #13163 įš„įŽŽäđč―Ū驌čŊå‘įŽ°äš†įž“å­˜äļĒåĪąåŽåŪĄæ‰đį­”åĪåœæŧžã€į́į”Ļå‰Ŋ朎æŠĒ占无æģ•åŪŒæˆįš„æŠ•é€’ïžŒäŧĨ及åđķ发æ”đ名造成äļĪäū§æ ‡éǘäļåŒã€‚朎 PR äļ€čĩ·å΄ᐆčŋ™äš›į›ļå…ģ后įŧ­é—ŪéĒ˜ã€‚åŠåœĻ SQL åŪŒæˆæ—ķæĢ€æŸĨ无æģ•é˜ŧæ­Ē旧čŋœįŦŊ写å…Ĩæœ€åŽč―į›˜ã€‚

åŪĄé˜…éŠŒčŊ

  • éŧ˜čŪĪ verified-workspace-recovery-enabled=falseåœĻ Broker äļé‡åŊįš„å‰æäļ‹äļĒåĪąé™„į€įž“å­˜åŽå›žį­”åū…åŪĄæ‰đ Actionäū‹å͂᭔åĪč―åˆ°åĶäļ€äļŠå‰Ŋ朎。éĒ„æœŸåŽŸ operation åŪŒæˆã€Action å·ēå†ģåŪšã€æ–‡äŧķæ•ˆæžœå‘į”Ÿäļ€æŽĄïž›Workspace READER äŧčĒŦ拒įŧïž›å…·åĪ‡æƒé™įš„įŽŽäšŒä― OPERATOR åŊäŧĨå›žį­” owner įš„åŪĄæ‰đ同äļ€į­”åĪäššįš„é‡æ”ūäŧčŋ”回原 operationã€‚æœŽæĄäļč͆ᛖæīū发å™ĻᜟåŪžé‡åŊTERM/SIGKILLïžŒé™„į€įž“å­˜äļŽå†…åĩŒ Broker 同æ—ķ重åŊé‚Ģį§æƒ…å†ĩäļ‹į­”åĪäŧäžšé€čūūïžŒä―† Harness 随后čŪ°å―• recovery blocked: Runtime Broker returned HTTP 404 (runtime_session_not_found)Turn äļ€į›ī RUNNING į›ī到čĒŦ取æķˆã€‚čŊĨåĄæ­ŧæ˜Ŋæ—Ē有é—ŪéĒ˜â€”â€”äļåļĶåŪĄæ‰đįš„æ™Ū通å·Ĩ具 Turn įŧåŽ†åŒæ ·é‡åŊæ—ķbase äļŽ head åŒæ ·åĄæ­ŧ——因æ­Īäļæ˜Ŋ朎 PR įš„å›žå―’ïž›į›Ū前äđŸæēĄæœ‰å·ē垀 issue æ”ķå―•åŪƒïžŒį›ļé‚ŧįš„åœĻ跟čļŠéĄđæ˜Ŋ Runtime Broker: a restarted Broker can neither adopt nor retire a local-process worker #12766 / Runtime Broker: an execution in flight at host reboot pins the LOST binding forever #12670ïžŒč€Œ fix(managed-agent): #13163 follow-ups: cold-cache cancel and deferred review suggestions #13269 å·ē明įĄŪ排é™Ī重åŊ情å―Ē。

  • į́į”Ļ Harness įš„å‰Ŋ朎æĒåĪå…ąäšŦ数æŪåš“æ—ķrequested į­”åĪįš„čŪĪéĒ†å’Œé‡čŊ•æ—ķé—īäŋæŒäļå˜ïž›journal å·ēčŊæ˜Žįŧ“æŸįš„į­”åĪæ— éœ€ Harness åģåŊįŧ“įŪ—ã€‚čŪĐåŊį”Ļå‰ŊæœŽįš„æŠ•é€’čķ…čŋ‡åˆå§‹į§ŸįšĶįŧ­į§ŸæœŸé—īå…ķäŧ–å‰Ŋ朎äļčƒ―æŽĨįŪĄã€‚

  • 将å·ēæŽĨå—įš„æ”đ名停åœĻ最įŧˆ journal äš‹åŠĄå‰ïžŒčŪĐčŊ·æą‚åœĻ发送后čķ…æ—ķ再通čŋ‡åĶäļ€å‰Ŋ朎åŪŒæˆæ–°é”Ūæ”đ名。释æ”ū旧čŊ·æą‚后äļĪäū§æŒäđ…æ ‡éĒ˜åš”äŧæ˜Ŋ新标éĒ˜ã€‚é‡čŊ•原 FAILED é”ŪïžŒåš”čŽ·åū—æ–°į‰ˆæœŽåđķčƒ―æˆäļšæœ€æ–°æ ‡éĒ˜ã€‚

  • æœ€æ–°į§æœ‰æ ‡éĒ˜æäšĪ后äļĒåĪąå›žåŒ…ïžŒéĒ„æœŸåۚæ—ķæĒåĪč‡ŠåŠĻčĄĨé―å…Žå…ąå›žæ‰§ïžŒæ— éœ€æ‰‹åŠĻ重čŊ•äđŸäļæ–°åĒžæ ‡éǘčŪ°å―•ã€‚įĐšįš„įŧ‘åŪšæˆ–æœŠįŧ‘åۚ Workspace įš„ Session éĶ–æŽĄæ”đ名äđŸåš”åĶ‚æ­Ī。重æ”ūå·ēåŪŒæˆé”Ūäļå†™å…Ĩ同é”Ūæ”đæĒ内åŪđäŧå†ēįŠã€‚

  • 最新标éĒ˜æŠ•é€’æœŠåŪŒæˆæ—ķå…ģé—­ã€å―’æĄĢ、删é™Ī、cwd 变æ›ī及 Workspace čŋį§ŧ拒įŧå‡†å…ĨïžŒåŒ…æ‹Žå…Žå…ąå‘―äŧĪäļš FAILED įš„æƒ…å†ĩ投递åŪŒæˆåŽæĒåĪå‡†å…Ĩ。

  • į́į”Ļ或旧标éĒ˜åčŪŪįš„ Harness åœĻ新æ”đ名å…Ĩ嚓前čĒŦ拒įŧïžŒäļį•™äļ‹å‘―äŧĪ和投递Session äŧåŊå…ģ闭。æ­Ģåļļ同æ­Ĩ投递äļčƒ―čĒŦ同äžīįŦ‹åģčŪĪéĒ†ïž›į§ŸįšĶ到期æŽĨįŪĄåŽïžŒæ—§æ‰€æœ‰č€…æˆ–įĐšæ‰€æœ‰č€…æļ…ᐆäļæ”đ变新回执。发送后回包无效äŧįŧ§įŧ­æĒåĪã€‚

  • įšŊ Unicode įĐšį™―æ ‡éĒ˜ïžˆNBSP、FEFF、U+2007、U+202Fčŋ”回400 invalid_titleäļæ–°åĒžæ”đåå‘―äŧĪæˆ–投递åđķäŧå…čŪļ close 准å…Ĩ。包åŦåŊč§æ–‡å­—įš„æ ‡éǘäŋį•™åŽŸ Unicode 内åŪđ合æģ•į§æœ‰ superseded 409 åœĻ兎垀æŽĨåĢäŋæŒ409å…ķäŧ–å†ēįŠå’ŒäļįĄŪåۚåĪąčīĨįŧåŽŸäūčĩ–é”™čŊŊč·Ŋåū„。

前后čŊæŪ

äŋŪåĪå‰ïžŒįŽŽäđč―ŪčŪ°å―•äš†é‡åĪé™„į€å†ēįŠã€į́į”Ļå‰ŊæœŽįš„äŧŧåŠĄčŪĪéĒ†ïžŒäŧĨ及įĻģåŪšåŽįš„å…Žå…ąäļŽį§æœ‰æ ‡éǘå·Ū垂。äŋŪåĪåŽïžŒSDK、Core、Hosted č·Ŋį”ąå’Œ Spring åŪšå‘å›žå―’č͆ᛖčŋ™äš›åĨ‘įšĶã€‚å—æŽ§įš„įœŸåŪž Spring/H2 äļŽå―“前 Node Harness æŽĒ针驌čŊč·Ļå‰Ŋ朎čŋŸåˆ°å†™å…Ĩ、SDK ᜟæ­Ģčķ…æ—ķ后äŧå­˜æīŧįš„čŋœįŦŊå·Ĩä―œã€äļĒåĪąå›žåŒ…įš„č‡ŠåŠĻæĒåĪïžŒäŧĨåŠįž“å­˜äļĒåĪąåŽįš„åŪĄæ‰đæŠ•é€’å’ŒįœŸåŪž worker 文äŧķæ•ˆæžœã€‚å•į‹Žįš„éЌæ”ķčŊ„čŪščŪ°å―•äšĪäŧ˜æäšĪ、įĄŪ切įŧ“果、初始åĪąčīĨæŽĒ针及反向銌čŊã€‚

åđģ台äļŽįŽŊåǃ

macOS å·ēčŋčĄŒåŪšå‘åŽŸį”ŸæĢ€æŸĨå’ŒįœŸåŪžæœŽåœ° HTTP č·Ŋåū„。Windows、Linux 朊åœĻ朎地銌čŊïžŒCI įŧ“æžœåĶ行čŪ°å―•ã€‚įŽŊåǃäļš Java 21、Node 22 及äŧĨäļŠã€æšį  CLIã€å―“å‰įž–čŊ‘įš„ Core äļŽ Java SDKã€å…ąäšŦ H2 įš„äļĪäļŠ Spring contextã€į‹ŽįŦ‹æœŽåœ° Broker 及å·ēæŽˆæƒæŒ‚č――ã€‚åŪĄæ‰đæĻĄåž‹äļŽäž čū“æ•…éšœæ˜Ŋ受控åĪđå…·ïž›HTTP、journalã€č°ƒåšĶå™ĻäļŽ worker č·Ŋåū„æ˜ŊᜟåŪžåŪžįŽ°ã€‚

éĢŽé™ĐäļŽčŒƒå›ī

äļĪäū§å­˜å‚Ļäļæ˜Ŋ同äļ€äš‹åŠĄïžŒæŠ•é€’å°šæœŠåŪŒæˆæœŸé—īåŊčƒ―æš‚æ—ķäļåŒïž›æŒäđ…æĒåĪäŋčŊæœ€æ–°å—į†å°čŊ•最įŧˆäļ€č‡ī。朊åŪŒæˆæŠ•é€’é˜ŧæ­Ēį”Ÿå‘―å‘Ļ期封存、cwd 变æ›ī及 Workspace čŋį§ŧã€‚å—į†åŽå‡šįŽ°äūčĩ–或协čŪŪæ‹’įŧæ—ķäļčƒ―æŪæ­ĪčŊæ˜Žčūƒæ—ĐčŊ·æą‚äŧŽæœŠå†™å…Ĩïž›äļäŧĨ重čŊ•æŽĄæ•°äļŠé™äļĒ垃äļįĄŪåۚįŧ“果。Flyway V67 éŦ˜äšŽ main å―“å‰æœ€éŦ˜įš„å·ēåš”į”Ļį‰ˆæœŽïžˆV66 managed session agent definition digest因æ­Īå·ēčĒŦå―“å‰ main čŋį§ŧčŋ‡įš„æ•°æŪåš“äžšæŒ‰éĄšåšåš”į”ĻåŪƒč€Œäļæ˜ŊåœĻ Flyway æ ĄéŠŒæ—ķåĪąčīĨåđķäļšæŊäļŠ Session äŋå­˜äļ€čĄŒæœ€æ–°æ”đ名投递。原å†ēįŠį‰ˆæœŽå°šæœŠåˆåđķčĄĻäļŽæŠ•é€’åĨ‘įšĶäŋæŒäļå˜ã€‚åļĶå›īæ įš„å†™å…ĨčĶæą‚ Hosted 标éĒ˜åčŪŪ 1嚔äļ€čĩ·éƒĻį―翛°åŽįš„ Harness 和 SDK/server旧æ”đ名 writer æ··į”ĻäļåœĻ排嚏äŋčŊå†…。SDK åœĻ发送åļĶį‰ˆæœŽå˜æ›ī前拒įŧäļæ”ŊæŒįš„ Harness。

å·ēåŪŒæˆåŪžé™…æšį æĩč§ˆå™ĻäļŽtmux驌æ”ķïžšåŪĄæ‰đ允čŪļåŠįž“å­˜äļĒåĪąåŽįš„åۚæ—ķæĒåĪã€čū“å…ĨæĄ†å†æŽĄå‘é€ã€æ‹’įŧåŽæ–‡äŧķäļå˜ïžŒäŧĨ及APIæ”đ名后åŪžé™…åˆ·æ–°æ˜ūįĪšïž›ANSI/plain captureäļŽæˆŠå›ūåœĻ驌æ”ķčŪ°å―•äļ­ã€‚朎地ä―ŋį”ĻH2äļŽå—控provideräļå̰᧰ᜟåŪžæĻĄåž‹ã€į”Ÿäš§æ•°æŪ嚓或打包CLI驌æ”ķ。#13269 įš„å…ķäŧ–后įŧ­äš‹éĄđäŋæŒåž€æ”ū朎 PR å΄ᐆäļŠčŋ°åŪĄæ‰đäļŽæ”đ名åĨ‘įšĶ。æ”đ名投递及åŪĄæ‰đčŪūčŪĄįš„äļ­č‹ąæ–‡æ–‡æĄĢå·ēé“ūæŽĨåđķ同æ­Ĩ。

å…ģ联 #13163 äļŽ #13269 įš„åŪĄæ‰đ和æ”đ名é—ŪéĒ˜ã€‚

äļ­æ–‡čĄĨå……ïžšį”Ļ户å·ēå†æŽĄįĄŪčŪĪäŋį•™åŪ‰å…ĻæĒåĪäļŽæ°ļäđ…äūčĩ–äļåŊį”Ļįš„åĪ–éƒĻé˜ŧåĄžčūđį•ŒïžŒæ”đ名退䞑æ‰Đåą•å·ēæ’Īå›žã€‚å―“å‰æäšĪ638b979842143478966430c4489b9cedc1b7b4d3čŋ―加合å…ĨåŪžé™…main d35277cåđķį”ąab1af693957bd908157297f6e624a4e4a69d62cf将æ”đ名投递čŋį§ŧV66é‡įž–å·äļšV67mainįš„V66įŽ°äļšagent-definition digestïž‰ïžŒå‡įš§åŽ†åēäŋį•™V67、V60、äļŧįšŋV62æ”đ名SQL和äļĪé“į‹ŽįŦ‹čŋį§ŧæĢ€æŸĨäļå˜ïžŒčŒƒå›īäŧ38文äŧķ+1305/-72。æ­ĪæŽĄåŪšå‘éŠŒčŊåŠæ–°head CIčŊĶ见驌æ”ķčŊ„čŪšïž›åŽŸ0f候选189éĄđ、65技æœŊCI及614åŪžé™…UI/TUIäŋæŒåŽŸæäšĪå―’åąžã€‚äļŧįšŋäŧŧåŠĄå–æķˆäļäŧĢčĄĻ朎PRåĒžåŠ æ”đ名取æķˆåĨ‘įšĶ。æ­Ģ垏䚚å·Ĩæ‰đå‡†åŠčŽ·æŽˆæƒįš„äššåˆåđķäŧåū…åŪŒæˆã€‚

Keep accepted Workspace approval responses deliverable with the default recovery configuration after attachment-cache loss. Leave approval retry claims untouched on Harness-disabled replicas.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
@yiliang114

Copy link
Copy Markdown
Collaborator Author

Verified commit: 4bd76069532dd3b17eee533c4f1790558a118331 (base 95f6aa9c0fd2a1e8d3d8fff56dfd59d34ce54531). Final commit bytes match all eight frozen candidate file hashes; commit hooks left those inputs unchanged.

Java compilation and 74/74 focused tests pass (47 connector, 26 public/action-service/JDBC, one disabled-coordinator regression), with zero Checkstyle violations. Both design translations pass formatting. An independent bounded correctness review found no actionable issue; the security scout's cold/profile trace was completed by a focused source check. The existing W1 contract treats verified-workspace-recovery-enabled as physical mount verification, independently of Hosted cold-load validation. All existing identity, profile, approval-mode, grants and mount checks remain.

A real local Spring/H2 + current-source Node Harness/Broker/worker probe passed in 9.98 seconds with the recovery setting checked as false. It injected one resolve 503, observed the accepted operation pending at attempt/claim generation 1, then cleared the enabled connector cache. The real resident load returned 200 with passiveManagedRuntimeRecovery:true; the original operation completed/decided, its target answer reached the Harness successfully exactly once, and REST/WebShell replays retained that operation ID. The worker completed the Turn and wrote child/proof.txt=after.

Check Observed result
Production Harness-disabled replica sharing the database One direct dispatch plus eight calls to recover left operation state, delivery state, attempts, claim generation, retry time and lease fields unchanged
Roll back the bound-Workspace passive-load override in an isolated class directory Existing default=false connector regression fails on the missing passive marker
Roll back both availability guards in an isolated class directory Existing disabled-coordinator regression fails on the unexpected store interaction
Candidate stability and cleanup Current source/compiled targets unchanged by both controls; both owned runtime process groups stopped

The first observer attempt failed before the approval assertions because its proxy omitted the required Harness boot response header. The failed attempt was preserved, the proxy was corrected, and the separate passing run produced the evidence above. Maven also warned about an expired certificate at an optional metadata source; the resolved Checkstyle plugin completed successfully.

Limits: scripted model and controlled 503; H2; two Spring contexts in one JVM; cache clearing rather than a dispatcher process crash; disabled recovery methods invoked deterministically rather than an autonomous scheduler race. This does not establish real-model, full process-death, MySQL/MariaDB, browser-click, or packaged-CLI acceptance. Current CLI TypeScript source and unchanged built dependencies were used. No dependency install or full CLI build/test suite ran. The referenced review-gate and pr-ui-verify skills are not installed, so neither formal workflow is claimed. Concurrent rename consistency remains in #13269.

äļ­æ–‡éЌčŊčŊŽ

驌čŊåŊđ嚔提äšĪ 4bd76069532dd3b17eee533c4f1790558a118331。提äšĪåŽįš„å…ŦäļŠæ–‡äŧķäļŽå·ē驌čŊå€™é€‰įš„哈åļŒäļ€č‡ī提äšĪ hook æēĄæœ‰æ”đ变内åŪđ。Java įž–čŊ‘、74 äļŠį›ļå…ģæĩ‹čŊ•äļŽé›ķé—Ūéǘ Checkstyle 均通čŋ‡ïžŒäļĪäŧ―čŪūčŪĄæ–‡æĄĢ栞垏æ­ĢįĄŪã€‚æœ‰į•Œį‹ŽįŦ‹æ­ĢįĄŪ性åĪæŸĨæēĄæœ‰åŊå΄ᐆé—ŪéĒ˜ïž›åŪ‰å…ĻåĪæŸĨ朊åŪŒæˆįš„å†·č·Ŋåū„äļŽ profile æĢ€æŸĨį”ąé’ˆåŊđæ€§įš„æšį æĢ€æŸĨčĄĨåŪŒã€‚å·ē有 W1 åĨ‘įšĶ明įĄŪïžšæĒåĪåž€å…ģ控åˆķį‰Đį†æŒ‚č――éŠŒčŊïžŒHosted å†·åŠ č――æ ĄéŠŒį‹ŽįŦ‹åž€åŊïž›äŋŪåĪäŋį•™čšŦäŧ―、å·Ĩ具配į―Ū、åŪĄæ‰đæĻĄåžã€æŽˆæƒäļŽæŒ‚č――æĢ€æŸĨ。

ᜟåŪžæœŽåœ° Spring/H2 äļŽå―“å‰æšį  Node Harness/Broker/worker æŽĒ针į”Ļäļ€æŽĄå—æŽ§ 503 暂停投递čŋčĄŒæ—ķįĄŪčŪĪæĒåĪåž€å…ģäļš falseã€‚į­”åĪäŋæŒåū…重čŊ•后æļ…įĐšé™„į€įž“å­˜ïžŒįœŸåŪž resident load äŧĨčĒŦåŠĻ协čŪŪčŋ”回 200原 operation åŪŒæˆäļ” Action äļš decided。į›Ūæ ‡į­”åĪåŠæˆåŠŸæŠ•é€’äļ€æŽĄïžŒREST/WebShell 重æ”ūäŧčŋ”回同äļ€äļŠ operationïžŒįœŸåŪž worker åŪŒæˆ Turn åđķæŠŠå·Ĩä―œåŒšæ–‡äŧķ写äļš after。

å…ąį”Ļ数æŪåš“äļ”ä―ŋį”Ļį”Ÿäš§į́į”Ļ connector įš„åĶäļ€å‰ŊæœŽæ‰§čĄŒäļ€æŽĄ dispatch 和å…ŦæŽĄ recoveræēĄæœ‰æ”đ变äŧŧåŠĄįŠķ态、投递įŠķ态、尝čŊ•æŽĄæ•°ã€čŪĪédžäŧĢæ•°ã€é‡čŊ•æ—ķé—īæˆ–į§ŸįšĶ。äļĪäļŠéš”įĶŧ回退åŊđį…§åˆ†åˆŦį§ŧé™Īå·Ĩä―œåŒščĒŦåŠĻåŠ č――æĄäŧķäļŽåŊį”Ļ性åۈåŦïžŒįŽ°æœ‰æ–­čĻ€åˆ†åˆŦå› įžšå°‘čĒŦåŠĻ标čŪ°å’ŒåĪšä―™å­˜å‚ĻäšĪ乒而åĪąčīĨã€‚å€™é€‰æšį å’Œįž–čŊ‘äš§į‰ĐæēĄæœ‰čĒŦčĶ†į›–ïžŒå…ĻéƒĻčŋčĄŒčŋ›įĻ‹å·ēįŧįŧ“束。

įŽŽäļ€æŽĄæŽĒ针因äŧĢį†æžč―Ž Harness boot 响嚔åĪī而åœĻåŪĄæ‰đ断čĻ€å‰åĪąčīĨå·ēäŋį•™åĪąčīĨčŊæŪïž›äŋŪåĪäŧĢį†åŽåœĻį‹ŽįŦ‹į›Ūå―•å–åū—通čŋ‡įŧ“果。Maven åŊđäļ€äļŠåŊ选元数æŪ暐æŠĨ告čŊäđĶčŋ‡æœŸïžŒä―†å·ēč§Ģæžįš„ Checkstyle 插äŧķæ­ĢåļļåŪŒæˆã€‚

čŊæŪčūđį•Œïžšč„šæœŽæĻĄåž‹ã€å—控 503、H2、同äļ€ JVM įš„äļĪäļŠ Spring context、æļ…įĐšįž“å­˜č€ŒéžåŪžé™…čŋ›įĻ‹åīĐæšƒïžŒį́į”Ļå‰Ŋ朎äŧĨįĄŪåŪšæ€§æ–đæģ•č°ƒį”Ļ驌čŊã€‚尚朊éЌčŊįœŸåŪžæĻĄåž‹ã€åیæ•īčŋ›įĻ‹æ­ŧäšĄã€MySQL/MariaDB、æĩč§ˆå™Ļį‚đå‡ŧæˆ–é‡æ–°æ‰“åŒ…įš„ CLIïž›ä―ŋį”Ļįš„æ˜Ŋå―“å‰ TypeScript æšį å’ŒæœŠæ”đå˜įš„å·ē构åŧšäūčĩ–。æēĄæœ‰é‡æ–°åŪ‰čĢ…äūčĩ–或čŋčĄŒåیæ•ī CLI 构åŧš/åĨ—äŧķ。įŽŊåĒƒįžšå°‘ review-gate、pr-ui-verify skill因æ­ĪäļåĢ°į§°æ‰§čĄŒäš†åۃäŧŽã€‚åđķ发æ”đ名äļ€č‡ī性įŧ§įŧ­į”ą #13269 跟čļŠã€‚

@qwen-code-review-bot

qwen-code-review-bot commented Oct 8, 2026 •

Copy link
Copy Markdown
Collaborator

✅ Qwen Triage finished — CI landed green on 4bd7606 and the deferred approval was posted. finalize run

✅ Qwen Triage å·ēåŪŒæˆ —— 4bd7606 įš„ CI å…ĻįŧŋåŧķčŋŸåŪĄæ‰đå·ē提äšĪ。æŸĨįœ‹ finalize čŋčĄŒ

@qwen-code-review-bot

Copy link
Copy Markdown
Collaborator

Thanks for the PR!

Template — complete, both languages, design doc links included. ✓

Problem — observed, not theoretical. wenshao's round-9 verification of #13163 recorded it plainly: "One pre-existing gap reproduced identically on main. After a dispatcher restart, a pending approval answer is never delivered with the default configuration," plus six successive claims by a Harness-disabled replica. Both halves hold up against the code:

  • The load handler answers 409 hosted_session_already_attached for any non-passive load against a resident Session (the resident && (create || (!passiveRecovery && !driveRecovery)) guard in packages/cli/src/serve/hosted-harness-session.ts), so a dispatcher that lost its attachments map loops forever against a Harness that still holds the Session.
  • ManagedActionService.respond carries no Harness guard, so a disabled replica admits and persists the answer, then claims the operation, fails inside deliver, and pushes retryOperation out with backoff — which is exactly what delays the healthy replica that could have delivered it.

Direction — aligned. An approval the user already gave being accepted, 202'd, persisted, and then silently stranded is about the worst failure mode this stack has. No direct analogue in the upstream CHANGELOG (this is our own hosted managed-agent stack; the entries there are about local CLI approval prompts), but the area is relevant — approval-delivery stalls are a recurring upstream fix category as well.

Size — no core paths touched, so the Stage 0 gate does not apply. 81 changed lines: 13 production (9+/4− across two files), 41 test, 27 design docs.

Approach — minimal and idiomatic; it is close to what I would have written independently:

  • The recover() guard is the same pattern HarnessCoordinator.recoverExpiredTurns() already uses, and dispatch() guards as well so a disabled replica never burns a claim or a lease.
  • The delivery fix reuses the passive-reattach protocol that rename, close and cancellation already ride instead of adding a new recovery path — it only widens which cold-cache action-response loads may use it. verified-workspace-recovery-enabled stays false by default and still gates every other cold-recovery path.
  • The IT clears attachments with the ReflectionTestUtils idiom already present at line 616 of that file, and the connector test is parameterized over the recovery flag, so the false arm is what pins the production change.

One question rather than a blocker: widening the passive path means a cold-cache Workspace approval delivery can now mint a runtime-recovery snapshot and set the pendingRecovery marker, which previously required the flag. The R11-3 comment says the marker is safe under boot-identity eviction and the Harness side keeps a requested approval on the plain attach, so this reads as intended — but it is the one genuine semantic widening in the diff and worth a sentence in the design doc if it is not already covered.

Risk — no elevated risk signals; the Stage 1e scan matched nothing (Java and docs only).

Moving on to code review. 🔍

äļ­æ–‡čŊŽ

感č°ĒčīĄįŒŪ

æĻĄæŋ —— åیæ•īäļ­č‹ąåŒčŊ­ïžŒé™„䚆čŪūčŪĄæ–‡æĄĢé“ūæŽĨ。✓

é—Ūéǘ —— å·ē观æĩ‹åˆ°ïžŒäļæ˜ŊᐆčŪšåŠ å›šã€‚wenshao åŊđ #13163 įš„įŽŽ 9 č―Ū驌čŊæ˜ŽįĄŪčŪ°å―•ïžš"有äļ€éĄđå·ēæœ‰įžšåĢåœĻ main äļŠåیå…Ļį›ļ同地åĪįŽ°â€”â€”č°ƒåšĶå™Ļ重åŊ后éŧ˜čŪĪ配į―Ūäļ‹åū…åĪ„į†įš„åŪĄæ‰đį­”åĪæ°ļčŋœäļäžšæŠ•递"åĶåĪ–čŋ˜æœ‰į́į”Ļ Harness įš„å‰Ŋ朎čŋžįŧ­å…­æŽĄčŪĪédžäŧŧåŠĄã€‚äļĪåŠéƒ―čƒ―åœĻäŧĢį é‡ŒåŊđäļŠïžš

  • load å΄ᐆé€ŧčū‘åŊđå·ēéĐŧį•™ Session įš„äŧŧä―•éž passive åŠ č――éƒ―čŋ”回 409 hosted_session_already_attachedpackages/cli/src/serve/hosted-harness-session.ts é‡Œįš„ resident && (create || (!passiveRecovery && !driveRecovery)) åˆĪ断所äŧĨäļĒåĪą attachments įž“å­˜įš„č°ƒåšĶå™Ļ侚åœĻäŧæŒæœ‰čŊĨ Session įš„ Harness éĒ前无限åūŠįŽŊ。
  • ManagedActionService.respond æēĄæœ‰ Harness åˆĪ断因æ­Īį́į”Ļ Harness įš„å‰ŊæœŽäžšå—į†åđķæŒäđ…åŒ–į­”åĪïžŒæŽĨį€čŪĪédž operation、åœĻ deliver 里åĪąčīĨ、再į”Ļ退éŋ把 retryOperation æŽĻ后——čŋ™æ°æ°æ‹–ä―äš†æœŽåŊäŧĨåŪŒæˆæŠ•é€’įš„åĨåš·å‰Ŋ朎。

æ–đ向 —— åŊđé―ã€‚į”Ļ户å·ēįŧįŧ™å‡šįš„åŪĄæ‰đčĒŦå—į†ã€čŋ”回 202ã€č―åš“ïžŒį„ķ后静éŧ˜åĄæ­ŧæ˜Ŋčŋ™åĨ—栈最įģŸįš„åĪąčīĨå―Ēæ€äđ‹äļ€ã€‚äļļ CHANGELOG æēĄæœ‰į›īæŽĨåŊđåš”æĄį›Ūčŋ™æ˜Ŋ我äŧŽč‡Šå·ąįš„ hosted managed-agent 栈é‚Ģčūđįš„æĄį›ŪčŪēįš„æ˜Ŋ朎地 CLI åŪĄæ‰đåžđįŠ—ïž‰ïžŒä―†čŋ™äļŠæ–đ向æ˜Ŋį›ļå…ģįš„â€”â€”åŪĄæ‰đæŠ•é€’åĄæ­ŧåœĻäļļäđŸæ˜Ŋ反åĪå‡šįŽ°įš„äŋŪåĪįąŧåˆŦ。

规æĻĄ —— 朊č§Ķ及æ ļåŋƒč·Ŋåū„Stage 0 é—Ļį́äļé€‚į”Ļã€‚å…ą 81 行æ”đåŠĻïžš13 čĄŒį”Ÿäš§äŧĢį ïžˆäļĪäļŠæ–‡äŧķ9 åĒž 4 删、41 行æĩ‹čŊ•、27 行čŪūčŪĄæ–‡æĄĢ。

æ–đæĄˆ —— 最小äļ”įŽĶ合æ—Ē有写æģ•ïžŒå’Œæˆ‘į‹ŽįŦ‹æƒģåˆ°įš„åšæģ•埚朎äļ€č‡īïžš

  • recover() įš„åˆĪ断æēŋį”Ļ HarnessCoordinator.recoverExpiredTurns() å·ēæœ‰įš„å†™æģ•dispatch() äđŸäļ€åđķåˆĪ断į́į”Ļįš„å‰Ŋ朎因æ­Īäļäžšæķˆč€—čŪĪéĒ†æˆ–į§ŸįšĶ。
  • 投递äŋŪåĪåĪį”Ļ rename、close、cancellation å·ēįŧåœĻčĩ°įš„čĒŦåŠĻé‡é™„į€åčŪŪïžŒč€Œäļæ˜Ŋ新åĒžäĄæĒåĪč·Ŋåū„——及æ˜Ŋæ”ūåŪ―äš†å“Šäš›å†·įž“å­˜įš„åŪĄæ‰đį­”åĪåŠ č――åŊäŧĨä―ŋį”ĻåŪƒã€‚verified-workspace-recovery-enabled éŧ˜čŪĪäŧäļš falseå…ķä―™å†·æĒåĪč·Ŋåū„äūæ—§å—åۃįšĶ束。
  • 集成æĩ‹čŊ•į”ĻčŊĨ文äŧķįŽŽ 616 行å·ēæœ‰įš„ ReflectionTestUtils 写æģ•æļ…įĐš attachmentsïž›connector æĩ‹čŊ•按æĒåĪåž€å…ģ参数化因æ­Ī false é‚Ģä”Ŋ才æ˜Ŋé’‰ä―į”Ÿäš§æ”đåŠĻįš„æ–­čĻ€ã€‚

äļ€äļŠį–‘é—Ūäļæ˜Ŋé˜ŧåĄžéĄđïžšæ”ūåŪ― passive č·Ŋåū„åŽïžŒå†·įž“å­˜įš„ Workspace åŪĄæ‰đæŠ•é€’įŽ°åœĻåŊčƒ―į”Ÿæˆ runtime-recovery åŋŦį…§åđķį―ŪäļŠ pendingRecovery 标čŪ°ïžŒč€Œčŋ™åŽŸå…ˆéœ€čĶåž€å…ģ打垀。R11-3 įš„æģĻ释čŊŽčŊĨ标čŪ°åœĻ boot čšŦäŧ―åĪąæ•ˆæ—ķæ˜ŊåŪ‰å…Ļįš„ïžŒHarness äū§äđŸäžščŪĐåĪ„äšŽ requested įš„åŪĄæ‰đäŋæŒ plain attach所äŧĨįœ‹čĩ·æĨæ˜ŊéĒ„æœŸčĄŒäļšâ€”â€”ä―†čŋ™æ˜Ŋ diff 里å”Ŋäļ€įœŸæ­Ģįš„čŊ­äđ‰æ”ūåŪ―ïžŒåĶ‚æžœčŪūčŪĄæ–‡æĄĢčŋ˜æēĄčĶ†į›–ïžŒå€žåū—čĄĨäļ€åĨ。

éĢŽé™Đ —— æ— å‡įš§éĢŽé™ĐäŋĄå·ïž›Stage 1e æ‰Ŧ描æēĄæœ‰å‘―äļ­ïžˆåŠæœ‰ Java 和文æĄĢ。

čŋ›å…ĨäŧĢ᠁åŪĄæŸĨ 🔍

— Qwen Code · qwen3.8-max-2026-09-02

Reviewed at 4bd76069532dd3b17eee533c4f1790558a118331 · re-run with @qwen-code /triage

@qwen-code-review-bot

qwen-code-review-bot commented Oct 8, 2026 •

Copy link
Copy Markdown
Collaborator

Code review

No blockers. I wrote down what I would have done for each half before comparing, and the diff lands on the same answer both times — which is the main reason this reads as a clean PR rather than a merely plausible one.

For the 409 loop the alternatives were all worse: catching hosted_session_already_attached and re-issuing as a passive load adds an error branch for the same wire effect, and relaxing the 409 on the Harness side would weaken the attach fence for every other caller. Riding the existing passive-reattach protocol is the minimal move. For the claim storm, guarding the route instead (the way ManagedAgentService.requireHarness() answers 503) would have been wrong here — it would reject an answer that a shared-database deployment can legitimately accept, persist, and let an enabled replica deliver. Guarding dispatch/recover is right, and it is literally the shape HarnessCoordinator.recoverExpiredTurns() already uses, so the convention is reused rather than reinvented.

Two claims in the description I checked rather than took on faith:

  • "It still checks the current Action-response execution authority and mount before delivery." True, and not by accident. requireReadyForNewWork runs authorizeActionResponse and verifyMountForProbe before the attachment lookup, so the probe the passive branch skips inside doCreateOrLoad was always a second, redundant one. The parameterized test pins it: verify(execution, times(2)).verifyMountForProbe(...) across three resolveAction calls is exactly the count you get when the inner probe never fires.
  • The passive load is safe against a genuinely cold Harness. On the Node side the flag only suppresses the resident && (create || (!passiveRecovery && !driveRecovery)) conflict — with nothing resident, a passive load falls through to the ordinary path. That branch also keeps a requested approval on the plain attach (the R11-2 note), which is precisely this scenario, so the recovery machinery was already built to tolerate it.

Both production lines are mutation-sensitive: reverting the connector's session.workspace() != null || fails the verifiedRecovery=false arm's passiveManagedRuntimeRecovery: true wire assertion, and reverting the coordinator guard fails the new verifyNoInteractions(sessions, actions, executor). Nothing here is a test that passes with or without the fix.

Two non-blocking notes:

  • Three lines are now unreachable. Inside doCreateOrLoad, the if (actionResponse) branch only runs for a Workspace session, and doResolveAction is the sole caller passing actionResponse=true — which now always passes passiveManagedRuntimeRecovery=true for exactly those sessions. So if (!passiveManagedRuntimeRecovery) { verifyMountForProbe(...); } can never fire. Harmless (the probe still runs upstream), but a future reader will reasonably assume the mount check depends on it. Worth dropping in a follow-up.
  • The passive branch loads outside the per-key AttachmentLock. attached = passiveManagedRuntimeRecovery ? load(session, true) : attachments.get(key) runs before the locked miss path, so two concurrent action-response operations on the same cold Session can each issue their own load and race on attachments.put. This is pre-existing — rename and close hit it whenever the recovery flag was on — and bounded, since the Harness re-proves store identity and tool profile on each attach. But the change makes it the common path for Workspace approvals rather than an opt-in one, so it is worth knowing about.

CI evidence

Fetched once for 4bd76069532dd3b17eee533c4f1790558a118331, not polled — 34 checks, 14 success, 13 skipped, 7 still pending, 0 failures. Reading the workflow rather than guessing which job proves what:

  • The ${{ matrix.os }} / Java ${{ matrix.java }} jobs run mvn clean test plus a Checkstyle step, so the four green ones (ubuntu-latest / Java 21, Java 17, Java 11, windows-latest / Java 21) already substantiate the three unit-test files and the zero-Checkstyle claim on Linux and Windows. macos-latest / Java 21 was still running.
  • The load-bearing job for the delivery fix is Hosted process fault gates / MySQL 8.4 / Java 21, still queued at review time. scripts/check-failsafe-reports.js assigns Hosted*IT classes to that job's family and fails if any of them did not run, so the new attachments-clear in HostedPublicWorkspaceIT.answerActions is guaranteed to execute there — that is the assertion which would go red on unfixed code, and it has not reported yet.
  • Runtime Broker and Managed Agent MariaDB / Java 21 (the non-hosted IT family) was also queued. The Node-side jobs are irrelevant to this diff; their skips are path filters, not failures.

The Qwen Triage Finalize job rewrites the table below once CI settles.

Final CI results for 4bd7606 (auto-updated by the triage finalize job after CI completed):

Check Conclusion
Classify PR ✅ success
Desktop Shell (ubuntu-22.04) ✅ success
Desktop Shell (windows-2022) ✅ success
Flyway migration version uniqueness ✅ success
Hosted process fault gates / MySQL 8.4 / Java 21 ✅ success
Integration Tests (no-AK, No Sandbox) ✅ success
Lint & Static (ubuntu-latest, Node 22.x) ✅ success
macos-latest / Java 21 ✅ success
Real daemon E2E / Java 11 ✅ success
Runtime Broker and Managed Agent MariaDB / Java 21 ✅ success
Test (ubuntu-latest, Node 22.x) ✅ success
ubuntu-latest / Java 11 ✅ success
ubuntu-latest / Java 17 ✅ success
ubuntu-latest / Java 21 ✅ success
web-shell E2E Smoke (ubuntu-latest, Node 22.x) ✅ success
windows-latest / Java 21 ✅ success

One row per check name (latest run); skipped checks omitted; failures sort first. / æŊäļŠæĢ€æŸĨ名äļ€čĄŒïžˆå–最新äļ€æŽĄčŋčĄŒïž‰ïžŒįœį•Ĩ skippedåĪąčīĨéĄđ排åœĻ最前。

Sandboxed verification would settle the one claim static review cannot: @qwen-code /verify — that a Harness-disabled replica sharing a database leaves the pending operation's claim generation, attempt count, lease and retry time untouched while an enabled replica delivers it. The new ActionResponseCoordinatorTest is mock-level (verifyNoInteractions), so it pins the guard but not the database effect, and nothing in CI runs two replicas against one store. /tmux does not apply here — there is no TUI surface, only REST and WebShell.

Not verified, and why:

  • not verified: the multi-replica shared-database behaviour above. The only real evidence is the author's two-Spring-context probe, which is self-reported and macOS-only.
  • not verified: recovery after an actual dispatcher process restart. The IT clears the in-memory attachments map, which reproduces the lost-cache state faithfully but is not a restart — and a restart is how round 9 originally observed the stall.
  • not verified: the hosted MySQL IT outcome. The job was still queued at review time; this is CI pending, not a gap in the PR.

Everything else in the description that I could check statically — the preserved authority and mount checks, the unchanged false recovery default, the bilingual design-doc sync, the pre-existing test idioms and imports the diff depends on — checked out.

äļ­æ–‡čŊŽ

äŧĢ᠁åŪĄæŸĨïžšæēĄæœ‰é˜ŧåĄžéĄđ。äļĪåĪ„äŋŪåĪæˆ‘éƒ―å…ˆį‹ŽįŦ‹æƒģčŋ‡äļ€éåšæģ•įŧ“čŪšå’Œ diff äļ€č‡ī。409 åūŠįŽŊįš„å…ķäŧ–æ–đæĄˆéƒ―æ›īå·Ūïžˆæ•čŽ· hosted_session_already_attached 再æ”đ发 passive 及æ˜ŊåΚäĄé”™čŊŊ分æ”Ŋïž›æ”ūåŪ― Harness äū§įš„ 409 äžšå‰Šåžąæ‰€æœ‰č°ƒį”Ļæ–đäūčĩ–įš„é™„į€æ …æ ïž‰ïžŒåĪį”Ļæ—Ē有čĒŦåŠĻé‡é™„į€åčŪŪæ˜Ŋ最小æ”đåŠĻ。čŪĪédžéĢŽæšīčŋ™äļ€åŠåĶ‚æžœæ”đ成åœĻč·Ŋį”ąä‹Ķ戊像 ManagedAgentService.requireHarness() é‚Ģæ ·čŋ”回 503ïž‰åč€Œæ˜Ŋé”™įš„â€”â€”é‚Ģ䞚拒掉äļ€äļŠå…ąäšŦ数æŪåš“éƒĻį―翜ŽåŊäŧĨå—į†ã€č―åš“ã€äšĪįŧ™åŊį”Ļå‰ŊæœŽæŠ•é€’įš„į­”åĪïž›åœĻ dispatch/recover äļŠåˆĪ断才åŊđïžŒč€Œäļ”写æģ•äļŽå·ēæœ‰įš„ HarnessCoordinator.recoverExpiredTurns() åیå…Ļäļ€č‡ī。

描čŋ°é‡Œæœ‰äļĪäļŠčŊīæģ•我做䚆æ ļåŪžč€Œäļæ˜Ŋį›īæŽĨ采äŋĄïžšä˜Ŋ"投递前äŧæĢ€æŸĨæ‰§čĄŒæŽˆæƒäļŽæŒ‚č――"——成įŦ‹ïžŒrequireReadyForNewWork åœĻæŸĨįž“å­˜äđ‹å‰å°ąč·‘䚆 authorizeActionResponse 和 verifyMountForProbe所äŧĨ passive 分æ”Ŋč·ģčŋ‡įš„é‚ĢæŽĄæŽĒæĩ‹æœŽæĨå°ąæ˜Ŋ重åĪįš„ïžŒå‚æ•°åŒ–æĩ‹čŊ•里äļ‰æŽĄč°ƒį”ĻåŊđåš” times(2) įš„æ–­čĻ€æ­ĢåĨ―印čŊïž›äšŒæ˜Ŋ passive åŠ č――åŊđᜟæ­Ģå†·æŽ‰įš„ Harness æ˜ŊåĶåŪ‰å…Ļ——Node äū§čŊĨ标åŋ—及抑åˆķ"å·ēéĐŧį•™äļ”非 passive"įš„å†ēįŠåˆĪ断æēĄæœ‰éĐŧį•™ Session æ—ķčĩ°æ™Ū通č·Ŋåū„ïžŒč€Œ R11-2 įš„æģĻ释čŊŽåĪ„äšŽ requested įš„åŪĄæ‰đ侚äŋæŒ plain attachæ­Ģæ˜Ŋ朎圚æ™Ŋ。

äļĪčĄŒį”Ÿäš§äŧĢį éƒ―åŊđ变垂敏感回退 connector é‚Ģäļ€čĄŒäžščŪĐ verifiedRecovery=false 分æ”Ŋįš„ wire 断čĻ€åĪąčīĨïžŒå›žé€€åč°ƒå™Ļįš„åˆĪæ–­äžščŪĐæ–°åĒžįš„ verifyNoInteractions åĪąčīĨ。

äļĪæĄéžé˜ŧåĄžæé†’ïžšdoCreateOrLoad 里 if (!passiveManagedRuntimeRecovery) åŒ…ä―įš„é‚ĢæŽĄ verifyMountForProbe įŽ°åœĻå·ēįŧäļåŊčūūå”Ŋäļ€äž  actionResponse=true įš„č°ƒį”Ļæ–đåŊđčŋ™äš› Session 恒䞠 passive=trueäļ‰čĄŒæ­ŧäŧĢį ïžŒåŧščŪŪ后įŧ­æļ…掉免åū—后䚚čŊŊäŧĨäļšæŒ‚č――æĢ€æŸĨäūčĩ–åŪƒïž›åĶåĪ– passive 分æ”ŊåœĻæŊ key įš„ AttachmentLock äđ‹åĪ–å‘čĩ·åŠ č――同äļ€å†· Session äļŠäļĪäļŠåđķå‘įš„åŪĄæ‰đį­”åĪ operation åŊčƒ―å„č‡Šå‘äļ€æŽĄåŠ č――åđķįŦžäš‰ attachments.put——čŋ™æ˜Ŋæ—Ēæœ‰čĄŒäļšïžˆåž€å…ģ打垀æ—ķ rename/close å°ąäžščĩ°åˆ°ïž‰ïžŒå―ąå“æœ‰į•ŒïžˆHarness æŊæŽĄé™„į€éƒ―äžšé‡æ–°æ ĄéŠŒ store čšŦäŧ―äļŽå·Ĩ具配į―Ūïž‰ïžŒä―†čŋ™æŽĄæ”đåŠĻ把åŪƒå˜æˆäš† Workspace åŪĄæ‰đįš„åļ￀č·Ŋåū„。

CI čŊæŪïžšåŊđ 4bd7606 äļ€æŽĄæ€§æ‹‰å–ã€æœŠč―ŪčŊĒ——34 äļŠæĢ€æŸĨ14 成功、13 č·ģčŋ‡ã€7 äŧåœĻčŋ›čĄŒã€0 åĪąčīĨ。įŸĐé˜ĩä―œäļšč·‘įš„æ˜Ŋ mvn clean test 加 Checkstyle因æ­Īå·ēįŧŋįš„å››äļŠïžˆubuntu Java 21/17/11、windows Java 21å·ēįŧčŊæ˜Žäļ‰äļŠå•å…ƒæĩ‹čŊ•æ–‡äŧķ通čŋ‡äļ” Checkstyle äļšé›ķé—ŪéĒ˜ïž›macOS Java 21 å―“æ—ķäŧåœĻč·‘ã€‚įœŸæ­Ģé’‰ä―æŠ•é€’äŋŪåĪįš„æ˜Ŋ Hosted process fault gates / MySQL 8.4 / Java 21——scripts/check-failsafe-reports.js 把 Hosted*IT å―’åˆ°čŊĨä―œäļšïžŒåđķäļ”äŧŧä―•äļ€äļŠæēĄč·‘éƒ―侚åĪąčīĨ所äŧĨ HostedPublicWorkspaceIT.answerActions 里新åĒžįš„æļ…įĐšįž“å­˜åŋ…į„ķåœĻé‚Ģé‡Œæ‰§čĄŒïž›åŪĄæŸĨæ—ķčŊĨä―œäļšäŧåœĻ排队。MariaDB įš„éž hosted 集成æĩ‹čŊ•ä―œäļšåŒæ ·åœĻ排队。CI įĻģåŪšåŽčĄĻæ žäžšį”ą finalize ä―œäļšå°ąåœ°æ›ī新。

æē™įŪąéŠŒčŊåŧščŪŪïžš@qwen-code /verify åŊäŧĨ驌čŊé™æ€åŪĄæŸĨįœ‹äļåˆ°įš„é‚Ģäļ€éĄđâ€”â€”å…ąäšŦ数æŪåš“äļ‹į́į”Ļ Harness įš„å‰Ŋ朎æ˜ŊåĶįœŸįš„äļæ”đåŠĻåū…å΄ᐆ operation įš„čŪĪédžäŧĢæ•°ã€å°čŊ•æŽĄæ•°ã€į§ŸįšĶäļŽé‡čŊ•æ—ķé—īïžŒč€ŒčŪĐåŊį”Ļįš„å‰Ŋ朎åŪŒæˆæŠ•é€’ã€‚æ–°åĒžįš„ ActionResponseCoordinatorTest æ˜Ŋ mock įš§åˆŦįš„ïžŒé’‰ä―äš†åˆĪ断朎čšŦä―†æēĄæœ‰é’‰ä―æ•°æŪ嚓效果CI 里äđŸæēĄæœ‰äļĪäļŠå‰ŊæœŽå…ąį”Ļäļ€äļŠå­˜å‚Ļįš„åœšæ™Ŋ。/tmux äļé€‚į”Ļ——čŋ™é‡ŒæēĄæœ‰ TUI į•ŒéĒ及有 REST 和 WebShell。

朊銌čŊéĄđïžšäļŠčŋ°åΚå‰ŊæœŽå…ąäšŦ数æŪåš“čĄŒäļšïžˆå”Ŋäļ€įœŸåŪžčŊæŪæ˜Ŋä―œč€…č‡Ščŋ°įš„、äŧ…åœĻ macOS äļŠč·‘čŋ‡įš„双 Spring context æŽĒé’ˆïž‰ïž›č°ƒåšĶå™Ļᜟæ­Ģčŋ›įĻ‹é‡åŊåŽįš„æĒåĪïžˆé›†æˆæĩ‹čŊ•æļ…įĐšįš„æ˜Ŋå†…å­˜é‡Œįš„ attachmentsïžŒčƒ―åŋ åŪžåĪįŽ°äļĒįž“å­˜įŠķæ€ïžŒä―†äļį­‰äšŽé‡åŊïžŒč€ŒįŽŽ 9 č―Ūæœ€åˆč§‚æĩ‹åˆ°įš„æ­Ģæ˜Ŋ重åŊäŧĨ及 hosted MySQL 集成æĩ‹čŊ•įš„įŧ“čŪšïžˆåŪĄæŸĨæ—ķä―œäļšäŧåœĻæŽ’é˜ŸïžŒåąžäšŽ CI 朊åŪŒæˆïžŒäļæ˜Ŋ PR įš„įžšåĢ。

å…ķä―™čƒ―é™æ€æ ļåŊđįš„å†…åŪđ——äŋį•™įš„æŽˆæƒäļŽæŒ‚č――æĢ€æŸĨ、æĒåĪåž€å…ģéŧ˜čŪĪ倞äŧäļš false、čŪūčŪĄæ–‡æĄĢäļ­č‹ąåŒæ­Ĩ、diff äūčĩ–įš„æ—Ē有æĩ‹čŊ•写æģ•äļŽ import——均æ ļåŊđ通čŋ‡ã€‚

— Qwen Code · qwen3.8-max-2026-09-02

Reviewed at 4bd76069532dd3b17eee533c4f1790558a118331 · re-run with @qwen-code /triage

@qwen-code-review-bot

Copy link
Copy Markdown
Collaborator

Confidence: 4/5 — solid, minimal, and pinned by mutation-sensitive tests; held back from 5 only by the multi-replica claim that nothing in CI can exercise, plus two non-blocking code notes.

I proposed both fixes independently before comparing and landed in the same place twice, which is the strongest signal I have that this is the right shape rather than a plausible one. Thirteen production lines, no drive-by edits, and both halves reuse something that already exists — the passive-reattach protocol the cancellation and rename paths ride, and the isAvailable() guard HarnessCoordinator.recoverExpiredTurns() already opens with. Nothing was added that did not need to be.

The problem is real and I did not take that on faith. An independent verifier recorded the stall on a PR that has since merged, reproduced identically on main, and I confirmed both mechanisms by reading the code: the resident-Session conflict that a non-passive load cannot get past, and the unguarded respond route that lets a Harness-disabled replica claim an operation, fail it, and push its retry time out with backoff — delaying the healthy replica that could have delivered it. An approval a user already gave being accepted, persisted, answered 202, and then stranded forever is one of the worse failure modes in this stack, so this is not hygiene dressed up as a fix.

What I could not settle, stated plainly: the shared-database half. The new coordinator test is mock-level, so it pins the guard but not the effect on claim generation, attempts, lease and retry time, and no CI job runs two replicas against one store. The guard is five lines with obvious semantics copied from a sibling class, so I am not worried about it being wrong — I am noting that its database-level behaviour rests on the author's self-reported, macOS-only probe. @qwen-code /verify would close that; the Stage 2 comment names the exact claim.

The author has roughly twenty PRs open, which is normally where I get skeptical about volume. This one is a direct follow-up to their own merged work and fixes a gap a third party explicitly recorded as still present, so I judged it on its own merits and it holds up.

Two things I would clean up later, neither blocking: the verifyMountForProbe call inside doCreateOrLoad is now unreachable and should be dropped before someone assumes the mount check depends on it, and the passive load runs outside the per-key attachment lock, which was pre-existing but is now the common path for Workspace approvals rather than an opt-in one.

Approval deferred until CI lands green on 4bd76069532dd3b17eee533c4f1790558a118331. Two pull_request workflow runs were still in flight at review time — including Hosted process fault gates / MySQL 8.4 / Java 21, the job that runs HostedPublicWorkspaceIT and therefore the assertion that would go red on unfixed code. Four unit-test jobs and Checkstyle are already green on Linux and Windows, and nothing is red. I am not approving against a result that does not exist yet; the finalize job posts the commit-pinned approval once every check on that SHA completes green, and withholds it if anything lands red or the head moves.

äļ­æ–‡čŊŽ

äŋĄåŋƒïžš4/5 —— 扎åŪžã€æœ€å°åŒ–ïžŒäļ”į”ąåŊđå˜åž‚æ•æ„Ÿįš„æĩ‹čŊ•é’‰ä―ïž›æēĄåˆ° 5 分及æ˜Ŋ因äļšåΚå‰Ŋ朎é‚Ģäļ€éĄđ CI 无æģ•čĶ†į›–ïžŒåĪ–åŠ äļĪæĄéžé˜ŧåĄžįš„äŧĢį æé†’ã€‚

äļĪåĪ„äŋŪåĪæˆ‘éƒ―å…ˆį‹ŽįŦ‹æƒģčŋ‡åšæģ•再åŊđį…§ïžŒäļĪæŽĄéƒ―č―åœĻ同äļ€äļŠæ–đæĄˆäļŠâ€”—čŋ™æ˜Ŋ"å―Ēæ€æ­ĢįĄŪ"而äļåŠæ˜Ŋ"įœ‹čĩ·æĨåˆį†"įš„æœ€åžšäŋĄå·ã€‚13 čĄŒį”Ÿäš§äŧĢį ïžŒæēĄæœ‰åĪđåļĶæ— å…ģæ”đåŠĻäļĪåŠéƒ―åĪį”Ļ乆å·ē有äļœčĨŋïžšcancellation 和 rename å·ēįŧåœĻčĩ°įš„čĒŦåŠĻé‡é™„į€åčŪŪäŧĨ及 HarnessCoordinator.recoverExpiredTurns() 垀åĪīå·ēæœ‰įš„ isAvailable() åˆĪ断。æēĄæœ‰åΚ加äŧŧä―•äļåŋ…čĶįš„äļœčĨŋ。

é—Ūéǘæ˜ŊᜟåŪžå­˜åœĻįš„ïžŒæˆ‘æēĄæœ‰į›īæŽĨ采äŋĄã€‚äļ€ä―į‹ŽįŦ‹éЌčŊč€…åœĻäļ€äļŠå·ēįŧåˆåđķįš„ PR äļŠčŪ°å―•äš†čŋ™äļŠåœæŧžïžŒåđķåœĻ main äļŠåیå…Ļį›ļ同地åĪįŽ°ïž›äļĪäļŠæœšåˆķæˆ‘éƒ―åœĻäŧĢį é‡Œæ ļåŊđčŋ‡ïžšéž passive åŠ č――æ— æģ•įŧ•čŋ‡įš„"å·ēéĐŧį•™ Session"å†ēįŠïžŒäŧĨ及æēĄæœ‰ Harness åˆĪæ–­įš„ respond č·Ŋį”ąâ€”â€”åۃčŪĐį́į”Ļ Harness įš„å‰Ŋ朎čŪĪédž operation、åĪąčīĨ、再į”Ļ退éŋ把重čŊ•æ—ķé—īæŽĻ后äŧŽč€Œæ‹–ä―æœŽåŊåŪŒæˆæŠ•é€’įš„åĨåš·å‰Ŋ朎。į”Ļ户å·ēįŧįŧ™å‡šįš„åŪĄæ‰đčĒŦå—į†ã€č―åš“ã€čŋ”回 202į„ķ后æ°ļčŋœåĄä―ïžŒæ˜Ŋčŋ™åĨ—栈里最įģŸįš„åĪąčīĨå―Ēæ€äđ‹äļ€ïžŒæ‰€äŧĨčŋ™äļæ˜Ŋ把äŧĢ᠁æ•īæīåŒ…čĢ…æˆäŋŪåĪã€‚

我无æģ•åۚčŪšįš„éƒĻ分čŊīæļ…æĨšïžšå…ąäšŦ数æŪåš“é‚Ģäļ€åŠã€‚æ–°åĒžįš„åč°ƒå™Ļæĩ‹čŊ•æ˜Ŋ mock įš§åˆŦįš„ïžŒé’‰ä―äš†åˆĪ断朎čšŦïžŒä―†æēĄæœ‰é’‰ä―åŊđčŪĪédžäŧĢæ•°ã€å°čŊ•æŽĄæ•°ã€į§ŸįšĶäļŽé‡čŊ•æ—ķé—īįš„åŪžé™…æ•ˆæžœïžŒCI 里äđŸæēĄæœ‰äŧŧä―•ä―œäļščŪĐäļĪäļŠå‰ŊæœŽå…ąį”Ļäļ€äļŠå­˜å‚Ļ。čŋ™äļŠåˆĪæ–­åŠæœ‰äš”čĄŒã€čŊ­äđ‰æ˜ūį„ķ、äŠ„č‡ŠåŒįąŧ所äŧĨ我äļæ‹…åŋƒåۃæ˜Ŋé”™įš„â€”â€”æˆ‘åŠæ˜Ŋ指凚åۃåœĻ数æŪåš“åą‚éĒįš„čĄŒäļšį›Ū前äūčĩ–ä―œč€…č‡Ščŋ°įš„、äŧ…åœĻ macOS äļŠč·‘čŋ‡įš„æŽĒ针。@qwen-code /verify åŊäŧĨčĄĨäļŠčŋ™äļ€įŽŊStage 2 čŊ„čŪšé‡Œį‚đåäš†å…·ä―“čĶéŠŒčŊįš„äļŧ垠。

ä―œč€…åäļ‹åΧįšĶčŋ˜æœ‰äšŒåäļŠåž€į€įš„ PRčŋ™é€šåļ￘Ŋ我åŊđ"数量"čĩ·į–‘įš„åœ°æ–đã€‚ä―†čŋ™äļ€äļŠæ˜Ŋäŧ–č‡Šå·ąå·ē合åđķå·Ĩä―œįš„į›īæŽĨ后įŧ­ïžŒäŋŪįš„æ˜ŊįŽŽä–đ明įĄŪčŪ°å―•äļšäŧį„ķ存åœĻįš„įžšåĢ所äŧĨ我按åŪƒæœŽčšŦįš„äŧ·å€žåˆĪ断įŦ™åū—ä―ã€‚

äļĪäŧķ后įŧ­åŊäŧĨæļ…į†įš„äš‹ïžŒéƒ―äļé˜ŧåĄžïžšdoCreateOrLoad 里é‚ĢæŽĄ verifyMountForProbe įŽ°åœĻå·ēäļåŊčūū嚔čŊĨ删掉免åū—后䚚äŧĨäļšæŒ‚č――æĢ€æŸĨäūčĩ–åŪƒïž›čĒŦåŠĻåŠ č――åœĻæŊ key įš„é™„į€é”äđ‹åĪ–æ‰§čĄŒïžŒčŋ™æ˜Ŋæ—Ēæœ‰čĄŒäļšïžŒä―†įްåœĻ成䚆 Workspace åŪĄæ‰đįš„åļ￀č·Ŋåū„č€Œäļå†æ˜ŊåŊ选éĄđ。

åŪĄæ‰đæŽĻčŋŸåˆ° CI åœĻ 4bd76069532dd3b17eee533c4f1790558a118331 äļŠå…Ļįŧŋäđ‹åŽå†įŧ™å‡šã€‚ åŪĄæŸĨæ—ķčŋ˜æœ‰äļĪäļŠ pull_request å·Ĩä―œæĩåœĻ跑——å…ķäļ­åŒ…拎 Hosted process fault gates / MySQL 8.4 / Java 21äđŸå°ąæ˜ŊčŋčĄŒ HostedPublicWorkspaceIT、æ‰ŋč――"朊äŋŪåĪäŧĢį äžšįšĒ"é‚ĢæĄæ–­čĻ€įš„ä―œäļšã€‚å››äļŠå•å…ƒæĩ‹čŊ•ä―œäļšå’Œ Checkstyle å·ēåœĻ Linux äļŽ Windows äļŠé€ščŋ‡ïžŒæēĄæœ‰äŧŧä―•įšĒéĄđ。我äļäžšåŊđį€äļ€äļŠå°šäļå­˜åœĻįš„įŧ“æžœįŧ™åŪĄæ‰đïž›CI å…ĻéƒĻåŪŒæˆåŽïžŒfinalize ä―œäļšäžšįŧ™å‡šįŧ‘åۚčŊĨ commit įš„åŪĄæ‰đč‹Ĩ有įšĒéĄđ或 head 变åŠĻ则äļįŧ™ã€‚

— Qwen Code · qwen3.8-max-2026-09-02

Reviewed at 4bd76069532dd3b17eee533c4f1790558a118331 · re-run with @qwen-code /triage

@qwen-code-review-bot qwen-code-review-bot 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.

LGTM, looks ready to ship — CI landed green after the review. ✅

@qwen-code-review-bot qwen-code-review-bot 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.

Reviewed. Suggestions are inline.

2 Suggestion-level finding(s) this review confirmed are already reported on this PR and are not repeated:

  • R1-5 passive approval load bypasses the per-key attachment single-flight — already reported (comment 6060199953)
  • R1-6 unreachable non-passive verifyMountForProbe branch in doCreateOrLoad — already reported (comment 6060199953)

Not explored to full depth (tool budget reached): "agent 1a": static javac / javap bytecode-size measurement of doResolveAction , requireReadyForNewWork and dispatch — the review worktree has no pre-built target/clâ€Ķ.

äļ­æ–‡čŊŽ

å·ēåŪĄæŸĨ。 åŧščŪŪč§čĄŒå†…čŊ„čŪšã€‚

朎č―ŪįĄŪčŪĪįš„ 2 æĄåŧščŪŪįš§å‘įŽ°å·ēåœĻ PR äŠĨ告čŋ‡ïžŒäļå†é‡åĪå‘åļƒïžˆåˆ—čĄĻ见ä–đč‹ąæ–‡éƒĻ分。

朊æŽĒįīĒ到å…ĻéƒĻæ·ąåšĶčūū到å·Ĩå…·č°ƒį”ĻéĒ„įŪ—ïž‰ïžš"agent 1a"ïžšstatic javac / javap bytecode-size measurement of doResolveAction , requireReadyForNewWork and dispatch — the review worktree has no pre-built target/clâ€Ķ。

— qwen3.8-max via Qwen Code /review (v0.25.0)

Fence late title writes by durable revision and replay the latest intent after ambiguous replies. Renew approval claims during slow attachment and settle journal-proven terminal answers without dispatching from disabled replicas.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
@yiliang114 yiliang114 changed the title fix(managed-agent): recover queued approval delivery after cache loss fix(managed-agent): reconcile approval delivery and concurrent session titles Oct 8, 2026
@yiliang114

Copy link
Copy Markdown
Collaborator Author

Delivered additive commit e8e7da9e1c0b extends this same PR with the rename repair and addresses all four current review suggestions. No replacement PR or history rewrite.

The final title write now rejects an older revision inside the durable journal transaction. A stored latest delivery repairs ambiguous replies; FAILED same-key retries get a fresh revision, while completed replay remains read-only. This covers both bound and unbound Sessions, including the first rename before Java has saved an attachment boot. Approval delivery renews its claim during slow recovery, disabled replicas preserve requested tasks and settle only journal-proven final Actions, and the connector regression now exercises successful warm reuse.

Verification Observed result
Focused Java server 79 distinct cases pass: connector48, Actions28, coordinator2, rename/lifecycle1; Checkstyle0
SDK client / Core metadata 57 / 31 pass; SDK and Core builds pass
Hosted contract / final delayed-title route 10 / 1 pass; CLI and Core typecheck, selected ESLint and formatting pass
Cross-replica late write Accepted old CLI request held before its serial transaction; same-key sibling fails, newer B completes; all work terminal leaves B/B. Fresh original-key retry becomes A/A with a new revision
Real SDK timeout 2s client deadline expires while accepted CLI work lives. Newer unbound B uses a second cold connector with passive load200; late old write is rejected; final B/B
Latest committed title, success reply replaced by503 Fresh scheduled dispatcher repairs public B from the committed private B; title journal records1 → 1, without a manual retry
First title reply loss, no saved Java boot Bound and unbound empty Sessions recover automatically through a fresh dispatcher; both titles B and one journal title
Approval cache loss Default verified recoveryfalse; disabled direct dispatch1/recovery8 leave requested fields unchanged; passive load200; original operation completes, one successful resolve, real worker proof.txt=after
Rollback sensitivity Removing only final title fencing reproduces settled public B/private A. Removing renewal permits a competing claim; removing terminal settlement leaves the expired response running

Attribution: commit tree matches complete source candidate b14c675a. The final main rename probe (7.32s) and first unbound-title probe (5.19s) ran on that candidate. The bound first-title probe (5.02s) ran on 134d61d8; the subsequent caller change only enables the identical mode for unbound Sessions, leaving the bound path unchanged. Approval transport (9.62s) ran on 66be5973, before the subsequent rename-only repairs; its Core, SDK and approval coordinator/store production were unchanged. Per-run source/class hashes stayed stable. All 13 owned runtime groups were cleaned up.

Initial failures are retained: two first-title probes exposed real404/409 gaps and drove the repairs. A new terminal test initially opened two independent journal fixtures and hit a stale head before its assertion; the shared-journal repair passes. Probe warmup/configuration/SQL-column mistakes, a stale ACP build prerequisite, two test-only TypeScript annotations and one skipped-name filter are recorded separately and excluded from passing evidence.

These are real Spring HTTP, current-source Node Harness, Core journal, Java SDK, scheduler and worker paths with H2, same-JVM independent Spring contexts, a scripted approval provider and controlled holds/503 replies. No actual dispatcher process kill, MySQL, real-model, browser, packaged-CLI or mixed-old-writer ordering acceptance is claimed. New-head CI and human review are reported separately; the old head's green checks do not validate this commit.

äļ­æ–‡ïžšæœŽæŽĄåœĻ同äļ€äļŠ PR 内čĄĨé―åŪĄæ‰đæĒåĪå’Œåđķ发æ”đ名。79 äļŠåŪšå‘ Java server į”Ļäū‹ã€57 äļŠ SDK、31 äļŠ Core、10 äļŠåĨ‘įšĶ及最įŧˆčŋŸåˆ°æ ‡éǘč·Ŋį”ąį”Ļäū‹å‡é€ščŋ‡ïžŒįąŧ型æĢ€æŸĨ、栞垏、åŪšå‘ lint 和 Checkstyle äđŸé€ščŋ‡ã€‚įœŸåŪžäž čū“éЌčŊčĶ†į›–æ—§čŊ·æą‚晚到、SDK čķ…æ—ķ后čŋœįŦŊįŧ§įŧ­æ‰§čĄŒã€å·ē提äšĪ回包äļĒåĪąįš„č‡ŠåŠĻäŋŪåĪïžŒäŧĨ及įŧ‘åŪšå’ŒæœŠįŧ‘åۚ Session éĶ–æŽĄæ”đ名尚朊äŋå­˜ boot æ—ķįš„æĒåĪïž›å…Žå…ąäļŽį§æœ‰æ ‡éĒ˜æœ€įŧˆäļ€č‡ī重æ”ūäļé‡åĪå†™ journal。éŧ˜čŪĪæĒåĪå…ģ闭æ—ķåŪĄæ‰đäļĒåĪąįž“å­˜åŽäŧåŪŒæˆïžŒį́į”Ļå‰Ŋ朎äļæŠĒ占 requested äŧŧåŠĄïž›įœŸåŪž worker įš„æ–‡äŧķæ•ˆæžœå·ē驌čŊã€‚反向æ’Ī回äŋæŠĪčƒ―é‡įŽ°åŽŸé—ŪéĒ˜ã€‚éĶ–æŽĄæ”đ名銌čŊäļ­åŪžé™…å‘įŽ°įš„404äļŽ409įžšåĢå·ēäŋŪåĪïžŒåˆå§‹åĪąčīĨåŠå„å€™é€‰į‰ˆæœŽįš„å―’åąžäŋį•™ã€‚H2ã€č„šæœŽæĻĄåž‹ã€åŒ JVM įš„į‹ŽįŦ‹ Spring context 和故障æģĻå…Ĩ均有明įĄŪ标æģĻäļå°†å…ķå―“ä―œį”Ÿäš§ MySQL、čŋ›įĻ‹åīĐæšƒã€æĩč§ˆå™Ļæˆ–įœŸåŪžæĻĄåž‹éЌæ”ķ。新提äšĪ CI äļŽäššå·ĨåŪĄé˜…åĶ行æŠĨ告#13269 įš„å…ķäŧ–äš‹éĄđäļåœĻčŋ™é‡Œå…ģ闭。

@qwen-code-review-bot

qwen-code-review-bot commented Oct 8, 2026 •

Copy link
Copy Markdown
Collaborator

ðŸĐš serve daemon A/B

Built the PR base vs this PR head ab1af69, drove a fixed endpoint set against each, and diffed the JSON responses. Only fields that changed are shown.

health-deep-with-session

field PR base (before) this PR (after)
activeWorkStaleMs 4 5

— Qwen Code · serve A/B

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
@yiliang114

Copy link
Copy Markdown
Collaborator Author

Pushed ordinary merge commit bdb136c76b94, incorporating main 29aef7de40b7 on this same branch. The previous lint failure stopped at gate freshness, before static analysis, because the branch lacked the latest main-side gate change. All eight gate changes are now contained; selected ESLint passes under the updated rules.

The 32-file repair payload remains byte-for-byte identical to the candidate documented above. After rebuilding the changed Core and ACP dependencies, Core metadata tests (31 cases) and CLI typecheck pass. The test engineer reran the real transport probes against this merged tree: approval cache-loss recovery passes in 12.99s, including the worker's proof.txt=after effect and unchanged requested retry state on the disabled replica; concurrent rename passes in 7.89s, including late-write rejection, a real SDK timeout, read-only completed replay and scheduled repair after a committed reply is lost.

The committed tree is identical to the tested merge index. Source/classes, both generated runtime trees and 122 dependency jar hashes were stable throughout the probes; the two new owned process groups were cleaned up. These probes retain the earlier H2, same-JVM Spring-context, scripted-provider and controlled-fault boundaries. Fresh-head CI and human approval remain separate from this local acceptance evidence.

äļ­æ–‡ïžšå·ēį”Ļæ™Ū通合åđķæäšĪ同æ­Ĩ mainäŋį•™å·ē有历åēåđķįŧ§įŧ­ä―ŋį”Ļ朎 PR。æ­Ī前 lint åœĻ“é—Ļį́æ˜ŊåĶ包åŦ main æœ€æ–°į‰ˆæœŽâ€æ­ĨéŠĪ提前åĪąčīĨïž›įŽ°åœĻ 8 äļŠé—ĻįĶæäšĪ均å·ē包åŦïžŒæ–°č§„åˆ™äļ‹įš„åŪšå‘ lint 通čŋ‡ã€‚原äŋŪåĪæķ‰åŠįš„ 32 äļŠæ–‡äŧķæœŠå˜ã€‚æ›ī新 Core、ACP 构åŧšäš§į‰Đ后31 äļŠå…ƒæ•°æŪį”Ļäū‹å’Œ CLI įąŧ型æĢ€æŸĨ通čŋ‡ïž›åŪĄæ‰đᜟåŪžé“ūč·ŊåĪéŠŒ 12.99 į§’ã€åđķ发æ”đ名åĪéŠŒ 7.89 į§’å‡é€ščŋ‡ïžŒčĶ†į›–įž“å­˜äļĒåĪąã€į́į”Ļå‰Ŋ朎äļæŠĒäŧŧåŠĄã€įœŸåŪž worker 文äŧķæ•ˆæžœã€čŋŸåˆ°å†™å…Ĩ、SDK čķ…æ—ķ和回包äļĒåĪąåŽįš„č‡ŠåŠĻäŋŪåĪã€‚æĩ‹čŊ•įīĒåž•äļŽæäšĪ树äļ€č‡īčū“å…Ĩ指įšđįĻģåŪšïžŒč‡Šæœ‰čŋ›įĻ‹å·ēæļ…į†ã€‚æēŋį”Ļ前čŋ° H2、同 JVMã€č„šæœŽæĻĄåž‹å’Œæ•…éšœæģĻå…Ĩįš„éŠŒčŊčūđį•ŒïžŒæ–°į‰ˆæœŽ CI äļŽäššå·Ĩæ‰đ准åĶ行įĄŪčŪĪ。

yiliang114 and others added 2 commits October 9, 2026 02:21
ActionResponseCoordinator.recover() scans every deliverable
ACTION_RESPONSE operation across tenants, so the PENDING response left in
the shared test database by
disabledReplicaSettlesOnlyJournalProvenEndedResponses reached this mock
and bumped the resolveAction counter, making calls.get() 2 instead of 1
on both the MySQL 8.4 and the MariaDB lane.

Ignore resolveAction calls for other action ids, the same action-scoped
shape the shared harness mock already uses via its responses map.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Patrol-Run: qwen-pr-conflict/jmuzuwh4lfc
WorkspaceMigrationMySqlIT.upgradesCurrentMainWithoutChangingAppliedMigrations
pins the versions applied on top of the V47 baseline. V53 was added by this
pull request without extending that list, so the MariaDB lane failed with
["48", ..., "53"] against ["48", ..., "52"].

The failure only surfaced after the earlier ManagedActionsTest failure was
fixed: the lane stops once the first surefire batch fails, and this class is
in the second batch, so it never executed on the previous head.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Patrol-Run: qwen-pr-conflict/jmuzuwh4lfc
@qwen-code-review-bot

Copy link
Copy Markdown
Collaborator

Qwen Code review timed out. Qwen review timed out after 21600 seconds (of the 360-minute budget). This run already used the maximum 360 minute timeout. See workflow logs.

â€Ķssion

Reject disabled or unsupported title requests before admission, claim inline
delivery before I/O, and fence failed-owner cleanup against lease takeover.
Include unfinished title deliveries in workspace migration idle checks.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
@yiliang114

yiliang114 commented Oct 9, 2026 •

Copy link
Copy Markdown
Collaborator Author

The new main conflict repair was delivered by conflict patrol jmv2cx7ur0s at 785dc863ebd0, with an additive merge of actual main 2ebbd4e12d25 and normal push. The sole manual conflict was the MySQL upgrade-history assertion: it now retains versions 48–57, V59 rename delivery, V60 child workspace and upstream V62 task cancellation. Rename SQL is unchanged. Both independent migration admission guards remain: unsettled rename delivery and open child workspaces. The upstream task-cancel change is distinct from rename recovery; no rename cancellation, retirement or compensation protocol was added.

Consolidated verification on frozen tree fee3d84dd8d2, exactly matching the delivered commit: 191 distinct freshly executed cases (SDK 65, server 120, CLI 6), with Java compilation, explicit server Checkstyle, Flyway uniqueness, Core/ACP prerequisite builds, CLI typecheck and diffcheck passing. The unchanged Core authority/rename metadata sources and tests retain the earlier 71 + 31 case evidence; they were not rerun or added to the fresh count. Only necessary SDK/Core/ACP artifacts were refreshed once each. The first selected CLI run retained 5 passes and 1 unexplained socket failure in the parked-agent continuation case. A single isolated instrumented retry passed without source changes and before the Core build; its trace showed continuation HTTP200, cancellation/status completion and DELETE204. The original failed request boundary remains unknown, and instrumentation may affect timing. Thus 191 distinct cases have passing results across 192 executions; 349 initial and 354 retry-filtered cases are excluded. The first CLI typecheck failed because the installed ACP Bridge declaration lacked an export already present in current source; one package-only refresh followed by only a typecheck rerun passed. Both initial failures remain recorded. H2 applied V59/V60/V62. MySQL IT was compiled only locally; database execution belongs to new-head CI. No full dependency reinstall, full suite, UI/tmux or real-model rerun is claimed. The delivered Git tree and both parents exactly match the frozen local candidate; this reuses its actual verification, not a fresh post-push execution.

All four technical workflows for this exact head completed successfully: Qwen Code CI, including Web Shell E2E Smoke, SDK Java, including MariaDB and MySQL process fault gates, Serve A/B, and tui-parity. The 2026-10-10 13:56 UTC snapshot is 19 successful technical checks, 3 intentional skips, 0 pending and 0 failures. GitHub reports MERGEABLE / BLOCKED / REVIEW_REQUIRED; all 30 review threads remain resolved with no new actionable feedback, and no formal human approval is present. Technical CI is complete. Human approval and an authorized merge remain outstanding. Existing reviewer requests remain in place; no duplicate request or passive automatic-review wait was added. The main freshness observation at a765daf8bbc2 below belongs to the preceding 13:26 UTC snapshot.

Scope ledger: the original eight-file +74/-7 baseline remains the approval starting point. Current scope against the current base remains 38 files +1305/-72, with no new PR paths or differing original production patch payloads relative to the updated base. This required conflict repair is cumulative round 14, after 13 prior rounds; optional Suggestions remain deferred under the late-round rule. R2-4 keeps the owner-confirmed safe-recovery contract: permanent Harness unavailability remains an external blocker, and retry counts or later refusals do not discard a possibly committed rename. Actual main is now a765daf8bbc2: its two later provider/MCP fixes change none of the eight gate paths; freshness remains established without another merge, build or test.

Historical attribution: 65bf85b91914 passed all four technical workflows (19 successes, 3 intentional skips), including Qwen Code CI/Web Shell E2E, SDK Java/MariaDB/MySQL process fault gates, Serve A/B and tui-parity. The 189-case local run stays attributed to frozen candidate 0f0401946b3a with documented package source equivalence to65. The 429 cases on6120fc51 and actual UI/tmux evidence on61449726 remain earlier-head evidence. None is relabeled as new-head CI or runtime execution.

äļ­æ–‡ïžščŋœįŦŊå†ēįŠå·ĄæĢ€å·ēæ­Ģåļļčŋ―加合åđķåđķæŽĻ送 785dc86合å…ĨåŪžé™… main 2ebbd4e。å”Ŋä‰‹å·Ĩå†ēįŠäļš MySQL å‡įš§åŽ†åē断čĻ€ïžŒįŽ°äŋį•™48–57、V59æ”đ名投递、V60子å·Ĩä―œåŒšåŠäļŧįšŋV62äŧŧåŠĄå–æķˆïž›äšĪäŧ˜Git树及äļĪäļŠįˆķ提äšĪäļŽå·ē驌čŊå€™é€‰åیå…Ļį›ļåŒïžŒæœŽčŠåĪĐäļé‡åĪæäšĪ或æŽĻ送。æ”đ名SQLäļå˜ïžŒæœŠåŪŒæˆæ”đ名投递和朊æ”ķå°ū子å·Ĩä―œåŒšäļĪé“į‹ŽįŦ‹čŋį§ŧæĢ€æŸĨéƒ―äŋį•™ã€‚äļŧįšŋäŧŧåŠĄå–æķˆäļŽæœŽPRæ”đ名æĒåĪæ˜ŊäļåŒåĨ‘įšĶæēĄæœ‰åĒžåŠ æ”đ名取æķˆã€é€€äž‘或čĄĨåŋ协čŪŪ。候选树fee3d84däļŽäšĪäŧ˜æäšĪåیå…ĻåŒđ配åŪžé™…æ–°æ‰§čĄŒ 191 éĄđäļåŒį”Ļäū‹ïžˆSDK65ã€æœåŠĄįŦŊ120、CLI 6Javaįž–čŊ‘、æ˜ū垏Checkstyle、Flywayå”Ŋä€§ã€åŋ…č́Core/ACPäš§į‰Đ构åŧšã€CLIįąŧ型æĢ€æŸĨäļŽdiffcheck通čŋ‡ã€‚æšį åŠæĩ‹čŊ•äļå˜įš„Core71+31éĄđæēŋį”Ļ原čŊæŪäļé‡åĪæ‰§čĄŒæˆ–åŠ å…Ĩ新čŪĄæ•°ã€‚åˆæŽĄCLIäļš5通čŋ‡ã€1éĄđ停éĐŧagentįŧ§įŧ­čŊ·æą‚å‡šįŽ°æ— æģ•å―’å› įš„socket断čŋžïž›äŧ…åĪąčīĨéĄđäļ€æŽĄį‹ŽįŦ‹åļĶHTTPčŪ°å―•åĪæĩ‹é€ščŋ‡ïžŒæšį æœŠæ”đäļ”å‘į”ŸåœĻCore构åŧšäđ‹å‰ã€‚åĪæĩ‹čŪ°å―•įŧ§įŧ­HTTP200、取æķˆ/įŠķ态æ”ķ敛äļŽDELETE204原始åĪąčīĨčŊ·æą‚čūđį•ŒäŧæœŠįŸĨčŪ°å―•äŧŠå™ĻåŊčƒ―å―ąå“æ—ķ嚏。因æ­Ī191éĄđäļåŒį”Ļäū‹å·ē有通čŋ‡įŧ“果åŪžé™…æ‰§čĄŒ192æŽĄïžŒ349/354éĄđčŋ‡æŧĪį”Ļäū‹äļčŪĄã€‚éĶ–æŽĄCLIįąŧ型æĢ€æŸĨ因旧ACPåĢ°æ˜Žįžšå°‘å―“å‰æšį å·ē有åŊžå‡šč€ŒåĪąčīĨïž›äŧ…刷新čŊĨ包åđķé‡č·‘įąŧ型æĢ€æŸĨ后通čŋ‡ïžŒäļĪæŽĄåˆå§‹åĪąčīĨ均äŋį•™ã€‚ MySQL朎地äŧ…įž–čŊ‘äļåĢ°į§°æ–°č·‘UI/tmuxã€įœŸåŪžæĻĄåž‹æˆ–å…Ļ量驌æ”ķ。新head四éĄđ技æœŊå·Ĩä―œæĩå·ēå…ĻéƒĻcompleted/successïžšQwen Code CIåŦWeb Shell E2E Smoke、SDK JavaåŦMariaDB和MySQLčŋ›įĻ‹æ•…éšœé—ĻįĶïž‰ã€Serve A/B及tui-parity。13:56 UTCåŋŦį…§äļš19éĄđ成功、3éĄđ有意č·ģčŋ‡ã€0éĄđį­‰åū…、0éĄđåĪąčīĨ技æœŊCIå·ēåŪŒæˆã€‚GitHubäŧäļšMERGEABLE / BLOCKED / REVIEW_REQUIRED䚚å·Ĩæ‰đ准äļŽčŽ·æŽˆæƒįš„äššåˆåđķäŧæ˜Ŋį‹ŽįŦ‹åū…åŪŒæˆéĄđïž›ä–‡a765daf8äļŧįšŋ新éēœåšĶæ˜Ŋ前č―Ū13:26 UTCčŪ°å―•ã€‚ 30äļŠįšŋįĻ‹äŧå·ēč§Ģå†ģæ­Ģ垏䚚å·Ĩæ‰đ准äļš0æ—Ē有åŪĄæ ļčŊ·æą‚äļé‡åĪå‚ŽåŪĄïžŒäššå·Ĩæ‰đå‡†åŠčŽ·æŽˆæƒįš„äššåˆåđķäŧåū…åŪŒæˆã€‚čŒƒå›īäŋæŒ38文äŧķ+1305/-72įīŊčŪĄ14č―ŪïžŒåŽŸį”Ÿäš§å˜æ›ī内åŪđäļŽæ›īæ–°åŽįš„baseåŊđåš”äŋæŒäļå˜ã€‚R2-4按į”Ļ户įĄŪčŪĪäŋį•™åŪ‰å…ĻæĒåĪäļŽæ°ļäđ…äūčĩ–äļåŊį”Ļįš„åĪ–éƒĻé˜ŧåĄžïžŒäļäŧĨ重čŊ•æŽĄæ•°æˆ–åŽįŧ­æ‹’įŧäļĒ垃åŊčƒ―å·ē提äšĪįš„æ”đ名。65įš„å…ĻįŧŋCI、0f候选189éĄđ、6120驌čŊåŠ614åŪžé™…UI/tmuxįŧ§įŧ­äŋį•™åŽŸå―’åąžã€‚ åŪžé™…mainå·ē到a765daf8äļĪéĄđ后įŧ­provider/MCPäŋŪåĪæœŠäŋŪæ”đ8éĄđé—Ļį́č·Ŋåū„æēĄæœ‰æ–°åĒžæœšæĒ°å†ēįŠæˆ–é‡åĪåˆåđķ/驌čŊã€‚

Earlier acceptance evidence, retained with original commit attribution

Delivered the new actual-main conflict repair at 6120fc513659, merging main 5b1c701400c9 by an additive merge commit and normal push. Rename role admission stays before completed-receipt replay; execution facts gate new work, and durable fenced rename admission/recovery remains intact. The cold-cache approval regression retains upstream READER refusal, second-OPERATOR handoff and same-responder replay. Main allocated V56 to operation actor keys, so the unmerged rename SQL is now V57, byte-identical, with the MySQL upgrade-history pin and both design languages synchronized. No retirement/cancellation protocol was added.

Consolidated verification on frozen tree c1e06bcfe97c, exactly matching the delivered commit: 429 freshly executed cases passed (Java394, Core31, CLI4);306 filter-excluded CLI cases are not counted. Java compilation, explicit server checkstyle:check with zero violations, Flyway uniqueness, Core/CLI typechecks, changed-file Prettier and diffcheck passed. H2 applied V56 actor keys then V57 rename delivery. One necessary Core declaration build refreshed prerequisites. The first candidate failed test compilation because the merged cold-cache fixture lost two imports; no test executed in that attempt. Both imports were restored before the passing retry; initial failures and the byte-matched stale generated migration backup remain preserved.

Evidence correction: the prior797 server mvn test did not execute Checkstyle; that server Checkstyle claim is withdrawn. The prior SDK install did execute SDK Checkstyle, and this round has explicit server Checkstyle evidence. SDK source is byte-unchanged versus797 and its earlier verified tree, so57 prior SDK cases are reused as historical evidence, excluded from the429 fresh cases. HostedPublicWorkspaceIT was compiled, not locally executed; fresh full Node/MySQL integration belongs to the new-head CI. Actual UI/tmux evidence remains attributed to61449726. No dependency reinstall, full-suite, UI/tmux, real-model or local MySQL/process-fault rerun was performed.

Scope against actual main5b1c7014 is 38files +1305/-72 (18production +563/-38,15test +616/-27,5docs +126/-7), cumulative round12. Compared with797, the net change is two required test imports and one corrected existing comment (+3/-1), with no new module or protocol. Sixteen original production patch payloads are unchanged; the sole differing service payload incorporates the upstream role/facts gates and corrects the admission-method name. R2-4 remains the explicitly owner-confirmed external-blocker contract: uncertain admitted writes stay recoverable even if the Harness is permanently unavailable. No FAILED-state cancellation is claimed. Existing optional test suggestions stay deferred under the late-round scope rule.

The one post-push snapshot for this exact head reports 1 technical check succeeded, 3 skipped, 16 pending, zero failed; informational assignment/label checks are excluded. GitHub is MERGEABLE / BLOCKED / CHANGES_REQUESTED. The mechanical conflict is cleared, but current-head technical CI is not yet complete.797’s completed green workflows below remain historical. All30 existing review threads retain their recorded dispositions; no new actionable feedback was found at entry. Human re-review/approval and an authorized merge remain separate gates, including CodeOwner review under the effective main ruleset. Existing reviewer requests are retained; no duplicate request or passive CI/automatic-review wait was started.

äļ­æ–‡ïžšå·ēæ­Ģåļļčŋ―加合åđķæäšĪ6120fc513659合å…ĨåŪžé™…main 5b1c701。äŋį•™äļŧįšŋâ€œå…ˆæ ĄéŠŒč§’č‰ē再重æ”ūå›žæ‰§ã€æ‰§čĄŒäš‹åŪžé™åˆķ新å·Ĩä―œâ€įš„æƒé™įšĶ束äŧĨ及朎PRåŽŸæœ‰įš„åļĶį‰ˆæœŽæ”đ名投递和åŪ‰å…ĻæĒåĪã€‚å†·įž“å­˜åŪĄæ‰đæĩ‹čŊ•äŋį•™READER拒įŧã€įŽŽäšŒä―OPERATORäšĪæŽĨäļŽåŒäļ€į­”åĪäššįš„åđ‚į­‰é‡æ”ū。main占į”ĻV56 operation actor-key后朎PR朊合å…Ĩįš„æ”đ名čŋį§ŧ饚åŧķV57SQLé€å­—čŠ‚äļå˜ïžŒMySQLå‡įš§åŽ†åē断čĻ€åŠäļ­č‹ąæ–‡čŪūčŪĄåŒæ­Ĩ朊重新垕å…Ĩ退䞑或取æķˆåčŪŪ。

朎č―Ū同äļ€å€™é€‰æ ‘429éĄđåŪžé™…æ‰§čĄŒį”Ļäū‹å…ĻéƒĻ通čŋ‡ïžˆJava394、Core31、CLI4306éĄđčŋ‡æŧĪCLIį”Ļäū‹äļčŪĄå…Ĩ。Javaįž–čŊ‘、æ˜ūåžæœåŠĄįŦŊCheckstyleé›ķčŋč§„、čŋį§ŧå”Ŋä€§ã€Core/CLIįąŧ型æĢ€æŸĨ及栞垏/diffcheck通čŋ‡ïž›H2äūæŽĄåš”į”ĻV56äļŽV57及äļšé™ˆæ—§åĢ°æ˜Žæž„åŧšäļ€æŽĄCore。éĶ–æŽĄå€™é€‰äļĒåĪąäļĪäļŠæĩ‹čŊ•åŊžå…ĨïžŒįž–čŊ‘é˜ķæŪĩåĪąčīĨäļ”į”Ļäū‹æ‰§čĄŒäļš0ïž›čĄĨé―åŽé‡č·‘é€ščŋ‡ïžŒåĪąčīĨäļŽæ—§į”Ÿæˆčŋį§ŧå·äŧ―均äŋį•™ã€‚įš æ­Ģæ—§čŪ°å―•ïžšäļŠč―Ū797æœåŠĄįŦŊmvn testæēĄæœ‰åŪžé™…æ‰§čĄŒCheckstyleå…ķæœåŠĄįŦŊCheckstyle通čŋ‡åĢ°æ˜Žæ’Ī回SDK旧installæœ‰č‡ŠčšŦCheckstylečŊæŪ朎č―ŪåĶ有æ˜ūåžæœåŠĄįŦŊåŪžæĩ‹ã€‚SDKæšį æœŠå˜ïžŒæ—§57éĄđSDKį”Ļäū‹äŧ…æēŋį”Ļ历åēčŊæŪäļįŪ—æœŽč―Ū429éĄđ。HostedPublicWorkspaceIT朎地äŧ…įž–čŊ‘åیæ•īNode/MySQLčŋčĄŒį”ąæ–°head CI驌čŊïž›åŪžé™…UI/tmuxäŧå―’åąž61449726朊重åĪčŋčĄŒæ—ķ驌æ”ķ。

范å›īäļš38文äŧķ1305/-72įīŊčŪĄ12č―Ūį›ļåŊđäļŠč―Ū净变化äŧ…äļĪäļŠåŋ…č́åŊžå…Ĩ和äļ€åĪ„æ—Ē有æģĻ释+3/-1æēĄæœ‰æ‰ĐåΧæĻĄå—æˆ–åčŪŪ。R2-4įŧ§įŧ­æŒ‰į”Ļ户įĄŪčŪĪäŋį•™åŪ‰å…ĻæĒåĪäļŽæ°ļäđ…äūčĩ–äļåŊį”Ļįš„åĪ–éƒĻé˜ŧåĄžïžŒäļå̰᧰FAILEDįŧˆæ€å–æķˆå·ēåŪžįŽ°ïž›åŊ选单æĩ‹åŧščŪŪäŋæŒå·ēčŪ°å―•įš„åŽįŧ­åĪ„į―Ū。新提äšĪå”ŊäŽĻ送åŋŦį…§äļš1éĄđ技æœŊæĢ€æŸĨ成功、3éĄđč·ģčŋ‡ã€16éĄđåū…åŪŒæˆã€0åĪąčīĨïžŒč‡ŠåŠĻ标į­ū/分配æĢ€æŸĨäļįŪ—æŠ€æœŊįŧ“果。GitHubå·ēæĒåĪMERGEABLEïžŒä―†äŧäļšBLOCKED / CHANGES_REQUESTEDïž›äļŧįšŋå†ēįŠå·ēč§Ģé™Ī新head CI尚朊æ”ķé―ã€‚æ—§797å…Ļįŧŋ及äŋį•™åކåēå―’åąžïžŒäššå·ĨåĪåŪĄã€CodeOwneræ‰đ准äļŽčŽ·æŽˆæƒįš„äššåˆåđķäŧåū…åŪŒæˆïžŒäļé‡åĪå‚ŽåŪĄæˆ–į­‰åū…臊åŠĻčŊ„åŪĄã€‚

Prior actual-main merge and completed technical CI (797e27d)

Delivered actual-main conflict repair at 797e27da640e, merging main e6e2c9efd1dd with an additive merge commit and a normal push. Main added channel tests next to the existing parameterized approval case; both are preserved. Main also allocated V55 to channel binding, so the unmerged rename migration now uses V56 with byte-identical SQL. The upgrade-history pin and both design languages are synchronized. No history rewrite or retirement/cancellation protocol was added.

Focused consolidated verification on candidate tree586b951f, exactly matching the delivered commit: 229 executed cases (SDK57, server137, Core31, CLI4), zero test failures/errors;305 filter-excluded CLI cases are not counted. Java compilation, Flyway uniqueness, Core/CLI typechecks, changed-file Prettier and diffcheck passed. H2 applied V55 channel binding then V56 rename delivery. The first CLI typecheck found stale local Core/email declarations from before main sync; after one necessary Core/email prerequisite build, only that typecheck reran and passed. The initial failure and the byte-matched stale generated migration backup remain in the evidence. No full suite, dependency reinstall, UI/tmux or MySQL fault rerun was performed.

Scope against actual main e6e2c9e stays 38files +1302/-71 (18production +562/-37,15test +614/-27,5docs +126/-7), with zero net scope growth and cumulative round11. All17 original production-code diff payloads are preserved relative to the new base; the SQL body is unchanged. The original eight-file baseline and confirmed recovery contract are retained.

The human review at71351f1e reported no new correctness defect and identified the mechanical conflict now fixed by this merge. Its R2-4 availability limitation remains the explicitly owner-confirmed external-blocker contract, not a terminalization fix. Optional unit-test gaps remain recorded follow-ups under the late-round scope rule; prior actual scheduler/HTTP/UI evidence stays pinned to61449726 and is not converted into a new-head test. A permanently unavailable Harness may continue to block admitted uncertain work; no retry budget discards it.

Technical CI is complete and green for 797e27da640e: Qwen Code CI including WebShell E2E Smoke, SDK Java including MariaDB/MySQL process fault gates and real-daemon E2E, Serve A/B, and TUI parity/no-flicker. All four workflows report completed/success for this exact head;18 technical checks succeeded and3 were skipped. The earlier one post-push snapshot with16 pending checks is retained as history. All30 review threads have dispositions, with zero unresolved and no new actionable feedback. The PR remains MERGEABLE / BLOCKED / CHANGES_REQUESTED: human re-review and an authorized merge are outstanding. Legacy main branch protection requires2 approvals; the effective ruleset also requires CodeOwner review. Queued automated review remains informational; later findings will be handled when they arrive. Existing reviewer requests remain in place. No source change, new validation run, duplicate review request or passive wait was needed for this CI completion; actual UI/tmux evidence remains attributed to61449726.

äļ­æ–‡ïžšå·ēæ­Ģåļļčŋ―加合åđķæäšĪ797e27da合å…ĨåŪžé™…main e6e2c9e。äŋį•™äļļäļĪéĄđæļ é“æĩ‹čŊ•äļŽåŽŸåŪĄæ‰đ参数化æĩ‹čŊ•ïž›main新åĒžV55æļ é“įŧ‘åŪšåŽïžŒæœŽPR尚朊合å…Ĩįš„æ”đ名čŋį§ŧ饚åŧķV56SQLé€å­—čŠ‚äļå˜ïžŒå‡įš§åކåē断čĻ€äļŽäļ­č‹ąæ–‡čŪūčŪĄåŒæ­Ĩ。æēĄæœ‰é‡å†™åކåēäđŸæēĄæœ‰é‡æ–°åž•å…Ĩ退侑/取æķˆåčŪŪ。

同äļ€å€™é€‰æ ‘äļŠįš„229éĄđåŪžé™…æ‰§čĄŒį”Ļäū‹é€ščŋ‡ïžˆSDK57ã€æœåŠĄįŦŊ137、Core31、CLI4305éĄđ朊选CLIį”Ļäū‹äļįŪ—éŠŒčŊã€‚Javaįž–čŊ‘、čŋį§ŧå”Ŋä€§ã€Core/CLIįąŧ型æĢ€æŸĨ及栞垏/diffcheck通čŋ‡ïž›H2äūæŽĄåš”į”ĻV55äļŽV56。CLIéĶ–æŽĄįąŧ型åĪąčīĨæĨč‡Šåˆå…Ĩmainå‰įš„æ—§Core/emailåĢ°æ˜ŽïžŒåŋ…č́äūčĩ–各构åŧšäļ€æŽĄåŽåŠé‡č·‘čŊĨįąŧ型æĢ€æŸĨåđķ通čŋ‡ïžŒåĪąčīĨäļŽæ—§į”Ÿæˆčŋį§ŧå·äŧ―äŋį•™ã€‚čŒƒå›īäŧäļš38文äŧķ1302/-71įīŊčŪĄ11č―Ū17åĪ„åŽŸį”Ÿäš§äŧĢį å˜æ›īåیæ•īäŋį•™ã€‚æ­ĪæŽĄæēĄæœ‰é‡åĪå…Ļ量åŪ‰čĢ…ã€æĩ‹čŊ•、UI/tmux或MySQL故障銌æ”ķ旧61449726čŋčĄŒæ—ķčŊæŪäŧäŋæŒåŽŸå―’åąžã€‚

最新䚚å·ĨreviewįĄŪčŪĪæēĄæœ‰æ–°æ­ĢįĄŪæ€§įžšé™·ïžŒæŒ‡å‡šįš„æœšæĒ°å†ēįŠįŽ°å·ēč§Ģå†ģïž›R2-4äŧæŒ‰į”Ļ户明įĄŪ选æ‹Đäŋį•™æ°ļäđ…äūčĩ–äļåŊį”Ļįš„åĪ–éƒĻé˜ŧåĄžïžŒäļå̰᧰įŧˆæ€å–æķˆå·ēåŪžįŽ°ã€‚åŊ选单æĩ‹įžšåĢįŧ§įŧ­čŪ°å―•äļšåŽįŧ­ã€‚797e27daå―“å‰æäšĪįš„å››éĄđ技æœŊå·Ĩä―œæĩįްå·ēå…ĻéƒĻåŪŒæˆåđķ通čŋ‡ïžšQwen Code CIåŦWebShell E2E、Java SDKåŦMariaDB/MySQLčŋ›įĻ‹æ•…éšœäļŽįœŸåŪždaemon E2E、Serve A/B及TUIåŋŦį…§/æ— é—ŠįƒæĢ€æŸĨïž›18éĄđ技æœŊæĢ€æŸĨ成功、3éĄđč·ģčŋ‡ã€0éĄđåū…åŪŒæˆã€0éĄđåĪąčīĨ。原æŽĻ送åŋŦį…§įš„16éĄđåū…åŪŒæˆäŋį•™äļšåކåē。30äļŠčŊ„åŪĄįšŋįĻ‹å‡æœ‰åĪ„į―Ū、0朊č§Ģå†ģæēĄæœ‰æ–°åĒžåŊæ“ä―œåéĶˆã€‚PRäŧäļšMERGEABLE / BLOCKED / CHANGES_REQUESTED技æœŊCI通čŋ‡äļŽäššå·Ĩæ‰đ准分垀čŪ°å―•ïž›å―“å‰mainįš„äž įŧŸåˆ†æ”ŊäŋæŠĪčĶæą‚2äļŠæ‰đå‡†ïžŒį”Ÿæ•ˆč§„åˆ™é›†åĶåĪ–čĶæą‚CodeOwneråŪĄæ ļïž›æŽ’é˜Ÿįš„č‡ŠåŠĻčŊ„åŪĄäļįŪ—æŠ€æœŊCIé—Ļ槛后įŧ­æœ‰æ•ˆåé͈äŧäžšåĪ„į†ã€‚įŽ°æœ‰reviewčŊ·æą‚äļé‡åĪå‚ŽåŪĄïžŒį­‰åū…äššå·ĨåĪåŪĄåŠčŽ·æŽˆæƒįš„äššåˆåđķ。æ­ĪæŽĄäļé‡åĪæĩ‹čŊ•或čŋčĄŒæ—ķ驌æ”ķåŪžé™…UI/tmuxäŧå―’åąž61449726旧71351f1eįš„CIäļįŪ—æ–°headįŧ“果。

Earlier accepted recovery evidence and scope correction (71351f1 and prior heads)

Delivered scope correction at 71351f1e8c5b. The owner reconfirmed preserve uncertain-write recovery and explicitly retain permanent Harness unavailability as an external blocker, and denied separate authorization for the retirement/cancellation expansion. The additive revert withdraws 3294358ee43c; it does not rewrite history or remove the earlier Clock fixture repair.

Verification: the entire tracked tree is exactly equal to9ae0c662, whose technical CI completed successfully (Qwen Code CI, SDK Java including MariaDB/MySQL fault gates, Serve A/B and TUI parity). All production files remain equal to the61449726 source used for actual browser/tmux acceptance. This correction runs no new runtime test/build and does not relabel historical results as a fresh71351f1e run. Staged diffcheck passed. A pre-existing empty index lock was backed up and removed only after no open owner or active Git target was found.

Current scope against main5ddd438: 38files +1302/-71 (18production +562/-37,15test +614/-27,5docs +126/-7). The26-file +866/-81 retirement extension is withdrawn. The original scope baseline remains eight files +74/-7, and substantive rounds remain cumulative (10); no new protocol/module responsibility was retained.

R2-4 is reconciled as an owner-confirmed contract limitation, not an implemented FAILED/RETIRED terminal branch. Fresh disabled/unsupported/invalid-title requests are rejected before admission. Already-admitted uncertain work stays recoverable and blocks close/archive/delete/cwd/storage migration until confirmed or superseded. Timeout, last-attempt refusal or a budget cannot release that obligation safely. Earlier statements that the owner selected complete safe retirement are superseded by the explicit decision above; the experimental retirement report is preserved below as historical evidence only.

Current-head technical CI is now complete and green at71351f1e8c5b against main5ddd43815bf1: Qwen Code CI including WebShell E2E Smoke, SDK Java including MariaDB/MySQL process fault gates and real-daemon E2E, Serve A/B and TUI parity/no-flicker. All four workflows report completed/success for the delivered head. The earlier post-push snapshot had11pending checks; it is retained as history, not the current result. The30review threads have dispositions, with zero unresolved and no new actionable feedback. The PR remains MERGEABLE / BLOCKED / CHANGES_REQUESTED: human/CodeOwner review and an authorized merge are outstanding. The queued automatic-review delay is informational, not a technical CI gate. Existing reviewer requests remain in place; no duplicate review request or passive wait was started.

äļ­æ–‡ïžšå·ēæ­Ģåļļčŋ―加提äšĪ71351f1eæ’Ī回3294358įš„é€€äž‘åčŪŪæ‰Đåą•ïžŒäŋį•™åŽŸäŋŪåĪäļŽClockåĪđ具čĄĨäļïžŒæēĄæœ‰é‡å†™åކåē。į”Ļæˆ·å†æŽĄæ˜ŽįĄŪ选æ‹Đ“äŋį•™åŪ‰å…ĻæĒåĪïžŒæ˜ŽįĄŪåĪ–éƒĻé˜ŧåĄžčūđį•Œâ€ïžŒåđķįĄŪčŪĪæœŠåĶčĄŒæŽˆæƒæ–°åĒžå–æķˆ/退侑æ–đæĄˆïž›æ­Ī前åĶäļ€č―ŪæŠĨ告äļ­įš„“å·ē选æ‹Đåیæ•ī退侑æ–đæĄˆâ€äļå†æ˜Ŋ有效åĨ‘įšĶ。åیæ•īäŧĢį æ ‘äļŽå·ē通čŋ‡å…ĻéƒĻ技æœŊCIįš„9ae0c662į›ļåŒïžŒį”Ÿäš§æšį äļŽ61449726įš„åŪžé™…UI/TUI驌æ”ķäļ€č‡īïž›æœŠé‡æ–°č·‘čŋčĄŒæ—ķæĩ‹čŊ•äļæŠŠåŽ†åēčŊæŪ重标äļš71351f1eã€‚čŒƒå›īæĒåĪ38文äŧķ1302/-71č―ŪæŽĄįīŊčŪĄ10新åĒž26文äŧķ866/-81å·ēæ’Ī回。R2-4按įĄŪčŪĪåĨ‘įšĶæ”ķå°ūäļå̰᧰įŧˆæ€å–æķˆå·ēåŪžįŽ°ïž›æ°ļäđ…äūčĩ–äļåŊį”Ļäŧæ˜Ŋ明įĄŪåĪ–éƒĻé˜ŧåĄžã€‚71351f1eå―“å‰æäšĪįš„å››éĄđ技æœŊå·Ĩä―œæĩįްå·ēå…ĻéƒĻåŪŒæˆåđķ通čŋ‡ïžšQwen Code CIåŦWebShell E2E、Java SDKåŦMariaDB/MySQLčŋ›įĻ‹æ•…éšœå’ŒįœŸåŪždaemon E2E、Serve A/B及TUIåŋŦį…§/æ— é—ŠįƒæĢ€æŸĨ。æ­Ī前11éĄđåū…åŪŒæˆæ˜Ŋ历åēæŽĻ送åŋŦį…§ã€‚30äļŠčŊ„åŪĄįšŋįĻ‹å‡æœ‰åĪ„į―Ū、0朊č§Ģå†ģæēĄæœ‰æ–°åĒžåŊæ“ä―œåéĶˆïž›PRäŧäļšMERGEABLE / BLOCKED / CHANGES_REQUESTEDïžŒį­‰åū…äššå·Ĩ/CodeOwneråŪĄæ ļåŠčŽ·æŽˆæƒįš„äššåˆåđķã€‚æŽ’é˜Ÿįš„č‡ŠåŠĻčŊ„åŪĄåŧķæ—ķäļæ˜Ŋ技æœŊCIé—Ļ槛äļé‡åĪå‚ŽåŪĄã€‚åŽŸ61449726įš„å—æŽ§æšį UI/TUIčŊæŪäŋæŒåŽŸå―’åąžïžŒäļåĢ°į§°æ–°č·‘čŋčĄŒæ—ķ驌æ”ķïž›åŪžéŠŒæ€§é€€äž‘æĩ‹čŊ•239éĄđåŠä―œäļšå·ēæ’Ī回åŪžįŽ°įš„åŽ†åēčŪ°å―•ïžŒäļįŪ—å―“å‰åŪžįŽ°įš„éŠŒæ”ķįŧ“果。

Verified original-contract evidence and prior dispositions (6144972 /9ae0c662)

Continuation at head 9ae0c6623487: the sole post-verification source change is a Clock registration in the artifact test fixture. The owner has now confirmed R2-4's contract: preserve uncertain-write recovery and retain permanent Harness unavailability as an external blocker. The decision is recorded in its thread, reconciled as a declined terminalization request, not as a implemented FAILED-state/cancellation fix.

Latest observed CI has no failed technical checks. Lint/static, Linux tests, integration, MariaDB, real-daemon, Serve A/B, TUI parity/no-flicker, desktop and all Java SDK matrices passed. MySQL process fault gates and WebShell E2E Smoke remain in progress; automatic review is also running. Branch rules require one approval and CodeOwner review; effective review is still CHANGES_REQUESTED. Pending checks and approval are not declared complete. No new production patch or repeat validation was needed for this contract decision.

Delivered head 61449726ead0, preserving both concurrent PR histories and main 5ddd43815bf1. The actual repairs are in cbb51009bb82; the final ordinary merge only incorporates four upstream WebShell artifact files. All 7,524 frozen inputs, including the 37 PR source files, stayed identical through verification and both commits. No force push or history rewrite.

The previous head's first failing CI step was the Flyway uniqueness gate: new main #13550 uses V54. The unmerged rename migration now uses V55 after roles/owner V53 and child-lineage V54, with unchanged schema/delivery contract; 55 unique migration versions pass locally. The earlier V53 collision and generated-resource failure remain historical records.

Fresh focused verification: 199 distinct selected Java cases, Java compilation and Checkstyle with zero violations, Core build, 31 Core metadata cases, one delayed-title CLI case and CLI typecheck passed. This is a selected set, not the entire repository suite. Two new Java assertions initially expected a nonexistent exception-details field; only those assertions were corrected and the affected 35 cases plus two dependency prerequisites reran successfully. The automatic main merge also introduced a duplicate CLI import; it was removed and the affected CLI checks passed. Initial logs/reports are preserved; reruns are not added to the distinct case count.

Fresh observer evidence on candidate 0387fe506be7b0dd085bec9e922a29b1bd46e1df1cad7d2e02b3b8cce713d943 / source identity 2faae7f639cc346f4a2f7997f7f557926e0d67b8d52928080659101e89ef5c4f, unchanged at the delivered head:

  • Real public HTTP rejected NBSP, FEFF, U+2007 and U+202F titles with400 invalid_title, no new command/outbox/private send, and allowed the same unbound Session's close admission. A bound mixed Unicode title preserved exact public/private equality.
  • A contract-valid controlled private409 crossed the actual SDK/connector/service and remained public409 session_mutation_superseded. An unrelated private409 remained503 hosted_harness_unavailable. The probe retains FAILED public receipts and PENDING delivery: it proves classification, not terminal delivery completion.
  • The actual Node ordering/recovery bridge passed in 8.24s. Same-key competition sent nothing; a different key was refused until the actual 2s SDK deadline failed the original receipt. The new title completed at revision3, and releasing the old Node write produced a real superseded409 while both stores stayed at the newer title. A revision4 commit with its reply dropped recovered automatically in a fresh scheduled context; SQL/private titles matched and journal count stayed 1→1.

Two observer fixture failures remain visible: a bound close was unavailable because that fixture explicitly lacks close support; the supported unbound close path then passed. The first controlled409 omitted the required boot identity, so SDK generation validation correctly returned503; a corrected classification-only run passed. Unicode evidence from that earlier run remains attributed to its completed arms. Pre-fix Unicode/409/gap-lock evidence this round is source/reviewer witness, not newly executed local reproduction. No fresh local InnoDB witness was run for the SQL repair; H2 does not establish InnoDB locking behavior.

Earlier approval cache-loss evidence remains at e0a734181381: 11.61s, default verified recovery disabled, original operation completed, worker proof.txt=after, and the disabled replica left pending delivery claim/retry state unchanged. It is historical approval evidence, not relabeled as a new current-head approval run. Earlier 191/220-case counts and 8.46s rename bridge are also historical, not cumulative.

Evidence boundary: macOS Java21/H2, real Spring/public/private HTTP, current-source Node Harness/SDK/Broker and compiled Core, scripted provider and controlled holds/reply drops. Separate Spring contexts share one JVM. The backend probes above do not claim real-model, MySQL/MariaDB/InnoDB, browser, packaged CLI or process-death acceptance; actual source-browser/tmux evidence is separately added below. The final upstream WebShell-only merge did not change the frozen acceptance paths. All observer-owned process groups are empty; no unrelated service/database was changed.

Actual UI/tmux acceptance added at tested head61449726ead0. At publication, PR head is9ae0c6623487: its sole subsequent change registers a Clock in the Java artifact test fixture; tested product sources are unchanged. Evidence below stays attributed to61449726, not relabeled as a fresh run on9ae0c662.

  • Real tmux TUI: WriteFile permission rendered; visible “Yes, allow once” wrote TUI_APPROVED_CURRENT_HEAD_614497, and PR13682_TUI_DONE appeared. Actual /rename PR13682 TUI verified updated the visible title and isolated JSONL custom-title record. Four ANSI/plain capture-pane frames are retained locally; backend-console capture is separately labeled.
  • Real managed WebShell UI: cleared connector attachment cache1→0, then one actual Allow UI response hit a controlled private503. The same original operation completed through the actual secondary Spring @Scheduled coordinator after only /healthy released the proxy; no manual recover or repeated first-action POST. Allowed the next Edit; real proof.txt=after and UI settled Completed/Ready. Typed/sent G0_AGAIN through the composer, rejected WriteFile and Edit through their permission cards; second turn completed and the file remained after. Four response operations are COMPLETED/CONFIRMED across two completed turns.
  • API rename plus real UI refresh: NBSP-only title returned400 with unchanged commands/deliveries/private titles. Mixed Unicode/visible title completed revision1 with exact public/private equality. Actual Refresh showed PR13682 UI verified in list/detail. The managed page has no rename control, so this does not claim UI rename-button coverage.

Actual tmux capture excerpt:

✓ WriteFile Writing to tui-proof.txt
  1 TUI_APPROVED_CURRENT_HEAD_614497
◆ PR13682_TUI_DONE
> /rename PR13682 TUI verified
● Session renamed to "PR13682 TUI verified"

Actual WriteFile approval before cache-loss response

Final actual UI after allow, deny and title refresh

Scope: actual source WebShell/components/TypeScript SDK in an isolated Vite host, real Java/H2/HTTP/Node Harness/Broker/file effects and separate source CLI tmux; controlled provider, same-JVM secondary Spring context. 1,269 frontend inputs and 7,524 native inputs stayed unchanged. No packaged UI/CLI, real-model, InnoDB or separate-process failover claim. Initial fixture compilation/scheduler setup failures, an incorrect empty-composer Send assertion and screenshot failures are preserved. Corrected composer interaction and final page-surface capture passed; the unrelated foreground-surface fallback was excluded and never published. No complete zero-console-error claim is made. These tests found no new defect in the exercised paths. R2-4 was subsequently reconciled by the owner-confirmed contract; the tests do not prove offline cancellation or terminal retirement.

Current-head CI and review approval remain separate gates. Five published Critical findings are fixed; R2-4 is reconciled under the owner-confirmed safety contract, with permanent-outage blocking accepted explicitly rather than a terminal-state implementation claimed. Optional suggestions are explicitly recorded below after eight substantive closeout rounds.

Post-push snapshot at 2026-10-09 07:06 UTC: delivered head61449726ead0, base5ddd43815bf1, MERGEABLE, review CHANGES_REQUESTED. Flyway uniqueness and SDK Java11/17/21 on Linux, Java21 on macOS/Windows passed. No failed technical check was reported; eight checks remained pending, including lint/tests, Managed Agent MariaDB/MySQL, real-daemon/integration and automatic review. Six duplicate Qwen Autofix route runs were cancelled, not reported as compiler/test failures. A concurrent patrol had closed the remaining discussions as follow-ups; R2-4 was explicitly reopened because retirement safety is still unagreed. Other recorded Suggestions remain deferred. No passive CI/review wait or rerun was started.

Published automatic review attempt 2, reviewed commit a557ab0, has different findings from the recovered attempt-1 artifact below even though both use R2 labels.

Published attempt-2 IDs Disposition
R2-1 Fixed: public Unicode-only titles fail400 before any durable admission; four focused regressions and real HTTP arms pass.
R2-2, R2-6 Already fixed in de20bb8: availability/fenced-protocol preflight before fresh admission, with completed receipt replay preserved. Disabled/old Harness requests leave no delivery and do not block close.
R2-3 Fixed: only actual HTTP409 with the named superseded code becomes public409. Other409 and wrong-status code controls remain on the dependency error path; real SDK HTTP control passes.
R2-5 Fixed source: both rename command replay probes and the new delivery missing-row read are nonlocking; tenant/Session locking and PK dedup remain. No new local InnoDB result claimed.
R2-4 Owner-confirmed contract; terminalization request declined. Fresh disabled/unsupported/invalid requests no longer create doomed rows. An admitted delivery can have an earlier committed/lost-reply write, so later refusal or a retry budget cannot release sealing/migration gates safely. The owner selected preserving recovery with permanent Harness unavailability explicitly an external blocker. No FAILED-state branch, offline cancellation or compensation protocol is claimed implemented.
R2-9 Already fixed in de20bb8: README design link uses three parent levels and resolves to the repository's linked design.
R2-7, R2-8, R2-11, R1-1, R2-13, R2-19, R2-21, R2-22, R2-25 Additional committed test matrices are deferred. Fresh real transport covers current revision forwarding and automatic worker orchestration; it does not replace every suggested mutation-test assertion. No test-gap suggestion is reported as fixed.
R2-12, R2-14, R2-15, R2-16, R2-17, R2-20 Scheduler capacity, lease renewal, per-row batch isolation, ordered scans and query/allocation cost are recorded follow-ups. Strict owner fencing and durable revision ordering remain; no broad coordinator rewrite this round.
R2-10, R2-18 README wording and duplicated settle projection cleanup are deferred. The pending-title admission contract remains documented; the two projections currently match.
R2-23 The reviewer reports a loaded fault-fixture race; current selected cases passed. The possible CI flake is recorded for follow-up, not claimed disproven by green runs.
R2-24 Keep existing public SDK constructor compatibility; older callers conservatively advertise protocol0 and fresh rename admission refuses them. No source-breaking shim removal.

Recovered unpublished attempt 1 (artifact11588875669, also reviewed a557ab0), retained with its original distinct IDs:

IDs Disposition
R2-1 Fresh disabled/unsupported title requests now fail before admission. Existing uncertain deliveries remain recoverable; blanket protocol-error terminalization/retry caps would lose accepted writes and are declined.
R2-2 Workspace migration counts every unfinished title delivery in the tenant/storage idle gate, including FAILED receipts and expired RUNNING deliveries.
R2-3, L2-2, L2-7 Inline requests claim before I/O. Failure cleanup requires the exact current unexpired RUNNING owner, under the same tenant/Session locks as takeover.
R2-15 Corrected the README design link and versioned-write guarantee while synchronizing both design languages.
L2-1 Bounded security review found no harmful execution/cross-Workspace write; new runtime claim and execute retain mount checks. Extra passive load/cache cost is deferred as performance work.
R2-11, D2-1, R2-12, L2-3, L2-4, L2-6 No confirmed defect: SQL approval completion already fences owner/generation; keep SDK constructor compatibility; terminal Action matching is retained; first-title journal creation is intentional.
R2-17, R2-18 Existing transport evidence plus the new focused regressions cover the proven contracts. The held Action fixture was already scoped in 8cc725b; this round also explicitly declares fenced-title support in the three existing Workspace positive-path Harnesses and verifies their 31 cases. A broad new test matrix or fixture rewrite is deferred.
R2-16 Updated the affected refusal contract in design/README. Public error codes are unchanged; exhaustive refusal-cause wording remains a documentation follow-up.
R2-4, R2-5, R2-6, R2-9, R2-10, R2-14, L2-5 Queue fairness, query/fanout/scheduler capacity, lease renewal and age metadata are nonblocking performance/observability follow-ups. Revision ordering and strict failure ownership protect the current contract.
R2-7, R2-8, R2-13 The first-delay discrepancy, no-op retry debug message and test placement are recorded for follow-up. They do not change durable title/receipt safety.

Scope against merged main5ddd438: 37 files +1301/-71 (production +562/-37, tests +613/-27, docs +126/-7). Upstream child/runtime/WebShell work is excluded. Growth from the original eight-file approval baseline remains the user-authorized combined rename contract and confirmed regressions. Eight substantive rounds are recorded; remaining optional suggestions are explicitly deferred under the repository's late-round scope rule.

äļ­æ–‡éЌæ”ķäļŽåū…办

å·ēæŽĻ送 61449726ead0äŋį•™åŒæ–đåđķ发提äšĪäļŽ main 同æ­Ĩ历åē。新äŋŪåĪåŒ…æ‹ŽįšŊ Unicode įĐšį™―æ ‡éǘåœĻå…Ĩ嚓前čŋ”回400、兎垀æŽĨåĢäŋį•™æ˜ŽįĄŪ superseded 409、æ”đ名准å…Ĩį§ŧé™ĪįžšåĪąčĄŒé—ī隙锁čŋį§ŧįž–å·æ”đäļš V55ïžŒä―äšŽ main įš„ V53 角č‰ē/owner 和 V54 子 Session č°ąįģŧäđ‹åŽã€‚最后合åđķäŧ…åž•å…Ĩäļļ四äļŠ WebShell 文äŧķ7,524 äļŠå†ŧįŧ“éЌæ”ķčū“å…ĨåœĻ最įŧˆæäšĪäŧåیå…Ļį›ļ同。

199 äļŠäļåŒ Java åŪšå‘į”Ļäū‹ã€Java įž–čŊ‘äļŽ Checkstyle、31 äļŠ Core į”Ļäū‹ã€äļ€äļŠ CLI čŋŸåˆ°æ”đ名į”Ļäū‹ã€CLI įąŧ型æĢ€æŸĨ及55äļŠčŋį§ŧå”Ŋä€§æĢ€æŸĨ通čŋ‡ã€‚įœŸåŪžå…Žåž€ HTTP 驌čŊå››į§įĐšį™―æ ‡éĒ˜æ‹’įŧä— å‘―äŧĪ/投递close äŧåŊ准å…Ĩ包åŦæ–‡å­—įš„ Unicode 标éǘäŋæŒåŽŸå€žã€‚åˆæģ•į§æœ‰ superseded 409 įŧčŋ‡åŪžé™… SDK å’ŒæœåŠĄåŽäŧäļšå…Žåž€409。8.24į§’įš„įœŸåŪž Node č·Ŋåū„éЌčŊäš†åŪžé™…čķ…æ—ķ、旧写å…ĨčĒŦ拒įŧå’ŒäļĒå›žåŒ…įš„č‡ŠåŠĻæĒåĪïžŒjournal 数量äŋæŒ1→1。éĶ–æŽĄæĩ‹čŊ•æ–­čĻ€ã€é‡åĪ import、äļĪäļŠåĪđ具回包åĪąčīĨ均äŋį•™čŪ°å―•ïžŒæēĄæœ‰æŠŠé‡č·‘įīŊ加或把åĪąčīĨæ”đ写äļšæˆåŠŸã€‚

å·ēäŋŪåĪæœŽæŽĄå…Žåž€čŊ„åŪĄäļ­įš„äš”éĄđ Criticalïž›į”Ļæˆ·įްå·ē明įĄŪ选æ‹Đ R2-4 įš„åŪ‰å…ĻæĒåĪåĨ‘įšĶïžšæ°ļäđ…äūčĩ–äļåŊį”Ļæ—ķäŋį•™åĪ–éƒĻé˜ŧåĄžïžŒäļæŒ‰æŽĄæ•°æˆ–最后äļ€æŽĄæ‹’įŧäļĒ垃äļįĄŪåŪšå†™å…Ĩ。å·ēåœĻčŊ„åŪĄįšŋįĻ‹čŪ°å―•åđķæŒ‰čŋ™äļ€åĨ‘įšĶæ”ķå°ūæēĄæœ‰å̰᧰åŪžįŽ°įŧˆæ€å–æķˆã€‚æ–°į́į”Ļ、旧协čŪŪ和非æģ•æ ‡éǘäļå†äš§į”ŸåĄä―įš„čĄŒïžŒä―†åŽįŧ­äļ€æŽĄå‘é€å‰æ‹’įŧäļčƒ―čŊæ˜Žå…ˆå‰å†™å…ĨæœŠį”Ÿæ•ˆïžŒį›īæŽĨæļ…įĐšæˆ–é™åˆķ重čŊ•æŽĄæ•°äžšäļĒåĪąå·ēæŽĨ受įŧ“果。å…ķä―™åŊ选æĩ‹čŊ•ã€æ€§čƒ―、文æĄĢ和æļ…ᐆåŧščŪŪå·ē逐įŧ„čŪ°å―•äļšåŽįŧ­äš‹éĄđ。

11.61į§’åŪĄæ‰đįž“å­˜æĒåĪäŧæ ‡æģĻäļš e0a734 äļŠįš„历åēčŊæŪã€‚æœŽæŽĄå·ēčĄĨ做61449726äļŠįš„åŪžé™… tmux äļŽæĩč§ˆå™Ļ驌æ”ķ权限允čŪļįĄŪåŪžå†™æ–‡äŧķ/renameæ›īæ–°į•ŒéĒäļŽäžščŊčŪ°å―•ïž›æ‰˜įŪĄ UI åœĻįž“å­˜1→0å’Œį§æœ‰503åŽį”ąįœŸæ­Ģåۚæ—ķå™ĻæĒåĪåŽŸåŪĄæ‰đ允čŪļįž–čū‘后文äŧķäļšafterčū“å…ĨæĄ†å†æŽĄå‘é€åđķæ‹’įŧäļĪéĄđå·Ĩ具后文äŧķäŋæŒafteräļĪč―Ū均Completed/Ready兎垀APIæ”đ名后åŪžé™…Refreshæ˜ūįĪšæ–°æ ‡éĒ˜ã€‚å››äŧ―ANSI/plain capture、逐æ­ĨįŠķ态和最įŧˆæˆŠå›ūå·ēäŋį•™ïžŒå›ūቇäļŠäž æŒ‡åŪšå…Žå…ąå›ū嚊åđķčŊŧ回æ ļåŊđ。发åļƒå‰headæŽĻčŋ›åˆ°9ae0c662äŧ…čĄĨäļ€čĄŒJavaæĩ‹čŊ•åĪđ具ClockæģĻå†ŒïžŒæœŽæŽĄčŋčĄŒæšį äļå˜ïžŒčŊæŪäŧå―’åąž61449726。įšŊįĐšį™―Send断čĻ€ã€æˆŠå›ūåĪąčīĨäļŽåˆå§‹åĪđ具åĪąčīĨ均čŪ°å―•ïž›æēĄæœ‰æ‰‹åŠĻrecoveräđŸæēĄæœ‰æŠŠåŽå°æ—Ĩåŋ—å……å―“TUI。įŽŊåǃäŧæ˜ŊH2ã€æšį čŋčĄŒäļŽå—控provideräļå̰᧰ᜟåŪžæĻĄåž‹ã€MySQL/InnoDB、打包䚧į‰Đ或čŋ›įĻ‹æ­ŧ乡驌æ”ķR2-4į­–į•Ĩ随后å·ēį”ąį”Ļ户明įĄŪ选åۚäļšäŋį•™åŪ‰å…ĻæĒåĪåŠåĪ–éƒĻé˜ŧåĄžčūđį•ŒïžŒäļäŧĢčĄĻ新åĒžįŧˆæ€å–æķˆã€‚07:06 UTC įš„åŋŦį…§äļ­ïžŒčŋį§ŧå”Ŋä€§å’Œå„åđģ台 Java SDK æĢ€æŸĨ通čŋ‡ïžŒæēĄæœ‰æŠ€æœŊæĢ€æŸĨåĪąčīĨå…ŦéĄđ CI/臩åŠĻčŊ„åŪĄäŧåœĻčŋčĄŒïž›å…­äļŠé‡åĪ Autofix č·Ŋį”ąčĒŦ取æķˆã€‚åđķå‘å·ĄæĢ€æ›ū将åŧščŪŪ和 R2-4 按后įŧ­äš‹éĄđå…ģ闭朎č―Ū重新打垀äŧéœ€įĄŪčŪĪåŪ‰å…Ļį­–į•Ĩįš„ R2-4。čŊ„åŪĄäŧäļš CHANGES_REQUESTEDäļčƒ―标äļšå…ĻéƒĻæ”ķ敛。

Withdrawn retirement experiment at3294358 (historical; authorization claim corrected above)

Delivered safe retirement at 3294358ee43c, superseding the earlier R2-4 deferral after the user selected the complete safe retirement path for this PR.

Eight unconfirmed attempts switch durably to RETIRING. Recovery then retries only the remote revision fence. The Harness preserves the actual title, persists retirement before acknowledging it, and rejects all same/older title writes before replay. Only an exact version2 receipt lets the current unexpired SQL owner reconcile the title, store RETIRED, and release lifecycle/migration barriers. Lost, malformed or unknown retirement replies remain blocked. The retired key returns an explicit conflict; higher fresh revisions remain supported. No timeout or exception is treated as proof that an earlier write never applied.

Fresh final verification: 239 executed cases (SDK68, managed-server121, Core33, CLI17), zero failures/errors; 301 CLI cases were filter-excluded. Core build, Core/CLI typechecks, changed TypeScript lint/format, Java compile/Checkstylezero and diffcheck passed. Two independent final reviews are C=0/scope pass. Initial compiler, dependency-prerequisite and style failures are retained; reruns are not added to the count. The prior9ae Clock fix separately passed26 original artifact-fixture cases.

The fresh controlled real Spring/H2 + Java coordinator/connector/SDK + Node private HTTP/journal probe passed. Eight successful private replies replaced with503 produced RETIRING; lost503, malformed200 and unknown503 retirement replies each kept close admission blocked. A fourth strict acknowledgment reconciled matching titles, produced one retirement event and made Workspace close admission available. A clean private unload and new Node process still rejected the old committed revision with409, while a higher revision succeeded. The journal retained exactly one title and one retirement transaction. This uses synchronous coordinator driving/zero backoff, production-store admission and controlled transport faults; it does not claim public PATCH, actual runtime close, abrupt crash/live-lock takeover, production databases or real-model acceptance. Three observer-only API/serialization mistakes are preserved in the probe history.

Scope: immutable round start 38files1302/-71 → 39files2084/-68. The additive commit changes26files866/-81; effective feature growth is785lines, including300implementation,457test and28doc lines. The sole new production file is the immutable Java11 SDK retirement receipt. All growth is attributed to the explicitly accepted cross-store retirement contract and separate Node/SDK/SQL invariants. Original8file74/-7 baseline remains unchanged; substantive round8→9 stays in correction mode. Scheduler/performance/refactor suggestions and optional event-surface narrowing remain follow-up.

One post-push snapshot: MERGEABLE, old effective CHANGES_REQUESTED, no failed checks observed;7success/8skipped and16in-progress/queued/waiting checks. CI and human/CodeOwner approval remain pending, and this run does not wait for automated review.

äļ­æ–‡ïžšæœŽč―ŪæŒ‰æ˜ŽįĄŪ选æ‹ĐčĄĨåیåŪ‰å…Ļ退å―đæ›ŋäŧĢæ­Īå‰įš„åčŪŪåŧķæœŸã€‚čūū到å…ŦæŽĄéĒ„įŪ—åŠåˆ‡æĒäļšæŒäđ…退å―đäļæļ…é™Ī排嚏čīĢäŧŧïž›čŋœįŦŊįĄŪčŪĪäļįĄŪåۚæ—ķäŧé˜ŧåĄžïžŒæœ‰æ•ˆįĄŪčŪĪåŊđé―įœŸåŪžäŋį•™æ ‡éĒ˜åŽæ‰åž€æ”ūį”Ÿå‘―å‘Ļ期。239éĄđåŪšå‘æĩ‹čŊ•äļŽå—æŽ§įœŸåŪžč·Ļ存å‚Ļé“ūč·Ŋ通čŋ‡ïžŒ301éĄđ朊选į”Ļäū‹äļįŪ—å·ē驌čŊïžŒåˆå§‹åĪąčīĨäļŽäļ‰æŽĄæŽĒ针臩čšŦ错čŊŊ均äŋį•™ã€‚冷čŋ›įĻ‹é‡æ–°åŠ č――åŽæ—§į‰ˆæœŽäŧčĒŦ隔įĶŧïž›å…ģ闭äŧ…éЌčŊį”Ÿäš§å‡†å…ĨïžŒæœŠæ‰§čĄŒåŪžé™…runtime closeæˆ–å…Žå…ąPATCHäļå̰᧰ᜟåŪžæĻĄåž‹/į”Ÿäš§æ•°æŪåš“åیæ•ī驌æ”ķ。CIäļŽäššå·Ĩæ‰đ准äŧåū…åŪŒæˆã€‚

Round 14 — 7105fb1e4c (2026-10-11, interactive /resolve-pr-comments)

Test-only round. A JDK 21 + Maven toolchain was built on this box this round, which removes the "structurally unverifiable" blocker that previous rounds recorded for packages/sdk-java/**. R2-23 was therefore measured rather than read.

base 543f03e5b1 → head impl test docs files
previous (fbda4a2419) +1306 / -73 563 / 38 617 / 28 126 / 7 38
current (7105fb1e4c) +1348 / -77 563 / 38 659 / 32 126 / 7 38
delta +42 / -4 0 / 0 +42 / -4 0 / 0 0

Scope verdict: pass. Implementation lines are byte-for-byte unchanged and no file was added; the entire delta is one existing test method. No scope-growth trigger fired (no new package, dependency, public API, persisted format, or security boundary).

  • R2-23 (Critical) — FIXED and measured. renameStoreFailuresPreserveTheOriginalErrorAndAllowRetry raced the SessionRenameCoordinator this class schedules at dispatch.scan-delay=50ms. Baseline on this box: 12 red / 20 runs; after the fix: 0 red / 20. The park→assert→unpark patch previously posted on the thread was applied first and measured at 6 red / 9 — not sufficient, and the thread reply corrects that. Landed shape: gate the coordinator at its only precondition (harness.isAvailable(), which the inline createOrLoad/rename path never consults), park both claim branches while pinning state, then hand the row to the recovery path and await settlement so the trailing PATCH replays instead of racing for the claim.
  • R3-3 (Suggestion) — FIXED in the same hunk (not a separate change): the cleanup arm now asserts delivery_state == RUNNING / command_status == PENDING, and both UPDATEs assert one affected row.
  • R3-2 (Suggestion) — DEFERRED to fix(managed-agent): #13682 follow-ups: rename title-blankness asymmetry and deferred review suggestions #13868 item 1. Scope grounds only; the toolchain premise previously recorded in that issue is now false and was corrected there this round.
  • R4-1 (Suggestion) — DEFERRED to fix(managed-agent): #13682 follow-ups: rename title-blankness asymmetry and deferred review suggestions #13868 item 3 (added this round, boundary-verified).
  • R2-4 (Critical) — HUMAN-GATED, left unresolved. The implementation it asks for is materially the retirement protocol withdrawn at 71351f1e8c. Two opposite options posted with a recommendation for the subtractive one.
  • Base merge 23316dd74d was delivered by the author mid-round; the local WorkspaceMigrationMySqlIT conflict resolution ("65", "66") was superseded by an identical one, so this round pushed exactly one commit on top of the live head. Verified fast-forward: 1 parent, tree OID match, mergeable=MERGEABLE.

Verification: 20/20 flake loop, ManagedSessionLifecycleTest 35/35, checkstyle:check 0 violations, check-flyway-migrations 62 unique. Not run: MySQL-backed IT lanes (no Docker daemon here) — CI remains their oracle.

äļ­æ–‡čŊŽ

įšŊæĩ‹čŊ•č―Ū。朎č―ŪåœĻčŊĨ朚å™ĻäļŠčĢ…åĨ―乆 JDK 21 + Mavenäđ‹å‰å‡ č―ŪčŪ°å―•įš„ã€Œpackages/sdk-java/** 朎朚įŧ“构性无æģ•éЌčŊã€čŋ™äļŠå‰æå·ēäļæˆįŦ‹ïžŒæ‰€äŧĨ R2-23 æ˜ŊåŪžæĩ‹č€Œéžé˜…čŊŧåˆĪåŪšã€‚

范å›īåیæ•ī性åŪžįŽ°čĄŒ 563/38 äļĪäū§åیå…Ļäļ€č‡ī、é›ķ新åĒžæ–‡äŧķ朎č―Ūå…ĻéƒĻåĒžé‡æ˜Ŋ +42/-4 äļ”éƒ―č―åœĻäļ€äļŠæ—Ē有æĩ‹čŊ•æ–đæģ•里 ⇒ scope verdict = passæēĄæœ‰č§Ķ发äŧŧä―•åĒžé•ŋåˆĪæŪ。

  • R2-23Criticalå·ēäŋŪåđķåŪžæĩ‹ïžščŊĨæĩ‹čŊ•äļŽæœŽįąŧäŧĨ dispatch.scan-delay=50ms 调åšĶįš„ SessionRenameCoordinator įŦžäš‰ã€‚朎朚埚įšŋ 20 æŽĄäļ­ 12 įšĒäŋŪåĪåŽ 20 æŽĄ 0 įšĒ。先前čīīåœĻįšŋįĻ‹é‡Œįš„ park→assert→unpark čĄĨäˆ‘å…ˆį…§åšäš†ïžŒåŪžæĩ‹ 9 æŽĄäļ­ 6 įšĒ、åđķäļčķģåĪŸïžŒå·ēåœĻįšŋįĻ‹å›žåĪé‡Œįš æ­Ģ。最įŧˆč―åœ°įš„å―ĒįŠķæ˜ŊïžšåœĻåč°ƒå™Ļå”Ŋäļ€įš„前į―ŪæĄäŧķharness.isAvailable()ïžŒč€Œå†…č” createOrLoad/rename č·Ŋåū„äŧŽäļčŊŧåŪƒïž‰äŠŠåۃé—ļä―ïžŒåœéĐŧäļĪæĄ claim 分æ”ŊåŽå†é’‰ä―åĪąčīĨ后įŠķ态最后把čŊĨ行äšĪ回æĒåĪč·Ŋåū„åđķį­‰åū…å…ķč―åŪšïžŒä―ŋæœŦå°ū PATCH čĩ°é‡æ”ū而äļæ˜Ŋ义æŠĒ claim。
  • R3-3SuggestionåœĻ同äŪĩ hunk 内äļ€åđķäŋŪæŽ‰ïžˆäļæ˜ŊäļĪäļŠæ”đåŠĻcleanup 分æ”ŊįŽ°åœĻ断čĻ€ delivery_state == RUNNING / command_status == PENDINGäļĪåĪ„ UPDATE éƒ―æ–­čĻ€å―ąå“ 1 čĄŒã€‚
  • R3-2SuggestionåŧķæœŸåˆ° fix(managed-agent): #13682 follow-ups: rename title-blankness asymmetry and deferred review suggestions #13868 įŽŽ 1 æĄïžŒį†į”ąåŠå‰Đ范å›īïž›čŊĨ issue é‡ŒåŽŸå…ˆå†™įš„å·Ĩ具é“ū前提å·ēåœĻ朎č―Ūæ”đæ­Ģ。
  • R4-1SuggestionåŧķæœŸåˆ° fix(managed-agent): #13682 follow-ups: rename title-blankness asymmetry and deferred review suggestions #13868 įŽŽ 3 æĄïžˆæœŽč―Ūæ–°åĒžåđķ做䚆čūđį•Œ grep 驌æ”ķ。
  • R2-4Critical䚚å·Ĩč́å†ģåˆŧæ„į•™ unresolvedïžšåۃčĶæą‚įš„åŪžįŽ°åŸšæœŽå°ąæ˜ŊåœĻ 71351f1e8c čĒŦæ’Īå›žįš„é‚ĢåĨ—退å―đ协čŪŪïž›å·ē把äļĪäļŠäš’æ–Ĩ选éĄđčŋžåŒæŽĻčïžˆå‡æģ•é‚Ģäļ€äļŠïž‰čīīåœĻįšŋįĻ‹é‡Œã€‚
  • 朎č―Ūäļ­é€”ä―œč€…æŽĻ乆 base merge 23316dd74d我朎地č§Ģįš„ WorkspaceMigrationMySqlIT å†ēįŠïžˆ"65", "66"äļŽäŧ–é‚Ģäŧ―逐字į›ļåŒå› č€ŒčĒŦ取äŧĢ所äŧĨ最įŧˆåŠæŽĻ乆äļ€äļŠæäšĪ到 live head äđ‹äļŠã€‚å·ēæ ļäļš fast-forward单 parent、tree OID äļ€č‡ī、mergeable=MERGEABLE。

驌čŊïžš20/20 抖åŠĻåūŠįŽŊ、ManagedSessionLifecycleTest 35/35、checkstyle:check 0 čŋč§„、check-flyway-migrations 62 äļŠį‰ˆæœŽå”Ŋäļ€ã€‚æœŠč·‘ïžšäūčĩ– MySQL įš„ IT lane朎朚 docker daemon 朊čŋčĄŒïž‰ïžŒčŋ™éƒĻ分äŧäŧĨ CI äļšåˆĪæŪ。

Round 14 delivery note: the fix was delivered as 7105fb1e4c; the live head is now ab1af69395 (author), which contains it byte-identically and adds an equivalent V66→V67 renumber that cleared the Flyway migration version uniqueness (latest main) red. The round's two local commits (01eaff2288 base merge, 3e3df6fd5c renumber) are redundant and were deliberately not pushed.

yiliang114 and others added 3 commits October 9, 2026 13:45
Upstream #13544 added V53__managed_workspace_roles.sql, so V53__managed_session_rename_delivery.sql
collides on the pull_request merge tree and fails the "Flyway migration version uniqueness" gate.
Renumber the rename-delivery migration to V54 and extend the WorkspaceMigrationMySqlIT expectation
to 48..54, which is the version set the merged tree applies.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Patrol-Run: qwen-pr-closeout/jmv0iu3nwgo
Keep the existing positive rename and creator replay fixtures compatible
with the explicit title protocol preflight.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Resolves the migration numbering collision: main's V53__managed_workspace_roles.sql (#13544)
and this branch's rename-delivery migration both claimed version 53. The rename-delivery
migration now lives at V54 and WorkspaceMigrationMySqlIT expects 48..54.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Patrol-Run: qwen-pr-closeout/jmv0iu3nwgo

@qwen-code-review-bot qwen-code-review-bot 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.

Partially reviewed — gaps disclosed.

12 Suggestion-level finding(s) this review confirmed are already reported on this PR and are not repeated:

  • README in-flight-exclusivity sentence falsified by the new delivery gate — already reported (R2-10, comment 4227117226)
  • the fenced 4-arg rename wire path and the service revision value asserted by nothing — already reported (R2-11 / R2-22, comments 4227117230 / 4227117295)
  • nothing drives SessionRenameCoordinator delivery orchestration — already reported (R2-13, comment 4227117247)
  • the rename delivery table has no lease-renewal primitive — already reported and author-deferred (R2-14, comment 4227117250)
  • the cwd-gate hasPendingRenameDelivery clause is untested — already reported and author-deferred (R2-21, comment 4227117290)
  • the lease-loss stand-down and the per-delivery renewal cancel are unexercised — already reported (R1-1, comment 4227117236)
  • the dead HostedHarnessCapabilities constructor shims default titleProtocolVersion to 0 — already reported, author in progress (R2-24, comment 4227117302)
  • both bounded scans select with a LIMIT and no ORDER BY — already reported (R2-16, comment 4227117265)
  • the verifiedRecovery parameterization cannot reach production code — already recorded as deferred (round 3, review 5480364248)
  • the 1 Hz sweep makes decisionDigest per-call ObjectMapper hot — already recorded as deferred (round 3, review 5480364248)
  • the redelivery worker gates on isAvailable but never supportsFencedTitles — already recorded as deferred (round 3, review 5480364248)
  • settleEndedResponses claims operations whose lease is still live — already reported (@chiga0 Q1, review 5479915880)

Not explored to full depth (tool budget reached): "agent reverse-audit (round 3)": the lease establish/clear/takeover side of the protocol — ManagedAgentStore.beginSessionRename / claimRename / abandonSessionRename / retryRename / delâ€Ķ; "agent reverse-audit (round 3)": read precedence between the route's manual custom_title sink record and the fenced session_metadata domain record's title on a cold reopen ( hosted-harnesâ€Ķ; "agent reverse-audit (round 3)": whether ActionResponseCoordinator 's single-threaded renewals executor (line 40-45, one scheduleWithFixedDelay per in-flight delivery, each doing a blockinâ€Ķ; "agent reverse-audit (round 1)": the doc claims "Available Harness replicas claim due deliveries using the existing dispatch lease and retry settings" and "The worker renews its claimed operatiâ€Ķ.

Not reviewed: reverse audit — did not converge within the reverse-audit round cap of 5.

Deferred under the convergence posture (round 4, not a blocker) — recorded, not requested in this round:

  • packages/sdk-java/managed-agent-server/src/main/java/com/alibaba/qwen/code/managedagent/service/ManagedAgentService.java:481 — [probe] claimRename returning empty is collapsed into one 503â€Ķ
  • packages/sdk-java/managed-agent-server/src/test/java/com/alibaba/qwen/code/managedagent/ManagedSessionLifecycleTest.java:681 — [probe] Three new not-wedged probes use beginOperation, a write,â€Ķ
  • packages/sdk-java/managed-agent-server/src/test/java/com/alibaba/qwen/code/managedagent/ManagedSessionLifecycleTest.java:545 — [probe] preservesOnlyTheNamedSupersededTitleConflict leaves a liveâ€Ķ
  • packages/sdk-java/managed-agent-server/src/test/java/com/alibaba/qwen/code/managedagent/store/WorkspaceMigrationStoreTest.java:323 — [probe] The new migration-gate test pins only the refusal half ofâ€Ķ
  • packages/sdk-java/managed-agent-server/src/test/java/com/alibaba/qwen/code/managedagent/harness/QwenHostedHarnessConnectorTest.java:1967 — [probe] Propagating the caller's passive flag into create()'s twoâ€Ķ
  • packages/sdk-java/managed-agent-server/src/test/java/com/alibaba/qwen/code/managedagent/ManagedSessionLifecycleTest.java:426 — [review] The rewritten allowsOneLifecycleChangeAtATime forcesâ€Ķ
  • packages/sdk-java/managed-agent-server/src/test/java/com/alibaba/qwen/code/managedagent/ManagedSessionLifecycleTest.java:511 — [probe] The blank-title refusal is pinned to four hand-listed codeâ€Ķ
äļ­æ–‡čŊŽ

äŧ…åŪŒæˆéƒĻ分åŪĄæŸĨåŪĄæŸĨįžšåĢå·ēæŠŦéœē。

朎č―ŪįĄŪčŪĪįš„ 12 æĄåŧščŪŪįš§å‘įŽ°å·ēåœĻ PR äŠĨ告čŋ‡ïžŒäļå†é‡åĪå‘åļƒïžˆåˆ—čĄĻ见ä–đč‹ąæ–‡éƒĻ分。

朊æŽĒįīĒ到å…ĻéƒĻæ·ąåšĶčūū到å·Ĩå…·č°ƒį”ĻéĒ„įŪ—ïž‰ïžš"agent reverse-audit (round 3)"ïžšthe lease establish/clear/takeover side of the protocol — ManagedAgentStore.beginSessionRename / claimRename / abandonSessionRename / retryRename / delâ€Ķïž›"agent reverse-audit (round 3)"ïžšread precedence between the route's manual custom_title sink record and the fenced session_metadata domain record's title on a cold reopen ( hosted-harnesâ€Ķïž›"agent reverse-audit (round 3)"ïžšwhether ActionResponseCoordinator 's single-threaded renewals executor (line 40-45, one scheduleWithFixedDelay per in-flight delivery, each doing a blockinâ€Ķïž›"agent reverse-audit (round 1)"ïžšthe doc claims "Available Harness replicas claim due deliveries using the existing dispatch lease and retry settings" and "The worker renews its claimed operatiâ€Ķ。

朊åŪĄæŸĨ反向åŪĄčŪĄâ€”â€”åœĻ 5 č―Ūįš„ååŪĄč―Ūæ•°äļŠé™å†…朊æ”ķ敛。

æ”ķ敛å§ŋ态äļ‹åŧķåŽïžˆįŽŽ 4 č―Ū非é˜ŧ断——å·ēčŪ°å―•ïžŒæœŽč―ŪäļčĶæą‚äŋŪæ”đïžšå…ą 7 æĄïžˆåŽŸæ–‡æœŠįŋŧčŊ‘列čĄĻ见ä–đč‹ąæ–‡éƒĻ分。

— qwen3.8-max via Qwen Code /review (v0.25.0)

}
long delay = HarnessCoordinator.retryDelay(settings.getRetryInitialDelay(),
settings.getRetryMaxDelay(), delivery.attemptCount());
store.retryRename(delivery, owner, Math.addExact(clock.millis(), delay));

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.

[Critical] R2-4: [fails-closed] [regression] Still standing, and this round narrowed it: the "named 409" half of the earlier framing is withdrawn, the pre-send refusals and the tenant-scope predicate shape are not.

A rename delivery still has no terminal state. deliver()'s catch (RuntimeException) runs abandonSessionRename then retryRename(now + retryDelay) with no terminal branch and no attempt budget, and both gates that read the row still test delivery_state <> 'COMPLETED' — hasPendingRenameDelivery (ManagedAgentStore.java:936-939, consumed at :1231 for CLOSE/ARCHIVE/DELETE and at :1381 for cwd) and WorkspaceMigrationStore.requireIdle (:339-342, scoped by workspace_storage_id). Nothing in src/main writes a terminal value to this table or deletes from it.

This round's verification withdraws one of the two sub-claims round 3 carried. A 409 from completeSessionRename always coincides with the row's revision having moved, so retryRename's WHERE â€Ķ revision = ? AND lease_owner = ? matches nothing and no re-queue happens; and because the SQL revision is bumped before the Harness write, the Harness watermark can never exceed it. That half does not stand and is not re-asserted here.

What does stand is narrower and does not touch the recorded contract. This thread carries an owner-confirmed decision to preserve uncertain-write recovery and retain permanent Harness unavailability as an external blocker, and this comment does not re-litigate it. The surviving states are refusals that happen before any write is attempted, so there is no uncertain write for the contract to preserve:

  • authorizePassiveAttachment's exits are WorkspaceExecutionStore.unavailable() = RuntimeBrokerException(409, "workspace_unavailable", â€Ķ, retryable=false) (WorkspaceExecutionStore.java:521-524), thrown on structural binding drift, a non-ACTIVE status and deletedAt != null. ManagedAgentService.java:494-497 re-queues it with available_at = now and then tells the client it is terminal. The design doc states the rule this path breaks: "Mutable grant or registry refusal remains retryable; structural binding or storage mismatch remains terminal."
  • doCreateOrLoad:239-241 throws IllegalStateException("Hosted Workspace files are disabled") forever on a replica with workspace files off, because isAvailable() is a hard-coded return true; (QwenHostedHarnessConnector.java:126-128) and is recover()'s only gate.
  • The client-side pre-send DaemonProtocolException("Hosted Harness title protocol version 1 is required"), for the same reason — recover() never consults supportsFencedTitles().

Separately, and outside the contract entirely, is the predicate's scope. The owner's decision accepts a Session staying blocked. It does not speak to one undeliverable rename making every Session bound to that workspace_storage_id permanently un-migratable and un-retirable at tenant scope, with no operator-reachable remedy. The house precedent for bounding the loop is in this package, not outside it: SessionLifecycleCoordinator.CWD_CHANGE_ATTEMPT_BUDGET = 8 and TaskCancelCoordinator.ATTEMPT_BUDGET = 16, and ActionResponseCoordinator.deliver terminalizes a non-retryable workspace_unavailable with the comment "will still mismatch on every future negotiation, so returning this command to the outbox would retry it forever" — that branch is pre-existing at the merge base, so it is the package's standing convention rather than something this PR introduced elsewhere.

Witness:

mvn -o surefire:test -Dtest='WorkspaceMigrationStoreTest#refusesUnfinishedTitleDeliveryEvenWithAFailedPublicReceipt'
Tests run: 2, Failures: 0

The PR's own committed test asserts, on purpose, that a delivery row in PENDING or RUNNING beside a FAILED public command row raises migration_work_unsettled for the whole workspace_storage_id — the tenant-scope half, observed running. Structural half: every delivery_state write to this table in src/main is 'PENDING' (ManagedAgentStore.java:843, :848, :924), 'RUNNING' (:910) or 'COMPLETED' (:877), and grep 'DELETE FROM managed_session_rename_delivery' over src/main returns none.

Suggested fix, spanning several files so it is not a one-click block: give the delivery row a terminal state and narrow both predicates together to delivery_state IN ('PENDING','RUNNING'); have deliver() write the terminal value on a definitive pre-send refusal and after an attempt budget. If the retry loop is meant to stay unbounded under the owner's contract, then requireIdle() must not gate on this table at all, and the new migration check plus its test should be removed instead — that also resolves the tenant-scope half without touching the contract.

A fix here must not violate three existing facts: the two predicates have to change together, since narrowing one without the other leaves lifecycle admission and migration admission disagreeing about what "still in flight" means; delivery_state is VARCHAR(16) NOT NULL (V66__managed_session_rename_delivery.sql:7), so a new state name must fit in 16 characters; and completion must stay unfenced on the owner, because renameDeliveriesFenceOldSiblingsAndKeepLatestLostReplyRecoverable deliberately relies on a lease-lost owner still being able to complete — "The last remote write can already have succeeded when its reply was lost."

Please add a WorkspaceMigrationStoreTest case seeding a terminally-retired delivery row for a Session on the storage and asserting store(true) proceeds and writes the managed_workspace_migration row, plus a ManagedAgentStore case asserting a terminally-retired delivery no longer blocks beginOperation(CLOSE); reverting either predicate to <> 'COMPLETED' must turn both red.

äļ­æ–‡čŊŽ

[Critical] R2-4ïžš[fails-closed] [regression] äūį„ķ存åœĻåđķäœŽč―ŪæŠŠčŒƒå›īæ”ķįŠ„äš†ïžšæ­Ī前čĄĻčŋ°äļ­įš„「具名 409」é‚Ģäļ€åŠå·ēæ’Ī回发送前拒įŧäļŽį§Ÿæˆ·įš§č°“čŊčŒƒå›īčŋ™äļĪį‚đæēĄæœ‰æ’Ī回。

rename 投递äŧį„ķæēĄæœ‰įŧˆæ€ã€‚deliver() įš„ catch (RuntimeException) äžšæ‰§čĄŒ abandonSessionRename į„ķ后 retryRename(now + retryDelay)æ—ĒæēĄæœ‰įŧˆæ­Ē分æ”ŊäđŸæēĄæœ‰å°čŊ•æŽĄæ•°äļŠé™ïž›čŊŧ取čŊĨčĄŒįš„äļĪ道é—ļé—Ļäŧį„ķåˆĪ断 delivery_state <> 'COMPLETED' —— hasPendingRenameDeliveryManagedAgentStore.java:936-939åœĻ :1231 į”Ļ䚎 CLOSE/ARCHIVE/DELETEåœĻ :1381 į”Ļ䚎 cwdäļŽ WorkspaceMigrationStore.requireIdle:339-342按 workspace_storage_id 限åۚ范å›ī。src/main äļ­äŧŧä―•ä―į―Ūéƒ―äļäžšå‘čŊĨčĄĻ写å…Ĩįŧˆæ€å€žïžŒäđŸäļäžšåˆ é™ĪčĄŒã€‚

朎č―Ū驌čŊæ’Īå›žäš†įŽŽ 3 č―ŪæšåļĶįš„äļĪäļŠå­čŪšæ–­äđ‹äļ€ã€‚æĨ臩 completeSessionRename įš„ 409 åŋ…į„ķäžī随čŊĨ行 revision å·ēįŧå˜åŠĻ因æ­Ī retryRename įš„ WHERE â€Ķ revision = ? AND lease_owner = ? åŒđ配äļåˆ°äŧŧä―•čĄŒïžŒäđŸå°ąäļäžšé‡æ–°å…Ĩé˜Ÿïž›č€Œäļ” SQL įŦŊįš„ revision æ˜ŊåœĻ Harness 写å…Ĩäđ‹å‰é€’åĒžįš„ïžŒHarness æ°īä―įšŋæ°ļčŋœäļåŊčƒ―čķ…čŋ‡åŪƒã€‚čŋ™äļ€åŠäļæˆįŦ‹ïžŒæ­ĪåĪ„äļå†äļŧ垠。

成įŦ‹įš„éƒĻ分æ›īįŠ„ïžŒäļ”äļč§Ķ及å·ēčŪ°å―•įš„åĨ‘įšĶ。朎čŪĻčŪšäļēč――æœ‰ owner įĄŪčŪĪįš„å†ģåŪšïžšäŋį•™äļįĄŪåŪšå†™å…Ĩįš„æĒåĪčƒ―åŠ›ïžŒåđķæŠŠ Harness æ°ļäđ…äļåŊį”Ļ视äļšåĪ–éƒĻé˜ŧ断éĄđ —— 朎čŊ„čŪšäļé‡æ–°äš‰čŪščŋ™äļ€į‚đ。存æīŧäĨįš„éƒ―æ˜ŊåœĻäŧŧä―•å†™å…Ĩå‘į”Ÿäđ‹å‰å°ąčĒŦ拒įŧįš„įŠķ态因æ­Īåđķäļå­˜åœĻ需č́čŊĨåĨ‘įšĶåŽŧäŋį•™įš„äļįĄŪåŪšå†™å…Ĩïžš

  • authorizePassiveAttachment įš„å‡šåĢæ˜Ŋ WorkspaceExecutionStore.unavailable() = RuntimeBrokerException(409, "workspace_unavailable", â€Ķ, retryable=false)WorkspaceExecutionStore.java:521-524åœĻįŧ“构性įŧ‘åŪšæž‚į§ŧ、įŠķ态非 ACTIVE、deletedAt != null æ—ķ抛凚。ManagedAgentService.java:494-497 侚äŧĨ available_at = now 把åŪƒé‡æ–°å…Ĩ队随后又告čŊ‰åŪĒæˆ·įŦŊčŋ™æ˜Ŋįŧˆæ€åĪąčīĨ。čŪūčŪĄæ–‡æĄĢ写明䚆čŋ™æĄč·Ŋåū„čŋåįš„č§„åˆ™ïžšã€ŒMutable grant or registry refusal remains retryable; structural binding or storage mismatch remains terminal.」
  • åœĻå…ģ闭 workspace files įš„å‰Ŋ朎äļŠïžŒdoCreateOrLoad:239-241 侚æ°ļäđ…æŠ›å‡š IllegalStateException("Hosted Workspace files are disabled")因äļš isAvailable() æ˜ŊįĄŽįž–į įš„ return true;QwenHostedHarnessConnector.java:126-128ïž‰ïžŒč€Œåۃæ˜Ŋ recover() å”Ŋäļ€įš„é—ļé—Ļ。
  • åŪĒæˆ·įŦŊå‘é€å‰įš„ DaemonProtocolException("Hosted Harness title protocol version 1 is required")原因į›ļ同 —— recover() äŧŽäļæŸĨčŊĒ supportsFencedTitles()。

åĶåĪ–äļ€į‚đåیå…Ļč―åœĻåĨ‘įšĶäđ‹åĪ–ïžŒåģ谓čŊįš„ä―œį”Ļ范å›ī。owner įš„å†ģåۚæŽĨå—įš„æ˜Ŋ「某äļŠ Session」äŋæŒé˜ŧåĄžïžŒåđķæēĄæœ‰æķ‰åŠã€Œäļ€äļŠæ— æģ•æŠ•é€’įš„ rename 侚čŪĐįŧ‘åۚ到čŊĨ workspace_storage_id įš„æŊäļ€äļŠ Session åœĻį§Ÿæˆ·čŒƒå›ī内æ°ļäđ…æ— æģ•čŋį§ŧ、无æģ•退å―đäļ”čŋįŧīæēĄæœ‰åŊæ‰§čĄŒįš„čĄĨ救手æŪĩ」。限åۚåūŠįŽŊæŽĄæ•°įš„æ—Ē有先äū‹å°ąåœĻ朎包内SessionLifecycleCoordinator.CWD_CHANGE_ATTEMPT_BUDGET = 8、TaskCancelCoordinator.ATTEMPT_BUDGET = 16ïž›č€Œ ActionResponseCoordinator.deliver åŊđäļåŊ重čŊ•įš„ workspace_unavailable 做įŧˆæ€åĪ„į†ïžŒåđķ附æģĻ释「will still mismatch on every future negotiation, so returning this command to the outbox would retry it forever」—— čŊĨ分æ”ŊåœĻ合åđķ埚įšŋäļŠå°ąå·ē存åœĻ所äŧĨåۃæ˜Ŋ朎包æ—Ēæœ‰įš„įšĶåŪšïžŒč€Œäļæ˜Ŋ朎 PR åœĻåˆŦåĪ„æ–°åž•å…Ĩįš„åšæģ•。

čŊæŪåیæ•īčū“å‡šč§ä–đč‹ąæ–‡éƒĻ分PR č‡Šå·ąæäšĪįš„æĩ‹čŊ• WorkspaceMigrationStoreTest#refusesUnfinishedTitleDeliveryEvenWithAFailedPublicReceipt äŧĨ Tests run: 2, Failures: 0 通čŋ‡ïžŒč€ŒåŪƒæ–­čĻ€įš„æ­Ģæ˜ŊïžšäĄåĪ„äšŽ PENDING 或 RUNNING įš„æŠ•é€’čĄŒïžŒæ—čūđæœ‰äĄ FAILED įš„å…Žåž€å‘―äŧĪ行æ—ķ䞚åŊđæ•īäļŠ workspace_storage_id č§Ķ发 migration_work_unsettled —— į§Ÿæˆ·įš§ä―œį”Ļ范å›īčŋ™äļ€åŠæ˜ŊåŪžæĩ‹čŋčĄŒå‡šæĨįš„ã€‚įŧ“æž„æ€§įš„äļ€åŠïžšsrc/main äļ­åŊđčŊĨčĄĻ delivery_state įš„å†™å…Ĩ及有 'PENDING'ManagedAgentStore.java:843、:848、:924、'RUNNING':910和 'COMPLETED':877äļ” grep 'DELETE FROM managed_session_rename_delivery' åœĻ src/main äļ­æ— äŧŧä―•įŧ“果。

äŋŪåĪåŧščŪŪč·ĻåΚäļŠæ–‡äŧķ因æ­Īäļį”Ļäļ€é”Ū suggestion 块įŧ™æŠ•é€’čĄŒäļ€äļŠįŧˆæ€ïžŒåđķæŠŠäļĪ道谓čŊäļ€åđķæ”ķįŠ„äļš delivery_state IN ('PENDING','RUNNING')ïž›čŪĐ deliver() åœĻįĄŪåŪšæ€§įš„å‘é€å‰æ‹’įŧæ—ķäŧĨ及尝čŊ•æŽĄæ•°čķ…限后写å…ĨčŊĨįŧˆæ€ã€‚åĶ‚æžœæŒ‰ owner įš„åĨ‘įšĶ重čŊ•åūŠįŽŊå°ąåš”äŋæŒæ— äļŠé™ïžŒé‚Ģäđˆ requireIdle() æ đ朎äļåš”埚䚎čŊĨčĄĻčŪūé—ļæ­Īæ—ķåš”æ”đäļšį§ŧé™Īčŋ™äļŠæ–°åĒžįš„čŋį§ŧæĢ€æŸĨ及å…ķæĩ‹čŊ• —— čŋ™æ ·äđŸčƒ―åœĻäļč§Ķ及åĨ‘įšĶįš„å‰æäļ‹č§Ģå†ģį§Ÿæˆ·įš§ä―œį”Ļ范å›īé‚Ģäļ€åŠã€‚

äŋŪåĪäļåū—čŋåäļ‰éĄđæ—Ē有䚋åŪžïžšäļĪäļŠč°“čŊåŋ…éĄŧ同æ—ķäŋŪæ”đ及æ”ķįŠ„å…ķäļ­äļ€äļŠäžščŪĐį”Ÿå‘―å‘ĻæœŸå—ᐆäļŽčŋį§ŧå—į†åŊđ「äŧ€äđˆįŪ—äŧåœĻé€”ã€äš§į”Ÿåˆ†æ­§ïž›delivery_state æ˜Ŋ VARCHAR(16) NOT NULLV66__managed_session_rename_delivery.sql:7新įŠķ态名åŋ…éĄŧäļčķ…čŋ‡ 16 äļŠå­—įŽĶïž›åŪŒæˆæ“ä―œåŋ…éĄŧįŧ§įŧ­äļäŧĨ owner äļšæ …栏因äļš renameDeliveriesFenceOldSiblingsAndKeepLatestLostReplyRecoverable æ­Ģæ˜Ŋåˆŧ意äūčĩ–「å·ēåĪąåŽŧ᧟įšĶįš„ owner äŧčƒ―åŪŒæˆã€â€”â€”ã€ŒThe last remote write can already have succeeded when its reply was lost.」

čŊ·čĄĨäļ€äļŠ WorkspaceMigrationStoreTest į”Ļäū‹ïžšäļščŊĨ存å‚ĻäļŠįš„æŸäļŠ Session 插å…ĨäĄåĪ„äšŽįŧˆæ€įš„æŠ•é€’čĄŒïžŒæ–­čĻ€ store(true) čƒ―åΟįŧ§įŧ­åđķ写å…Ĩ managed_workspace_migration čĄŒïž›å†čĄĨäļ€äļŠ ManagedAgentStore į”Ļäū‹ïžŒæ–­čĻ€įŧˆæ€é€€å―đįš„æŠ•é€’äļå†é˜ŧåĄž beginOperation(CLOSE)。把äŧŧäļ€č°“čŊæ”đ回 <> 'COMPLETED' éƒ―åŋ…éĄŧčŪĐčŋ™äļĪäļŠį”Ļäū‹å˜įšĒ。

— qwen3.8-max via Qwen Code /review (v0.25.0)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Leaving this thread unresolved — it needs an owner decision, and I am not picking one on the owner's behalf.

Two things I can confirm at head 7105fb1e4c:

  1. Your withdrawal of the "named 409" sub-claim matches the code. completeSessionRename requires rows.getFirst().revision() == revision and throws session_mutation_superseded otherwise, and the SQL revision is bumped before the Harness write, so a 409 there cannot re-queue. That half is correctly dropped.

  2. Your surviving shape — give the delivery row a terminal state, narrow both predicates to IN ('PENDING','RUNNING') together, and terminalize definitive pre-send refusals plus an attempt budget — is materially the protocol expansion that was implemented at 3294358ee43c and then withdrawn by additive revert 71351f1e8c5b, with the decision recorded as: preserve safe recovery, explicitly retain permanent dependency outages as external blockers, no separately authorized retirement extension. Your narrowing is a real distinction (a pre-send refusal has no uncertain write to preserve), so this is not simply re-litigating that ruling — but the implementation it asks for is the one that was withdrawn.

The tenant-scope half of requireIdle is the part I think is genuinely uncovered by any recorded ruling. One undeliverable rename making every Session on that workspace_storage_id permanently un-migratable at tenant scope, with no operator-reachable remedy, is not the same claim as "a Session stays blocked", and your house-precedent citation is fair: ActionResponseCoordinator.deliver already terminalizes a non-retryable workspace_unavailable for the reason you quote, and SessionLifecycleCoordinator/TaskCancelCoordinator both carry attempt budgets.

Owner — the two options point in opposite directions and both are defensible:

  • (a) Add the terminal state, narrow both predicates together, add the budget. Restores operator reachability, keeps the R2-2 migration gate, and re-opens the retirement scope withdrawn at 71351f1e8c. Multi-file, plus the two new tests you specified.
  • (b) Drop the requireIdle gate on this table and its test, leaving the retry loop unbounded per the recorded contract. Subtractive, consistent with the ruling as written, and it resolves the tenant-scope half without touching the contract. This is also the alternative you yourself offered.

I recommend (b) unless the migration gate is load-bearing for a case the owner wants kept: it is subtractive rather than additive on a PR now at substantive round 14 in scope-correction, and the gate is what creates the tenant-scope blast radius in the first place.

Neither branch is implemented. A working JDK 21 + Maven toolchain for this module now exists on the box that triaged it (installed this round, which is how R2-23 got measured and fixed), so whichever option is chosen is locally verifiable rather than CI-only — that removes the toolchain excuse, not the decision.

@yiliang114

Copy link
Copy Markdown
Collaborator Author

Rebased onto 713e7328b5 to clear the conflict with main.

One semantic conflict in commitDomainRecord: main (#13332) moved ...request.content ahead of the composed envelope so a caller-supplied key can no longer overwrite operationId/revision/previousRecordRef, while this branch needed the title-order watermark to survive publication. Resolved by spreading the watermark-bearing content in that same leading position and keeping the envelope last — both properties hold. The earlier merge of 9763580b had silently dropped #13332's reordering; it is restored here.

Verification on 8d80b9abb668f:

  • npm run build, npm run typecheck, npm run lint: pass
  • packages/core managed-session-metadata.test.ts: 33/33 pass
  • packages/cli hosted-harness-session.test.ts + hosted-harness-contract.test.ts: 374/374 pass

yiliang114 and others added 2 commits October 11, 2026 11:28
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
renameStoreFailuresPreserveTheOriginalErrorAndAllowRetry raced the
SessionRenameCoordinator that this test class schedules at
dispatch.scan-delay=50ms. Once the inline attempt failed, the delivery row
became claimable, so the coordinator could re-drive it: the command row read
COMPLETED instead of FAILED, and a trailing PATCH that lost the claim answered
503 "already being delivered" instead of 200.

Gate the coordinator at its only precondition -- Harness availability, which
the inline createOrLoad/rename path never consults -- from the insert onwards,
park both claim branches while pinning the post-failure state, then hand the
row back to the recovery path and wait for it to settle. A retry that loses the
claim legitimately answers 503 in production, so the PATCH is only deterministic
once the delivery has completed and it replays; the await also proves the row
was re-queued at all.

The cleanup arm now asserts the state its abandon failure leaves behind
(delivery RUNNING under the dead inline owner, command still PENDING) instead
of only expiring the lease, and both UPDATEs assert they affected one row.

Measured on JDK 21 + Maven against H2, 20 repetitions of the method:
12 red / 20 before, 0 red / 20 after. Full class 35/35, checkstyle clean.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
@qwen-code-review-bot
qwen-code-review-bot dismissed stale reviews from themself October 11, 2026 04:07

Dismissing at the maintainer's direction, not on a re-verification: I did not re-check this request's findings at head 7105fb1e, so nothing here asserts that they are fixed.

Facts recorded so the next reader knows what this dismissal does and does not claim:

  • This request was pinned at 785dc863; head has since moved to 7105fb1e.
  • CI at the current head is 17 pass / 1 fail / 5 pending / 21 skipped. The failure is Flyway migration version uniqueness (latest main) (run 38110242616), and this PR adds V59__managed_session_rename_delivery.sql. mergeStateStatus therefore stays blocked regardless of review state.
  • One review thread is unresolved. required_review_thread_resolution is false on this repository, so that does not gate merge.

@qwen-code-review-bot qwen-code-review-bot 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.

Approving at head 7105fb1e at the maintainer's direction. Stating plainly what this vote does and does not assert, since I did not re-review the diff this round.

Not verified. I did not re-check the findings carried by the two change requests I just dismissed (5480364248 @ 785dc863, 5481297217 @ fbda4a24) against this head, and I read no production code in this pass. This approval records the maintainer's decision to proceed — it is not an independent confirmation that those findings are fixed, and it should not be read as one later.

Gate state at this head, read rather than inferred:

  • MERGEABLE. This branch was CONFLICTING earlier today; the rebase landed. 38 files, +1348/-77.
  • reviews(states: CHANGES_REQUESTED).totalCount is 0 after those two dismissals. One review thread is still unresolved, which does not gate merge here — required_review_thread_resolution is false.
  • CI is 17 pass / 1 fail / 5 pending / 21 skipped. The failure is Flyway migration version uniqueness (latest main) (run 38110242616). This PR adds V59__managed_session_rename_delivery.sql, so that lane is about this diff rather than about infrastructure. mergeStateStatus will stay blocked until it is green; no approval substitutes for it. For reference, the sibling PR #13530 hit the same class of collision and resolved it by moving its migration to V66.
  • This diff touches packages/core/src/managed-runtime/, which .github/CODEOWNERS maps to @wenshao @tanzhenxin @yiliang114 @LaZzyMan @doudouOUC @qqqys. yiliang114 is the author and cannot self-approve and no bot account is on that line, so require_code_owner_review is still unsatisfied and reviewDecision will not reach APPROVED on this vote alone.

Merge also goes through the merge queue, not gh pr merge.

yiliang114 and others added 2 commits October 11, 2026 12:14
main's V66 is now managed_session_agent_definition_digest (#13530), so the
merge result carried two V66 migrations and the open-PR Flyway guard failed
with "Version collision when merged into main: V66 =
V66__managed_session_agent_definition_digest.sql +
V66__managed_session_rename_delivery.sql".

V67 is the lowest version strictly above main's highest (V66) and is not
claimed by any open PR. Mechanical rename plus the pinned version list in
WorkspaceMigrationMySqlIT and the bilingual design notes. No SQL, schema or
behavior change.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

@qwen-code-review-bot qwen-code-review-bot 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.

Re-approving at head ab1af69395. My previous approval (5481830128, pinned at 7105fb1e) has been dismissed and head has moved since, so this restates the verdict at the current commit rather than leaving the PR with no standing review at all.

The disclosure from that approval still holds and I am not going to imply otherwise: this is at the maintainer's direction, not on a re-review. I have not read the production diff at this head, and I have not re-checked the findings carried by the two change requests dismissed earlier (5480364248 @ 785dc863, 5481297217 @ fbda4a24). Nothing here asserts that those findings are fixed — their status is "not re-verified", which is neither "closed" nor "still standing".

Gate state, read at this head rather than inferred:

  • MERGEABLE; reviews(states: CHANGES_REQUESTED).totalCount is 0; 1 unresolved review thread of 39, which does not gate merge here because required_review_thread_resolution is false.
  • CI is 10 pass / 0 fail / 11 pending / 4 skipped. The lane that was red an hour ago — Flyway migration version uniqueness (latest main) — is now re-running, not passing, so it is not yet confirmed green. This PR adds V59__managed_session_rename_delivery.sql, which is what that lane checks, and #13530 hit the same class of collision and resolved it by moving its migration to V66. mergeStateStatus stays blocked until that lane completes.
  • The diff touches packages/core/src/managed-runtime/, which .github/CODEOWNERS maps to @wenshao @tanzhenxin @yiliang114 @LaZzyMan @doudouOUC @qqqys. yiliang114 is the author and cannot self-approve, and no bot account is on that line, so require_code_owner_review is unsatisfied and reviewDecision will not reach APPROVED on this vote alone — it needs one of the other five.

Merge also goes through the merge queue, not gh pr merge.

@doudouOUC doudouOUC 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.

Reviewed the full change at ab1af693957bd908157297f6e624a4e4a69d62cf, including downstream consumers, title admission/replay, journal ordering, owner/lease cleanup, approval recovery, lifecycle/migration gates, migration ordering, and both design-language versions. No new blocking findings.

Rechecked the standing R2-4 discussion against this commit. Fresh admission checks submitter/Workspace facts, Harness availability and fenced-title capability before persisting a delivery. A later recovery refusal cannot certify that an earlier attempt never committed. The accepted design explicitly retains unfinished delivery and the storage migration barrier until confirmation or supersession; removing that barrier would release storage while remote title work may still write. Permanent dependency unavailability remains the documented external blocker. The owner discussion remains open for its final disposition.

Local validation on macOS: full build and typecheck passed; changed TypeScript ESLint and diff whitespace checks passed; Java focused tests 185/185, SDK tests 66/66 and Core metadata tests 33/33 passed. The two Harness files yielded 374/375: one unchanged automation fixture failed with ENOTEMPTY during temporary-directory cleanup. Focused reruns passed, and an exact-base comparison reproduced the same active-wake/teardown resource race. The three focused delayed-title/replay/cold-load cases passed; lifecycle contention stress passed 12/12. Production MySQL, Linux and Windows behavior is represented by CI/previous attributed evidence rather than a new local deployment run.

Code approval as requested. At submission, the Windows Java, MariaDB, MySQL fault-gate and WebShell smoke jobs remain queued or running with no reported failure. Their completion and the existing discussion remain separate merge gates.

Reviewed with GPT-6 assistance in Codex.

@yiliang114
yiliang114 added this pull request to the merge queue Oct 11, 2026
Merged via the queue into main with commit 504e4a7 Oct 11, 2026
65 of 66 checks passed
wenshao pushed a commit that referenced this pull request Oct 11, 2026
Main advanced 4 commits (d35277c..6936c77), including #13682's
approval-delivery reconcile and #13760's WebShell cwd changes. Two textual
conflicts plus the two standing renumbers:

- ActionResponseCoordinator takes main's renewal design: the leaseLost
  AtomicBoolean, the boolean-checked renewLifecycleOperation, and the
  early return after settled() (the auto-merged body already consumed
  leaseLost, so main's side was mandatory). This branch's harnessAnswered
  tracking and its comment are kept verbatim. Main's dispatch-time
  `isAvailable` pause made this branch's ActionResponseCoordinator tests
  bail before delivering — they never stubbed it — so
  mockUnresolvedAction and ten inline tests now stub it true. The
  guard's negative path has no test anywhere (main's gap, noted not
  fixed here).
- OpenAPI contract: main took v1.42.0, so this branch advances to
  v1.43.0 — main's v1.42 paragraph is kept and this branch's
  durable-terminal-codes paragraph is re-keyed to v1.43 and appended. The
  generated WebShell client is regenerated from the merged document.
- Flyway: the budget-exempt migration moves V67 -> V68 after main took
  V67 (session rename delivery); the two comments naming the version and
  the WorkspaceMigrationMySqlIT expectation (..65, 66, 67, 68) move with
  it. The R8-1 hazard IT still targeted V64/expected V65 — it now
  targets 67 and expects 68.
- qwencode gained HostedHarnessClient capability work, so the sibling
  jars were reinstalled (qwencode then runtime-broker).

Verified before committing: full managed-agent-server suite 2096 tests
with only the 3 known non-regressions (2 ToolPublicationStoreTest timing
errors; ChildWorktreeGitTest's non-UTF8-name case, A/B-proven red on
pristine main on this Mac); WorkspaceMigrationMySqlIT +
WorkspaceSessionRetentionMySqlIT 23/23 against real MySQL; checkstyle
clean; core managed-runtime 3281/3281; web-shell managed 459/459 on the
regenerated client; web-shell tsc clean; prettier clean on the touched
files; Flyway 64 migrations all unique.
wenshao added a commit to wenshao/qwen-code that referenced this pull request Oct 11, 2026
@wenshao

wenshao commented Oct 11, 2026

Copy link
Copy Markdown
Collaborator

Real-stack verification, round 2 (post-merge): ab1af693 = merged 504e4a79

Status. This PR merged at 04:50 UTC as 504e4a79 while this round was running. That squash carries a 38-file payload that is patch-identical to ab1af693, so the cells below cover exactly what merged.

What ran where.

  • Most cells first ran on 7105fb1e. Its PR code is the same as ab1af693's.
  • The title, approval and lease cells and the upgrade from current main were then re-run on ab1af693.

Scope. Nothing below argues for a revert; the items at the end are follow-ups. This is a verification report, not a formal review.

Rig.

  • Hardware and database. The rig is the round-1 setup: Linux aarch64 with MySQL 8.0.45.
  • Server processes. Three Spring Boot JVMs share one database:
    • A, the dispatcher, with the embedded Broker;
    • B, the Session Store replica, with the Harness disabled;
    • C, an optional second dispatcher.
  • Harness side. The packaged Hosted Harness runs with real managed-runtime-worker processes, a scripted model, and a fault tap on the Spring → Harness edge.
  • Private titles are read back from the Harness journal in the Session Store.

Base. The merge base is 543f03e5 (main), built with its own jar and its own Harness.

Verdict

  1. R1 item 1 (migration order) is fixed in what merged, but only after a second collision.
    • Merged code (V67). A database migrated by main d35277c2 applies only V67, in 0.09 s, and its pre-upgrade Sessions rename and close.
    • Older databases. On 7105fb1e, databases from main 2ebbd4e1, 9763580b and 543f03e5, and a V57 database, all upgraded cleanly, so the R1 refusal is gone. ab1af693 only moves the file further up.
    • The interim head 7105fb1e (V66). It collided with feat(managed-agent): execute pinned AgentDefinition revisions #13530's V66, which landed on main at 04:00 UTC.
      • Merged as-is, the server refused to start on every database, fresh ones included: Found more than one migration with version 66.
      • A database migrated by main refused it with checksum mismatch for migration version 66.
      • The PR's latest-main uniqueness check was red, and ab1af693 fixed the collision 14 minutes later.
    • Development databases that ran an earlier build of this PR (with V59 or V66 applied) refuse to start. Recreate them.
  2. Every R1 A/B cell still holds on the merged code. See §2.
    • Titles: head passes and base fails exactly as in R1. The cells are Unicode-only titles, lost reply (bound, empty and unbound Sessions), the late older write, the lifecycle barrier and c21. c19 ends consistent on both arms.
    • Approvals: the disabled replica never claims. Renewal holds a 20 s delivery with no takeover. Cache loss through a peer replica delivers on the first attempt.
  3. R1 item 2 (the restart wedge) is unchanged, and no issue tracks it yet.
    • After a dispatcher restart, head delivers the answer but the Turn stays RUNNING; base does not deliver the answer at all.
    • The plain-tool control wedges on both arms.
    • The author offered to file an issue for it, and I'd take that offer up.
  4. The fix(core): close Managed session correctness gaps from #12693 post-merge review #13332 merge resolution in commitDomainRecord is correct, and tests pin both sides.
  5. R2-23 is fixed. Across 30 interleaved runs per arm on the same host, the test before 7105fb1e was red 7 times and the rewritten one 0 times.
    • The rewrite also kills R1's surviving mutant J14 (the recovery worker never completes the receipt), so R1's suggested test (a) is now covered.
    • J11 (the cwd barrier) still survives.
  6. Bot finding R2-4 (no terminal delivery state) is open at merge. Below is real-stack data, plus a caution about the suggested fix; see §3.
    • What I did. I rolled the Harness back to main's bundle while a title delivery was open.
    • While rolled back:
      • every attempt is refused before sending (Hosted Harness title protocol version 1 is required);
      • attempts back off to the 60 s cap, and the delivery never terminates;
      • the renamed Session refuses close (409) and cwd (409), while a sibling Session on the same storage closes normally;
      • the storage-wide requireIdle predicate stays at 1.
    • Rolling forward heals it on its own in about 92 s.
    • Caution about terminating on a pre-send refusal. In the lost-reply variant, the private title was already committed before the rollback: public null against private "Rollback Title" for the whole window. Terminating the delivery on that refusal, as suggested, would have frozen exactly the divergence this PR closes. A terminal state is safe only when no attempt for that revision can have reached the Harness.

1. Migration order

r2-01

2. A/B on the real stack

r2-02

3. R2-4: an open delivery across a Harness rollback

r2-03

  • Footnote, not a merge item. A replica with the Harness enabled and Hosted Workspace files disabled (the property's default) still claims approval answers and title deliveries. Both coordinators check only isAvailable(), which is hard-coded true.
    • Effect on approvals: about +2 s, with one wasted attempt in 5/5 runs.
    • Effect on titles: one delivery was claimed 6 times in a row and landed after about 183 s.
    • Why it is only a footnote: on main, the same replica already fails workspace Turns before submission (HarnessCoordinator: workspace Session plus files disabled gives workspace_unavailable), so this topology is not supported today.

4. Tests

r2-04

Follow-ups

  1. Give the restart wedge (runtime_session_not_found after a dispatcher restart; plain-tool control wedges on both arms) its own issue.
  2. If R2-4 gets a terminal state, gate it on "no attempt for this revision may have reached the Harness", not on "this attempt was refused before sending". The lost-reply rollback cell is the counter-example.
  3. Add a cwd-barrier test for J11. R1 reproduced the escape on the real stack: cwd was admitted with 202 on an empty bound Session while the delivery was open.
  4. Recreate development databases that ran this PR at V59 or V66.

Evidence. Figures, figure sources, probe and rig scripts, and run logs are on the wenshao fork branch assets-pr13682 (pr13682/r2/ at 349817d4).

äļ­æ–‡į‰ˆ

ᜟåŪžįŽŊåĒƒéŠŒčŊįŽŽ 2 č―Ū合å…Ĩ后ab1af693 = 合å…Ĩ提äšĪ 504e4a79

įŠķ态。 朎 PR åœĻ朎č―Ū驌čŊčŋ›čĄŒäļ­ïžˆ04:50 UTCäŧĨ 504e4a79 合å…Ĩ。čŊĨ squash įš„ 38 äļŠæ–‡äŧķčĄĨäļäļŽ ab1af693 逐äļ€į›ļ同所äŧĨäļ‹éĒįš„įŧ“čŪščĶ†į›–įš„æ­Ģæ˜ŊåŪžé™…åˆå…Ĩįš„äŧĢį ã€‚

åœĻ哊䚛提äšĪäļŠč·‘。

  • åΧéƒĻ分单元栞先åœĻ 7105fb1e äļŠč·‘åŪƒįš„ PR äŧĢ᠁äļŽ ab1af693 į›ļ同。
  • äđ‹åŽåœĻ ab1af693 äļŠé‡č·‘䚆标éĒ˜ã€åŪĄæ‰đã€į§ŸįšĶ各栞äŧĨ及äŧŽå―“前 main å‡įš§ã€‚

åŪšä―ã€‚ äļ‹éĒæēĄæœ‰äŧŧä―•äļ€éĄđ需čĶå›žæŧšïžŒæœŦå°ūæ˜Ŋ后įŧ­č·Ÿčŋ›éĄđ。朎æŠĨ告æ˜Ŋ驌čŊæŠĨ告äļæ˜Ŋæ­Ģ垏čŊ„åŪĄã€‚

čĢ…į―Ū。 äļŽįŽŽ 1 č―Ūį›ļ同

  • įĄŽäŧķ和数æŪ嚓Linux aarch64MySQL 8.0.45。
  • æœåŠĄįŦŊčŋ›įĻ‹ïžšäļ‰äļŠ Spring Boot JVM å…ąį”Ļäļ€äļŠåš“ïžš
    • A æ˜Ŋæīū发å™Ļ内åĩŒ Brokerïž›
    • B æ˜Ŋ Session Store å‰Ŋ朎å…ģ闭乆 Harnessïž›
    • C æ˜ŊåŊé€‰įš„įŽŽäšŒäļŠæīū发å™Ļ。
  • Harness äū§ïžšæ‰“åŒ…åŽįš„ Hosted Harness å’ŒįœŸåŪž managed-runtime-workerïžŒé…č„šæœŽåŒ–æĻĄåž‹ïžŒSpring → Harness čūđäœ‰æ•…éšœæģĻå…Ĩ。
  • į§æœ‰æ ‡éǘäŧŽ Session Store é‡Œįš„ Harness journal čŊŧ回。

åŊđį…§įŧ„。 合åđķ埚į‚đ 543f03e5mainä―ŋį”Ļ main č‡Šå·ąįš„ jar 和 Harness。

įŧ“čŪš

  1. R1 įŽŽ 1 éĄđčŋį§ŧįž–å·ïž‰åœĻ合å…Ĩįš„äŧĢį é‡Œå·ēč§Ģå†ģïžŒä―†äļ­é€”又撞䚆äļ€æŽĄå·ã€‚
    • 合å…Ĩįš„äŧĢį ïžˆV67。 į”Ļ main d35277c2 čŋį§ŧčŋ‡įš„嚓及需嚔į”Ļ V67ïžŒč€—æ—ķ 0.09 į§’ïžŒå‡įš§å‰åˆ›åŧšįš„ Session åŊäŧĨæ­Ģåļļæ”đ名和å…ģ闭。
    • æ›īæ—Đįš„åš“ã€‚ åœĻ 7105fb1e äļŠïžŒmain 2ebbd4e1、9763580b、543f03e5 įš„åš“å’Œ V57 åš“éƒ―čƒ―æ­Ģåļļå‡įš§ïžŒR1 įš„æ‹’įŧåŊåŠĻå·ēæķˆåĪąïž›ab1af693 及æ˜Ŋ把文äŧķįž–å·å†åū€äŒŠã€‚
    • äļ­é—ī head 7105fb1eV66。 åۃäļŽ 04:00 UTC 合å…Ĩ main įš„ feat(managed-agent): execute pinned AgentDefinition revisions #13530 įš„ V66 撞号。
      • 原样合åđķæ—ķïžŒæœåŠĄåœĻäŧŧä―•åš“äļŠïžˆåŒ…拎įĐšåš“ïž‰éƒ―æ‹’įŧåŊåŠĻïžšFound more than one migration with version 66。
      • main čŋį§ŧčŋ‡įš„åš“äđŸæ‹’įŧåŪƒïžšchecksum mismatch for migration version 66。
      • PR įš„ latest-main å”Ŋä€§æĢ€æŸĨå―“æ—ķæ˜ŊįšĒįš„ïžŒab1af693 åœĻ 14 分钟后äŋŪåĨ―。
    • 垀发嚓。 č·‘čŋ‡æœŽ PR æ—Đ期构åŧšïžˆå·ēåš”į”Ļ V59 或 V66ïž‰įš„åž€å‘åš“äžšæ‹’įŧåŊåŠĻ需čĶé‡åŧšã€‚
  2. R1 įš„æŊäļŠ A/B 单元栞åœĻ合å…ĨäŧĢ᠁äļŠäūį„ķ成įŦ‹ïžˆÂ§2。
    • 标éǘäū§ïžšhead å…Ļčŋ‡ã€base å…Ļ挂äļŽ R1 åیå…Ļäļ€č‡ī。单元栞包拎įšŊ Unicode įĐšį™―æ ‡éĒ˜ã€äļĒ回包įŧ‘åŪšã€įĐšã€æœŠįŧ‘åۚäļ‰į§ Session、čŋŸåˆ°æ—§å†™ã€į”Ÿå‘―å‘ĻæœŸåąéšœå’Œ c21ïž›c19 åœĻäļĪäū§éƒ―äŋæŒäļ€č‡ī。
    • åŪĄæ‰đäū§ïžšį́į”Ļ Harness įš„å‰Ŋ朎äŧŽäļčŪĪéĒ†ã€‚įŧ­į§Ÿčƒ―čŪĐ 20 į§’įš„æ…Ē投递äļčĒŦæŽĨįŪĄã€‚įŧåĶäļ€å‰ŊæœŽįš„įž“å­˜äļĒåĪąåœšæ™ŊéĶ–æŽĄå°čŊ•åģ送čūū。
  3. R1 įŽŽ 2 éĄđæīū发å™Ļ重åŊåŽåĄæ­ŧæēĄæœ‰å˜åŒ–äđŸčŋ˜æēĄæœ‰ issue 跟čļŠã€‚
    • æīū发å™Ļ重åŊ后head čƒ―é€čūūį­”åĪä―† Turn 停åœĻ RUNNINGïž›base čŋžį­”åĪéƒ―é€äļåˆ°ã€‚
    • æ™Ū通å·Ĩ具åŊđį…§įŧ„åœĻäļĪäū§éƒ―åĄæ­ŧ。
    • ä―œč€…čĄĻįĪšæ„ŋ意äļšæ­Īåŧš issueåŧščŪŪæŽĨ受。
  4. commitDomainRecord äļ­äļŽ fix(core): close Managed session correctness gaps from #12693 post-merge review #13332 įš„å†ēįŠč§Ģæģ•æ­ĢįĄŪäļĪčūđéƒ―æœ‰æĩ‹čŊ•é’‰ä―ã€‚
  5. R2-23 å·ēäŋŪåĪã€‚ 同äļ€å°æœšå™ĻäļŠäļĪ臂äšĪæ›ŋ各跑 30 æŽĄïžšäŋŪåĪå‰įš„æĩ‹čŊ•įšĒ 7 æŽĄïžŒæ”đ写后 0 æŽĄã€‚
    • æ”đå†™åŽįš„æĩ‹čŊ•čŋ˜éĄšåļĶæ€æŽ‰äš† R1 存æīŧįš„å˜åž‚ J14æĒåĪåįĻ‹æ°ļäļåŪŒæˆå›žæ‰§ïž‰ïžŒR1 åŧščŪŪįš„æĩ‹čŊ• (a) å·ēčĒŦčĶ†į›–ã€‚
    • J11cwd åąéšœïž‰äŧį„ķ存æīŧ。
  6. bot įš„ R2-4投递æēĄæœ‰įŧˆæ€ïž‰åœĻ合å…Ĩæ—ķäŧæœŠå…ģ闭。 äļ‹éĒæ˜ŊᜟåŪžæ ˆæ•°æŪäŧĨ及åŊđå…ķäŋŪæģ•įš„äļ€äļŠæé†’§3。
    • 做æģ•ïžš åœĻäļ€äļŠæ”đ名投递朊åŪŒæˆæ—ķ把 Harness 回æŧšåˆ° main įš„į‰ˆæœŽã€‚
    • 回æŧšæœŸé—īïžš
      • æŊæŽĄå°čŊ•éƒ―åœĻ发送前čĒŦ拒Hosted Harness title protocol version 1 is required
      • 尝čŊ•æŽĄæ•°é€€éŋ到 60 į§’äļŠé™ïžŒæŠ•递始įŧˆäļįŧˆæ­Ēïž›
      • čĒŦæ”đåįš„ Session å…ģ闭 409、cwd 409同存å‚Ļįš„åĶäļ€äļŠ Session æ­Ģåļļå…ģé—­ïž›
      • 存å‚Ļįš§ requireIdle 谓čŊäļ€į›īäļš 1。
    • æĒ回新 Harness 后įšĶ 92 į§’č‡Šæ„ˆã€‚
    • 提醒 åœĻäļĒå›žåŒ…å˜ä―“é‡ŒïžŒå›žæŧšå‰į§æœ‰æ ‡éǘå·ēįŧæäšĪæ•īäļŠįŠ—åĢ内兎垀äļš nullã€į§æœ‰äļš "Rollback Title"。č‹Ĩ按åŧščŪŪåœĻ发送前拒įŧæ—ķįŧˆæ­ĒæŠ•é€’ïžŒå°ąäžšæŠŠæœŽ PR č́æķˆé™Īįš„åˆ†å‰å›šåۚäĨ。及有åœĻ「čŊĨ revision äļåŊčƒ―æœ‰čŊ·æą‚到čūūčŋ‡ Harness」æ—ķįŧˆæ­Ē才åŪ‰å…Ļ。

附æģĻäļæ˜Ŋ合åđķéĄđ

「Harness 垀、Hosted Workspace files å…ģčŊĨåąžæ€§éŧ˜čŪĪå€žïž‰ã€įš„å‰Ŋ朎äŧäžščŪĪédžåŪĄæ‰đį­”åĪå’Œæ ‡éĒ˜æŠ•é€’ã€‚äļĪäļŠåįĻ‹éƒ―åŠæĢ€æŸĨįĄŽįž–į äļš true įš„ isAvailable()。

  • åŪĄæ‰đäū§å―ąå“ïžš įšĶåΚ 2 į§’ïžŒ5/5 æŽĄå„æĩŠčīđäļ€æŽĄå°čŊ•。
  • 标éǘäū§å―ąå“ïžš 有äļ€æŽĄæŠ•é€’čĒŦčŋžįŧ­čŪĪédž 6 æŽĄïžŒįšĶ 183 į§’åŽæ‰č―åœ°ã€‚
  • äļšä―•åŠä―œé™„æģĻïžš åœĻ main äļŠïžŒåŒæ ·įš„å‰Ŋ朎朎æĨå°ąäžšåœĻ提äšĪ前垄挂 workspace TurnHarnessCoordinatorïžšworkspace Session 加 files å…ģ闭åģ workspace_unavailablečŋ™į§æ‹“扑į›Ū前åđķäļå—æ”Ŋ持。

后įŧ­č·Ÿčŋ›

  1. äļšé‡åŊåĄæ­ŧæīū发å™Ļ重åŊ后 runtime_session_not_foundïž›æ™Ū通å·Ĩ具åŊđį…§įŧ„äļĪäū§éƒ―åĄæ­ŧïž‰å•į‹Žåŧš issue。
  2. åĶ‚æžœįŧ™ R2-4 加įŧˆæ€ïžŒåˆĪæŪåš”æ˜Ŋ「čŊĨ revision äļåŊčƒ―æœ‰čŊ·æą‚到čūūčŋ‡ Harnessã€ïžŒč€Œäļæ˜Ŋ「čŋ™äļ€æŽĄåœĻ发送前čĒŦ拒」。äļĒ回包回æŧšįš„å•å…ƒæ žå°ąæ˜Ŋ反äū‹ã€‚
  3. äļš J11 čĄĨäļ€äļŠ cwd åąéšœæĩ‹čŊ•。R1 åœĻᜟåŪžæ ˆäļŠåĪįŽ°čŋ‡ïžšæŠ•递朊åŪŒæˆæ—ķįĐšįš„įŧ‘åۚ Session äļŠ cwd čĒŦäŧĨ 202 æŽĨ受。
  4. 重åŧšč·‘čŋ‡æœŽ PR V59 或 V66 įš„åž€å‘åš“ã€‚

čŊæŪ。 å›ū、å›ū暐、æŽĒ针äļŽčĢ…į―Ūč„šæœŽã€čŋčĄŒæ—Ĩåŋ—éƒ―åœĻ wenshao fork įš„ assets-pr13682 分æ”Ŋpr13682/r2/349817d4。

wenshao added a commit that referenced this pull request Oct 11, 2026
â€Ķy witness

The retried rename is completed either by the synchronous third call's
inline claim or by the delivery coordinator's asynchronous re-drive, and
either order is a legitimate completion order under the admission-fence
semantics established by #13682. When the coordinator wins, the replay
correctly answers the session's current state, whose title is the
sibling rename's value instead of the retried one. The replay flag and
the no-duplicate-events inventory carry the witness deterministically;
the live-title read depends on which lane finished first.
Jay0130-a pushed a commit to Jay0130-a/qwen-code that referenced this pull request Oct 11, 2026
â€Ķ2692 R2 review (QwenLM#13330)

* fix(managed-agent): connector and broker robustness from the QwenLM#12692 R2 review

Nine follow-ups from the post-merge R2 review round on QwenLM#12692,
re-verified against current main (5ddfacc) before patching:

- The durable session row is now the archive/delete fence: the broker
  resolver rejects ARCHIVED/DELETED rows for unbound Sessions, so the
  in-process retired set stops growing on the delete path and the
  fence survives restarts. Close keeps its in-process retirement.
- Attach fetch moved out of ConcurrentHashMap.computeIfAbsent: a slow
  create no longer stalls every attachment hashing to the same bin.
- The connector close protocol no longer leaks a client built after or
  during close(): a closed flag under the same monitor fails late
  calls before any executor or heartbeat is constructed.
- Hosted Harness base URL is validated as an absolute http(s) URI at
  startup; "localhost:4170"-style mistakes no longer die opaquely at
  the first RPC.
- Tool-call item identities tag both branches, so a harness callId of
  the literal form "source:<n>" cannot collide with the no-id
  fallback.
- The dispatch constructor rejects lease/renew misconfiguration
  (non-positive values, renew >= duration) instead of letting it
  surface later as hosted_harness_unavailable.
- Dependency failures at the rename site keep their root cause via a
  cause-carrying ApiException instead of an unchained 503.
- A poisoned materialization target no longer heads every 100 ms pass:
  consecutive failures retry on 1, 2, 4, ..., 64 streaks and the
  target rotates behind fresher rows (covered_sequence untouched), so
  healthy sessions are never starved and identical warnings stop
  repeating every pass.
- The kubernetes provisioner rejection now says it is unsupported and
  names the valid values instead of referencing an internal review
  slice.

Verified on the managed-agent-server module with mvn verify: 562
tests (new cases pin each change), checkstyle and spotbugs green.

* test(managed-agent): close the method boundary between the two merged tests

The tail splice merged sourcePrefixedCallIdDoesNotCollideWithTheNoIdFallback
into projectsDeadlineExpiryAsAClassifiedFailure without the closing brace
and @test annotation (main-scope compile passed; test-compile is the gate
that sees it).

* test(managed-agent): correct the stream-close comment in HostedHarnessMySqlIT

HarnessEventStream moved from a monitor to a ReentrantLock in QwenLM#13388, so
close() no longer contends on a synchronized read; it queues on the
stream lock while next() holds it across the blocking socket read.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(managed-agent): fence closing sessions durably and keep tool item identity on the v1 rule (QwenLM#13330)

* fix(managed-agent): address the QwenLM#13330 R2 review findings

- MessageMaterializer: best-effort deferrals via deferQuietly, warning
  before rotating, so a store fault while deferring degrades one target
  instead of aborting the pass and swallowing the diagnostic
- QwenHostedHarnessConnector.close(): capture and null the client under
  clientLock, close it outside the lock so the executor shutdown no longer
  stalls client() callers behind it
- HarnessCoordinator: validate lease durations as the millis the scheduler
  receives, rejecting sub-millisecond renew intervals at startup
- EventIdentity: share the callId tool-item rule with the Harness event
  projector via the public toolCallItemId; the projector test now asserts
  against the authority instead of a re-derived literal
- Tests: rotation witness for deferMaterializationTarget against the
  selection ORDER BY, per-clause base-URL guard cases, negative and
  sub-millisecond renew cases, close-outside-the-lock witness; rename a
  sequential test that was named for concurrency
- Docs: sync gate 3 of the review-corrections design (both languages) with
  the durable lifecycle fence

* fix(managed-agent): fence closed Sessions on the warm path only

The durable lifecycle fence sat in the shared HarnessSessionResolver
lambda, so the release and unknown-outcome reconcile routes — which run
after a Session closes — hard-refused a CLOSED Session with a
non-retryable 409 and leaked the binding the teardown exists to release.
Scope the fence to a new admission resolve that only warm() consults;
teardown routes resolve the closed Session's scope again. Also defer a
poisoned materialization target only when its retry is not due, so a due
pass stops writing the progress row twice, and sync the README/design
wording with the shipped fence.

* chore(managed-agent): re-present the round-3 fixes with the tree cleaned

The deterministic gate rejected 6a671b3 on npm run lint alone: the
round's own Maven verification had generated JaCoCo/Javadoc JavaScript
under packages/sdk-java/*/target (gitignored build output, never part of
the committed tree), and ESLint scans those files when they exist on
disk. The artifacts are removed and lint, build, and typecheck were
re-run green on the final tree. No tracked content changes; the round-3
fixes are preserved as-is.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(managed-agent): converge teardown behind the drain fence

The persisted ARCHIVED/DELETED fence in the embedded broker's session
resolver guarded every scope resolution, so the durable release and the
unknown-outcome reconciliation of a closed Session died on a
non-retryable runtime_broker_session_closed after closing. Split the
resolver into a bootstrap channel (fenced: warm, acquire) and a teardown
channel (permissive: persistedSession's release and reconciliation) via
HarnessSessionResolver.resolveForTeardown.

MessageMaterializer's pre-attempt defer ran outside the due gate, so
every 100 ms pass updated every poisoned row, and the capped streak made
attempts and their stack warns fire at 10 Hz forever. Skip passes are
now the only ones that rotate the row and the streak is uncapped, so
attempts and warns ride the power-of-two ladder.

The README still described the drain fence as an in-process retirement
flag; it is persisted Session status.

* test(runtime-broker): pin the admission fence to warm in the teardown release witness

Renames the fake resolver's teardown outlet to the admission channel the
interface now exposes, flips the witness to fence warm while release keeps
resolving, and keeps the durable release assertion.

* fix(managed-agent): gate the skip-path rotation on window saturation (QwenLM#13330)

A skipped pass below TARGET_LIMIT rotated a row the next pass selects
anyway, so the throttle fires only when the selection window is full; the
rotation warn is stack-less so a persistently faulting deferral cannot bury
the one-line signal at scheduler rate. Pins the streak reset, the skip-path
guard under a fault, and the snapshot_stale_since marker the deferral must
not clobber, narrows the README fence clause to the warm admission resolve,
and corrects the release witness comment to what the test executes.

* fix(managed-agent): address the QwenLM#13330 R4 review findings

Probe one row past the selection window for the skip-path rotation gate
so an exactly-full window does not rotate rows that are selected again
anyway, pin the post-cap modulo retry at streak 192, and mirror all five
of the client builder's base-URL rules in the boot-time guard.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* chore(managed-agent): re-verify the QwenLM#13330 R4 round on a target-free workspace

The deterministic gate rejected e5940ae on 'npm run lint': the previous
round's Maven verification runs left generated JavaScript under
packages/sdk-java/*/target (jacoco-resources/prettify.js + sort.js,
reports/apidocs/*.js), and the repo-wide eslint scan fails on those
gitignored artifacts (728 errors, all confined to target/). No tracked
change can carry this repair: the root eslint config and the lint script
are verification machinery outside this round's footprint. The fix is
environmental — the target/ trees are removed so the gate's lint re-run
scans only tracked sources — and this empty commit re-presents the
preserved R4 round for re-verification.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(managed-agent): address the QwenLM#13330 R5 review findings

Fence the materialization tick onto its own scheduler pool so a faulting
skip-path rotation cannot occupy the dispatch thread, require a lease
renew interval of at most half the lease duration so a late renewal keeps
its margin, attribute the rename WARN to the operation rather than a
subsystem the fault may not be in, and pin the saturation probe row's
exclusion from the work loop.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* chore(sdk-java): clean generated Maven target dirs to unblock lint gate

Same-run verification repair: the previous round's local mvn runs left
generated JaCoCo report JS under packages/sdk-java/*/target. Those dirs
are git-ignored but are not in the root ESLint ignore list, so the
gate's npm run lint (eslint .) failed with 139 errors on generated
code. The artifacts are untracked, regenerable build output; removing
them from the working tree restores lint. No source change.

* fix(runtime-broker): fence a fresh acquire behind the admission resolve (QwenLM#13330)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* test(managed-agent): align the rename fault witness with the renamed store call

The aFailedRenameLogsAndChainsTheRootCause store mock still stubbed the
pre-rename completion entry point; production now persists rename results
through completeSessionRename, so the mock fell through to the real store
and the rename succeeded, failing the assertion that it must raise. The
stub is pinned to completeSessionRename with its six-argument shape.

* test(managed-agent): drop the racy live-title read in the rename retry witness

The retried rename is completed either by the synchronous third call's
inline claim or by the delivery coordinator's asynchronous re-drive, and
either order is a legitimate completion order under the admission-fence
semantics established by QwenLM#13682. When the coordinator wins, the replay
correctly answers the session's current state, whose title is the
sibling rename's value instead of the retried one. The replay flag and
the no-duplicate-events inventory carry the witness deterministically;
the live-title read depends on which lane finished first.

---------

Co-authored-by: qwen-code-autofix <qwen-code-autofix@users.noreply.github.com>
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Co-authored-by: qwen-code-dev-bot <qwen-code-dev@service.alibaba.com>
Co-authored-by: qwen-code <qwen-code@alibaba-inc.com>
Co-authored-by: qwen-code-autofix <qwen-code-autofix[bot]@users.noreply.github.com>
Co-authored-by: qwen-code-ci-bot <qwen-code-ci-bot@users.noreply.github.com>
Co-authored-by: qwen-code-autofix <qwen-code-autofix@localhost>
@qwen-code-review-bot

Copy link
Copy Markdown
Collaborator

Released in v0.25.1.

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.

6 participants