@detergent-software/conductor 3.0.0-dev.4 → 3.0.0-dev.40

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.
Files changed (212) hide show
  1. package/CHANGELOG.md +339 -0
  2. package/README.md +270 -123
  3. package/build/brief-cli.js +5 -12
  4. package/build/brief-cli.js.map +1 -1
  5. package/build/brief.js +4 -3
  6. package/build/brief.js.map +1 -1
  7. package/build/broker-cli.js +15 -10
  8. package/build/broker-cli.js.map +1 -1
  9. package/build/broker.js +1 -1
  10. package/build/broker.js.map +1 -1
  11. package/build/claude.js +48 -2
  12. package/build/claude.js.map +1 -1
  13. package/build/cli.js +221 -71
  14. package/build/cli.js.map +1 -1
  15. package/build/clones.js +92 -0
  16. package/build/clones.js.map +1 -0
  17. package/build/code-host-cli.js +158 -39
  18. package/build/code-host-cli.js.map +1 -1
  19. package/build/code-host-service.js +35 -2
  20. package/build/code-host-service.js.map +1 -1
  21. package/build/code-host.js +140 -16
  22. package/build/code-host.js.map +1 -1
  23. package/build/conditions.js +33 -16
  24. package/build/conditions.js.map +1 -1
  25. package/build/config.js +58 -28
  26. package/build/config.js.map +1 -1
  27. package/build/console.js +43 -27
  28. package/build/console.js.map +1 -1
  29. package/build/credentials.js +49 -36
  30. package/build/credentials.js.map +1 -1
  31. package/build/daemon.js +57 -66
  32. package/build/daemon.js.map +1 -1
  33. package/build/file-lock.js +35 -3
  34. package/build/file-lock.js.map +1 -1
  35. package/build/follow-ups.js +2 -2
  36. package/build/follow-ups.js.map +1 -1
  37. package/build/help.js +228 -82
  38. package/build/help.js.map +1 -1
  39. package/build/history.js +10 -4
  40. package/build/history.js.map +1 -1
  41. package/build/host/credential-manager.js +109 -0
  42. package/build/host/credential-manager.js.map +1 -0
  43. package/build/host/keychain.js +44 -0
  44. package/build/host/keychain.js.map +1 -0
  45. package/build/host/launchd.js +118 -0
  46. package/build/host/launchd.js.map +1 -0
  47. package/build/host/libsecret.js +40 -0
  48. package/build/host/libsecret.js.map +1 -0
  49. package/build/host/macos-terminal.js +63 -0
  50. package/build/host/macos-terminal.js.map +1 -0
  51. package/build/host/platform.js +4 -0
  52. package/build/host/platform.js.map +1 -0
  53. package/build/host/secrets.js +46 -0
  54. package/build/host/secrets.js.map +1 -0
  55. package/build/host/shell.js +26 -0
  56. package/build/host/shell.js.map +1 -0
  57. package/build/host/startup.js +26 -0
  58. package/build/host/startup.js.map +1 -0
  59. package/build/host/systemd.js +91 -0
  60. package/build/host/systemd.js.map +1 -0
  61. package/build/host/task-scheduler.js +78 -0
  62. package/build/host/task-scheduler.js.map +1 -0
  63. package/build/host/terminal.js +46 -0
  64. package/build/host/terminal.js.map +1 -0
  65. package/build/host/tmux.js +39 -0
  66. package/build/host/tmux.js.map +1 -0
  67. package/build/host/windows-terminal.js +46 -0
  68. package/build/host/windows-terminal.js.map +1 -0
  69. package/build/in-process.js +6 -5
  70. package/build/in-process.js.map +1 -1
  71. package/build/inbox.js +50 -34
  72. package/build/inbox.js.map +1 -1
  73. package/build/init.js +509 -0
  74. package/build/init.js.map +1 -0
  75. package/build/landing.js +86 -7
  76. package/build/landing.js.map +1 -1
  77. package/build/lib/providers/ado/code-host.js +5 -1
  78. package/build/lib/providers/ado/code-host.js.map +1 -1
  79. package/build/lib/providers/ado/pipelines.js +138 -26
  80. package/build/lib/providers/ado/pipelines.js.map +1 -1
  81. package/build/lib/providers/ado/trigger.js +5 -0
  82. package/build/lib/providers/ado/trigger.js.map +1 -1
  83. package/build/lib/providers/ado/writes.js +17 -2
  84. package/build/lib/providers/ado/writes.js.map +1 -1
  85. package/build/lib/providers/github/actions.js +90 -3
  86. package/build/lib/providers/github/actions.js.map +1 -1
  87. package/build/lib/providers/github/code-host.js +2 -0
  88. package/build/lib/providers/github/code-host.js.map +1 -1
  89. package/build/lib/providers/github/writes.js +25 -2
  90. package/build/lib/providers/github/writes.js.map +1 -1
  91. package/build/lib/providers/index.js +4 -3
  92. package/build/lib/providers/index.js.map +1 -1
  93. package/build/lib/providers/npm/stage.js +28 -5
  94. package/build/lib/providers/npm/stage.js.map +1 -1
  95. package/build/lib/providers/timing.js +10 -0
  96. package/build/lib/providers/timing.js.map +1 -0
  97. package/build/lib/providers/verdicts/pr.js +47 -6
  98. package/build/lib/providers/verdicts/pr.js.map +1 -1
  99. package/build/lib/providers/verdicts/runs.js +12 -2
  100. package/build/lib/providers/verdicts/runs.js.map +1 -1
  101. package/build/logins.js +1 -1
  102. package/build/logins.js.map +1 -1
  103. package/build/manager.js +131 -55
  104. package/build/manager.js.map +1 -1
  105. package/build/note.js +5 -15
  106. package/build/note.js.map +1 -1
  107. package/build/notes.js +130 -23
  108. package/build/notes.js.map +1 -1
  109. package/build/notify.js +104 -42
  110. package/build/notify.js.map +1 -1
  111. package/build/npm-reads.js +323 -0
  112. package/build/npm-reads.js.map +1 -0
  113. package/build/ownership.js +2 -2
  114. package/build/paths.js +44 -1
  115. package/build/paths.js.map +1 -1
  116. package/build/plugin.js +4 -2
  117. package/build/plugin.js.map +1 -1
  118. package/build/profile-fields.js +153 -0
  119. package/build/profile-fields.js.map +1 -0
  120. package/build/profile-layers.js +264 -0
  121. package/build/profile-layers.js.map +1 -0
  122. package/build/profile.js +107 -51
  123. package/build/profile.js.map +1 -1
  124. package/build/project-check-cli.js +19 -19
  125. package/build/project-check-cli.js.map +1 -1
  126. package/build/project-check.js +194 -108
  127. package/build/project-check.js.map +1 -1
  128. package/build/protocol.js +5 -21
  129. package/build/protocol.js.map +1 -1
  130. package/build/pushover.js +5 -5
  131. package/build/pushover.js.map +1 -1
  132. package/build/queue.js +4 -4
  133. package/build/queue.js.map +1 -1
  134. package/build/registry.js +195 -36
  135. package/build/registry.js.map +1 -1
  136. package/build/release-kinds.js +34 -0
  137. package/build/release-kinds.js.map +1 -0
  138. package/build/rule-actions.js +8 -6
  139. package/build/rule-actions.js.map +1 -1
  140. package/build/rules-service.js +104 -47
  141. package/build/rules-service.js.map +1 -1
  142. package/build/rules.js +23 -23
  143. package/build/rules.js.map +1 -1
  144. package/build/run.js +20 -7
  145. package/build/run.js.map +1 -1
  146. package/build/runs.js +218 -68
  147. package/build/runs.js.map +1 -1
  148. package/build/scheduler.js +89 -13
  149. package/build/scheduler.js.map +1 -1
  150. package/build/search.js +2 -1
  151. package/build/search.js.map +1 -1
  152. package/build/server.js +51 -14
  153. package/build/server.js.map +1 -1
  154. package/build/spend.js +1 -1
  155. package/build/spend.js.map +1 -1
  156. package/build/store.js +79 -20
  157. package/build/store.js.map +1 -1
  158. package/build/supervise.js +1 -1
  159. package/build/supervise.js.map +1 -1
  160. package/build/timeline.js +104 -0
  161. package/build/timeline.js.map +1 -0
  162. package/build/tracker-reads-cli.js +4 -5
  163. package/build/tracker-reads-cli.js.map +1 -1
  164. package/build/trackers.js +56 -10
  165. package/build/trackers.js.map +1 -1
  166. package/build/train-cli.js +6 -5
  167. package/build/train-cli.js.map +1 -1
  168. package/build/train.js +2 -2
  169. package/build/train.js.map +1 -1
  170. package/build/upgrade.js +8 -9
  171. package/build/upgrade.js.map +1 -1
  172. package/build/wait.js +10 -10
  173. package/build/wait.js.map +1 -1
  174. package/build/watchers/ado.js +42 -18
  175. package/build/watchers/ado.js.map +1 -1
  176. package/build/watchers/github.js +19 -4
  177. package/build/watchers/github.js.map +1 -1
  178. package/build/watchers/index.js +2 -2
  179. package/build/watchers/index.js.map +1 -1
  180. package/build/watchers/linear-queue.js +47 -14
  181. package/build/watchers/linear-queue.js.map +1 -1
  182. package/build/watchers/linear-writes.js +26 -12
  183. package/build/watchers/linear-writes.js.map +1 -1
  184. package/build/watchers/linear.js +2 -2
  185. package/build/watchers/linear.js.map +1 -1
  186. package/build/watchers/npm.js +6 -4
  187. package/build/watchers/npm.js.map +1 -1
  188. package/build/webhook.js +80 -0
  189. package/build/webhook.js.map +1 -0
  190. package/build/why.js +1 -1
  191. package/build/why.js.map +1 -1
  192. package/build/worktrees.js +56 -93
  193. package/build/worktrees.js.map +1 -1
  194. package/package.json +61 -61
  195. package/plugin/.claude-plugin/plugin.json +1 -1
  196. package/plugin/hooks/model.ts +46 -6
  197. package/plugin/hooks/register.tsx +41 -2
  198. package/plugin/skills/conductor-console/SKILL.md +26 -27
  199. package/plugin/skills/work-item/SKILL.md +57 -53
  200. package/plugin/skills/work-item/trackers/ado-boards.md +2 -2
  201. package/plugin/skills/work-item/trackers/github-issues.md +1 -1
  202. package/plugin/skills/work-item/trackers/linear.md +2 -2
  203. package/plugin/types/index.d.ts +1 -1
  204. package/protocol/PROTOCOL.md +3 -9
  205. package/build/checkout-sync.js +0 -249
  206. package/build/checkout-sync.js.map +0 -1
  207. package/build/credential.js +0 -66
  208. package/build/credential.js.map +0 -1
  209. package/build/startup.js +0 -92
  210. package/build/startup.js.map +0 -1
  211. package/build/tab.js +0 -32
  212. package/build/tab.js.map +0 -1
package/build/help.js CHANGED
@@ -41,7 +41,7 @@ const WINDOW = [
41
41
  '<when>',
42
42
  'for --since or --until: now, today, yesterday, a span ago (30m, 24h, 7d), a date, or a date and time',
43
43
  ];
44
- const WORKER = ['<worker>', 'its item (ATK-309), its name (probe-ATK-309) or #<id>'];
44
+ const WORKER = ['<worker>', 'its item (ENG-309), its name (probe-ENG-309) or #<id>'];
45
45
  const REPORT_OPTIONS = [
46
46
  ['--json', 'print the report as JSON'],
47
47
  ['--project <name>', 'one project only'],
@@ -51,12 +51,12 @@ const REPORT_OPTIONS = [
51
51
  export const COMMANDS = [
52
52
  {
53
53
  arguments: [
54
- ['<item>', "the item (ATK-312), or the inbox item's id as '#12' (quoted: a shell reads #12 as a comment)"],
54
+ ['<item>', "the item (ENG-312), or the inbox item's id as '#12' (quoted: a shell reads #12 as a comment)"],
55
55
  ],
56
56
  description: ['Posts "approve" on the item as you and wakes its worker.'],
57
57
  examples: [
58
- ["approve ATK-312's plan", 'approve ATK-312'],
59
- ['the same, with a word for the worker', 'approve ATK-312 --text "skip the docs"'],
58
+ ["approve ENG-312's plan", 'approve ENG-312'],
59
+ ['the same, with a word for the worker', 'approve ENG-312 --text "skip the docs"'],
60
60
  ],
61
61
  group: 'Inbox and approvals',
62
62
  name: 'approve',
@@ -67,8 +67,11 @@ export const COMMANDS = [
67
67
  },
68
68
  {
69
69
  arguments: [WORKER],
70
- description: ['Wakes a parked worker (with no event text) and opens its session in a tab.'],
71
- examples: [["open ATK-309's worker in a tab", 'attach ATK-309']],
70
+ description: [
71
+ "Wakes a parked worker (with no event text) and opens its session in a tab, whatever config.json's workers.tab says: in the terminal workers.terminal names (Windows Terminal, iTerm or Terminal on macOS, tmux elsewhere).",
72
+ 'A tmux tab is in a detached session, and the command prints how to attach to it. With no terminal to open, it prints the claude attach to run yourself.',
73
+ ],
74
+ examples: [["open ENG-309's worker in a tab", 'attach ENG-309']],
72
75
  group: 'Projects and workers',
73
76
  name: 'attach',
74
77
  seeAlso: ['launch', 'retire', 'status'],
@@ -81,10 +84,10 @@ export const COMMANDS = [
81
84
  ['<slug>', 'a few words for the branch, joined by dashes'],
82
85
  ],
83
86
  description: [
84
- "Renames the worktree's branch (worktree-ATK-454) to <type>/<key>-<slug>, such as feat/atk-454-code-host-writes, with the item from the worktree's name (or --item).",
87
+ "Renames the worktree's branch (worktree-ENG-454) to <type>/<key>-<slug>, such as feat/eng-454-code-host-writes, with the item from the worktree's name (or --item).",
85
88
  'Prints JSON. Runs here, with or without a conductor.',
86
89
  ],
87
- examples: [['in the ATK-454 worktree: feat/atk-454-code-host-writes', 'branch feat code-host-writes']],
90
+ examples: [['in the ENG-454 worktree: feat/eng-454-code-host-writes', 'branch feat code-host-writes']],
88
91
  group: 'Used by work skills',
89
92
  name: 'branch',
90
93
  options: [ITEM],
@@ -93,7 +96,7 @@ export const COMMANDS = [
93
96
  usage: ['branch <type> <slug> [--item <item>]'],
94
97
  },
95
98
  {
96
- arguments: [['<item>', 'the item (ATK-312)']],
99
+ arguments: [['<item>', 'the item (ENG-312)']],
97
100
  description: [
98
101
  "The item's context for a worker's orient step, read by the conductor from the tracker (no MCP): title, status, project, Area and labels, blockers, the items it blocks and related items, its phase notes, the approve or revise: after the newest Plan, and the description.",
99
102
  "Also the work skill's phase (orient, plan, awaiting-approval, implement, wait, land, done, abandoned, canceled), from the status, the notes and the PR; and the PR (its worker's, else the newest PR opened note's) as its code host has it, with its verdict.",
@@ -101,8 +104,8 @@ export const COMMANDS = [
101
104
  "With no conductor, it is read here from this checkout's project, as its account.",
102
105
  ],
103
106
  examples: [
104
- ['orient on ATK-312', 'brief ATK-312'],
105
- ['check for an approval after a wake', 'brief ATK-312 --fresh'],
107
+ ['orient on ENG-312', 'brief ENG-312'],
108
+ ['check for an approval after a wake', 'brief ENG-312 --fresh'],
106
109
  ],
107
110
  exitCodes: [
108
111
  [
@@ -132,9 +135,7 @@ export const COMMANDS = [
132
135
  "The clone stays out of the worktree's git status, and conduct retire checks it for unpushed work.",
133
136
  'Prints JSON. Runs here.',
134
137
  ],
135
- examples: [
136
- ['clone the registry for a skill fix', 'checkout EmergentSoftware/agentic-toolkit-registry fix lock-path'],
137
- ],
138
+ examples: [['clone the registry for a skill fix', 'checkout contoso/skills-registry fix lock-path']],
138
139
  group: 'Used by work skills',
139
140
  name: 'checkout',
140
141
  options: [ITEM],
@@ -143,13 +144,13 @@ export const COMMANDS = [
143
144
  usage: ['checkout <owner>/<repo> <type> <slug> [--item <item>]'],
144
145
  },
145
146
  {
146
- arguments: [['<item>', 'the item (ATK-312)']],
147
+ arguments: [['<item>', 'the item (ENG-312)']],
147
148
  description: [
148
149
  "Every comment on the item, oldest first, with its whole text: when, who, and whether an approver wrote it. Read as conduct brief reads the item: by the conductor (no MCP), else here from this checkout's project, as its account.",
149
150
  ],
150
151
  examples: [
151
- ['read ATK-312 whole', 'comments ATK-312'],
152
- ['what was said since the plan', 'comments ATK-312 --since 2026-10-15T09:00Z'],
152
+ ['read ENG-312 whole', 'comments ENG-312'],
153
+ ['what was said since the plan', 'comments ENG-312 --since 2026-10-15T09:00Z'],
153
154
  ],
154
155
  exitCodes: [[1, 'refused, or nothing was read, as for conduct brief: the message says why']],
155
156
  group: 'Used by work skills',
@@ -165,9 +166,9 @@ export const COMMANDS = [
165
166
  },
166
167
  {
167
168
  description: [
168
- "Opens the console, the Claude session the conductor mod serves, in a Windows Terminal tab in the conductor's own folder (~/.conductor/console): it belongs to no project, so it opens with none registered.",
169
+ "Opens the console, the Claude session the conductor mod serves, in a tab in the conductor's own folder (~/.conductor/console): it belongs to no project, so it opens with none registered.",
169
170
  'It starts with the conductor plugin (--plugin-dir ~/.conductor/plugin), which brings the mod and /conductor:conductor-console.',
170
- 'The tab needs Windows Terminal, and refuses while CONDUCTOR_HOME is set (a tab would not see it): use --here then.',
171
+ 'The tab opens in the terminal config.json\'s workers.terminal names: Windows Terminal (window "conductor"), iTerm or Terminal on macOS, or tmux elsewhere (session conductor: the command prints its tmux attach). It starts with this terminal\'s CONDUCTOR_HOME. With no terminal to open (no tmux), it refuses: the start is claimed by then, so run `conduct console --here --force`.',
171
172
  'Also how to get it back after it closed: it keeps no state of its own.',
172
173
  'One at a time: it refuses while a console is open, or started in the last minute and not yet following the events.',
173
174
  ],
@@ -249,8 +250,8 @@ export const COMMANDS = [
249
250
  ],
250
251
  examples: [
251
252
  [
252
- 'a follow-up in apps/conductor that waits on ATK-480',
253
- 'file --title "conductor: color the status" --body-file follow-up.md --area apps/conductor --blocked-by ATK-480',
253
+ 'a follow-up in apps/web that waits on ENG-480',
254
+ 'file --title "web: color the status" --body-file follow-up.md --area apps/web --blocked-by ENG-480',
254
255
  ],
255
256
  ],
256
257
  exitCodes: [[1, 'refused or failed'], LOST_LOGIN],
@@ -259,7 +260,7 @@ export const COMMANDS = [
259
260
  options: [
260
261
  [
261
262
  '--area <area>',
262
- "one of the tracker's Areas: a label of the Area group, a path below a board's root, or the name after a GitHub Issues area prefix",
263
+ "one of the tracker's Areas: a label of the Area group, a path below a board's root, or the name after a GitHub Issues area prefix; left out for a Linear team with no Area group (tracker.areaLabelGroup null)",
263
264
  ],
264
265
  ['--blocked-by <item>…', 'the items it waits on; repeated or comma-separated'],
265
266
  ['--body-file <file>', 'its description'],
@@ -275,7 +276,7 @@ export const COMMANDS = [
275
276
  seeAlso: ['brief', 'note'],
276
277
  summary: 'file a follow-up of the item, in Backlog with its Area',
277
278
  usage: [
278
- 'file --title <title> --body-file <file> --area <area> [--related <item>…] [--blocked-by <item>…] [--human] [--waits-release] [--item <item>]',
279
+ 'file --title <title> --body-file <file> [--area <area>] [--related <item>…] [--blocked-by <item>…] [--human] [--waits-release] [--item <item>]',
279
280
  ],
280
281
  },
281
282
  {
@@ -284,8 +285,8 @@ export const COMMANDS = [
284
285
  "Sets the project's slots or ordering weight until <when>; with neither, its items go first (weight 100).",
285
286
  ],
286
287
  examples: [
287
- ['work atk first until 17:00', 'focus atk --until 17:00'],
288
- ['six slots for atk until tomorrow', 'focus atk --slots 6 --until tomorrow'],
288
+ ['work web first until 17:00', 'focus web --until 17:00'],
289
+ ['six slots for web until tomorrow', 'focus web --slots 6 --until tomorrow'],
289
290
  ],
290
291
  group: 'Scheduling',
291
292
  name: 'focus',
@@ -306,7 +307,7 @@ export const COMMANDS = [
306
307
  ],
307
308
  examples: [
308
309
  ['the last 24 hours', 'history'],
309
- ['a week of atk', 'history 7d --project atk'],
310
+ ['a week of web', 'history 7d --project web'],
310
311
  ['the last 30 minutes', 'history --since 30m'],
311
312
  ],
312
313
  group: 'Logs and reports',
@@ -326,29 +327,71 @@ export const COMMANDS = [
326
327
  summary: 'what waits on you',
327
328
  usage: ['inbox [--json]'],
328
329
  },
330
+ {
331
+ arguments: [['<path>', 'a checkout of the repo; by default the one you are in']],
332
+ description: [
333
+ "Onboards the repo of a checkout. It detects what it can: the code host from origin (GitHub or Azure DevOps), CI as the code host's own, the base branch from origin/HEAD, setup from the lockfiles at the root, a verify-* skill in .claude/skills, and the item key the commits carry. It asks for the rest, each detected value the default.",
334
+ "It writes a starter profile to ~/.conductor/projects/<name>.json, or with --shared to the checkout's .claude/conductor.json, which counts once it is pushed. A profile file that is there is never overwritten, and a repo profile on origin/<base> that names the project means nothing is written. Then it runs project add and project check.",
335
+ "Run it again after each step it prints: trust the new clone with `claude` once, and with no verify skill, the conductor plugin's /conductor:create-verification-skill in the checkout (in `claude --plugin-dir <the plugin>`), committed and pushed. Each run goes on from what is done, so a run on a project that is set up only fetches and checks it.",
336
+ 'Without --yes it asks in the terminal, and refuses with no terminal (Git Bash under mintty is none to node).',
337
+ ],
338
+ examples: [
339
+ ['onboard the repo of the checkout you are in, answering its questions', 'init'],
340
+ ['the same with no questions, for a GitHub repo with GitHub Issues', 'init --yes --key PAR'],
341
+ ['with a Linear team as the tracker', 'init --tracker linear --team ENG'],
342
+ ['a profile the team shares, committed to the repo', 'init --shared'],
343
+ ],
344
+ group: 'Projects and workers',
345
+ name: 'init',
346
+ options: [
347
+ ['--name <name>', "the project's name; by default the repo's, or the one it was added under"],
348
+ ['--base <branch>', 'the base branch; by default origin/HEAD'],
349
+ ['--tracker <kind>', "github-issues, ado-boards or linear; by default the code host's own"],
350
+ ['--key <KEY>', 'the item key on GitHub Issues or ADO Boards (PAR-12 is issue #12)'],
351
+ ['--team <key>', 'the Linear team key, with --tracker linear'],
352
+ ['--query <query>', 'the saved Boards query that is the queue, with ADO Boards'],
353
+ ['--shared', "write the repo's .claude/conductor.json instead of the machine profile"],
354
+ ['--yes', 'ask nothing: take what was detected, and refuse what is missing with its flag'],
355
+ ],
356
+ seeAlso: ['project', 'profile', 'launch'],
357
+ summary: 'onboard a repo: a starter profile, then add and check it',
358
+ usage: [
359
+ 'init [<path>] [--name <name>] [--base <branch>] [--tracker <kind>] [--key <KEY>] [--team <key>] [--query <query>] [--shared] [--yes]',
360
+ ],
361
+ },
329
362
  {
330
363
  description: [
331
- "Registers a Windows Task Scheduler task that runs conduct supervise at logon, which restarts the daemon if it dies. Run it from the main checkout: a worktree's build goes away.",
364
+ "Registers what runs conduct supervise at logon, which restarts the daemon if it dies, with this build. Run it from the main checkout: a worktree's build goes away.",
365
+ 'Windows: a Task Scheduler task, "Conductor", which it registers without starting.',
366
+ 'macOS: a launchd agent, ~/Library/LaunchAgents/software.detergent.conductor.plist, which it loads into your login session, and that starts it. Its output goes to ~/.conductor/logs/startup.log. Run it in a terminal on the Mac, not over ssh alone.',
367
+ 'Linux: a systemd user unit, ~/.config/systemd/user/conductor.service, which it enables and starts. Its output goes to the journal (journalctl --user -u conductor). It starts at your login; on a machine nobody logs in to, loginctl enable-linger starts it at boot, and the command says so.',
368
+ "The agent and the unit keep this terminal's PATH, since a login gives them a short one with no claude or git: run it again after that changes.",
369
+ 'On macOS and Linux, running it again restarts a daemon the agent or unit started, so the new one counts. A daemon started another way keeps running, and the one the startup starts beside it ends on its lock. --remove leaves a running daemon alone.',
332
370
  ],
333
371
  examples: [['start the daemon at every logon', 'install-startup']],
334
372
  group: 'Setup',
335
373
  name: 'install-startup',
336
- options: [['--remove', 'remove that logon task']],
374
+ options: [['--remove', 'remove that task, agent or unit']],
337
375
  seeAlso: ['supervise', 'start'],
338
- summary: 'start the daemon at logon (Windows Task Scheduler)',
376
+ summary: 'start the daemon at every logon',
339
377
  usage: ['install-startup', 'install-startup --remove'],
340
378
  },
341
379
  {
342
380
  arguments: [['<pr>', 'the PR number']],
343
381
  description: [
344
- "Sets the worker's PR up to land, then gives its first verdict. Safe to repeat. A brake already on the PR (a comment, a failed build, conflicts) is reported and nothing is armed. Otherwise it arms the host's own landing: on Azure DevOps a +10 vote (auto mode) and auto-complete with noFastForward; on GitHub, auto-merge with a merge commit (auto mode, where the repo allows it, refused with the reason where it doesn't). Then it posts the Landing note.",
382
+ "Sets the worker's PR up to land, then gives its first verdict. Safe to repeat, except with --requeue. A brake already on the PR (a comment, a failed build, conflicts) is reported and nothing is armed. Otherwise it arms the host's own landing: on Azure DevOps a +10 vote (auto mode) and auto-complete with noFastForward; on GitHub, auto-merge with a merge commit (auto mode, where the repo allows it, refused with the reason where it doesn't). Then it posts the Landing note.",
345
383
  'A Landing note with auto-complete or auto-merge gone means someone cancelled it: auto-merge-cancelled, until --rearm. A PR ADO started completing in the last few minutes, which clears auto-complete, is waiting instead.',
346
384
  'With a conductor, the daemon records the landing and keeps it armed while the worker waits (conduct wait pr <pr>): it queues an expired build again and restores a cleared vote.',
385
+ "--requeue <run> queues one of a build-failed PR's failed builds again, for a flake no change caused, then arms as above: on Azure Repos through its policy evaluation, on GitHub by re-running the failed jobs of the check's Actions run (a PR the item opened from a checkout; one a hook's publish opened has none, so land refuses it). It posts a closed Requeue note with the run, the build and the PR's head commit first, and refuses a second requeue of that build on that head, even for the new run: a second failure is fixed and pushed. Each build that failed on the head can be queued again once. It refuses while a comment waits for an answer, and a GitHub run with a job still running. Until the PR shows the new run, the verdict waits on the build instead of reporting the old failure, for 15 minutes at most. A GitHub re-run keeps the run's id, so a failed check of it that finished after the note is the new attempt's failure, reported at once.",
347
386
  'Prints JSON with the verdict and "via".',
348
387
  ],
349
388
  examples: [
350
389
  ['land PR 1850 by itself', 'land 1850 --mode auto --reason "S fix, no review paths"'],
351
390
  ['arm it again after a cancel', 'land 1850 --rearm --reason "the operator said go on"'],
391
+ [
392
+ 'queue a flaky build again, once',
393
+ 'land 1850 --requeue 8040 --reason "ENG-637: the known flake, no change caused it"',
394
+ ],
352
395
  ],
353
396
  exitCodes: [[1, 'refused'], LOST_LOGIN],
354
397
  group: 'Used by work skills',
@@ -359,23 +402,30 @@ export const COMMANDS = [
359
402
  '--mode auto|review',
360
403
  "held to the profile's landing rules for the PR's files and the plan's tier: auto where they allow it, else refused; without it the rules pick",
361
404
  ],
362
- ['--reason <why>', 'why this mode, for the Landing note (required)'],
405
+ [
406
+ '--reason <why>',
407
+ 'why this mode, for the Landing note (required); with --requeue, why the build is queued again, for the Requeue note',
408
+ ],
363
409
  ['--rearm', 'arm it again after someone cancelled it'],
364
410
  PR_REPO,
411
+ ['--requeue <run>', 'queue that failed build again first, once per build and head commit'],
365
412
  ['--tier S|M|L', "the plan's tier without a conductor; the daemon takes it from the item's Plan note"],
366
413
  ],
367
414
  seeAlso: ['wait', 'pr', 'runs'],
368
415
  summary: "arm the worker's PR to land, and its first verdict",
369
- usage: ['land <pr> --reason <why> [--mode auto|review] [--rearm] [--tier S|M|L] [--repo <repo>] [--item <item>]'],
416
+ usage: [
417
+ 'land <pr> --reason <why> [--mode auto|review] [--rearm] [--requeue <run>] [--tier S|M|L] [--repo <repo>] [--item <item>]',
418
+ ],
370
419
  },
371
420
  {
372
- arguments: [['<item>', 'the item to work (ATK-312)']],
421
+ arguments: [['<item>', 'the item to work (ENG-312)']],
373
422
  description: [
374
- "Starts a worker on the item: its worktree, a background session running the project's work skill, and a tab.",
423
+ "Starts a worker on the item: its worktree, and a background session running the project's work skill.",
424
+ "Workers run headless. With config.json's workers.tab, each launch also opens a tab attached to the session (as conduct attach does); a tab that fails to open never fails the launch.",
375
425
  ],
376
426
  examples: [
377
- ['start a worker on ATK-312', 'launch ATK-312'],
378
- ['a probe with its own prompt', 'launch ATK-312 --probe --prompt "time the test suite"'],
427
+ ['start a worker on ENG-312', 'launch ENG-312'],
428
+ ['a probe with its own prompt', 'launch ENG-312 --probe --prompt "time the test suite"'],
379
429
  ],
380
430
  group: 'Projects and workers',
381
431
  name: 'launch',
@@ -386,7 +436,7 @@ export const COMMANDS = [
386
436
  ['--prompt <text>', "the session's first prompt instead of the work skill (or the probe prompt)"],
387
437
  ],
388
438
  seeAlso: ['attach', 'retire', 'status'],
389
- summary: 'start a worker: its worktree, a background session, a tab',
439
+ summary: 'start a worker: its worktree and a background session',
390
440
  usage: ['launch <item> [--project <name>] [--probe] [--prompt <text>] [--conductor <name>]'],
391
441
  },
392
442
  {
@@ -438,7 +488,7 @@ export const COMMANDS = [
438
488
  },
439
489
  {
440
490
  arguments: [
441
- ['<item>', 'the item (ATK-312)'],
491
+ ['<item>', 'the item (ENG-312)'],
442
492
  ['<file>', 'the note, its heading first'],
443
493
  ],
444
494
  description: [
@@ -447,7 +497,7 @@ export const COMMANDS = [
447
497
  "With no conductor, it is posted from this checkout as its project's account, and the item moves the same way.",
448
498
  `The note must keep worker protocol ${PROTOCOL} (protocol/PROTOCOL.md in the package): a known phase (${PHASES.join(', ')}), a Handoff with a kind and one line (${HANDOFF_KINDS.join(', ')}), no kind on a phase that carries none, and a Plan with its **Size tier** and **Landing:** lines. One that breaks it is refused, with the rule, before anything is posted.`,
449
499
  ],
450
- examples: [['post the Plan note', 'note ATK-312 plan.md']],
500
+ examples: [['post the Plan note', 'note ENG-312 plan.md']],
451
501
  exitCodes: [
452
502
  [
453
503
  1,
@@ -466,14 +516,14 @@ export const COMMANDS = [
466
516
  usage: ['note <item> <file> [--worker <worker>]'],
467
517
  },
468
518
  {
469
- arguments: [['<item>', 'the item (ATK-312)']],
519
+ arguments: [['<item>', 'the item (ENG-312)']],
470
520
  description: [
471
521
  "The item's phase notes with their whole text, oldest first: what conduct brief lists as one line each. --phase and --kind keep the ones that match, and --last the newest of those, such as the Handoff an escalation is about.",
472
522
  "Read as conduct brief reads the item: by the conductor (no MCP), else here from this checkout's project, as its account.",
473
523
  ],
474
524
  examples: [
475
- ['every note on ATK-312', 'notes ATK-312'],
476
- ['the newest conductor Handoff', 'notes ATK-312 --phase Handoff --kind conductor --last'],
525
+ ['every note on ENG-312', 'notes ENG-312'],
526
+ ['the newest conductor Handoff', 'notes ENG-312 --phase Handoff --kind conductor --last'],
477
527
  ],
478
528
  exitCodes: [[1, 'refused, or nothing was read, as for conduct brief: the message says why']],
479
529
  group: 'Used by work skills',
@@ -509,7 +559,7 @@ export const COMMANDS = [
509
559
  group: 'Inbox and approvals',
510
560
  name: 'notify',
511
561
  options: [
512
- ['--channel remote-control|pushover', 'with test: push on that channel'],
562
+ ['--channel remote-control|pushover|webhook', 'with test: push on that channel'],
513
563
  ['--json', 'print the state as JSON'],
514
564
  ['--kind <kind>', 'with test: the kind of item (npm-otp by default)'],
515
565
  ['--raise', 'with test: put a real item in the inbox instead; it takes no --channel'],
@@ -520,7 +570,7 @@ export const COMMANDS = [
520
570
  usage: [
521
571
  'notify [--json]',
522
572
  'notify profile [<name>] [--until <when>]',
523
- 'notify test [--kind <kind>] [--channel remote-control|pushover] [--raise]',
573
+ 'notify test [--kind <kind>] [--channel remote-control|pushover|webhook] [--raise]',
524
574
  ],
525
575
  },
526
576
  {
@@ -528,7 +578,7 @@ export const COMMANDS = [
528
578
  description: ['No new launches in the project, or in every project without one, until <when> or conduct unpause.'],
529
579
  examples: [
530
580
  ['pause every project until tomorrow', 'pause --until tomorrow'],
531
- ['pause atk until you unpause it', 'pause atk'],
581
+ ['pause web until you unpause it', 'pause web'],
532
582
  ],
533
583
  group: 'Scheduling',
534
584
  name: 'pause',
@@ -557,6 +607,10 @@ export const COMMANDS = [
557
607
  },
558
608
  {
559
609
  commands: [
610
+ [
611
+ 'abandon <pr>',
612
+ "close the worker's PR unmerged (Azure DevOps abandons it), then post a closed `<skill> · Abandoned` note on it with --reason. Only the item's PR: its title and head branch carry the item key, and it is from the branch the checkout is on now (--force: from another branch of the item). A merged PR is refused; one closed already only gets the note if it lacks one, so it is safe to repeat",
613
+ ],
560
614
  [
561
615
  'create',
562
616
  "check the title carries the item key, the branch carries it too, the description fits the host, no PR is open from the branch, nothing is uncommitted, the branch is ahead of its base, and commitlint passes, all before anything is pushed. Then push and open the PR into the base branch (--repo: into the other repo's default branch, from its checkout)",
@@ -567,17 +621,18 @@ export const COMMANDS = [
567
621
  ],
568
622
  ],
569
623
  description: [
570
- "Opens the worker's PR, checked and pushed, or reads its threads.",
624
+ "Opens the worker's PR, checked and pushed, reads its threads, or abandons it.",
571
625
  "The description ends with the tracker's reference when it has one (AB#<id> for an ADO Boards item on a GitHub PR, so the Boards GitHub app links it), counted in its length.",
572
- 'With a conductor, the daemon opens it for the worker that owns this checkout, checking the ownership again, and records the PR on the worker. Without one (or an older one) it opens it here.',
626
+ 'With a conductor, the daemon opens or abandons it for the worker that owns this checkout, checking the ownership again, and records the PR on the worker. Without one (or an older one) it does it here.',
573
627
  'Prints JSON with "via": "daemon" or "local".',
574
628
  ],
575
629
  examples: [
576
630
  [
577
631
  'check everything, push nothing',
578
- 'pr create --title "feat(conductor): help sections (ATK-478)" --body-file pr.md --dry-run',
632
+ 'pr create --title "feat(web): help sections (ENG-478)" --body-file pr.md --dry-run',
579
633
  ],
580
634
  ["PR 1850's threads", 'pr threads 1850'],
635
+ ['drop PR 1850, which another PR made redundant', 'pr abandon 1850 --reason "ENG-412\'s PR merged the same fix"'],
581
636
  ],
582
637
  exitCodes: [[1, 'refused or failed'], LOST_LOGIN],
583
638
  group: 'Used by work skills',
@@ -585,53 +640,82 @@ export const COMMANDS = [
585
640
  options: [
586
641
  ['--body-file <file>', 'with create: its description'],
587
642
  ['--dry-run', 'with create: stop before the push'],
643
+ ['--force', "with abandon: the item's PR from a branch the checkout isn't on"],
588
644
  ITEM,
645
+ ['--reason <why>', 'with abandon: why, in its note'],
589
646
  PR_REPO,
590
647
  ['--title <title>', 'with create: its title, with the item key'],
591
648
  ],
592
649
  seeAlso: ['land', 'reply', 'state'],
593
- summary: "open the worker's PR, checked and pushed; read its threads",
650
+ summary: "open the worker's PR, read its threads, or abandon it",
594
651
  usage: [
652
+ 'pr abandon <pr> --reason <why> [--repo <repo>] [--item <item>] [--force]',
595
653
  'pr create --title <title> --body-file <file> [--repo <repo>] [--item <item>] [--dry-run]',
596
654
  'pr threads <pr> [--repo <repo>]',
597
655
  ],
598
656
  },
657
+ {
658
+ arguments: [['<project>', 'a project added with conduct project add']],
659
+ description: [
660
+ "A project's profile as the conductor reads it: its machine profile (~/.conductor/projects/<project>.json) over the repo's .claude/conductor.json at origin/<base> in its clone, when there is one.",
661
+ "Objects merge key by key and the machine's wins; arrays are replaced whole; rules stack, the machine's first, so a machine rule shadows a repo rule with its id. Each field says whether it came from the machine, the repo or a default.",
662
+ 'Read here from the files and the clone as fetched last, with or without the daemon.',
663
+ ],
664
+ examples: [
665
+ ["web's profile and where each field came from", 'profile web'],
666
+ ['the same as JSON', 'profile web --json'],
667
+ ],
668
+ exitCodes: [[1, 'no clone of the project, or its profile is invalid (the message names the files)']],
669
+ group: 'Projects and workers',
670
+ name: 'profile',
671
+ options: [['--json', 'print the profile and its sources as JSON']],
672
+ seeAlso: ['project', 'rules'],
673
+ summary: "a project's profile, each field with its source",
674
+ usage: ['profile <project> [--json]'],
675
+ },
599
676
  {
600
677
  commands: [
601
- ['add <path>', 'register the project whose checkout holds .claude/conductor.json; works without the daemon'],
678
+ [
679
+ 'add <url | path>',
680
+ "clone the project's remote into ~/.conductor/projects/<name>/repo and register it. A path names a checkout whose origin is cloned: the folder itself is never cloned or touched again. The name is the one the repo's .claude/conductor.json gives, or --name. Adding a project again fetches its clone and updates the registration in place, and moves a project registered by its checkout to a clone. Works without the daemon",
681
+ ],
602
682
  ['list [--json]', 'the registered projects'],
603
683
  [
604
684
  'remove <name>',
605
- "drop a registration: a renamed project's old name, or a project no longer conducted. Resolves its open inbox items; refused while it has workers in flight. Works without the daemon",
685
+ 'drop a registration: a project no longer conducted. Resolves its open inbox items; refused while it has workers in flight. Its clone and machine profile stay. Works without the daemon',
606
686
  ],
607
687
  [
608
688
  'check <name>',
609
- 'whether the project can be conducted, before its first launch finds out: its profile (and what differs from the stored copy), tracker, code host and base branch, release pipelines, a throwaway worktree made and removed through its hooks, its installed skills, a free port slot and its health URLs. One ok, warn, fail or skip line each, with the fix',
689
+ 'whether the project can be conducted, before its first launch finds out: its profile (what differs from the stored copy, and fields newer than its conductor minimum), tracker, code host and base branch, release pipelines, a throwaway worktree made from the clone and removed, with its skills and Claude Code trust, the plugin skills, free ports and its health URLs. One ok, warn, fail or skip line each, with the fix',
610
690
  ],
611
691
  ],
612
692
  description: [
613
693
  'Registers a project, lists the registered ones, removes one, or checks one.',
614
- 'After that the daemon takes the profile from disk when it starts and each time the file is saved.',
615
- 'A project keeps the name it was registered under. To rename one, remove the old name, then add it again: with both registered, both would read the same queue.',
694
+ 'A project is a clone the conductor owns: its worktrees are made there (~/.conductor/projects/<name>/worktrees), never in a checkout of yours. The daemon fetches the clone every clones.fetchMinutes and takes the profile again when its .claude/conductor.json on the base branch changes, or when the machine profile (~/.conductor/projects/<name>.json) is saved. `conduct profile <name>` shows how the two merge.',
695
+ 'Claude Code trusts a worktree by its repository: run `claude` in a new clone once and accept the trust prompt before its first launch.',
616
696
  "check goes through the daemon, as its accounts, or runs here as the machine's when it isn't running. Only the worktree check writes, and it removes what it made.",
617
697
  ],
618
698
  examples: [
619
- ['register the checkout you are in', 'project add .'],
699
+ ['conduct the repo of the checkout you are in', 'project add .'],
700
+ [
701
+ 'conduct a repo by its URL, under a name of your own',
702
+ 'project add https://github.com/owner/repo.git --name mine',
703
+ ],
620
704
  ['the registered projects', 'project list'],
621
- ['drop the old name before adding the renamed project', 'project remove atk-old'],
622
- ['check atk before conducting it', 'project check atk'],
623
- ['the same without the worktree (its hook runs pnpm install)', 'project check atk --no-worktree'],
705
+ ['check web before conducting it', 'project check web'],
706
+ ['the same without the worktree (its setup runs pnpm install)', 'project check web --no-worktree'],
624
707
  ],
625
708
  group: 'Projects and workers',
626
709
  name: 'project',
627
710
  options: [
628
711
  ['--json', 'with list or check: print them as JSON'],
712
+ ['--name <name>', "with add: the project's name, when the repo's profile gives none or another"],
629
713
  ['--no-worktree', 'with check: skip the throwaway worktree'],
630
714
  ],
631
- seeAlso: ['launch', 'ports', 'status'],
715
+ seeAlso: ['init', 'profile', 'launch', 'ports', 'status'],
632
716
  summary: 'register a project, or list, remove or check them',
633
717
  usage: [
634
- 'project add <path>',
718
+ 'project add <url | path> [--name <name>]',
635
719
  'project list [--json]',
636
720
  'project remove <name>',
637
721
  'project check <name> [--no-worktree] [--json]',
@@ -674,9 +758,9 @@ export const COMMANDS = [
674
758
  {
675
759
  arguments: [WORKER],
676
760
  description: [
677
- "Stops the worker's session and removes its worktree. It refuses while the worker's turn runs or its worktree has unfinished work (uncommitted or unpushed).",
761
+ "Stops the worker's session and removes its worktree. It refuses while the worker's turn runs, while it is attached (open in a tab), or while its worktree has unfinished work (uncommitted or unpushed).",
678
762
  ],
679
- examples: [['retire ATK-309 once it is done', 'retire ATK-309']],
763
+ examples: [['retire ENG-309 once it is done', 'retire ENG-309']],
680
764
  group: 'Projects and workers',
681
765
  name: 'retire',
682
766
  options: [['--force', 'retire it anyway and throw that work away']],
@@ -689,7 +773,7 @@ export const COMMANDS = [
689
773
  description: ['The same report as conduct history, as Markdown.', 'Give a <range> or --since/--until, not both.'],
690
774
  examples: [
691
775
  ["yesterday's retro", 'retro yesterday'],
692
- ['a week of atk, to a file', 'retro 7d --project atk > retro.md'],
776
+ ['a week of web, to a file', 'retro 7d --project web > retro.md'],
693
777
  ],
694
778
  group: 'Logs and reports',
695
779
  name: 'retro',
@@ -700,13 +784,14 @@ export const COMMANDS = [
700
784
  },
701
785
  {
702
786
  arguments: [
703
- ['<item>', "the item (ATK-312), or the inbox item's id as '#12' (quoted: a shell reads #12 as a comment)"],
787
+ ['<item>', "the item (ENG-312), or the inbox item's id as '#12' (quoted: a shell reads #12 as a comment)"],
704
788
  ['<text>', 'what to change in the plan'],
705
789
  ],
706
790
  description: [
707
791
  'Posts "revise: <text>" on the item as you and wakes its worker. Every word after <item> is the text, quoted or not.',
792
+ "With no plan of the item in the inbox, it revises the item's approved plan: the conductor posts the revise, wakes its parked worker to re-plan (not once its PR has merged), and holds back the worker's next note until it does.",
708
793
  ],
709
- examples: [['ask for a smaller plan', 'revise ATK-312 put the web change in a PR of its own']],
794
+ examples: [['ask for a smaller plan', 'revise ENG-312 put the web change in a PR of its own']],
710
795
  group: 'Inbox and approvals',
711
796
  name: 'revise',
712
797
  seeAlso: ['approve', 'inbox'],
@@ -726,7 +811,7 @@ export const COMMANDS = [
726
811
  ],
727
812
  description: [
728
813
  'The rules in force, and a dry run of them on a sample. A sample for rules test:',
729
- { pre: ['{ "event": "pr.comment", "project": "atk",', ' "fields": { "wait.kind": "merge" } }'] },
814
+ { pre: ['{ "event": "pr.comment", "project": "web",', ' "fields": { "wait.kind": "merge" } }'] },
730
815
  ],
731
816
  examples: [
732
817
  ['the rules in force', 'rules'],
@@ -744,14 +829,24 @@ export const COMMANDS = [
744
829
  description: [
745
830
  "One look at a merge's runs: on Azure Pipelines for the project's Azure DevOps repo (the pipelines whose YAML trigger the merge fires, read in this worktree), on GitHub Actions for a GitHub repo (the runs the merge's push started). The outcome is succeeded, failed, cancelled, waiting-for-approval, missing, none (nothing ran: at once on Azure Pipelines, after 5 minutes on GitHub) or waiting (look again, or conduct wait merge).",
746
831
  "Each failed run comes with its failed tasks and the end of its log (logs). For the project's repo, each of the profile's releases whose run succeeded gives what it staged (stages): package, version, stageId, the npm stage approve line, and whether npm has it (published).",
747
- "On Azure Pipelines a cancelled run (a newer push's batch, or a person) gives way to a later run on the base whose commit contains the merge: that run is the merge's, with supersedes naming the cancelled one. So cancelled means no newer run carries the merge, and the note gives the --requeue line.",
748
- "--requeue <pipeline> queues that pipeline again on the base at its tip, for the item's own merge (its branch's PR merged as <sha>) when its run was cancelled and no newer run carries it; it refuses a run that is waiting, running, succeeded or failed, a pipeline the merge didn't trigger, a merge under 15 minutes old (Azure DevOps can still list a newer run), and GitHub. By the daemon for the worker that owns this checkout, else here. conduct wait merge <sha> then follows the new run.",
832
+ "On Azure Pipelines a cancelled run (a newer push's batch, or a person) gives way to a later run on the base whose commit contains the merge: that run is the merge's, with supersedes naming the cancelled one (or the failed one, for a run queued again for a failure: retryOf). So cancelled means no newer run carries the merge, and the note gives the --requeue line.",
833
+ "A batched pipeline (batch: true) holds the merge's push while its run on the base still goes, so a merge with no run yet waits as long as that run does and 2 minutes after (behind names it), not 15 minutes. Missing means no run, and none ahead of its batch, 15 minutes after the merge; the note gives the --requeue line.",
834
+ "--requeue <pipeline> queues that pipeline on the base at its tip, for the item's own merge (its branch's PR merged as <sha>) when its run was cancelled and no newer run carries it, when it failed, or when it is missing; it refuses a run that is waiting, running or succeeded, a batch still behind a run, a pipeline the merge didn't trigger, a cancelled or missing run under 15 minutes after the merge (Azure DevOps can still list a newer run). By the daemon for the worker that owns this checkout, else here. conduct wait merge <sha> then follows the new run.",
835
+ "On GitHub Actions (the project's repo, or one the item checked out under .scratch/repos, with --repo) --requeue re-runs the merge's run itself, at its own commit: the failed jobs of a failed run, all of a cancelled one. The run keeps its id, and conduct wait merge <sha> --repo <repo> follows its new attempt. It re-runs a run once (GitHub's run_attempt above 1 is refused), only while the run is its workflow's newest run on the base the PR merged into, of any event (re-running an older one would build an older commit after a newer one), and never a missing run, which has nothing to re-run.",
836
+ "A failed run is queued again once, for a flake its log shows that no change caused (a timeout in a test nothing touched, an agent or network error; not another merge's real failure); the note gives the line. A run queued by hand after the failed one stands in for it and names it (retryOf), so a second --requeue, of a run queued again that failed too, is refused. A newer push's run never stands in for a failed one.",
837
+ "--grep <pattern> searches every task log of the --for pipelines' runs, whatever their result, for a JavaScript regular expression (case-sensitive). grep.runs gives, for each run, the matching lines by stage and task (matches, at most 200 a task) and every task it searched with its line count (searched), so no match shows the run never printed it. A pipeline with no run, a run not finished or waiting on an approval, and a log that can't be read each say so in a note.",
749
838
  'Prints JSON. A read, so it runs here, except with --requeue.',
750
839
  ],
751
840
  examples: [
752
841
  ['the runs of the merge a1b2c3d', 'runs a1b2c3d'],
753
842
  ['its API deploy alone', 'runs a1b2c3d --for deploy-api'],
843
+ ['what its API deploy printed about deploying', 'runs a1b2c3d --for deploy-api --grep Deploying'],
754
844
  ['queue its cancelled conductor release again', 'runs a1b2c3d --requeue release-conductor'],
845
+ ['queue its CLI release again once, after a flaky test failed it', 'runs a1b2c3d --requeue release-cli'],
846
+ [
847
+ "re-run the registry merge's failed Build Registry once",
848
+ 'runs 9ad075d --requeue build-registry --repo github:contoso/skills-registry',
849
+ ],
755
850
  ],
756
851
  exitCodes: [[1, 'refused or failed'], LOST_LOGIN],
757
852
  group: 'Used by work skills',
@@ -765,12 +860,20 @@ export const COMMANDS = [
765
860
  '--repo <repo>',
766
861
  "github:<owner>/<repo> for another repo, such as the registry; the profile's code host by default",
767
862
  ],
768
- ['--requeue <pipeline>', "queue the merge's cancelled run of this pipeline again (Azure Pipelines)"],
863
+ ['--grep <pattern>', "with --for: the lines of those runs' logs that match, by task, whatever the run's result"],
864
+ [
865
+ '--requeue <pipeline>',
866
+ "queue the merge's cancelled, failed (once) or missing run of this pipeline; on GitHub Actions, re-run its failed or cancelled run once",
867
+ ],
769
868
  ['--item <KEY-n>', "with --requeue: the item whose merge it is, when the worktree's name has no key"],
770
869
  ],
771
- seeAlso: ['wait', 'land'],
870
+ seeAlso: ['wait', 'land', 'timeline'],
772
871
  summary: "a merge's runs, their verdict, failed logs and npm stages",
773
- usage: ['runs <sha> [--for <pipeline>[,<pipeline>…]] [--repo <repo>]', 'runs <sha> --requeue <pipeline>'],
872
+ usage: [
873
+ 'runs <sha> [--for <pipeline>[,<pipeline>…]] [--repo <repo>]',
874
+ 'runs <sha> --for <pipeline>[,<pipeline>…] --grep <pattern> [--repo <repo>]',
875
+ 'runs <sha> --requeue <pipeline> [--repo <repo>]',
876
+ ],
774
877
  },
775
878
  {
776
879
  arguments: [['<terms…>', 'the words to look for; an item matches only with every one']],
@@ -798,7 +901,7 @@ export const COMMANDS = [
798
901
  },
799
902
  {
800
903
  description: [
801
- 'Starts the logon task when it runs this build, else a detached conduct supervise --fail-fast, and waits until the daemon answers. Does nothing when one runs already.',
904
+ "Starts the logon startup (install-startup's task, agent or unit) when it runs this build, else a detached conduct supervise --fail-fast, and waits until the daemon answers. Does nothing when one runs already.",
802
905
  ],
803
906
  examples: [['start the daemon', 'start']],
804
907
  group: 'Daemon',
@@ -814,7 +917,7 @@ export const COMMANDS = [
814
917
  ],
815
918
  examples: [
816
919
  ['where this worktree stands', 'state'],
817
- ['the registry checkout alone', 'state --repo EmergentSoftware/agentic-toolkit-registry'],
920
+ ['the registry checkout alone', 'state --repo contoso/skills-registry'],
818
921
  ],
819
922
  exitCodes: [LOST_LOGIN],
820
923
  group: 'Used by work skills',
@@ -849,9 +952,9 @@ export const COMMANDS = [
849
952
  },
850
953
  {
851
954
  description: [
852
- 'Runs conduct serve and starts it again when it dies (a crash, a kill, a start that fails), after 1 s, 5 s, 15 s, 30 s, then every minute, and every 5 minutes once it has pushed. A daemon down 2 minutes sends one Pushover push, held through quiet hours. A stop (conduct stop, upgrade, Ctrl+C), or another daemon holding the lock, ends it. The logon task runs it.',
955
+ 'Runs conduct serve and starts it again when it dies (a crash, a kill, a start that fails), after 1 s, 5 s, 15 s, 30 s, then every minute, and every 5 minutes once it has pushed. A daemon down 2 minutes sends one Pushover push, held through quiet hours. A stop (conduct stop, upgrade, Ctrl+C), or another daemon holding the lock, ends it. The logon startup (install-startup) runs it.',
853
956
  ],
854
- examples: [['what the logon task runs', 'supervise']],
957
+ examples: [['what the logon startup runs', 'supervise']],
855
958
  group: 'Daemon',
856
959
  name: 'supervise',
857
960
  options: [['--fail-fast', 'end when the first serve exits before it comes up, as conduct start runs it']],
@@ -859,6 +962,49 @@ export const COMMANDS = [
859
962
  summary: 'run the daemon and restart it when it dies',
860
963
  usage: ['supervise [--fail-fast]'],
861
964
  },
965
+ {
966
+ arguments: [['<run>', 'a run id (an Azure Pipelines build, a GitHub Actions run)']],
967
+ description: [
968
+ "A run's tasks and when each ran: on Azure Pipelines each timeline task under its stage and job, on GitHub Actions each step under its job, in the order they started, with started, finished and seconds (null until a task has both times), and the host's own state and result. The run itself has the same times.",
969
+ "--for <pipeline> reads the last finished runs of one pipeline on a branch instead (the profile's base by default, 3 runs, at most 20), newest first, so a step can be measured across runs without their merge commits.",
970
+ "--task <regex> keeps the tasks whose name matches (a JavaScript regular expression, not case-sensitive), so Cache Next build also matches its Post-job: Cache Next build save. --grep <regex> (case-sensitive, with --task) gives those tasks' log lines that match, as runs --grep does: the matches by task (at most 200 a task) and every task it searched with its line count. A run not finished, a --task that matches nothing (it lists the run's tasks) and a log that can't be read each say so in a note.",
971
+ 'Prints JSON. A read, so it runs here.',
972
+ ],
973
+ examples: [
974
+ ['every task of build 8123 and how long it took', 'timeline 8123'],
975
+ [
976
+ 'the Next cache and export steps of the last 3 web deploys on develop, with what they printed',
977
+ 'timeline --for deploy-web --task "Cache Next build|Static export build" --grep "Cache restored|cache miss|Compiled successfully"',
978
+ ],
979
+ [
980
+ "the registry's last 5 Build Registry runs on main",
981
+ 'timeline --for build-registry --branch main --count 5 --repo github:contoso/skills-registry',
982
+ ],
983
+ ],
984
+ exitCodes: [[1, 'refused or failed'], LOST_LOGIN],
985
+ group: 'Used by work skills',
986
+ name: 'timeline',
987
+ options: [
988
+ [
989
+ '--for <pipeline>',
990
+ 'one pipeline (YAML file name such as deploy-web, its path, or its name): its last finished runs',
991
+ ],
992
+ ['--branch <branch>', "with --for: the runs on this branch; the profile's base by default"],
993
+ ['--count <n>', 'with --for: how many runs, 1 to 20; 3 by default'],
994
+ ['--task <regex>', 'only the tasks whose name matches, not case-sensitive'],
995
+ ['--grep <regex>', "with --task: those tasks' log lines that match"],
996
+ [
997
+ '--repo <repo>',
998
+ "github:<owner>/<repo> for another repo, such as the registry; the profile's code host by default",
999
+ ],
1000
+ ],
1001
+ seeAlso: ['runs'],
1002
+ summary: "a run's tasks and their times; a pipeline's last runs",
1003
+ usage: [
1004
+ 'timeline <run> [--task <regex>] [--grep <regex>] [--repo <repo>]',
1005
+ 'timeline --for <pipeline> [--branch <branch>] [--count <n>] [--task <regex>] [--grep <regex>] [--repo <repo>]',
1006
+ ],
1007
+ },
862
1008
  {
863
1009
  arguments: [['<project>', "a registered project; without it, the checkout you're in"]],
864
1010
  description: [
@@ -867,7 +1013,7 @@ export const COMMANDS = [
867
1013
  ],
868
1014
  examples: [
869
1015
  ['what a train would take and leave out', 'train --dry-run'],
870
- ["merge atk's waiting publishes", 'train atk'],
1016
+ ["merge web's waiting publishes", 'train web'],
871
1017
  ],
872
1018
  group: 'Projects and workers',
873
1019
  name: 'train',
@@ -883,7 +1029,7 @@ export const COMMANDS = [
883
1029
  ],
884
1030
  examples: [
885
1031
  ['launch again everywhere', 'unpause'],
886
- ['launch again in atk', 'unpause atk'],
1032
+ ['launch again in web', 'unpause web'],
887
1033
  ],
888
1034
  group: 'Scheduling',
889
1035
  name: 'unpause',
@@ -940,7 +1086,7 @@ export const COMMANDS = [
940
1086
  "the project's login to the provider works again (projects.<name> in config.json says which account)",
941
1087
  ],
942
1088
  ['time <when>', 'such as 17:00 (the next one) or 2026-10-10T09:00 (local)'],
943
- ['<full form>', 'such as pr:ado:Emergent.AgenticToolkit#1850:merged'],
1089
+ ['<full form>', 'such as pr:ado:Contoso.Web#1850:merged'],
944
1090
  ],
945
1091
  description: [
946
1092
  "In a worker's worktree with the daemon running, registers the wait and exits 0 at once: end the turn, and the daemon resumes the session when the condition holds. Otherwise checks it here and blocks until it holds or --timeout passes.",
@@ -950,7 +1096,7 @@ export const COMMANDS = [
950
1096
  ['wait for PR 1850 to merge', 'wait pr 1850 merged'],
951
1097
  ["wait on PR 1850's merge, checks and comments at once", 'wait pr 1850 merged checks comment'],
952
1098
  ['wait for the plan approval', 'wait approval'],
953
- ['wait for a dev release on npm', 'wait npm 8.7.0-dev.8 --tag dev --package @detergent-software/atk'],
1099
+ ['wait for a dev release on npm', 'wait npm 8.7.0-dev.8 --tag dev --package @contoso/cli'],
954
1100
  ],
955
1101
  exitCodes: [
956
1102
  [0, 'the condition holds, or the daemon registered the wait'],
@@ -979,12 +1125,12 @@ export const COMMANDS = [
979
1125
  usage: ['wait <condition> [--local] [--timeout <minutes>] [--worker <worker>] [--item <item>]'],
980
1126
  },
981
1127
  {
982
- arguments: [['<event id | item>', 'an event id (4200) or an item (ATK-312)']],
1128
+ arguments: [['<event id | item>', 'an event id (4200) or an item (ENG-312)']],
983
1129
  description: [
984
1130
  "With an event id, that event's rule and the events that led to it; with an item, the same for each of its newest actions.",
985
1131
  ],
986
1132
  examples: [
987
- ['why the conductor acted on ATK-312', 'why ATK-312'],
1133
+ ['why the conductor acted on ENG-312', 'why ENG-312'],
988
1134
  ['the rule behind event 4200', 'why 4200'],
989
1135
  ],
990
1136
  group: 'Console and rules',
@@ -1003,7 +1149,7 @@ const HELP_ROWS = [
1003
1149
  ];
1004
1150
  const FOOTER = [
1005
1151
  'Run conduct help <command> for its options and examples.',
1006
- 'A <worker> is its item (ATK-309) or its name (probe-ATK-309).',
1152
+ 'A <worker> is its item (ENG-309) or its name (probe-ENG-309).',
1007
1153
  'Files live in ~/.conductor (CONDUCTOR_HOME overrides it).',
1008
1154
  ];
1009
1155
  // A placeholder, `conduct <command>`, or a flag: what prose styles.