@oisin-ee/pi-dogsled 0.0.0-stage → 0.13.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +522 -2
- package/package.json +54 -4
- package/pi/board.ts +168 -0
- package/pi/inbox.ts +149 -0
- package/pi/index.ts +306 -0
- package/pi/panel.ts +227 -0
- package/pi/work-history.ts +33 -0
- package/pi/work-panel.ts +213 -0
- package/pi/work-todo.ts +200 -0
- package/pi/work.ts +46 -0
- package/plugins/dogsled/skills/dogsled/SKILL.md +115 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Oisín
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,523 @@
|
|
|
1
|
-
#
|
|
1
|
+
# dogsled
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Host status and placement for coding agents across [Herdr](https://herdr.dev) hosts.
|
|
4
|
+
|
|
5
|
+
Dogsled measures hosts, starts Pi, Claude, and Codex children and jobs on the host with room, queues work when every host is full, and carries every message between agents through an inbox. Nothing types into an agent's terminal.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
Install the binary on each Herdr host. Use the same release tag in each command.
|
|
10
|
+
|
|
11
|
+
Binary:
|
|
12
|
+
|
|
13
|
+
```sh
|
|
14
|
+
mise use github:oisin-ee/dogsled@v0.13.0
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Pi (extension, tools, and skill), from npm or as part of `@oisin-ee/oisinpi`:
|
|
18
|
+
|
|
19
|
+
```sh
|
|
20
|
+
pi install npm:@oisin-ee/pi-dogsled@0.13.0
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
At session start the extension compares its version with `dogsled --version` and warns when they differ.
|
|
24
|
+
|
|
25
|
+
Claude Code (hooks, tools, and skill):
|
|
26
|
+
|
|
27
|
+
```sh
|
|
28
|
+
claude plugin marketplace add oisin-ee/dogsled#v0.13.0
|
|
29
|
+
claude plugin install dogsled@dogsled
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Codex (hooks, tools, and skill):
|
|
33
|
+
|
|
34
|
+
```sh
|
|
35
|
+
codex plugin marketplace add oisin-ee/dogsled --ref v0.13.0
|
|
36
|
+
codex plugin add dogsled@dogsled
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Codex requires review and trust before it runs plugin hooks. See the [Codex hooks documentation](https://developers.openai.com/codex/hooks#plugin-hooks).
|
|
40
|
+
The [Codex CLI reference](https://developers.openai.com/codex/cli/reference#codex-plugin) describes plugin installation.
|
|
41
|
+
|
|
42
|
+
Herdr (status-board popup):
|
|
43
|
+
|
|
44
|
+
```sh
|
|
45
|
+
herdr plugin install oisin-ee/dogsled --ref v0.13.0 --yes
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Harness plugins use the binary on `PATH`. They do not install it or start host services.
|
|
49
|
+
|
|
50
|
+
## Commands
|
|
51
|
+
|
|
52
|
+
```sh
|
|
53
|
+
dogsled serve # local measurements every 10 seconds
|
|
54
|
+
dogsled serve --interval 20 # change the interval, in seconds
|
|
55
|
+
dogsled serve --once # publish and run each action lane once
|
|
56
|
+
dogsled status # hosts, agents, and reservations
|
|
57
|
+
dogsled status --json
|
|
58
|
+
dogsled status --line # one line for the tab row
|
|
59
|
+
dogsled status --brief # at most six lines for prompt hooks
|
|
60
|
+
dogsled status --watch # refresh until interrupted
|
|
61
|
+
dogsled place --json # reserve the host with the most headroom
|
|
62
|
+
dogsled place --host netcup --json # pin by host id or label
|
|
63
|
+
dogsled place --branch feat/unit-a --base main --repo /path/to/repo --json
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Exit codes: 0 success, 1 queued without waiting, 2 error. Job waits return the job's exit code.
|
|
67
|
+
When every host is full, `place`, `agent`, and `run` print `{"queued":true,"ticket":"…"}`.
|
|
68
|
+
`--wait --max 30m` waits for admission. A wait that reaches its deadline prints `still running` and exits 124.
|
|
69
|
+
|
|
70
|
+
## Jobs, agents, and owners
|
|
71
|
+
|
|
72
|
+
```sh
|
|
73
|
+
dogsled run --wait -- sh -c 'echo hi; exit 3'
|
|
74
|
+
dogsled run --host netcup --cwd /tmp --timeout 1h --idle-timeout 10m -- make test
|
|
75
|
+
dogsled run --branch feat/job --base main --cwd /path/to/repo -- cargo test
|
|
76
|
+
dogsled ps --all
|
|
77
|
+
dogsled logs JOB --follow
|
|
78
|
+
dogsled stop JOB
|
|
79
|
+
dogsled wait JOB --max 30m
|
|
80
|
+
dogsled agent --kind codex --name reviewer --message 'Review the change' --branch feat/review --base main
|
|
81
|
+
dogsled agent --profile general --name api-dups --message-file task.md --branch feat/api-dups
|
|
82
|
+
dogsled board
|
|
83
|
+
dogsled read api-dups
|
|
84
|
+
dogsled send api-dups --message 'Also cover the empty case.'
|
|
85
|
+
dogsled track netcup w1:p2 --name child
|
|
86
|
+
dogsled items --owner "$HERDR_PANE_ID" --json
|
|
87
|
+
dogsled cancel TICKET
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Jobs use a new tab in the caller's workspace. With `--branch`, an agent uses the pane of the worktree's new Herdr workspace.
|
|
91
|
+
Remote work uses a workspace with the same name as the caller's workspace, creating it when absent.
|
|
92
|
+
Without a branch, a remote non-repository `--cwd` must exist there.
|
|
93
|
+
Repository directories map to the same path relative to home. A linked-worktree caller needs `--branch` to preserve its branch remotely.
|
|
94
|
+
|
|
95
|
+
The pane runs `dogsled exec ID -- COMMAND`. Output goes to the pane and `jobs/ID.log` on that host.
|
|
96
|
+
If the pane output closes, capture continues to the log and preserves the child exit code.
|
|
97
|
+
The atomic `jobs/ID.json` contains the command, directory, host, owner, exit code, signal, reason, and millisecond timestamps.
|
|
98
|
+
After the job ends, `exec` saves this final record, reports completion, then closes its own pane and tab.
|
|
99
|
+
`wait` reads the final record, and `logs` reads the saved output after the tab closes.
|
|
100
|
+
If the close fails, `exec` logs the error to stderr without changing the result. Prune can close the ended job tab later.
|
|
101
|
+
`host.json` includes job records. `ps --all` includes completed jobs and reads remote records through the snapshot cache.
|
|
102
|
+
`logs`, `stop`, and `wait` use the configured SSH transport for remote jobs.
|
|
103
|
+
`stop` requests a process-group kill. Timeouts and wrapper termination also kill the process group.
|
|
104
|
+
Both timeout defaults are unlimited. Durations accept integer `ms`, `s`, `m`, and `h` suffixes.
|
|
105
|
+
The sidebar shows `working`, then `idle` for success or `blocked` for failure, with a `dogsled` exit or timeout token.
|
|
106
|
+
|
|
107
|
+
`--max` sets one deadline from command startup, including discovery, placement, admission, and job completion. It defaults to 30 minutes.
|
|
108
|
+
Operations use the remaining command budget, capped at 30 seconds for routine calls and locks, or 10 minutes for setup.
|
|
109
|
+
Setup includes worktree creation and `setup` commands, repository clones, mise trust checks, and agent startup, locally and through SSH.
|
|
110
|
+
A non-waiting action reports the operation that exceeded its deadline.
|
|
111
|
+
`logs --follow` can continue indefinitely, but each remote read has a 30-second limit.
|
|
112
|
+
Run long waits through the harness's background-task facility.
|
|
113
|
+
A wait deadline does not cancel its job or ticket. `cancel` only cancels pending tickets.
|
|
114
|
+
|
|
115
|
+
### Agents and profiles
|
|
116
|
+
|
|
117
|
+
`dogsled agent` starts a child with `herdr agent start <name> --kind pi|claude|codex --pane <pane> -- <args>`. The task is a launch argument, so nothing is typed into the new pane.
|
|
118
|
+
A task with a newline, a leading `-` or `@`, or more than 4000 characters goes to `launches/<id>.task.md`. Pi reads it as `@<file>`; Claude and Codex get a one-line pointer to it.
|
|
119
|
+
`--message-file PATH` (or `-` for stdin) reads the task from a file.
|
|
120
|
+
A failed `herdr agent start` is retried with backoff, three tries in all. After the last, the ticket fails and the owner's inbox says so. A refusal or a deadline fails at once.
|
|
121
|
+
|
|
122
|
+
`--profile NAME` (Pi only) reads `~/.config/dogsled/profiles/NAME/profile.json` on the host that runs the child:
|
|
123
|
+
|
|
124
|
+
```json
|
|
125
|
+
{"description": "Ordinary units", "model": "alias/sol", "thinking": "medium", "prompt": "prompt.md", "role": "writer", "pi_args": []}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
The child gets `--model`, `--thinking`, `--append-system-prompt <prompt>`, then `pi_args`. Unknown keys are ignored, so Shepherdr profiles load as they are.
|
|
129
|
+
`role` is `reader` or `writer`. Without it, a child with `--branch` is a writer, and any other child a reader.
|
|
130
|
+
`dogsled profiles` lists them; a broken profile shows as `broken: <reason>`.
|
|
131
|
+
|
|
132
|
+
### Items and closing
|
|
133
|
+
|
|
134
|
+
The owner's host stores locked `items.json` and `queue.json` files.
|
|
135
|
+
An item records its host, pane, owner pane, creation time, closure time, and for an agent its harness, profile, model, role, and captured final reply.
|
|
136
|
+
`items --json` returns `{items,queue}`. `--owner` filters both collections.
|
|
137
|
+
The service closes a job item after job completion, and any item after pane removal.
|
|
138
|
+
|
|
139
|
+
Closing is driven by events. When a child's turn completes (Herdr's `completion_seq` goes up) and it is `idle` or `done`, the sweep:
|
|
140
|
+
|
|
141
|
+
1. reads its final reply from the transcript and keeps it in the item;
|
|
142
|
+
2. puts the reply in the owner's inbox (see [Inbox](#inbox));
|
|
143
|
+
3. closes a reader whose worktree is clean with no commits outside the default branch, and any child whose branch has landed.
|
|
144
|
+
|
|
145
|
+
A child with commits to land stays open and shows under TO LAND on the board, and the prompt line says `To land: web-tests (+2)`. Merge or drop the branch; the next sweep closes it.
|
|
146
|
+
A `blocked` child stays open, and the owner's inbox gets one `blocked` record per episode. A `working` child, or one that has never completed a turn, is never closed. Nothing closes on a timer.
|
|
147
|
+
|
|
148
|
+
`dogsled board` groups an owner's children, jobs, and queued tickets by what the owner must do: TO LAND, ATTENTION, RUNNING, and WAITING. Each agent row names the harness and model; each job row names its command. `--json` is what the Pi widget draws.
|
|
149
|
+
`dogsled read TARGET [--host H]` shows a child's or job's newest output and the captured final reply.
|
|
150
|
+
|
|
151
|
+
```sh
|
|
152
|
+
dogsled close w2:p1
|
|
153
|
+
dogsled close w9:p1 --host netcup --json
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
`close` ends a child now, for an owner who does not want to wait for the sweep. `--host` defaults to the host of the pane's open item, else local.
|
|
157
|
+
In an agent worktree (locked `agent:worktree`, as dogsled makes them), it runs the repository's `teardown` commands in the worktree (see [Repository configuration](#repository-configuration)).
|
|
158
|
+
Then it closes every pane that uses the worktree and the Herdr workspace that shows it, unlocks the worktree, and runs `git worktree remove` without force.
|
|
159
|
+
It deletes the branch only when dogsled's integration check finds it integrated (see [Cleanup](#cleanup)). An unmerged branch, or a branch still at the base tip, stays.
|
|
160
|
+
When `place` opened the main checkout's workspace as the anchor and no linked worktree is open in Herdr any more, close closes that anchor too. It does so only while the anchor is unfocused, is not the caller's, and has one pane with no agent.
|
|
161
|
+
A pane outside a worktree, or in an unlocked worktree (someone's own checkout), is closed alone; the checkout stays.
|
|
162
|
+
A child tab in the caller's own workspace is closed. Close refuses a missing pane, the caller's own pane, a worktree the caller works in or whose workspace is the caller's, a worktree outside the repository's worktree directory, a dirty or detached worktree, and any other lock.
|
|
163
|
+
It also refuses a busy target or a busy pane that uses the worktree: an agent that is not `idle` or `done`, or a shell with a foreground command.
|
|
164
|
+
Each refusal happens before a change. If a `teardown` command fails, the worktree, its panes, its lock, and the item stay, and the error shows the command's last lines of output.
|
|
165
|
+
After removal, close drops the worktree's registration, as prune does.
|
|
166
|
+
The JSON result is `{pane,worktree:{path,branch,workspace,branch_deleted,anchor_closed?}|null,pane_closed}`. A remote host runs the same steps over SSH.
|
|
167
|
+
|
|
168
|
+
The service admits tickets in FIFO order using the same placement policy.
|
|
169
|
+
It records an admission error rather than silently choosing another host after a clone, prepare, or launch failure.
|
|
170
|
+
A service interruption during admission leaves an explicit failed ticket for inspection, not an automatic duplicate launch.
|
|
171
|
+
For non-waiting callers, admission tells the owner through its inbox. An owner without an inbox reader hears once it has one; nothing is typed into its terminal.
|
|
172
|
+
`status` lists open items per owner and pending tickets. `--brief` includes their counts. Prompt context adds the caller's own `To land:` line.
|
|
173
|
+
|
|
174
|
+
## Inbox
|
|
175
|
+
|
|
176
|
+
Every message to an agent goes through one inbox on the agent's host: a child's final reply, a blocked report, an admitted ticket, a launch failure, and a message from another agent.
|
|
177
|
+
|
|
178
|
+
```sh
|
|
179
|
+
dogsled send api-dups --message 'Also cover the empty case.'
|
|
180
|
+
dogsled send w9:p1 --host netcup --kind task --message-file note.md
|
|
181
|
+
dogsled inbox list
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
`send` resolves a name or pane on any host and writes the record there, over SSH for a peer. A target with no inbox reader fails at once, and the sender hears so; a record never waits where nothing reads it.
|
|
185
|
+
Records live in `inbox/<terminal>.json`, keyed by Herdr's terminal id, so a record follows the terminal and not a reused pane id.
|
|
186
|
+
A reader claims records with `inbox claim`, which is a lease. A claimed record is offered again with backoff until `inbox ack` marks it delivered. When the terminal is gone, the record fails and the sender's own inbox says so.
|
|
187
|
+
|
|
188
|
+
Readers:
|
|
189
|
+
|
|
190
|
+
- **Pi:** the extension watches its inbox file, injects each batch as one `dogsled` message (`steer` while the agent runs, a new turn when it is idle), and acknowledges it when Pi has written the message to the session.
|
|
191
|
+
- **Claude Code and Codex:** `dogsled hook inbox --harness claude|codex --event Stop|UserPromptSubmit`, registered by the plugin. The first hook run registers the reader. At `Stop`, records continue the turn as `{"decision":"block","reason":…}`; at `UserPromptSubmit`, they go beside the user's text as `additionalContext`. Records printed are acknowledged. At `Stop`, the same response also includes a new reminder about finished children with work to land. It prints nothing when neither is pending.
|
|
192
|
+
|
|
193
|
+
A hook runs only when its harness acts, so an idle Claude Code or Codex agent sees a record at its next prompt or stop. Pi has no such delay.
|
|
194
|
+
|
|
195
|
+
`inbox list --json` gives `{pane,terminal,received,sent,lines}`; `lines` is the display form the Pi panel shows.
|
|
196
|
+
|
|
197
|
+
### Backoff
|
|
198
|
+
|
|
199
|
+
One schedule is used for inbox leases, the sender's follow-up, peer reads, and launch retries: 10 seconds, doubling with jitter, capped at 5 minutes.
|
|
200
|
+
A host that cannot be read shows `retry in 40s` on the board. `dogsled retry HOST` reads it again now.
|
|
201
|
+
|
|
202
|
+
## Host service and status
|
|
203
|
+
|
|
204
|
+
Run `dogsled serve` on every host. Dotfiles owns launchd and systemd user-service installation.
|
|
205
|
+
The measurement step uses no SSH. It reads CPU busy time, cores, memory, home disk space, Herdr agents, and Herdr panes.
|
|
206
|
+
When it has owned items or tickets, the service reads peers through the status cache and can launch admitted work through SSH.
|
|
207
|
+
Separate watchdog, admission, sweep, and inbox workers keep check-ins, slow setup, cleanup, and delivery independent from snapshot publication. Routine calls and lock waits have 30-second limits. Setup calls have a 10-minute limit.
|
|
208
|
+
An admission timeout records a failed ticket. The service continues publication and later actions.
|
|
209
|
+
It writes `~/.local/state/dogsled/host.json` through atomic replacement.
|
|
210
|
+
Each `probe.agent_panes` entry contains `pane`, `agent`, `state`, `name`, `transcript`, `transcript_modified`, `terminal_id`, `completion_seq`, `cwd`, the session's model and latest activity, and the worktree's branch, commits ahead, dirty state, and whether it landed.
|
|
211
|
+
Transcript paths come from Herdr path sessions. Exact Claude and Codex session IDs also resolve against their standard session directories.
|
|
212
|
+
Ambiguous, absent, or unreadable transcripts remain unstalled. Modification times use Unix milliseconds.
|
|
213
|
+
Each pane also has `stalled_since_ms` and `state_since_ms`. The latter records the start of the observed state.
|
|
214
|
+
The service stops with an error if a measurement fails. The last complete snapshot remains available.
|
|
215
|
+
|
|
216
|
+
On Linux, the smallest finite `memory.max` from the process cgroup through its ancestors governs memory.
|
|
217
|
+
Used memory is that scope's `memory.current` minus `inactive_file` from `memory.stat`.
|
|
218
|
+
Without a finite limit, memory comes from `/proc/meminfo`: total minus `MemAvailable`.
|
|
219
|
+
With a finite limit, the probe measures both and reports the scope with less free memory.
|
|
220
|
+
On macOS, memory comes from `vm_stat` and `sysctl hw.memsize`, and `pressure_level` from `sysctl kern.memorystatus_vm_pressure_level` (1 normal, 2 warn, 4 critical).
|
|
221
|
+
|
|
222
|
+
CPU busy is the fraction of the last interval that the CPUs were not idle.
|
|
223
|
+
On Linux the probe records cumulative `/proc/stat` ticks (`cpu_ticks`); the service derives `busy` from the previous snapshot, so the first tick after start has no sample and admits nothing.
|
|
224
|
+
On macOS `busy` comes from a one-second `iostat -c 2 -w 1` window.
|
|
225
|
+
`load1` stays in the probe for display. It no longer takes part in admission.
|
|
226
|
+
|
|
227
|
+
Every tick appends one line to `~/.local/state/dogsled/samples.jsonl`: time, cores, busy, load1, memory, pressure level, disk, reservations, live agents, free cores, and the admission verdict. Lines older than seven days are dropped on append.
|
|
228
|
+
|
|
229
|
+
`status` reads the local snapshot and each enabled Herdr peer's snapshot.
|
|
230
|
+
Peer reads run in parallel through SSH and the configured `remote_command`.
|
|
231
|
+
A shared, locked cache permits at most one read per peer per ten seconds, including concurrent callers.
|
|
232
|
+
Status never probes peers itself.
|
|
233
|
+
|
|
234
|
+
A missing snapshot, failed read, or snapshot older than 30 seconds shows `service: down`.
|
|
235
|
+
The last peer measurement remains visible when available. Every discovered host stays in the output.
|
|
236
|
+
The JSON output contains `hosts`, with service state, reachability, sample time, probe, headroom, errors, and `retry_ms` while a peer read backs off.
|
|
237
|
+
|
|
238
|
+
```sh
|
|
239
|
+
dogsled machine list
|
|
240
|
+
dogsled machine rename ID LABEL
|
|
241
|
+
dogsled machine disable ID
|
|
242
|
+
dogsled machine reconnect ID # a new tab, for SSH prompts
|
|
243
|
+
dogsled machine add user@host --label name
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
Hosts are Herdr's saved machines. `machine` runs the matching `herdr machine` command; `reconnect` and `add` run it in a new focused tab, so the user can answer SSH prompts.
|
|
247
|
+
|
|
248
|
+
Example tab-row output:
|
|
249
|
+
|
|
250
|
+
```text
|
|
251
|
+
local 11/12 ▲ · netcup 3/16 · momokaya-2 1/7
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
`▲` means not eligible. `?` means the snapshot is missing, stale, or unavailable.
|
|
255
|
+
A host without measurements prints `momokaya-2 ?`. A stale host keeps its last numbers, followed by ` ?`.
|
|
256
|
+
The numbers are busy cores over cores. A host without a CPU sample shows `load N/cores` instead.
|
|
257
|
+
`--brief` includes busy/cores, memory, disk, agent counts, and a hint to run `dogsled status`.
|
|
258
|
+
Fleets larger than five hosts share lines to preserve both the six-line limit and visibility of every host.
|
|
259
|
+
`--watch --interval N` changes the refresh interval. Its default is five seconds.
|
|
260
|
+
|
|
261
|
+
## Stalls and check-ins
|
|
262
|
+
|
|
263
|
+
A `working` or `unknown` agent stalls after ten minutes without a transcript change. Screen redraws do not reset this clock.
|
|
264
|
+
An agent without a readable transcript never stalls. Recovery clears its `$dogsled` sidebar token.
|
|
265
|
+
Status lists stalled panes. Brief status and prompt context include a stall count within six lines.
|
|
266
|
+
|
|
267
|
+
The owner's service checks every minute. It checks in only with `idle` or `done` owners, never `working` or `blocked` owners.
|
|
268
|
+
A check-in is a `check-in` record in the owner's inbox. An owner without an inbox reader gets none; a due check-in stays due until it has one.
|
|
269
|
+
A stall or a completed job makes a check-in due. Other open work gets a check-in after 30 minutes without a check-in or lifecycle event. A finished child's reply comes from the sweep, not a check-in.
|
|
270
|
+
Transcript writes alone do not postpone regular check-ins. Pending job-completion events survive item closure.
|
|
271
|
+
The note includes names, hosts, states, ages, transcript silence, and bounded recent activity.
|
|
272
|
+
Known Pi, Claude, and Codex transcripts supply the latest tool call or message. Unknown formats fall back to plain pane text.
|
|
273
|
+
Job notes use the last five log lines. All note content has terminal escape codes removed.
|
|
274
|
+
It asks the owner to wait, message a child with `dogsled send`, close it, or stop a job. Output in the note is untrusted data.
|
|
275
|
+
A stalled top-level pane gets one Herdr notification per stall episode.
|
|
276
|
+
|
|
277
|
+
Locked `watchdog.json` records events and last check-ins. `parents.json` identifies tracked children on their own host.
|
|
278
|
+
A normal service restart does not repeat a delivered check-in. The inbox lease carries delivery from there.
|
|
279
|
+
Notification attempts are recorded before delivery and never repeat within that stall; a crash can lose that notification.
|
|
280
|
+
|
|
281
|
+
For authorized live tests only, `DOGSLED_TEST_STALL_MS` overrides the ten-minute threshold with a positive millisecond value.
|
|
282
|
+
It does not shorten check-in cadence. Use private `DOGSLED_STATE` and stop the test service afterward.
|
|
283
|
+
Debug binaries also accept `DOGSLED_TEST_NOW_MS` for deterministic integration tests. Release binaries ignore this test clock.
|
|
284
|
+
|
|
285
|
+
## Cleanup
|
|
286
|
+
|
|
287
|
+
```sh
|
|
288
|
+
dogsled doctor --json
|
|
289
|
+
dogsled doctor --host netcup
|
|
290
|
+
dogsled prune worktrees jobs
|
|
291
|
+
dogsled prune --host netcup --yes panes
|
|
292
|
+
dogsled prune targets
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
Doctor changes no candidates. It reports `worktrees`, `branches`, `workspaces`, `panes`, `jobs`, `targets`, `disk`, `processes`, and `repositories`.
|
|
296
|
+
Doctor lists linked worktrees on a branch and detached ones.
|
|
297
|
+
A removable worktree has a HEAD that has not moved more than 24 hours after Git made it and no commits beyond the base, or an integrated branch.
|
|
298
|
+
A detached worktree is removable when it is clean, no pane holds it, and a remote branch holds its HEAD. Otherwise doctor reports its commits on no remote. A worktree whose HEAD has not moved is not integrated, even when its base moved past it. It also needs a clean tree, no foreign lock, and no pane that uses it.
|
|
299
|
+
A worktree whose branch has unmerged commits and that no pane uses is report-only. Doctor shows the commits ahead, how many are on no remote, and the age of the last commit.
|
|
300
|
+
A branch is integrated when it is deleted, when it is an ancestor of Git's remote default branch (local `main` is the fallback), or when commits on that branch apply it.
|
|
301
|
+
The branch's commits split into consecutive runs, and each run needs one commit that applies it. A commit applies a run when it changes every path the run changed, and merging the run into the commit's parent gives the commit's content on those paths.
|
|
302
|
+
One run is a merge, squash, or cherry-pick of the whole branch. Several runs are a stack: the branch holds an earlier branch's commits, and each branch landed as its own squash. Git alone decides this.
|
|
303
|
+
Each path merges on its own. An addition, deletion, or mode change on a path the base also changed differently is a conflict, and renames are not followed, so a doubtful run is not applied.
|
|
304
|
+
Results use the remote-tracking branch, so `git fetch` keeps them current.
|
|
305
|
+
A local branch with no worktree is removable when it is integrated or every commit is on a remote branch. Other branches are report-only. The default branch is never a candidate. Prune deletes a branch with `git branch -D` after it rechecks the planned commit.
|
|
306
|
+
A pane holds a worktree when it works in it or sits in its workspace. A shell with no foreground command does not hold it.
|
|
307
|
+
An agent holds it until it has been `idle` or `done` for 24 hours. Before that, the sweep closes a finished child that has nothing left to land.
|
|
308
|
+
Held, dirty, and locked integrated worktrees are reported with the reason and are not removed.
|
|
309
|
+
A registered worktree whose directory is gone is a stale registration. Prune drops the record only.
|
|
310
|
+
A shell with no foreground command in an ended job's tab is idle at once: the job log keeps its output. So is a shell whose directory no longer exists.
|
|
311
|
+
Other panes need more than 24 hours continuously idle or done, based on service observations and a fresh snapshot.
|
|
312
|
+
A shell pane is idle when the service found no foreground command at each sample for more than 24 hours, and it still has none. Herdr reports no activity time, so a command that starts and ends between samples does not count.
|
|
313
|
+
A workspace whose every pane is idle is one `workspaces` entry, and prune closes it whole. The caller's workspace stays, and so does a workspace that a worktree removal closes.
|
|
314
|
+
Ended jobs expire after 24 hours, together with their logs. Disk usage above 90% lists the largest known dogsled-owned paths.
|
|
315
|
+
A `targets` entry is build output: a directory with a `CACHEDIR.TAG` that starts with the cache-directory signature, directly under a main checkout or a linked worktree, such as Rust's `target/`.
|
|
316
|
+
It is removable when no Herdr workspace shows the checkout and no pane or process works in it. Work in a linked worktree inside the main checkout uses that worktree, not the main checkout.
|
|
317
|
+
Prune removes it after it checks the tag again. A worktree that the same plan removes takes its build output with it, so that output is not listed.
|
|
318
|
+
Processes above 100% CPU outside Herdr pane ancestry are report-only. Prune never kills processes or frees arbitrary disk paths.
|
|
319
|
+
|
|
320
|
+
Prune displays a plan and asks before removal. `--yes` skips that question, not safety checks.
|
|
321
|
+
Each removal rechecks current state. Working or blocked panes, held worktrees, dirty worktrees, and unintegrated branches remain untouched.
|
|
322
|
+
Removal rechecks Git path, branch, HEAD, and repository against the approved plan. Any identity change stops removal.
|
|
323
|
+
Worktree removal is the same as `close`: `teardown`, the panes and workspace, unlock, `git worktree remove`, the branch when integrated, and the idle anchor. Dogsled checks that the worktree is gone afterwards.
|
|
324
|
+
Each entry is independent. A failed or refused entry does not stop the others; prune reports each failure, then exits with status 2.
|
|
325
|
+
`--json` returns `{results,failures}`. A result names the removed path and the closed panes. A failed `teardown` command's error includes its last lines of output.
|
|
326
|
+
|
|
327
|
+
Placement records repositories in `repositories.json`, independently of `worktrees.json`. Repository registrations survive the last worktree removal.
|
|
328
|
+
Doctor also discovers repositories from the caller, live pane directories, Herdr workspaces, and `cleanup.repositories`. It never scans the whole home directory.
|
|
329
|
+
A configured path that is not a Git checkout is a report-only `repositories` entry.
|
|
330
|
+
### The sweep in `serve`
|
|
331
|
+
|
|
332
|
+
The sweep closes finished children (see [Items and closing](#items-and-closing)), and a job closes its own tab. That closed loop ends most work.
|
|
333
|
+
The sweep catches what a broken loop leaves behind: a crashed owner, a killed process, or a worktree that something else made.
|
|
334
|
+
On each pass, the service's sweep worker builds the doctor plan in sweep scope. It applies only entries whose removal loses nothing:
|
|
335
|
+
|
|
336
|
+
- `panes` and `workspaces`: a shell at an empty prompt in an ended job's tab, or in a directory that no longer exists. A workspace closes whole when every pane in it is one of these.
|
|
337
|
+
- `worktrees`: a clean worktree whose branch is integrated, or a clean detached worktree whose HEAD is on a remote branch. Nothing may hold it: no pane works in it, no workspace shows it, and no process works in it. An idle shell holds it too.
|
|
338
|
+
- `branches`: a local branch with no worktree whose every commit is on a remote ref. An integrated branch with commits on no remote waits for `prune`.
|
|
339
|
+
- Orphaned children: an open agent item whose owner pane no longer exists, whose child is `idle` or `done`, whose worktree is clean, and whose every commit is on a remote ref. The sweep closes it as `dogsled close` does: `teardown`, the workspace, the worktree, and the item. A remote child closes over SSH with `host close --pushed`.
|
|
340
|
+
|
|
341
|
+
The sweep runs the same checks as `close` and `prune`. It never closes the service's own pane or workspace, or a worktree that the service works in. It skips a worktree it cannot check, and a failure on one entry does not stop the others.
|
|
342
|
+
Each removal is a `dogsled sweep:` line on stderr, the service journal.
|
|
343
|
+
An orphan that is dirty, unpushed, `working`, `blocked`, or on an unreachable host stays open. Status shows `orphaned:` and the reason on its item line, the brief counts it, and every check-in on the host lists it.
|
|
344
|
+
Everything else is for a confirmed `prune`: idle shells and agents after a day, a worktree with no commits a day after it was made, integrated branches with unpushed commits, ended jobs, stale registrations, and `targets`. Disk, process, and repository findings are report-only.
|
|
345
|
+
|
|
346
|
+
## Placement
|
|
347
|
+
|
|
348
|
+
Headroom is free cores, the smaller of the measured and the declared value:
|
|
349
|
+
|
|
350
|
+
```text
|
|
351
|
+
measured = cores × (1 − busy) − reservation_load × reservations
|
|
352
|
+
declared = cores − reservation_load × (active agents + reservations)
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
An active agent is a live agent that is not `idle`.
|
|
356
|
+
It holds its demand while it waits on its model, because its next build starts within minutes.
|
|
357
|
+
The measured value counts work that dogsled does not know about.
|
|
358
|
+
|
|
359
|
+
A host is eligible when all of these hold:
|
|
360
|
+
|
|
361
|
+
- a fresh service snapshot with a CPU sample;
|
|
362
|
+
- at least `disk_free_min_percent` free on the home filesystem;
|
|
363
|
+
- on macOS, memory pressure below critical;
|
|
364
|
+
- free memory of at least `memory_reserve_bytes × (reservations + 1)`;
|
|
365
|
+
- total memory of at least `memory_reserve_bytes × (active agents + reservations + 1)`;
|
|
366
|
+
- free cores of at least `free_core_fraction_min × cores`.
|
|
367
|
+
|
|
368
|
+
The host with most free cores wins. Ties use fewer live agents, then host id.
|
|
369
|
+
The reasons for each refusal appear in `status --json` under `headroom.reason`.
|
|
370
|
+
The thresholds come from the fleet measurements in `docs/research/2026-10-15-admission-metric.md`.
|
|
371
|
+
The selected host rechecks reservations under its own lock before it accepts the placement.
|
|
372
|
+
|
|
373
|
+
`place` writes a reservation with a default TTL of 90 seconds.
|
|
374
|
+
It returns the host id and label. JSON also includes the reservation id.
|
|
375
|
+
With `--branch`, it creates or reuses the branch's worktree on that host and returns its `path` and `pane_id` (see [Repository configuration](#repository-configuration)).
|
|
376
|
+
`place` does not start an agent. `run` and `agent` perform placement and launch together.
|
|
377
|
+
|
|
378
|
+
A reservation ends only at its TTL, which covers the time until the new agent appears in `herdr agent list`.
|
|
379
|
+
Until the TTL ends, the new agent counts twice: as its reservation and as an active agent.
|
|
380
|
+
Agent discovery and worktree failures do not end it early.
|
|
381
|
+
|
|
382
|
+
## Configuration
|
|
383
|
+
|
|
384
|
+
The optional host policy lives in `~/.config/dogsled/config.toml`.
|
|
385
|
+
`--config PATH` or `$DOGSLED_CONFIG` selects another file.
|
|
386
|
+
Unknown keys are errors.
|
|
387
|
+
|
|
388
|
+
```toml
|
|
389
|
+
free_core_fraction_min = 0.25
|
|
390
|
+
memory_reserve_bytes = 3221225472
|
|
391
|
+
disk_free_min_percent = 15
|
|
392
|
+
reservation_load = 1.0
|
|
393
|
+
reservation_ttl_ms = 90000
|
|
394
|
+
remote_command = ["mise", "x", "--", "dogsled"]
|
|
395
|
+
|
|
396
|
+
[cleanup]
|
|
397
|
+
repositories = [] # for example "~/.config/mise"; `~/` is the home directory
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
Host policy has no worktree hooks. A `[hooks]` table is an unknown key, so it is an error. Worktree setup and teardown belong to each repository.
|
|
401
|
+
|
|
402
|
+
### Repository configuration
|
|
403
|
+
|
|
404
|
+
An optional `dogsled.toml` at the root of the repository's main checkout configures its worktrees. Without the file, the defaults apply.
|
|
405
|
+
Unknown keys are errors.
|
|
406
|
+
|
|
407
|
+
```toml
|
|
408
|
+
[worktree]
|
|
409
|
+
dir = ".worktrees" # relative to the main checkout
|
|
410
|
+
setup = [] # run in a new worktree after creation, in order
|
|
411
|
+
teardown = [] # run in a worktree before removal, in order
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
Each command runs with `sh -c` in the worktree. `{main}` is the main checkout, `{path}` the worktree, and `{branch}` its branch (empty for a detached worktree).
|
|
415
|
+
Dogsled quotes each value as one shell word. Any other `{…}` is an error, so the command text cannot use braces for anything else.
|
|
416
|
+
Dogsled reads `dogsled.toml` from the main checkout, also for a worktree on an older branch.
|
|
417
|
+
|
|
418
|
+
With `--branch`, `place`, `agent`, and `run` use the branch's worktree on the selected host:
|
|
419
|
+
|
|
420
|
+
1. Dogsled refuses an invalid branch name, `--base` for a branch that exists, a branch checked out in the main checkout, and a worktree that has another lock. It needs a reachable Herdr server.
|
|
421
|
+
2. A branch that has a worktree reuses it without `setup`. Otherwise `git worktree add` makes `<dir>/<branch>` with each `/` as `-`. A new branch starts from `--base`, else the remote default branch's local name (else `main`).
|
|
422
|
+
3. The worktree is locked with the reason `agent:worktree`. The lock marks it as agent-owned, and `git worktree remove` refuses it until close or prune unlocks it.
|
|
423
|
+
4. `setup` runs in a new worktree. If a command fails, dogsled removes the new worktree and the branch it made, and placement fails. The reservation stays.
|
|
424
|
+
5. `herdr worktree open --no-focus` opens the worktree as a Herdr workspace linked to the repository. When the main checkout had no open workspace, Herdr opens one as the anchor, and dogsled records its id in the Git common directory as `agent-worktree-anchor`. A workspace that already showed the worktree may belong to a running child, so that is an error.
|
|
425
|
+
|
|
426
|
+
Before repository work, dogsled verifies the selected host's checkout against the caller's `git remote get-url origin`.
|
|
427
|
+
If the host has no checkout of the repository, dogsled clones it from the caller's origin into the same path relative to home first.
|
|
428
|
+
An existing path with a different origin, or a non-repository path, is an error. Dogsled does not overwrite it.
|
|
429
|
+
Clone errors identify the host and origin. Dogsled does not silently move the work elsewhere.
|
|
430
|
+
After a fresh clone, dogsled checks mise configuration. If mise reports missing trust, dogsled trusts only that new checkout's configuration.
|
|
431
|
+
For peers, a checkout under the local home maps to the same relative path under the peer's home.
|
|
432
|
+
The peer reads its own host policy.
|
|
433
|
+
Checkouts outside the home keep their absolute path.
|
|
434
|
+
Hooks substitute `{branch}` and `{base}` literally, without interpreting placeholders inside their values.
|
|
435
|
+
When `--base` is absent, a word that is only `{base}` is omitted. Other placeholders produce an error that names them.
|
|
436
|
+
Prefer an argument list over shell interpolation.
|
|
437
|
+
|
|
438
|
+
The hook must print JSON with `pane_id`, `path`, or both. `workspace_id` is optional.
|
|
439
|
+
Progress text can precede a final JSON line.
|
|
440
|
+
|
|
441
|
+
State defaults to `$XDG_STATE_HOME/dogsled`, or `~/.local/state/dogsled`.
|
|
442
|
+
`$DOGSLED_STATE` selects a complete state-directory path.
|
|
443
|
+
Host snapshots use `host.json`. New placement reservations use `placements.json`.
|
|
444
|
+
Jobs use `jobs/`, owner items use `items.json`, and FIFO tickets use `queue.json`.
|
|
445
|
+
The removed lead ledger and event log are not read or migrated.
|
|
446
|
+
|
|
447
|
+
## Prompt context and integrations
|
|
448
|
+
|
|
449
|
+
`dogsled hook context --harness claude|codex|pi` leads with your own children and jobs, then shows the fleet totals from `status --brief`.
|
|
450
|
+
The owner summary separates work to land, attention, idle, done, running, and queued work.
|
|
451
|
+
The `To land:` line names finished children with unmerged commits or uncommitted changes.
|
|
452
|
+
Claude Code and Codex register `SessionStart` and `UserPromptSubmit` context hooks, and `UserPromptSubmit` and `Stop` inbox hooks (see [Inbox](#inbox)), in `plugins/dogsled`.
|
|
453
|
+
Each registration supplies `--event`. The default context event is `UserPromptSubmit`.
|
|
454
|
+
The CLI never reads stdin. Claude Code and Codex receive `hookSpecificOutput` JSON with `hookEventName` and `additionalContext`.
|
|
455
|
+
Pi receives plain text through its `before_agent_start` extension. All three use the same snapshot reader and formatter.
|
|
456
|
+
|
|
457
|
+
Before an orchestrator stops, the stop gate checks its own TO LAND children.
|
|
458
|
+
Pi calls `dogsled hook gate` from `agent_before_settle` and adds a visible message that continues the run.
|
|
459
|
+
Claude Code and Codex include the reminder in their existing `Stop` inbox response.
|
|
460
|
+
The reminder requests a review, a commit from dirty children, integration, or an explicit blocker or deferral.
|
|
461
|
+
It never commits, merges, closes, or discards work itself. Clean readers and working children do not trigger it.
|
|
462
|
+
|
|
463
|
+
The gate records each set of child item IDs, commit counts, and dirty states in `gate.json`.
|
|
464
|
+
It continues once per distinct set, across process restarts. Row order and idle/done transitions do not cause another reminder.
|
|
465
|
+
New states can trigger another reminder. Closing all owner items clears the history.
|
|
466
|
+
Pi skips the gate on errors, aborts, and boundaries that already request continuation.
|
|
467
|
+
This is a bounded reminder, not a permanent prohibition on stopping.
|
|
468
|
+
|
|
469
|
+
Without `HERDR_ENV`, service snapshots, or a usable binary, the hooks add nothing.
|
|
470
|
+
A hook has a five-second command budget. Hook failures exit successfully without output.
|
|
471
|
+
Plugin commands end with `|| true`. Pi also leaves the prompt unchanged if the binary fails.
|
|
472
|
+
|
|
473
|
+
### Tools
|
|
474
|
+
|
|
475
|
+
`dogsled mcp` serves the dogsled commands as MCP tools over stdio: `status`, `spawn`, `run`, `send`, `inbox`, `read`, `close`, `stop`, `cancel`, and `place`.
|
|
476
|
+
Each tool calls the same code as its CLI command and returns the same JSON. No tool waits: `spawn` and `run` return the item or the queued ticket at once.
|
|
477
|
+
The caller is the harness's `HERDR_PANE_ID`. Pi registers the server from its extension (tools `mcp__dogsled__*`); Claude Code reads `plugins/dogsled/.mcp.json`; Codex reads `plugins/dogsled/codex-mcp.json`, which forwards the Herdr and `DOGSLED_*` variables.
|
|
478
|
+
|
|
479
|
+
### Pi
|
|
480
|
+
|
|
481
|
+
The extension adds host status before each prompt, registers the tools, and draws:
|
|
482
|
+
|
|
483
|
+
- **The board widget** above the editor shows host meters, the current task, and agents and jobs grouped TO LAND, ATTENTION, RUNNING, and WAITING. Agent/job data refreshes every ten seconds. Compatible pi-todo snapshots update immediately. Empty providers hide the widget. Unavailable providers show an error.
|
|
484
|
+
- **Alt+W or `/work`** expands or collapses that widget in place, without a popup or editor replacement. Alt+J/K moves selection, Alt+] changes views, and Alt+I shows inline details. Typing stays in the editor. Alt+S stops jobs, Alt+C cancels queued work, and Alt+M sends agent messages. Stop and cancel require confirmation. Completed job history starts collapsed.
|
|
485
|
+
- **`/dogsled`**, the control panel, with four tabs: Status (hosts with their retry state, then your rows; Enter on a host reads it again now), Hosts (reconnect, rename, enable, disable, add), Profiles (Enter edits `prompt.md`), and Inbox. The widget steps aside while the panel is open.
|
|
486
|
+
- **The inbox reader** and a renderer that shows each record's kind, sender, and text, folded past twelve lines.
|
|
487
|
+
|
|
488
|
+
Without `HERDR_PANE_ID`, the extension starts no Dogsled polling or jobs. The shared display can still show todos and reports Dogsled unavailable. `$DOGSLED_BIN` selects the binary.
|
|
489
|
+
|
|
490
|
+
Todos follow the active Pi session branch. Agents and jobs follow the calling Herdr owner pane, including after a Pi session change. `/todos` and Alt+T open the Todos view when compatible pi-todo is active. `/todos list` remains a plain readout. The [display contract](docs/pi-work.md) keeps task state and reminders in pi-todo. Dogsled retains execution, logs, cancellation, and completion delivery.
|
|
491
|
+
|
|
492
|
+
The Jobs view joins retained records to the current owner's ledger by host and job ID. It does not show unrelated fleet jobs. Job inspection uses `dogsled read` for a bounded log tail and shows the `dogsled logs` command for full output. Expired records and unavailable hosts produce explicit errors. The panel never starts a new process manager, edits todos, or writes into an agent terminal.
|
|
493
|
+
|
|
494
|
+
The Herdr plugin keeps only the status-board popup:
|
|
495
|
+
|
|
496
|
+
```sh
|
|
497
|
+
herdr plugin pane open --plugin dogsled --entrypoint board
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
The popup runs `dogsled status --watch`. The pane-close release hooks and sidebar token configuration are removed.
|
|
501
|
+
All three harness packages share `plugins/dogsled/skills/dogsled/SKILL.md`. It describes delegation, jobs, messages, and the queue.
|
|
502
|
+
|
|
503
|
+
## Build and development
|
|
504
|
+
|
|
505
|
+
Build this branch with the repository's pinned Rust toolchain:
|
|
506
|
+
|
|
507
|
+
```sh
|
|
508
|
+
cargo build --release
|
|
509
|
+
npm ci
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
The executable is `target/release/dogsled`.
|
|
513
|
+
Release archives include the binary, `dogsled.service`, and `dev.dogsled.plist` from `plugin/services/`.
|
|
514
|
+
Harness installers read their manifests and skill from Git, not the binary archive. The skill move does not change the archive contents.
|
|
515
|
+
Both run `dogsled serve` through `~/.local/bin/mise`, restart on failure, and log to the dogsled state directory.
|
|
516
|
+
Dotfiles installs the systemd user unit or renders the launchd template with an absolute, XML-escaped `@HOME@` path.
|
|
517
|
+
For launchd, dotfiles creates `~/.local/state/dogsled` before loading the agent. Systemd creates it through `StateDirectory`.
|
|
518
|
+
If mise has a different installation path, dotfiles adjusts the executable path.
|
|
519
|
+
Install the same release on every host before enabling its service. This PR does not install or start host services.
|
|
520
|
+
|
|
521
|
+
The pre-commit hook runs `mise run check`: Rust format, Clippy, Rust tests, TypeScript typecheck, and Pi extension tests.
|
|
522
|
+
CLI behavior tests use private state and fake Herdr/SSH executables. Time-sensitive unit tests inject timestamps.
|
|
523
|
+
See [the design](docs/design.md) for watchdog delivery guarantees and cleanup scope.
|
package/package.json
CHANGED
|
@@ -1,6 +1,56 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oisin-ee/pi-dogsled",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.13.1",
|
|
4
|
+
"description": "Pi extension for dogsled: the board, the /dogsled panel, the inbox reader, and the dogsled tools. Needs the dogsled binary of the same version.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/oisin-ee/dogsled.git"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/oisin-ee/dogsled#readme",
|
|
12
|
+
"files": [
|
|
13
|
+
"pi/",
|
|
14
|
+
"!pi/**/*.test.ts",
|
|
15
|
+
"plugins/dogsled/skills/",
|
|
16
|
+
"README.md",
|
|
17
|
+
"LICENSE"
|
|
18
|
+
],
|
|
19
|
+
"publishConfig": {
|
|
20
|
+
"access": "public",
|
|
21
|
+
"provenance": true
|
|
22
|
+
},
|
|
23
|
+
"keywords": [
|
|
24
|
+
"pi-package",
|
|
25
|
+
"pi-extension",
|
|
26
|
+
"pi",
|
|
27
|
+
"herdr",
|
|
28
|
+
"agents",
|
|
29
|
+
"orchestration"
|
|
30
|
+
],
|
|
31
|
+
"engines": {
|
|
32
|
+
"node": ">=20.6.0"
|
|
33
|
+
},
|
|
34
|
+
"scripts": {
|
|
35
|
+
"typecheck": "tsc --noEmit -p tsconfig.json",
|
|
36
|
+
"test": "node --test \"pi/**/*.test.ts\""
|
|
37
|
+
},
|
|
38
|
+
"pi": {
|
|
39
|
+
"extensions": [
|
|
40
|
+
"./pi/index.ts"
|
|
41
|
+
],
|
|
42
|
+
"skills": [
|
|
43
|
+
"./plugins/dogsled/skills/dogsled"
|
|
44
|
+
]
|
|
45
|
+
},
|
|
46
|
+
"peerDependencies": {
|
|
47
|
+
"@earendil-works/pi-coding-agent": "*",
|
|
48
|
+
"@earendil-works/pi-tui": "*"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@earendil-works/pi-coding-agent": "1.0.4",
|
|
52
|
+
"@earendil-works/pi-tui": "1.0.4",
|
|
53
|
+
"@types/node": "26.6.4",
|
|
54
|
+
"typescript": "7.0.2"
|
|
55
|
+
}
|
|
56
|
+
}
|