@dna113p/machines 0.3.3 → 0.3.5
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 +12 -2
- package/claude/statusline.mjs +5 -2
- package/dist/mcp/server.js +2 -2
- package/dist/src/cli.js +163 -20
- package/dist/src/codex.d.ts +2 -0
- package/dist/src/codex.js +2 -0
- package/dist/src/host.js +6 -2
- package/dist/src/launcher.d.ts +3 -0
- package/dist/src/launcher.js +3 -0
- package/dist/src/run-graph.d.ts +39 -0
- package/dist/src/run-graph.js +91 -0
- package/dist/src/run-status.d.ts +19 -3
- package/dist/src/run-status.js +64 -5
- package/dist/src/run-ui-page.d.ts +6 -0
- package/dist/src/run-ui-page.js +690 -0
- package/dist/src/run-ui.d.ts +62 -0
- package/dist/src/run-ui.js +258 -0
- package/dist/src/run-viewer.d.ts +57 -0
- package/dist/src/run-viewer.js +66 -0
- package/dist/src/run-watch.d.ts +3 -1
- package/dist/src/run-watch.js +10 -6
- package/docs/architecture.md +10 -0
- package/docs/authoring.md +13 -0
- package/docs/integrations.md +186 -10
- package/package.json +88 -20
- package/skills/machine-builder/SKILL.md +31 -0
- package/skills/machine-delegation/SKILL.md +23 -0
- package/skills/machine-project-setup/SKILL.md +23 -5
- package/skills/machine-project-setup/references/project-workflows.md +4 -0
package/docs/integrations.md
CHANGED
|
@@ -209,14 +209,27 @@ directory is created by the first write, as `0700`, and each file is `0600`:
|
|
|
209
209
|
`status` is `running`, `waiting`, `completed`, or `failed`. `state` is the current
|
|
210
210
|
state as a string (JSON for a nested state). `agent` is present while an Agent
|
|
211
211
|
state has reported its identity, and `error` after a failure. `owner` is
|
|
212
|
-
`MACHINES_RUN_OWNER` when set, otherwise
|
|
213
|
-
|
|
212
|
+
`MACHINES_RUN_OWNER` when set, otherwise the session id the coding agent gives
|
|
213
|
+
the commands it starts (`CLAUDE_CODE_SESSION_ID`, then `CODEX_THREAD_ID`, then
|
|
214
|
+
`PI_SESSION_ID`), otherwise absent; see
|
|
215
|
+
[how a host names its session](#drawing-your-own-widgets). `stateSince` is when
|
|
216
|
+
the current state was entered. `label` is the first
|
|
214
217
|
line of `MACHINES_RUN_LABEL` (at most 160 characters) when a launcher sets it to
|
|
215
218
|
say what the run is for, such as a ticket id and title; it is the launcher's
|
|
216
219
|
choice to publish that text. `machine run` exports its run id as
|
|
217
220
|
`MACHINES_RUN_PARENT`, so a Machine started by one of its Operations or Agents
|
|
218
221
|
records that id as `parent`; the status line shows only top-level runs.
|
|
219
222
|
|
|
223
|
+
`graph` is the Machine's states and transitions, published once when the run
|
|
224
|
+
starts: `initial`, `states` (each with an `id`, a `kind` of `agent`, `human`,
|
|
225
|
+
`operation`, `final`, `group`, or `state`, an Agent's `role`, and the `parent`
|
|
226
|
+
group of a nested state), and `edges` (`from`, `to`, and the `event` taken). Ids
|
|
227
|
+
are state paths joined by dots, so a nested state is `review.round`. A Machine
|
|
228
|
+
with more than 300 states or 1000 transitions publishes no graph. `trail` is the
|
|
229
|
+
states the run entered, oldest first, each with the time it was entered, as the
|
|
230
|
+
same dotted paths; it keeps the latest 200. Both are additions to version 2:
|
|
231
|
+
a reader that does not know them ignores them.
|
|
232
|
+
|
|
220
233
|
A run hosted through `startMachineHost` from `@dna113p/machines/host` publishes
|
|
221
234
|
the same record when its host asks with `publishRunStatus: true` and
|
|
222
235
|
publication is on in the hosting process, as a daemon that runs tickets does. A
|
|
@@ -279,8 +292,17 @@ taken a response from its inbox, its record lists that delivery's id in
|
|
|
279
292
|
id stays listed for at least a minute, however many responses the run takes
|
|
280
293
|
after it, and never contains the response.
|
|
281
294
|
|
|
282
|
-
|
|
283
|
-
|
|
295
|
+
When a run finishes, `machine run`, the MCP server, and a host that asks for
|
|
296
|
+
publication all three publish the optional `note` field if the final output
|
|
297
|
+
is an object with a non-empty string `summary`. It is trimmed and limited to
|
|
298
|
+
2000 characters, including a trailing `…` when shortened
|
|
299
|
+
at a word boundary (a single word longer than the limit is cut to fit).
|
|
300
|
+
Empty or whitespace-only summaries leave the field absent. The whole note,
|
|
301
|
+
including its line breaks, is available in JSON. This optional field keeps
|
|
302
|
+
`schemaVersion` at 2; readers should accept records with or without it.
|
|
303
|
+
|
|
304
|
+
Machine input, output fields other than that summary, and Human responses are
|
|
305
|
+
never recorded. A Human prompt and its choices are written to the `0600` file while the request is
|
|
284
306
|
waiting. The standard directory is private to you; one you name instead should
|
|
285
307
|
be a directory only you can read and write.
|
|
286
308
|
|
|
@@ -326,10 +348,13 @@ waiting run its prompt, request id, and choices (tab-separated when its
|
|
|
326
348
|
output is not a terminal). A run's label follows as a fifth column when it has
|
|
327
349
|
one, and a sixth says `watched` for a run this session
|
|
328
350
|
[watches](#watching-other-runs). It lists the running and waiting runs of every
|
|
329
|
-
session and project
|
|
351
|
+
session and project; `--for` narrows it to
|
|
352
|
+
[what one viewer shows](#drawing-your-own-widgets). `--all`, with or without `--json`, lists every published
|
|
330
353
|
run: also the ones whose records remain after they finished, as `completed` or
|
|
331
354
|
`failed`, or after their process disappeared, as `lost` (in JSON such a record
|
|
332
|
-
keeps the status it last published).
|
|
355
|
+
keeps the status it last published). For a completed or failed run, the first
|
|
356
|
+
non-empty line of its note is printed beneath the row; `--json` includes the
|
|
357
|
+
whole note. A run answered through its host shows
|
|
333
358
|
`answered through its host` in place of a request id:
|
|
334
359
|
|
|
335
360
|
```text
|
|
@@ -440,13 +465,43 @@ for the same time, so the status line must run where it can see that process.
|
|
|
440
465
|
Set `NO_COLOR` (to any value, even an empty one) for plain text and `COLUMNS`
|
|
441
466
|
to change the 120-column truncation.
|
|
442
467
|
|
|
468
|
+
### Watching runs in a browser
|
|
469
|
+
|
|
470
|
+
```bash
|
|
471
|
+
machine ui [--port <port>] [--project <dir>]
|
|
472
|
+
```
|
|
473
|
+
|
|
474
|
+
serves a live page on `127.0.0.1` (port 4777, or the next free one) of every
|
|
475
|
+
published run: what is waiting on you, what is running, and what finished, with
|
|
476
|
+
each run's Machine drawn as a graph, its current state marked, the states and
|
|
477
|
+
transitions it has taken counted, and the path it took so far. A waiting run
|
|
478
|
+
that takes outside responses is answered from the page, as `machine respond`
|
|
479
|
+
answers it; a run answered through its host, such as a daemon's, names where to
|
|
480
|
+
answer it instead. The page loads nothing from outside, accepts requests only
|
|
481
|
+
under its own host name, and answers a run only with a token it was served.
|
|
482
|
+
|
|
483
|
+
A project adds its own panels beside the runs, such as its tickets or pull
|
|
484
|
+
requests, in `.machines/ui.json` in the project (the nearest directory above the
|
|
485
|
+
current one that has a `.machines` directory, or `--project`):
|
|
486
|
+
|
|
487
|
+
```json
|
|
488
|
+
{ "panels": [{ "title": "Tickets", "command": ["node", "scripts/ui-panels.mjs", "tickets"], "refreshSeconds": 10 }] }
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
Each command runs in the project directory every `refreshSeconds` (10 by
|
|
492
|
+
default) and prints one JSON object: `{ "summary"?, "items": [{ "text",
|
|
493
|
+
"detail"?, "status"?, "href"?, "at"? }] }`, where `status` is `ok`, `warn`,
|
|
494
|
+
`bad`, `active`, or `idle`, `href` is a web link, and `at` a time. Commands are
|
|
495
|
+
project code, trusted as `.machines/` Machines are; a command that fails or
|
|
496
|
+
prints something else shows its error in its panel.
|
|
497
|
+
|
|
443
498
|
### Watching other runs
|
|
444
499
|
|
|
445
500
|
A session can pull in runs it did not start: a ticket that a daemon runs, or a
|
|
446
501
|
run started by another session or under another project. Nothing is configured.
|
|
447
502
|
The session is identified as a run's `owner` is, by `MACHINES_RUN_OWNER` and
|
|
448
|
-
otherwise
|
|
449
|
-
command.
|
|
503
|
+
otherwise by the session id its coding agent gives it, so an agent inside Claude
|
|
504
|
+
Code, Codex, or Pi only runs the command.
|
|
450
505
|
|
|
451
506
|
```bash
|
|
452
507
|
machine runs # running and waiting runs, with their labels
|
|
@@ -455,6 +510,7 @@ machine watch org-9 # runs whose id or label starts with org-9
|
|
|
455
510
|
machine watch --dir ../other # runs working in that directory or below it
|
|
456
511
|
machine watch # what this session watches, and the published runs each entry matches now
|
|
457
512
|
machine unwatch org-9 # also: unwatch --dir <path>, unwatch --all
|
|
513
|
+
machine watch --for <session> org-9 # the same commands for another session's list
|
|
458
514
|
```
|
|
459
515
|
|
|
460
516
|
- `machine watch <text>` names every top-level run whose id starts with the
|
|
@@ -467,7 +523,12 @@ machine unwatch org-9 # also: unwatch --dir <path>, unwatch --all
|
|
|
467
523
|
- An entry keeps matching runs that start later, so a ticket can be watched
|
|
468
524
|
before its run exists. `machine watch` lists a matched run for as long as its
|
|
469
525
|
record remains, with the status `machine runs --all` gives it, so it also
|
|
470
|
-
says how a watched run ended
|
|
526
|
+
says how a watched run ended, with the first non-empty line of its note
|
|
527
|
+
beneath the row when present.
|
|
528
|
+
- `--for <session>`, first, makes `machine watch` and `machine unwatch` read
|
|
529
|
+
and change the list of the session it names instead of this process's own.
|
|
530
|
+
A program that draws [its own widgets](#drawing-your-own-widgets) for a
|
|
531
|
+
viewer manages that viewer's list this way, without setting a variable.
|
|
471
532
|
|
|
472
533
|
A watched run is shown even when another session owns it or it works outside
|
|
473
534
|
the project. Everything else is as for any run: sub-runs stay hidden, a run is
|
|
@@ -486,7 +547,122 @@ session id that is not safe as a file name is refused. Removing the last entry
|
|
|
486
547
|
removes the file, and writing a list or starting a run removes other sessions'
|
|
487
548
|
lists that have not changed for 30 days. A missing, unreadable, or malformed list watches
|
|
488
549
|
nothing; it is never an error on the status line. The commands fail with a
|
|
489
|
-
message when publication is off or when
|
|
550
|
+
message when publication is off or when nothing names the session.
|
|
551
|
+
|
|
552
|
+
### Drawing your own widgets
|
|
553
|
+
|
|
554
|
+
Any application can show Machine runs in its own way from what is already
|
|
555
|
+
published: an extension for Codex or Pi, a web app, an editor panel. The Claude
|
|
556
|
+
Code status line above is one such consumer. Nothing is configured and nothing
|
|
557
|
+
new runs; there are three ways to read the same directory:
|
|
558
|
+
|
|
559
|
+
| Read with | You get |
|
|
560
|
+
| --- | --- |
|
|
561
|
+
| `machine runs --for <session> --json` | The runs one viewer shows, each ready to draw |
|
|
562
|
+
| `@dna113p/machines/run-status` | The same rule and the readers, in your own process |
|
|
563
|
+
| The files | The [records](#run-status-for-host-status-lines) and [watch lists](#watching-other-runs) themselves; the rule is then yours to apply |
|
|
564
|
+
|
|
565
|
+
A viewer is one surface that shows runs: a session of a coding agent, a browser
|
|
566
|
+
tab, a status line. It is named by a session id and may have a project
|
|
567
|
+
directory. The rule that decides what it shows is the status line's:
|
|
568
|
+
|
|
569
|
+
- only top-level runs: a run started from inside another Machine is never shown;
|
|
570
|
+
- the runs its session owns, unowned runs working in its project directory or
|
|
571
|
+
below it, and the runs its session [watches](#watching-other-runs), whoever
|
|
572
|
+
owns them;
|
|
573
|
+
- a run recorded as running or waiting whose process is gone is `lost`;
|
|
574
|
+
- a finished or lost run stays for 30 seconds and then drops out;
|
|
575
|
+
- each run once, the ones that can still change first, then the most recently
|
|
576
|
+
updated. Runs updated in the same millisecond keep the order they were read
|
|
577
|
+
in from the directory, for the command, the library, and the status line
|
|
578
|
+
alike.
|
|
579
|
+
|
|
580
|
+
Both ways below take a snapshot. Read again to refresh, as the status line does
|
|
581
|
+
every few seconds, and read where the runs' processes can be seen, or every run
|
|
582
|
+
looks `lost`.
|
|
583
|
+
|
|
584
|
+
```bash
|
|
585
|
+
machine runs --for "$SESSION" --project "$PWD" --json # what that viewer shows
|
|
586
|
+
machine runs --for --json # for this process's own session
|
|
587
|
+
machine runs --for "$SESSION" --all # as text, and with older finished and lost runs
|
|
588
|
+
machine watch --for "$SESSION" org-9 # change what that viewer watches
|
|
589
|
+
```
|
|
590
|
+
|
|
591
|
+
`--for` takes the viewer's session id; with no id after it, the viewer is this
|
|
592
|
+
process's own session, and the command fails when nothing names one.
|
|
593
|
+
`--project` is the viewer's project directory, compared as an absolute path;
|
|
594
|
+
without it only owned and watched runs are selected. `--all` also keeps the
|
|
595
|
+
finished and lost runs that the 30 seconds would have dropped, for as long as
|
|
596
|
+
their records remain. Without `--json` the runs are printed in the columns of
|
|
597
|
+
`machine runs`. Without `--for`, `machine runs` is unchanged: every session's
|
|
598
|
+
running and waiting runs, as plain records.
|
|
599
|
+
|
|
600
|
+
Each item is the published record with three additions:
|
|
601
|
+
|
|
602
|
+
```json
|
|
603
|
+
{
|
|
604
|
+
"schemaVersion": 2, "id": "1a2b3c4d-…", "pid": 4242, "owner": "<session id>",
|
|
605
|
+
"machine": "release", "path": "/work/.machines/release.ts", "cwd": "/work",
|
|
606
|
+
"status": "waiting", "state": "approve",
|
|
607
|
+
"human": { "prompt": "Publish version 0.4.0?", "requestId": "9f8e7d6c-…", "choices": ["publish", "hold"] },
|
|
608
|
+
"startedAt": "2026-03-04T05:06:07.000Z", "updatedAt": "2026-03-04T05:08:12.000Z",
|
|
609
|
+
"shown": "owned",
|
|
610
|
+
"answer": { "via": "respond", "runId": "1a2b3c4d-…", "requestId": "9f8e7d6c-…" }
|
|
611
|
+
}
|
|
612
|
+
```
|
|
613
|
+
|
|
614
|
+
- `status` is the effective one: what the record says, or `lost`.
|
|
615
|
+
- `shown` says why the viewer shows the run: `owned`, `project`, or `watched`,
|
|
616
|
+
the first of them that holds.
|
|
617
|
+
- `answer` is present while the run waits on a Human request that something
|
|
618
|
+
can answer. `"via": "respond"` carries the two ids for
|
|
619
|
+
`machine respond <runId> <requestId> <response>`; `"via": "host"` means only
|
|
620
|
+
the program hosting the run can answer it, so a widget shows the prompt and
|
|
621
|
+
offers no input. `human` still has the prompt, choices, and suggestions.
|
|
622
|
+
|
|
623
|
+
Nothing is added for presentation: no colour, layout, or shortening, and no
|
|
624
|
+
limit on how many runs are returned. Recorded text is the run's own, so escape
|
|
625
|
+
it for your surface as the status line strips control characters.
|
|
626
|
+
|
|
627
|
+
The library gives the same answer without starting a process:
|
|
628
|
+
|
|
629
|
+
```ts
|
|
630
|
+
import {
|
|
631
|
+
readRunStatuses, readRunWatches, runStatusDirectory, runsForViewer,
|
|
632
|
+
} from "@dna113p/machines/run-status";
|
|
633
|
+
|
|
634
|
+
const directory = runStatusDirectory(); // undefined while publication is off
|
|
635
|
+
const runs = directory === undefined ? [] : runsForViewer(readRunStatuses(directory), {
|
|
636
|
+
sessionId,
|
|
637
|
+
projectDir: "/work/project",
|
|
638
|
+
watches: readRunWatches(directory, sessionId),
|
|
639
|
+
});
|
|
640
|
+
for (const run of runs) draw(run.label ?? run.id, run.status, run.shown, run.answer);
|
|
641
|
+
```
|
|
642
|
+
|
|
643
|
+
`runsForViewer(records, viewer, options)` is pure apart from probing whether
|
|
644
|
+
each process is alive; `options` takes `now`, `all`, and an `isAlive` of your
|
|
645
|
+
own. The module also exports `runSessionId`, the types of a record, a watch, a
|
|
646
|
+
viewer, and an item, and `settledRunVisibleMilliseconds`. It only reads:
|
|
647
|
+
publishing stays with the runtime, and a viewer's watch list is changed with
|
|
648
|
+
`machine watch --for`.
|
|
649
|
+
|
|
650
|
+
**Naming the session.** A viewer shows the runs whose `owner` is its session
|
|
651
|
+
id, so the host and the runs it starts must agree on that id. Any host can set
|
|
652
|
+
`MACHINES_RUN_OWNER` in the environment of the commands it starts and pass the
|
|
653
|
+
same value to `--for`; the id may use letters, digits, `.`, `_`, and `-`. Where
|
|
654
|
+
it is not set, the id is the one the coding agent already gives its commands:
|
|
655
|
+
|
|
656
|
+
| Host | Variable | Given to |
|
|
657
|
+
| --- | --- | --- |
|
|
658
|
+
| Any | `MACHINES_RUN_OWNER` | Whatever the host starts with it set; takes precedence |
|
|
659
|
+
| Claude Code | `CLAUDE_CODE_SESSION_ID` | The commands a session runs; also the `session_id` its status line receives |
|
|
660
|
+
| Codex | `CODEX_THREAD_ID` | The commands a thread runs |
|
|
661
|
+
| Pi | `PI_SESSION_ID` | The commands its `bash` and `powershell` tools run, not `!` commands typed by the user |
|
|
662
|
+
|
|
663
|
+
The first one that is set names the session, in that order. A run started from
|
|
664
|
+
inside one of these agents is therefore owned by that session: it is shown
|
|
665
|
+
there, and in another session only when that session watches it.
|
|
490
666
|
|
|
491
667
|
## Troubleshooting
|
|
492
668
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dna113p/machines",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.5",
|
|
4
4
|
"description": "Reusable workflows coordinating agents, local operations, and human decisions.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -20,29 +20,96 @@
|
|
|
20
20
|
},
|
|
21
21
|
"types": "./dist/src/index.d.ts",
|
|
22
22
|
"exports": {
|
|
23
|
-
".": {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
"./
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
"./
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
"./
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
"./
|
|
23
|
+
".": {
|
|
24
|
+
"types": "./dist/src/index.d.ts",
|
|
25
|
+
"import": "./dist/src/index.js"
|
|
26
|
+
},
|
|
27
|
+
"./acp": {
|
|
28
|
+
"types": "./dist/src/acp.d.ts",
|
|
29
|
+
"import": "./dist/src/acp.js"
|
|
30
|
+
},
|
|
31
|
+
"./agy": {
|
|
32
|
+
"types": "./dist/src/agy.d.ts",
|
|
33
|
+
"import": "./dist/src/agy.js"
|
|
34
|
+
},
|
|
35
|
+
"./chatgpt-web": {
|
|
36
|
+
"types": "./dist/src/chatgpt-web.d.ts",
|
|
37
|
+
"import": "./dist/src/chatgpt-web.js"
|
|
38
|
+
},
|
|
39
|
+
"./claude": {
|
|
40
|
+
"types": "./dist/src/claude.d.ts",
|
|
41
|
+
"import": "./dist/src/claude.js"
|
|
42
|
+
},
|
|
43
|
+
"./conversation": {
|
|
44
|
+
"types": "./dist/src/conversation.d.ts",
|
|
45
|
+
"import": "./dist/src/conversation.js"
|
|
46
|
+
},
|
|
47
|
+
"./codex": {
|
|
48
|
+
"types": "./dist/src/codex.d.ts",
|
|
49
|
+
"import": "./dist/src/codex.js"
|
|
50
|
+
},
|
|
51
|
+
"./deepseek": {
|
|
52
|
+
"types": "./dist/src/deepseek.d.ts",
|
|
53
|
+
"import": "./dist/src/deepseek.js"
|
|
54
|
+
},
|
|
55
|
+
"./decision": {
|
|
56
|
+
"types": "./dist/src/decision.d.ts",
|
|
57
|
+
"import": "./dist/src/decision.js"
|
|
58
|
+
},
|
|
59
|
+
"./jev": {
|
|
60
|
+
"types": "./dist/src/jev.d.ts",
|
|
61
|
+
"import": "./dist/src/jev.js"
|
|
62
|
+
},
|
|
63
|
+
"./openrouter": {
|
|
64
|
+
"types": "./dist/src/openrouter.d.ts",
|
|
65
|
+
"import": "./dist/src/openrouter.js"
|
|
66
|
+
},
|
|
67
|
+
"./laya": {
|
|
68
|
+
"types": "./dist/src/laya.d.ts",
|
|
69
|
+
"import": "./dist/src/laya.js"
|
|
70
|
+
},
|
|
71
|
+
"./von": {
|
|
72
|
+
"types": "./dist/src/von.d.ts",
|
|
73
|
+
"import": "./dist/src/von.js"
|
|
74
|
+
},
|
|
75
|
+
"./host": {
|
|
76
|
+
"types": "./dist/src/host.d.ts",
|
|
77
|
+
"import": "./dist/src/host.js"
|
|
78
|
+
},
|
|
79
|
+
"./launcher": {
|
|
80
|
+
"types": "./dist/src/launcher.d.ts",
|
|
81
|
+
"import": "./dist/src/launcher.js"
|
|
82
|
+
},
|
|
83
|
+
"./mcp": {
|
|
84
|
+
"types": "./dist/mcp/server.d.ts",
|
|
85
|
+
"import": "./dist/mcp/server.js"
|
|
86
|
+
},
|
|
87
|
+
"./pi-extension": {
|
|
88
|
+
"types": "./dist/pi-extension/index.d.ts",
|
|
89
|
+
"import": "./dist/pi-extension/index.js"
|
|
90
|
+
},
|
|
91
|
+
"./run-status": {
|
|
92
|
+
"types": "./dist/src/run-viewer.d.ts",
|
|
93
|
+
"import": "./dist/src/run-viewer.js"
|
|
94
|
+
}
|
|
40
95
|
},
|
|
41
|
-
"files": [
|
|
96
|
+
"files": [
|
|
97
|
+
"dist",
|
|
98
|
+
"claude/statusline.mjs",
|
|
99
|
+
"docs/architecture.md",
|
|
100
|
+
"docs/authoring.md",
|
|
101
|
+
"docs/integrations.md",
|
|
102
|
+
"docs/local-decisions.md",
|
|
103
|
+
"services/laya/server.py",
|
|
104
|
+
"skills",
|
|
105
|
+
"LICENSE",
|
|
106
|
+
"README.md"
|
|
107
|
+
],
|
|
42
108
|
"scripts": {
|
|
43
109
|
"build": "node scripts/build.mjs",
|
|
44
110
|
"build:plugin": "npm run build && node scripts/build-plugin.mjs",
|
|
45
|
-
"check": "npm run typecheck && npm test",
|
|
111
|
+
"check": "npm run lint && npm run typecheck && npm test",
|
|
112
|
+
"lint": "oxlint --deny-warnings",
|
|
46
113
|
"example": "node examples/operation.ts",
|
|
47
114
|
"example:agents": "node examples/named-agents.ts",
|
|
48
115
|
"example:agy": "node examples/agy.ts",
|
|
@@ -72,6 +139,7 @@
|
|
|
72
139
|
},
|
|
73
140
|
"devDependencies": {
|
|
74
141
|
"@types/node": "^24.0.0",
|
|
142
|
+
"oxlint": "^1.87.0",
|
|
75
143
|
"typescript": "^7.0.2"
|
|
76
144
|
}
|
|
77
145
|
}
|
|
@@ -31,6 +31,11 @@ needs. Existing Machines and examples are starting points, not a fixed menu.
|
|
|
31
31
|
Make consequential checks and decisions explicit in states when they need to
|
|
32
32
|
control progress. Choose the complexity needed to complete the task reliably.
|
|
33
33
|
|
|
34
|
+
Machine Shop is an optional starter library of common software-task Machines,
|
|
35
|
+
kept in its own repository at `https://github.com/dna113p/machine-shop`. Nothing
|
|
36
|
+
here requires it; clone it to try a default or adapt one, as
|
|
37
|
+
[machine-project-setup](../machine-project-setup/SKILL.md) describes.
|
|
38
|
+
|
|
34
39
|
Look for common task sequences and recurring manual workflows while doing the
|
|
35
40
|
work. Convert them into Machines when explicit steps would improve repeatability
|
|
36
41
|
or code quality. Parameterize assignment details so the workflow can serve the
|
|
@@ -82,3 +87,29 @@ Agent runners or injected Human input where possible. A successful run reaches
|
|
|
82
87
|
the intended final state and produces the requested artifact or effect. Run real
|
|
83
88
|
external work only within the user's authorized scope. Report what was verified
|
|
84
89
|
and any branch that still requires a configured harness or human interaction.
|
|
90
|
+
|
|
91
|
+
## Checks the Machine owns
|
|
92
|
+
|
|
93
|
+
Design the workflow so these checks control progress and leave evidence for the
|
|
94
|
+
next repair round or person taking over:
|
|
95
|
+
|
|
96
|
+
- Run every gate, not only up to the first failure, so one repair round sees
|
|
97
|
+
all failures.
|
|
98
|
+
- Keep the project's gate list in one place that every route reads.
|
|
99
|
+
- For new behaviour, write tests first; have an Operation see them fail before
|
|
100
|
+
implementation, then pass after implementation.
|
|
101
|
+
- After each editing Agent, run an Operation that compares the changed paths
|
|
102
|
+
against the paths the assignment allows.
|
|
103
|
+
- Ask for a structured review: each acceptance criterion met or not, findings
|
|
104
|
+
tagged by severity. Let an Operation, not the reviewer's verdict word, decide
|
|
105
|
+
what happens next.
|
|
106
|
+
- Match a reviewer's findings across rounds by their place in the conversation,
|
|
107
|
+
never by their wording.
|
|
108
|
+
- End stuck unattended runs with work kept and a written note of what a person
|
|
109
|
+
must decide, instead of waiting in a Human state. Every stop keeps both so a later
|
|
110
|
+
run or a person can continue from them.
|
|
111
|
+
- Before implementation, have a read-only Agent try to show the assignment is
|
|
112
|
+
wrong, already done, or underspecified; require options and a recommended answer
|
|
113
|
+
for each question it raises.
|
|
114
|
+
- Tell editing Agents that checks they cannot run in their environment are the
|
|
115
|
+
workflow's to run, so a sandboxed Agent returns its work instead of `blocked`.
|
|
@@ -62,6 +62,16 @@ Workers do not inherit this conversation. Supply the context needed to act:
|
|
|
62
62
|
- Applicable constraints, permitted effects, and what should produce a blocked outcome.
|
|
63
63
|
- A result location readable by the coordinator, and what evidence it must contain.
|
|
64
64
|
|
|
65
|
+
State these five fields for each assignment:
|
|
66
|
+
|
|
67
|
+
1. Its goal.
|
|
68
|
+
2. The paths it may change.
|
|
69
|
+
3. Its acceptance criteria.
|
|
70
|
+
4. How it will be verified.
|
|
71
|
+
5. What is forbidden.
|
|
72
|
+
|
|
73
|
+
A field that cannot be filled means the unit is not scoped yet.
|
|
74
|
+
|
|
65
75
|
Follow the selected Machine's input contract. MCP/Pi accept JSON-serializable
|
|
66
76
|
input; CLI positional input is text, while `--input-file <file|->` accepts JSON.
|
|
67
77
|
Keep task details in input rather than hardcoding each assignment into a new
|
|
@@ -103,6 +113,15 @@ polling continuously. Interpret the current snapshot:
|
|
|
103
113
|
Preserve existing user authorization when answering Human requests, and surface a
|
|
104
114
|
new decision when the request requires one. A desire to finish is not an answer.
|
|
105
115
|
|
|
116
|
+
A `blocked` or parked run is a completed run to read, not a failure to retry blindly.
|
|
117
|
+
Design stuck unattended runs to end with work kept and a written note of what a
|
|
118
|
+
person must decide, instead of waiting in a Human state; every stop keeps both.
|
|
119
|
+
Read the note, answer it or take it to the user, then start a fresh run from the
|
|
120
|
+
kept work and note when resolved, or let a person continue from them.
|
|
121
|
+
|
|
122
|
+
Tell an editing Agent that checks it cannot run in its environment are the
|
|
123
|
+
workflow's to run, so a sandboxed Agent returns its work instead of `blocked`.
|
|
124
|
+
|
|
106
125
|
To follow a run this session did not start, such as a ticket a daemon runs, use
|
|
107
126
|
`machine watch <ticket-or-run-id>` where run status is published (`machine runs`
|
|
108
127
|
lists what can be watched; `--all` adds runs that already ended). Watching only
|
|
@@ -126,3 +145,7 @@ verified. Read the report and inspect relevant changes or checks, then integrate
|
|
|
126
145
|
the result into the user's task. If evidence is missing, treat that as incomplete
|
|
127
146
|
work even if the run says `completed`. Report the useful result, any blocker, and
|
|
128
147
|
artifact paths; a run ID alone is not the delegated deliverable.
|
|
148
|
+
|
|
149
|
+
Read the reviewer's structured report: each acceptance criterion met or not,
|
|
150
|
+
findings tagged by severity. Let an Operation, not the reviewer's verdict word,
|
|
151
|
+
decide what happens next.
|
|
@@ -29,6 +29,19 @@ types, quality gates, recurring failure modes, and decisions needing a Human.
|
|
|
29
29
|
Include domain-specific work, not just generic coding stages. Use only relevant,
|
|
30
30
|
available project context; distinguish observed needs from speculative ones.
|
|
31
31
|
|
|
32
|
+
Inventory the project's deterministic checks before designing any workflow, by
|
|
33
|
+
class: lint, types, tests, build, and a live check that drives the real artifact
|
|
34
|
+
(a packaging smoke, an install test, a CLI or service run against a scratch
|
|
35
|
+
directory). Take them from the project's own scripts and CI, not from a fixed
|
|
36
|
+
list, and run each once to learn its duration and that it leaves the checkout
|
|
37
|
+
clean. Record the inventory in the map, naming the classes the project has no
|
|
38
|
+
command for; a missing class is a finding for the owner, not something to
|
|
39
|
+
invent. Put the resulting gate list in one project-owned place that every
|
|
40
|
+
route reads (a configuration file the launchers load, not a copy in each
|
|
41
|
+
launcher), so an Agent is held to the same gates a person runs. Where the
|
|
42
|
+
project's checks stop at the first failure, prefer running every gate and
|
|
43
|
+
reporting all failures at once: one repair round then sees them all.
|
|
44
|
+
|
|
32
45
|
Inspect the existing orchestrator instructions and any `.machines/README.md`.
|
|
33
46
|
Run `machine list` and `machine agents` in the actual work directories, or use
|
|
34
47
|
`machine_list` / `machine_agents` with the correct workspace. Read candidate
|
|
@@ -95,11 +108,16 @@ instead of presenting same-model review as independent.
|
|
|
95
108
|
|
|
96
109
|
## Build the smallest useful set
|
|
97
110
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
111
|
+
Machine Shop is an optional starter library of common software-task Machines:
|
|
112
|
+
implementation, bug fixing, review, investigation, and model-free verification
|
|
113
|
+
among them. Nothing here requires it, but it is a good set of defaults to try
|
|
114
|
+
before rebuilding a common software process. It is a separate repository,
|
|
115
|
+
`https://github.com/dna113p/machine-shop`, and is not installed with the runtime;
|
|
116
|
+
when no checkout is present, tell the user about it or clone it to try it out.
|
|
117
|
+
Read its `docs/catalog.md` and the candidate `defaults/` sources, then run one
|
|
118
|
+
from source or copy selected entries with its project-local installer; do not
|
|
119
|
+
install the entire catalog by default. Its check commands, Agent bindings, and
|
|
120
|
+
task inputs remain project-specific.
|
|
103
121
|
|
|
104
122
|
Map the major work to existing or missing workflows. Favor frequent delegation,
|
|
105
123
|
important quality gates, and costly recurring mistakes. Reuse good definitions;
|
|
@@ -19,6 +19,10 @@ For each major task type, record:
|
|
|
19
19
|
- Expected final state, checks, result retrieval, and verification command.
|
|
20
20
|
- Allowed effects, Human decisions, retry limits, and untested prerequisites.
|
|
21
21
|
|
|
22
|
+
Record the gate inventory once, by class (lint, types, tests, build, live
|
|
23
|
+
check): the command for each, where the one list that every route reads lives,
|
|
24
|
+
and the classes the project has no command for.
|
|
25
|
+
|
|
22
26
|
Mark deliberately direct, deferred, or blocked work with its reason. An existing
|
|
23
27
|
setup may need no new Machine. Do not generate placeholders to fill categories.
|
|
24
28
|
Include copyable invocations only for routes that exist. CLI positional input is
|