@spoolway/win32-x64 0.1.0 → 0.2.0
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/README.md +131 -43
- package/bin/spoolway.exe +0 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,6 +5,12 @@
|
|
|
5
5
|
</picture>
|
|
6
6
|
</p>
|
|
7
7
|
|
|
8
|
+
<p align="center">
|
|
9
|
+
<a href="LICENSE"><img alt="license" src="https://img.shields.io/github/license/marvingygas/spoolway?style=flat-square&label=license&labelColor=3f3f46&color=18181b"></a>
|
|
10
|
+
<a href="https://github.com/marvingygas/spoolway/actions/workflows/ci.yml"><img alt="ci" src="https://img.shields.io/github/actions/workflow/status/marvingygas/spoolway/ci.yml?branch=main&style=flat-square&label=ci&labelColor=3f3f46"></a>
|
|
11
|
+
<a href="https://github.com/marvingygas/spoolway/releases/latest"><img alt="release" src="https://img.shields.io/github/v/release/marvingygas/spoolway?style=flat-square&label=release&labelColor=3f3f46&color=18181b"></a>
|
|
12
|
+
</p>
|
|
13
|
+
|
|
8
14
|
Minimalistic command line state machine for turning coding agents into a pipeline you can actually reason about. No dependencies, terminal native. Runs headless or controls supported multiplexers. Worktree management and built-in support for GitHub's stacked pull requests.
|
|
9
15
|
|
|
10
16
|
Supported providers:
|
|
@@ -42,10 +48,12 @@ sometimes does. spoolway won't surprise you with a bill or an opinion.
|
|
|
42
48
|
- **Session reuse.** A step can resume its prompt's earlier conversation instead of
|
|
43
49
|
paying to rebuild context, bounded by how full the model's window already is.
|
|
44
50
|
- **Unattended runs.** Overnight, nothing parks for a person: blocked work is resumed by
|
|
45
|
-
an unblocker prompt, with
|
|
46
|
-
- **Trials.** Fork
|
|
47
|
-
arms side by side in eval.
|
|
51
|
+
an unblocker prompt, with a token or dollar ceiling as the brake.
|
|
52
|
+
- **Trials.** Fork a whole group into one arm per task, each on its own pipeline, and queue
|
|
53
|
+
them together, then read the arms side by side in eval.
|
|
48
54
|
- **Routines.** Keep the tasks you run over and over in `.spoolway/routines/`.
|
|
55
|
+
- **Jobs.** Run a routine on a cron schedule. The dispatcher fires it from its own pass, so
|
|
56
|
+
nightly work needs nothing but a dispatcher left running.
|
|
49
57
|
- **Eval built in.** Every lane's spend and outcome land in a ledger, so you can see what
|
|
50
58
|
your last pipeline edit did to pass rate and price.
|
|
51
59
|
|
|
@@ -56,7 +64,9 @@ npm install -g spoolway
|
|
|
56
64
|
```
|
|
57
65
|
|
|
58
66
|
A prebuilt binary, not a Node program — the package is a thin wrapper that runs it. Linux
|
|
59
|
-
(x64, arm64, musl), macOS (Apple Silicon, Intel) and Windows (x64, experimental).
|
|
67
|
+
(x64, arm64, musl), macOS (Apple Silicon, Intel) and Windows (x64, experimental). Successful
|
|
68
|
+
self-updates show what changed, and `spoolway whats-new` reads the installed release notes
|
|
69
|
+
offline from any directory.
|
|
60
70
|
|
|
61
71
|
From source instead, in a clone of this repository:
|
|
62
72
|
|
|
@@ -106,9 +116,10 @@ spoolway queue
|
|
|
106
116
|
<img src="docs/screenshots/queue.png" alt="the queue screen">
|
|
107
117
|
|
|
108
118
|
*The queue screen lists the groups on the left and previews the selected group's tasks on the
|
|
109
|
-
right
|
|
110
|
-
a task on the fly, `p` forks one across several pipelines as
|
|
111
|
-
|
|
119
|
+
right. Each task names its own pipeline. `enter` queues what is checked and offers to start
|
|
120
|
+
dispatching on the spot. `g` gates a task on the fly, `p` forks one across several pipelines as
|
|
121
|
+
a trial, `s` saves a group as a routine, and `r` opens the routines you keep in
|
|
122
|
+
`.spoolway/routines/`.*
|
|
112
123
|
|
|
113
124
|
### 4. Dispatch
|
|
114
125
|
|
|
@@ -119,18 +130,18 @@ spoolway dispatch # watch the board, and step in only where you are needed
|
|
|
119
130
|
<img src="docs/screenshots/dispatch.png" alt="the dispatcher board">
|
|
120
131
|
|
|
121
132
|
*One row per task, grouped by `group:`. The board says what each lane is spending as it
|
|
122
|
-
spends it, what every queued task is waiting on, and which tasks are
|
|
123
|
-
|
|
133
|
+
spends it, what every queued task is waiting on, and which tasks are paused for you. NEXT
|
|
134
|
+
distinguishes a lane holding a question from a task waiting to be resumed past a gate. The
|
|
135
|
+
ledger at the bottom shows the slots in use and every scheduled job with its next firing.*
|
|
124
136
|
|
|
125
137
|
Every task on the board is in one of a few states:
|
|
126
138
|
|
|
127
139
|
| State | Meaning |
|
|
128
140
|
|---|---|
|
|
129
141
|
| `queued` | Waiting for its dependencies and a free slot. |
|
|
130
|
-
| `running` | An agent is working the task's current step
|
|
131
|
-
| `
|
|
132
|
-
| `
|
|
133
|
-
| `blocked` | Something needs a person. |
|
|
142
|
+
| `running` | An agent is working the task's current step, or it has just moved there and a lane is starting. |
|
|
143
|
+
| `paused` | Waiting for you on purpose: a gate, a question in its pane, or a park. `r` on the board resumes it. |
|
|
144
|
+
| `blocked` | A step reported a block, or ran out of loops. Read the task's `## Blocker`, then `spoolway resume`. An unattended run hands it to the unblocker prompt instead. |
|
|
134
145
|
| `unreachable` | A task it depends on is blocked, so it cannot start until you clear that one. |
|
|
135
146
|
| `done` | Finished: the branch is handed over, the worktree removed, the task archived. |
|
|
136
147
|
|
|
@@ -181,7 +192,7 @@ steps:
|
|
|
181
192
|
description: Write the code to satisfy the task's acceptance criteria.
|
|
182
193
|
agent: pi
|
|
183
194
|
prompt: implementer
|
|
184
|
-
model:
|
|
195
|
+
model: Ornith-1.5-35B-A3B
|
|
185
196
|
session: true
|
|
186
197
|
on_pass: review
|
|
187
198
|
on_fail: blocked
|
|
@@ -202,7 +213,7 @@ steps:
|
|
|
202
213
|
description: Bring the domain documents in line with what this task changed.
|
|
203
214
|
agent: pi
|
|
204
215
|
prompt: archivist
|
|
205
|
-
model:
|
|
216
|
+
model: Ornith-1.5-35B-A3B
|
|
206
217
|
on_pass: handover
|
|
207
218
|
on_fail: blocked
|
|
208
219
|
|
|
@@ -221,67 +232,144 @@ steps:
|
|
|
221
232
|
on_fail: blocked
|
|
222
233
|
```
|
|
223
234
|
|
|
224
|
-
**You do not have to write one by hand.** The `/spoolway-
|
|
235
|
+
**You do not have to write one by hand.** The `/spoolway-config` skill writes a pipeline
|
|
225
236
|
for you, and edits the one you already have.
|
|
226
237
|
|
|
238
|
+
## Jobs
|
|
239
|
+
|
|
240
|
+
A job runs a routine on a schedule. It is three things: a cron expression, a pipeline, and a
|
|
241
|
+
routine you saved under `.spoolway/routines/`.
|
|
242
|
+
|
|
243
|
+
spoolway has no clock of its own. The dispatcher fires a due job at the top of its pass, and
|
|
244
|
+
while any job is enabled it stays up on an empty queue instead of exiting. A `spoolway dispatch`
|
|
245
|
+
left running overnight is all a job needs.
|
|
246
|
+
|
|
247
|
+
```
|
|
248
|
+
spoolway jobs # the screen: write, edit, pause, delete, or fire a job
|
|
249
|
+
spoolway jobs list # every job, its schedule, and when it fires next
|
|
250
|
+
spoolway jobs run <name> # fire one now, ignoring its schedule
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
<img src="docs/screenshots/jobs.png" alt="the jobs screen">
|
|
254
|
+
|
|
255
|
+
*The jobs screen. `n` walks three choices: the routine, the cron expression, and the pipeline.
|
|
256
|
+
A job fires once per matching minute and skips a window while its previous run is still in the
|
|
257
|
+
queue. A window that passes while no dispatcher is running is not caught up later.*
|
|
258
|
+
|
|
259
|
+
A job is a few lines of TOML. Yours live in `~/.spoolway/<project>/jobs.toml`. Put one in
|
|
260
|
+
`.spoolway/jobs.toml` inside the checkout to share it with the team.
|
|
261
|
+
|
|
262
|
+
```toml
|
|
263
|
+
[jobs.nightly-audit]
|
|
264
|
+
schedule = "0 3 * * 1-5" # weekdays at 03:00, local time
|
|
265
|
+
pipeline = "impl_fast"
|
|
266
|
+
routine = "nightly" # a folder or a single .md under .spoolway/routines/
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### Routines
|
|
270
|
+
|
|
271
|
+
A routine is work you run more than once. Queueing a group deletes its documents from
|
|
272
|
+
`pending/`, so repeatable tasks live in `.spoolway/routines/` instead, tracked in git. Press `s`
|
|
273
|
+
on a group in the queue screen to save it there, and `r` to browse and queue what is saved.
|
|
274
|
+
Every queued copy gets a fresh id, so a routine can run again without colliding with its last
|
|
275
|
+
run. The saved files are never changed.
|
|
276
|
+
|
|
277
|
+
### Trials
|
|
278
|
+
|
|
279
|
+
A trial answers one question: which pipeline does this task best? Press `p` on a group in the
|
|
280
|
+
queue screen, pick a pipeline per task, and tick any steps to skip. Every task becomes one arm,
|
|
281
|
+
queued under its chosen pipeline, and all arms share one trial id. Read them side by side with
|
|
282
|
+
`spoolway eval --runs --trial <id>`. An arm never pushes a branch or opens a pull request. When
|
|
283
|
+
the last arm finishes, every arm's copy is removed, and only the source group and the ledger
|
|
284
|
+
rows stay.
|
|
285
|
+
|
|
286
|
+
## Issue tracker
|
|
287
|
+
|
|
288
|
+
Use event hooks to sync with project management tools. GitHub and Jira sample scripts are shipped.
|
|
289
|
+
|
|
290
|
+
| Event | When it fires |
|
|
291
|
+
|---|---|
|
|
292
|
+
| `fetch` | `spoolway issue show <ref>` reads one issue out of the tracker |
|
|
293
|
+
| `open` | `spoolway queue add` opens a ticket per document |
|
|
294
|
+
| `queued` | A task arrives in the queue |
|
|
295
|
+
| `blocked` | A task comes to rest on `blocked` |
|
|
296
|
+
| `paused` | A task arrives on the persisted `paused` stage; a live-step row whose public state is `paused` does not fire it |
|
|
297
|
+
| `done` | A task finishes |
|
|
298
|
+
|
|
299
|
+
**The two shipped scripts are samples.** `spoolway init` writes `github.sh` and `jira.sh` into
|
|
300
|
+
`.spoolway/hooks/` — the `.ps1` pair on a native Windows install.
|
|
301
|
+
|
|
302
|
+
See **[Issue Tracking](docs/configuration.md#issue_tracking--a-hook-fired-on-four-task-events)**.
|
|
303
|
+
|
|
227
304
|
## Configurable per project
|
|
228
305
|
|
|
229
306
|
- Unattended mode delegates **`blocked`** tasks to a prompt you define. It clears
|
|
230
307
|
obstacles on its own and keeps your pipeline running while nobody is watching.
|
|
231
|
-
- Set specific
|
|
308
|
+
- Set a specific model for generating pipelines.
|
|
232
309
|
|
|
233
310
|
```toml
|
|
234
|
-
skills = ["spoolway-plan"] # which skills `spoolway eval` gives a block of their own
|
|
235
|
-
|
|
236
311
|
[dispatch]
|
|
237
312
|
backend = "herdr" # herdr, tmux, or headless
|
|
238
313
|
herdr_mode = "split" # "split": a workspace per task; "grouped": one shared tab, a pane per task
|
|
239
|
-
|
|
314
|
+
tmux_mode = "grouped" # "grouped": one session for the run; "split": a session per task
|
|
315
|
+
worktree_root = "" # where a task's worktree is cut; blank is ~/.spoolway/<project>/worktrees
|
|
316
|
+
interval = "10s" # how long the dispatcher waits between passes
|
|
240
317
|
lane_quiet = "15m" # silence before a lane is reminded to report
|
|
241
318
|
default_pipeline = "default" # which pipeline a task runs when it names none
|
|
242
|
-
auto_commit = true
|
|
319
|
+
auto_commit = true # commit a lane's leftover work when its step settles
|
|
243
320
|
|
|
244
321
|
[unattended]
|
|
245
322
|
enabled = true # the overnight switch
|
|
246
|
-
max_output_tokens = 0 #
|
|
323
|
+
max_output_tokens = 0 # output-token ceiling for a run with nobody watching; 0 is none
|
|
324
|
+
max_cost_usd = 0.0 # dollar ceiling for the same run; 0 is none
|
|
247
325
|
skip_blocked_lane = true # a cleared block carries the task past the step it blocked on
|
|
248
326
|
blocked_agent = "claude" # who staffs `blocked` when nobody is at the keyboard
|
|
249
327
|
blocked_model = "claude-opus-5"
|
|
250
328
|
blocked_effort = "medium"
|
|
329
|
+
blocked_session = true # the unblocker carries its own earlier session forward
|
|
251
330
|
blocked_prompt = "unblocker"
|
|
252
331
|
|
|
253
332
|
[pipeline_gen]
|
|
254
333
|
pipeline_agent = "claude" # who `spoolway pipeline gen` opens its session as
|
|
255
334
|
pipeline_model = "claude-opus-5"
|
|
256
335
|
pipeline_effort = "medium"
|
|
257
|
-
pipeline_auto = false # false asks before writing the pipeline
|
|
258
|
-
pipeline_local_models = false
|
|
259
336
|
|
|
260
|
-
[
|
|
261
|
-
|
|
337
|
+
[housekeeping]
|
|
338
|
+
update_check = true # tell a person at a keyboard that a newer release is out
|
|
339
|
+
calibrate_window = "14d" # how far back `/spoolway-calibrate` reads
|
|
340
|
+
retention_days = 30 # how long run records and archived tasks are kept; 0 keeps everything
|
|
341
|
+
price_max_age_days = 30 # how old the price table may be before `spoolway doctor` says so
|
|
262
342
|
|
|
263
|
-
[
|
|
264
|
-
|
|
343
|
+
[agents.claude]
|
|
344
|
+
kind = "claude"
|
|
345
|
+
concurrency = 3 # most lanes of this profile at once
|
|
346
|
+
session_reuse_ctx = 50 # % of the window before a carried session restarts fresh
|
|
347
|
+
session_blocked_ctx = 0 # % of the window at which a running lane is stopped and blocked; 0 is off
|
|
348
|
+
permission_mode = "auto"
|
|
265
349
|
|
|
266
|
-
[
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
350
|
+
[agents.codex]
|
|
351
|
+
kind = "codex"
|
|
352
|
+
concurrency = 3
|
|
353
|
+
session_reuse_ctx = 50
|
|
354
|
+
session_blocked_ctx = 0
|
|
355
|
+
permission_mode = "never"
|
|
270
356
|
|
|
271
357
|
[agents.pi]
|
|
272
358
|
kind = "pi"
|
|
273
|
-
session_reuse_ctx = 50 # % of the window before a carried session restarts fresh
|
|
274
|
-
|
|
275
|
-
[agents.claude]
|
|
276
|
-
kind = "claude"
|
|
277
|
-
concurrency = 3
|
|
278
359
|
session_reuse_ctx = 50
|
|
279
|
-
|
|
360
|
+
session_blocked_ctx = 0
|
|
280
361
|
|
|
281
|
-
[models."
|
|
362
|
+
[models."Ornith-1.5-35B-A3B"] # a local model, served by llama.cpp
|
|
282
363
|
context_window = 100096
|
|
283
|
-
slots =
|
|
364
|
+
slots = 2 # parallel lanes the local server can actually hold
|
|
284
365
|
exclusive = true # never alongside another exclusive model
|
|
366
|
+
local = true # runs on hardware you own
|
|
367
|
+
|
|
368
|
+
[issue_tracking]
|
|
369
|
+
hook = "" # a script in .spoolway/hooks/, e.g. "github.sh"; blank runs none
|
|
370
|
+
project_key = "" # handed to the hook verbatim, e.g. owner/repo
|
|
371
|
+
on_fail = "ignore" # what a failing hook does: ignore it, or pause the task
|
|
372
|
+
key_in_names = false # prefix branch and worktree names with the tracker's slug
|
|
285
373
|
```
|
|
286
374
|
|
|
287
375
|
See **[Configuration](docs/configuration.md)**.
|
|
@@ -298,9 +386,9 @@ spoolway eval
|
|
|
298
386
|
|
|
299
387
|
<img src="docs/screenshots/eval.png" alt="the eval screen">
|
|
300
388
|
|
|
301
|
-
*The eval screen on its runs view, one row per attempt at a task — `tab` cycles the
|
|
302
|
-
views: the version comparisons per pipeline and per step, this one
|
|
303
|
-
|
|
389
|
+
*The eval screen on its runs view, one row per attempt at a task — `tab` cycles the three
|
|
390
|
+
views: the version comparisons per pipeline and per step, and this one. `f` filters, `e`
|
|
391
|
+
exports CSV.*
|
|
304
392
|
|
|
305
393
|
## Documentation
|
|
306
394
|
|
package/bin/spoolway.exe
CHANGED
|
Binary file
|