crewhaus 0.1.7 → 0.2.0

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 (136) hide show
  1. package/README.md +10 -3
  2. package/dist/advice-apply.d.ts +182 -0
  3. package/dist/advice-apply.js +286 -0
  4. package/dist/advise-rules.d.ts +348 -0
  5. package/dist/advise-rules.js +905 -0
  6. package/dist/alert-sink.d.ts +48 -0
  7. package/dist/alert-sink.js +86 -0
  8. package/dist/approval-gate.d.ts +127 -0
  9. package/dist/approval-gate.js +254 -0
  10. package/dist/audit-verify.d.ts +69 -0
  11. package/dist/audit-verify.js +97 -0
  12. package/dist/autodistill.d.ts +113 -0
  13. package/dist/autodistill.js +256 -0
  14. package/dist/channel-provision.d.ts +360 -0
  15. package/dist/channel-provision.js +881 -0
  16. package/dist/ci-scaffold.d.ts +31 -0
  17. package/dist/ci-scaffold.js +343 -0
  18. package/dist/compile-check.d.ts +90 -0
  19. package/dist/compile-check.js +285 -0
  20. package/dist/compliance-schedule.d.ts +35 -0
  21. package/dist/compliance-schedule.js +36 -0
  22. package/dist/context-pressure.d.ts +80 -0
  23. package/dist/context-pressure.js +166 -0
  24. package/dist/dataset-mine.d.ts +172 -0
  25. package/dist/dataset-mine.js +403 -0
  26. package/dist/datasets.d.ts +124 -0
  27. package/dist/datasets.js +260 -0
  28. package/dist/deploy-canary.d.ts +83 -0
  29. package/dist/deploy-canary.js +87 -0
  30. package/dist/doctor-checks.d.ts +33 -0
  31. package/dist/doctor-checks.js +92 -0
  32. package/dist/doctor-detect.d.ts +108 -0
  33. package/dist/doctor-detect.js +214 -0
  34. package/dist/doctor-fix.d.ts +81 -0
  35. package/dist/doctor-fix.js +164 -0
  36. package/dist/egress-triage.d.ts +121 -0
  37. package/dist/egress-triage.js +261 -0
  38. package/dist/eval-bridge.d.ts +114 -0
  39. package/dist/eval-bridge.js +158 -0
  40. package/dist/eval-coverage.d.ts +140 -0
  41. package/dist/eval-coverage.js +428 -0
  42. package/dist/eval-history.d.ts +48 -0
  43. package/dist/eval-history.js +157 -0
  44. package/dist/eval-matrix.d.ts +80 -0
  45. package/dist/eval-matrix.js +182 -0
  46. package/dist/eval-sentinel.d.ts +65 -0
  47. package/dist/eval-sentinel.js +132 -0
  48. package/dist/faq.d.ts +68 -0
  49. package/dist/faq.js +168 -0
  50. package/dist/feedback.d.ts +246 -0
  51. package/dist/feedback.js +612 -0
  52. package/dist/fewshot.d.ts +83 -0
  53. package/dist/fewshot.js +158 -0
  54. package/dist/fleet.d.ts +207 -0
  55. package/dist/fleet.js +488 -0
  56. package/dist/flywheel.d.ts +193 -0
  57. package/dist/flywheel.js +519 -0
  58. package/dist/graders-suggest.d.ts +186 -0
  59. package/dist/graders-suggest.js +658 -0
  60. package/dist/incident.d.ts +99 -0
  61. package/dist/incident.js +217 -0
  62. package/dist/index.d.ts +9 -1
  63. package/dist/index.js +11727 -740
  64. package/dist/init-interactive.d.ts +105 -0
  65. package/dist/init-interactive.js +208 -0
  66. package/dist/intents.d.ts +105 -0
  67. package/dist/intents.js +292 -0
  68. package/dist/judge-calibrate.d.ts +137 -0
  69. package/dist/judge-calibrate.js +247 -0
  70. package/dist/justification-calibrate.d.ts +150 -0
  71. package/dist/justification-calibrate.js +262 -0
  72. package/dist/justification-gate.d.ts +27 -6
  73. package/dist/justification-gate.js +30 -6
  74. package/dist/knowledge-sync.d.ts +179 -0
  75. package/dist/knowledge-sync.js +551 -0
  76. package/dist/lessons.d.ts +87 -0
  77. package/dist/lessons.js +207 -0
  78. package/dist/lint.d.ts +127 -0
  79. package/dist/lint.js +226 -0
  80. package/dist/loadtest.d.ts +114 -0
  81. package/dist/loadtest.js +196 -0
  82. package/dist/marketplace-cli.d.ts +110 -0
  83. package/dist/marketplace-cli.js +250 -0
  84. package/dist/mcp-doctor.d.ts +121 -0
  85. package/dist/mcp-doctor.js +249 -0
  86. package/dist/model-scan.d.ts +116 -0
  87. package/dist/model-scan.js +226 -0
  88. package/dist/onchain-tune.d.ts +164 -0
  89. package/dist/onchain-tune.js +346 -0
  90. package/dist/permissions-suggest.d.ts +126 -0
  91. package/dist/permissions-suggest.js +333 -0
  92. package/dist/pii-tune.d.ts +107 -0
  93. package/dist/pii-tune.js +122 -0
  94. package/dist/propose.d.ts +117 -0
  95. package/dist/propose.js +184 -0
  96. package/dist/refresh-goldens.d.ts +82 -0
  97. package/dist/refresh-goldens.js +221 -0
  98. package/dist/regression-pin.d.ts +160 -0
  99. package/dist/regression-pin.js +281 -0
  100. package/dist/retention.d.ts +193 -0
  101. package/dist/retention.js +607 -0
  102. package/dist/retire.d.ts +118 -0
  103. package/dist/retire.js +291 -0
  104. package/dist/right-size.d.ts +100 -0
  105. package/dist/right-size.js +123 -0
  106. package/dist/scaffold-evals.d.ts +138 -0
  107. package/dist/scaffold-evals.js +410 -0
  108. package/dist/scope-audit-drift.d.ts +139 -0
  109. package/dist/scope-audit-drift.js +260 -0
  110. package/dist/security-corpus.d.ts +237 -0
  111. package/dist/security-corpus.js +516 -0
  112. package/dist/security-digest.d.ts +173 -0
  113. package/dist/security-digest.js +650 -0
  114. package/dist/sessions-index.d.ts +27 -0
  115. package/dist/sessions-index.js +51 -0
  116. package/dist/slo-doctor.d.ts +67 -0
  117. package/dist/slo-doctor.js +119 -0
  118. package/dist/slo-sink.d.ts +96 -0
  119. package/dist/slo-sink.js +107 -0
  120. package/dist/spec-changelog.d.ts +102 -0
  121. package/dist/spec-changelog.js +237 -0
  122. package/dist/state-backup.d.ts +223 -0
  123. package/dist/state-backup.js +648 -0
  124. package/dist/tools-cli.d.ts +170 -0
  125. package/dist/tools-cli.js +298 -0
  126. package/dist/triage.d.ts +202 -0
  127. package/dist/triage.js +403 -0
  128. package/dist/upgrade.d.ts +57 -0
  129. package/dist/upgrade.js +113 -0
  130. package/dist/version.d.ts +6 -0
  131. package/dist/version.js +27 -0
  132. package/dist/voice-eval.d.ts +138 -0
  133. package/dist/voice-eval.js +309 -0
  134. package/dist/watch.d.ts +58 -0
  135. package/dist/watch.js +97 -0
  136. package/package.json +89 -64
@@ -0,0 +1,360 @@
1
+ import type { IrChannels, IrDiscordConfig, IrSecretRef, IrSlackConfig, IrTelegramConfig } from "@crewhaus/ir";
2
+ /**
3
+ * Item 61 — `crewhaus channel provision|verify`: one-command channel app
4
+ * setup + scope doctor, factored out of the entry file `index.ts` (which
5
+ * runs a top-level argv switch and so cannot be imported by a test without
6
+ * executing the CLI). Side-effect-free on import and directly unit-testable,
7
+ * mirroring `audit-verify.ts` / `security-digest.ts` / `scope-audit-drift.ts`.
8
+ *
9
+ * The problem this closes: channel-bot harnesses assume platform-side
10
+ * configuration the user had to hand-build — a Slack app with the right
11
+ * scopes/event subscriptions, a Telegram webhook registered with the secret
12
+ * the adapter verifies (`channel-adapter-telegram` documents the
13
+ * `setWebhook(secret_token=...)` expectation but nothing performed it), a
14
+ * Discord application pointed at the daemon's interactions endpoint.
15
+ *
16
+ * Everything here is DERIVED from the adapters + the compiled daemon, not
17
+ * guessed (per-platform derivations are documented on the builders below).
18
+ * The one shared fact: the generated gateway routes webhooks by path —
19
+ * `/^\/([^/]+)\/events$/` in target-channel-bot's `renderGateway` — so the
20
+ * platform-side URL is always `<base-url>/<adapterId>/events`.
21
+ *
22
+ * Design decisions:
23
+ * - Slack is EMIT-AND-INSTRUCT only (no `--apply`). Slack's manifest API
24
+ * (`apps.manifest.create`) authenticates with an app *configuration*
25
+ * token; the adapter/spec carry only the bot token (`xoxb`, Bearer for
26
+ * chat.postMessage/reactions.add), the signing secret (HMAC verify), and
27
+ * the reserved Socket-Mode `appToken` (`xapp`) — none of which can call
28
+ * the manifest API, and inventing a new env var for a token family the
29
+ * runtime never uses was ruled out.
30
+ * - Discord's adapter is interactions-endpoint-based (Ed25519-verified
31
+ * webhooks; types 1/2/3/5), NOT gateway-websocket-based — so provision
32
+ * PATCHes `applications/@me` `interactions_endpoint_url` and prints the
33
+ * invite URL with permission bits derived from the adapter's REST usage.
34
+ * Application *commands* are not registered: the spec declares no
35
+ * command list and the adapter accepts ANY command name (it renders
36
+ * `/<name> <options>` into the agent turn), so command names cannot be
37
+ * derived without guesswork — provision prints the registration
38
+ * instruction instead.
39
+ * - All network calls go through an injectable `fetchImpl` so tests are
40
+ * credential-free, and every network-performing path has a dry-run
41
+ * counterpart (`display` plans / `describeVerifyProbes`) that renders
42
+ * env refs as `$NAME` and literals as `[redacted]` — never the value.
43
+ */
44
+ /** Platforms `channel provision|verify` supports. whatsapp (Meta app config
45
+ * lives in the Meta developer console) and imessage (host-local chat.db —
46
+ * there is no platform side to provision) are out of item-61 scope; when a
47
+ * spec configures them the CLI prints a note instead of failing. */
48
+ export declare const CHANNEL_PLATFORMS: readonly ["slack", "telegram", "discord"];
49
+ export type ChannelPlatform = (typeof CHANNEL_PLATFORMS)[number];
50
+ export type FetchLike = typeof fetch;
51
+ /** Placeholder for an inline-literal secret in printable output — mirrors
52
+ * `packages/ir/src/redact.ts`'s `REDACTED_VALUE` convention. */
53
+ export declare const REDACTED_LITERAL = "[redacted]";
54
+ /** Thrown on a malformed/unconfigured `--platform` value. The CLI entry file
55
+ * catches it and routes the message through `die()`. */
56
+ export declare class InvalidPlatformFlagError extends Error {
57
+ readonly name = "InvalidPlatformFlagError";
58
+ }
59
+ /** Thrown when a secret env-ref (`$VAR_NAME` in the spec) is unset at the
60
+ * moment a REAL platform call needs its value. Dry-run paths never throw
61
+ * this — they print the `$VAR_NAME` placeholder instead. */
62
+ export declare class ChannelEnvRefError extends Error {
63
+ readonly label: string;
64
+ readonly envName: string;
65
+ readonly name = "ChannelEnvRefError";
66
+ constructor(label: string, envName: string);
67
+ }
68
+ /** Thrown on a failed platform API call (non-2xx or a logical `ok: false`).
69
+ * Messages are built from REDACTED endpoints — never the token-bearing URL. */
70
+ export declare class ChannelApiError extends Error {
71
+ readonly name = "ChannelApiError";
72
+ }
73
+ /** Thrown on a malformed `--base-url`. */
74
+ export declare class InvalidBaseUrlError extends Error {
75
+ readonly name = "InvalidBaseUrlError";
76
+ constructor(value: string, detail: string);
77
+ }
78
+ /**
79
+ * Resolve the `--platform` flag against the spec's configured channels.
80
+ * `all` (or an absent flag) selects every configured platform this command
81
+ * supports; an explicit platform must actually be configured in the spec —
82
+ * provisioning a channel the daemon will never serve is a footgun, not a
83
+ * convenience. `unsupported` lists configured channels outside item-61
84
+ * scope (whatsapp/imessage) so the CLI can print a note.
85
+ */
86
+ export declare function resolvePlatformsFlag(flagValue: string | undefined, channels: IrChannels): {
87
+ readonly platforms: ReadonlyArray<ChannelPlatform>;
88
+ readonly unsupported: ReadonlyArray<string>;
89
+ };
90
+ /** Resolve a lowered secret ref to its value. Env-refs read `env`; an unset
91
+ * (or empty) env var throws {@link ChannelEnvRefError} — matching the
92
+ * compiled daemon's own startup check, which exits non-zero on the same
93
+ * condition rather than serving webhooks with an empty secret. */
94
+ export declare function resolveSecretRef(label: string, ref: IrSecretRef, env: NodeJS.ProcessEnv): string;
95
+ /** Printable form of a secret ref: `$NAME` for env-refs (the indirection is
96
+ * not a secret), {@link REDACTED_LITERAL} for inline literals. */
97
+ export declare function describeSecretRef(ref: IrSecretRef): string;
98
+ /** The daemon route the platform must deliver webhooks to. Single source:
99
+ * target-channel-bot's gateway matches `/^\/([^/]+)\/events$/` and looks the
100
+ * captured segment up in its adapter map keyed by adapter id. */
101
+ export declare function channelEventsPath(platform: ChannelPlatform): string;
102
+ /**
103
+ * Join `--base-url` with a daemon route. Validates the base URL parses and
104
+ * is http(s); trailing slashes are normalized so `https://x/` and `https://x`
105
+ * produce the same webhook URL. (Slack, Telegram, and Discord all require a
106
+ * publicly reachable https URL in production — http is tolerated here for
107
+ * local tunnels/tests; the platform rejects it server-side if unsupported.)
108
+ */
109
+ export declare function joinBaseUrl(baseUrl: string, path: string): string;
110
+ /** A missing env-ref surfaced by a provision plan builder: which spec field,
111
+ * which env var. The CLI dies listing these before a live (non-dry-run) call. */
112
+ export type MissingEnvRef = {
113
+ readonly label: string;
114
+ readonly envName: string;
115
+ };
116
+ /**
117
+ * The secret fields a platform's daemon REQUIRES at boot, per
118
+ * target-channel-bot's `requiredEnvNames`: slack botToken + signingSecret
119
+ * (appToken is reserved for a future Socket-Mode path — parsed but unused,
120
+ * so not required), telegram botToken + secretToken, discord applicationId +
121
+ * botToken + publicKeyHex. Shared by the doctor channel check and `verify`.
122
+ */
123
+ export declare function platformSecretRefs(platform: ChannelPlatform, channels: IrChannels): ReadonlyArray<{
124
+ readonly label: string;
125
+ readonly ref: IrSecretRef;
126
+ }>;
127
+ export declare const SLACK_MANIFEST_FILENAME = "slack-app-manifest.yaml";
128
+ export type SlackScope = {
129
+ readonly scope: string;
130
+ readonly reason: string;
131
+ };
132
+ /**
133
+ * Bot scopes derived from `@crewhaus/channel-adapter-slack`'s ACTUAL API
134
+ * usage and parsed event types — not from a generic bot template:
135
+ * - `sendReply` POSTs `chat.postMessage` → chat:write
136
+ * - `react` POSTs `reactions.add` (the generated session-router always
137
+ * attempts 👀/✅/⚠️ status acks) → reactions:write
138
+ * - `parseInbound` handles `app_mention` → app_mentions:read
139
+ * - `parseInbound` handles `message` in any
140
+ * conversation type, so each `message.*` event
141
+ * subscription needs its history scope → channels/groups/im/mpim:history
142
+ * - `parseInbound` normalises `reaction_added` into 👍/👎 `user_feedback`
143
+ * (the v0.1.8 ratings feature), but the generated gateway only
144
+ * dispatches it when the spec sets `feedback.channelReactions` — so
145
+ * reactions:read is requested exactly then → reactions:read
146
+ */
147
+ export declare function deriveSlackScopes(opts: {
148
+ readonly channelReactions: boolean;
149
+ }): ReadonlyArray<SlackScope>;
150
+ /** Event subscriptions matching {@link deriveSlackScopes} — the event types
151
+ * the adapter's `parseInbound` consumes (everything else parses to skip). */
152
+ export declare function deriveSlackBotEvents(opts: {
153
+ readonly channelReactions: boolean;
154
+ }): ReadonlyArray<string>;
155
+ /** A Slack app manifest (api.slack.com/reference/manifests), restricted to
156
+ * the sections the channel daemon needs. */
157
+ export type SlackAppManifest = {
158
+ readonly display_information: {
159
+ readonly name: string;
160
+ readonly description: string;
161
+ };
162
+ readonly features: {
163
+ readonly bot_user: {
164
+ readonly display_name: string;
165
+ readonly always_online: boolean;
166
+ };
167
+ };
168
+ readonly oauth_config: {
169
+ readonly scopes: {
170
+ readonly bot: ReadonlyArray<string>;
171
+ };
172
+ };
173
+ readonly settings: {
174
+ readonly event_subscriptions: {
175
+ readonly request_url: string;
176
+ readonly bot_events: ReadonlyArray<string>;
177
+ };
178
+ readonly org_deploy_enabled: boolean;
179
+ readonly socket_mode_enabled: boolean;
180
+ readonly token_rotation_enabled: boolean;
181
+ };
182
+ };
183
+ /**
184
+ * Build the complete Slack app manifest for a channel spec. The request URL
185
+ * is the compiled daemon's slack route under `--base-url`; `socket_mode` is
186
+ * off because the daemon is a webhook server (the spec's `appToken` is
187
+ * documented as reserved for a future Socket-Mode path).
188
+ */
189
+ export declare function buildSlackManifest(spec: {
190
+ readonly name: string;
191
+ readonly channelReactions: boolean;
192
+ }, baseUrl: string): SlackAppManifest;
193
+ export declare function renderSlackManifestYaml(manifest: SlackAppManifest): string;
194
+ /** Post-manifest instructions. Slack app creation from a manifest is a
195
+ * console flow (no `--apply` — see the module header for why), so the CLI
196
+ * prints exactly what to do with the file it just wrote. */
197
+ export declare function slackNextSteps(cfg: IrSlackConfig, manifestRef: string): ReadonlyArray<string>;
198
+ /** Update kinds the adapter's `parseInbound` actually consumes — its three
199
+ * populated slots are `message`, `edited_message`, and `callback_query`;
200
+ * everything else returns skip, so the webhook shouldn't receive it. */
201
+ export declare const TELEGRAM_ALLOWED_UPDATES: readonly ["message", "edited_message", "callback_query"];
202
+ export type TelegramSetWebhookPayload = {
203
+ readonly url: string;
204
+ readonly secret_token: string;
205
+ readonly allowed_updates: ReadonlyArray<string>;
206
+ };
207
+ export type TelegramProvision = {
208
+ /** Printable call — token/secret rendered as `$NAME` / `[redacted]`. */
209
+ readonly display: {
210
+ readonly endpoint: string;
211
+ readonly payload: TelegramSetWebhookPayload;
212
+ };
213
+ /** The real call. Absent when an env-ref is unset (see `missingEnv`). */
214
+ readonly request?: {
215
+ readonly endpoint: string;
216
+ readonly payload: TelegramSetWebhookPayload;
217
+ };
218
+ readonly missingEnv: ReadonlyArray<MissingEnvRef>;
219
+ };
220
+ /**
221
+ * Build the `setWebhook` call: url = the daemon's `/telegram/events` route
222
+ * under `--base-url`, secret_token = the spec's `secretToken` — the SAME
223
+ * value the adapter compares (timing-safely) against the
224
+ * `X-Telegram-Bot-Api-Secret-Token` header on every inbound POST —
225
+ * allowed_updates = the adapter's three consumed update kinds. The api base
226
+ * honours `TELEGRAM_API_BASE_URL` exactly like the adapter does.
227
+ */
228
+ export declare function buildTelegramProvision(cfg: IrTelegramConfig, baseUrl: string, env: NodeJS.ProcessEnv): TelegramProvision;
229
+ /** Perform the setWebhook POST. Errors carry the REDACTED endpoint (the real
230
+ * one embeds the bot token in its path). Returns Telegram's description. */
231
+ export declare function performTelegramSetWebhook(provision: TelegramProvision, fetchImpl?: FetchLike): Promise<string>;
232
+ /**
233
+ * Invite-URL permission bits derived from the adapter's REST usage — the
234
+ * adapter never opens a gateway websocket, so no presence/guild intents:
235
+ * - `sendReply` POSTs `channels/<id>/messages` → View Channel + Send Messages
236
+ * - threads are first-class (`threadTs` from `channel.parent_id`), and the
237
+ * same POST into a thread channel → Send Messages in Threads
238
+ * - `setTyping` POSTs `channels/<id>/typing` → covered by Send Messages
239
+ */
240
+ export declare const DISCORD_PERMISSIONS: readonly [{
241
+ readonly name: "View Channel";
242
+ readonly bit: 1024;
243
+ }, {
244
+ readonly name: "Send Messages";
245
+ readonly bit: 2048;
246
+ }, {
247
+ readonly name: "Send Messages in Threads";
248
+ readonly bit: 274877906944;
249
+ }];
250
+ export declare const DISCORD_PERMISSION_BITS: number;
251
+ export type DiscordProvision = {
252
+ /** Printable call — token rendered as `Bot $NAME` / `Bot [redacted]`. */
253
+ readonly display: {
254
+ readonly method: "PATCH";
255
+ readonly endpoint: string;
256
+ readonly payload: {
257
+ readonly interactions_endpoint_url: string;
258
+ };
259
+ readonly authorization: string;
260
+ readonly inviteUrl: string;
261
+ };
262
+ /** The real call. Absent when an env-ref is unset (see `missingEnv`). */
263
+ readonly request?: {
264
+ readonly endpoint: string;
265
+ readonly payload: {
266
+ readonly interactions_endpoint_url: string;
267
+ };
268
+ readonly authorization: string;
269
+ };
270
+ /** Invite URL with the RESOLVED application id (needs no secret — the id
271
+ * is public); absent when the id's env-ref is unset. */
272
+ readonly inviteUrl?: string;
273
+ readonly missingEnv: ReadonlyArray<MissingEnvRef>;
274
+ };
275
+ /**
276
+ * Build the interactions-endpoint registration: PATCH `applications/@me`
277
+ * (Bot-token auth — the same token the adapter uses for its REST sends)
278
+ * setting `interactions_endpoint_url` to the daemon's `/discord/events`
279
+ * route. Discord VALIDATES the URL during the PATCH (it sends a PING plus a
280
+ * bad-signature probe), so the daemon must be live at `--base-url` first.
281
+ */
282
+ export declare function buildDiscordProvision(cfg: IrDiscordConfig, baseUrl: string, env: NodeJS.ProcessEnv): DiscordProvision;
283
+ export type DiscordProvisionResult = {
284
+ /** `interactions_endpoint_url` found on the application BEFORE the PATCH
285
+ * (undefined when none was set). */
286
+ readonly previousEndpoint?: string;
287
+ /** True when a different pre-existing endpoint was overwritten (--force). */
288
+ readonly replacedPrevious: boolean;
289
+ };
290
+ /**
291
+ * Perform the registration, read-before-write (adversarial-review F5): GET
292
+ * `applications/@me` first, and if an `interactions_endpoint_url` is already
293
+ * set to something OTHER than the daemon route, refuse to overwrite it
294
+ * unless `force` is set — silently clobbering it would detach whatever
295
+ * service the application currently points at (the same stance as `state
296
+ * restore`, which refuses to overwrite without --force). A 4xx on the PATCH
297
+ * usually means Discord's live endpoint validation failed — surfaced with
298
+ * that hint.
299
+ */
300
+ export declare function performDiscordProvision(provision: DiscordProvision, fetchImpl?: FetchLike, opts?: {
301
+ readonly force?: boolean;
302
+ }): Promise<DiscordProvisionResult>;
303
+ /** Post-registration instructions: the invite URL plus the command-
304
+ * registration note (see the module header for why commands aren't
305
+ * auto-registered: the spec declares none and the adapter accepts any). */
306
+ export declare function discordNextSteps(inviteUrl: string): ReadonlyArray<string>;
307
+ /** Shape shared with `index.ts`'s DoctorCheck and audit-verify's
308
+ * AuditIntegrityCheck (label/pass/warn/reason). */
309
+ export type ChannelCheck = {
310
+ readonly label: string;
311
+ readonly pass: boolean;
312
+ /** warn+pass renders as "~" — informational, never fails verify. */
313
+ readonly warn?: boolean;
314
+ readonly reason?: string;
315
+ };
316
+ export type ChannelVerifyOptions = {
317
+ readonly env: NodeJS.ProcessEnv;
318
+ readonly fetchImpl?: FetchLike;
319
+ /** When set, webhook/endpoint URLs are asserted against the daemon route
320
+ * under this origin; when absent those checks degrade to informational. */
321
+ readonly baseUrl?: string;
322
+ };
323
+ /**
324
+ * Slack probes: `auth.test` with the bot token (identity + reachability),
325
+ * then the token's GRANTED scopes — Slack returns them on every Web API
326
+ * response in the `x-oauth-scopes` header — diffed against the needed set
327
+ * from {@link deriveSlackScopes}. The signing secret is only checked for
328
+ * presence: Slack never exposes it back over the API.
329
+ */
330
+ export declare function verifySlackChannel(cfg: IrSlackConfig, spec: {
331
+ readonly channelReactions: boolean;
332
+ }, opts: ChannelVerifyOptions): Promise<ChannelCheck[]>;
333
+ /**
334
+ * Telegram probes: `getWebhookInfo`, compared against the daemon route.
335
+ * Telegram never returns the configured secret_token (write-only by design),
336
+ * so the secret is checked for presence on the daemon side — the adapter
337
+ * rejects every inbound POST if the two ever diverge, which surfaces as
338
+ * pending updates + a 401 last_error here.
339
+ */
340
+ export declare function verifyTelegramChannel(cfg: IrTelegramConfig, opts: ChannelVerifyOptions): Promise<ChannelCheck[]>;
341
+ /**
342
+ * Discord probes: `GET applications/@me` with the bot token, asserting the
343
+ * three facts the adapter depends on — the token belongs to the declared
344
+ * `applicationId`, the application's `verify_key` equals the spec's
345
+ * `publicKeyHex` (a mismatch means every inbound webhook fails Ed25519
346
+ * verification with a 401), and `interactions_endpoint_url` points at the
347
+ * daemon's `/discord/events` route.
348
+ */
349
+ export declare function verifyDiscordChannel(cfg: IrDiscordConfig, opts: ChannelVerifyOptions): Promise<ChannelCheck[]>;
350
+ /** Redacted one-liners describing what `verify` would call — the dry-run
351
+ * counterpart for the probes (network never happens under --dry-run). */
352
+ export declare function describeVerifyProbes(platform: ChannelPlatform, channels: IrChannels, env: NodeJS.ProcessEnv): ReadonlyArray<string>;
353
+ export type ChannelVerifySummary = {
354
+ readonly lines: ReadonlyArray<string>;
355
+ readonly exitCode: 0 | 1;
356
+ };
357
+ /** Render checks as the doctor's ✓/~/✗ lines + the exit code — non-zero on
358
+ * any hard failure (missing scopes, mismatched webhook, bad credentials);
359
+ * warns are informational. Mirrors audit-verify's `summarizeVerifyResult`. */
360
+ export declare function summarizeChannelChecks(checks: ReadonlyArray<ChannelCheck>): ChannelVerifySummary;