Skip to content

feat(server): send a message to a thread when it settles - #2

Open
bogorman wants to merge 1 commit into
mainfrom
settle-prompt
Open

bogorman wants to merge 1 commit into
mainfrom
settle-prompt

Conversation

@bogorman

Copy link
Copy Markdown
Owner

Problem

Settling means "this thread is done", but the agent has no chance to wrap up: summarise what it did, note what's left,
or report it somewhere. The only settle hook today is the project settle script (pingdotgg#16290). That's a shell command, it runs
after the thread is parked, and it skips threads in the shared checkout.

Change

A new project-scoped setting, Message on settle (settlePrompt, empty by default), under Thread behavior.
When a thread settles (by hand, after inactivity, or on merge), the thread gets that message, for example a skill such as
/wrap-up, as one more turn. When the turn ends, the thread settles again, and settle cleanup (idle shells, the settle
script) runs after that.

  • Empty: settling is unchanged.
  • Once per settlement: a re-emitted thread.settled with the same settledAt sends nothing more.
  • Timeout: a turn still running after 10 minutes is interrupted, then the thread settles.
  • Waiting on the user: if the turn leaves the thread blocked (a question, an approval, a queued message), the
    follow-up settle is refused and the thread stays active for them.
  • Skipped: archived threads and threads that take no messages (dispatch fails, it's logged, and the thread settles
    as before).
  • Where it lives: in ThreadSettlementServiceV2, keyed off the thread.settled and run.* events, so manual,
    automatic and agent-initiated settles all go through it.
  • Settings and docs: the field is searchable and project-overridable; the docs are in thread-sidebar.md.

While the wrap-up turn runs, the thread is briefly active (sending a message re-engages it), then it settles again.
Mobile settings don't show the field yet. The server honours it either way.

Testing

  • ThreadSettlementService.test.ts has 3 new tests:
    • the prompt is sent, then the thread settles again when its turn ends, then cleanup runs
    • the prompt is sent once when a settlement is re-emitted
    • a turn past the timeout is interrupted, then the thread settles
  • Server: 5,498 tests pass and 8 fail. The same 8 fail on unchanged main on this machine (file-system and sandbox
    tests). Contracts: 644 pass. Web: 6,599 pass. Type checks and format are clean.
  • Manual check in the desktop app is still to do.

🤖 Generated with Claude Code

A new project-scoped setting, Message on settle (`settlePrompt`, empty by default), holds a
message, such as a skill, that a thread gets as one more turn when it settles by hand or
automatically. The thread settles again when that turn ends; settle cleanup (idle shells, the
settle script) runs after that second settle. Empty keeps settling exactly as before.

- once per settlement: a re-emitted thread.settled sends nothing more
- a turn that runs past 10 minutes is interrupted, then the thread settles
- if the turn leaves the thread waiting on the user (question, approval, queued message),
  the follow-up settle is refused and the thread stays active
- archived threads and threads that take no messages skip it
- settings row under Thread behavior, searchable; docs in thread-sidebar.md

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.

1 participant