Bundle
dsh-goal-restart
Automatically re-arm active goals when the dsh service (re)starts, so the goal-round driver resumes rounds without human intervention.
- Source
- joshryandavis
- License
- MIT
- Updated
- Updated 6 days ago
Readme
English | [中文](README.zh.md)
# dsh-goal-restart
Re-arm persisted same-session goals automatically when the dsh service
(re)starts, so the [goal-round driver](https://github.com/deepseek-ai/deepseek-harness)
resumes rounds without human intervention.
> **Why?** When an agent is doing long-running work — like developing its own
> plugins — and the service it lives in gets restarted (crash, launchd
> respawn, a deliberate bounce), the in-flight goal used to stay stuck until
> somebody ran `/goal resume`. This plugin removes that step.
## The problem
A dsh goal's **durable state** (objective, phase, revision, `roundsStarted`)
lives in the session log and survives restarts. Its **activation** ("armed")
is deliberately process-local: it is never persisted, and every
`agent/session-start` edge disarms it. So after the dsh service restarts, an
in-flight goal is replayed as `active` but stays stopped until someone issues
an explicit resume.
## What this plugin does
On `agent/session-start` where `payload.source === 'resume'` (the session was
just loaded from persistence), it calls `ctx.goals.resume(agent, ref)` for a
durable-`active` goal that still has round budget. The stock
`goal-round-driver` (mounted by `dsh-base`) then reserves and queues the next
round exactly as it would after a normal human resume — but nobody had to
click anything.
## Policy (conservative, in one table)
| Situation | Action |
| ------------------------------------------------- | --------------------------- |
| Session rehydrated after a service restart, goal `active`, budget left | re-arm (`ctx.goals.resume`) |
| Session started fresh (`source: 'startup'`) | skip (no goal) |
| Forked session (inherited goal) | skip (in-process lineage) |
| Subagent session (`origin: subagent`) | skip (in-process lineage) |
| Goal `paused` / `blocked` / `complete` | skip (durable phase wins) |
| Goal `active` but already `armed` | skip (idempotent) |
| Goal at `roundsStarted >= maxGoalRounds` | skip (no budget — raise the cap, then resume) |
## Install
```sh
dsh plugin --profile <profile> add dsh-goal-restart
```
Then restart the dsh service so the new bundle is loaded.
## Disable
In the profile's `cordis.patch.yml`:
```yaml
- id: goal-restart
disabled: true
```
## Notes
- Re-arming writes one durable `resume` mutation (revision +1) into the
session log — the domain's documented reactivation edge, and the same
write a human `/goal resume` performs.
- The round driver already handles durability and cancellation safety; this
plugin only decides *that* continuation is wanted, not *how* it runs.
- Sessions resume when a live agent loads them. In the web GUI that happens
when the conversation is reopened after restart; re-arming occurs at that
moment, before the driver's first idle checkpoint.
- The policy is verified by 13 in-memory unit tests (`npm test`) and a smoke
script (`npm run smoke`) that need no network and no live process.
## License
[MIT](LICENSE)
Install
dsh plugin --profile web add github:joshryandavis/dsh-goal-restart
Profile: web
With the hub plugin installed, ask your agent to install it by name — it resolves the same plan shown here.
dsh plugin --profile web add github:stvlynn/dsh.fish#path:packages/dsh-plugin-hub
install dsh-goal-restart from the hub
- This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.