@detergent-software/conductor 1.0.0-dev.28 → 1.0.0-dev.29
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 +6 -0
- package/README.md +2 -2
- package/build/cli.js +2 -2
- package/mod/.claude-plugin/plugin.json +1 -1
- package/mod/README.md +2 -2
- package/mod/hooks/model.ts +2 -2
- package/mod/hooks/register.tsx +4 -6
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
Releases are tagged `conductor-v<version>` and staged on npm by `atk-conductor-release` (`pipelines/release-conductor.yml`), which writes each section below. `scripts/check-changelog.mjs` fails when a tag has no section here.
|
|
4
4
|
|
|
5
|
+
## [1.0.0-dev.29](https://emergentcode.visualstudio.com/Emergent%20Software/_git/Emergent.AgenticToolkit/branchCompare?baseVersion=GTconductor-v1.0.0-dev.28&targetVersion=GTconductor-v1.0.0-dev.29) (2026-10-12)
|
|
6
|
+
|
|
7
|
+
### Bug Fixes
|
|
8
|
+
|
|
9
|
+
* **conductor:** drop the mod's status line from every session (ATK-388) ([b87cba2](https://emergentcode.visualstudio.com/Emergent%20Software/_git/Emergent.AgenticToolkit/commit/b87cba2bd91e3bf9029513300b8b9260423e211b))
|
|
10
|
+
|
|
5
11
|
## [1.0.0-dev.28](https://emergentcode.visualstudio.com/Emergent%20Software/_git/Emergent.AgenticToolkit/branchCompare?baseVersion=GTconductor-v1.0.0-dev.27&targetVersion=GTconductor-v1.0.0-dev.28) (2026-10-12)
|
|
6
12
|
|
|
7
13
|
### Bug Fixes
|
package/README.md
CHANGED
|
@@ -454,8 +454,8 @@ It runs `claude -n conductor --permission-mode auto -- /conductor-console` with
|
|
|
454
454
|
|
|
455
455
|
`mod/` is the conductor mod: a Claude Code plugin (a hooks module, code that costs no tokens) that does the console's plumbing. `conduct install-mod` installs it for this user from the package's own `mod/` folder, as a folder marketplace (`claude plugin install conductor --marketplace <package>/mod --scope user`). Claude Code reads a folder marketplace's plugin in place, so `conduct upgrade` replaces the mod along with the daemon; open sessions load the new version with `/reload-plugins`. `--remove` uninstalls it.
|
|
456
456
|
|
|
457
|
-
- **
|
|
458
|
-
- **The console**, the session started with `CONDUCTOR_CONSOLE=1` (`conduct console` starts it; see Console),
|
|
457
|
+
- **Other sessions** get nothing from it: no status line, and no calls to the daemon.
|
|
458
|
+
- **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:
|
|
459
459
|
- **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;
|
|
460
460
|
- **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), the workers by project (each project's rule has [pause] and [focus]; a row expands to attach and why), and today's spend;
|
|
461
461
|
- **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);
|
package/build/cli.js
CHANGED
|
@@ -125,8 +125,8 @@ const USAGE = `Usage: conduct <command>
|
|
|
125
125
|
install-startup start the daemon at logon (Windows Task Scheduler)
|
|
126
126
|
install-startup --remove remove that logon task
|
|
127
127
|
install-mod install the conductor mod in Claude Code (user scope) from this package:
|
|
128
|
-
the
|
|
129
|
-
|
|
128
|
+
the inbox band, pane and commands in the console (a session started
|
|
129
|
+
with CONDUCTOR_CONSOLE=1)
|
|
130
130
|
install-mod --remove uninstall it
|
|
131
131
|
upgrade [--tag dev|latest] stop the daemon, npm install the newest version on the tag (default:
|
|
132
132
|
the tag the installed version came from), start the daemon again
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "conductor",
|
|
3
3
|
"version": "1.0.0",
|
|
4
|
-
"description": "The conductor console's plumbing:
|
|
4
|
+
"description": "The conductor console's plumbing: the inbox band, the fleet pane, zero-token commands, Remote Control pushes and escalation wake-ups.",
|
|
5
5
|
"author": { "name": "Emergent Software" },
|
|
6
6
|
"types": "./types/index.d.ts"
|
|
7
7
|
}
|
package/mod/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Conductor mod
|
|
2
2
|
|
|
3
|
-
A Claude Code plugin (a hooks module) that does the conductor console's plumbing in code, so it costs no tokens
|
|
3
|
+
A Claude Code plugin (a hooks module) that does the conductor console's plumbing in code, so it costs no tokens. Only the console (`CONDUCTOR_CONSOLE=1`) gets anything from it: the inbox band, the fleet pane, `/conductor` `/inbox` `/approve` `/revise` `/attach` `/notify` `/pause` `/unpause` `/focus-project`, toasts, Remote Control pushes (and the one warning when Remote Control is off), and the one model wake-up for an escalation. What it shows and does is in the conductor README's *Mod* section (`apps/conductor/README.md`).
|
|
4
4
|
|
|
5
5
|
Install it with the daemon's CLI, which ships this folder:
|
|
6
6
|
|
|
@@ -11,7 +11,7 @@ conduct install-mod
|
|
|
11
11
|
| File | Holds |
|
|
12
12
|
|---|---|
|
|
13
13
|
| `hooks/register.tsx` | the hooks: session start, commands, the band, the pane, the event stream; only its top-level functions take `$` |
|
|
14
|
-
| `hooks/model.ts` | the logic without the engine: parsing the daemon's answers, what the
|
|
14
|
+
| `hooks/model.ts` | the logic without the engine: parsing the daemon's answers, what the band and pane show, what each event asks for |
|
|
15
15
|
| `types/index.d.ts` | the `$.state` contract (`conductor.snapshot`, `confirming`, `expanded`) |
|
|
16
16
|
| `tests/conductor.test.tsx` | `claude plugin test`: the hooks against the engine, the daemon faked beneath them |
|
|
17
17
|
| `tests/model.spec.ts` | vitest (`pnpm -C apps/conductor test`, in CI): `model.ts` |
|
package/mod/hooks/model.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// The conductor mod's logic, with nothing of the engine in it: what the daemon's answers mean, what
|
|
2
|
-
// the
|
|
2
|
+
// the band and pane show, and what each event asks the mod to do. register.tsx does
|
|
3
3
|
// the engine's part (only its top-level functions may take `$`); vitest tests this file in CI
|
|
4
4
|
// (apps/conductor/mod/tests/model.spec.ts).
|
|
5
5
|
import type { ConductorInboxItem, ConductorNotify, ConductorSnapshot, ConductorWorker } from '../types';
|
|
@@ -56,7 +56,7 @@ export type Found<T> = { error: string; found?: undefined } | { error?: undefine
|
|
|
56
56
|
|
|
57
57
|
const BAND_LIMIT = 5;
|
|
58
58
|
|
|
59
|
-
// `conductor 3▶ 2⏸ ✉2
|
|
59
|
+
// `conductor 3▶ 2⏸ ✉2` for the pane's title, or undefined when no daemon answers.
|
|
60
60
|
export function statusText(snapshot: ConductorSnapshot | null): string | undefined {
|
|
61
61
|
if (snapshot === null || snapshot.error !== null) return undefined;
|
|
62
62
|
const running = snapshot.workers.filter((w) => w.status === 'running').length;
|
package/mod/hooks/register.tsx
CHANGED
|
@@ -37,8 +37,8 @@ import {
|
|
|
37
37
|
|
|
38
38
|
const PANE = 'conductor';
|
|
39
39
|
const TITLE = 'Conductor';
|
|
40
|
-
//
|
|
41
|
-
//
|
|
40
|
+
// The console reads /fleet and /inbox this often. It also follows the event stream, so this is its
|
|
41
|
+
// safety net and what re-ages its rows.
|
|
42
42
|
const POLL_MS = 30_000;
|
|
43
43
|
const DEBOUNCE_MS = 300;
|
|
44
44
|
const RESTART_MS = 5_000;
|
|
@@ -97,7 +97,7 @@ async function callApi($: EngineInterface, method: 'GET' | 'POST', path: string,
|
|
|
97
97
|
return { body: parsed, status: answer.status };
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
-
// Reads /fleet, /inbox and /notify into the state the drawings read
|
|
100
|
+
// Reads /fleet, /inbox and /notify into the state the drawings read.
|
|
101
101
|
async function refresh($: EngineInterface): Promise<ConductorSnapshot> {
|
|
102
102
|
const readAt = await $.clock.now();
|
|
103
103
|
let next: ConductorSnapshot;
|
|
@@ -113,7 +113,6 @@ async function refresh($: EngineInterface): Promise<ConductorSnapshot> {
|
|
|
113
113
|
next = { error: error instanceof Error ? error.message : String(error), inbox: [], notify: null, readAt, workers: [] };
|
|
114
114
|
}
|
|
115
115
|
await update($, snapshot, () => next);
|
|
116
|
-
$.ui.status(statusText(next));
|
|
117
116
|
return next;
|
|
118
117
|
}
|
|
119
118
|
|
|
@@ -138,7 +137,6 @@ async function onLine($: EngineInterface, text: string): Promise<void> {
|
|
|
138
137
|
case 'disconnected': {
|
|
139
138
|
const readAt = await $.clock.now();
|
|
140
139
|
await update($, snapshot, () => ({ error: NOT_RUNNING, inbox: [], notify: null, readAt, workers: [] }));
|
|
141
|
-
$.ui.status(undefined);
|
|
142
140
|
return;
|
|
143
141
|
}
|
|
144
142
|
case 'escalate':
|
|
@@ -307,9 +305,9 @@ export const register: Register = (on) => {
|
|
|
307
305
|
const started = await next(e);
|
|
308
306
|
if (!e.isInteractive) return started;
|
|
309
307
|
isConsole = (await $.env.get('CONDUCTOR_CONSOLE')) === '1';
|
|
308
|
+
if (!isConsole) return started;
|
|
310
309
|
$.clock.every(POLL_MS, () => void refresh($));
|
|
311
310
|
await refresh($);
|
|
312
|
-
if (!isConsole) return started;
|
|
313
311
|
await registerCommands($);
|
|
314
312
|
void follow($);
|
|
315
313
|
// Docked as a sidebar on a wide fullscreen terminal; below that it waits until opened.
|
package/package.json
CHANGED