@detergent-software/conductor 3.6.1-dev.1 → 3.7.0-dev.1

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 CHANGED
@@ -2,6 +2,16 @@
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
+ ## [3.7.0-dev.1](https://emergentcode.visualstudio.com/Emergent%20Software/_git/Emergent.AgenticToolkit/branchCompare?baseVersion=GTconductor-v3.6.1-dev.1&targetVersion=GTconductor-v3.7.0-dev.1) (2026-11-11)
6
+
7
+ ### Features
8
+
9
+ * **conductor:** run the profile's checks with conduct checks (ATK-969) ([3e73be7](https://emergentcode.visualstudio.com/Emergent%20Software/_git/Emergent.AgenticToolkit/commit/3e73be725f5128882e61d93bb59f8dc149f023a9))
10
+
11
+ ### Bug Fixes
12
+
13
+ * **conductor:** address review of conduct checks (ATK-969) ([010abb9](https://emergentcode.visualstudio.com/Emergent%20Software/_git/Emergent.AgenticToolkit/commit/010abb94e436f1eccdb08a91bd35a0b9c90c8f21))
14
+
5
15
  ## [3.6.1-dev.1](https://emergentcode.visualstudio.com/Emergent%20Software/_git/Emergent.AgenticToolkit/branchCompare?baseVersion=GTconductor-v3.6.0&targetVersion=GTconductor-v3.6.1-dev.1) (2026-11-11)
6
16
 
7
17
  ### Bug Fixes
package/README.md CHANGED
@@ -72,6 +72,7 @@ conduct comments <item> [--since <time>] [--json]
72
72
  conduct search <terms…> [--json] the tracker's open items that match every term
73
73
  conduct mode --tier S|M|L --files <a,b>
74
74
  the landing mode a plan states before its PR (see Worker verbs)
75
+ conduct checks [--all] [--json] the profile's checks for the paths the branch changes, PASS/FAIL (see Worker verbs)
75
76
  conduct wait <condition> wait for an outside event (see Waits)
76
77
  conduct state [--repo <repo>] the worktree's branch, changes and PR, and its other repos' (see Worker verbs)
77
78
  conduct branch <type> <slug> [--item <item>]
@@ -251,6 +252,12 @@ Protocol 2's verbs on git and the code host (providers design note, section 4),
251
252
  - `conduct file --title … --body-file … --area … [--related …] [--blocked-by …] [--human] [--waits-release]` files a follow-up of the checkout's item: in Backlog, in the item's project, with one Area (a label of the profile's Area group, a path below a board's `areaRoot`, or the name after a GitHub Issues `areaPrefix` label; none, and no `--area`, for a Linear team with no Area group; on Boards, no `--area` files it at the `areaRoot` itself, for a board with no sub-areas, ATK-702), the profile's `triageLabel`, its `humanLabel` with `--human`, and its `releaseWait` label (a tag on Boards) with `--waits-release` (the follow-up then waits until each Done blocker has shipped). It is related to the item and each `--related`, and waits on each `--blocked-by` (keys, repeated or comma-separated). A key of another project, an Area outside the group, or `--waits-release` without a `--blocked-by` or on a profile with no `tracker.releaseWait`, is refused before anything is written. On Boards, Azure DevOps refuses an Area Path the board doesn't have (`TF401347`), and the error names the path and how to file at the root. On Linear a relation that fails after the issue exists is a warning; on Boards the item and its links are one request. On GitHub Issues the follow-up also carries the `queueLabel`, the related items are a `Related: #n` line in its body (GitHub has no related relation), and a dependency that fails after the issue exists is a warning. With `--waits-release`, Linear and GitHub Issues look up each `--blocked-by` first and refuse one they don't have. The daemon files it for the worker (`POST /workers/:id/follow-ups`) and logs `tracker.filed`. The worker searches for a duplicate first, with `conduct search`: this only files. On Boards a filing also carries the profile's `queueTags`; `--type` picks the work item type, and `--done-when-file` the Done when, which goes to the type's Acceptance Criteria when it has them and is otherwise the body's last section (ADO Boards, below).
252
253
  - `conduct file --new --title … --body-file … [--area …] [--type …] [--done-when-file …] [--related …] [--blocked-by …] [--human] [--triage] [--waits-release]` files a new item that follows up none, as `/file-item` does on ADO Boards and GitHub Issues (ATK-709). It files here, as the project's account, from any checkout of the project (a worker's included, with no daemon record), related only to each `--related`, and with the triage label only with `--triage`. On Linear it is refused: a new item there has no item to take its project from, and `/file-item` files it itself.
253
254
  - `conduct mode --tier S|M|L --files <a,b>` gives the landing mode a plan states before its PR exists, with the reasons, by the rule `conduct land` holds the PR to (`work.landing`). It reads only the profile, so it runs here.
255
+ - `conduct checks [--all] [--json]` (ATK-969) runs the checks the profile declares, so a worker's verify step is one call and not a hooks table turned into commands each time:
256
+ - **Declaring them.** `"checks": [{ "name": "web lint", "command": "pnpm -C apps/web lint", "cwd": ".", "paths": ["apps/web/"] }]`. `cwd` is a folder inside the checkout (the root by default; an absolute or `..` path is refused), names are unique, and `paths` are globs relative to the checkout as `path.matchesGlob` reads them, with one that ends in `/` meaning every file under that folder, dotfiles too (`*` and `**` pass over a name that starts with a dot, as `path.matchesGlob` does). The field needs conductor `3.7.0-dev.1`. A project with none keeps its checks in its hooks file, and the verb refuses with a pointer there.
257
+ - **Which run.** A check runs when one of its globs matches a path the branch changes: a file that differs between the branch's fork point from `origin/<base>` and the working tree (committed or not, deleted too), or an untracked file git doesn't ignore, so checks run before a commit still match. `--all` runs every check. None matching prints `nothing to run` and exits 0.
258
+ - **Running them.** One after another in the profile's order, each through a shell in its `cwd` for up to 30 minutes, with stderr merged into stdout. It prints `PASS` or `FAIL` with the name and time as each ends, and under a failure the last 40 lines of its output without colour codes, then the verdict. `--json` prints one object at the end instead (`outcome` `pass`, `fail` or `none-matched`, each check's command, cwd, status, exit code, duration and tail, the changed paths). It exits 1 when a check failed.
259
+ - **The record.** The verdicts, never the output, go to the daemon for the worker that owns the checkout (`POST /workers/:id/checks`), which logs `worker.checks-ran` with the commit the run started on and `dirty`: true when the checks ran on more than that commit (uncommitted or untracked files, or a HEAD that moved during the run). The verb says whether it was recorded; with no daemon, one without the route, or no worker for the checkout it records nothing and still exits on the checks. It runs here either way.
260
+ - **Checking them.** `conduct project check` reads the clone's files at `origin/<base>` and warns, on its profile result, about a check whose `cwd` holds no file or one of whose globs matches none: it would never run as written.
254
261
  - `conduct pr status <pr>` gives any PR's verdict, read as `land` reads the worker's own, with no checkout, no ownership check and nothing armed: a PR the item didn't open, such as one a skill publish opened in the registry. On `merged` it names the `mergeCommit` and `noFastForward` (whether that commit has two parents), so a worker passes it to `conduct runs` (ATK-534). `--head <branch>` in place of the number finds the newest PR from that branch, in any state, so a worker that lost a publish's PR URL finds it by the publish's branch; a branch with no PR exits 1 (ATK-778). A `conduct wait pr` that ends on a merge names the merge commit too: `pr <repo>#<n> merged as <sha>`.
255
262
  - `conduct pr threads <pr>` lists the PR's threads (on GitHub each comment and review) with `needsAnswer` (ATK-384). `conduct reply <pr> [<thread>]` answers on the worker's own PR: in the ADO thread named, or as a note on the PR. The text is headed `## <work skill> · Reply` unless it starts with a note heading. The daemon logs `code-host.replied`. `--repo` takes `github:<owner>/<repo>` (from its `.scratch/repos` checkout, into its default branch) or `ado:<repository>`; the profile's `codeHost` is the default.
256
263
  - `conduct pr abandon <pr> --reason <why>` closes the worker's PR unmerged, such as one another item's PR made redundant (ATK-479): ADO sets its status to `abandoned` (`PATCH pullrequests/<n>`), GitHub closes it (`PATCH pulls/<n>`). Then it posts a closed `## <work skill> · Abandoned` note with the reason; a note that fails after the PR closed comes back as `noteError`, not an error. The PR must be the item's: its title and head branch carry the key, and it isn't from its base. It must also be from the branch the checkout is on now, unless `--force`, which takes the item's PR from another of its branches (an earlier one, a follow-up's), never another item's. A merged PR is refused. A closed one stays closed (`already: true`) and gets the note only when it has no Abandoned note yet, so it is safe to repeat, and a second run posts a note that failed the first time. The daemon abandons it for the worker (`POST /workers/:id/abandons`) and logs `code-host.pr-abandoned`.
@@ -800,6 +807,7 @@ Everything lives in `~/.conductor` (`CONDUCTOR_HOME` overrides it):
800
807
  - `POST /workers` with `{ "item": "ENG-312", "project"?, "probe"?, "prompt"?, "conductor"? }`: launch; answers 202 with the `launching` worker. `GET /workers/:id` shows it with its latest events.
801
808
  - `DELETE /workers/:id` (`?force=true`): retire; 409 with the unfinished work (the worktree's, and each `.scratch/repos` checkout's under `checkouts`) when it refuses.
802
809
  - `POST /workers/:id/attach`: wake if parked, mark attached, open the tab; `tab` is why none opened, else null, `hint` how to reach one off the desktop (`tmux attach -t <session>`), and `already` true when a `claude attach` client runs for the session, so no tab opened.
810
+ - `POST /workers/:id/checks` with `{ "all", "base", "dirty", "head", "results": [{ "name", "status", "exitCode", "durationMs" }] }`: `conduct checks`'s verdicts, logged as `worker.checks-ran` for an in-flight worker; 201 with the event's id, 409 for a worker that isn't in flight.
803
811
  - `POST /workers/:id/prs` with `{ "title", "body", "repo"? }`: open the worker's PR after the ownership checks (see Worker verbs); 201 with the PR, 409 refused, 503 a lost login (with `login.provider` and `login.command`), 502 the host failed.
804
812
  - `POST /workers/:id/landings` with `{ "pr", "reason", "mode"?, "rearm"?, "repo"?, "requeue"? }`: `conduct land` for the worker; 200 with the landing and its verdict. `POST /workers/:id/replies` with `{ "pr", "body", "thread"?, "repo"? }`: `conduct reply`; 201. Both answer 409, 503 and 502 as `/prs` does.
805
813
  - `POST /items/:id/notes` with `{ "body": "## work-item · …", "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"`.
@@ -0,0 +1,179 @@
1
+ import { existsSync, statSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { stripVTControlCharacters } from 'node:util';
4
+ import { callApi } from "./client.js";
5
+ import { here } from "./code-host-cli.js";
6
+ import { ConductorError } from "./errors.js";
7
+ import { globMatches, PROFILE_FILE } from "./profile.js";
8
+ import { outputOf, run } from "./run.js";
9
+ import { daemonWorker } from "./wait.js";
10
+ // A build or a test suite can take minutes; one that hangs stops here.
11
+ export const CHECK_TIMEOUT_MS = 30 * 60_000;
12
+ // The end of a failure's output that the line under it shows.
13
+ const TAIL_LINES = 40;
14
+ // The paths the branch changes: every file that differs between its fork point from origin/<base>
15
+ // and the working tree (committed or not, deleted too), and the untracked files git doesn't ignore,
16
+ // so checks run before a commit still match. Relative to the checkout, with forward slashes.
17
+ export async function changedPaths(git, checkout, base) {
18
+ const fork = await git(['merge-base', `origin/${base}`, 'HEAD'], checkout);
19
+ const forkPoint = fork.stdout.trim();
20
+ if (fork.code !== 0 || forkPoint === '') {
21
+ throw new ConductorError(`can't find where the branch forked from origin/${base}`, [
22
+ outputOf(fork, 300),
23
+ `run git fetch origin ${base}, or conduct checks --all`,
24
+ ]);
25
+ }
26
+ const diff = await git(['diff', '--name-only', '--no-renames', '-z', forkPoint], checkout);
27
+ if (diff.code !== 0)
28
+ throw new ConductorError('git diff failed', [outputOf(diff, 300)]);
29
+ const untracked = await git(['ls-files', '--others', '--exclude-standard', '-z'], checkout);
30
+ if (untracked.code !== 0)
31
+ throw new ConductorError('git ls-files failed', [outputOf(untracked, 300)]);
32
+ const paths = [diff.stdout, untracked.stdout].flatMap((text) => text.split('\0')).filter((p) => p !== '');
33
+ return [...new Set(paths)].sort();
34
+ }
35
+ // `conduct checks`: refused (exit 1) when the profile declares none. Otherwise 1 when a check failed,
36
+ // 0 when every one that ran passed or none matched.
37
+ export async function checksCommand(paths, options, io) {
38
+ const { checkout, git, profile } = await here(paths, io);
39
+ const declared = profile.checks;
40
+ if (declared.length === 0) {
41
+ throw new ConductorError('the profile declares no checks', [
42
+ `declare them as "checks" in ${PROFILE_FILE} (conduct help checks), or run the ones the work skill's checks hook names`,
43
+ ]);
44
+ }
45
+ const base = profile.baseBranch;
46
+ const changed = options.all ? null : await changedPaths(git, checkout, base);
47
+ const selected = changed === null ? [...declared] : selectChecks(declared, changed);
48
+ const show = (line) => {
49
+ if (!options.json)
50
+ io.out(line);
51
+ };
52
+ show(changed === null
53
+ ? `checks: all ${declared.length} (--all)`
54
+ : `checks: ${selected.length} of ${declared.length} match the ${changed.length} ${changed.length === 1 ? 'path' : 'paths'} changed since origin/${base}`);
55
+ const report = { all: options.all, base, changed, declared: declared.length };
56
+ if (selected.length === 0) {
57
+ show("nothing to run: no check's paths match a changed path (--all runs every one)");
58
+ if (options.json)
59
+ io.out(JSON.stringify({ ...report, checks: [], outcome: 'none-matched', via: 'local' }, null, 2));
60
+ return 0;
61
+ }
62
+ const headNow = async () => (await git(['rev-parse', 'HEAD'], checkout)).stdout.trim();
63
+ const head = await headNow();
64
+ const status = await git(['status', '--porcelain'], checkout);
65
+ const uncommitted = status.code !== 0 || status.stdout.trim() !== '';
66
+ const now = io.now ?? Date.now;
67
+ const width = Math.max(...selected.map((c) => c.name.length));
68
+ const runs = [];
69
+ for (const check of selected) {
70
+ const ran = await runCheck(check, checkout, io.runCheck ?? defaultRunCheck, now);
71
+ runs.push(ran);
72
+ checkLines(ran, width).forEach(show);
73
+ }
74
+ const failed = runs.filter((r) => r.status === 'fail').length;
75
+ const passed = runs.length - failed;
76
+ show(failed === 0
77
+ ? `PASS: ${passed === 1 ? 'the check' : `all ${passed} checks`} passed`
78
+ : `FAIL: ${failed} of ${runs.length} failed`);
79
+ const dirty = uncommitted || (await headNow()) !== head;
80
+ const record = {
81
+ all: options.all,
82
+ base,
83
+ dirty,
84
+ head,
85
+ results: runs.map(({ durationMs, exitCode, name, status }) => ({ durationMs, exitCode, name, status })),
86
+ };
87
+ const recorded = await (io.record ?? ((dir, body) => recordOnWorker(paths, dir, body)))(checkout, record);
88
+ show(recorded.recorded
89
+ ? `recorded on worker ${recorded.worker} (worker.checks-ran) at ${head.slice(0, 8)}${dirty ? ' with uncommitted changes' : ''}`
90
+ : `not recorded: ${recorded.why}`);
91
+ if (options.json) {
92
+ io.out(JSON.stringify({
93
+ ...report,
94
+ checks: runs,
95
+ dirty,
96
+ failed,
97
+ head,
98
+ outcome: failed === 0 ? 'pass' : 'fail',
99
+ passed,
100
+ ...recorded,
101
+ via: 'local',
102
+ }, null, 2));
103
+ }
104
+ return failed === 0 ? 0 : 1;
105
+ }
106
+ // The checks one of the changed paths matches, in the profile's order.
107
+ export function selectChecks(checks, changed) {
108
+ return checks.filter((check) => changed.some((path) => check.paths.some((glob) => globMatches(glob, path))));
109
+ }
110
+ // A check's line, then a failure's tail under it.
111
+ function checkLines(ran, width) {
112
+ const seconds = `${(ran.durationMs / 1000).toFixed(1)} s`;
113
+ const why = ran.status === 'pass' ? '' : ` ${ran.error ?? `exit ${ran.exitCode}`}`;
114
+ const line = `${ran.status === 'pass' ? 'PASS' : 'FAIL'} ${ran.name.padEnd(width)} ${seconds}${why}`;
115
+ return [line, ...ran.tail.map((t) => ` ${t}`)];
116
+ }
117
+ function defaultRunCheck(check, dir) {
118
+ return run(check.command, [], { combineOutput: true, cwd: dir, shell: true, timeoutMs: CHECK_TIMEOUT_MS });
119
+ }
120
+ function messageOf(error) {
121
+ return error instanceof Error ? error.message : String(error);
122
+ }
123
+ // The result on the worker that owns this checkout, as worker.checks-ran. Never fails the verb: the
124
+ // checks have run, so a record that can't be made says why instead.
125
+ async function recordOnWorker(paths, checkout, body) {
126
+ try {
127
+ const worker = await daemonWorker(paths, checkout, undefined);
128
+ if (worker === 'no-daemon')
129
+ return { recorded: false, why: 'no conductor is running' };
130
+ if (worker === 'unreachable')
131
+ return { recorded: false, why: "the conductor didn't answer" };
132
+ if (worker === null)
133
+ return { recorded: false, why: "no conductor worker's worktree is this checkout" };
134
+ const answer = await callApi(paths, {
135
+ body,
136
+ method: 'POST',
137
+ path: `/workers/${worker.id}/checks`,
138
+ timeoutMs: 30_000,
139
+ });
140
+ if (answer.status === 201)
141
+ return { recorded: true, worker: worker.name };
142
+ if (answer.status === 404)
143
+ return { recorded: false, why: 'the conductor running is older than conduct checks' };
144
+ const error = typeof answer.body === 'object' && answer.body !== null && 'error' in answer.body
145
+ ? `: ${String(answer.body.error)}`
146
+ : '';
147
+ return { recorded: false, why: `the conductor answered ${answer.status}${error}` };
148
+ }
149
+ catch (error) {
150
+ return { recorded: false, why: messageOf(error) };
151
+ }
152
+ }
153
+ async function runCheck(check, checkout, runOne, now) {
154
+ const dir = join(checkout, check.cwd);
155
+ const base = { command: check.command, cwd: check.cwd, name: check.name };
156
+ // A shell started in a missing folder says only that the shell wasn't found.
157
+ if (!existsSync(dir) || !statSync(dir).isDirectory()) {
158
+ const error = `no folder ${check.cwd} in the checkout`;
159
+ return { ...base, durationMs: 0, error, exitCode: null, status: 'fail', tail: [] };
160
+ }
161
+ const started = now();
162
+ const result = await runOne(check, dir);
163
+ const durationMs = Math.max(0, now() - started);
164
+ const pass = result.code === 0;
165
+ return {
166
+ ...base,
167
+ durationMs,
168
+ error: result.error,
169
+ exitCode: result.code,
170
+ status: pass ? 'pass' : 'fail',
171
+ tail: pass ? [] : tailOf(result),
172
+ };
173
+ }
174
+ // The end of what a failed check printed, without colour codes.
175
+ function tailOf(result) {
176
+ const text = stripVTControlCharacters(`${result.stdout}${result.stderr}`).replace(/\r\n?/g, '\n').trimEnd();
177
+ return text === '' ? [] : text.split('\n').slice(-TAIL_LINES);
178
+ }
179
+ //# sourceMappingURL=checks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checks.js","sourceRoot":"","sources":["../src/checks.ts"],"names":[],"mappings":"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"}
package/build/cli.js CHANGED
@@ -7,6 +7,7 @@ import { parseArgs } from 'node:util';
7
7
  import { z } from 'zod';
8
8
  import { briefCommand } from "./brief-cli.js";
9
9
  import { heldLocks, lockCommand, lockLine, portsCommand } from "./broker-cli.js";
10
+ import { checksCommand } from "./checks.js";
10
11
  import { trustStep } from "./claude.js";
11
12
  import { callApi, NotRunningError, ping, readEndpoint } from "./client.js";
12
13
  import { branchCommand, checkoutCommand, dispatchCommand, fileCommand, landCommand, modeCommand, prAbandonCommand, prCreateCommand, prStatusCommand, prThreadsCommand, replyCommand, runsCommand, stateCommand, timelineCommand, } from "./code-host-cli.js";
@@ -538,6 +539,7 @@ async function main(argv) {
538
539
  allowPositionals: true,
539
540
  args: argv,
540
541
  options: {
542
+ all: { type: 'boolean' },
541
543
  'allow-downgrade': { type: 'boolean' },
542
544
  area: { type: 'string' },
543
545
  base: { type: 'string' },
@@ -653,6 +655,11 @@ async function main(argv) {
653
655
  throw usageError('checkout');
654
656
  process.exitCode = await checkoutCommand(paths, sub, arg, fourth, { ...item, ...(values.base === undefined ? {} : { base: values.base }) }, verbIo());
655
657
  return;
658
+ case 'checks':
659
+ if (sub !== undefined)
660
+ throw usageError('checks');
661
+ process.exitCode = await checksCommand(paths, { all: values.all === true, json: values.json === true }, verbIo());
662
+ return;
656
663
  case 'close':
657
664
  if (sub === undefined || arg !== undefined)
658
665
  throw usageError('close');