fix(agent-org): port red-team recovery hardening to develop#533
Open
ShiboSheng wants to merge 1 commit into
Open
fix(agent-org): port red-team recovery hardening to develop#533ShiboSheng wants to merge 1 commit into
ShiboSheng wants to merge 1 commit into
Conversation
ShiboSheng
marked this pull request as ready for review
July 25, 2026 09:13
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why this PR exists
The main goal of this PR is to close the edge cases raised in follow-up review and red-team feedback on the earlier Agent Org recovery work. It is not a new Agent Org workflow.
The normal path was already working: launch an org, assign work, exchange messages, and finish a run. The feedback focused on the less common paths that can leave a run stuck or make recovery unsafe:
@input ordering?Those fixes were implemented in #424, but #424 was a stacked PR whose base was
fix/issue-272-agent-org-recovery-invariants, notdevelop. GitHub merged it into that stacked branch, so the hardening never became part ofdevelop.Since then,
develophas split the old Agent Org files into smaller Inbox, Plan Approval, Task Store, Session Message, Org Tasks, Watchdog, and Turn Executor modules. This PR therefore ports the behavior from #424 into the current architecture instead of copying the old files back.Source: #424 /
df158006ad76271a0cc60440dc4c611e54774f8aWhat we fixed
1. An undeliverable message can now be resolved without rewriting history
Previously, a permanently undeliverable Inbox row could keep waking a member or prevent a Run from becoming final. Marking it as read would hide the evidence and incorrectly imply that the recipient saw it.
This PR adds a coordinator-only
org_inbox_repairtool:inspectexplains why a delivery is stuck.cancelrecords that the coordinator intentionally cancelled it.supersedelinks it to a real replacement delivery.The original Inbox row is retained and remains unread as audit evidence. A separate durable resolution records the operational decision, and resolved rows no longer block unread processing or Run finality.
2. Work is bound to the exact Run and roster member
Review feedback found several places where reusable
agent_idvalues could be mistaken for roster identity. That is unsafe when two members share the same underlying agent definition.The repaired paths consistently use the exact
(org_run_id, member_id)pair for:Turn intents also gain a nullable
org_run_id. Agent Org turns may bind a previously unbound intent once, but an intent can never be reassigned from one Run to another. Existing ordinary turns remainNULL; we do not guess ownership for old rows.3. Recovery decisions are rechecked at the moment they are committed
The watchdog and coordinator can observe valid state that becomes stale before the write happens. For example, a task may be reassigned or a member may recover while a recovery action is being prepared.
This PR revalidates the Run, member, task, eligibility, Inbox facts, and work revision inside the writer transaction. Wake-budget consumption, recovery writes, and recovery notices are committed atomically. If the observed facts are stale, the action aborts instead of applying an outdated recovery plan.
Recovery fingerprints are now stable, typed, sorted, and bounded so harmless ordering differences do not consume extra budget and large/corrupt payloads cannot inflate the recovery reason.
4. Old or malformed data fails closed
Historical task and Inbox rows are validated before they are used for operational decisions. Invalid identifiers, timestamps, dependency graphs, statuses, metadata, or payloads are reported as corrupt rather than silently projected as healthy pending work.
The port also adds explicit limits for task counts, identifiers, JSON, Inbox snapshots, history rows/bytes, and UI previews.
Plan Approval paths receive component-wise traversal checks, canonical-root validation, race-bounded artifact installation, and startup reconciliation for missing durable artifacts.
5. The UI no longer trusts stale or unbounded state
The frontend side of the feedback is covered as well:
@keydown/input ordering is normalized.corruptanddeliveryResolution.The current
developPlan Approval detail cache is already bounded by both entry count and bytes, which is stronger than #424's entry-only version, so that newer implementation is intentionally retained.What this PR deliberately does not do
developbehavior with an older implementation whendevelopis already stronger.Complete review-feedback mapping (15 items)
inspect,cancel, andsupersedeagent_iddevelopimplementation retained@orderingSchema and API changes
agent_inbox_delivery_resolutionswithout deleting or mutating the original Inbox evidence.session_turn_intents.org_run_id; legacy and ordinary turns remainNULL.org_inbox_repairthrough tool policy, assembly, metadata, and tool-name contracts.corruptand Inbox/historydeliveryResolutionprojections.Verification
The pushed commit is
c51e92625c1a1a825deedd6c4238165f386bb53c, directly based on fetcheddevelopcommit8396874b366e1868d089373ef95a820ffb7c0000.Passed
cargo check -p agent_core -p session_persistence -p e2e-test -p org2 --all-targetspnpm run typecheckpnpm run lint— 0 errorspnpm run check:circular— 5,819 files, no circular dependencycargo test -p agent_core --lib --no-fail-fast— 3,126 passed, 2 ignoredcargo test -p session_persistence --no-fail-fast— 35 passedpnpm test— 691 files / 6,267 tests passedin_progresswork or hidden tool-error trajectoryExisting repository baseline
cargo fmt --all -- --checkreports formatting in files outside this PR.cargo clippy --workspace --all-targets -- -D warningsstops in the untouched gateway CLI test layout. The PR's affected crates pass scoped clippy, and the GitHub Rust clippy job is green.Rendered Tauri E2E baseline
All three requested rendered specs were executed with isolated ORGII homes and independent ports. They are not reported as passing:
The pause/resume and recovery failures reproduce on clean
develop. The clean Group Chat run fails earlier and then triggers atauri-plugin-webdriver-automation 0.1.3pending-script panic followed by a poisoned lock. The finaldevelopadvance did not touch the affected Agent Org UI/E2E paths.These are recorded as existing rendered-harness/UI baseline blockers rather than hidden or attributed to this port.
Audit reports
docs/architecture-audit-2026-07-24/AgentOrgRedTeamPort.mddocs/frontend-ui-audit-2026-07-24/AgentOrgRedTeamPort.md