@allocator-one/harness-cli 1.13.0 → 1.14.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 +197 -19
- package/dist/{chunk-XFMECLOU.js → chunk-F2YVTB2A.js} +683 -77
- package/dist/cli.js +81 -127
- package/dist/{server-CYBKYG5E.js → server-75QJASTY.js} +130 -7
- package/package.json +2 -1
- package/spec/openapi.json +3924 -11
package/README.md
CHANGED
|
@@ -58,20 +58,47 @@ numbering, `ALL-` numbers up to the import ceiling came from Linear, and
|
|
|
58
58
|
## Daily workflow
|
|
59
59
|
|
|
60
60
|
```sh
|
|
61
|
-
harness ready --claim
|
|
61
|
+
harness ready --claim # claim the team's next ready, unassigned issue
|
|
62
62
|
harness show CLI-12 # read it, including attached screenshots
|
|
63
63
|
# … do the work …
|
|
64
64
|
harness close CLI-12 --reason "Implemented in 1a2b3c4"
|
|
65
65
|
```
|
|
66
66
|
|
|
67
67
|
**Queue.** `harness ready` lists open, unblocked issues, highest priority
|
|
68
|
-
first. Blocked issues, `hold`-labeled issues, and parents with
|
|
69
|
-
are
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
`--team`.
|
|
68
|
+
first. Blocked issues, `hold`-labeled issues, and parents with sub-issues
|
|
69
|
+
that are not completed are excluded. Only a completed blocker resolves: a
|
|
70
|
+
cancelled or archived one still blocks until it is completed or the
|
|
71
|
+
dependency is removed or re-pointed. An issue that is waiting on a wait
|
|
72
|
+
condition (see [Plans](#plans)) is not ready either. `harness blocked` lists
|
|
73
|
+
issues that are waiting on a blocker.
|
|
74
|
+
Both commands take `--team`. `ready` marks agent steps, the plan steps
|
|
75
|
+
Operator runs, with `[agent]` before the title and a legend under the table,
|
|
76
|
+
and `--json` gives every issue an `agent_step` flag. Only the plan driver
|
|
77
|
+
claims an agent step. The issue payload carries no executor, so the CLI
|
|
78
|
+
goes by the team: agent steps are filed in the organization's Operator team
|
|
79
|
+
(named Operator, keyed `OPERATOR`, or `OPERATOR2` and so on). That is a
|
|
80
|
+
heuristic. A step handed back to a person keeps its team and stays marked,
|
|
81
|
+
and the claim itself is the authority.
|
|
82
|
+
|
|
83
|
+
**Claim the next issue.** `harness ready --claim` is a single request: the
|
|
84
|
+
server picks the team's most important ready issue that has no assignee
|
|
85
|
+
(urgent, high, medium, low, then none; oldest first, then by id), assigns
|
|
86
|
+
you, and moves it to the team's first started state, all in one transaction.
|
|
87
|
+
Concurrent callers get different issues, and the CLI does no paging, sorting,
|
|
88
|
+
or retrying of its own.
|
|
89
|
+
|
|
90
|
+
- It needs a team: `--team`, then `HARNESS_TEAM`, then the repo config. With
|
|
91
|
+
none of them it is a usage error, and the claim is never sent.
|
|
92
|
+
- `--all`, `--limit`, and `--page` are refused with `--claim`, because the
|
|
93
|
+
server already ranks the whole ready set.
|
|
94
|
+
- An empty queue is a normal outcome: it prints "Nothing to claim: team CLI
|
|
95
|
+
has no unassigned ready issues." (`null` with `--json`) and exits `0`.
|
|
96
|
+
- A rate limit, server error, or unreadable response exits `1`, and an
|
|
97
|
+
unreachable API exits `3`. None of these is reported as an empty queue.
|
|
98
|
+
The CLI never retries the claim. When an unreadable response or a lost
|
|
99
|
+
connection leaves it unknown whether the claim landed, the error says to
|
|
100
|
+
check `harness list --team <key> --assignee me --status in_progress`
|
|
101
|
+
before claiming again.
|
|
75
102
|
|
|
76
103
|
**Read.** `harness show <id>` prints the fields, relations, children, and
|
|
77
104
|
comments. It also downloads the images attached to the issue's description,
|
|
@@ -79,7 +106,13 @@ design, acceptance criteria, notes, and comments (up to 20, cached locally)
|
|
|
79
106
|
and prints their paths. Screenshots are often the reproduction, so read
|
|
80
107
|
them. `--no-images` skips the downloads. If a download fails, a stderr
|
|
81
108
|
notice says so and the command still succeeds. `harness comments <id>`
|
|
82
|
-
prints the full, untruncated comment thread with comment ids.
|
|
109
|
+
prints the full, untruncated comment thread with comment ids. The
|
|
110
|
+
`Blocked:` line names a cancelled or archived blocker as such
|
|
111
|
+
(`yes, by CLI-3 (cancelled), CLI-4 (archived), CLI-5`). When the issue has
|
|
112
|
+
wait conditions, `Waiting:` says how many still hold it, and a
|
|
113
|
+
`Wait conditions:` section lists each one (`[ ] gate "Finance sign-off" · <id>`,
|
|
114
|
+
`[x] not before … (satisfied …)`, `system event`) with the id
|
|
115
|
+
`harness gate satisfy` takes.
|
|
83
116
|
`harness activity <id>` prints the issue's activity timeline: comments,
|
|
84
117
|
creation, and state and assignee changes. It shows the newest 20 entries
|
|
85
118
|
(`--limit` accepts 1–100), and `--all` reads further back.
|
|
@@ -110,8 +143,13 @@ harness create --title "Fix login redirect" --type bug --priority high \
|
|
|
110
143
|
**Update.** `harness update <id>` with:
|
|
111
144
|
|
|
112
145
|
- `--claim`: atomic. It assigns you and moves the issue to the team's first
|
|
113
|
-
started state. A conflict
|
|
114
|
-
|
|
146
|
+
started state. A conflict (exit `1`, HTTP 409) names its reason: someone
|
|
147
|
+
else holds the issue, or it is not claimable yet. Two reasons come with a
|
|
148
|
+
next step: `agent_step` (Operator runs it; to do it yourself, set its
|
|
149
|
+
executor to `none` with `harness plan edit <plan-id>` and release the plan
|
|
150
|
+
again) and `waiting_on_condition` (`harness show` lists what it waits on;
|
|
151
|
+
tick a gate with `harness gate satisfy`). It cannot be combined with
|
|
152
|
+
`--assignee`.
|
|
115
153
|
- `--state <name-or-type>`: moves the issue to the workflow state whose name
|
|
116
154
|
or type matches.
|
|
117
155
|
- `--title`, `--description`, `--design`, `--acceptance`, `--priority`,
|
|
@@ -136,7 +174,13 @@ duplicate-of form records a duplicate relation and cannot be combined with
|
|
|
136
174
|
`--cancel`. `--reason` records why the issue is done. The output lists the
|
|
137
175
|
issues each closure unblocked
|
|
138
176
|
(`Closed CLI-12 — unblocked: CLI-13, CLI-14`); act on them instead of
|
|
139
|
-
leaving them in the queue.
|
|
177
|
+
leaving them in the queue. Only completing releases dependents: a canceled
|
|
178
|
+
issue still blocks them. A duplicate close moves its blocking edges to the
|
|
179
|
+
canonical issue, and any edge that cannot move stays on the duplicate. When
|
|
180
|
+
the closed issue still blocks anything, an indented line names those
|
|
181
|
+
dependents (`Still blocking: CLI-13 (a cancelled issue still blocks its
|
|
182
|
+
dependents)`) so you can remove or re-point those dependencies. With
|
|
183
|
+
several ids, each one is closed on its own.
|
|
140
184
|
A failure prints `FAILED <id>: …`, and the command exits `1` after trying
|
|
141
185
|
the rest. `harness archive <id>…` archives issues, `--restore` brings them
|
|
142
186
|
back, and `harness list --scope archived` lists them.
|
|
@@ -167,8 +211,12 @@ comments. Comment ids are UUIDs from `harness comments`.
|
|
|
167
211
|
`--parent <id>` (children of an epic), and `--scope all|archived`.
|
|
168
212
|
|
|
169
213
|
**Overview.** `harness stats` prints per-team and total counts.
|
|
170
|
-
`harness prime` prints those counts, the
|
|
171
|
-
|
|
214
|
+
`harness prime` prints those counts, the organization's ten most important
|
|
215
|
+
ready issues across every team (urgent first and priority none last, ranked
|
|
216
|
+
the way `harness ready --claim` ranks, though that claims only unassigned
|
|
217
|
+
issues on one team), and a short workflow reminder. It is meant for the
|
|
218
|
+
start of an agent session. Against a server older than this read it shows
|
|
219
|
+
the ten newest ready issues instead.
|
|
172
220
|
|
|
173
221
|
### Text from a file
|
|
174
222
|
|
|
@@ -193,7 +241,9 @@ git log -1 --format=%B | harness close CLI-12 --reason-file -
|
|
|
193
241
|
| `comment`, `comment edit` | `--body-file` |
|
|
194
242
|
|
|
195
243
|
Other commands (`project`, `milestone`, `doc`, `link`, and so on) take inline
|
|
196
|
-
values only.
|
|
244
|
+
values only. `plan create` and `plan edit` read a whole JSON or YAML
|
|
245
|
+
document with `--file` (see [Plans](#plans)), under the same stdin and
|
|
246
|
+
UTF-8 rules, up to 8 MB (the API's request limit). `-` reads from stdin, and only one option per invocation can do
|
|
197
247
|
that. stdin must not be a terminal. Passing both the inline and the file form
|
|
198
248
|
of a field is a usage error, and so is a file that produces an empty title,
|
|
199
249
|
reason, or comment. Conflicting options are caught before anything is read,
|
|
@@ -201,6 +251,119 @@ so a rejected command never consumes your pipe. A file must be valid UTF-8
|
|
|
201
251
|
and at most 1 MB, and one trailing newline is dropped, as with
|
|
202
252
|
`$(cat file)`.
|
|
203
253
|
|
|
254
|
+
## Plans
|
|
255
|
+
|
|
256
|
+
A plan is a root issue and its steps, created in one request: their
|
|
257
|
+
parents, `blocked_by` dependencies, executors, teams and wait conditions.
|
|
258
|
+
Either the whole plan is created or nothing is. Plans start held, so
|
|
259
|
+
nothing runs until a person releases one.
|
|
260
|
+
|
|
261
|
+
```sh
|
|
262
|
+
harness plan create --file plan.yaml --team IO --idempotency-key q3-report
|
|
263
|
+
harness plan show <plan-id>
|
|
264
|
+
harness plan release <plan-id> --collaborator grace@example.com
|
|
265
|
+
harness gate satisfy IO-121 "Finance sign-off"
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
**The plan file** is the API's request body, as JSON (`.json`) or YAML
|
|
269
|
+
(anything else, and stdin with `--file -`). YAML is read as YAML 1.2 and
|
|
270
|
+
held to what JSON can carry: dates stay strings, and a duplicate key, an
|
|
271
|
+
explicit tag such as `!!timestamp`, or `.inf`/`.nan` is refused. The
|
|
272
|
+
root's fields sit at the top level, and each step has a `key` that other
|
|
273
|
+
steps refer to:
|
|
274
|
+
|
|
275
|
+
```yaml
|
|
276
|
+
title: Ship the Q3 LP report
|
|
277
|
+
spend_budget_cents: 5000 # needed to release Operator steps
|
|
278
|
+
steps:
|
|
279
|
+
- key: gather
|
|
280
|
+
title: Gather the fund data
|
|
281
|
+
executor: operator # Operator runs it; the description is its instruction
|
|
282
|
+
description: Pull the Q3 NAVs for every fund in the portfolio
|
|
283
|
+
- key: review
|
|
284
|
+
title: Review the numbers
|
|
285
|
+
team: IO # a person's step; defaults to --team
|
|
286
|
+
blocked_by: [gather]
|
|
287
|
+
conditions:
|
|
288
|
+
- kind: gate
|
|
289
|
+
label: Finance sign-off
|
|
290
|
+
- key: send
|
|
291
|
+
title: Send the report
|
|
292
|
+
blocked_by: [review]
|
|
293
|
+
conditions:
|
|
294
|
+
- kind: not_before
|
|
295
|
+
not_before: "2026-10-15T09:00:00Z"
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
- A step takes the issue fields (`title`, `description`, `priority` as a
|
|
299
|
+
number from 0 for none to 4 for low, `assignee`, `label_ids`, …) plus
|
|
300
|
+
`key`, `parent` (the key of the step that contains it), `blocked_by`
|
|
301
|
+
(keys), `executor` (`none`, the default, or `operator`), `team`, and
|
|
302
|
+
`conditions`. Operator steps are filed in the Operator team. Only steps
|
|
303
|
+
without sub-steps carry an executor, edges, or conditions.
|
|
304
|
+
- Wait conditions: `not_before` (a UTC instant), `gate` (a `label` a person
|
|
305
|
+
ticks), and `event` (`event`, `subject_id`, and for a stage change
|
|
306
|
+
`target_id`). The allowed events are `deal_stage_changed`,
|
|
307
|
+
`opportunity_stage_changed`, `form_submitted`, and `investment_executed`.
|
|
308
|
+
Every condition must hold before the step is ready.
|
|
309
|
+
- A plan has at most 100 steps, its root included.
|
|
310
|
+
- `--team` (or `HARNESS_TEAM` or the repo config) is the root's team and the
|
|
311
|
+
default team for people's steps. `--idempotency-key` works as it does for
|
|
312
|
+
`create`: if a create times out, run it again with the same key to get
|
|
313
|
+
the same plan back.
|
|
314
|
+
|
|
315
|
+
**Validation.** The server checks the whole graph and an invalid plan
|
|
316
|
+
creates nothing. The command exits `1`, and stderr lists every violation by
|
|
317
|
+
the step key it is about:
|
|
318
|
+
|
|
319
|
+
```text
|
|
320
|
+
harness: The plan is not valid; nothing was changed (HTTP 422)
|
|
321
|
+
step "review" (steps[1]): parent names no step of this plan, or no issue in this organization (parent: nope) [unknown_parent]
|
|
322
|
+
plan: A plan with Operator steps needs a positive spend budget [spend_budget_required]
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
**Show.** `harness plan show <plan-id>` prints the plan's status, budgets,
|
|
326
|
+
revision, and spend estimate, then every step in tree order (indented by
|
|
327
|
+
depth) with its key, executor, state, and status. The status is `ready`,
|
|
328
|
+
`held` (edited since the release), `not in revision` (added after it),
|
|
329
|
+
`waiting` (on a wait condition), `container`, `done`, `cancelled`,
|
|
330
|
+
`archived`, or `-`. The edges and each step's wait conditions come after
|
|
331
|
+
the steps.
|
|
332
|
+
|
|
333
|
+
**Edit.** `harness plan edit <plan-id> --file edits.yaml` changes step
|
|
334
|
+
executors and keys, naming each step by its `step` key or `issue`
|
|
335
|
+
identifier, and the budgets (`retry_budget`, `spend_budget_cents`):
|
|
336
|
+
|
|
337
|
+
```yaml
|
|
338
|
+
steps:
|
|
339
|
+
- step: gather
|
|
340
|
+
executor: none # hand the step to a person
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
Editing a released step holds it until the plan is released again. A
|
|
344
|
+
budget change needs the plan held first. Descriptions, parents, and edges
|
|
345
|
+
are edited with the issue commands (`update`, `dep`). Conditions are set
|
|
346
|
+
when the plan is created. Editing them later goes through the API's issue
|
|
347
|
+
condition endpoints, which have no command yet; `gate satisfy` ticks a
|
|
348
|
+
gate.
|
|
349
|
+
|
|
350
|
+
**Release and hold.** `harness plan release <plan-id>` releases the plan as
|
|
351
|
+
you: it freezes the next revision and lets ready steps run.
|
|
352
|
+
`--collaborator <id-or-email>` (repeatable) adds people to the plan room
|
|
353
|
+
where its Operator steps run, and `--retry-budget` and
|
|
354
|
+
`--spend-budget-cents` set the budgets. `harness plan hold <plan-id>`
|
|
355
|
+
pauses every step until the plan is released again.
|
|
356
|
+
|
|
357
|
+
**Gates.** `harness gate satisfy <issue> <gate>` ticks a gate and
|
|
358
|
+
`harness gate unsatisfy <issue> <gate>` unticks it. `<gate>` is the gate's
|
|
359
|
+
label or its condition id from `harness show`. A label matches exactly
|
|
360
|
+
first, then ignoring case, and a label that more than one gate carries is
|
|
361
|
+
refused with their ids. Ticking a gate requires staff standing in the
|
|
362
|
+
organization.
|
|
363
|
+
|
|
364
|
+
A server without the plan API answers the plan commands with a 404, and the
|
|
365
|
+
error says that the server may predate plans.
|
|
366
|
+
|
|
204
367
|
## Uploads
|
|
205
368
|
|
|
206
369
|
`harness upload <path>` uploads a file and prints a markdown reference to
|
|
@@ -290,7 +453,7 @@ can read.
|
|
|
290
453
|
- The `activity`, `search`, and `show` notices described above.
|
|
291
454
|
- The update notice (see [Staying current](#staying-current)).
|
|
292
455
|
- **Pagination.** `ready`, `blocked`, `list`, `project list`, and `doc list`
|
|
293
|
-
return 50 records per page by default. `--limit` changes the page size,
|
|
456
|
+
return 50 records per page by default (`ready --claim` has no pages). `--limit` changes the page size,
|
|
294
457
|
`--page` selects a page, and `--all` follows every page (pass `--all` or
|
|
295
458
|
`--page`, not both). The truncation notice goes to stderr only, so a
|
|
296
459
|
script that reads just the `--json` output cannot tell a full page from a
|
|
@@ -299,8 +462,8 @@ can read.
|
|
|
299
462
|
|
|
300
463
|
| Code | Meaning |
|
|
301
464
|
| --- | --- |
|
|
302
|
-
| `0` | Success. |
|
|
303
|
-
| `1` | The command failed. Causes include an API error (the message gives the HTTP status), a
|
|
465
|
+
| `0` | Success, including `ready --claim` finding nothing to claim. |
|
|
466
|
+
| `1` | The command failed. Causes include an API error (the message gives the HTTP status, followed by any per-field errors or plan violations, one per line), a response the CLI cannot interpret, a partial failure across several ids, or a local refusal such as an unreadable or oversized upload. |
|
|
304
467
|
| `2` | Usage or configuration error, including "not signed in" outside a terminal. Nothing was sent. |
|
|
305
468
|
| `3` | The API was unreachable (DNS, TLS, connection refused, or timeout). Retry with backoff, and if the API stays down, say so instead of dropping tracked work. |
|
|
306
469
|
|
|
@@ -319,7 +482,7 @@ With a global install, `harness mcp` works as the command instead of the
|
|
|
319
482
|
{ "mcpServers": { "harness": { "command": "npx", "args": ["-y", "@allocator-one/harness-cli", "mcp"] } } }
|
|
320
483
|
```
|
|
321
484
|
|
|
322
|
-
The server exposes
|
|
485
|
+
The server exposes 58 tools:
|
|
323
486
|
|
|
324
487
|
| Area | Tools |
|
|
325
488
|
| --- | --- |
|
|
@@ -331,6 +494,7 @@ The server exposes 52 tools:
|
|
|
331
494
|
| Labels | `label_list`, `label_create`, `label_update`, `label_delete` |
|
|
332
495
|
| Teams and states | `team_list`, `team_create`, `team_rename`, `team_set_default`, `workflow_states`, `state_add`, `state_update`, `state_order`, `state_delete` |
|
|
333
496
|
| People | `member_list`, `member_add`, `member_set_role`, `user_list` |
|
|
497
|
+
| Plans and gates | `plan_create`, `plan_show`, `plan_edit`, `plan_release`, `plan_hold`, `gate_set` |
|
|
334
498
|
| Other | `stats`, `upload` |
|
|
335
499
|
|
|
336
500
|
The tools cover the issue workflow and the admin surface. Some commands are
|
|
@@ -343,8 +507,22 @@ Some tools behave differently from their commands:
|
|
|
343
507
|
|
|
344
508
|
- `issue_list` with `ready: true` or `blocked: true` accepts every list
|
|
345
509
|
filter. The CLI's `ready` and `blocked` take only `--team`.
|
|
510
|
+
- `issue_list` only lists. Claiming the team's next issue (`ready --claim`)
|
|
511
|
+
is CLI-only; over MCP, claim a specific issue with `issue_claim`.
|
|
346
512
|
- `issue_show` downloads images only when you pass `images: true`.
|
|
347
513
|
- `state_delete` and `label_delete` don't need the CLI's `--yes`.
|
|
514
|
+
- `plan_create` takes the plan as an object (`plan`), with `team` and
|
|
515
|
+
`idempotency_key` beside it, instead of a file. Its schema describes the
|
|
516
|
+
steps and conditions, and keys inside `plan` that the schema does not
|
|
517
|
+
know are still sent, so the server reports them. `plan_edit` takes
|
|
518
|
+
`steps`, `retry_budget`, and `spend_budget_cents` directly. As with every
|
|
519
|
+
tool, a top-level argument the tool does not declare is dropped.
|
|
520
|
+
`gate_set` takes `issue`, `gate`, and `satisfied`.
|
|
521
|
+
- An API error's details come back in the tool error text: a validation
|
|
522
|
+
error's fields, and an invalid plan's violations, one per line by step
|
|
523
|
+
key.
|
|
524
|
+
- `issue_list` with `ready: true` gives every issue an `agent_step` flag,
|
|
525
|
+
read from its team as `ready` does.
|
|
348
526
|
|
|
349
527
|
For example, `issue_list` with `{"ready": true, "team": "CLI"}` returns the
|
|
350
528
|
ready queue, and `issue_claim` with `{"id": "CLI-12"}` claims an issue
|