claude-slack-channel-bots 0.18.0 → 0.18.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.
Files changed (118) hide show
  1. package/docs/agent-director.md +2 -2
  2. package/docs/bots.md +8 -4
  3. package/docs/configuration.md +1 -1
  4. package/docs/migration.md +2 -2
  5. package/docs/scheduled-prompts.md +4 -4
  6. package/package.json +1 -1
  7. package/scripts/install-check.ts +5 -5
  8. package/scripts/write-credentials.sh +1 -1
  9. package/skills/debug-slack-channel-bots/SKILL.md +327 -327
  10. package/skills/setup-slack-channel-bots/SKILL.md +2 -2
  11. package/src/ack-tracker.ts +1 -1
  12. package/src/ad-config-file.ts +2 -2
  13. package/src/ad-description-phrases.ts +24 -25
  14. package/src/ad-error-class.ts +28 -30
  15. package/src/ad-phase1-types.ts +4 -5
  16. package/src/ad-settings.ts +36 -37
  17. package/src/ad-version-gate.ts +71 -78
  18. package/src/agent-director-client.ts +16 -16
  19. package/src/agent-director-errors.ts +23 -25
  20. package/src/agent-director-logger.ts +3 -3
  21. package/src/agent-director-startup.ts +22 -24
  22. package/src/agent-director-template.ts +24 -22
  23. package/src/atomic-write.ts +5 -5
  24. package/src/backoff.ts +3 -3
  25. package/src/bot-system-prompt.ts +1 -1
  26. package/src/channel-delivery.ts +71 -72
  27. package/src/checked-kill.ts +54 -54
  28. package/src/clear-latch.ts +6 -6
  29. package/src/cli-teardown.ts +64 -75
  30. package/src/cli.ts +138 -149
  31. package/src/codex-config-keys.ts +2 -2
  32. package/src/config.ts +170 -179
  33. package/src/conflict-latch.ts +114 -119
  34. package/src/cron-bootstrap.ts +2 -2
  35. package/src/cron-dispatch.ts +7 -7
  36. package/src/cron-log.ts +15 -16
  37. package/src/cron-scheduler.ts +10 -11
  38. package/src/crontable.ts +4 -4
  39. package/src/delivery-ad-scope.ts +1 -1
  40. package/src/delivery-constants.ts +1 -1
  41. package/src/delivery-decision.ts +36 -39
  42. package/src/delivery-engine.ts +6 -6
  43. package/src/delivery-intake.ts +5 -5
  44. package/src/delivery-lifecycle.ts +1 -1
  45. package/src/delivery-notices.ts +2 -2
  46. package/src/delivery-policy.ts +1 -1
  47. package/src/delivery-queue.ts +5 -5
  48. package/src/delivery-receipt.ts +3 -3
  49. package/src/health-check.ts +68 -69
  50. package/src/install-check-labels.ts +2 -3
  51. package/src/install-check.ts +9 -11
  52. package/src/install-skill-pointer.ts +2 -2
  53. package/src/interject.ts +2 -2
  54. package/src/invalid-flags-hold.ts +27 -28
  55. package/src/json-position.ts +2 -2
  56. package/src/jsonl-persistence-check.ts +9 -9
  57. package/src/kill-failure-alert.ts +38 -38
  58. package/src/kill-retry.ts +30 -31
  59. package/src/lib.ts +1 -1
  60. package/src/live-row-sequence.ts +146 -150
  61. package/src/liveness-reading.ts +15 -15
  62. package/src/logging.ts +1 -1
  63. package/src/lost-message.ts +9 -10
  64. package/src/message-archive.ts +2 -2
  65. package/src/old-life-wait.ts +32 -33
  66. package/src/outage-state.ts +99 -106
  67. package/src/pane-read.ts +14 -15
  68. package/src/pending-row.ts +122 -133
  69. package/src/permission-click-handler.ts +33 -33
  70. package/src/permission-poller.ts +116 -118
  71. package/src/permission-trail.ts +21 -23
  72. package/src/persona-bringup-controller.ts +48 -48
  73. package/src/persona-bringup.ts +9 -10
  74. package/src/persona-connection-errors.ts +2 -2
  75. package/src/persona-connections.ts +31 -31
  76. package/src/persona-credentials.ts +12 -12
  77. package/src/persona-destination-hold.ts +22 -29
  78. package/src/persona-destination.ts +28 -28
  79. package/src/persona-diagnostics.ts +32 -34
  80. package/src/persona-episodes.ts +118 -126
  81. package/src/persona-event-router.ts +7 -8
  82. package/src/persona-identity.ts +20 -22
  83. package/src/persona-lifecycle.ts +107 -111
  84. package/src/persona-notifier.ts +42 -49
  85. package/src/persona-retry-schedule.ts +9 -9
  86. package/src/persona-routing.ts +42 -43
  87. package/src/persona-serializer.ts +4 -4
  88. package/src/persona-slack-clients.ts +4 -4
  89. package/src/persona-slack-episodes.ts +4 -4
  90. package/src/persona-slack-validation.ts +17 -18
  91. package/src/persona-start.ts +17 -18
  92. package/src/persona-web-api-watch.ts +2 -2
  93. package/src/pid.ts +1 -1
  94. package/src/postinstall.ts +9 -9
  95. package/src/registry.ts +75 -85
  96. package/src/reload-apply.ts +15 -15
  97. package/src/reload-fingerprint.ts +6 -6
  98. package/src/reload-plan.ts +66 -70
  99. package/src/reload-preview-clauses.ts +5 -5
  100. package/src/reload-timer.ts +3 -3
  101. package/src/reload.ts +115 -120
  102. package/src/restart.ts +290 -300
  103. package/src/retired-keys.ts +110 -113
  104. package/src/row-read-rules.ts +24 -25
  105. package/src/server.ts +414 -425
  106. package/src/session-manager.ts +1852 -1957
  107. package/src/shutdown-deadline.ts +1 -1
  108. package/src/slack-log-redaction.ts +1 -1
  109. package/src/slow-recovery.ts +12 -13
  110. package/src/startup-errors.ts +1 -1
  111. package/src/startup-summary-ending.ts +3 -3
  112. package/src/state-dir-migration.ts +16 -16
  113. package/src/tag-description.ts +1 -1
  114. package/src/tag-wrapper.ts +4 -4
  115. package/src/test-mcp-drop.ts +1 -1
  116. package/src/test-timer-overrides.ts +1 -1
  117. package/src/tokens.ts +1 -1
  118. package/src/unavailable-retry.ts +193 -210
@@ -155,13 +155,13 @@ At agent-director's defaults, `pause` sets the need: its 9 s plus 30 s is 39 s,
155
155
  **The startup warning.** Once per start, right after the server reads agent-director's settings and before any persona is brought up, the server writes one line to `server.log` when the setting is at or below the need:
156
156
 
157
157
  ```text
158
- [slack] agent-director settings: agent_director_call_timeout_ms is <value>, at or below its need of <need> ms (the <verb> ceiling plus the 15000 ms margin): a call can time out while its verb still acts; see the switch-over runbook in docs/migration.md, section "Switching over to agent-director Phase 1" (b.jg5 SRJ-213)
158
+ [slack] agent-director settings: agent_director_call_timeout_ms is <value>, at or below its need of <need> ms (the <verb> ceiling plus the 15000 ms margin): a call can time out while its verb still acts; see the switch-over runbook in docs/migration.md, section "Switching over to agent-director Phase 1"
159
159
  ```
160
160
 
161
161
  `<verb>` names the row whose ceiling sets the need: its verb, or `resume/spawn-with-reuse/plain-spawn` for the launch row those three share. When `[pause] timeout_seconds` holds a value that is not used, the line is this one instead, whatever the setting is:
162
162
 
163
163
  ```text
164
- [slack] agent-director settings: agent_director_call_timeout_ms is <value>; its need is unknown: [pause] timeout_seconds holds <found>, a value that is not used, so pause's wait is not counted and the need without it is <need> ms; see the switch-over runbook in docs/migration.md, section "Switching over to agent-director Phase 1" (b.jg5 SRJ-213)
164
+ [slack] agent-director settings: agent_director_call_timeout_ms is <value>; its need is unknown: [pause] timeout_seconds holds <found>, a value that is not used, so pause's wait is not counted and the need without it is <need> ms; see the switch-over runbook in docs/migration.md, section "Switching over to agent-director Phase 1"
165
165
  ```
166
166
 
167
167
  `<found>` is the number (for example `0`) or the kind of value, never the file's text. At agent-director's defaults, the default `60000` writes no line; a setting of `54000` writes the first line, naming `pause`.
package/docs/bots.md CHANGED
@@ -106,13 +106,17 @@ Each persona's Slack app must have **interactivity enabled** with **Socket Mode*
106
106
 
107
107
  ### AskUserQuestion
108
108
 
109
- The `AskUserQuestion` tool is denied for every CSCB-spawned bot via the agent-director template (`deny: ['AskUserQuestion']`). Bots respond to operator questions via the Slack `reply` MCP tool instead. There is no `ask-relay.sh` hook and no `/ask` HTTP endpoint.
109
+ For fresh or reuse Claude launches, the agent-director template denies `AskUserQuestion` (`deny: ['AskUserQuestion']`). Bots respond to operator questions via the Slack `reply` MCP tool instead. There is no `ask-relay.sh` hook and no `/ask` HTTP endpoint.
110
110
 
111
- The template pre-allows `mcp__slack-channel-router__reply`, so a newly spawned Claude persona can answer a reply reminder without human approval. This grants only the reply tool; other tool approvals still follow the permission relay. Template refreshes preserve this rule.
111
+ Fresh or reuse Claude launches save the exact `mcp__slack-channel-router__reply` allowance in their launch arguments, so it is retained on resume. Deny rules and managed restrictions still take priority; other tool approvals follow the existing permission relay. Template refreshes preserve this reply rule for subsequent launches.
112
+
113
+ Agent-director resume does not restore the template's `AskUserQuestion` denial or memory-read allowances; only the exact reply allowance is also saved in launch arguments. Independently configured permission rules and managed restrictions still apply.
112
114
 
113
115
  ### Memory-directory reads
114
116
 
115
- The template also pre-allows each bot to read its own persistent-memory directory, so those reads don't surface a permission prompt to a human. One `Read(//<config-dir>/projects/*/memory/**)` rule is derived per distinct Claude config directory across your personas (a persona's own `claude_config_dir`, the top-level `claude_config_dir`, or the `~/.claude` default). The rules follow the applied personas: when a confirmed change alters the set of config directories, the server rewrites them. If that rewrite fails, `server.log` shows a `template refresh: … failed` line. Until the directories change again or the server restarts, a persona using a new directory then asks for permission each time it reads its memory notes. The rule is scoped to `projects/*/memory/**` only — never the config-dir root, which holds live credentials — so it never pre-authorizes credential reads.
117
+ On fresh or reuse Claude launches, the template also pre-allows each persona to read its own persistent-memory directory, subject to deny rules and managed restrictions. One `Read(//<config-dir>/projects/*/memory/**)` rule is derived per distinct Claude config directory across your personas (a persona's own `claude_config_dir`, the top-level `claude_config_dir`, or the `~/.claude` default). The rules follow the applied personas: when a confirmed change alters the set of config directories, the server rewrites them.
118
+
119
+ If that rewrite fails, `server.log` shows a `template refresh: … failed` line. Until the directories change again or the server restarts, a persona using a new directory may need permission to read its memory notes, depending on independently configured rules. The rule is scoped to `projects/*/memory/**` only — never the config-dir root, which holds live credentials — so it never pre-authorizes credential reads.
116
120
 
117
121
  ---
118
122
 
@@ -171,7 +175,7 @@ You received a Slack message and you haven't replied. If you meant to answer in
171
175
 
172
176
  The persona can reply or end its turn. There is at most one reminder per delivered Slack message, including across server restarts. Both Claude and Codex personas are covered, regardless of `claude_config_dir`; no `jq` installation is needed.
173
177
 
174
- Claude conversations launched before the reply permission was added receive no new reminders. Resuming a conversation preserves its saved permissions, so a server restart or resume alone does not enable reminders for those older conversations. New Claude launches carry the reply permission and a `reply_tool_preallowed=1` agent-director label; reminders require that label. Existing conversations continue receiving ordinary messages.
178
+ Claude reminders require the `reply_tool_preallowed=1` agent-director label; conversations without it receive no new reminders. An existing label alone does not prove that the conversation's saved launch arguments include the reply allowance. Updating the template leaves existing conversations and their saved arguments unchanged; ordinary fresh or reuse launches obtain the current rule, and existing conversations continue receiving ordinary messages.
175
179
 
176
180
  Only Slack deliveries arm reminders. Scheduled prompts, `/interject` messages and reminders themselves do not. A `reply` call by that persona suppresses the reminder even if posting fails or the call targets another conversation. Replies through another tool or service can therefore be followed by one harmless reminder.
177
181
 
@@ -113,7 +113,7 @@ The key is used for:
113
113
 
114
114
  **No persona's key may start with another persona's key.** The server rejects such a pair when it checks the configuration (see [Load-time rules](#load-time-rules)), with an error that names both personas and suggests a new name. tmux matches a session target by prefix unless it is written with `=`, so a human's tmux command without `=` for one persona (for example `tmux attach -t slack_bot_dev`) could reach another persona's session. With personas `dev` and `dev_2`, that command could reach `slack_bot_dev_2`.
115
115
 
116
- Give the shorter name a suffix, such as `dev_main` beside `dev_2`, or `horde_main` beside `horde_admin`, or rename either so that neither key starts with the other. Keys that only share a start, such as `dev_a` and `dev_b`, are fine. A name that isn't its own key counts by its key: `"Dev Bot"` (key `dev_bot_…`) can't sit beside `dev` either.
116
+ Give the shorter name a suffix, such as `dev_main` beside `dev_2`, or `team_main` beside `team_admin`, or rename either so that neither key starts with the other. Keys that only share a start, such as `dev_a` and `dev_b`, are fine. A name that isn't its own key counts by its key: `"Dev Bot"` (key `dev_bot_…`) can't sit beside `dev` either.
117
117
 
118
118
  Renaming a persona changes its key, so the old persona is removed and a new one added (see [What a confirmation applies](reload.md#what-a-confirmation-applies)).
119
119
 
package/docs/migration.md CHANGED
@@ -280,7 +280,7 @@ After upgrading, every bot starts one fresh conversation; memory files are kept.
280
280
  This major version accepts only the persona configuration format. These are the configuration steps of an upgrade from an earlier major version. Do them inside the switch-over runbook, not on their own: steps 1, 2, 3, 5 and 6 (the persona file, names, reply settings, Slack apps and who can reach each persona) at [step 1 of the switch-over](#step-1-check-the-host-and-stage-the-release), and steps 4, 7 and 8 (credentials files, crontable and `/interject` callers) at [step 7 of the switch-over](#step-7-install-the-new-cscb-without-starting-it). At switch-over step 1, these steps are written into the separate staged file, not `config.json`; step 7 puts that file in place as `config.json`. Until the new CSCB's first start, the new CLI keeps using the old state directory, `~/.claude/channels/slack`, so the persona `config.json`, the credentials files and the crontable go there; the first start moves that directory to `~/.config/claude-slack-channel-bots`.
281
281
 
282
282
  1. **Rewrite `config.json` by hand.** A configuration from an earlier major version stops the server at start, with an error that names the offending setting and says the configuration must be converted to personas. Nothing is converted automatically and the file is not changed. Write a `personas` list as described in [Personas (config.json)](configuration.md#personas-configjson); the server-wide settings keep their names. The `debug-slack-channel-bots` skill covers this error under "Pre-persona configuration".
283
- 2. **Pick persona names whose keys don't start with one another.** The configuration check rejects such a pair. If your bots were named `horde`, `horde_admin`, …, don't name a persona `horde` beside `horde_admin`: give the shorter name a suffix, such as `horde_main` (see [Persona name and key](configuration.md#persona-name-and-key)).
283
+ 2. **Pick persona names whose keys don't start with one another.** The configuration check rejects such a pair. If your bots were named `team`, `team_admin`, …, don't name a persona `team` beside `team_admin`: give the shorter name a suffix, such as `team_main` (see [Persona name and key](configuration.md#persona-name-and-key)).
284
284
  3. **Set the reply settings in `config.json`.** Choose top-level `queued_ack_reaction` and `ack_reaction`, or use their defaults after checking both emoji exist in the Slack workspace; custom emoji must exist before configuration. See [Acknowledgement reactions](server-settings.md#acknowledgement-reactions). If you had changed how replies are split, set `reply_chunk_limit` and `reply_chunk_mode` there too.
285
285
  4. **Move the tokens into credentials files.** Tokens come only from each persona's credentials file. Create one [credentials file](configuration.md#credentials-files) per persona, then remove any token environment variables you exported for the previous version.
286
286
  5. **Give each persona its own Slack app.** Your existing app can serve one persona; create another app for each additional persona. Add the `im:write`, `channels:read` and `groups:read` bot scopes to the existing app and re-install it; the `debug-slack-channel-bots` skill has the steps under "A persona can't open a DM" and "The message archive shows channel IDs".
@@ -301,7 +301,7 @@ Earlier releases ignore this release’s queue and can resume a bot without thei
301
301
 
302
302
  ---
303
303
 
304
- ## Upgrading from pre-Epic-2 (v0.5.x → v0.6.x)
304
+ ## Upgrading from pre-v0.6 (v0.5.x → v0.6.x)
305
305
 
306
306
  If you installed CSCB before v0.6.0 you may have legacy artifacts on disk that are no longer needed. Clean them up by hand; no install step removes them.
307
307
 
@@ -46,16 +46,16 @@ On first boot the server auto-creates the crontable with this self-documenting h
46
46
  # skipped on its own; sibling lines still schedule.
47
47
  #
48
48
  # Example (every day at 09:00, run grooming-tick.md, target two personas):
49
- # 0 9 * * * /home/horde/prompts/grooming-tick.md planner,reviewer
49
+ # 0 9 * * * ~/prompts/grooming-tick.md planner,reviewer
50
50
  #
51
51
  # Example (every hour, run standup.md, no persona list — NOT delivered yet):
52
- # 0 * * * * /home/horde/prompts/standup.md
52
+ # 0 * * * * ~/prompts/standup.md
53
53
  ```
54
54
 
55
55
  Each schedule is one line of **exactly 5 cron fields**, then the prompt-file path, then an optional comma-separated list of personas, each written as the persona's name or its key:
56
56
 
57
57
  ```
58
- 0 9 * * 1 /home/horde/prompts/weekly-report.md planner,reviewer
58
+ 0 9 * * 1 ~/prompts/weekly-report.md planner,reviewer
59
59
  ```
60
60
 
61
61
  Rules:
@@ -117,7 +117,7 @@ Each load of the crontable, at start and after each edit, writes one line with i
117
117
  Each load also writes one `warn` line for each line with no persona list, naming its line number in the file and its prompt path:
118
118
 
119
119
  ```text
120
- 2026-10-09T15:12:00.002Z cscb-cron:grooming - warn line=34 prompt=/home/horde/prompts/grooming.md undeliverable: this crontable line names no personas, so it will never be delivered in this version …
120
+ 2026-10-09T15:12:00.002Z cscb-cron:grooming - warn line=34 prompt=~/prompts/grooming.md undeliverable: this crontable line names no personas, so it will never be delivered in this version …
121
121
  ```
122
122
 
123
123
  Add a persona list to that line. The warning comes back at every start and every edit until you do; an unchanged crontable is not reloaded, so it is not repeated each minute. To list them in the cron log at its default location:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-slack-channel-bots",
3
- "version": "0.18.0",
3
+ "version": "0.18.1",
4
4
  "description": "Run several Claude Code personas, each its own Slack app, from one server via Socket Mode",
5
5
  "type": "module",
6
6
  "bin": {
@@ -2,13 +2,13 @@
2
2
  /**
3
3
  * scripts/install-check.ts — `bun run install-check` entry point.
4
4
  *
5
- * SR-6: standalone diagnostic command. Calls runInstallCheck() once,
5
+ * standalone diagnostic command. Calls runInstallCheck once,
6
6
  * renders the result to stdout (success) or stderr (failure), and exits
7
7
  * with the appropriate code.
8
8
  *
9
9
  * Success (exit 0) prints the OK block (binary, version, the client's
10
10
  * minimum). When the binary is below CSCB's Phase 1 floor, the result carries
11
- * the Phase 1 note (b.jg5 SRJ-212) and the block ends with it: the server
11
+ * the Phase 1 note and the block ends with it: the server
12
12
  * refuses to start on that binary until agent-director Phase 1 is installed,
13
13
  * see the switch-over runbook section. A binary that meets the floor prints
14
14
  * the block alone. The note line's label is `INSTALL_CHECK_NOTE_LABEL`.
@@ -34,8 +34,8 @@ import { renderInstallSkillInstructions } from '../src/install-skill-pointer.ts'
34
34
 
35
35
  /**
36
36
  * The label the OK block's Phase 1 note line starts with, after its indent
37
- * (b.jg5 SRJ-212). The install skill relays the note found under this label
38
- * (SRJ-1110).
37
+ * The install skill relays the note found under this label
38
+ *
39
39
  */
40
40
  export const INSTALL_CHECK_NOTE_LABEL = 'note:'
41
41
 
@@ -73,7 +73,7 @@ export async function main(): Promise<void> {
73
73
  }
74
74
 
75
75
  let body = renderFailure(result)
76
- // SR-6.3: append the manual-skill-install block to every failure class
76
+ // append the manual-skill-install block to every failure class
77
77
  // EXCEPT ad-version-floor-unreadable (the skill can't fix a corrupt AD
78
78
  // package; remediation is checking the agent-director npm package
79
79
  // installed with CSCB, with the switch-over runbook section).
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env bash
2
2
  # scripts/write-credentials.sh — write one persona's credentials file from the
3
- # operator's own terminal (b.av2 SR-12, SR-1.4 part).
3
+ # operator's own terminal (part).
4
4
  #
5
5
  # Usage: write-credentials.sh <credentials file path>
6
6
  #