@bluewombat/runtime 0.8.0 → 0.10.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 +236 -142
- package/SPECS.md +138 -97
- package/dist/cli.js +35 -37
- package/dist/cli.js.map +1 -1
- package/dist/config/agent-shorthand.d.ts +24 -4
- package/dist/config/agent-shorthand.d.ts.map +1 -1
- package/dist/config/agent-shorthand.js +65 -28
- package/dist/config/agent-shorthand.js.map +1 -1
- package/dist/config/defaults.d.ts +0 -2
- package/dist/config/defaults.d.ts.map +1 -1
- package/dist/config/defaults.js +0 -2
- package/dist/config/defaults.js.map +1 -1
- package/dist/config/find-config.d.ts +3 -2
- package/dist/config/find-config.d.ts.map +1 -1
- package/dist/config/find-config.js +4 -4
- package/dist/config/find-config.js.map +1 -1
- package/dist/config/home.d.ts +2 -0
- package/dist/config/home.d.ts.map +1 -1
- package/dist/config/home.js +4 -2
- package/dist/config/home.js.map +1 -1
- package/dist/config/load-config.d.ts +2 -2
- package/dist/config/load-config.d.ts.map +1 -1
- package/dist/config/load-config.js +342 -73
- package/dist/config/load-config.js.map +1 -1
- package/dist/config/parse-args.d.ts +1 -1
- package/dist/config/parse-args.d.ts.map +1 -1
- package/dist/config/parse-args.js +132 -103
- package/dist/config/parse-args.js.map +1 -1
- package/dist/config/types.d.ts +142 -38
- package/dist/config/types.d.ts.map +1 -1
- package/dist/config/types.js +13 -1
- package/dist/config/types.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/loop/authority.d.ts +41 -5
- package/dist/loop/authority.d.ts.map +1 -1
- package/dist/loop/authority.js +68 -24
- package/dist/loop/authority.js.map +1 -1
- package/dist/loop/context.d.ts +23 -3
- package/dist/loop/context.d.ts.map +1 -1
- package/dist/loop/deliveries.d.ts +16 -16
- package/dist/loop/deliveries.d.ts.map +1 -1
- package/dist/loop/deliveries.js +35 -187
- package/dist/loop/deliveries.js.map +1 -1
- package/dist/loop/describe.d.ts +4 -6
- package/dist/loop/describe.d.ts.map +1 -1
- package/dist/loop/describe.js +2 -2
- package/dist/loop/describe.js.map +1 -1
- package/dist/loop/drive.d.ts +11 -7
- package/dist/loop/drive.d.ts.map +1 -1
- package/dist/loop/drive.js +24 -38
- package/dist/loop/drive.js.map +1 -1
- package/dist/loop/features.d.ts +23 -0
- package/dist/loop/features.d.ts.map +1 -0
- package/dist/loop/features.js +834 -0
- package/dist/loop/features.js.map +1 -0
- package/dist/loop/journal.d.ts +1 -1
- package/dist/loop/journal.js +2 -2
- package/dist/loop/journal.js.map +1 -1
- package/dist/loop/lock.d.ts +1 -1
- package/dist/loop/lock.js +1 -1
- package/dist/loop/open-host.d.ts.map +1 -1
- package/dist/loop/open-host.js +132 -31
- package/dist/loop/open-host.js.map +1 -1
- package/dist/loop/probe.d.ts +1 -1
- package/dist/loop/probe.d.ts.map +1 -1
- package/dist/loop/probe.js +51 -22
- package/dist/loop/probe.js.map +1 -1
- package/dist/loop/process-tree.d.ts +1 -1
- package/dist/loop/process-tree.js +1 -1
- package/dist/loop/report.d.ts +9 -7
- package/dist/loop/report.d.ts.map +1 -1
- package/dist/loop/report.js +49 -106
- package/dist/loop/report.js.map +1 -1
- package/dist/loop/streams.d.ts +5 -5
- package/dist/loop/streams.d.ts.map +1 -1
- package/dist/loop/streams.js +3 -3
- package/dist/loop/streams.js.map +1 -1
- package/dist/loop/tick.d.ts +6 -4
- package/dist/loop/tick.d.ts.map +1 -1
- package/dist/loop/tick.js +50 -78
- package/dist/loop/tick.js.map +1 -1
- package/dist/loop/trace.d.ts +5 -5
- package/dist/loop/trace.d.ts.map +1 -1
- package/dist/loop/trace.js +5 -14
- package/dist/loop/trace.js.map +1 -1
- package/dist/loop/transformers.d.ts +18 -14
- package/dist/loop/transformers.d.ts.map +1 -1
- package/dist/loop/transformers.js +139 -74
- package/dist/loop/transformers.js.map +1 -1
- package/dist/loop/warm.d.ts +3 -3
- package/dist/loop/warm.js +4 -4
- package/dist/loop/warm.js.map +1 -1
- package/dist/loop/work-line.d.ts +1 -1
- package/dist/operator/agent-plugins.d.ts +11 -0
- package/dist/operator/agent-plugins.d.ts.map +1 -1
- package/dist/operator/agent-plugins.js +17 -11
- package/dist/operator/agent-plugins.js.map +1 -1
- package/dist/operator/board.d.ts +3 -8
- package/dist/operator/board.d.ts.map +1 -1
- package/dist/operator/board.js +2 -11
- package/dist/operator/board.js.map +1 -1
- package/dist/operator/cancel.d.ts +2 -2
- package/dist/operator/cancel.js +6 -6
- package/dist/operator/cancel.js.map +1 -1
- package/dist/operator/doctor.d.ts +9 -0
- package/dist/operator/doctor.d.ts.map +1 -1
- package/dist/operator/doctor.js +110 -53
- package/dist/operator/doctor.js.map +1 -1
- package/dist/operator/explain.d.ts +76 -0
- package/dist/operator/explain.d.ts.map +1 -0
- package/dist/operator/explain.js +585 -0
- package/dist/operator/explain.js.map +1 -0
- package/dist/operator/film.d.ts +3 -11
- package/dist/operator/film.d.ts.map +1 -1
- package/dist/operator/film.js +8 -93
- package/dist/operator/film.js.map +1 -1
- package/dist/operator/init.d.ts.map +1 -1
- package/dist/operator/init.js +52 -55
- package/dist/operator/init.js.map +1 -1
- package/dist/operator/live.js +1 -1
- package/dist/operator/live.js.map +1 -1
- package/dist/operator/log.js +12 -6
- package/dist/operator/log.js.map +1 -1
- package/dist/operator/release.d.ts +2 -2
- package/dist/operator/release.js +7 -7
- package/dist/operator/release.js.map +1 -1
- package/dist/operator/run.d.ts +25 -0
- package/dist/operator/run.d.ts.map +1 -0
- package/dist/operator/run.js +70 -0
- package/dist/operator/run.js.map +1 -0
- package/dist/operator/setup.d.ts.map +1 -1
- package/dist/operator/setup.js +22 -16
- package/dist/operator/setup.js.map +1 -1
- package/dist/plugins/manager.d.ts +33 -2
- package/dist/plugins/manager.d.ts.map +1 -1
- package/dist/plugins/manager.js +67 -0
- package/dist/plugins/manager.js.map +1 -1
- package/package.json +15 -16
package/SPECS.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
# Host
|
|
2
2
|
|
|
3
3
|
The composition root, not a Transformer. It is the process you run: Cursor, admission,
|
|
4
|
-
Conductor, report. It is not a
|
|
4
|
+
Conductor, report. It is not a TicketStandard transformer and it is not a
|
|
5
5
|
sequencer — Conductor sequences; this package calls it.
|
|
6
6
|
|
|
7
|
-
Host does not know a tracker. It resolves one
|
|
8
|
-
the options it never reads, and drives the `
|
|
7
|
+
Host does not know a tracker. It resolves one TicketTracker package, hands it
|
|
8
|
+
the options it never reads, and drives the `Manager` (a FeatureTracker and a TicketTracker) that package returns.
|
|
9
9
|
Adding GitLab or Jira changes nothing here.
|
|
10
10
|
|
|
11
11
|
## 1. Job
|
|
@@ -19,7 +19,7 @@ Adding GitLab or Jira changes nothing here.
|
|
|
19
19
|
persist) no longer lists Publisher / Refresher slots
|
|
20
20
|
the work line copy refresh the work line copy
|
|
21
21
|
one Delivery at a time:
|
|
22
|
-
admit /
|
|
22
|
+
admit / resume / cancel,
|
|
23
23
|
reconcile, drive, report,
|
|
24
24
|
save Cursor
|
|
25
25
|
sweep: drive what is in flight
|
|
@@ -29,7 +29,7 @@ Adding GitLab or Jira changes nothing here.
|
|
|
29
29
|
|
|
30
30
|
**In:** WorkLineStable, how to isolate and fold it (`workLine.isolation`),
|
|
31
31
|
workspace root, ledger root, a manager specifier and its opaque options,
|
|
32
|
-
|
|
32
|
+
Builder / Gate argv.
|
|
33
33
|
**Out:** a typed result. The CLI maps that to an exit code.
|
|
34
34
|
|
|
35
35
|
## 2. Faces
|
|
@@ -37,12 +37,12 @@ Planner / Builder / Gate argv.
|
|
|
37
37
|
| Face | Entry | Must not |
|
|
38
38
|
| ------ | ------------------------------------------------------------------------------------- | --------------------------------------------- |
|
|
39
39
|
| Import | `openHost(options)` then `runOnce` / `run` | Live inside Conductor `src/run/` |
|
|
40
|
-
| CLI | `mason run \| watch \| status \| log \| cancel \| release \| init \| setup \| doctor` | Interpret a
|
|
40
|
+
| CLI | `mason run \| watch \| status \| log \| cancel \| release \| init \| setup \| doctor` | Interpret a TicketStandard; pick Child paths |
|
|
41
41
|
|
|
42
42
|
`src/loop/` is the process: `open-host.ts` opens packages (composition),
|
|
43
43
|
`tick.ts` runs the listen / probe / Cursor / sweep loop, `deliveries.ts` handles one
|
|
44
|
-
Delivery, `drive.ts` runs one Project and reports on the
|
|
45
|
-
`report.ts` maps Conductor outcomes to
|
|
44
|
+
Delivery, `drive.ts` runs one Project and reports on the Ticket that ran,
|
|
45
|
+
`report.ts` maps Conductor outcomes to TicketTracker Events,
|
|
46
46
|
`journal.ts` and `trace.ts` are its film and its stdout. `loop/` may import
|
|
47
47
|
Transformer packages: this package **is** the composition root for the
|
|
48
48
|
execution Transformers. Conductor still must not. Host must not import a
|
|
@@ -55,11 +55,11 @@ import rule between them are in [README.md](./README.md) § Layers.
|
|
|
55
55
|
`mason.config.yaml`, found by walking up from the working directory, or the
|
|
56
56
|
file `--config` names. Relative paths in the file resolve against the file;
|
|
57
57
|
relative paths in a flag resolve against the working directory. Flags override
|
|
58
|
-
the file. `--
|
|
58
|
+
the file. `--feature-tracker-option key=value` (and `--ticket-tracker-option`) merges per key, so overriding one option
|
|
59
59
|
does not drop the others; a repeated key becomes an array.
|
|
60
60
|
|
|
61
61
|
Host validates only its own keys, against a closed list: an unknown key is a
|
|
62
|
-
refusal, not something ignored. `
|
|
62
|
+
refusal, not something ignored. Each side's `options` is copied through untouched:
|
|
63
63
|
a tracker's fields are that package's business, and its errors are that
|
|
64
64
|
package's words.
|
|
65
65
|
|
|
@@ -71,7 +71,7 @@ See § 8.
|
|
|
71
71
|
|
|
72
72
|
## 4. Loading a manager
|
|
73
73
|
|
|
74
|
-
`
|
|
74
|
+
`featureTracker.package` and `ticketTracker.package` are each a package name or a path. The two sides may name the same package or two different ones: a package asked for a side it does not answer is refused by name. One package with the same options on both sides is built once. `doctor` and `setup` run each distinct manager once; the reference work line is named by the ticket tracker, which holds the Authority. Resolution imports the bare specifier
|
|
75
75
|
first — mason and its managers installed side by side in one project — then
|
|
76
76
|
walks up from the config file's directory, which covers a global `mason`
|
|
77
77
|
driving a locally installed manager. A module without `createManager` is
|
|
@@ -95,41 +95,85 @@ not losing an Event.
|
|
|
95
95
|
|
|
96
96
|
## 6. One Delivery
|
|
97
97
|
|
|
98
|
+
The FeatureTracker's `listen` delivers Features whose specification is final.
|
|
98
99
|
`adapt` first. Then:
|
|
99
100
|
|
|
100
|
-
| Adapter | Host
|
|
101
|
-
| ------------------------------------------- |
|
|
102
|
-
| `invalid` (new, or the intention changed) |
|
|
103
|
-
| `invalid` (same fingerprint as recorded) | leave it; the tracker was told, and telling it is what delivered it again
|
|
104
|
-
| `upsert` (
|
|
105
|
-
| `upsert` (
|
|
106
|
-
| `upsert` (
|
|
107
|
-
| `upsert` + `
|
|
108
|
-
| `
|
|
109
|
-
| `cancel` | `
|
|
110
|
-
| `unavailable` / interrupt | stop the tick
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
101
|
+
| Adapter | Host |
|
|
102
|
+
| ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
103
|
+
| `invalid` (new, or the intention changed) | emit `invalid` on the Feature, keyed by fingerprint |
|
|
104
|
+
| `invalid` (same fingerprint as recorded) | leave it; the tracker was told, and telling it is what delivered it again |
|
|
105
|
+
| `upsert` (absent or `waiting`) | `admitFeature`, emit `accepted`. Nothing is driven here: the sweep does it |
|
|
106
|
+
| `upsert` (`open` or `escalated`) whose `skip_e2e` differs from the ledger's | `setFeatureSkipE2e`; journal `skip-e2e`; no other change |
|
|
107
|
+
| `upsert` (any other state) | leave it; journal `skipped`. An echo of a Host report is this row |
|
|
108
|
+
| `upsert` + `signalsResume` while `escalated` | same as `resume` — a poll snapshot has no `labeled` edge |
|
|
109
|
+
| `resume` | resume the Feature, emit `resumed` |
|
|
110
|
+
| `cancel` | `cancelFeatureFlow`: the Tickets not done are cancelled, the line is dropped, the Project is free |
|
|
111
|
+
| `unavailable` / interrupt | stop the tick |
|
|
112
|
+
|
|
113
|
+
A Ticket is never delivered: the sweep reads the Tickets of the open Feature
|
|
114
|
+
from the TicketTracker (`tickets`). A `resume` on an escalated Ticket, an edit of
|
|
115
|
+
a Ticket not yet started, a Ticket closed on the tracker are read there
|
|
116
|
+
(`syncTickets`) and acted on the same way as for a Feature. A Ticket in flight is
|
|
117
|
+
not admitted again on each pass; only a `received` Ticket whose fingerprint
|
|
118
|
+
changed is.
|
|
119
|
+
|
|
120
|
+
### The sweep: one Feature per Project
|
|
121
|
+
|
|
122
|
+
Every pass, each Project with a `waiting`, `open` or `submitted` Feature is
|
|
123
|
+
advanced (`advanceProject`):
|
|
124
|
+
|
|
125
|
+
1. No active Feature: open the next one that may. A Feature may open when every
|
|
126
|
+
Feature blocking it is `done`, and every one of its Tickets
|
|
127
|
+
(`tickets`) is `task_ready`. Order: priority, then age. The Feature is then
|
|
128
|
+
`open`: with an Authority, its line `feature/<id>` is cut from the final
|
|
129
|
+
branch (`openLine`); the Tickets are admitted with their Feature and their
|
|
130
|
+
blockers.
|
|
131
|
+
2. `open`: the work line copy is refreshed onto the line, then Tickets are
|
|
132
|
+
driven one at a time (a Ticket whose blockers are not `done` is skipped; the
|
|
133
|
+
next by priority then age is taken). Each Ticket's Submission targets the line. When every Ticket
|
|
134
|
+
is `done` or `cancelled` the Feature is closed: the line goes to the
|
|
135
|
+
Authority (`submit`). With no Authority the Feature is `done` at once.
|
|
136
|
+
3. `submitted`: the Feature waits. Without `merge-when-ready` a human folds it;
|
|
137
|
+
`settled` says `folded` (done) or `closed` (escalated). With
|
|
138
|
+
`merge-when-ready` the assembly judgement runs on the line and the Authority
|
|
139
|
+
folds it. No other Feature opens on the Project meanwhile.
|
|
140
|
+
4. A Feature whose Tickets are all blocked escalates; one that cannot be
|
|
141
|
+
settled because the Authority lacks `settled` waits.
|
|
142
|
+
|
|
143
|
+
The e2e acceptance check, when the Project declares it (`builder.e2e`):
|
|
144
|
+
|
|
145
|
+
- A Feature does not open (and is reported `invalid`, once per reason) unless it holds exactly
|
|
146
|
+
one e2e Ticket (`TicketEntry.e2e`), blocked by every other live Ticket, or carries `skip_e2e`.
|
|
147
|
+
- A Ticket with `e2e` is admitted with `e2e` and `no_tests`: no tests are written first, and
|
|
148
|
+
Transformers makes it with `builder.e2e` (its command, its Gates, for the first pass, a refused
|
|
149
|
+
pass and the recheck) instead of the producer and the repair.
|
|
150
|
+
- A Feature with `skip_e2e` has its e2e Ticket cancelled by the sweep (journal
|
|
151
|
+
`e2e-ticket-cancelled`, a trace line), and Transformers leaves out, for that Feature, every
|
|
152
|
+
Gate of `feature.validate`, `feature.gates` and `feature.fix` that has `skipWhen:
|
|
153
|
+
skip-test-e2e`: the journal gets `gate-skipped` with the Gate id and the reason, and the trace
|
|
154
|
+
says "`<id>` not run: the Feature carries skip-test-e2e". The mark is read from the ledger as
|
|
155
|
+
each pass starts (`TransformerSlots.marks`).
|
|
156
|
+
- A Feature that is not marked and no longer holds a live e2e Ticket (it was cancelled while the
|
|
157
|
+
mark was on) escalates when it closes.
|
|
158
|
+
|
|
159
|
+
Host never drives an `escalated` unit: that state is frozen until a human `resume`.
|
|
114
160
|
|
|
115
161
|
Every Event Host emits is a write to the tracker, and a tracker that lists by
|
|
116
162
|
"last updated" delivers the intention again on the next pass because of that
|
|
117
163
|
write. No row above may emit on that echo: `invalid` is keyed by fingerprint,
|
|
118
164
|
`accepted` by the ledger not knowing the key (or knowing it `invalid`), the
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
refusing a second cancel, an in-flight Feature (including `submitted`) by
|
|
165
|
+
post-run Events by the Ticket that was driven, `resumed` by taking the signal back, `cancelled` by the ledger
|
|
166
|
+
refusing a second cancel, an in-flight Ticket (including `submitted`) by
|
|
122
167
|
leaving the upsert.
|
|
123
168
|
|
|
124
169
|
On top of that, every Event that states a fact carries an `eventId`, so a
|
|
125
170
|
manager that already has it says nothing — after a restart as much as within
|
|
126
171
|
a pass. The id names the fact: `<key>:accepted:<fingerprint>` and
|
|
127
|
-
`<key>:invalid:<fingerprint>` (an edit is a new fact), `<key>:
|
|
128
|
-
`<key>:
|
|
129
|
-
`<key>:
|
|
130
|
-
`<key>:escalated:<round>:<kind>[:<subtask>]`, `<key>:done`,
|
|
172
|
+
`<key>:invalid:<fingerprint>` (an edit is a new fact), `<key>:submitted:<reference>`,
|
|
173
|
+
`<key>:refused:<n>`, `<key>:resumed:<round>`,
|
|
174
|
+
`<key>:escalated:<round>:<kind>`, `<key>:done`,
|
|
131
175
|
`<key>:cancelled`, `<key>:reject_late:…`. The round is the ledger's count of
|
|
132
|
-
`
|
|
176
|
+
`resume` taken: an escalation resumed and escalated again has the same Attempt
|
|
133
177
|
count both times, and only the round tells the two escalations apart.
|
|
134
178
|
`escalation_reminder` alone would carry none, repetition being its point.
|
|
135
179
|
|
|
@@ -147,7 +191,7 @@ than waited for; the Transformer then answers `interrupted`. `mason run` exits
|
|
|
147
191
|
|
|
148
192
|
Each pass appends JSON lines to `<ledgerRoot>/events.jsonl` (listen, probed,
|
|
149
193
|
Transformer progress, admitted, reported, queued, idle, a heartbeat while
|
|
150
|
-
`submitted`, one `held` while a
|
|
194
|
+
`submitted`, one `held` while a unit waits on a bail that has not expired).
|
|
151
195
|
Every report to the tracker is filmed with how long it took (`ms`): `reported`
|
|
152
196
|
when the manager took it (including a Thread that already carried that eventId
|
|
153
197
|
— a duplicate is already said), `report-declined` when it failed. That file is
|
|
@@ -156,7 +200,7 @@ the ledger is still right. `mason run` still writes a human Trace on stdout.
|
|
|
156
200
|
The journal is how another process attaches.
|
|
157
201
|
|
|
158
202
|
An offer the work could not get past is journaled `submit-refused`, with the
|
|
159
|
-
|
|
203
|
+
Ticket's `key`, `by` (`publisher` when the work could not be placed,
|
|
160
204
|
`authority` when the Authority would not open a Submission) and the refuser's
|
|
161
205
|
own `reason`. The same reason becomes the escalation's Trace; the line is so
|
|
162
206
|
`mason log --problems` and a watcher see why a run stopped, not only that it
|
|
@@ -164,47 +208,43 @@ did.
|
|
|
164
208
|
|
|
165
209
|
After listen, if the manager declares `probe` and the listen reached the source
|
|
166
210
|
(`completed`, `listened` — not `source-lost` / `interrupted` / `invalid-invocation`),
|
|
167
|
-
Host asks `probe` of every Feature
|
|
168
|
-
|
|
211
|
+
Host asks the FeatureTracker's `probe` of every Feature, and the
|
|
212
|
+
TicketTracker's of every Ticket, abandon is still legal for. `gone` is the
|
|
169
213
|
same abandon as a `cancel` delivery, so a deleted item a poll can never list
|
|
170
214
|
still frees the Project; `unavailable` is not abandon. Probe runs before the
|
|
171
215
|
work-line refresh and the deliveries, so a cancel in this pass can start the
|
|
172
216
|
`received` queue on a copy that was just fast-forwarded.
|
|
173
217
|
|
|
174
|
-
The sweep after the deliveries
|
|
175
|
-
|
|
176
|
-
was driven.
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
copy: starting a queued Feature on a copy that was not fast-forwarded this
|
|
180
|
-
tick would build on a version that no longer exists.
|
|
218
|
+
The sweep after the deliveries advances every Project that has a `waiting`,
|
|
219
|
+
`open` or `submitted` Feature, once per tick (§ 6). The result is reported on
|
|
220
|
+
the Ticket that was driven. The work line copy is refreshed onto the Feature's
|
|
221
|
+
line before a Ticket starts: starting on a copy that was not fast-forwarded
|
|
222
|
+
would build on a version that no longer exists.
|
|
181
223
|
|
|
182
224
|
## 8. init, setup, doctor, watch, status, log, cancel and release
|
|
183
225
|
|
|
184
|
-
`init` writes a config that already runs: the
|
|
185
|
-
`@bluewombat/slots/planners/`, the Builder is a stub that says what to replace
|
|
226
|
+
`init` writes a config that already runs: the Builder is a stub that says what to replace
|
|
186
227
|
(example Cursor CLI and Claude Code Builders live in `@bluewombat/slots/builders/`),
|
|
187
228
|
and the Gate sequence starts empty. Example Gates live in
|
|
188
229
|
`@bluewombat/slots/gates/` (`parent-clean`, `sensitive-path`,
|
|
189
230
|
`workspace-changed`, `ci-green`).
|
|
190
231
|
|
|
191
|
-
|
|
192
|
-
`builder.
|
|
193
|
-
`
|
|
194
|
-
|
|
195
|
-
dispatched between buckets: a check that is right for one pass can be wrong
|
|
232
|
+
Four Gate sequences: `builder.gates`, shared by `builder.producer` and
|
|
233
|
+
`builder.repair`, then `ticket.fix.gates`, `ticket.validate.gates` and
|
|
234
|
+
`ticket.gates` for the one judgement-only pass with no producer of its own.
|
|
235
|
+
The assembly sequences are not shared and nothing is dispatched between buckets: a check that is right for one pass can be wrong
|
|
196
236
|
for another, even within the same stage — `workspace-changed` says an Attempt
|
|
197
237
|
that changed nothing did nothing, which is true of `builder.producer`/`repair`
|
|
198
|
-
and false of `
|
|
199
|
-
was left to do.
|
|
200
|
-
|
|
238
|
+
and false of `ticket.gates`'s pass, whose correct outcome is that nothing
|
|
239
|
+
was left to do. A repair Attempt is judged by `builder.gates`, the same list as the
|
|
240
|
+
producer's (Host hands Implementer that list as both `gates` and `repairGates`). The assembly's
|
|
201
241
|
judgement-only pass produces nothing unless something refused it first: it is
|
|
202
|
-
a judgement, and a refusal is `
|
|
203
|
-
things may judge it: `
|
|
204
|
-
was published) and, optionally, `
|
|
205
|
-
that runs before either, judged by its own `
|
|
206
|
-
`
|
|
207
|
-
`maxRefusals` budget.
|
|
242
|
+
a judgement, and a refusal is `ticket.fix`, not a second first-pass. Two
|
|
243
|
+
things may judge it: `ticket.gates` (and an Authority's own checks on what
|
|
244
|
+
was published) and, optionally, `ticket.validate` — a local, read-only pass
|
|
245
|
+
that runs before either, judged by its own `ticket.validate.gates`, not
|
|
246
|
+
`ticket.gates`. Both send a refusal to the same `fix` and spend the same
|
|
247
|
+
`ticket.maxRefusals` budget.
|
|
208
248
|
|
|
209
249
|
Every child of a Task carries its own ceiling and no other. Every `cmd` names
|
|
210
250
|
its own `timeoutMs`, and none is inherited from a neighbour — nothing else
|
|
@@ -213,7 +253,7 @@ or its sequence's `defaultTimeoutMs`, and a Gate that would end up with neither
|
|
|
213
253
|
is refused when the config loads. Nothing is derived from what another child
|
|
214
254
|
left behind, so what bounds a whole Task is arithmetic the Project can do:
|
|
215
255
|
the builder's `maxAttempts` times its producer's ceiling plus the sum of its Gates'.
|
|
216
|
-
An assembly fix is bounded the same way from `
|
|
256
|
+
An assembly fix is bounded the same way from `ticket.maxAttempts` and `ticket.fix`.
|
|
217
257
|
Root `timeoutMs` bounds what is outside a Task — the manager, the
|
|
218
258
|
isolations. Host has no flag named after a tracker (`--repo` is not a Host
|
|
219
259
|
flag): tracker fields come from that package.
|
|
@@ -242,13 +282,13 @@ re-cloned. `init` then runs `setup` and offers to apply it, so nothing has to be
|
|
|
242
282
|
re-run by hand.
|
|
243
283
|
|
|
244
284
|
A flag is read by the same question that would have asked for it, so
|
|
245
|
-
`--manager-option
|
|
285
|
+
`--manager-option repo=owner/name` lands in the config in the shape a typed answer
|
|
246
286
|
would, and a malformed one is refused before anything is written. The setup plan
|
|
247
287
|
that follows never decides `init`'s exit code: it wrote its files, and
|
|
248
288
|
`mason init && mason setup --apply` must not stop because a token is not
|
|
249
289
|
exported yet.
|
|
250
290
|
|
|
251
|
-
`--manager` turns every question off, which is what a script wants;
|
|
291
|
+
`--manager` (one package for both sides; the config is where they are told apart) turns every question off, which is what a script wants;
|
|
252
292
|
`--interactive` forces them when stdin is a pipe. Overwriting an existing config
|
|
253
293
|
needs `--force`, or a yes to the question. Ctrl-C, Ctrl-D, or a pipe running dry
|
|
254
294
|
stops on the spot with `Cancelled. Nothing written.` and exit 130 — a read after
|
|
@@ -278,12 +318,12 @@ the manager, the ledger root — and closes it with `host-stopped` before the lo
|
|
|
278
318
|
is released. A journal holds every run that ever wrote to that ledger, and
|
|
279
319
|
without these a reader cannot tell one process's film from the next, nor a run
|
|
280
320
|
that ended from one whose process was killed: the missing `host-stopped` is how
|
|
281
|
-
the second is said. Every line about a Task also carries the
|
|
282
|
-
as `key`; a line that names a Task and no
|
|
321
|
+
the second is said. Every line about a Task also carries the Ticket it serves,
|
|
322
|
+
as `key`; a line that names a Task and no Ticket is a line nothing can join.
|
|
283
323
|
|
|
284
324
|
`observability.streams` films what every child says, as it says it: the
|
|
285
|
-
producers
|
|
286
|
-
`<dir>/<
|
|
325
|
+
producers and the Gates. One file per child under
|
|
326
|
+
`<dir>/<ticket>/<task>-attempt-<n>[-gate-<id>]-<stamp>.ndjson`, one JSON object
|
|
287
327
|
per chunk with its own stamp and which stream it came from, filed under the same
|
|
288
328
|
directory name a transcript uses. Each file is named in the journal by a
|
|
289
329
|
`stream-opened` line, so nothing has to rebuild the path. `dir` resolves against
|
|
@@ -300,7 +340,7 @@ killed for writing past its output bound is filmed up to the kill: the bound
|
|
|
300
340
|
protects Host's memory, and that child is the one worth having a film of.
|
|
301
341
|
|
|
302
342
|
A film says what it held as it closes — `stream-closed` with the bytes, the
|
|
303
|
-
chunks and the milliseconds — and a
|
|
343
|
+
chunks and the milliseconds — and a Ticket that reaches `done` or `cancelled`
|
|
304
344
|
has its films removed, which the journal records as `streams-discarded` with the
|
|
305
345
|
count and the size. An escalation keeps everything: that is the outcome where
|
|
306
346
|
somebody has to go and look. Nothing prunes transcripts.
|
|
@@ -313,7 +353,7 @@ poll. A `listen` that did not complete is never held and never hidden.
|
|
|
313
353
|
`watch` and `status` are the operator live view. They open the ledger the same
|
|
314
354
|
way `run` does (`openFilesystemPersist` then `openWorkLedger`) and they do not
|
|
315
355
|
open a manager, Conductor, or Host. `status` prints a snapshot of every known
|
|
316
|
-
|
|
356
|
+
Ticket and exits. `watch` prints that snapshot, then follows new journal lines
|
|
317
357
|
until SIGINT (exit 0). A missing journal is not an error: the snapshot still
|
|
318
358
|
stands. `--json` prints the snapshot as JSON. Ctrl-C on watch leaves the worker
|
|
319
359
|
running. The file can grow without rotation. A followed line that records a
|
|
@@ -327,15 +367,13 @@ are hidden. `--all` keeps them. `--problems` keeps only lines that explain a
|
|
|
327
367
|
stop. `--tail N` keeps the last N of the text film (0 means no limit). `--json`
|
|
328
368
|
prints every kept line, and when `--tail` is also passed and drops lines the
|
|
329
369
|
object names `kept` and `shown`. After the text film it tallies the distinct
|
|
330
|
-
problems
|
|
331
|
-
just before it. A run that then pauses, with no exit code, is tallied as
|
|
332
|
-
`interrupted`, apart from a non-zero exit that left the same detail. When a
|
|
370
|
+
problems, each stop once with how many times it happened. When a
|
|
333
371
|
slot was given `--transcript-dir` it names the newest transcript files with
|
|
334
372
|
the agent exit and duration read from the start of each file. A missing
|
|
335
373
|
journal is not an error. Exit 2 when the config or `--tail` cannot be read.
|
|
336
374
|
|
|
337
|
-
`cancel <key>` abandons one
|
|
338
|
-
team still abandons in the
|
|
375
|
+
`cancel <key>` abandons one Ticket the same way a `cancel` delivery does. The
|
|
376
|
+
team still abandons in the TicketTracker; this is the hatch when the tracker
|
|
339
377
|
cannot say the intention is gone (a manager with no `probe`, or an operator
|
|
340
378
|
who already knows) and the ledger would otherwise freeze the Project. It
|
|
341
379
|
takes the ledger lock — stop `run` first if it holds it. Exit 0 on cancel or
|
|
@@ -343,26 +381,26 @@ already cancelled, 1 when abandon is refused (`done`, point of no return), 2
|
|
|
343
381
|
when the key is missing or the ledger does not know it. The key is the first
|
|
344
382
|
positional: `cancel github:owner/name#19`.
|
|
345
383
|
|
|
346
|
-
`release <key>` drops a held
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
384
|
+
`release <key>` drops a held unit without waiting for the bail clock — the
|
|
385
|
+
hatch after a crash left nobody on the work. A clean stop releases itself. It
|
|
386
|
+
takes the ledger lock — stop `run` first if it holds it. Exit 0 when the unit
|
|
387
|
+
was released or the Ticket was already free, 1 when the Ticket is not
|
|
388
|
+
`running` (the state is named),
|
|
351
389
|
2 when the key is missing or the ledger does not know it. The key is the first
|
|
352
390
|
positional: `release github:owner/name#19`.
|
|
353
391
|
|
|
354
392
|
## 9. Acceptance
|
|
355
393
|
|
|
356
394
|
1. Convertible upsert in an empty Source → WorkLineStable carries the Builder
|
|
357
|
-
marker, Thread `accepted`, `
|
|
395
|
+
marker, Thread `accepted`, `done`, Cursor is that file name.
|
|
358
396
|
2. Unconvertible upsert → Thread `invalid`, no Conductor work, Cursor advanced.
|
|
359
|
-
3. Fail-blocking Gate, then a `
|
|
397
|
+
3. Fail-blocking Gate, then a `resume` Event, then passing Gates → Thread
|
|
360
398
|
contains `escalated` then `resumed` then `done`.
|
|
361
399
|
4. `cancel` while `escalated` → Thread `cancelled`; WorkLineStable seed-only.
|
|
362
400
|
5. Re-running `runOnce` with the saved Cursor does not re-deliver the first Event.
|
|
363
401
|
6. GitHub: convertible issue (mocked API) → WorkLineStable marker, comments
|
|
364
|
-
`accepted`, `
|
|
365
|
-
7. GitHub: fail-blocking then the same issue with the
|
|
402
|
+
`accepted`, `done`.
|
|
403
|
+
7. GitHub: fail-blocking then the same issue with the resume label → `escalated`,
|
|
366
404
|
`resumed`, `done`.
|
|
367
405
|
8. A manager named by path, and one named by package, both load; a module without
|
|
368
406
|
`createManager` is refused by name.
|
|
@@ -378,26 +416,29 @@ positional: `release github:owner/name#19`.
|
|
|
378
416
|
does not appear; `listInFlight()` is the mid-flight subset.
|
|
379
417
|
14. A Transformer `status` line and a `gate-finished` line during `runProject`
|
|
380
418
|
appear in `<ledgerRoot>/events.jsonl`.
|
|
381
|
-
15. `watch` on a ledger with
|
|
382
|
-
including a `submitted`
|
|
419
|
+
15. `watch` on a ledger with Tickets and no journal prints the snapshot,
|
|
420
|
+
including a `submitted` Ticket's reference, and exits 0 on interrupt. It
|
|
383
421
|
does not import `openHost` or a manager package.
|
|
384
|
-
16. Two Features on one Project
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
422
|
+
16. Two Features on one Project: the second does not open while the first is
|
|
423
|
+
open, escalated or submitted. A Feature blocked by another does not open
|
|
424
|
+
until it is `done`. A Feature whose Tickets are not all `task-ready` does
|
|
425
|
+
not open.
|
|
426
|
+
16b. With the e2e check declared: a Feature without an e2e Ticket nor `skip_e2e` does not open and
|
|
427
|
+
is reported `invalid`; with `skip_e2e` its e2e Ticket is cancelled and the e2e Gate is not run,
|
|
428
|
+
the journal and the trace saying so; with an e2e Ticket the line is judged once by the suite,
|
|
429
|
+
red goes to `feature.fix` and green lets the line be offered. A Project without `builder.e2e`
|
|
430
|
+
is unchanged.
|
|
431
|
+
17. After an escalation, a `probe` of `gone` cancels that Ticket (or Feature)
|
|
432
|
+
and the sweep goes on. `unavailable` leaves the
|
|
391
433
|
escalation. A listen that missed the source does not probe. GitHub: a 404
|
|
392
434
|
on `GET /issues/{n}` after a completed listen cancels, even when the
|
|
393
|
-
listing is empty. `cancel <key>` abandons an escalated
|
|
394
|
-
18. A
|
|
435
|
+
listing is empty. `cancel <key>` abandons an escalated Ticket.
|
|
436
|
+
18. A Ticket `submitted`, then the same upsert delivered again, then the
|
|
395
437
|
Authority refuses: Host skips the echo, records no `pending_fingerprint`,
|
|
396
|
-
and the next pass repairs. It does not escalate as
|
|
438
|
+
and the next pass repairs. It does not escalate as an edited intention.
|
|
397
439
|
19. `log` on a journal that recorded `unavailable` with a `detail` prints that
|
|
398
440
|
detail, hides `idle`, and `--problems` drops the phase labels that are not
|
|
399
|
-
themselves the failure. `--json` returns every kept line.
|
|
400
|
-
with no planner exit code is tallied apart from a non-zero exit. It does
|
|
441
|
+
themselves the failure. `--json` returns every kept line. It does
|
|
401
442
|
not import `openHost`.
|
|
402
443
|
|
|
403
444
|
How to install, configure and run: [README.md](./README.md).
|
package/dist/cli.js
CHANGED
|
@@ -1,54 +1,56 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { CLI_NAME } from "@bluewombat/manager-kit";
|
|
3
|
+
import { DEFAULT_CONFIG_FILENAME } from "./config/find-config.js";
|
|
4
4
|
import { DEFAULT_HOME } from "./config/home.js";
|
|
5
|
-
import { parseArgs } from "./config/parse-args.js";
|
|
6
|
-
import { openHost } from "./loop/open-host.js";
|
|
7
5
|
import { runCancel } from "./operator/cancel.js";
|
|
8
6
|
import { runDoctor } from "./operator/doctor.js";
|
|
7
|
+
import { runExplain } from "./operator/explain.js";
|
|
9
8
|
import { runInit } from "./operator/init.js";
|
|
10
9
|
import { runLive } from "./operator/live.js";
|
|
11
10
|
import { runLog } from "./operator/log.js";
|
|
12
11
|
import { isInteractive, terminalAsk } from "./operator/prompt.js";
|
|
13
12
|
import { runRelease } from "./operator/release.js";
|
|
13
|
+
import { runRun } from "./operator/run.js";
|
|
14
14
|
import { runSetup } from "./operator/setup.js";
|
|
15
|
-
const USAGE = `Usage: ${
|
|
15
|
+
const USAGE = `Usage: ${CLI_NAME} <command>
|
|
16
16
|
|
|
17
|
-
run drain the
|
|
17
|
+
run drain the tracker, run Conductor, report
|
|
18
18
|
watch snapshot the ledger and follow the journal
|
|
19
19
|
status snapshot the ledger, then exit
|
|
20
20
|
log replay the journal, including why a phase stopped
|
|
21
|
-
cancel abandon a
|
|
22
|
-
release drop a held
|
|
21
|
+
cancel abandon a Ticket by key (when the tracker cannot say it is gone)
|
|
22
|
+
release drop a held unit without waiting for the bail clock
|
|
23
23
|
init set this directory up — asks, writes, then runs setup
|
|
24
24
|
doctor check the config, the slots, and the manager
|
|
25
|
+
explain say what an agent role starts with: prompt, plugins, skills (read-only)
|
|
25
26
|
setup prepare the tracker (--apply to write; a plan without it)
|
|
26
27
|
|
|
27
|
-
init flags: --manager PKG --manager-option KEY=VALUE --work-line-stable DIR
|
|
28
|
+
init flags: --config FILE --manager PKG --manager-option KEY=VALUE --work-line-stable DIR
|
|
28
29
|
--clone REMOTE [--branch NAME] --force --interactive
|
|
29
30
|
|
|
30
|
-
Shared flags: --config FILE --
|
|
31
|
+
Shared flags: --config FILE --feature-tracker NAME --feature-tracker-option KEY=VALUE
|
|
32
|
+
--ticket-tracker NAME --ticket-tracker-option KEY=VALUE --home DIR
|
|
31
33
|
--work-line-stable DIR --work-line-branch NAME --workspace-root DIR --ledger DIR
|
|
32
34
|
--streams-dir DIR
|
|
33
|
-
--planner -- CMD --planner-timeout-ms N
|
|
34
35
|
--builder -- CMD --builder-timeout-ms N --builder-max-attempts N
|
|
35
36
|
--builder-repair -- CMD --builder-repair-timeout-ms N
|
|
36
37
|
--builder-gate ID -- CMD --builder-gate-timeout-ms N
|
|
37
|
-
--
|
|
38
|
-
--
|
|
39
|
-
--
|
|
38
|
+
--ticket-fix -- CMD --ticket-fix-timeout-ms N --ticket-max-attempts N
|
|
39
|
+
--ticket-validate -- CMD --ticket-validate-timeout-ms N
|
|
40
|
+
--ticket-gate ID -- CMD --ticket-gate-timeout-ms N
|
|
40
41
|
--timeout-ms N --poll-interval-ms N
|
|
41
42
|
|
|
42
43
|
A gate's --*-gate-timeout-ms comes before the --*-gate it bounds.
|
|
43
44
|
|
|
44
|
-
watch / status also take --json (snapshot as JSON).
|
|
45
|
+
watch / status also take --json (snapshot as JSON). explain takes an optional role
|
|
46
|
+
(builder.producer, builder.repair, ticket.fix, ticket.validate, authority.describe) and --json.
|
|
45
47
|
|
|
46
48
|
log also takes --problems, --all, and --json (every kept line).
|
|
47
49
|
--tail N limits the text film (0 = no limit). With --json it names kept and shown when it drops lines.
|
|
48
50
|
|
|
49
|
-
Without --config, the nearest ${
|
|
50
|
-
keeps its own files (default ${DEFAULT_HOME}): the
|
|
51
|
-
the work line.
|
|
51
|
+
Without --config, the nearest ${DEFAULT_CONFIG_FILENAME} is used, and init writes
|
|
52
|
+
that name. --home is where Host keeps its own files (default ${DEFAULT_HOME}): the
|
|
53
|
+
ledger, the workspaces, its copy of the work line.
|
|
52
54
|
|
|
53
55
|
--streams-dir films what every child says, as it says it, one file per child.
|
|
54
56
|
Naming the directory is what turns it on; the config key "observability.streams"
|
|
@@ -67,30 +69,18 @@ function installSignalHandlers(state) {
|
|
|
67
69
|
};
|
|
68
70
|
}
|
|
69
71
|
async function run(argv) {
|
|
70
|
-
const parsed = parseArgs(argv, { cwd: process.cwd() });
|
|
71
|
-
if (!parsed.ok) {
|
|
72
|
-
process.stderr.write(`${parsed.reason}\n`);
|
|
73
|
-
return 2;
|
|
74
|
-
}
|
|
75
72
|
const interruptFlag = { interrupted: false };
|
|
76
|
-
const options = { ...parsed.invocation, interruptFlag };
|
|
77
73
|
const detachSignals = installSignalHandlers(interruptFlag);
|
|
78
|
-
let host;
|
|
79
74
|
try {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
}
|
|
88
|
-
catch (error) {
|
|
89
|
-
process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
|
|
90
|
-
return 2;
|
|
75
|
+
return await runRun({
|
|
76
|
+
cwd: process.cwd(),
|
|
77
|
+
argv,
|
|
78
|
+
write: (text) => process.stdout.write(text),
|
|
79
|
+
writeError: (text) => process.stderr.write(text),
|
|
80
|
+
interruptFlag,
|
|
81
|
+
});
|
|
91
82
|
}
|
|
92
83
|
finally {
|
|
93
|
-
await host?.close();
|
|
94
84
|
detachSignals();
|
|
95
85
|
}
|
|
96
86
|
}
|
|
@@ -170,6 +160,14 @@ async function main(argv) {
|
|
|
170
160
|
write: (line) => process.stdout.write(line),
|
|
171
161
|
});
|
|
172
162
|
}
|
|
163
|
+
if (command === "explain") {
|
|
164
|
+
return await runExplain({
|
|
165
|
+
cwd: process.cwd(),
|
|
166
|
+
argv: rest,
|
|
167
|
+
env: process.env,
|
|
168
|
+
write: (text) => process.stdout.write(text),
|
|
169
|
+
});
|
|
170
|
+
}
|
|
173
171
|
if (command === "cancel") {
|
|
174
172
|
const interruptFlag = { interrupted: false };
|
|
175
173
|
const detachSignals = installSignalHandlers(interruptFlag);
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|