ForgeBot Skill Audit

Slack Skill: Scripts, Tests, Functions

ForgeFX Slack operating guide and TypeScript helper surface for ForgeBot. This skill is the single Slack entry point; older scattered Slack skills/subskills have been flattened into this file, with supporting references, scripts, tests, fixtures, and legacy archive material filed under the top-level Slack skill folders. This preview inventories the active helper scripts, test coverage, and callable TypeScript surface after running the real test suite.

Generated Jul 1, 2026, 8:27 PM HST Branch main Revision bfa602a3f Path .forgebot/skills/slack
7Passing checks
9Active scripts shown
4Test files shown
31Functions and methods mapped

What This Skill Does

Test Run

PASS Scaffold, contract, and live read-only tests passed. The live tests exercised real Slack auth and channel metadata reads through Doppler.

(node:72656) [DEP0205] DeprecationWarning: `module.register()` is deprecated. Use `module.registerHooks()` instead.
(Use `node --trace-deprecation ...` to show where the warning was created)
✔ slack skill scaffold check passes (0.747542ms)
(node:72657) [DEP0205] DeprecationWarning: `module.register()` is deprecated. Use `module.registerHooks()` instead.
(Use `node --trace-deprecation ...` to show where the warning was created)
✔ getSlackToken prefers the ForgeBot token name and falls back to legacy SLACK_BOT_TOKEN (0.550792ms)
✔ read-only method guard accepts only read methods (0.100333ms)
✔ read-only method guard rejects write and admin Slack methods (0.133417ms)
✔ client rejects write/admin methods before any Slack request can be built (0.177333ms)
ℹ tests 5
ℹ suites 0
ℹ pass 5
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 120.360958
(node:72754) [DEP0205] DeprecationWarning: `module.register()` is deprecated. Use `module.registerHooks()` instead.
(Use `node --trace-deprecation ...` to show where the warning was created)
✔ auth.test succeeds with the live Slack token (297.163ms)
✔ channel search reads real public and private channel metadata (1266.101916ms)
ℹ tests 2
ℹ suites 0
ℹ pass 2
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 1689.96825

Scripts

ScriptLinesPurpose
.forgebot/skills/slack/scripts/check-skill.ts112Supporting Slack skill script.
.forgebot/skills/slack/scripts/legacy/slack-readonly.ts455Read-only Slack Web API helper for the ForgeFX Slack skill.
.forgebot/skills/slack/scripts/legacy/slack-history.mjs101 return new Date(Number(ts) * 1000).toLocaleTimeString();
.forgebot/skills/slack/scripts/legacy/download-slack-files.sh91download_slack_files.sh
.forgebot/skills/slack/scripts/verify/verify.sh35verify.sh — ForgeBot Slack health check, tiers 1-4. No external posting.
.forgebot/skills/slack/scripts/verify/check-llm-auth.sh79check-llm-auth.sh — Tier 1+2: pooled LLM credentials AND a real model round-trip.
.forgebot/skills/slack/scripts/verify/check-gateway.sh44check-gateway.sh — Tier 3: is the Hermes Slack gateway alive and Slack-connected?
.forgebot/skills/slack/scripts/verify/check-slack-send.sh24check-slack-send.sh — Tier 4: does the bot-token Slack delivery path resolve?
.forgebot/skills/slack/scripts/verify/roundtrip.sh47roundtrip.sh — simulate posting to Slack and capturing a ForgeBot reply.

Tests

Test fileLinesCases
.forgebot/skills/slack/tests/check-skill.test.ts11slack skill scaffold check passes
.forgebot/skills/slack/tests/legacy/slack-readonly-contract.test.ts58getSlackToken prefers the ForgeBot token name and falls back to legacy SLACK_BOT_TOKEN read-only method guard accepts only read methods read-only method guard rejects write and admin Slack methods client rejects write/admin methods before any Slack request can be built
.forgebot/skills/slack/tests/legacy/slack-readonly-live.test.ts41auth.test succeeds with the live Slack token channel search reads real public and private channel metadata
.forgebot/skills/slack/tests/legacy/README.md194No node:test cases detected; support documentation or fixture file.

Functions And Methods

local function

parseFrontmatter

.forgebot/skills/slack/scripts/check-skill.ts:16
function parseFrontmatter(markdown: string): {
exported function

checkSkill

.forgebot/skills/slack/scripts/check-skill.ts:65
export function checkSkill(skillDir = DEFAULT_SKILL_DIR): SkillCheckResult {
local function

isMain

.forgebot/skills/slack/scripts/check-skill.ts:100
function isMain(): boolean {
exported function

isReadOnlySlackMethod

.forgebot/skills/slack/scripts/legacy/slack-readonly.ts:114
export function isReadOnlySlackMethod(method: string): method is ReadOnlySlackMethod {
exported function

assertReadOnlySlackMethod

.forgebot/skills/slack/scripts/legacy/slack-readonly.ts:118
export function assertReadOnlySlackMethod(method: string): asserts method is ReadOnlySlackMethod {
exported function

getSlackToken

.forgebot/skills/slack/scripts/legacy/slack-readonly.ts:124
export function getSlackToken(env: SlackEnv = process.env): string {
class

SlackApiError

.forgebot/skills/slack/scripts/legacy/slack-readonly.ts:134
export class SlackApiError extends Error {
method

SlackApiError.constructor

.forgebot/skills/slack/scripts/legacy/slack-readonly.ts:140
constructor(method: string, errorCode: string, status: number, response: SlackApiResponse | null) {
local function

encodeParams

.forgebot/skills/slack/scripts/legacy/slack-readonly.ts:183
function encodeParams(params: SlackParams): URLSearchParams {
local function

normalizeLimit

.forgebot/skills/slack/scripts/legacy/slack-readonly.ts:192
function normalizeLimit(value: number | undefined, fallback: number, max: number): number {
local function

nextCursor

.forgebot/skills/slack/scripts/legacy/slack-readonly.ts:198
function nextCursor(response: SlackApiSuccess): string | undefined {
class

SlackReadOnlyClient

.forgebot/skills/slack/scripts/legacy/slack-readonly.ts:203
export class SlackReadOnlyClient {
method

SlackReadOnlyClient.constructor

.forgebot/skills/slack/scripts/legacy/slack-readonly.ts:211
constructor(options: SlackReadOnlyClientOptions = {}) {
method

SlackReadOnlyClient.authTest

.forgebot/skills/slack/scripts/legacy/slack-readonly.ts:259
authTest(): Promise<SlackApiSuccess> {
method

SlackReadOnlyClient.getChannelInfo

.forgebot/skills/slack/scripts/legacy/slack-readonly.ts:263
getChannelInfo(channel: string): Promise<SlackApiSuccess & { channel: SlackChannel }> {
method

SlackReadOnlyClient.listChannels

.forgebot/skills/slack/scripts/legacy/slack-readonly.ts:267
async listChannels(options: ListChannelsOptions = {}): Promise<SlackChannel[]> {
private method

SlackReadOnlyClient.listChannelsFromMethod

.forgebot/skills/slack/scripts/legacy/slack-readonly.ts:275
private async listChannelsFromMethod(
method

SlackReadOnlyClient.findChannelsByName

.forgebot/skills/slack/scripts/legacy/slack-readonly.ts:299
async findChannelsByName(query: string, options: ListChannelsOptions = {}): Promise<SlackChannel[]> {
method

SlackReadOnlyClient.getChannelHistory

.forgebot/skills/slack/scripts/legacy/slack-readonly.ts:305
getChannelHistory(channel: string, options: ChannelHistoryOptions = {}): Promise<SlackApiSuccess & { messages?: SlackMessage[] }> {
method

SlackReadOnlyClient.getThreadReplies

.forgebot/skills/slack/scripts/legacy/slack-readonly.ts:315
getThreadReplies(channel: string, ts: string, limit = 100): Promise<SlackApiSuccess & { messages?: SlackMessage[] }> {
method

SlackReadOnlyClient.getChannelMembers

.forgebot/skills/slack/scripts/legacy/slack-readonly.ts:323
getChannelMembers(channel: string, limit = 200, cursor?: string): Promise<SlackApiSuccess & { members?: string[] }> {
method

SlackReadOnlyClient.searchMessages

.forgebot/skills/slack/scripts/legacy/slack-readonly.ts:331
searchMessages(query: string, options: SearchMessagesOptions = {}): Promise<SlackApiSuccess> {
method

SlackReadOnlyClient.getUserInfo

.forgebot/skills/slack/scripts/legacy/slack-readonly.ts:340
getUserInfo(user: string): Promise<SlackApiSuccess & { user?: SlackUser }> {
method

SlackReadOnlyClient.listUsers

.forgebot/skills/slack/scripts/legacy/slack-readonly.ts:344
listUsers(limit = 200, cursor?: string): Promise<SlackApiSuccess & { members?: SlackUser[] }> {
method

SlackReadOnlyClient.lookupUserByEmail

.forgebot/skills/slack/scripts/legacy/slack-readonly.ts:351
lookupUserByEmail(email: string): Promise<SlackApiSuccess & { user?: SlackUser }> {
local function

parseSlackResponse

.forgebot/skills/slack/scripts/legacy/slack-readonly.ts:356
async function parseSlackResponse(response: Response): Promise<SlackApiResponse | null> {
local function

sleep

.forgebot/skills/slack/scripts/legacy/slack-readonly.ts:366
function sleep(ms: number): Promise<void> {
local function

usage

.forgebot/skills/slack/scripts/legacy/slack-readonly.ts:370
function usage(): string {
local function

main

.forgebot/skills/slack/scripts/legacy/slack-readonly.ts:387
async function main(args: string[]): Promise<void> {
local function

history

.forgebot/skills/slack/scripts/legacy/slack-history.mjs:33
async function history(limit = 20) {
local function

fmt

.forgebot/skills/slack/scripts/legacy/slack-history.mjs:43
function fmt(ts) {

Active Command Surface

  • auth — verify Slack token identity.
  • channels <name-fragment> — find visible public/private channels.
  • info <channel-id> — read channel metadata.
  • history <channel-id> [limit] — read recent messages.
  • members <channel-id> [limit] — read member IDs.
  • user <user-id> — read user profile metadata.

Guardrails Verified

  • Read-only allowlist accepts Slack read methods.
  • Write/admin examples are rejected locally.
  • Credential lookup prefers the ForgeBot bot token name, then legacy fallback.
  • Live reads use Doppler; no token values are printed in this report.