claude-slack-channel-bots 0.6.7 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -38,7 +38,7 @@ See the sections below for manual configuration details if you prefer not to use
38
38
 
39
39
  - [Bun](https://bun.sh) `>= 1.0.21` (agent-director minimum)
40
40
  - [Claude Code](https://claude.ai/code) installed and authenticated
41
- - [`agent-director`](https://github.com/gabemahoney/agent-director) **runtime dependency** — pulled in transitively when you install this package. Hard required at server boot: CSCB refuses to start if the library is missing, the host platform is unsupported, Bun is too old, or the installed version is below `MIN_AD_VERSION` (`^0.6.3`). agent-director itself requires [tmux](https://github.com/tmux/tmux) on the operator's PATH; CSCB no longer probes for it directly.
41
+ - [`agent-director`](https://github.com/gabemahoney/agent-director) **installed system-wide** as a prerequisite like `git` or `docker`. CSCB no longer vendors the AD binary. The npm `agent-director` package CSCB depends on is now a thin TypeScript shim that locates the system-installed binary at startup via `resolveSystemBinary()` / `Client.create()` and refuses to start when the binary is missing, too old, or unreachable. The startup gate enforces AD's required version (declared by AD in `dist/version-floor.json`) and reports the required version on mismatch. agent-director itself requires [tmux](https://github.com/tmux/tmux) on the operator's PATH; CSCB no longer probes for it directly.
42
42
  - Slack workspace admin access (to create and configure the Slack app)
43
43
  - **cozempic** (optional) — Python 3.10+ and `pip install cozempic` — used by JSONL path resolution helpers retained for downstream callers.
44
44
 
@@ -52,9 +52,74 @@ See the sections below for manual configuration details if you prefer not to use
52
52
  | `darwin-x64` (Intel Mac) | **Not supported** by agent-director |
53
53
  | Windows | **Not supported** by agent-director |
54
54
 
55
- If the host is unsupported, the SR-5.1 startup gate exits non-zero at server boot with a typed error from agent-director (`ErrPlatformPackageMissing` or `ErrUnsupportedPlatform`) and writes the failure to `~/.claude/channels/slack/startup-errors.log` and stderr. See [Startup errors](#startup-errors) below.
55
+ If the host is unsupported, the system-installed `agent-director` itself will refuse to install or run; CSCB's startup gate then exits non-zero with one of the `ad-system-install-*` class labels (see [Startup errors](#startup-errors)) and writes the failure to `~/.claude/channels/slack/startup-errors.log` and stderr. Consult [agent-director's documentation](https://github.com/gabemahoney/agent-director) for the canonical platform support list.
56
56
 
57
- > **Note on agent-director versions.** v0.4.1 is a zombie release (the published tarball is missing `dist/` and cannot be imported). v0.4.2 lacks the `MakeTemplateParams.overwrite` field CSCB needs for the boot-time template refresh. v0.5.4 and earlier lack `allow_pending` on `readPane`/`sendKeys`, causing `ErrSpawnNotInteractive` during dev-channels dialog approval on freshly-spawned bots. v0.6.0 shipped a stale TS shim whose `Client` dropped `getPermission`, whose `buildDecide()` dropped `--request-token`, and whose error catalog omitted `ErrInvalidFlags` / `ErrPermissionRequestNotFound` / `ErrAmbiguousRequest` — each silently breaks the disambiguation relay. v0.6.1–0.6.2 still lack the full `permission_requests` plural projection + composite-key disambiguation surface CSCB depends on for concurrent open requests. CSCB pins `^0.6.3` to get past all of these.
57
+ > **Note on agent-director versions.** v0.4.1 is a zombie release (the published tarball is missing `dist/` and cannot be imported). v0.4.2 lacks the `MakeTemplateParams.overwrite` field CSCB needs for the boot-time template refresh. v0.5.4 and earlier lack `allow_pending` on `readPane`/`sendKeys`, causing `ErrSpawnNotInteractive` during dev-channels dialog approval on freshly-spawned bots. v0.6.0 shipped a stale TS shim whose `Client` dropped `getPermission`, whose `buildDecide()` dropped `--request-token`, and whose error catalog omitted `ErrInvalidFlags` / `ErrPermissionRequestNotFound` / `ErrAmbiguousRequest` — each silently breaks the disambiguation relay. v0.6.1–0.6.2 still lack the full `permission_requests` plural projection + composite-key disambiguation surface CSCB depends on for concurrent open requests. From v0.7.0 onward, AD ships as a thin npm shim around a system-installed binary, and CSCB defers the minimum-AD-version decision to AD itself via `dist/version-floor.json` (AD's library-side `Client.create()` reads it). CSCB's `package.json` caret-pin on `agent-director` governs npm resolution of AD's TypeScript shim only — not the runtime floor, which is owned by the AD release the system binary belongs to.
58
+
59
+ ### Checking your agent-director install
60
+
61
+ Before starting the server, you can confirm `agent-director` is installed system-wide and meets the declared minimum with:
62
+
63
+ ```sh
64
+ bun run install-check
65
+ ```
66
+
67
+ The script calls the same discovery + floor-comparison pipeline the startup gate uses (it reads AD's `dist/version-floor.json`, calls `resolveSystemBinary()`, and compares versions via `semver.gte`). It exits 0 on success with a single-line block naming `agent-director`, the absolute resolved binary path, the detected version, and the floor. On failure it writes one of the canonical class labels to stderr and exits non-zero:
68
+
69
+ - `ad-system-install-not-found` — no agent-director on PATH or at the standard install path. Install AD and retry. The stderr also points at the install-cscb skill for interactive remediation.
70
+ - `ad-system-install-too-old` — AD binary is below the floor. Upgrade AD and retry. The stderr points at the skill.
71
+ - `ad-system-install-unreachable` — AD discovered but the probe could not invoke it (eight `.reason` values exposed verbatim). The stderr points at the skill.
72
+ - `ad-version-floor-unreadable` — `dist/version-floor.json` is missing, malformed, or lacks `min_binary_version`. The remediation is to reinstall `agent-director` from npm; the install-cscb skill cannot fix a corrupt AD package, so this case does NOT append the skill instructions block.
73
+
74
+ The script is purely diagnostic — it never prompts, never runs an install command, never fetches the skill. The startup gate enforces the same floor automatically at server boot via AD's `Client.create()`; `install-check` is for operators who want to confirm their setup ahead of time.
75
+
76
+ ### Installing the install-cscb skill
77
+
78
+ If `bun run install-check` (or the startup gate) reports one of the
79
+ `ad-system-install-*` failure classes, you can install the `install-cscb`
80
+ Claude skill for an interactive walkthrough. The skill drives the same
81
+ shared check module but walks you through install/upgrade and a
82
+ per-reason remediation flow for each of the eight
83
+ `ErrSystemInstallUnreachable.reason` values.
84
+
85
+ The skill is NOT auto-installed by `bun install` — fetch it manually
86
+ from CSCB's GitHub repo and place it in your local Claude skills
87
+ folder:
88
+
89
+ 1. **Fetch** `SKILL.md` from:
90
+
91
+ ```
92
+ https://github.com/gabemahoney/claude-slack-channel-bots/blob/main/skills/install-cscb/SKILL.md
93
+ ```
94
+
95
+ (The startup gate's `ad-system-install-*` error log line includes
96
+ this URL automatically.)
97
+
98
+ 2. **Place** it at:
99
+
100
+ ```
101
+ ~/.claude/skills/install-cscb/SKILL.md
102
+ ```
103
+
104
+ 3. **Invoke** the skill from Claude Code:
105
+
106
+ ```
107
+ /install-cscb
108
+ ```
109
+
110
+ The skill calls `bun run install-check` on each iteration, surfaces
111
+ `agent-director`'s published install/upgrade command verbatim (no
112
+ CSCB-owned install command — AD's documentation is the source of
113
+ truth), prompts before running, and loops until the check passes or
114
+ you decline. The `ad-version-floor-unreadable` class is handled
115
+ separately: the skill prints reinstall-from-npm guidance and does NOT
116
+ loop on it (the skill cannot fix a corrupt AD npm package).
117
+
118
+ The published CSCB npm tarball includes `skills/install-cscb/SKILL.md`
119
+ under its `files` array, so the skill source is also available via
120
+ `node_modules/claude-slack-channel-bots/skills/install-cscb/SKILL.md`
121
+ after `bun install`. The manual GitHub-fetch step above is for users
122
+ who haven't yet installed CSCB at all.
58
123
 
59
124
  ---
60
125
 
@@ -433,15 +498,15 @@ CSCB writes fatal startup errors to `~/.claude/channels/slack/startup-errors.log
433
498
 
434
499
  Classes you may see:
435
500
 
436
- - `ad-platform-package-missing` — agent-director's platform-native peer dependency is absent. The host is unsupported by agent-director.
437
- - `ad-unsupported-platform` — agent-director's runtime check rejected the host's `process.platform`/`process.arch` tuple.
501
+ - `ad-system-install-not-found` — `Client.create()` could not locate an `agent-director` binary on PATH or at the standard install path. Install agent-director system-wide and retry. The log line appends a manual-skill-install instructions block pointing at `skills/install-cscb/SKILL.md` (URL, target path under `~/.claude/skills/`, and invocation command `/install-cscb`) for the interactive install/upgrade flow.
502
+ - `ad-system-install-too-old` — the system-installed agent-director binary is below the floor declared in `dist/version-floor.json`. The log line names the detected and required versions, and appends the manual-skill-install instructions block.
503
+ - `ad-system-install-unreachable` — agent-director was discovered but the probe could not execute it (e.g. permission bits, broken symlink, runtime crash). The log line surfaces AD's supplied `err.reason` value verbatim (one of `not-executable`, `not-a-regular-file`, `probe-timeout`, `probe-nonzero-exit`, `probe-killed-by-signal`, `unparseable-version`, `spawn-failed`, `other`) and appends the manual-skill-install instructions block.
438
504
  - `ad-bun-version-too-old` — agent-director needs Bun `>= 1.0.21`. Upgrade Bun.
439
- - `ad-cli-not-executable` — the resolved agent-director CLI binary exists but is not executable. Run `chmod +x` on the binary referenced in the log line.
440
505
  - `ad-version-probe` — `agent-director` was loaded but the `version()` probe failed (subprocess invocation, platform binary, etc.).
441
- - `ad-version-stale` — installed `agent-director` is below the minimum version this CSCB requires. Run `bun add agent-director@^<minimum>`.
442
- - `ad-shim-missing-get-permission` — the installed `agent-director` TS shim's `Client` does not expose `getPermission`. The npm-published package is out of sync with its bundled binary. Reinstall and confirm the resolved version actually ships the method.
506
+ - `ad-shim-missing-get-permission` — the installed `agent-director` TS shim's `Client` does not expose `getPermission`. The npm-published package is out of sync with the system-installed binary. Reinstall a matching `agent-director` version and confirm the resolved package actually ships the method.
443
507
  - `ad-shim-catalog-incomplete` — the installed `agent-director` TS error catalog is missing one or more of `ErrInvalidFlags`, `ErrPermissionRequestNotFound`, `ErrAmbiguousRequest`. The log line lists the missing names. Same remediation as `ad-shim-missing-get-permission`.
444
- - `ad-shim-decide-drops-token` — the installed `agent-director` dist does not include `--request-token` in its bundled JS, meaning `buildDecide()` would resolve permission clicks against the wrong row. Reinstall and confirm `buildDecide` carries the flag.
508
+ - `ad-shim-decide-drops-token` — the installed `agent-director` dist does not include `--request-token` in its bundled JS, meaning `buildDecide()` would resolve permission clicks against the wrong row. Reinstall a matching `agent-director` version and confirm `buildDecide` carries the flag.
509
+ - `ad-version-floor-unreadable` — `node_modules/agent-director/dist/version-floor.json` could not be read, parsed, or is missing `.min_binary_version`. This is a packaging defect — reinstall `agent-director` from npm. Surfaced by `bun run install-check`; the startup gate itself does not emit this label (it relies on `Client.create()`, which fails differently when the AD package is corrupt).
445
510
  - `ad-call-timeout` — an agent-director verb call exceeded the configured `callTimeoutMs` (default 30 s). Investigate the subprocess or increase the timeout.
446
511
  - `ad-same-user` — `~/.agent-director/state.db` is owned by a different UID than the CSCB process. Reinstall agent-director as the correct user or remove the mismatched file.
447
512
  - `ad-same-user-stat` — Non-ENOENT stat error on the state DB (permissions, I/O). Investigate the file before re-launching.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-slack-channel-bots",
3
- "version": "0.6.7",
3
+ "version": "0.7.1",
4
4
  "description": "Multi-session Slack-to-Claude bridge — run multiple Claude Code bots across Slack channels via Socket Mode",
5
5
  "type": "module",
6
6
  "bin": {
@@ -10,6 +10,7 @@
10
10
  "src/*.ts",
11
11
  "!src/*.test.ts",
12
12
  "scripts/fixup-bun-cache.ts",
13
+ "scripts/install-check.ts",
13
14
  "slack-app-manifest.yml",
14
15
  "README.md",
15
16
  "skills/"
@@ -22,6 +23,7 @@
22
23
  "start": "bun install --no-summary && bun src/server.ts",
23
24
  "pretest": "bun scripts/fixup-bun-cache.ts && bun scripts/check-no-toplevel-mock-module.ts",
24
25
  "check:mocks": "bun scripts/check-no-toplevel-mock-module.ts",
26
+ "install-check": "bun scripts/install-check.ts",
25
27
  "test": "bun test",
26
28
  "typecheck": "tsc --noEmit"
27
29
  },
@@ -29,11 +31,12 @@
29
31
  "@modelcontextprotocol/sdk": "^1.0.0",
30
32
  "@slack/socket-mode": "^2.0.0",
31
33
  "@slack/web-api": "^7.0.0",
32
- "agent-director": "^0.6.3"
34
+ "agent-director": "^0.7.0",
35
+ "semver": "^7.6.0"
33
36
  },
34
37
  "devDependencies": {
35
38
  "@types/bun": "^1.0.0",
36
- "semver": "^7.6.0",
39
+ "@types/semver": "^7.7.1",
37
40
  "typescript": "^5.4.0"
38
41
  },
39
42
  "license": "MIT",
@@ -0,0 +1,67 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * scripts/install-check.ts — `bun run install-check` entry point.
4
+ *
5
+ * SR-6: standalone diagnostic command. Calls runInstallCheck() once,
6
+ * renders the result to stdout (success) or stderr (failure), and exits
7
+ * with the appropriate code.
8
+ *
9
+ * Appends the manual-skill-install instructions block to every failure
10
+ * class EXCEPT ad-version-floor-unreadable — that case's remediation is
11
+ * "reinstall agent-director from npm," not "install the install skill."
12
+ *
13
+ * The script MUST NOT prompt for input, MUST NOT run any install command,
14
+ * MUST NOT attempt to fetch the install skill. It is purely diagnostic.
15
+ *
16
+ * Not wired to any npm/bun lifecycle (no preinstall, postinstall, prepare,
17
+ * prepublishOnly). Operator runs it manually via `bun run install-check`.
18
+ *
19
+ * SPDX-License-Identifier: MIT
20
+ */
21
+
22
+ import { runInstallCheck } from '../src/install-check.ts'
23
+ import type { InstallCheckResult } from '../src/install-check.ts'
24
+ import { renderInstallSkillInstructions } from '../src/install-skill-pointer.ts'
25
+
26
+ export function renderSuccess(result: InstallCheckResult & { ok: true }): string {
27
+ return [
28
+ 'agent-director install check: OK',
29
+ ` binary: ${result.binaryPath}`,
30
+ ` version: ${result.binaryVersion}`,
31
+ ` floor: ${result.floor}`,
32
+ ].join('\n')
33
+ }
34
+
35
+ export function renderFailure(result: InstallCheckResult & { ok: false }): string {
36
+ const lines = [
37
+ `agent-director install check: FAILED (${result.classLabel})`,
38
+ result.message,
39
+ ]
40
+ if (Object.keys(result.detail).length > 0) {
41
+ lines.push(` detail: ${JSON.stringify(result.detail)}`)
42
+ }
43
+ return lines.join('\n')
44
+ }
45
+
46
+ export async function main(): Promise<void> {
47
+ const result = await runInstallCheck()
48
+
49
+ if (result.ok) {
50
+ process.stdout.write(renderSuccess(result) + '\n')
51
+ process.exit(0)
52
+ }
53
+
54
+ let body = renderFailure(result)
55
+ // SR-6.3: append the manual-skill-install block to every failure class
56
+ // EXCEPT ad-version-floor-unreadable (the skill can't fix a corrupt AD
57
+ // package; remediation is "reinstall agent-director").
58
+ if (result.classLabel !== 'ad-version-floor-unreadable') {
59
+ body += renderInstallSkillInstructions()
60
+ }
61
+ process.stderr.write(body + '\n')
62
+ process.exit(1)
63
+ }
64
+
65
+ if (import.meta.main) {
66
+ void main()
67
+ }
@@ -0,0 +1,209 @@
1
+ ---
2
+ name: install-cscb
3
+ description: Interactive walkthrough that installs or upgrades the system-installed `agent-director` so claude-slack-channel-bots can boot. Drives Epic 2's bun run install-check and per-reason remediation.
4
+ version: 1.0.0
5
+ author: Gabe Mahoney
6
+ license: MIT
7
+ user-invocable: true
8
+ argument-hint: "(no arguments)"
9
+ allowed-tools: [Bash, Read]
10
+ ---
11
+
12
+ # /install-cscb
13
+
14
+ Diagnose and fix a broken or missing `agent-director` system install so
15
+ `claude-slack-channel-bots` (CSCB) can boot. This skill is the interactive
16
+ counterpart to the diagnostic `bun run install-check` script — same shared
17
+ check module, but with a guided remediation loop for each failure class.
18
+
19
+ ## When to invoke
20
+
21
+ Invoke this skill when CSCB's startup gate emits one of these class labels
22
+ in `~/.claude/channels/slack/startup-errors.log`:
23
+
24
+ - `ad-system-install-not-found`
25
+ - `ad-system-install-too-old`
26
+ - `ad-system-install-unreachable`
27
+
28
+ The gate appends a pointer to this skill on those three classes. Other
29
+ failure classes (`ad-bun-version-too-old`, `ad-shim-*`, `ad-same-user`,
30
+ `ad-version-floor-unreadable`) are NOT remediated by this skill — see
31
+ the README's Startup-errors section for those.
32
+
33
+ ## Step 1 — Run the shared check
34
+
35
+ From the CSCB project root, run:
36
+
37
+ ```sh
38
+ bun run install-check
39
+ ```
40
+
41
+ This is the same command you can run directly from the shell. It calls
42
+ the shared check module (`src/install-check.ts`) which is also what this
43
+ skill drives internally on every iteration.
44
+
45
+ Read the output carefully:
46
+
47
+ - **Exit 0 + "OK"**: agent-director is satisfied. Print the resolved
48
+ binary path, detected version, and floor from the success output, then
49
+ exit cleanly. No further action required.
50
+
51
+ - **Exit non-zero**: identify the class label on stderr (one of
52
+ `ad-system-install-not-found`, `ad-system-install-too-old`,
53
+ `ad-system-install-unreachable`, `ad-version-floor-unreadable`) and
54
+ branch on it as documented below.
55
+
56
+ ## Step 2 — Identify the user's platform
57
+
58
+ Detect the platform via `uname -sm`. CSCB supports two platforms:
59
+
60
+ - **linux-x64** — `Linux x86_64`
61
+ - **darwin-arm64** — `Darwin arm64` (Apple Silicon Mac)
62
+
63
+ Any other platform is unsupported by `agent-director` itself and the
64
+ skill cannot proceed; surface the platform mismatch to the user and
65
+ exit non-zero.
66
+
67
+ ## Step 3 — Branch on the class label
68
+
69
+ ### `ad-system-install-not-found` — agent-director missing
70
+
71
+ Surface the install command published by `agent-director` verbatim for
72
+ the detected platform. Do NOT invent or maintain a CSCB-owned command —
73
+ consult agent-director's documentation
74
+ (<https://github.com/gabemahoney/agent-director>) for the canonical
75
+ install procedure. The current installer is `install.sh` from
76
+ agent-director's repo; recommend running it.
77
+
78
+ Prompt the user (using AskUserQuestion or an equivalent) — the literal
79
+ command must be visible:
80
+
81
+ > agent-director is not installed system-wide. Run the AD-published install
82
+ > command? `<command>`
83
+ >
84
+ > - **Yes** — run the command via Bash and continue.
85
+ > - **No** — install manually then continue.
86
+
87
+ - **Yes**: run the command via Bash. Capture stdout/stderr for the user
88
+ to see. Return to Step 1.
89
+ - **No**: instruct the user to install manually. Wait for confirmation.
90
+ Return to Step 1.
91
+
92
+ If the user declines to proceed at any point, exit non-zero with a
93
+ one-line summary: "Aborted by user — agent-director still not installed."
94
+
95
+ ### `ad-system-install-too-old` — agent-director below floor
96
+
97
+ Same flow as `ad-system-install-not-found` but with the upgrade command
98
+ instead of the install command. Surface the detected version and the
99
+ required floor from the stderr block so the user understands what they
100
+ are upgrading from and to.
101
+
102
+ Prompt:
103
+
104
+ > agent-director is installed but at version `<detected>`, below the
105
+ > required floor `<required>`. Run the AD-published upgrade command?
106
+ > `<command>`
107
+ >
108
+ > - **Yes** — run the command via Bash and continue.
109
+ > - **No** — upgrade manually then continue.
110
+
111
+ - **Yes**: run via Bash. Return to Step 1.
112
+ - **No**: wait for manual upgrade. Return to Step 1.
113
+
114
+ ### `ad-system-install-unreachable` — exhaustive reason switch
115
+
116
+ The stderr block carries an `err.reason` value verbatim. Branch on it
117
+ explicitly — every reason has a named branch, no `default:`-only
118
+ fallthrough.
119
+
120
+ 1. **`not-executable`** — the agent-director file exists but lacks the
121
+ executable bit. Show the user the binary path from the stderr block
122
+ and suggest:
123
+ ```sh
124
+ chmod +x <binary_path>
125
+ ```
126
+ Re-run Step 1.
127
+
128
+ 2. **`not-a-regular-file`** — the path resolved by `resolveSystemBinary()`
129
+ is a directory, broken symlink, or other non-file. Recommend
130
+ inspection (`ls -la <binary_path>`) and removal of the bad entry,
131
+ then re-installation via the AD install command. Re-run Step 1.
132
+
133
+ 3. **`probe-timeout`** — `agent-director --version` did not return within
134
+ the probe window. Likely the binary is hanging on startup
135
+ (corrupted, mismatched architecture, missing shared library).
136
+ Recommend a manual `<binary_path> --version` invocation to confirm,
137
+ then reinstall via the AD install command. Re-run Step 1.
138
+
139
+ 4. **`probe-nonzero-exit`** — `agent-director --version` exited with a
140
+ non-zero code. The stderr block surfaces `exitCode` and any
141
+ `diagnostic` from AD. Show the user the values and recommend a
142
+ manual reproduction (`<binary_path> --version`), then reinstall.
143
+ Re-run Step 1.
144
+
145
+ 5. **`probe-killed-by-signal`** — `agent-director --version` was killed
146
+ by a signal (SIGSEGV, SIGBUS, etc.). The stderr block surfaces
147
+ `signal`. The binary is likely corrupted or built for a different
148
+ architecture. Recommend a full reinstall via the AD install command.
149
+ Re-run Step 1.
150
+
151
+ 6. **`unparseable-version`** — `agent-director --version` returned but
152
+ the output could not be parsed as semver. The stderr's `diagnostic`
153
+ field carries the raw output. Likely the installed binary is from
154
+ a pre-release line that uses non-semver tags (e.g. `v0.6.3-dev`
155
+ without sentinel handling). Recommend upgrading to a release AD
156
+ version via the AD install command. Re-run Step 1.
157
+
158
+ 7. **`spawn-failed`** — the OS rejected the spawn before the subprocess
159
+ ran (ENOENT after stat succeeded, EACCES, EPERM, etc.). The stderr's
160
+ `diagnostic` field carries the underlying OS error. Recommend
161
+ checking filesystem permissions, then reinstalling. Re-run Step 1.
162
+
163
+ 8. **`other`** — an unexpected failure mode AD's `resolveSystemBinary()`
164
+ could not classify. Print the raw underlying error message from
165
+ `detail.underlying` (or `diagnostic`) and direct the user to file
166
+ a bug against `agent-director`:
167
+ <https://github.com/gabemahoney/agent-director/issues>
168
+
169
+ This is the only branch that recommends bug-filing rather than a
170
+ local remediation step.
171
+
172
+ After rendering the per-reason remediation, ask the user to confirm
173
+ they have applied it, then return to Step 1.
174
+
175
+ ### `ad-version-floor-unreadable` — corrupt agent-director npm package
176
+
177
+ This class is NOT a system-install problem — it indicates the
178
+ `node_modules/agent-director/dist/version-floor.json` file is missing,
179
+ malformed, or lacks `.min_binary_version`. The skill cannot walk the
180
+ user through fixing a corrupt AD npm package.
181
+
182
+ Print the reinstall guidance:
183
+
184
+ > The agent-director npm package appears corrupted. Reinstall it from
185
+ > npm in CSCB's project root:
186
+ >
187
+ > ```sh
188
+ > bun add agent-director@latest
189
+ > ```
190
+
191
+ Then exit. Do NOT loop on this class — the user must manually verify
192
+ the AD package is intact before re-invoking the skill.
193
+
194
+ ## Step 4 — Loop or exit
195
+
196
+ After each remediation step, re-run Step 1. The skill keeps looping
197
+ until the check passes (exit cleanly with the success output) or the
198
+ user declines to proceed (exit non-zero with the abort summary).
199
+
200
+ ## Notes
201
+
202
+ - This skill does not maintain its own list of agent-director install
203
+ commands. AD's documentation is the source of truth; the skill
204
+ surfaces AD's published command verbatim.
205
+ - This skill does not touch `~/.claude/channels/slack/` or CSCB's
206
+ routing configuration. It only acts on the system-wide
207
+ `agent-director` install.
208
+ - The skill is callable repeatedly; each invocation re-runs Step 1
209
+ from a clean state.
@@ -3,19 +3,20 @@
3
3
  * `agent-director` library Client (SR-0.1).
4
4
  *
5
5
  * Public API:
6
- * - getClient(): Client — lazy-construct + return the singleton
6
+ * - getClient(): Client — sync cached accessor for the singleton
7
+ * - setClient(client): void — install a pre-built Client (startup gate only)
7
8
  * - closeClient(): void — idempotent shutdown for SR-11 Event 11
8
- * - MIN_AD_VERSION: string — semver string derived from package.json
9
9
  * - DEFAULT_STORE_PATH / DEFAULT_TEMPLATE_NAME — paths CSCB pins
10
10
  * - resetClientForTests(): void — test-only handle reset
11
11
  *
12
- * MIN_AD_VERSION is read once at module init from this package.json's
13
- * `dependencies['agent-director']` range, stripping leading semver operators
14
- * (`^`, `~`, `>=`, etc.) so a single source of truth covers both the install-
15
- * time dep declaration (SR-5.3) and the runtime version gate (SR-5.1 step 3).
16
- *
17
- * Construction uses `{ storePath, createIfMissing: true, logger: console }`
18
- * per SR-0.1; tilde expansion is the library's responsibility.
12
+ * Construction: AD 0.7.0+ exposes an async `Client.create()` factory; the
13
+ * subprocess constructor is protected and `new Client(...)` is a compile-time
14
+ * TS error. The SR-5.1 startup gate (src/agent-director-startup.ts) awaits
15
+ * `Client.create({ storePath, createIfMissing: true, logger: console })` and
16
+ * then hands the resolved instance to `setClient()`. Verb call sites pull the
17
+ * installed singleton through `getClient()`; calling `getClient()` before the
18
+ * gate has installed a Client throws an internal bug-marker error (it
19
+ * indicates a caller-site bug, not a runtime condition).
19
20
  *
20
21
  * Concurrency: AD's Client is internally safe for concurrent verb calls
21
22
  * (the subprocess-CLI transport serializes its own dispatch) per SR-0.1,
@@ -24,9 +25,6 @@
24
25
  * SPDX-License-Identifier: MIT
25
26
  */
26
27
 
27
- import { readFileSync } from 'node:fs'
28
- import { dirname, join } from 'node:path'
29
- import { fileURLToPath } from 'node:url'
30
28
  import { AgentDirectorError, Client } from 'agent-director'
31
29
  import type {
32
30
  DecideParams as ADDecideParams,
@@ -45,40 +43,6 @@ export const DEFAULT_STORE_PATH = '~/.agent-director/state.db'
45
43
  /** Name of the CSCB-shipped template (SR-3.1). */
46
44
  export const DEFAULT_TEMPLATE_NAME = 'slack-channel-bot'
47
45
 
48
- /**
49
- * Resolve the package.json that ships with this module, then extract and
50
- * normalize `dependencies['agent-director']` into a bare semver string.
51
- *
52
- * Throws at module init if the dep is missing or shaped wrong — that's a
53
- * packaging bug worth failing loudly on, not a runtime condition.
54
- */
55
- function readMinAdVersion(): string {
56
- const moduleDir = dirname(fileURLToPath(import.meta.url))
57
- // src/agent-director-client.ts → package.json lives one level up
58
- const pkgPath = join(moduleDir, '..', 'package.json')
59
- const raw = readFileSync(pkgPath, 'utf-8')
60
- const pkg = JSON.parse(raw) as { dependencies?: Record<string, string> }
61
- const range = pkg.dependencies?.['agent-director']
62
- if (typeof range !== 'string' || range.length === 0) {
63
- throw new Error(
64
- `agent-director-client: package.json dependencies['agent-director'] is missing or empty — cannot derive MIN_AD_VERSION`,
65
- )
66
- }
67
- // Strip leading semver operators: ^, ~, >=, >, =, v. Anything left should
68
- // parse as semver; we don't validate further here — the SR-5.1 version gate
69
- // does the actual comparison.
70
- const stripped = range.replace(/^[\^~]|^>=|^>|^=/, '').replace(/^v/, '').trim()
71
- if (stripped.length === 0) {
72
- throw new Error(
73
- `agent-director-client: dependencies['agent-director']=${range} reduced to empty string after stripping operators`,
74
- )
75
- }
76
- return stripped
77
- }
78
-
79
- /** Minimum agent-director version CSCB requires at runtime (SR-5.3). */
80
- export const MIN_AD_VERSION: string = readMinAdVersion()
81
-
82
46
  // ---------------------------------------------------------------------------
83
47
  // Singleton state
84
48
  // ---------------------------------------------------------------------------
@@ -86,20 +50,19 @@ export const MIN_AD_VERSION: string = readMinAdVersion()
86
50
  let singleton: Client | null = null
87
51
 
88
52
  /**
89
- * Return the singleton Client, lazy-constructing it on first call.
53
+ * Return the singleton Client installed by the SR-5.1 startup gate.
90
54
  *
91
- * Construction is synchronous: all platform / Bun / subprocess-resolution
92
- * errors fire eagerly here per SR-0.1, not at first verb call. Typed `Err*`
93
- * subclasses propagate; the SR-5.1 startup gate is the only intended
94
- * caller-of-record that branches them.
55
+ * This is a sync cached accessor; it does NOT construct the Client. The
56
+ * startup gate (`runAgentDirectorStartupGate`) is responsible for awaiting
57
+ * `Client.create(...)` and installing the result via `setClient`. Calling
58
+ * `getClient()` before the gate has run is a caller-site bug and throws
59
+ * loudly — there is no lazy-construction fallback.
95
60
  */
96
61
  export function getClient(): Client {
97
62
  if (singleton === null) {
98
- singleton = new Client({
99
- storePath: DEFAULT_STORE_PATH,
100
- createIfMissing: true,
101
- logger: console,
102
- })
63
+ throw new Error(
64
+ 'agent-director-client: getClient() called before the startup gate installed a Client — caller-site bug. The startup gate must run first (via runAgentDirectorStartupGate).',
65
+ )
103
66
  }
104
67
  return singleton
105
68
  }
@@ -128,6 +91,17 @@ export function resetClientForTests(): void {
128
91
  singleton = null
129
92
  }
130
93
 
94
+ /**
95
+ * Install a pre-built Client into the singleton slot. Called once by the
96
+ * startup gate (src/agent-director-startup.ts) after `await Client.create(opts)`
97
+ * resolves. Production verb call sites never invoke this — they go through
98
+ * `getClient()`. Lexically distinct from `setClientForTests` so the test
99
+ * helper stays grep-discoverable.
100
+ */
101
+ export function setClient(client: Client): void {
102
+ singleton = client
103
+ }
104
+
131
105
  /**
132
106
  * Test-only helper: install a pre-built Client (typically a stub) as the
133
107
  * singleton. Skip the Client construction path entirely.
@@ -156,9 +130,9 @@ export interface DecideParamsWithToken extends ADDecideParams {
156
130
  }
157
131
 
158
132
  /**
159
- * Always-include-token decide wrapper. MIN_AD_VERSION is now pinned at
160
- * `^0.6.0`, which carries `request_token` on `DecideParams` natively. The
161
- * structural cast is retained because, until the lockfile is refreshed to
133
+ * Always-include-token decide wrapper. The `agent-director` package.json pin
134
+ * is at `^0.6.0`+, which carries `request_token` on `DecideParams` natively.
135
+ * The structural cast is retained because, until the lockfile is refreshed to
162
136
  * resolve the bumped pin, the imported `DecideParams` type still comes from
163
137
  * the locked `0.5.6` package — same lockfile-lag pattern as
164
138
  * `GetResultWithPermissionRequests`.
@@ -201,13 +175,14 @@ export function isErrPermissionRequestNotFound(err: unknown): boolean {
201
175
  }
202
176
 
203
177
  /**
204
- * `get-permission` wrapper (SR-7.1). MIN_AD_VERSION is pinned at `^0.6.0`,
205
- * which carries the verb; the SR-6.1 startup gate is the compatibility
206
- * boundary that keeps stale-version installs from reaching this path. The
207
- * wrapper takes a structural client (rather than `Pick<Client, 'getPermission'>`)
208
- * because the locked `0.5.6` types do not yet expose the method shape, and
209
- * fails loudly at runtime when the verb is missing as defense-in-depth for
210
- * the dev/test edge (e.g. stub clients that omit it on purpose).
178
+ * `get-permission` wrapper (SR-7.1). The `agent-director` package.json pin is
179
+ * at `^0.6.0`+, which carries the verb; the SR-6.1 startup gate is the
180
+ * compatibility boundary that keeps stale-version installs from reaching this
181
+ * path. The wrapper takes a structural client (rather than
182
+ * `Pick<Client, 'getPermission'>`) because the locked `0.5.6` types do not yet
183
+ * expose the method shape, and fails loudly at runtime when the verb is
184
+ * missing as defense-in-depth for the dev/test edge (e.g. stub clients that
185
+ * omit it on purpose).
211
186
  */
212
187
  export async function getPermission(
213
188
  client: { getPermission?: (params: GetPermissionParams) => Promise<GetPermissionResult> },
@@ -216,7 +191,7 @@ export async function getPermission(
216
191
  if (typeof client.getPermission !== 'function') {
217
192
  throw new Error(
218
193
  'agent-director-client: getPermission verb unavailable — ' +
219
- 'confirm installed agent-director version meets the MIN_AD_VERSION pin',
194
+ 'confirm installed agent-director version meets the package.json pin',
220
195
  )
221
196
  }
222
197
  return client.getPermission(params)
@@ -7,10 +7,10 @@
7
7
  * keep the subset list in sync with SRD edits.
8
8
  *
9
9
  * Catalog (SR-0.2):
10
- * - ErrUnsupportedPlatform (Client constructor / platform gate)
11
10
  * - ErrBunVersionTooOld (Client constructor / Bun version gate)
12
- * - ErrPlatformPackageMissing (Client constructor / @agent-director/<plat>)
13
- * - ErrCliNotExecutable (Client constructor / CLI binary lacks +x)
11
+ * - ErrSystemInstallNotFound (Client.create / resolveSystemBinary — no `agent-director` on PATH or at ~/.agent-director)
12
+ * - ErrSystemInstallTooOld (Client.create / resolveSystemBinary — system binary older than required minimum)
13
+ * - ErrSystemInstallUnreachable (Client.create / resolveSystemBinary — system binary present but not executable or fails --version)
14
14
  * - ErrInstanceIdCollision (spawn / SR-1.4 idempotency)
15
15
  * - ErrSpawnNotFound (get / status / decide on missing row)
16
16
  * - ErrNoSessionId (resume / SR-1.3 fallthrough)
@@ -37,10 +37,10 @@
37
37
  export {
38
38
  AgentDirectorError,
39
39
  ErrClientClosed,
40
- ErrUnsupportedPlatform,
41
- ErrPlatformPackageMissing,
42
40
  ErrBunVersionTooOld,
43
- ErrCliNotExecutable,
41
+ ErrSystemInstallNotFound,
42
+ ErrSystemInstallTooOld,
43
+ ErrSystemInstallUnreachable,
44
44
  ErrCallTimeout,
45
45
  ErrInstanceIdCollision,
46
46
  ErrSpawnNotFound,