Skip to content

Assign and dispatch tasks to agents - #120

Merged
smarzban merged 309 commits into
mainfrom
dispatch
Oct 21, 2026
Merged

smarzban merged 309 commits into
mainfrom
dispatch

Conversation

@smarzban

@smarzban smarzban commented Sep 22, 2026 •

Copy link
Copy Markdown
Owner

Ships the agents feature as v0.12.0. You assign a task to an agent, dispatch it into its own Git worktree and Herdr workspace, then clean up when you complete the task.

What ships

  • Agent profiles: [agent.<name>] tables in <state dir>/config.toml. Each has an argv command template, an optional prompt, and optional env. Templates use the {number} {title} {notes} {steps} {worktree} {branch} {base} placeholders. Profiles without their own prompt get a default prompt: work only on the branch, open a PR into the base without merging, then set the task to review or blocked. The first board open seeds a commented starter file.
  • Assign: !a name, @ (board, peek, task page), the task page's Assignee field and footer, palette set assignee (also on marked sets), and tsk add/edit --assignee. Filter by assignee with the project board's t Filter (threads · @assignees) or a Projects v view per assignee. / search and tsk list --assignee match assignees too.
  • Dispatch: ctrl+g, palette, or tsk dispatch T<n>. It creates a branch, worktree, and Herdr workspace named after the task, launches the agent (named t<n>-<assignee>), and records the dispatch and sets started in one save. An unassigned task asks for an agent first. A marked set gets one confirm card and launches in the background. Relaunch with a second ctrl+g, dispatch again, or --again. A live dispatch shows ◉. Requires Herdr on macOS or Linux; Windows refuses with unsupported-platform.
  • Base branch: !b, the task page's ⎇ footer or Base field, palette set base, or --base. Without one, dispatch uses the repository's origin/HEAD, never the current checkout. The branch picker opens on cached refs and refreshes after a background fetch. Dispatch, the picker, and cleanup share a 60-second fetch window.
  • Complete and clean up: ctrl+d on a live dispatch opens a card showing merged status. y completes at once and, in the background, removes the worktree and workspace, and deletes the branch only if it is merged into the recorded base. A marked set gets one card and one undo step. Uncommitted work is never touched. Any branch whose merge cannot be confirmed is kept, with a reason. Scripts use tsk clean T<n> [--json] and tsk status T<n> done --clean.

Breaking: store format v6 adds task assignees, base branches, and dispatch records. A v5 store migrates on first save and keeps tsk.json.v5; older binaries refuse a v6 store, so restoring tsk.json.v5 is the rollback.

Version bump to 0.12.0, the v0.12.0 changelog section, the board announcement, and the release docs pass land via #152 into dispatch.

Verification

  • CI on the current dispatch head (e78cb60) is green: Verify on macOS, Ubuntu, Windows x86-64 and ARM64; parity; site build; installer Windows smokes.
  • Each feature PR into dispatch got the local green bar (fmt, clippy -D warnings, cargo test), Windows-gnu clippy, site tests (with parity for UI/site changes), and an independent review before merge.
  • Dispatch and cleanup go through the DispatchHost seam, which has fake-host unit and integration coverage. Dispatch has been dogfooded through Herdr against real repositories to build this feature.

@vercel

vercel Bot commented Sep 22, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
herdr-tsk Ready Ready Preview Oct 21, 2026 7:40pm UTC

@smarzban smarzban changed the title Assign and dispatch tasks to agents (store v6) Assign and dispatch tasks to agents Sep 22, 2026
@mruderman

Copy link
Copy Markdown

Very much looking forward to this PR, let me know if you need any testers for Linux! Thank you!

…rd-and-dispatch-fe

T164: open picker and cleanup card from cached refs, share a 60s fetch window
Slug keeps whole title words up to 30 characters (hard-cut a longer first word), none
for a symbols-only title. Workspace label is T<n> plus the kept words, with an ellipsis
when cut. A taken local/remote branch or worktree directory gets -2, -3; a failed check
refuses. Recorded names are reused on --again.
…nicode slugs, occupied checkout dirs

- Words are runs of letters/digits in any script; symbol-only text costs nothing.
- The label is the original title up to the slug's cut (same words, same hard-cut point).
- Slugs keep Unicode letters and digits, counted in chars; Herdr's ASCII-only directory
  name is mirrored for the collision check.
- A directory already at Herdr's checkout path, registered or not, is a collision.
- Tests: --again keeps recorded names after a retitle without probing; first dispatch hands
  the cut label and suffixed branch to Herdr and the agent.
…h-worktree-and-wor

T154: shorter dispatch branch, worktree, and workspace names
* Hide agent messages under board rows with z (T305)

z hides every board row's message line for the session and marks rows that had one with ✉; the palette offers hide/show agent messages. [board] messages = "hidden" in config.toml opens the board hidden. Web demo uses shift+Z (z is its drawer).

* Keep assignee_label_shown's doc comment on it (T305 F-1)

* Regenerate hidden-message goldens for the ': commands' footer (T305)
* Ship the tsk-coordinator skill with tsk setup (T312)

* Quote the coordinator skill description; YAML-parse every skill's frontmatter; test coordinator symlinks and --json skills (T312 review)

* Compare the --json skill path separator-agnostically for Windows (T312 review)
… task (T285) (#237)

* After picker: search box with pinned tasks, clear works; before numbers open their task (T285)

* Docs: the task picker query is one word (Space pins)

* Task picker review fixes: wrap rows, keep the cursor off clear all, no archived before links (T285)

* Point the page-targeting comment at the reducer prelude (T285)

* After picker keys: Enter pins, ctrl+x clears, shift+Enter saves; typed spaces search (T285)

* After picker: shift+Enter is the save in the comment and keys table (T285)
* Fix flaky test root causes (T233)

- PTY children drop inherited HERDR_* env, so a sibling test's plugin context never opens the board on its project
- setup_agent lib test injects its search path instead of swapping PATH for every concurrent git spawn
- backup waiter test unlocks its slot instead of closing it, so a child spawned meanwhile cannot keep the lock
- base picker test releases its fake transport and waits for the cancelled lookup before removing the repo
- demo repaint keeps the focused field's selection, so keys after a resize land where they were typed
- npm test builds dist once up front; the agents page sync skips unchanged pages and replaces changed ones whole

* Bound the base picker fake transport's wait; ignore page sync temp files (T233)
…res as v6 (T313) (#241)

* Collapse dispatch store bumps v6..v15 into one v5->v6; open dev v7..v15 stores as v6 (T313)

* Store module doc: older and dev versions open
…capture (T314) (#243)

* Backup URLs: redact credentials everywhere; restore id past 20; help capture (T314)

- sanitized_config strips URL credentials from inline backup lists too, via one
  traversal shared with the loader
- every printed target location and git error shows credentials as ***;
  backup remove takes the shown form
- backup add takes the run lock; clone and set-url pass -- before the URL
- tsk restore <id> searches every version; a bare number refuses with a hint
- tsk help capture / tsk capture --help print a reference
- docs: storage.md credentials section, cli.md restore exit 3

* Rewrap remove_target doc comment

* Review fixes: char-safe redaction, whole passwords, usage errors, ambiguous remove, stored errors, -- test (T314)

- redacted() rewrites only a URL's authority and never slices mid-character
- clean locations print through shown_location directly
- usage errors redact URLs
- backup remove refuses a *** form that names two targets
- every recorded or printed git error goes through target_error, which also hides
  userinfo git quotes outside a URL (git:// lookups)
- tests for each, including a --upload-pack URL

* Review pass 2: redact an unknown version id; set-url -- regression; repo_contents and read_version through target_error (T314)
…e-dir (#244)

* No duplicate task numbers after restore; capture honours --state-dir (T316)

* Capture help and cli.md show --state-dir; other capture arguments refuse with the reason (T316 review)
… or env value typed (T315) (#242)

* Dispatch: launch Unix agents through a private launcher, never typed task text (T315)

The pane now types only /bin/sh "<state>/launchers/dispatch-<ws>.sh". The script
re-runs itself through $SHELL -l -c with a fixed string for the login environment,
deletes itself, and execs the argv with env values. Task text and env values never
reach the pane's shell parser or history, whatever the shell (audit F-25, F-26, F-6,
F-27); a test pins env values out of the stored record (F-23).

* Dispatch launcher: env as sh exports, POSIX key check, Unix unsafe-state-dir docs (T315 review)

- Stage 2 exports each env value as a shell assignment instead of env(1)
  arguments, so no value sits in any process argv (F-1). A key sh cannot
  export refuses agent-config before anything is created.
- The login-shell stand-in puts the agent on a login-only PATH and the
  profile names it bare (F-10).
- Unix cleanup removing the launcher is tested (F-11).
- cli.md, presenter help: unsafe-state-dir applies on every platform (F-4);
  storage.md says the program must be an executable on the login PATH (F-16).
…319) (#247)

* Final docs pass before #120: docs vs code, CHANGELOG, What's new 6, llms.txt, landing, skill (T319)

* tsk --help: edit names who it waits on; backup takes several repositories (T319)

* Docs pass review fixes: cleanups/ refuses not resumes, HERDR_CONFIG_PATH in update rehearsal, After changelog line within 30 words (T319)
…sh purge unlinks once (T320) (#248)

* Restore: a stale snapshot cannot save over a whole-store restore; trash purge unlinks once (T320)

* Restore review: status-done tail checks the done's token; restore refusals name the next step (T320)

* Skill: the dispatch exit-3 line says, not ends with, 'the agent may still run' (T320)
This was referenced Oct 21, 2026
…n, --show-prompt (T231) (#253)

* Agent prompt: generic default with {on}, prompt_append layers, [project] review_on, dispatch --show-prompt (T231)

* show-prompt: resolve base and branch like a dispatch, from cached refs; test --base and a dispatched record (T231 review)

* Starter config: every setting with its options and default, error rule, kind, --show-prompt (T231)

* Starter config: backups copy on save or daily; define both every values (T231)

* Starter config: maintainer's section layout, new examples, defaults as commented examples (T231)
) (T321) (#254)

* Board: ctrl+s starts a blocked task; a cursor task it cannot start says why (#252)

* Sort the project picker and Projects view by name or age (#250); docs, demo, goldens

* Project picker keeps one width across orders; help row and palette sort on Projects view

* ctrl+s on a notice stays silent; ctrl+s dispatches a never-dispatched blocked task (test)
* Backups: a broken [[backup]] config shows on the board status row (T325)

* Backups: redact [[backup]] values before quoting them in config errors; [board] guard test (T325)

This branch was successfully deployed

1 active deployment
Preview — ffeaf695 Deployed Oct 21, 2026 by vercel[bot]
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.

2 participants