@detergent-software/conductor 1.0.0-dev.30 → 1.0.0-dev.32
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/CHANGELOG.md +20 -0
- package/README.md +31 -3
- package/build/brief-cli.js +68 -0
- package/build/brief-cli.js.map +1 -0
- package/build/brief.js +211 -0
- package/build/brief.js.map +1 -0
- package/build/cli.js +9 -0
- package/build/cli.js.map +1 -1
- package/build/config.js +6 -2
- package/build/config.js.map +1 -1
- package/build/daemon.js +4 -1
- package/build/daemon.js.map +1 -1
- package/build/help.js +11 -0
- package/build/help.js.map +1 -1
- package/build/history.js +3 -0
- package/build/history.js.map +1 -1
- package/build/inbox.js +44 -3
- package/build/inbox.js.map +1 -1
- package/build/notes.js +2 -2
- package/build/notes.js.map +1 -1
- package/build/server.js +26 -7
- package/build/server.js.map +1 -1
- package/build/store.js +3 -1
- package/build/store.js.map +1 -1
- package/build/trackers.js +3 -0
- package/build/trackers.js.map +1 -1
- package/build/watchers/ado.js +24 -4
- package/build/watchers/ado.js.map +1 -1
- package/build/watchers/boards-brief.js +63 -0
- package/build/watchers/boards-brief.js.map +1 -0
- package/build/watchers/boards.js +20 -16
- package/build/watchers/boards.js.map +1 -1
- package/build/watchers/conflicts.js +132 -0
- package/build/watchers/conflicts.js.map +1 -0
- package/build/watchers/index.js +20 -7
- package/build/watchers/index.js.map +1 -1
- package/build/watchers/source.js +3 -3
- package/build/watchers/source.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,26 @@
|
|
|
2
2
|
|
|
3
3
|
Releases are tagged `conductor-v<version>` and staged on npm by `atk-conductor-release` (`pipelines/release-conductor.yml`), which writes each section below. `scripts/check-changelog.mjs` fails when a tag has no section here.
|
|
4
4
|
|
|
5
|
+
## [1.0.0-dev.32](https://emergentcode.visualstudio.com/Emergent%20Software/_git/Emergent.AgenticToolkit/branchCompare?baseVersion=GTconductor-v1.0.0-dev.31&targetVersion=GTconductor-v1.0.0-dev.32) (2026-10-12)
|
|
6
|
+
|
|
7
|
+
### Features
|
|
8
|
+
|
|
9
|
+
* **conductor:** wake a parked worker when its PR conflicts (ATK-383) ([1c6c4cb](https://emergentcode.visualstudio.com/Emergent%20Software/_git/Emergent.AgenticToolkit/commit/1c6c4cb0e639403a70847f1c5b516b05488307c9))
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* **conductor:** keep conflict spells true to the PR (ATK-383) ([fbe0dc7](https://emergentcode.visualstudio.com/Emergent%20Software/_git/Emergent.AgenticToolkit/commit/fbe0dc717a05dfc7f61b81084755ba1017d1c84d))
|
|
14
|
+
|
|
15
|
+
## [1.0.0-dev.31](https://emergentcode.visualstudio.com/Emergent%20Software/_git/Emergent.AgenticToolkit/branchCompare?baseVersion=GTconductor-v1.0.0-dev.30&targetVersion=GTconductor-v1.0.0-dev.31) (2026-10-12)
|
|
16
|
+
|
|
17
|
+
### Features
|
|
18
|
+
|
|
19
|
+
* **conductor:** conduct brief, an item's context for orient (ATK-371) ([441d47f](https://emergentcode.visualstudio.com/Emergent%20Software/_git/Emergent.AgenticToolkit/commit/441d47fd735eb927690e22d5b30ab130fafd7d16))
|
|
20
|
+
|
|
21
|
+
### Bug Fixes
|
|
22
|
+
|
|
23
|
+
* **conductor:** brief cache drops on any item event (ATK-371) ([59b9775](https://emergentcode.visualstudio.com/Emergent%20Software/_git/Emergent.AgenticToolkit/commit/59b9775703f2296cdd44e8abc5bec2c9b5d9c71b))
|
|
24
|
+
|
|
5
25
|
## [1.0.0-dev.30](https://emergentcode.visualstudio.com/Emergent%20Software/_git/Emergent.AgenticToolkit/branchCompare?baseVersion=GTconductor-v1.0.0-dev.29&targetVersion=GTconductor-v1.0.0-dev.30) (2026-10-12)
|
|
6
26
|
|
|
7
27
|
### Features
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Conductor
|
|
2
2
|
|
|
3
|
-
`@detergent-software/conductor`: the local daemon that runs the work loop for every conducted project on this machine, and its `conduct` CLI. The design, decisions and build order are in the Linear document *Conductor: design note* (project *Conductor daemon*). This package has build step 1, the skeleton (ATK-308), step 2, the session manager (ATK-309), step 3, the watchers and `conduct wait` (ATK-310), the daemon's side of step 4, worker protocol v1's `conduct note` (ATK-311), step 5, the inbox with `conduct approve` / `revise` (ATK-312), step 6, the notifier (ATK-313), step 9, the conductor mod for Claude Code in `mod/` (ATK-265), step 8, the scheduler, settings and rules (ATK-315), the daemon's side of step 7, the console (ATK-314), step 12, the port broker (ATK-318),
|
|
3
|
+
`@detergent-software/conductor`: the local daemon that runs the work loop for every conducted project on this machine, and its `conduct` CLI. The design, decisions and build order are in the Linear document *Conductor: design note* (project *Conductor daemon*). This package has build step 1, the skeleton (ATK-308), step 2, the session manager (ATK-309), step 3, the watchers and `conduct wait` (ATK-310), the daemon's side of step 4, worker protocol v1's `conduct note` (ATK-311), step 5, the inbox with `conduct approve` / `revise` (ATK-312), step 6, the notifier (ATK-313), step 9, the conductor mod for Claude Code in `mod/` (ATK-265), step 8, the scheduler, settings and rules (ATK-315), the daemon's side of step 7, the console (ATK-314), step 12, the port broker (ATK-318), step 13, the ADO Boards tracker (ATK-319), and `conduct brief` for a worker's orient step (ATK-371).
|
|
4
4
|
|
|
5
5
|
## Commands
|
|
6
6
|
|
|
@@ -47,6 +47,8 @@ conduct rules test <file> [--json]
|
|
|
47
47
|
dry-run the rules on a sample event; acts on nothing
|
|
48
48
|
conduct note <item> <file> post a phase note on the item and record its phase (see Notes)
|
|
49
49
|
[--worker <worker>]
|
|
50
|
+
conduct brief <item> [--json] [--fresh]
|
|
51
|
+
the item's status, links, phase notes and approval, from the tracker (see Briefs)
|
|
50
52
|
conduct wait <condition> wait for an outside event (see Waits)
|
|
51
53
|
conduct ports [<path>] [--prefer <slot>] [--json]
|
|
52
54
|
a checkout's dev ports from the port broker, or every worktree's (see Broker)
|
|
@@ -96,6 +98,28 @@ The work skill is the profile's `skills.work`. A note headed with one of `skills
|
|
|
96
98
|
|
|
97
99
|
On Linear the daemon uses the key the watchers read (below), so that key needs **Create comments** as well as Read. Comments it writes carry the key owner's name, as the Linear MCP's do. On ADO Boards it posts a markdown discussion comment as the `az login` identity.
|
|
98
100
|
|
|
101
|
+
## Briefs
|
|
102
|
+
|
|
103
|
+
`conduct brief <item>` gives a worker the item's context for its orient step, read by the daemon from the tracker, so the worker needs no MCP call. It gives:
|
|
104
|
+
- the title, URL, status (name and type), the tracker's project, Area and labels;
|
|
105
|
+
- the blockers, the items it blocks and the related items, each with its status and title;
|
|
106
|
+
- its phase notes (time, phase, kind and line), the newest Plan, and the `approve` / `revise:` after it with its words;
|
|
107
|
+
- the description.
|
|
108
|
+
|
|
109
|
+
`--json` prints it as one object.
|
|
110
|
+
|
|
111
|
+
The queue's snapshot has no descriptions, relations or comments, so the daemon reads the item itself:
|
|
112
|
+
- **Linear:** one GraphQL request with the watchers' key, and more only for comments past the first 100.
|
|
113
|
+
- **ADO Boards:** the work item with its links, its linked items' titles and states, its discussion comments and the `az login` identity. Predecessor is a blocker, Successor an item it blocks.
|
|
114
|
+
|
|
115
|
+
A brief is kept for 30 seconds. Anything the daemon sees happen to the item drops it: a note it posted, an `approve` or `revise` it posted, a wait resolved. `--fresh` reads the tracker again, as a worker checking for an approval after a wake should.
|
|
116
|
+
|
|
117
|
+
| Exit | Means | The worker then |
|
|
118
|
+
|---|---|---|
|
|
119
|
+
| 0 | the brief | uses it |
|
|
120
|
+
| 3 | no daemon, one without the brief API, or one that couldn't read the tracker (no key, the tracker down) | reads the item from the tracker itself (the Linear MCP, or the work skill's helper) |
|
|
121
|
+
| 1 | refused: no project tracks the item, or the tracker has no such item | reads the message |
|
|
122
|
+
|
|
99
123
|
## Inbox
|
|
100
124
|
|
|
101
125
|
The `inbox` table holds everything that waits on Jason, across projects. Each item records:
|
|
@@ -117,6 +141,7 @@ An item resolves itself when its condition is seen, and records what resolved it
|
|
|
117
141
|
| `permission`, `stall` | `worker.stalled` | `worker.stall-cleared`, a park or resume, a new wait (stall only), or a daemon restart (it is raised again if it persists) |
|
|
118
142
|
| `stall` (park failing) | `worker.park-failed`, with `conduct attach` and `conduct retire` | a park, the session stopping unexpectedly (which raises `failed`), its retirement, or a daemon restart (the park is tried again, and fails again if it still does). A new wait doesn't resolve it. A retire stops the session the same way, so when the pid outlives `claude stop`, end that process: the next sweep finds the session gone |
|
|
119
143
|
| `failed` | a failed launch, or a session that stopped unexpectedly | a new launch, the worker running again, or its retirement |
|
|
144
|
+
| `conflict` | `pr.conflict-stuck`: a watched PR has conflicted with its base for `watchers.conflictMinutes` (30) since its worker was woken for it, and the wake never reached the worker or a pass still sees the conflict; with `conduct attach` and the PR link | the PR merging cleanly again, merged or abandoned (`pr.conflict-cleared`), its retirement, or a daemon restart (the spell starts over) |
|
|
120
145
|
| `runaway` | a worker passing `inbox.runawayTokens` (2M) input, output and cache-write tokens in all, once per worker | `conduct done`, or its retirement |
|
|
121
146
|
| `ready-to-release`, `queue-drained` | the scheduler's default rules (see Scheduler) | `conduct done` |
|
|
122
147
|
| `console` | the console's finding on an escalation, with `conduct escalations done <id> --ask` (see Console) | `conduct done` |
|
|
@@ -153,7 +178,7 @@ The notifier routes each new inbox item to the phone, on two channels:
|
|
|
153
178
|
"profiles": {
|
|
154
179
|
"default": [{ "to": ["remote-control", "pushover"] }], // built in
|
|
155
180
|
"away": [{ "to": ["pushover"] }], // built in
|
|
156
|
-
"focus": [{ "kinds": ["npm-otp", "permission", "failed", "jason"], "to": ["remote-control", "pushover"] }], // built in
|
|
181
|
+
"focus": [{ "kinds": ["npm-otp", "permission", "failed", "conflict", "jason"], "to": ["remote-control", "pushover"] }], // built in
|
|
157
182
|
"workday": [
|
|
158
183
|
{ "projects": ["cadence"], "days": ["sat", "sun"], "to": [] }, // keep these off every channel
|
|
159
184
|
{ "kinds": ["npm-otp"], "to": ["pushover", "remote-control"], "remind": { "afterMinutes": 10, "times": 5 } },
|
|
@@ -262,6 +287,8 @@ A worker waits by posting its note, running `conduct wait …` and ending the tu
|
|
|
262
287
|
|
|
263
288
|
**Watchers.** One per API: Linear (GraphQL with `LINEAR_API_KEY` or the `atk-conductor-linear` credential, ported from conduct-atk), Azure DevOps (REST with the `az login` token), GitHub (`gh api`), npm (the registry's dist-tags, no cache) and `/health`. Time waits are the session manager's sweep. An API is asked nothing while no wait needs it. Otherwise it's asked once per `watchers.<api>.intervalSeconds`, within `perMinute` requests in any rolling minute shared by every project. Each pass covers all of that API's waits in as few requests as it can; Linear's is one request, filtered on `updatedAt` (with a 2-minute overlap) after the first. A pass that runs out of budget stops, and the next one starts a wait further on. A failing API waits twice as long each time (up to 10 minutes) and logs `watcher.failed` once, then `watcher.recovered`. A wait that can't be checked logs `wait.check-failed` once and stays open. Every `watchers.statsMinutes` (10) in which anything waited, a `watcher.stats` event records each API's passes, requests, budget skips, failures and waits.
|
|
264
289
|
|
|
290
|
+
**PR conflicts.** Azure DevOps runs no build on a PR that conflicts with its base branch, so its `checks` never settle and it can't merge. The ADO watcher reads the PR's `mergeStatus` and target branch with the PR itself, at no extra request, and doesn't ask a conflicted PR's build evaluations, which can only be stale. The first pass that sees `conflicts` starts a spell for each worker waiting on the PR: it logs `pr.conflicted` and resolves the worker's waits on the PR with `pr <n> conflicts with <base>: merge origin/<base> into the branch (no rebase), resolve, rerun the checks, push and wait on the PR again` (after a wait's own line when it resolved on its own, such as a comment), which wakes the worker. Later passes in the spell wake nobody, unless the PR conflicts on a new source commit: the worker pushed and the base moved again, which starts a new spell. A pass that sees a clean merge, or the PR merged or abandoned, ends it (`pr.conflict-cleared`). A spell older than `watchers.conflictMinutes` (30) whose wake hasn't reached the worker, or whose conflict a pass still sees, logs `pr.conflict-stuck` once and raises a `conflict` inbox item. Spells are kept in memory, so after a restart a PR still in conflict wakes its worker once more. `conduct wait` without a daemon returns the same line while the PR conflicts.
|
|
291
|
+
|
|
265
292
|
## ADO Boards
|
|
266
293
|
|
|
267
294
|
A project whose work items live in Azure DevOps Boards (Cadence) sets `tracker.kind` to `ado-boards` (design note, section 12; ATK-319):
|
|
@@ -348,7 +375,7 @@ Everything lives in `~/.conductor` (`CONDUCTOR_HOME` overrides it):
|
|
|
348
375
|
|
|
349
376
|
| File | Holds |
|
|
350
377
|
|---|---|
|
|
351
|
-
| `config.json` | machine settings, JSONC (comments allowed), validated at startup; `inbox.runawayTokens` (2000000, the `runaway` rule's number); `notify` and `quietHours` (see Notifications); `scheduler` holds `mode` (`on`, `observe` or `off`), `slots` (4, across projects, and the most any rule can give one project), `dailyTokens` (20000000, the `daily-cap` rule's number) and `tickSeconds` (120); `sessions` holds `pollSeconds` (10), `settleSeconds` (5), `permissionMinutes` (5), `idleMinutes` (20); `watchers` holds `ado`, `github`, `health`, `linear` and `npm`, each `{ intervalSeconds, perMinute }` (30/60, 30/30, 30/30, 30/10, 20/30),
|
|
378
|
+
| `config.json` | machine settings, JSONC (comments allowed), validated at startup; `inbox.runawayTokens` (2000000, the `runaway` rule's number); `notify` and `quietHours` (see Notifications); `scheduler` holds `mode` (`on`, `observe` or `off`), `slots` (4, across projects, and the most any rule can give one project), `dailyTokens` (20000000, the `daily-cap` rule's number) and `tickSeconds` (120); `sessions` holds `pollSeconds` (10), `settleSeconds` (5), `permissionMinutes` (5), `idleMinutes` (20); `watchers` holds `ado`, `github`, `health`, `linear` and `npm`, each `{ intervalSeconds, perMinute }` (30/60, 30/30, 30/30, 30/10, 20/30), `statsMinutes` (10) and `conflictMinutes` (30) |
|
|
352
379
|
| `rules.json` | machine rules, JSONC, reloaded on save (see Rules) |
|
|
353
380
|
| `token` | the API token, readable by this user only; every request sends `Authorization: Bearer <token>` |
|
|
354
381
|
| `conductor.pid`, `port` | the single-instance lock and where the API listens (`127.0.0.1`) |
|
|
@@ -367,6 +394,7 @@ Everything lives in `~/.conductor` (`CONDUCTOR_HOME` overrides it):
|
|
|
367
394
|
- `DELETE /workers/:id` (`?force=true`): retire; 409 with the unfinished work when it refuses.
|
|
368
395
|
- `POST /workers/:id/attach`: wake if parked, mark attached, open the tab.
|
|
369
396
|
- `POST /items/:id/notes` with `{ "body": "## work-issue · …", "worker"?: 1 }`: post a phase note (see Notes); 201 with the note and the worker. 409 when it won't post it; 502 when the tracker didn't take it, with `posted: "no"` or `"unknown"`.
|
|
397
|
+
- `GET /items/:id/brief` (`?fresh=true`): the item's brief (see Briefs), as `{ "brief": … }`. 404 when the tracker has no such item, 409 when no project tracks it, 502 when the tracker couldn't be read.
|
|
370
398
|
- `GET /inbox`: the open inbox items, oldest first.
|
|
371
399
|
- `POST /inbox/:id/resolve`: Jason's answer (see Inbox). The body is `{ "action": "approve", "text"? }`, `{ "action": "revise", "text" }` or `{ "action": "done" }`.
|
|
372
400
|
- 200 with the item, the comment and the waits it resolved.
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { briefLines } from "./brief.js";
|
|
3
|
+
import { callApi, NotRunningError } from "./client.js";
|
|
4
|
+
import { ConductorError } from "./errors.js";
|
|
5
|
+
// Exit code for a brief no conductor gave (none running, one without the brief API, or one that
|
|
6
|
+
// couldn't read the tracker): the worker reads the item from the tracker itself. A refusal (no
|
|
7
|
+
// project tracks the item, the tracker has no such item) exits 1.
|
|
8
|
+
export const NOT_BRIEFED = 3;
|
|
9
|
+
// The daemon asks the tracker once or a few times, each within 20 s.
|
|
10
|
+
const BRIEF_TIMEOUT_MS = 60_000;
|
|
11
|
+
const link = z.object({ id: z.string(), status: z.string().nullable(), title: z.string().nullable() });
|
|
12
|
+
export const briefSchema = z.object({
|
|
13
|
+
approval: z.object({ at: z.string(), kind: z.enum(['approve', 'revise']), text: z.string() }).nullable(),
|
|
14
|
+
area: z.string().nullable(),
|
|
15
|
+
blockedBy: z.array(link),
|
|
16
|
+
blocks: z.array(link),
|
|
17
|
+
description: z.string(),
|
|
18
|
+
item: z.string(),
|
|
19
|
+
labels: z.array(z.string()),
|
|
20
|
+
notes: z.array(z.object({ at: z.string(), kind: z.string().nullable(), line: z.string().nullable(), phase: z.string() })),
|
|
21
|
+
plan: z.string().nullable(),
|
|
22
|
+
project: z.string(),
|
|
23
|
+
readAt: z.string(),
|
|
24
|
+
related: z.array(link),
|
|
25
|
+
status: z.object({ name: z.string(), type: z.string().nullable() }),
|
|
26
|
+
title: z.string(),
|
|
27
|
+
trackerProject: z.string().nullable(),
|
|
28
|
+
url: z.string().nullable(),
|
|
29
|
+
});
|
|
30
|
+
const refused = z.object({ details: z.array(z.string()).optional(), error: z.string() });
|
|
31
|
+
// `conduct brief <item>`: the item's context from the daemon, as text or JSON. Returns the exit
|
|
32
|
+
// code: 0, NOT_BRIEFED, or 1 (thrown) when the conductor refused it.
|
|
33
|
+
export async function briefCommand(paths, item, options, io) {
|
|
34
|
+
const notBriefed = (why) => {
|
|
35
|
+
io.err(`no brief: ${why}; read the item from the tracker yourself`);
|
|
36
|
+
return NOT_BRIEFED;
|
|
37
|
+
};
|
|
38
|
+
let answer;
|
|
39
|
+
try {
|
|
40
|
+
answer = await callApi(paths, {
|
|
41
|
+
method: 'GET',
|
|
42
|
+
path: `/items/${encodeURIComponent(item)}/brief${options.fresh ? '?fresh=true' : ''}`,
|
|
43
|
+
timeoutMs: BRIEF_TIMEOUT_MS,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
if (error instanceof NotRunningError)
|
|
48
|
+
return notBriefed('the conductor is not running');
|
|
49
|
+
throw error;
|
|
50
|
+
}
|
|
51
|
+
if (answer.status === 200) {
|
|
52
|
+
const { brief } = z.object({ brief: briefSchema }).parse(answer.body);
|
|
53
|
+
if (options.json)
|
|
54
|
+
io.out(JSON.stringify(brief, null, 2));
|
|
55
|
+
else
|
|
56
|
+
briefLines(brief).forEach((line) => io.out(line));
|
|
57
|
+
return 0;
|
|
58
|
+
}
|
|
59
|
+
const error = refused.safeParse(answer.body).data;
|
|
60
|
+
// A daemon from before the brief API answers its route's `not_found`; a missing item says which.
|
|
61
|
+
if (answer.status === 404 && error?.error === 'not_found')
|
|
62
|
+
return notBriefed('this conductor has no brief API (upgrade it)');
|
|
63
|
+
// The conductor couldn't read the tracker (no key, the tracker down): the worker still may.
|
|
64
|
+
if (answer.status === 502)
|
|
65
|
+
return notBriefed(`${error?.error ?? 'the conductor could not read the tracker'}${error?.details?.length ? ` (${error.details.join('; ')})` : ''}`);
|
|
66
|
+
throw new ConductorError(error?.error ?? `the API answered ${answer.status}`, error?.details ?? []);
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=brief-cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"brief-cli.js","sourceRoot":"","sources":["../src/brief-cli.ts"],"names":[],"mappings":"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"}
|
package/build/brief.js
ADDED
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { ConductorError } from "./errors.js";
|
|
3
|
+
import { ITEM, projectFor } from "./notes.js";
|
|
4
|
+
import { notePrefixes } from "./profile.js";
|
|
5
|
+
import { linearApi, LinearRequestError } from "./watchers/linear-api.js";
|
|
6
|
+
import { approvalAfterPlan, noteHeading } from "./watchers/linear.js";
|
|
7
|
+
// `conduct brief` (design note, section 13): one item's context for a worker's orient step, read
|
|
8
|
+
// by the daemon from the tracker with its own key or az login, never through an MCP. The queue's
|
|
9
|
+
// snapshot holds no description, relations or comments, so the brief reads the item itself.
|
|
10
|
+
const TTL_MS = 30_000;
|
|
11
|
+
// A brief the tracker couldn't give: `missing` when it has no such item, `unreadable` otherwise.
|
|
12
|
+
export class BriefError extends ConductorError {
|
|
13
|
+
reason;
|
|
14
|
+
constructor(message, reason, details = []) {
|
|
15
|
+
super(message, details);
|
|
16
|
+
this.name = 'BriefError';
|
|
17
|
+
this.reason = reason;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
// The brief as a reader sees it, for `conduct brief` without --json.
|
|
21
|
+
export function briefLines(brief) {
|
|
22
|
+
const links = (label, list) => list.length === 0 ? [] : [`${label}:`, ...list.map((l) => ` ${l.id} ${l.status ?? '?'} ${l.title ?? ''}`.trimEnd())];
|
|
23
|
+
const approval = brief.plan === null ? 'no Plan note yet'
|
|
24
|
+
: brief.approval === null ? `none after the Plan of ${brief.plan}`
|
|
25
|
+
: `${brief.approval.kind} ${brief.approval.at}: "${brief.approval.text}"`;
|
|
26
|
+
return [
|
|
27
|
+
`${brief.item} ${brief.title}`,
|
|
28
|
+
...(brief.url ? [brief.url] : []),
|
|
29
|
+
`status: ${brief.status.name}${brief.status.type && brief.status.type !== brief.status.name.toLowerCase() ? ` (${brief.status.type})` : ''}`,
|
|
30
|
+
`project: ${brief.project}${brief.trackerProject ? ` · ${brief.trackerProject}` : ''}`,
|
|
31
|
+
`area: ${brief.area ?? 'none'}`,
|
|
32
|
+
`labels: ${brief.labels.length > 0 ? brief.labels.join(', ') : 'none'}`,
|
|
33
|
+
...links('blocked by', brief.blockedBy),
|
|
34
|
+
...links('blocks', brief.blocks),
|
|
35
|
+
...links('related', brief.related),
|
|
36
|
+
...(brief.notes.length === 0
|
|
37
|
+
? ['notes: none']
|
|
38
|
+
: ['notes:', ...brief.notes.map((n) => ` ${n.at} ${n.phase}${n.kind ? ` · ${n.kind}${n.line ? `: ${n.line}` : ''}` : ''}`)]),
|
|
39
|
+
`approval: ${approval}`,
|
|
40
|
+
'',
|
|
41
|
+
brief.description.trim() || '(no description)',
|
|
42
|
+
];
|
|
43
|
+
}
|
|
44
|
+
// The brief from what the tracker gave: the comments as phase notes, the newest Plan, and the
|
|
45
|
+
// approval after it.
|
|
46
|
+
export function briefOf(item, project, read, prefixes, at) {
|
|
47
|
+
const { comments, viewer, ...fields } = read;
|
|
48
|
+
const sorted = [...comments].sort((a, b) => Date.parse(a.createdAt) - Date.parse(b.createdAt));
|
|
49
|
+
const notes = sorted.flatMap((c) => {
|
|
50
|
+
const heading = noteHeading(c.body, prefixes);
|
|
51
|
+
return heading ? [{ at: c.createdAt, ...heading }] : [];
|
|
52
|
+
});
|
|
53
|
+
const found = approvalAfterPlan(sorted, viewer, prefixes);
|
|
54
|
+
// Notes carry the same author as the answer, so only a comment that isn't a note can be it.
|
|
55
|
+
const said = found && sorted.find((c) => c.createdAt === found.at && c.authorId === viewer && noteHeading(c.body, prefixes) === null);
|
|
56
|
+
return {
|
|
57
|
+
...fields,
|
|
58
|
+
approval: found ? { ...found, text: said ? said.body.trim() : '' } : null,
|
|
59
|
+
item,
|
|
60
|
+
notes,
|
|
61
|
+
plan: notes.findLast((n) => n.phase === 'Plan')?.at ?? null,
|
|
62
|
+
project,
|
|
63
|
+
readAt: at.toISOString(),
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
export function briefService({ now = () => new Date(), reader, store, ttlMs = TTL_MS, }) {
|
|
67
|
+
const cache = new Map();
|
|
68
|
+
// Bumped by each event about an item, so a read that began before one isn't kept.
|
|
69
|
+
const changes = new Map();
|
|
70
|
+
// Whatever the daemon sees happen to an item (a note posted, an approve or revise it posted, a
|
|
71
|
+
// wait resolved) makes its brief stale at once.
|
|
72
|
+
store.onEvent((event) => {
|
|
73
|
+
if (!event.subject)
|
|
74
|
+
return;
|
|
75
|
+
const key = event.subject.toUpperCase();
|
|
76
|
+
cache.delete(key);
|
|
77
|
+
changes.set(key, (changes.get(key) ?? 0) + 1);
|
|
78
|
+
});
|
|
79
|
+
return {
|
|
80
|
+
read: async (item, { fresh = false } = {}) => {
|
|
81
|
+
if (!ITEM.test(item))
|
|
82
|
+
throw new ConductorError(`"${item}" is not a tracker item, such as ATK-311`);
|
|
83
|
+
const key = item.toUpperCase();
|
|
84
|
+
const at = now().getTime();
|
|
85
|
+
for (const [k, entry] of cache)
|
|
86
|
+
if (at - entry.at >= ttlMs)
|
|
87
|
+
cache.delete(k);
|
|
88
|
+
const hit = cache.get(key);
|
|
89
|
+
if (!fresh && hit)
|
|
90
|
+
return hit.brief;
|
|
91
|
+
let project;
|
|
92
|
+
try {
|
|
93
|
+
project = projectFor(store, key);
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
// Its details are for a note (--worker), which a brief doesn't take.
|
|
97
|
+
throw error instanceof ConductorError ? new ConductorError(error.message) : error;
|
|
98
|
+
}
|
|
99
|
+
const seen = changes.get(key) ?? 0;
|
|
100
|
+
let read;
|
|
101
|
+
try {
|
|
102
|
+
read = await reader.read(key, project.profile);
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
if (error instanceof BriefError)
|
|
106
|
+
throw error;
|
|
107
|
+
const details = error instanceof ConductorError ? error.details : [];
|
|
108
|
+
throw new BriefError(`couldn't read ${key}: ${error instanceof Error ? error.message : String(error)}`, 'unreadable', details);
|
|
109
|
+
}
|
|
110
|
+
const brief = briefOf(key, project.name, read, notePrefixes(project.profile), now());
|
|
111
|
+
if ((changes.get(key) ?? 0) === seen)
|
|
112
|
+
cache.set(key, { at: now().getTime(), brief });
|
|
113
|
+
return brief;
|
|
114
|
+
},
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
const STATE = 'state { name type }';
|
|
118
|
+
const LINKED = `identifier title ${STATE}`;
|
|
119
|
+
const COMMENTS = 'comments(first: 100, after: $after) { pageInfo { hasNextPage endCursor } nodes { body createdAt user { id } } }';
|
|
120
|
+
export const BRIEF_QUERY = `query Brief($id: String!, $after: String) {
|
|
121
|
+
viewer { id }
|
|
122
|
+
issue(id: $id) {
|
|
123
|
+
identifier title description url ${STATE}
|
|
124
|
+
project { name }
|
|
125
|
+
labels(first: 50) { nodes { name parent { name } } }
|
|
126
|
+
relations(first: 50) { nodes { type relatedIssue { ${LINKED} } } }
|
|
127
|
+
inverseRelations(first: 50) { nodes { type issue { ${LINKED} } } }
|
|
128
|
+
${COMMENTS}
|
|
129
|
+
}
|
|
130
|
+
}`;
|
|
131
|
+
export const BRIEF_COMMENTS_QUERY = `query BriefComments($id: String!, $after: String) {
|
|
132
|
+
issue(id: $id) { ${COMMENTS} }
|
|
133
|
+
}`;
|
|
134
|
+
const state = z.object({ name: z.string(), type: z.string() });
|
|
135
|
+
const linked = z.object({ identifier: z.string(), state, title: z.string().nullable() });
|
|
136
|
+
const commentsPage = z.object({
|
|
137
|
+
nodes: z.array(z.object({ body: z.string(), createdAt: z.string(), user: z.object({ id: z.string() }).nullable() })),
|
|
138
|
+
pageInfo: z.object({ endCursor: z.string().nullable(), hasNextPage: z.boolean() }),
|
|
139
|
+
});
|
|
140
|
+
const briefAnswer = z.object({
|
|
141
|
+
issue: z
|
|
142
|
+
.object({
|
|
143
|
+
comments: commentsPage,
|
|
144
|
+
description: z.string().nullable(),
|
|
145
|
+
identifier: z.string(),
|
|
146
|
+
inverseRelations: z.object({ nodes: z.array(z.object({ issue: linked.nullable(), type: z.string() })) }),
|
|
147
|
+
labels: z.object({ nodes: z.array(z.object({ name: z.string(), parent: z.object({ name: z.string() }).nullable() })) }),
|
|
148
|
+
project: z.object({ name: z.string() }).nullable(),
|
|
149
|
+
relations: z.object({ nodes: z.array(z.object({ relatedIssue: linked.nullable(), type: z.string() })) }),
|
|
150
|
+
state,
|
|
151
|
+
title: z.string(),
|
|
152
|
+
url: z.string().nullable(),
|
|
153
|
+
})
|
|
154
|
+
.nullable(),
|
|
155
|
+
viewer: z.object({ id: z.string() }),
|
|
156
|
+
});
|
|
157
|
+
const commentsAnswer = z.object({ issue: z.object({ comments: commentsPage }).nullable() });
|
|
158
|
+
// Linear: the issue, its labels (the Area is the one under the profile's label group), relations
|
|
159
|
+
// both ways and every comment, in one request (more only for comments past the first 100).
|
|
160
|
+
export function linearBriefs(options = {}) {
|
|
161
|
+
const request = linearApi(options);
|
|
162
|
+
const ask = async (query, variables) => {
|
|
163
|
+
try {
|
|
164
|
+
return await request(query, variables);
|
|
165
|
+
}
|
|
166
|
+
catch (error) {
|
|
167
|
+
// Linear answers an identifier it doesn't have with an error, not a null issue.
|
|
168
|
+
if (error instanceof LinearRequestError && error.kind === 'refused' && /not found/i.test(error.message)) {
|
|
169
|
+
throw new BriefError(`Linear has no issue ${String(variables.id)}`, 'missing');
|
|
170
|
+
}
|
|
171
|
+
throw error;
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
return {
|
|
175
|
+
read: async (item, profile) => {
|
|
176
|
+
if (profile.tracker.kind !== 'linear')
|
|
177
|
+
throw new ConductorError(`project ${profile.name}'s tracker isn't Linear`);
|
|
178
|
+
const { issue, viewer } = briefAnswer.parse(await ask(BRIEF_QUERY, { after: null, id: item }));
|
|
179
|
+
if (!issue)
|
|
180
|
+
throw new BriefError(`Linear has no issue ${item}`, 'missing');
|
|
181
|
+
const comments = [...issue.comments.nodes];
|
|
182
|
+
for (let page = issue.comments.pageInfo; page.hasNextPage && page.endCursor !== null;) {
|
|
183
|
+
const more = commentsAnswer.parse(await ask(BRIEF_COMMENTS_QUERY, { after: page.endCursor, id: item })).issue?.comments;
|
|
184
|
+
if (!more)
|
|
185
|
+
break;
|
|
186
|
+
comments.push(...more.nodes);
|
|
187
|
+
page = more.pageInfo;
|
|
188
|
+
}
|
|
189
|
+
const link = (l) => ({ id: l.identifier, status: l.state.name, title: l.title });
|
|
190
|
+
// "A blocks B" is stored on A: B sees it as an inverse relation. `related` shows on either side.
|
|
191
|
+
const outward = issue.relations.nodes.flatMap((r) => (r.relatedIssue ? [{ issue: r.relatedIssue, type: r.type }] : []));
|
|
192
|
+
const inward = issue.inverseRelations.nodes.flatMap((r) => (r.issue ? [{ issue: r.issue, type: r.type }] : []));
|
|
193
|
+
const { areaLabelGroup } = profile.tracker;
|
|
194
|
+
return {
|
|
195
|
+
area: issue.labels.nodes.find((l) => l.parent?.name === areaLabelGroup)?.name ?? null,
|
|
196
|
+
blockedBy: inward.filter((r) => r.type === 'blocks').map((r) => link(r.issue)),
|
|
197
|
+
blocks: outward.filter((r) => r.type === 'blocks').map((r) => link(r.issue)),
|
|
198
|
+
comments: comments.map((c) => ({ authorId: c.user?.id ?? null, body: c.body, createdAt: c.createdAt })),
|
|
199
|
+
description: issue.description ?? '',
|
|
200
|
+
labels: issue.labels.nodes.map((l) => l.name),
|
|
201
|
+
related: [...outward, ...inward].filter((r) => r.type === 'related').map((r) => link(r.issue)),
|
|
202
|
+
status: { name: issue.state.name, type: issue.state.type },
|
|
203
|
+
title: issue.title,
|
|
204
|
+
trackerProject: issue.project?.name ?? null,
|
|
205
|
+
url: issue.url,
|
|
206
|
+
viewer: viewer.id,
|
|
207
|
+
};
|
|
208
|
+
},
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
//# sourceMappingURL=brief.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"brief.js","sourceRoot":"","sources":["../src/brief.ts"],"names":[],"mappings":"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"}
|
package/build/cli.js
CHANGED
|
@@ -5,6 +5,7 @@ import { resolve, sep } from 'node:path';
|
|
|
5
5
|
import { fileURLToPath } from 'node:url';
|
|
6
6
|
import { parseArgs } from 'node:util';
|
|
7
7
|
import { z } from 'zod';
|
|
8
|
+
import { briefCommand } from "./brief-cli.js";
|
|
8
9
|
import { heldLocks, lockCommand, lockLine, portsCommand } from "./broker-cli.js";
|
|
9
10
|
import { callApi, NotRunningError, ping, readEndpoint } from "./client.js";
|
|
10
11
|
import { loadConfig } from "./config.js";
|
|
@@ -418,6 +419,14 @@ async function main(argv) {
|
|
|
418
419
|
if (sub === undefined)
|
|
419
420
|
throw usageError('attach');
|
|
420
421
|
return attach(paths, sub);
|
|
422
|
+
case 'brief':
|
|
423
|
+
if (sub === undefined)
|
|
424
|
+
throw usageError('brief');
|
|
425
|
+
process.exitCode = await briefCommand(paths, sub, { fresh: values.fresh === true, json: values.json === true }, {
|
|
426
|
+
err: (line) => process.stderr.write(`${line}\n`),
|
|
427
|
+
out,
|
|
428
|
+
});
|
|
429
|
+
return;
|
|
421
430
|
case 'console':
|
|
422
431
|
return consoleCommand(paths, { here: values.here === true, project: values.project });
|
|
423
432
|
case 'done':
|