[shepherding] Durable outbox for Pi adapter: atomic leases + at-least-once + dead-letter isolation
Is this feature related to a problem? | 该功能需求是否与某个问题相关?请描述
Shepherding issue split out of #1070 (see review comment closing that PR). Follow-up PR author: @kbob3687-hub. Targets
feat/server_team.
Background
The proxy-first Pi adapter has landed in MemoryProxy/src/agent-adapters/pi.ts
via #1126, but that PR only covers the transport layer — it does not provide
any durability guarantees. #1070 originally shipped a full durable-delivery
layer that we want to reintroduce as an independent, testable PR.
Why this matters: without a durable outbox, memory writes generated during a Pi coding session can be lost on process crash, replayed on network retry, or silently deduplicated against the wrong turn. This is the single largest correctness gap in the current Pi path.
In scope
- Atomic lease on outbox entries (single-consumer semantics across concurrent Pi sessions on the same host)
- At-least-once delivery to the gateway with idempotency-key propagation
- Dead-letter isolation for entries that fail past the retry ceiling, with an operator-visible surface (not just a log line)
- Crash-window contract test: gateway
accept→ localackwrite is interrupted → restartrecover()must not double-deliver - Wire-in point:
MemoryProxy/src/agent-adapters/pi.ts(post-#1126 layout)
Alignment with #1142
The outbox writes MUST carry idempotency_key: turn.key and the gateway
side MUST treat same-key + same-payload as no-op, same-key + different-payload
as an explicit error. This is the contract #1142 establishes for
retry-safe conversation writes — please read that PR before implementing
so we avoid the ack-gap discussion that consumed #978.
Out of scope
- Any changes to the proxy-first transport layer landed by #1126
- Cross-branch memory identity (that's the
/treeshepherding issue) - Gateway-side idempotency implementation itself (owned by #1142)
Acceptance criteria
- Outbox entries carry
idempotency_keyon every gateway call - Same key + same payload → gateway no-op (unit test)
- Same key + different payload → gateway error surfaces to DLQ (unit test)
- Crash-window test: kill process between gateway
202and local ack, restart, assert no duplicate delivery - DLQ entries queryable and re-drivable via a documented operator path
- No modifications to
handler.tsorsession/codebuddy/init.ts(per repo contribution guidance) - All new tests pass; existing test suite unaffected
Related
- Closes down the outbox portion of #1070
- Consumes the contract in #1142
- See #978 for the earlier ack-gap discussion this design avoids
Suggested branching
Branch name: pi-adapter/durable-outbox against feat/server_team.
Please keep this PR to the outbox layer only — the other three follow-ups
have their own shepherding issues (linked in the batch comment on #1070).
Describe the solution you'd like | 描述你期望的解决方案
/
Describe alternatives you've considered | 描述你考虑过的其他方案
No response
Additional context | 补充说明
No response
Source: TencentCloud/TencentDB-Agent-Memory