refactor(daemon): drop the reused-workdir prompt block now that checkout keeps work (MUL-7034) (#8316)

The "Files from an earlier run" per-turn block was added in #8291 because a
fresh session in a reused workdir had no memory of the work there, and
re-running `multica repo checkout` reset an existing checkout and deleted it.
MUL-7284 (#8309) fixed that in checkout itself: an existing checkout holding
uncommitted, untracked or unpushed work is kept, and the CLI reports it
("Kept the existing checkout ... N uncommitted files, M unpushed commits").
The brief documents that behavior and --fresh, and the server's continuity
notice already says the earlier attempt's context did not come back. The block
only repeated those, so remove it, its two runTask insertion points, and its
tests. prompt.go and runTask are back to their pre-#8291 form.

The server still offers an automatic retry its parent's workdir only to
daemons that make that safe. The capability now names what they guarantee:
reused-workdir-notice-v1 becomes checkout-keeps-work-v1. Neither string has
shipped in a release, and a new daemon talking to an old server, or the
reverse, just gets a fresh directory as today.

The end-to-end runTask test keeps its reuse assertions: a fresh-session run
offered a prior workdir continues in it, and falls back to a fresh directory
once that one is gone.

Co-authored-by: J <[email protected]>
Co-authored-by: multica-agent <[email protected]>
This commit is contained in:
Bohan Jiang
2026-09-11 17:18:03 +08:00
committed by GitHub
co-authored by J multica-agent
parent 67bc6686d1
commit d44932089b
9 changed files with 45 additions and 242 deletions
+1 -1
View File
@@ -210,7 +210,7 @@ func daemonCommonCapabilities() []string {
protocol.DaemonCapabilitySourceContextQuickCreateV1,
protocol.DaemonCapabilityRPCV1,
protocol.DaemonCapabilityPlatformSkillV1,
protocol.DaemonCapabilityReusedWorkdirNoticeV1,
protocol.DaemonCapabilityCheckoutKeepsWorkV1,
}
}
+1 -1
View File
@@ -54,7 +54,7 @@ func TestClient_IdentityHeaders_PostJSON(t *testing.T) {
// Gates whether an automatic retry is handed its parent's workdir
// (MUL-7034). Dropping it silently sends those retries back to a
// fresh directory, losing the continuity nothing else would flag.
protocol.DaemonCapabilityReusedWorkdirNoticeV1,
protocol.DaemonCapabilityCheckoutKeepsWorkV1,
} {
if !capabilities[want] {
t.Errorf("X-Client-Capabilities missing %q: %v", want, capabilities)
-12
View File
@@ -8027,13 +8027,6 @@ func (d *Daemon) runTask(ctx context.Context, task Task, provider string, slot i
if env.LocalWorktree != nil && len(env.LocalWorktree.ReplayConflicts) > 0 {
promptOptions = append(promptOptions, WithWorktreeReplayConflicts(env.LocalWorktree.ReplayConflicts))
}
// A fresh session in a reused workdir starts among files it has no memory
// of producing (MUL-7034). envReused is what this daemon actually did, not
// what the server offered: a GC'd directory falls back to Prepare and is
// not warned about.
if envReused && task.PriorSessionID == "" {
promptOptions = append(promptOptions, WithReusedWorkdir())
}
prompt := BuildPrompt(task, provider, promptOptions...)
// Pass task-scoped auth credentials and context so the spawned agent CLI
@@ -8405,11 +8398,6 @@ func (d *Daemon) runTask(ctx context.Context, task Task, provider string, slot i
execOpts.SystemPrompt = runtimeBrief
}
}
// The first attempt was resuming, so it was not warned about the reused
// workdir; this one is in the same directory without that memory.
if envReused {
promptOptions = append(promptOptions, WithReusedWorkdir())
}
freshPrompt := BuildPrompt(task, provider, promptOptions...)
retryResult, retryTools, retryErr := d.executeAndDrain(ctx, backend, freshPrompt, execOpts, taskLog, task.ID, env.CodexHome, &msgSeq)
@@ -163,148 +163,44 @@ func TestShouldReusePriorWorkdirDeclinesRemovedDirectory(t *testing.T) {
}
}
// TestRunTaskWarnsFreshSessionInReusedWorkdir drives real runTask calls to pin
// where the reused-workdir warning lands (MUL-7034). A run that reuses an
// earlier run's directory without resuming its session is warned in the prompt
// the backend receives, and the warning stays out of the brief written into the
// workdir, which must be byte-stable across runs (MUL-5377). A run that resumes
// the session remembers the work and is not warned; a run whose offered
// directory is gone gets a fresh one and nothing to be warned about.
func TestRunTaskWarnsFreshSessionInReusedWorkdir(t *testing.T) {
// TestRunTaskReusesPriorWorkdirForFreshSession drives real runTask calls
// through what the server hands an automatic retry after a
// conversation-poisoning failure: the parent's workdir and no session
// (MUL-7034). The run continues in that directory; once the directory has been
// GC'd, it prepares a fresh one instead.
func TestRunTaskReusesPriorWorkdirForFreshSession(t *testing.T) {
t.Parallel()
d, _, promptsFile, cleanup := newPromptCapturingReuseTestDaemon(t)
d, _, cleanup := newLeaderReuseTestDaemon(t)
defer cleanup()
const warning = "Files from an earlier run"
run := func(task Task) (TaskResult, string) {
run := func(task Task) TaskResult {
t.Helper()
task.IsLeaderTask = false
result, err := d.runTask(context.Background(), task, "claude", 0, d.logger)
if err != nil {
t.Fatalf("runTask %s: %v", task.ID, err)
}
prompts, err := os.ReadFile(promptsFile)
if err != nil {
t.Fatalf("read prompts: %v", err)
}
lines := strings.Split(strings.TrimRight(string(prompts), "\n"), "\n")
return result, lines[len(lines)-1]
return result
}
firstResult, firstPrompt := run(leaderReuseTestTask("task-first"))
if strings.Contains(firstPrompt, warning) {
t.Fatalf("a fresh environment was warned about an earlier run: %s", firstPrompt)
}
firstResult := run(leaderReuseTestTask("task-first"))
// What the server hands an automatic retry after a conversation-poisoning
// failure: the parent's workdir, no session.
retry := leaderReuseTestTask("task-retry")
retry.PriorWorkDir = firstResult.WorkDir
retry.PriorSessionResumeUnavailable = true
retryResult, retryPrompt := run(retry)
if !sameDir(t, retryResult.WorkDir, firstResult.WorkDir) {
if retryResult := run(retry); !sameDir(t, retryResult.WorkDir, firstResult.WorkDir) {
t.Fatalf("retry WorkDir = %q, want the reused %q", retryResult.WorkDir, firstResult.WorkDir)
}
if !strings.Contains(retryPrompt, warning) {
t.Fatalf("fresh session in a reused workdir was not warned; prompt: %s", retryPrompt)
}
brief, err := os.ReadFile(filepath.Join(retryResult.WorkDir, "CLAUDE.md"))
if err != nil {
t.Fatalf("read brief: %v", err)
}
if strings.Contains(string(brief), warning) {
t.Fatal("reused-workdir warning leaked into the byte-stable brief")
}
followUp := leaderReuseTestTask("task-follow-up")
followUp.PriorWorkDir = retryResult.WorkDir
followUp.PriorSessionID = retryResult.SessionID
followUpResult, followUpPrompt := run(followUp)
if !sameDir(t, followUpResult.WorkDir, retryResult.WorkDir) {
t.Fatalf("follow-up WorkDir = %q, want the reused %q", followUpResult.WorkDir, retryResult.WorkDir)
}
if strings.Contains(followUpPrompt, warning) {
t.Fatalf("a resumed session was warned about work it remembers: %s", followUpPrompt)
}
if err := os.RemoveAll(firstResult.EnvRoot); err != nil {
t.Fatalf("remove env root: %v", err)
}
afterGC := leaderReuseTestTask("task-after-gc")
afterGC.PriorWorkDir = firstResult.WorkDir
afterGCResult, afterGCPrompt := run(afterGC)
if afterGCResult.WorkDir == firstResult.WorkDir {
if afterGCResult := run(afterGC); afterGCResult.WorkDir == firstResult.WorkDir {
t.Fatalf("run reused a workdir that no longer exists: %q", afterGCResult.WorkDir)
}
if strings.Contains(afterGCPrompt, warning) {
t.Fatalf("a fresh environment was warned about an earlier run: %s", afterGCPrompt)
}
}
// TestRunTaskWarnsFreshRetryAfterRejectedResume covers the in-turn path to the
// same state: a run that reused a workdir to resume its session, had the resume
// rejected, and retried with a fresh session in that directory. The resuming
// attempt remembers the work and is not warned; the fresh retry is (MUL-7034).
func TestRunTaskWarnsFreshRetryAfterRejectedResume(t *testing.T) {
t.Parallel()
d, _, promptsFile, cleanup := newPromptCapturingReuseTestDaemon(t)
defer cleanup()
first := leaderReuseTestTask("task-first")
first.IsLeaderTask = false
firstResult, err := d.runTask(context.Background(), first, "claude", 0, d.logger)
if err != nil {
t.Fatalf("first runTask: %v", err)
}
// From here on the provider refuses every --resume the way Claude does
// when the transcript is gone, and accepts a fresh session.
rejectingScript := `#!/bin/sh
IFS= read -r prompt
printf '%s\n' "$prompt" >> "` + promptsFile + `"
for arg in "$@"; do
if [ "$arg" = "--resume" ]; then
echo "No conversation found with session ID: session-leader-reuse" >&2
printf '%s\n' '{"type":"result","subtype":"error_during_execution","is_error":true,"result":"No conversation found"}'
exit 1
fi
done
printf '%s\n' '{"type":"system","session_id":"session-fresh"}'
printf '%s\n' '{"type":"result","subtype":"success","is_error":false,"session_id":"session-fresh","result":"done"}'
`
if err := os.WriteFile(d.cfg.Agents["claude"].Path, []byte(rejectingScript), 0o755); err != nil {
t.Fatalf("rewrite fake agent: %v", err)
}
second := leaderReuseTestTask("task-second")
second.IsLeaderTask = false
second.PriorWorkDir = firstResult.WorkDir
second.PriorSessionID = firstResult.SessionID
secondResult, err := d.runTask(context.Background(), second, "claude", 0, d.logger)
if err != nil {
t.Fatalf("second runTask: %v", err)
}
if secondResult.SessionID != "session-fresh" {
t.Fatalf("second run did not end on the fresh session: %+v", secondResult)
}
prompts, err := os.ReadFile(promptsFile)
if err != nil {
t.Fatalf("read prompts: %v", err)
}
lines := strings.Split(strings.TrimRight(string(prompts), "\n"), "\n")
if len(lines) != 3 {
t.Fatalf("got %d invocations, want first run + rejected resume + fresh retry:\n%s", len(lines), prompts)
}
const warning = "Files from an earlier run"
if strings.Contains(lines[1], warning) {
t.Fatalf("the resuming attempt was warned about work it remembers: %s", lines[1])
}
if !strings.Contains(lines[2], warning) {
t.Fatalf("fresh retry in the reused workdir was not warned: %s", lines[2])
}
}
// TestShouldReusePriorWorkdirSquadLeaderAcceptsManagedProvenance is the unit
@@ -457,25 +353,14 @@ func TestShouldReusePriorWorkdirSquadLeaderRejectsSymlinkEscape(t *testing.T) {
func newLeaderReuseTestDaemon(t *testing.T) (*Daemon, string, func()) {
t.Helper()
d, argsFile, _, cleanup := newPromptCapturingReuseTestDaemon(t)
return d, argsFile, cleanup
}
// newPromptCapturingReuseTestDaemon is newLeaderReuseTestDaemon that also
// returns a file holding each invocation's prompt, one stream-json frame per
// line in invocation order.
func newPromptCapturingReuseTestDaemon(t *testing.T) (*Daemon, string, string, func()) {
t.Helper()
testDir := t.TempDir()
fakeBin := filepath.Join(testDir, "claude")
argsFile := filepath.Join(testDir, "claude-args.txt")
promptsFile := filepath.Join(testDir, "claude-prompts.txt")
script := `#!/bin/sh
printf '%s\n' "$@" >> "` + argsFile + `"
printf '%s\n' '--invocation-end--' >> "` + argsFile + `"
IFS= read -r prompt
printf '%s\n' "$prompt" >> "` + promptsFile + `"
IFS= read -r _
printf '%s\n' '{"type":"system","session_id":"session-leader-reuse"}'
printf '%s\n' '{"type":"result","subtype":"success","is_error":false,"session_id":"session-leader-reuse","result":"done"}'
`
@@ -503,7 +388,7 @@ printf '%s\n' '{"type":"result","subtype":"success","is_error":false,"session_id
},
},
}
return d, argsFile, promptsFile, srv.Close
return d, argsFile, srv.Close
}
func writeLeaderTaskMarker(t *testing.T, workDir, agentID, issueID string) {
-28
View File
@@ -67,7 +67,6 @@ func perTurnContextBlocks(task Task, opts promptOpts) string {
if task.PriorSessionResumeUnavailable {
b.WriteString(sessionContinuityNoticeFor(task))
}
b.WriteString(buildReusedWorkdirBlock(opts.reusedWorkdir))
b.WriteString(execenv.BuildTaskInitiatorBlock(task.InitiatorType, task.InitiatorName, task.InitiatorEmail))
b.WriteString(execenv.BuildConnectedAppsBlock(task.ConnectedApps))
return b.String()
@@ -79,7 +78,6 @@ func perTurnContextBlocks(task Task, opts promptOpts) string {
type promptOpts struct {
sharedLocalDirectory bool
worktreeReplayConflicts []string
reusedWorkdir bool
}
// PromptOption tunes per-turn prompt copy with run-scoped context.
@@ -105,14 +103,6 @@ func WithWorktreeReplayConflicts(files []string) PromptOption {
return func(o *promptOpts) { o.worktreeReplayConflicts = files }
}
// WithReusedWorkdir marks a turn that runs a fresh provider session inside a
// workdir an earlier run left behind: an automatic or manual retry after a
// failure that poisoned the conversation, or a resume the daemon had to drop.
// The files are there; the memory of producing them is not (MUL-7034).
func WithReusedWorkdir() PromptOption {
return func(o *promptOpts) { o.reusedWorkdir = true }
}
// buildSharedLocalDirectoryBlock warns an unlocked turn that its working
// directory is shared live. Deliberately guidance and not a prohibition: the
// mutex never covered the user's own editor either, so refusing writes here
@@ -130,24 +120,6 @@ func buildSharedLocalDirectoryBlock(shared bool) string {
return b.String()
}
// buildReusedWorkdirBlock tells a fresh session that its working directory
// already holds an earlier run's files. Nothing else says so, and the brief
// points at `multica repo checkout` for fetching code. That command keeps an
// existing checkout holding work (MUL-7284), but a session that does not know
// the work is there neither continues from it nor knows to leave `--fresh`
// alone. Per-turn, not in the brief: it is true of this run only, and the brief
// must stay byte-stable across runs (MUL-5377).
func buildReusedWorkdirBlock(reused bool) string {
if !reused {
return ""
}
var b strings.Builder
b.WriteString("## Files from an earlier run\n\n")
b.WriteString("Your working directory was kept from an earlier run, but this run does not continue that run's conversation, so you have no memory of what it did here. Repository checkouts in it may hold that work, including uncommitted changes.\n\n")
b.WriteString("Look before you fetch anything: list the working directory, and in each existing checkout run `git status` and `git log` to see what was changed. Continue from that work where it serves this task. Running `multica repo checkout` for a repository that is already checked out here keeps that checkout as it is when it holds uncommitted changes, untracked files, or unpushed commits, and only fetches. Pass `--fresh` only once you have confirmed nothing in it needs keeping: it discards uncommitted changes and untracked files and starts a new branch from the default branch, leaving commits on the old branch — push any you still need first.\n\n")
return b.String()
}
// maxConflictListBytes bounds the RENDERED file list, in bytes of the escaped
// output rather than in entries: a git path can be as long as the filesystem
// allows, so a per-entry count bounds nothing. 4 KiB is roughly a thousand
-42
View File
@@ -2071,45 +2071,3 @@ func TestWorktreeReplayConflictBlock(t *testing.T) {
}
})
}
// TestReusedWorkdirBlock covers the warning a fresh session gets when it lands
// in an earlier run's workdir (MUL-7034): it must say the files are there, that
// `multica repo checkout` keeps an existing checkout holding work, and that
// `--fresh` discards it (MUL-7284). It is appended per turn after the prompt
// body, never ahead of it. That it reaches
// the backend's prompt and not the brief is pinned end to end by
// TestRunTaskWarnsFreshSessionInReusedWorkdir.
func TestReusedWorkdirBlock(t *testing.T) {
t.Parallel()
issue := Task{IssueID: "issue-1", IssueIdentifier: "MUL-7034"}
chat := Task{ChatSessionID: "chat-1", ChatMessage: "keep going"}
if out := BuildPrompt(issue, "codex"); strings.Contains(out, "Files from an earlier run") {
t.Fatalf("reused-workdir warning rendered without the option:\n%s", out)
}
for name, task := range map[string]Task{"issue": issue, "chat": chat} {
t.Run(name, func(t *testing.T) {
out := BuildPrompt(task, "codex", WithReusedWorkdir())
block := buildReusedWorkdirBlock(true)
if !strings.HasSuffix(out, block) {
t.Fatalf("warning was not appended after the %s prompt body:\n%s", name, out)
}
if !strings.HasPrefix(out, buildPromptBody(task, "codex")) {
t.Fatalf("warning displaced the %s prompt body:\n%s", name, out)
}
for _, want := range []string{
"## Files from an earlier run",
"no memory of what it did here",
"`git status`",
"Running `multica repo checkout` for a repository that is already checked out here keeps that checkout as it is",
"Pass `--fresh` only once you have confirmed nothing in it needs keeping",
"leaving commits on the old branch",
} {
if !strings.Contains(block, want) {
t.Fatalf("warning missing %q:\n%s", want, block)
}
}
})
}
}
+12 -12
View File
@@ -2155,16 +2155,16 @@ func rerunSourceMatchesTaskScope(task, source db.AgentTaskQueue) bool {
// child: a poisoned conversation says nothing about the files it left behind,
// the same contract the manual-retry branch applies (MUL-4869, MUL-7034).
//
// The workdir is offered only to a daemon that warns the fresh session about
// the files it will find (DaemonCapabilityReusedWorkdirNoticeV1). Unwarned, the
// session follows the brief and re-runs `multica repo checkout`, which resets
// an existing checkout and deletes the work being kept, so an older daemon gets
// a fresh directory as before. The daemon validates the directory before
// reusing it and falls back to a fresh Prepare when it is gone. Either way the
// failed attempt's working memory does not come back, so the continuity gap is
// disclosed.
func applyFreshSessionRetryWorkdir(task db.AgentTaskQueue, resp *AgentTaskResponse, daemonWarnsOfReusedWorkdir bool) {
if daemonWarnsOfReusedWorkdir && task.WorkDir.Valid {
// The workdir is offered only to a daemon whose `multica repo checkout` keeps
// an existing checkout's work (DaemonCapabilityCheckoutKeepsWorkV1). The fresh
// session has no memory of that work and will fetch its repositories again;
// an older daemon's checkout resets the checkout and deletes the work being
// kept, so it gets a fresh directory as before. The daemon validates the
// directory before reusing it and falls back to a fresh Prepare when it is
// gone. Either way the failed attempt's working memory does not come back, so
// the continuity gap is disclosed.
func applyFreshSessionRetryWorkdir(task db.AgentTaskQueue, resp *AgentTaskResponse, daemonKeepsCheckoutWork bool) {
if daemonKeepsCheckoutWork && task.WorkDir.Valid {
resp.PriorWorkDir = task.WorkDir.String
}
resp.PriorSessionResumeUnavailable = true
@@ -2808,7 +2808,7 @@ func (h *Handler) buildClaimedTaskResponse(r *http.Request, task *db.AgentTaskQu
// Automatic retry that must start a fresh session: continue in the
// parent's workdir, never its session. A force_fresh task with no
// retry lineage still resumes nothing.
applyFreshSessionRetryWorkdir(*task, &resp, requestHasClientCapability(r, protocol.DaemonCapabilityReusedWorkdirNoticeV1))
applyFreshSessionRetryWorkdir(*task, &resp, requestHasClientCapability(r, protocol.DaemonCapabilityCheckoutKeepsWorkV1))
}
}
@@ -2987,7 +2987,7 @@ func (h *Handler) buildClaimedTaskResponse(r *http.Request, task *db.AgentTaskQu
// Same as the issue branch. The retry lineage is what separates this
// from a user-requested fresh start (the Lark fresh-session command),
// which still inherits nothing.
applyFreshSessionRetryWorkdir(*task, &resp, requestHasClientCapability(r, protocol.DaemonCapabilityReusedWorkdirNoticeV1))
applyFreshSessionRetryWorkdir(*task, &resp, requestHasClientCapability(r, protocol.DaemonCapabilityCheckoutKeepsWorkV1))
}
parts := make([]string, 0, len(unanswered))
+7 -7
View File
@@ -3210,10 +3210,10 @@ func createAutoRetryForTest(t *testing.T, ctx context.Context, parentID string)
// failure: a fresh session, the parent's workdir, and a disclosed continuity
// gap. The retry row comes from the real CreateRetryTask so the query and the
// claim are pinned together; the workdir reaches the daemon only when both
// carry it (GH #7998). The workdir is offered only to a daemon that warns the
// fresh session about the files it will find there; an older daemon keeps
// getting a fresh directory, because unwarned its agent would re-run
// `multica repo checkout` and reset the very checkout being kept. Contrast a
// carry it (GH #7998). The workdir is offered only to a daemon whose
// `multica repo checkout` keeps an existing checkout's work; an older daemon
// keeps getting a fresh directory, because its checkout would reset the very
// checkout being kept. Contrast a
// force_fresh task with no retry lineage, which resumes nothing
// (TestClaimTask_IssuePriorSessionRuntimeGuard).
func TestClaimTask_AutoRetryFreshSessionReusesParentWorkdir(t *testing.T) {
@@ -3227,8 +3227,8 @@ func TestClaimTask_AutoRetryFreshSessionReusesParentWorkdir(t *testing.T) {
wantWorkDir string
}{
{
name: "daemon_warns_of_reused_workdir",
capabilities: protocol.DaemonCapabilityReusedWorkdirNoticeV1,
name: "daemon_checkout_keeps_work",
capabilities: protocol.DaemonCapabilityCheckoutKeepsWorkV1,
wantWorkDir: "/tmp/codex-stuck-workdir",
},
{
@@ -3315,7 +3315,7 @@ func TestClaimTask_ChatAutoRetryFreshSessionReusesParentWorkdir(t *testing.T) {
})
createAutoRetryForTest(t, ctx, parentID)
task := claimTaskForRuntimeGuardWithCapabilities(t, runtimeID, daemonID, protocol.DaemonCapabilityReusedWorkdirNoticeV1)
task := claimTaskForRuntimeGuardWithCapabilities(t, runtimeID, daemonID, protocol.DaemonCapabilityCheckoutKeepsWorkV1)
if task.PriorWorkDir != "/tmp/codex-stuck-chat-workdir" {
t.Fatalf("PriorWorkDir = %q, want the failed parent's /tmp/codex-stuck-chat-workdir", task.PriorWorkDir)
}
+10 -10
View File
@@ -49,18 +49,18 @@ const (
// nothing extra, so the stub retires itself as daemons update.
DaemonCapabilityPlatformSkillV1 = "platform-skill-v1"
// DaemonCapabilityReusedWorkdirNoticeV1 advertises that the daemon warns a
// fresh provider session when it lands in a workdir an earlier run left
// behind (MUL-7034).
// DaemonCapabilityCheckoutKeepsWorkV1 advertises that the daemon's
// `multica repo checkout` keeps an existing checkout that holds work
// (uncommitted changes, untracked files, unpushed commits) instead of
// resetting it (MUL-7284).
//
// The server hands an automatic retry that must start a fresh session its
// parent's workdir only when this is present. That session has no memory of
// the work in the directory, and the brief tells it to fetch repositories
// with `multica repo checkout`, which resets an existing checkout and deletes
// uncommitted changes. Without the warning, reusing the directory would
// destroy the work it was meant to keep, so an older daemon keeps getting a
// fresh directory and the parent's stays untouched on disk.
DaemonCapabilityReusedWorkdirNoticeV1 = "reused-workdir-notice-v1"
// parent's workdir only when this is present (MUL-7034). That session has no
// memory of the work in the directory and will fetch its repositories again.
// An older daemon's checkout resets an existing checkout and deletes that
// work, so such a daemon keeps getting a fresh directory and the parent's
// stays untouched on disk.
DaemonCapabilityCheckoutKeepsWorkV1 = "checkout-keeps-work-v1"
// AppCapabilityChatDraftRestoreV1 is advertised (X-Client-Capabilities) by
// app clients that understand the durable draft-restore recovery path: