@detergent-software/conductor 2.2.0-dev.3 → 3.0.0-dev.10
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 +98 -0
- package/README.md +86 -37
- package/build/broker-cli.js +19 -21
- package/build/broker-cli.js.map +1 -1
- package/build/broker.js +66 -92
- package/build/broker.js.map +1 -1
- package/build/checkout-sync.js +4 -21
- package/build/checkout-sync.js.map +1 -1
- package/build/claude.js +56 -9
- package/build/claude.js.map +1 -1
- package/build/cli.js +43 -46
- package/build/cli.js.map +1 -1
- package/build/code-host.js +10 -8
- package/build/code-host.js.map +1 -1
- package/build/config.js +10 -0
- package/build/config.js.map +1 -1
- package/build/console.js +39 -29
- package/build/console.js.map +1 -1
- package/build/daemon.js +55 -6
- package/build/daemon.js.map +1 -1
- package/build/help.js +19 -33
- package/build/help.js.map +1 -1
- package/build/in-process.js +3 -3
- package/build/in-process.js.map +1 -1
- package/build/inbox.js +47 -4
- package/build/inbox.js.map +1 -1
- package/build/lib/providers/index.js +1 -1
- package/build/lib/providers/index.js.map +1 -1
- package/build/lib/providers/npm/stage.js +14 -4
- package/build/lib/providers/npm/stage.js.map +1 -1
- package/build/local-files.js +95 -0
- package/build/local-files.js.map +1 -0
- package/build/manager.js +215 -27
- package/build/manager.js.map +1 -1
- package/build/npm-reads.js +194 -0
- package/build/npm-reads.js.map +1 -0
- package/build/paths.js +2 -0
- package/build/paths.js.map +1 -1
- package/build/plugin.js +146 -0
- package/build/plugin.js.map +1 -0
- package/build/profile.js +60 -21
- package/build/profile.js.map +1 -1
- package/build/project-check-cli.js +4 -1
- package/build/project-check-cli.js.map +1 -1
- package/build/project-check.js +89 -30
- package/build/project-check.js.map +1 -1
- package/build/rules-service.js +22 -4
- package/build/rules-service.js.map +1 -1
- package/build/scheduler.js +11 -1
- package/build/scheduler.js.map +1 -1
- package/build/server.js +8 -16
- package/build/server.js.map +1 -1
- package/build/spend.js +4 -0
- package/build/spend.js.map +1 -1
- package/build/store.js +11 -10
- package/build/store.js.map +1 -1
- package/build/tracker-reads-cli.js +2 -4
- package/build/tracker-reads-cli.js.map +1 -1
- package/build/upgrade.js +25 -3
- package/build/upgrade.js.map +1 -1
- package/build/watchers/ado.js +3 -2
- package/build/watchers/ado.js.map +1 -1
- package/build/watchers/github.js +3 -2
- package/build/watchers/github.js.map +1 -1
- package/build/watchers/npm.js +6 -4
- package/build/watchers/npm.js.map +1 -1
- package/build/worktrees.js +182 -38
- package/build/worktrees.js.map +1 -1
- package/package.json +9 -9
- package/plugin/.claude-plugin/plugin.json +7 -0
- package/plugin/README.md +18 -0
- package/{mod → plugin}/hooks/model.ts +22 -4
- package/{mod → plugin}/hooks/register.tsx +63 -17
- package/plugin/skills/conductor-console/SKILL.md +94 -0
- package/plugin/skills/create-verification-skill/LICENSE +21 -0
- package/plugin/skills/create-verification-skill/README.md +9 -0
- package/plugin/skills/create-verification-skill/SKILL.md +44 -0
- package/plugin/skills/create-verification-skill/manifest.json +27 -0
- package/plugin/skills/create-verification-skill/references/feature-map-example/README.md +47 -0
- package/plugin/skills/create-verification-skill/references/feature-map-example/create-note.md +39 -0
- package/plugin/skills/create-verification-skill/references/feature-map-example/search.md +45 -0
- package/plugin/skills/maintain-verification-skill/LICENSE +21 -0
- package/plugin/skills/maintain-verification-skill/README.md +9 -0
- package/plugin/skills/maintain-verification-skill/SKILL.md +39 -0
- package/plugin/skills/maintain-verification-skill/manifest.json +23 -0
- package/plugin/skills/work-item/SKILL.md +253 -0
- package/plugin/skills/work-item/trackers/ado-boards.md +23 -0
- package/plugin/skills/work-item/trackers/github-issues.md +23 -0
- package/plugin/skills/work-item/trackers/linear.md +21 -0
- package/protocol/PROTOCOL.md +1 -1
- package/build/mod.js +0 -53
- package/build/mod.js.map +0 -1
- package/mod/.claude-plugin/marketplace.json +0 -6
- package/mod/.claude-plugin/plugin.json +0 -7
- package/mod/README.md +0 -19
- /package/{mod → plugin}/hooks/hooks.json +0 -0
- /package/{mod → plugin}/types/index.d.ts +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,104 @@
|
|
|
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.0.0-dev.10](https://emergentcode.visualstudio.com/Emergent%20Software/_git/Emergent.AgenticToolkit/branchCompare?baseVersion=GTconductor-v3.0.0-dev.9&targetVersion=GTconductor-v3.0.0-dev.10) (2026-10-17)
|
|
6
|
+
|
|
7
|
+
### Bug Fixes
|
|
8
|
+
|
|
9
|
+
* **conductor:** follow a new session id once it stays listed 5 s (ATK-574) ([32b86ea](https://emergentcode.visualstudio.com/Emergent%20Software/_git/Emergent.AgenticToolkit/commit/32b86ea40bc93e92736a9447aee3a1e0e9572879))
|
|
10
|
+
* **conductor:** follow a new session id only once two listings show it (ATK-574) ([5e8b65a](https://emergentcode.visualstudio.com/Emergent%20Software/_git/Emergent.AgenticToolkit/commit/5e8b65ad625fdbfa57566bc1b2b7d4adaa55b186))
|
|
11
|
+
|
|
12
|
+
## [3.0.0-dev.9](https://emergentcode.visualstudio.com/Emergent%20Software/_git/Emergent.AgenticToolkit/branchCompare?baseVersion=GTconductor-v3.0.0-dev.8&targetVersion=GTconductor-v3.0.0-dev.9) (2026-10-17)
|
|
13
|
+
|
|
14
|
+
### Bug Fixes
|
|
15
|
+
|
|
16
|
+
* **conductor:** hold launches only for a profile that doesn't read (ATK-573) ([2032a41](https://emergentcode.visualstudio.com/Emergent%20Software/_git/Emergent.AgenticToolkit/commit/2032a41daafc9fc85ccfcc594fd99520e8d38d49))
|
|
17
|
+
* **conductor:** name the conductor a profile needs and hold its launches (ATK-573) ([b8eb37e](https://emergentcode.visualstudio.com/Emergent%20Software/_git/Emergent.AgenticToolkit/commit/b8eb37e13bdb94ab4c9ca1e9cf46495f65e13f7b))
|
|
18
|
+
|
|
19
|
+
## [3.0.0-dev.8](https://emergentcode.visualstudio.com/Emergent%20Software/_git/Emergent.AgenticToolkit/branchCompare?baseVersion=GTconductor-v3.0.0-dev.7&targetVersion=GTconductor-v3.0.0-dev.8) (2026-10-17)
|
|
20
|
+
|
|
21
|
+
### Bug Fixes
|
|
22
|
+
|
|
23
|
+
* **conductor:** open the console tab while CONDUCTOR_HOME is set (ATK-572) ([68e7131](https://emergentcode.visualstudio.com/Emergent%20Software/_git/Emergent.AgenticToolkit/commit/68e713197bca1c45a93a1dc122293253ffe5c952))
|
|
24
|
+
|
|
25
|
+
## [3.0.0-dev.7](https://emergentcode.visualstudio.com/Emergent%20Software/_git/Emergent.AgenticToolkit/branchCompare?baseVersion=GTconductor-v3.0.0-dev.6&targetVersion=GTconductor-v3.0.0-dev.7) (2026-10-17)
|
|
26
|
+
|
|
27
|
+
### Features
|
|
28
|
+
|
|
29
|
+
* **conductor:** check Claude Code's workspace trust before a launch (ATK-571) ([fab9457](https://emergentcode.visualstudio.com/Emergent%20Software/_git/Emergent.AgenticToolkit/commit/fab94576638b713f913198a9a394a1e08a5709ac))
|
|
30
|
+
|
|
31
|
+
### Bug Fixes
|
|
32
|
+
|
|
33
|
+
* **conductor:** skip the trust probe behind a skills fail (ATK-571) ([a3614a5](https://emergentcode.visualstudio.com/Emergent%20Software/_git/Emergent.AgenticToolkit/commit/a3614a5f5c35c04991b002de6a459fdd3159d32e))
|
|
34
|
+
* **conductor:** trust probe review fixes (ATK-571) ([c9d1a11](https://emergentcode.visualstudio.com/Emergent%20Software/_git/Emergent.AgenticToolkit/commit/c9d1a11578dde0c92559bfce8c1b255a7f7ca8f7))
|
|
35
|
+
|
|
36
|
+
## [3.0.0-dev.6](https://emergentcode.visualstudio.com/Emergent%20Software/_git/Emergent.AgenticToolkit/branchCompare?baseVersion=GTconductor-v3.0.0-dev.5&targetVersion=GTconductor-v3.0.0-dev.6) (2026-10-17)
|
|
37
|
+
|
|
38
|
+
### Bug Fixes
|
|
39
|
+
|
|
40
|
+
* **conductor:** pick npm's proxy as npm does, and follow redirects (ATK-561) ([76db548](https://emergentcode.visualstudio.com/Emergent%20Software/_git/Emergent.AgenticToolkit/commit/76db5481a3920fdf3e1ea97c773b158837249142))
|
|
41
|
+
* **conductor:** read npm with npm's own registry and proxy settings (ATK-561) ([cd5dacf](https://emergentcode.visualstudio.com/Emergent%20Software/_git/Emergent.AgenticToolkit/commit/cd5dacf50c5a76c0a08fcec7d628210cd2637d42))
|
|
42
|
+
|
|
43
|
+
## [3.0.0-dev.5](https://emergentcode.visualstudio.com/Emergent%20Software/_git/Emergent.AgenticToolkit/branchCompare?baseVersion=GTconductor-v3.0.0-dev.4&targetVersion=GTconductor-v3.0.0-dev.5) (2026-10-17)
|
|
44
|
+
|
|
45
|
+
### Bug Fixes
|
|
46
|
+
|
|
47
|
+
* **conductor:** start the console without the caller's Claude session (ATK-559) ([767279a](https://emergentcode.visualstudio.com/Emergent%20Software/_git/Emergent.AgenticToolkit/commit/767279a80281dbc4774329b2f9d6aa06d0ccdf78))
|
|
48
|
+
|
|
49
|
+
## [3.0.0-dev.4](https://emergentcode.visualstudio.com/Emergent%20Software/_git/Emergent.AgenticToolkit/branchCompare?baseVersion=GTconductor-v3.0.0-dev.3&targetVersion=GTconductor-v3.0.0-dev.4) (2026-10-17)
|
|
50
|
+
|
|
51
|
+
### Features
|
|
52
|
+
|
|
53
|
+
* **conductor:** make worktrees built in, with named ports (ATK-526) ([a899350](https://emergentcode.visualstudio.com/Emergent%20Software/_git/Emergent.AgenticToolkit/commit/a899350fb4606f67a4de7af2a50d3e6d616ccead))
|
|
54
|
+
* **conductor:** take its ports in dev-ports, document built-in worktrees (ATK-526) ([1e19523](https://emergentcode.visualstudio.com/Emergent%20Software/_git/Emergent.AgenticToolkit/commit/1e19523fa9ca8252f9cd5a518edd2b66b7899a2a))
|
|
55
|
+
|
|
56
|
+
### Bug Fixes
|
|
57
|
+
|
|
58
|
+
* **conductor:** harden built-in worktrees from the review and probe (ATK-526) ([900f495](https://emergentcode.visualstudio.com/Emergent%20Software/_git/Emergent.AgenticToolkit/commit/900f49504b3291083dd3fa5f64f7efc11d28ecc2))
|
|
59
|
+
* **conductor:** never delete a worktree that may hold work (ATK-526) ([f2114b1](https://emergentcode.visualstudio.com/Emergent%20Software/_git/Emergent.AgenticToolkit/commit/f2114b1fb0e31c7ecad8d215fae6174ccfeee6b8))
|
|
60
|
+
|
|
61
|
+
### Documentation
|
|
62
|
+
|
|
63
|
+
* **conductor:** describe the hardened worktree launch and retire (ATK-526) ([be45c3c](https://emergentcode.visualstudio.com/Emergent%20Software/_git/Emergent.AgenticToolkit/commit/be45c3ca98c51f404d77279e4d34b03bedf3ea71))
|
|
64
|
+
|
|
65
|
+
## [3.0.0-dev.3](https://emergentcode.visualstudio.com/Emergent%20Software/_git/Emergent.AgenticToolkit/branchCompare?baseVersion=GTconductor-v3.0.0-dev.2&targetVersion=GTconductor-v3.0.0-dev.3) (2026-10-17)
|
|
66
|
+
|
|
67
|
+
### Bug Fixes
|
|
68
|
+
|
|
69
|
+
* **conductor:** read the upgrade's dist-tag fresh from npm (ATK-558) ([4b31619](https://emergentcode.visualstudio.com/Emergent%20Software/_git/Emergent.AgenticToolkit/commit/4b31619a6d3ebd6380751c993eada457259a1346))
|
|
70
|
+
|
|
71
|
+
## [3.0.0-dev.2](https://emergentcode.visualstudio.com/Emergent%20Software/_git/Emergent.AgenticToolkit/branchCompare?baseVersion=GTconductor-v3.0.0-dev.1&targetVersion=GTconductor-v3.0.0-dev.2) (2026-10-17)
|
|
72
|
+
|
|
73
|
+
### Documentation
|
|
74
|
+
|
|
75
|
+
* **conductor:** say the first console asks to trust its folder (ATK-525) ([8d9e37d](https://emergentcode.visualstudio.com/Emergent%20Software/_git/Emergent.AgenticToolkit/commit/8d9e37de5b37807bfab5fb7a94903be868513d6a))
|
|
76
|
+
|
|
77
|
+
## [3.0.0-dev.1](https://emergentcode.visualstudio.com/Emergent%20Software/_git/Emergent.AgenticToolkit/branchCompare?baseVersion=GTconductor-v2.2.0-dev.3&targetVersion=GTconductor-v3.0.0-dev.1) (2026-10-17)
|
|
78
|
+
|
|
79
|
+
### ⚠ BREAKING CHANGES
|
|
80
|
+
|
|
81
|
+
* **conductor:** conduct install-mod and conduct console --project
|
|
82
|
+
are removed. The console runs in ~/.conductor/console and loads the
|
|
83
|
+
conductor plugin with --plugin-dir.
|
|
84
|
+
|
|
85
|
+
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
|
86
|
+
|
|
87
|
+
### Features
|
|
88
|
+
|
|
89
|
+
* **conductor:** run the console at machine level and retire install-mod (ATK-525) ([343fa6f](https://emergentcode.visualstudio.com/Emergent%20Software/_git/Emergent.AgenticToolkit/commit/343fa6f5edf25d4005de7adfafaec56765ca5475))
|
|
90
|
+
* **conductor:** say when a worker wakes without the plugin (ATK-525) ([9af10be](https://emergentcode.visualstudio.com/Emergent%20Software/_git/Emergent.AgenticToolkit/commit/9af10be6025ef32a1c9d5461027bbaedf28d8186))
|
|
91
|
+
* **conductor:** ship the plugin and load it with --plugin-dir (ATK-525) ([7a143de](https://emergentcode.visualstudio.com/Emergent%20Software/_git/Emergent.AgenticToolkit/commit/7a143de8301fd982a4f8aca41e94be3563930cb6))
|
|
92
|
+
|
|
93
|
+
### Bug Fixes
|
|
94
|
+
|
|
95
|
+
* **conductor:** act on the plugin review (ATK-525) ([b349227](https://emergentcode.visualstudio.com/Emergent%20Software/_git/Emergent.AgenticToolkit/commit/b349227a5e079d7b7ca71f003c7c93b67920771d))
|
|
96
|
+
* **conductor:** report a worker's plugin to its own daemon (ATK-525) ([f746c2a](https://emergentcode.visualstudio.com/Emergent%20Software/_git/Emergent.AgenticToolkit/commit/f746c2a106b41b7c74fa050b9f0bffa07a8e175c))
|
|
97
|
+
|
|
98
|
+
### Documentation
|
|
99
|
+
|
|
100
|
+
* **conductor:** describe the plugin and the machine-level console (ATK-525) ([4b62b99](https://emergentcode.visualstudio.com/Emergent%20Software/_git/Emergent.AgenticToolkit/commit/4b62b99f1a8cc28f5228f3f88e90f99f9e994aab))
|
|
101
|
+
* **conductor:** say only what was seen of the console's trust prompt (ATK-525) ([1baa805](https://emergentcode.visualstudio.com/Emergent%20Software/_git/Emergent.AgenticToolkit/commit/1baa8057445cb6ff92ef0a0227accf9def4dd899))
|
|
102
|
+
|
|
5
103
|
## [2.2.0-dev.3](https://emergentcode.visualstudio.com/Emergent%20Software/_git/Emergent.AgenticToolkit/branchCompare?baseVersion=GTconductor-v2.2.0-dev.2&targetVersion=GTconductor-v2.2.0-dev.3) (2026-10-17)
|
|
6
104
|
|
|
7
105
|
### 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 `
|
|
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 (ATK-265), now part of the conductor plugin in `plugin/` (ATK-525), 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
|
|
|
@@ -37,7 +37,7 @@ conduct focus <project> [--slots <n>] [--weight <n>] --until <when>
|
|
|
37
37
|
a project's slots or ordering weight, for a while (neither: it goes first)
|
|
38
38
|
conduct why <event id | item> [--json]
|
|
39
39
|
the rule behind an action, and the events that led to it
|
|
40
|
-
conduct console [--
|
|
40
|
+
conduct console [--here]
|
|
41
41
|
open the console in a Windows Terminal tab, or in this terminal (see Console)
|
|
42
42
|
conduct escalations [--json] what rules escalated to the console and it hasn't handled
|
|
43
43
|
conduct escalations done <id> [--ask] <text>
|
|
@@ -80,15 +80,13 @@ conduct runs <sha> --requeue <pipeline>
|
|
|
80
80
|
queue the item's merge's cancelled run again on the base (see Worker verbs)
|
|
81
81
|
conduct train [<project>] [--dry-run]
|
|
82
82
|
merge the waiting skill publishes into one registry PR (see Skill trains)
|
|
83
|
-
conduct ports [<path>] [--
|
|
84
|
-
a checkout's dev ports from the port broker, or every worktree's (see Broker)
|
|
83
|
+
conduct ports [<path>] [--json] a conducted worktree's dev ports from the port broker, or every worktree's (see Broker)
|
|
85
84
|
conduct lock acquire|release|status <name> [--owner <id>] [--wait <minutes>]
|
|
86
85
|
a lock every project shares, such as chrome (see Broker)
|
|
87
86
|
conduct events [--since <id>] [--follow] [--console]
|
|
88
87
|
the event log, one JSON event per line (see API)
|
|
89
88
|
conduct install-startup start the supervised daemon at logon (Windows Task Scheduler)
|
|
90
89
|
conduct install-startup --remove remove that logon task
|
|
91
|
-
conduct install-mod [--remove] install the conductor mod in Claude Code (see Mod)
|
|
92
90
|
conduct upgrade [--tag dev|latest] [--allow-downgrade]
|
|
93
91
|
stop the daemon, npm install the tag's newest version, start it again
|
|
94
92
|
```
|
|
@@ -101,11 +99,27 @@ A `<worker>` is its item (`ATK-309`) or its name (`probe-ATK-309`).
|
|
|
101
99
|
|
|
102
100
|
The session manager owns the `claude --bg` sessions it launches, and only those:
|
|
103
101
|
|
|
104
|
-
- **launch:** the worktree comes first,
|
|
102
|
+
- **launch:** the worktree comes first, made by the daemon itself (design note v2, section 2; ATK-526), with no hooks:
|
|
103
|
+
1. the broker gives it a port for each name in the profile's `ports` (see Broker);
|
|
104
|
+
2. `git worktree add` makes `<root>/.claude/worktrees/<name>` on `worktree-<name>` from `origin/<base>`, fetched first (after `git worktree prune`, and on Windows with `core.longpaths` on). A worktree git still reads there is reused, its own changes and all; one with a `.git` git can't read is never deleted, and fails the launch. A `worktree-<name>` branch that is left is checked out again, with any commits it kept;
|
|
105
|
+
3. with `localFilesFrom` (an absolute path to a checkout the operator keeps), the gitignored files there that match its `.worktreeinclude` are copied in, as they are now;
|
|
106
|
+
4. the profile's `setup` commands run in order in the worktree, through the shell, with `CONDUCTOR_PORT_<NAME>` (such as `CONDUCTOR_PORT_WEB=41000`), `CONDUCTOR_ITEM`, `CONDUCTOR_PROJECT` and `CONDUCTOR_WORKTREE` set. They build its gitignored files from what the repo commits (ATK's: `pnpm install`, `atk setup --tool claude-code --yes`, `node scripts/dev-ports.mjs assign`, `atk install`). The first that fails fails the launch, with the end of its output. So does a setup that leaves changes git sees, such as an `.atk-lock.json` that `atk install` rewrote: the worker would take them for its own;
|
|
107
|
+
5. the ports go into the worktree's `.claude/settings.local.json` as `env`, merged into what the file had. A `claude --bg` session doesn't inherit the environment it is started from, but Claude Code applies that file's `env` to every session in the folder and to each resume;
|
|
108
|
+
6. the profile's work and verify skills must be there: a `conductor:<skill>` in the plugin, any other in the worktree's `.claude/skills` or `~/.claude/skills`.
|
|
109
|
+
|
|
110
|
+
A launch that fails removes the worktree it made when it is clean, with its branch while that still has the launch's name; a worktree that was there before the launch stays.
|
|
111
|
+
|
|
112
|
+
Then `claude --bg -n <name> --plugin-dir <home>/plugin --disallowedTools EnterPlanMode ExitPlanMode --permission-mode auto -- <prompt>` runs with its cwd in the worktree (see Plugin), never `--worktree`. A profile with `"workers": { "tab": true }` also gets a Windows Terminal tab attached to the session.
|
|
105
113
|
- **park:** a worker with a wait (`POST /waits`) is stopped once `claude agents` shows its turn has ended. Its status becomes `parked`, and its tab closes.
|
|
106
114
|
- **resume:** when a wait resolves, the daemon lets the stop settle (`sessions.settleSeconds`). It checks the process has exited, then runs `claude --bg --resume <session> -- "[conductor] event: …"`. The session keeps its name, model, permission mode and disallowed tools. A resume of a session that still runs starts a copy; the daemon stops and removes the copy, then tries again.
|
|
107
115
|
- **compact:** a parked worker with no resolved wait, whose context the rules find too big (the default `compact-on-park`: past `sessions.compactTokens`, 300k), is resumed with `/compact <what to keep>` once its stop has settled (`worker.compacting`). It runs until its transcript shows the compaction's boundary (`worker.compacted`, with the context before it and the conversation it kept), then parks again on its waits, which resume it as usual. Each turn of a session re-reads its whole context from cache, so a worker left to grow pays for it every turn (ATK-454 reached 883k). A resume that starts a copy is tried again on a later sweep (`worker.compact-deferred`), as a resume is. A compaction whose resume fails, or whose turn ends with no boundary 10 minutes on, logs `worker.compact-failed`, which raises a `context` item in the inbox. The worker still parks, and the daemon doesn't try it again until it restarts or the session compacts some other way: any boundary in its transcript, Claude Code's own included, logs `worker.compacted` and resolves that item. A worker whose context is unknown is never compacted, so even a rule with no threshold can't compact it on every park.
|
|
108
|
-
- **retire:** refuses
|
|
116
|
+
- **retire:** refuses a worker whose turn still runs, unless `--force`, and never retires a session that is still starting. What happens to the worktree depends on the worker's PR (design note v2, section 2):
|
|
117
|
+
- **merged** (read from the code host): it refuses uncommitted or unpushed work unless `--force`, then stops the session, removes the worktree and deletes its local branch, and runs `claude rm`;
|
|
118
|
+
- **no PR, and nothing uncommitted or unpushed** (a canceled item, a worker retired before its first commit): as merged, with nothing to lose;
|
|
119
|
+
- **not merged** (abandoned or closed, or no PR with work in it): it stops and removes the session and frees the ports, and keeps the worktree and its branch, so nothing the PR didn't land is lost. `worker.retired` names it under `kept`, which raises one `failed` inbox item with the path, the branch and the commands that remove them. A PR the project's code host can't read at all counts as not merged;
|
|
120
|
+
- **unread** (the code host didn't answer): it refuses, as a refusal that passes on its own, and the scheduler tries again.
|
|
121
|
+
|
|
122
|
+
A probe's worktree and a `--force` retire's always go. The removal moves the worktree aside, has git forget it, deletes the branch and then the directory with Node, which unlinks pnpm's junctions without following them (`git worktree remove` leaves them on Windows). The delete is asynchronous, so the API goes on answering through a minute of `node_modules`. With the directory gone already, it deletes the `worktree-<name>` branch only when none of its commits is unpushed. If the stop fails, nothing is removed.
|
|
109
123
|
- **restarts:** a launch the daemon was stopped in adopts its session if one was started, and otherwise fails and removes its clean worktree.
|
|
110
124
|
- **attach:** a parked worker is resumed with no event text, so it wakes idle and keeps running when its tab closes. An attached worker isn't parked until it registers a new wait, or until its turn has been over `sessions.idleMinutes` (`worker.detached`). The daemon can't see the tab, so this also delivers a wait that resolved while it was attached. A wait that resolves after the attach, on a worker whose transcript shows no turn since then, is delivered at once: the worker is detached (`reason: wait resolved`), parked, which closes its tab, and resumed with the event. A worker someone woke outside the daemon counts as attached since its stop, so the turn that woke it counts. One that took a turn since the attach (or has no transcript to tell), or whose wait resolved before the attach, keeps it until the idle release, logs `worker.resume-held` (`reason: attached`) once, and `conduct status` shows it as `idle, holding resolved waits for the attached session`.
|
|
111
125
|
- **park failures:** a session whose process outlives `claude stop` by 30 s logs one `worker.park-failed` per spell, which raises a `stall` in the inbox (see Inbox), and the park is tried again every 5 minutes.
|
|
@@ -389,14 +403,13 @@ The scheduler moves conduct-atk's tick into the daemon (design note, section 8).
|
|
|
389
403
|
|
|
390
404
|
## Skill bumps reach the main checkout
|
|
391
405
|
|
|
392
|
-
A worker's worktree branches from `origin/<base>` and installs its own pins. The main checkout is different: it keeps the pins it was last pulled at,
|
|
406
|
+
A worker's worktree branches from `origin/<base>` and its `setup` installs its own pins. The main checkout is different: it keeps the pins it was last pulled at, for the sessions people start there. The console's skill doesn't: it comes with the conductor plugin (see Plugin). So the daemon checks each conducted project that has an `.atk-lock.json`, at most every `checkout.intervalMinutes` (10), until the daemon owns its clones (design note v2, step 6):
|
|
393
407
|
|
|
394
408
|
1. It runs `git fetch origin <base>` in the main checkout and compares the pins (asset type, name and version) at `HEAD` with those at `origin/<base>`. When they match and nothing is left to install, nothing more happens.
|
|
395
409
|
2. When they differ, it records the pins as pending (a `checkout.pending` event). With the main checkout on `<base>` and no local changes to `.atk-lock.json`, it then runs `git merge --ff-only origin/<base>`.
|
|
396
410
|
3. Once `HEAD` has the pins, whether by this pull or yours, it runs `atk install` for the pending assets. A `checkout.updated` event lists each `name old → new`. An install that fails or leaves drift stays pending, and the next check tries it again, in this daemon or the next.
|
|
397
|
-
4. When `conductor-console` itself changed, a `operator` inbox item asks you once to restart the console (`/clear`, then `/conductor-console`). Other skills need no restart, because every worker starts fresh.
|
|
398
411
|
|
|
399
|
-
The checkout isn't touched in these cases: it is on another branch, its lockfile has local changes, or git refuses the fast-forward. Instead one `operator` item gives the commands (`git -C <root> pull --ff-only`, `atk install -P <root>`). The same item stays open while an install leaves drift, and it resolves itself once the pins are installed. A worktree create waits for a check that is running, and a check waits while one of the project's workers is launching, so
|
|
412
|
+
The checkout isn't touched in these cases: it is on another branch, its lockfile has local changes, or git refuses the fast-forward. Instead one `operator` item gives the commands (`git -C <root> pull --ff-only`, `atk install -P <root>`). The same item stays open while an install leaves drift, and it resolves itself once the pins are installed. A worktree create waits for a check that is running, and a check waits while one of the project's workers is launching, so the two never run git in the main checkout at once. A failed fetch is only logged. `checkout.mode` is `update` (the default), `notify` (the item only, with no git or atk run) or `off`.
|
|
400
413
|
|
|
401
414
|
## Skill trains
|
|
402
415
|
|
|
@@ -544,14 +557,11 @@ Everything goes through the project's gh account (`projects.<name>.github.user`,
|
|
|
544
557
|
|
|
545
558
|
The broker shares what every project on the machine uses (ATK-318).
|
|
546
559
|
|
|
547
|
-
**Ports.** Each profile
|
|
548
|
-
- A
|
|
549
|
-
-
|
|
550
|
-
- A
|
|
551
|
-
-
|
|
552
|
-
- A project's dev scripts read the assignment with `--json`, as ATK's `scripts/dev-ports.mjs assign` does. They keep their own scheme when it exits 1 (`not brokered`): no daemon, an older one, or a checkout in no registered project.
|
|
553
|
-
- The broker knows only the slots it gave out. A slot a script picked on its own while no daemon answered stays unknown until that worktree asks the broker; until then only the listening probe keeps the slot clear. So `--prefer` is the slot the script would pick itself (`dev-ports.mjs` passes the checkout's own slot or its own free-slot scan's). The preferred slot is taken without the listening probe, because the checkout's own servers may be what listens there.
|
|
554
|
-
- A stored assignment follows its project's profile: when the base ports or `maxSlot` change, the worktree moves, its old slot first.
|
|
560
|
+
**Ports.** Each profile names the ports a worktree's dev servers need, such as ATK's `"ports": ["web", "api"]` (design note v2, section 2; ATK-526).
|
|
561
|
+
- A launch gives the worktree one port per name from the machine's pool, `ports.first` to `ports.last` in config.json (41000 to 41999): each the pool's first port that no other worktree of any project holds, nothing listens on (IPv4 or IPv6 loopback), and that binds, which also skips a range Windows reserves. They reach `setup` and the worker as `CONDUCTOR_PORT_<NAME>` (see Workers).
|
|
562
|
+
- The pool sits away from the usual dev ports and their slot schemes, such as ATK's 3000+N and 7071+N for a person's own worktrees, so those never take a port a worker was given.
|
|
563
|
+
- A worktree keeps its ports while the profile names the same ports; a changed list gives it new ones. Retiring the worker frees them, and so does a worktree whose directory is gone (at the next assignment).
|
|
564
|
+
- `conduct ports` lists the assignments, and `conduct ports <path>` gives one worktree's (`--json` for either). Only a launch assigns. `conduct project check` previews the ports a new worktree would get, saving nothing.
|
|
555
565
|
|
|
556
566
|
**Locks.** `conduct lock acquire chrome` takes the lock every project's verify runs share. It answers the work-issue helper's JSON (`acquired`, `heldBy`, `since`, `refreshed`; `released` for a release; `verdict` for a status).
|
|
557
567
|
- The owner is `--owner`, else the item of the worker whose worktree this is.
|
|
@@ -614,6 +624,7 @@ Everything lives in `~/.conductor` (`CONDUCTOR_HOME` overrides it):
|
|
|
614
624
|
- `GET /console/escalations`: the open escalations, oldest first (see Console).
|
|
615
625
|
- `POST /console/escalations/:id` with `{ "text": "<finding>", "ask"?: true }`: the console's report on one; 201 with the escalation, the `console.handled` event's id and the inbox item `ask` raised. 404 when the id isn't an escalation, 409 when it is handled already or older than 14 days.
|
|
616
626
|
- `POST /console/cache` with `{ "action": "warm" | "cold" | "failed", "contextTokens", "usage": { "cacheRead", "cacheWrite", "input", "output" } | null, "warms" }` or `{ "action": "clear", "contextTokens", "reason" }`: the mod's report on the idle console's prompt cache (see Mod); 201 with the `console.cache` event's id.
|
|
627
|
+
- `POST /plugin/seen` with `{ "sessionId", "version"? }`: the mod's report that the conductor plugin loaded in a session (see Plugin); 200 with `{ "worker": <name> | null }`, the worker that session belongs to.
|
|
617
628
|
- `GET /fleet`: the workers in flight, with session activity, phase, PR, waits and spend (today, total).
|
|
618
629
|
- `POST /workers` with `{ "item": "ATK-309", "project"?, "probe"?, "prompt"?, "conductor"? }`: launch; answers 202 with the `launching` worker. `GET /workers/:id` shows it with its latest events.
|
|
619
630
|
- `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.
|
|
@@ -663,7 +674,11 @@ conduct install-startup
|
|
|
663
674
|
conduct project add <path to the project's main checkout>
|
|
664
675
|
```
|
|
665
676
|
|
|
666
|
-
`conduct project add` walks up from the path it is given to the directory that holds `.claude/conductor.json`, and maps a worktree to its main checkout. After that the daemon takes the whole profile from disk when it starts and each time the file is saved, so a `git pull` that changes `slots` or `skills.work` needs no `conduct project add`. An older daemon refuses a profile with fields it doesn't know, so upgrade the daemon before a profile that uses new ones lands.
|
|
677
|
+
`conduct project add` walks up from the path it is given to the directory that holds `.claude/conductor.json`, and maps a worktree to its main checkout. After that the daemon takes the whole profile from disk when it starts and each time the file is saved, so a `git pull` that changes `slots` or `skills.work` needs no `conduct project add`. An older daemon refuses a profile with fields it doesn't know, so upgrade the daemon before a profile that uses new ones lands.
|
|
678
|
+
|
|
679
|
+
A profile that uses new fields says which conductor reads them: `"conductor": "3.0.0-dev.9"`, the version that first read the newest of them (a `-dev.N` while it is only on `dev`; a stable minimum such as `3.0.0` is newer than every `3.0.0-dev.N`, as semver orders them). Every conductor from the one that knows this key (ATK-573) checks it before the rest of the profile, and an older one refuses the file with one line instead of a list of fields: `conductor: needs 3.0.0-dev.9 or newer; this is 3.0.0-dev.7: run \`conduct upgrade --tag dev\`` (`--tag latest` for a stable minimum). The worker verbs that read the profile in a worktree (`conduct state`, `conduct branch`, `conduct search`, a lock with no daemon) say the same and exit 1, and the daemon's inbox item carries the line and the upgrade command. While a project's profile on disk doesn't read (a minimum above this conductor, a schema problem, another protocol), the scheduler launches none of the project's items: each waits in `conduct queue` as `profile refused: <its first problem>`, since a new worktree would hold the same file and its verbs would refuse it. A profile that reads but whose rules are refused, or that renames the project, keeps the last good profile and launches as before. Workers already running carry on, and launches resume on the first tick after the file loads.
|
|
680
|
+
|
|
681
|
+
After an `--allow-downgrade` to a version without those fields, the stored copy no longer validates either: the project shows `the stored profile no longer validates` and isn't conducted until its file, saved without them, is read again.
|
|
667
682
|
|
|
668
683
|
Then `conduct project check <name>` says whether the project can be conducted, before its first launch finds out. Each check prints one line, `ok`, `warn`, `fail` or `skip`, with a fix under a warn or a fail, and the command exits 1 when any check fails (`--json` prints the same as data):
|
|
669
684
|
|
|
@@ -671,13 +686,24 @@ Then `conduct project check <name>` says whether the project can be conducted, b
|
|
|
671
686
|
- **auth:** which credential each provider the project uses signs in with (project token, machine token or CLI login; see Accounts), probed as the daemon would. For each that isn't the project's own token, a detail line gives the scopes, the `cmdkey` line and the config key that would scope it; that is advice, and the check passes. A token that is there but refused, or no credential at all, fails.
|
|
672
687
|
- **tracker:** the tracker's login answers, and the queue reads (Linear: the team, and whether any of its projects has a priority; Boards: the saved query; GitHub Issues: the labelled issues).
|
|
673
688
|
- **code-host** and **ci:** the code host's login answers and the base branch exists; each release's `pipeline` names exactly one of the repo's pipelines.
|
|
674
|
-
- **worktree:** the launch's
|
|
675
|
-
- **skills:**
|
|
676
|
-
- **ports:** the
|
|
689
|
+
- **worktree:** the launch's worktree steps on a throwaway `conduct-check-<time>`: `git worktree add` from `origin/<base>`, `localFilesFrom`'s files, the ports the broker would give, and `setup`. Then the profile's skills must be there after it, and a `warn` says when git doesn't ignore `.claude/settings.local.json`, where the ports go. A `claude --bg` with no prompt then checks that Claude Code would start a session there: it starts idle, costs no tokens and is removed at once. Claude Code keeps workspace trust per repository, so a root nobody has opened in Claude Code fails here with the one step that trusts it, `claude` run in the root once with its trust prompt accepted (ATK-571). It is removed with its branch, whatever happened. The one check that writes; `--no-worktree` skips it, since setup can take a while (ATK's runs `pnpm install`).
|
|
690
|
+
- **skills:** `skills.work` is there and declares `protocol: 2` in its SKILL.md frontmatter (worker protocol 2), `skills.verify` is there, and `atk audit` finds the installed ones unchanged; a missing alias is a `warn`. A skill named `conductor:<skill>` is read from this package's plugin and isn't audited, and beside a plugin work skill the aliases only name older notes' headings, so they aren't checked; any other is read from the main checkout.
|
|
691
|
+
- **ports:** the machine's pool has a free port for each of the profile's `ports`, saving nothing; `skip` for a profile with none.
|
|
677
692
|
- **health:** each `health` URL answers; a `warn` at most, since an environment can be down.
|
|
678
693
|
|
|
679
694
|
With the daemon running it checks through the API, as the daemon's own accounts; without it, here, as the machine's.
|
|
680
695
|
|
|
696
|
+
A new worktree's local files come from the profile (design note v2, section 2; see Workers):
|
|
697
|
+
|
|
698
|
+
```jsonc
|
|
699
|
+
// The dev ports a worktree needs, by name: CONDUCTOR_PORT_WEB and CONDUCTOR_PORT_API.
|
|
700
|
+
"ports": ["web", "api"],
|
|
701
|
+
// Run in order in each new worktree; they build its gitignored files from what the repo commits.
|
|
702
|
+
"setup": ["pnpm install --frozen-lockfile", "node scripts/dev-ports.mjs assign"],
|
|
703
|
+
// Optional: copy the .worktreeinclude files of a checkout you keep, for local files made by hand.
|
|
704
|
+
"localFilesFrom": "C:\\Users\\you\\src\\project"
|
|
705
|
+
```
|
|
706
|
+
|
|
681
707
|
The profile's optional `work` section is for the project's work skill; the daemon only checks it:
|
|
682
708
|
|
|
683
709
|
```jsonc
|
|
@@ -710,34 +736,56 @@ To switch from a linked build to the package: `conduct stop`, `npm rm --global @
|
|
|
710
736
|
|
|
711
737
|
## Console
|
|
712
738
|
|
|
713
|
-
The console (design note, section 11) is the one Claude session that stays open beside the daemon. The conductor mod in it does the plumbing in code (see
|
|
739
|
+
The console (design note, section 11) is the one Claude session that stays open beside the daemon. The conductor mod in it does the plumbing in code (see Plugin). Its model wakes only for an escalation or for you, and runs the plugin's console skill (`/conductor:conductor-console`). It has no loop: no Monitor, no heartbeat, no ticks. Everything it knows comes from the daemon, so a new console after a close loses nothing.
|
|
740
|
+
|
|
741
|
+
The console belongs to the machine, not to a project (design note v2, section 1): it runs in `<home>/console` (`~/.conductor/console`), a folder of the conductor's own, and opens with no project registered. It reads items through the `conduct` verbs, which find the project from the item while the daemon runs, and a subagent that reads a project's code or logs works in that project's checkout, from `conduct status`.
|
|
714
742
|
|
|
715
743
|
```bash
|
|
716
|
-
conduct console
|
|
717
|
-
conduct console --here
|
|
718
|
-
conduct console --project cadence # with several projects registered: whose checkout it runs in
|
|
744
|
+
conduct console # a tab in Windows Terminal (window "conductor"), in ~/.conductor/console
|
|
745
|
+
conduct console --here # the same session in this terminal
|
|
719
746
|
```
|
|
720
747
|
|
|
721
|
-
It runs `claude -n conductor --permission-mode auto -- /conductor-console` with `CONDUCTOR_CONSOLE=1`. The skill starts the daemon if it isn't running (`conduct start`, detached, so it doesn't end with the session), then handles what waits.
|
|
748
|
+
It writes the plugin copy if none exists yet (see Plugin), then runs `claude --plugin-dir <home>/plugin -n conductor --permission-mode auto -- /conductor:conductor-console` with `CONDUCTOR_CONSOLE=1`. The first console in that folder asks Claude Code to trust it once, and the mod's band and the console's stream start only after you accept; background sessions there run with no prompt (ATK-525). The skill starts the daemon if it isn't running (`conduct start`, detached, so it doesn't end with the session), then handles what waits.
|
|
722
749
|
|
|
723
750
|
**Escalations.** A rule's `escalate console "<ask>"` appends `console.escalated` (the default `conductor-handoff` does it for a worker's `Handoff · conductor` note). The mod wakes the model with `[conductor] escalation #<id> on <item>: <ask>`. The console does the job and reports back with `conduct escalations done <id> "<what it found or did>"`, which logs `console.handled` with the escalation as its cause, so `conduct why <that event>` leads to the rule. With `--ask`, the finding also goes in the inbox as a `console` item, pushed like any other, for something only you can do. `conduct escalations` lists those not yet handled, from the last 14 days, including the ones raised while no console was open; the console reads it when it starts.
|
|
724
751
|
|
|
725
752
|
**With no console open.** The daemon counts the console's streams of `/events` (the mod's `conduct events --follow --console`). When escalations are open and no console stream has been open for 30 s, it raises one `console` inbox item, "escalations wait for the console and none is open: start one with conduct console", pushed like any other. The 30 s cover a console's own reconnects (the mod restarting `conduct events`, a daemon restart). The item resolves when a console opens or the last escalation is handled. The built-in `focus` profile doesn't push the `console` kind. The daemon never opens a console itself: that would wake a model on every escalation, unattended.
|
|
726
753
|
|
|
727
|
-
**Moving from conduct-atk.** Stop the conduct-atk session, `conduct upgrade` (the scheduler now launches by default),
|
|
754
|
+
**Moving from conduct-atk.** Stop the conduct-atk session, `conduct upgrade` (the scheduler now launches by default), then `conduct console`. A machine that keeps conduct-atk's loop sets `"scheduler": { "mode": "observe" }` in `config.json`.
|
|
755
|
+
|
|
756
|
+
## Plugin
|
|
757
|
+
|
|
758
|
+
`plugin/` is the conductor plugin (design note v2, section 4), one Claude Code plugin named `conductor` that holds:
|
|
759
|
+
|
|
760
|
+
- **the mod** (`hooks/`), below;
|
|
761
|
+
- **the console skill**, `/conductor:conductor-console` (see Console);
|
|
762
|
+
- **the reference work skill**, `/conductor:work-item`: a project's profile names it `skills.work: "conductor:work-item"`, and its notes are headed with the bare name, `work-item · `;
|
|
763
|
+
- **the verification-skill pair**, `/conductor:create-verification-skill` and `/conductor:maintain-verification-skill`, vendored from the ATK registry at a pinned version with their pstack MIT `LICENSE`.
|
|
764
|
+
|
|
765
|
+
It loads only into the sessions the conductor starts, the workers and the console: each starts with `--plugin-dir <home>/plugin`, and nothing installs it for the user, so other sessions list none of its skills. Skills of a plugin are namespaced (`/conductor:work-item`; the bare `/work-item` folds to it when nothing else has the name), while the mod's commands stay bare (`/approve`).
|
|
766
|
+
|
|
767
|
+
**The copy in `<home>/plugin`.** Sessions load a copy the daemon keeps, never the package folder, which moves with the Node version under nvm: a resume wakes a session with its saved `--plugin-dir`, and one whose path is gone runs on without the plugin, silently (ATK-522). The daemon refreshes the copy as it starts, and `conduct upgrade` does after npm installs; `conduct console` writes one only where none exists yet, and otherwise leaves the daemon's copy alone. A refresh writes only changed files, each beside itself and renamed over the old one, the hooks module last, and removes files the package no longer ships; it leaves what Claude Code writes into a plugin folder (`.claude-plugin/types/`, `tsconfig.json`). It also writes `conductor.json`, naming this package's `build/cli.js`, which the mod runs, and the daemon's home, which the mod reports to: a `claude --bg` session doesn't see the environment of the process that started it, so the mod can't read `CONDUCTOR_HOME` there. The folder itself is never moved or swapped.
|
|
768
|
+
|
|
769
|
+
**Reach of an update.** A parked worker loads the new plugin on its next wake. A live session reloads the hooks module by itself when the folder changes; skills need `/reload-plugins`.
|
|
770
|
+
|
|
771
|
+
**A worker that woke without it.** The mod reports every session start to `POST /plugin/seen`, a background worker's too. The daemon notes the time before each launch or resume, and a worker whose session hasn't reported within 3 minutes logs `worker.plugin-missing`, which raises a `failed` inbox item naming the plugin folder to check.
|
|
772
|
+
|
|
773
|
+
**The user-scope mod is retired.** `conduct install-mod` is gone. The daemon uninstalls a user-scope `conductor@conductor` and its marketplace on its first start (`plugin.user-install-retired`, which later starts check for), for the machine's own home only.
|
|
774
|
+
|
|
775
|
+
**Vendored skills.** `vendored-skills.json` pins each vendored skill's version and its files' hashes, and a test holds `plugin/skills/<name>` to them, so CI catches an edit without reaching the registry. `node scripts/vendor-skills.mjs <name> <version>` checks a skill out with `atk checkout` and pins it; `node scripts/vendor-skills.mjs --check` compares the pins with the registry (both need `atk` signed in).
|
|
728
776
|
|
|
729
|
-
|
|
777
|
+
### Mod
|
|
730
778
|
|
|
731
|
-
|
|
779
|
+
The mod is the plugin's hooks module, code that costs no tokens, which does the console's plumbing.
|
|
732
780
|
|
|
733
|
-
- **
|
|
781
|
+
- **Every session** sends its plugin report on start, and nothing else: no status line, and no other calls to the daemon.
|
|
734
782
|
- **The console**, the session started with `CONDUCTOR_CONSOLE=1` (`conduct console` starts it; see Console), reads `GET /fleet`, `GET /inbox` and `GET /notify` every 30 s and gets:
|
|
735
783
|
- **the band** above the prompt while the inbox has items: one hotkey per item (a plan approves after a second press, `y`, since a digit typed into an empty prompt presses a band button; an npm OTP copies its `npm stage approve` line; the rest open the pane), and `o` for the pane;
|
|
736
784
|
- **the pane** (`/conductor`, `o`, or opened at the start, docked as a sidebar on a fullscreen terminal of 144 columns or more): the notification profile (a picker; buttons on mobile) and Remote Control's state, the inbox with each item's actions (approve, revise, copy a command, open a link, done; on a Windows terminal, open is a button that opens a web link in the default browser once, since a ctrl+click on a link in a pane opened it twice, ATK-494), the workers by project (each project's rule has [pause] and [focus]), and today's spend. The header counts the workers running and parked and the inbox in words. Each worker is one line in columns that line up across projects, cut to the pane's width so it never wraps: a glyph, the item, its phase, its PR, what it waits on in words (`PR #557 to merge (agentic-toolkit-registry)`, `npm 8.9.0-dev.1 on dev (atk)`, `login (ado)`) or else its activity, and the age. As the pane narrows, the age goes first, then the wait, then the PR and the phase (ATK-521). The glyphs are one cell wide: `●` in a turn, `◌` up between turns, `!` stuck on a prompt, `○` parked, `×` failed or gone, `·` starting. A row expands to attach and why, its tokens today, its whole PR ref and its raw wait keys;
|
|
737
785
|
- **commands answered in code**, never by the model: `/conductor`, `/inbox`, `/approve <item | #id>`, `/revise <item | #id> <text>`, `/attach <item | worker>`, `/notify [<profile> [--until <when>]]`, `/pause [<project>] [--until <when>]`, `/unpause [<project>]`, `/focus-project <project> [--until <when>]` (puts its items first, until midnight without `--until`; not `/focus`, which is Claude Code's own);
|
|
738
|
-
- **a check that `/conductor-console` ran**: a console started without it (by hand, as `claude -n conductor`) shows `console without its skill: run /conductor-console` in the band, and each prompt, Jason's or an escalation's, carries a line telling the model to load the skill before it answers. Running the skill (`/conductor-console`, or the model's Skill tool) clears both, until a `/clear` or a resume starts a conversation without it;
|
|
786
|
+
- **a check that `/conductor:conductor-console` ran**: a console started without it (by hand, as `claude --plugin-dir … -n conductor`) shows `console without its skill: run /conductor:conductor-console` in the band, and each prompt, Jason's or an escalation's, carries a line telling the model to load the skill before it answers. Running the skill (`/conductor:conductor-console`, or the model's Skill tool) clears both, until a `/clear` or a resume starts a conversation without it;
|
|
739
787
|
- **a warm prompt cache while it idles** (ATK-386). The console's cache lasts an hour after its last use, and a wake after that writes the whole context again. So 55 minutes after the console's last turn, the mod sends one ping (`$.model.fork`, the console's own last request plus a one-word ask, no tools, no turn in the transcript). The API serves the ping from the cache for a tenth of a write's price, and the hour starts over. It pings again every 55 minutes until a turn comes, and each turn starts the timer over. At an idle point it runs `/clear` instead when the context is 150k or more, or after 12 pings in a row (the 13th idle point, about 12 hours after the last turn), and the band says `fresh console (cleared while idle: …)` until the next prompt loads the skill. A ping that read less than half the context from the cache (the cache was gone anyway, as under a 5-minute TTL) stops the pings until the next turn. Each ping and clear goes to `POST /console/cache`, which logs a `console.cache` event with the context size and what the ping cost. A fork isn't in the transcript, so that event is the only place its cost shows;
|
|
740
|
-
- **the stream**: it runs `node <
|
|
788
|
+
- **the stream**: it runs `node <the cli.js that conductor.json names> events --follow --console` (`--console` tells the daemon a console is open), redraws on each event, toasts each new inbox item, and acts on three events:
|
|
741
789
|
|
|
742
790
|
| Event | Data | The mod |
|
|
743
791
|
|---|---|---|
|
|
@@ -747,7 +795,7 @@ It runs `claude -n conductor --permission-mode auto -- /conductor-console` with
|
|
|
747
795
|
|
|
748
796
|
The notifier emits `notify.requested` (see Notifications), and the rules' `escalate console` action emits `console.escalated`. Nothing emits `worker.message-requested` yet.
|
|
749
797
|
|
|
750
|
-
Its checks: `pnpm -C apps/conductor test` runs `
|
|
798
|
+
Its checks: `pnpm -C apps/conductor test` runs `plugin/tests/*.spec.ts` (the logic, in CI). `pnpm -C apps/conductor typecheck` checks the mod too, in CI: its hooks, `$.state` contract and `*.test.tsx` against Claude Code's plugin API (`tsconfig.mod.json`), and its specs (`tsconfig.mod-specs.json`). CI has no Claude Code to write that API's types, so `mod-types/claude-code.d.ts` holds a copy; its first line names the Claude Code version it came from. After a Claude Code upgrade, load `/plugin-authoring` once in a session (it writes that build's types), then run `node scripts/sync-mod-types.mjs` from `apps/conductor` and `typecheck`. `pnpm -C apps/conductor lint` covers `plugin/` as well. `claude plugin validate apps/conductor/plugin` and `claude plugin test apps/conductor/plugin` (the hooks against the engine, UI on the terminal, desktop, VS Code and mobile surfaces) need Claude Code, so they run locally. To try a change in a session of your own: `claude --plugin-dir apps/conductor/plugin`.
|
|
751
799
|
|
|
752
800
|
## Releases
|
|
753
801
|
|
|
@@ -757,12 +805,13 @@ Its checks: `pnpm -C apps/conductor test` runs `mod/tests/*.spec.ts` (the logic,
|
|
|
757
805
|
|
|
758
806
|
```bash
|
|
759
807
|
pnpm -C apps/conductor lint
|
|
760
|
-
pnpm -C apps/conductor typecheck # src/, and
|
|
808
|
+
pnpm -C apps/conductor typecheck # src/, and plugin/ against mod-types/ (see Mod)
|
|
761
809
|
pnpm -C apps/conductor test
|
|
762
810
|
pnpm -C apps/conductor build
|
|
763
811
|
cd apps/conductor && node scripts/check-changelog.mjs
|
|
764
812
|
pnpm --filter @atk/providers check # the vendored src/lib/providers matches packages/providers
|
|
765
813
|
pnpm -C packages/providers test
|
|
766
|
-
claude plugin validate apps/conductor/
|
|
767
|
-
claude plugin test apps/conductor/
|
|
814
|
+
claude plugin validate apps/conductor/plugin
|
|
815
|
+
claude plugin test apps/conductor/plugin
|
|
816
|
+
node scripts/vendor-skills.mjs --check # from apps/conductor: the vendored skills match the registry
|
|
768
817
|
```
|
package/build/broker-cli.js
CHANGED
|
@@ -7,7 +7,8 @@ import { itemFor } from "./code-host-cli.js";
|
|
|
7
7
|
import { ConductorError } from "./errors.js";
|
|
8
8
|
import { fileLock } from "./file-lock.js";
|
|
9
9
|
import { usageError } from "./help.js";
|
|
10
|
-
import {
|
|
10
|
+
import { samePath } from "./paths.js";
|
|
11
|
+
import { PROFILE_FILE, profileProblem, readProfile } from "./profile.js";
|
|
11
12
|
import { lockSchema, portAssignmentSchema } from "./store.js";
|
|
12
13
|
import { daemonWorker, gitToplevel } from "./wait.js";
|
|
13
14
|
// How often `conduct lock acquire --wait` asks again, as the work-issue helper's lock does.
|
|
@@ -69,13 +70,14 @@ export async function lockCommand(paths, action, name, options, io) {
|
|
|
69
70
|
export function lockLine(lock) {
|
|
70
71
|
return ` ${lock.name} ${lock.holder} since ${new Date(lock.since).toLocaleString()}${lock.verdict === 'stale' ? ' (stale: free to take over)' : ''}`;
|
|
71
72
|
}
|
|
72
|
-
// `conduct ports [<
|
|
73
|
+
// `conduct ports [<checkout>]`: every worktree's dev ports from the broker, or one worktree's. Only a
|
|
74
|
+
// launch assigns them, so this only reads.
|
|
73
75
|
export async function portsCommand(paths, path, options, io) {
|
|
76
|
+
const answer = await ask(paths, { method: 'GET', path: '/ports' });
|
|
77
|
+
if (!answer.ok)
|
|
78
|
+
return notBrokered(answer.why);
|
|
79
|
+
const assignments = z.object({ assignments: z.array(portAssignmentSchema) }).parse(answer.body).assignments;
|
|
74
80
|
if (path === undefined) {
|
|
75
|
-
const answer = await ask(paths, { method: 'GET', path: '/ports' });
|
|
76
|
-
if (!answer.ok)
|
|
77
|
-
return notBrokered(answer.why);
|
|
78
|
-
const assignments = z.object({ assignments: z.array(portAssignmentSchema) }).parse(answer.body).assignments;
|
|
79
81
|
if (options.json)
|
|
80
82
|
io.out(JSON.stringify(assignments, null, 2));
|
|
81
83
|
else if (assignments.length === 0)
|
|
@@ -84,23 +86,21 @@ export async function portsCommand(paths, path, options, io) {
|
|
|
84
86
|
assignments.forEach((a) => io.out(portsLine(a)));
|
|
85
87
|
return 0;
|
|
86
88
|
}
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
return notBrokered(answer.why);
|
|
94
|
-
const { assignment } = z.object({ assignment: portAssignmentSchema }).parse(answer.body);
|
|
89
|
+
const worktree = resolve(io.cwd, path);
|
|
90
|
+
const assignment = assignments.find((a) => samePath(a.worktree, worktree));
|
|
91
|
+
if (!assignment)
|
|
92
|
+
throw new ConductorError(`${worktree} has no ports from the conductor`, [
|
|
93
|
+
'a conducted worktree gets them when its worker launches; `conduct ports` lists them all',
|
|
94
|
+
]);
|
|
95
95
|
io.out(options.json ? JSON.stringify(assignment, null, 2) : portsLine(assignment));
|
|
96
96
|
return 0;
|
|
97
97
|
}
|
|
98
|
-
// One line per
|
|
98
|
+
// One line per worktree: project, each port, then where.
|
|
99
99
|
export function portsLine(a) {
|
|
100
100
|
const ports = Object.entries(a.ports)
|
|
101
101
|
.map(([name, port]) => `${name} ${port}`)
|
|
102
102
|
.join(' · ');
|
|
103
|
-
return `${a.project}
|
|
103
|
+
return `${a.project} ${ports} ${a.worktree}`;
|
|
104
104
|
}
|
|
105
105
|
// The body of a 200 answer, or why nothing was brokered.
|
|
106
106
|
async function ask(paths, request) {
|
|
@@ -134,8 +134,8 @@ async function lockHere(action, name, options, io, why) {
|
|
|
134
134
|
try {
|
|
135
135
|
profile = readProfile(checkout).profile;
|
|
136
136
|
}
|
|
137
|
-
catch {
|
|
138
|
-
return notBrokered(`${why}, and ${checkout} has no readable ${PROFILE_FILE}`);
|
|
137
|
+
catch (error) {
|
|
138
|
+
return notBrokered(`${why}, and ${checkout} has no readable ${PROFILE_FILE}: ${profileProblem(error)}`);
|
|
139
139
|
}
|
|
140
140
|
const given = options.owner?.trim();
|
|
141
141
|
// Status needs no owner; the others take the checkout's item, and refuse without one.
|
|
@@ -158,9 +158,7 @@ async function lockHere(action, name, options, io, why) {
|
|
|
158
158
|
io.out(JSON.stringify(answer, null, 2));
|
|
159
159
|
return 0;
|
|
160
160
|
}
|
|
161
|
-
// Nothing brokered: none runs, an older one has no broker, or it refused
|
|
162
|
-
// registered project, no free slot). The caller keeps its own scheme, as ATK's
|
|
163
|
-
// scripts/dev-ports.mjs does on any exit but 0.
|
|
161
|
+
// Nothing brokered: none runs, an older one has no broker, or it refused.
|
|
164
162
|
function notBrokered(why) {
|
|
165
163
|
throw new ConductorError(`not brokered: ${why}`, ['nothing was brokered']);
|
|
166
164
|
}
|
package/build/broker-cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"broker-cli.js","sourceRoot":"","sources":["../src/broker-cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACvC,OAAO,EAAoB,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"broker-cli.js","sourceRoot":"","sources":["../src/broker-cli.ts"],"names":[],"mappings":"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"}
|