pm-slack 0.1.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.
package/CHANGELOG.md ADDED
@@ -0,0 +1,7 @@
1
+ # Changelog
2
+
3
+ ## 0.1.0 - 2026-05-26
4
+
5
+ ### Other
6
+
7
+ - Release readiness hardening for pm-slack ([pm-slack-uont](https://github.com/unbraind/pm-slack/blob/main/.agents/pm/tasks/pm-slack-uont.toon))
package/README.md ADDED
@@ -0,0 +1,165 @@
1
+ # pm-slack
2
+
3
+ Slack notifications for [pm-cli](https://github.com/unbraind/pm-cli) item lifecycle events.
4
+
5
+ Fires after `create`, `close`, and `block` operations and posts a formatted message to a Slack incoming webhook.
6
+
7
+ ---
8
+
9
+ ## Installation
10
+
11
+ ```bash
12
+ pm ext install pm-slack
13
+ ```
14
+
15
+ Or clone and link for local development:
16
+
17
+ ```bash
18
+ git clone https://github.com/unbraind/pm-slack.git
19
+ cd pm-cli-ext-slack
20
+ npm install
21
+ npm run build
22
+ pm ext link .
23
+ ```
24
+
25
+ ---
26
+
27
+ ## Setup
28
+
29
+ ### 1. Create a Slack Incoming Webhook
30
+
31
+ 1. Go to [api.slack.com/apps](https://api.slack.com/apps) and create a new app (or use an existing one).
32
+ 2. Under **Features → Incoming Webhooks**, activate incoming webhooks.
33
+ 3. Click **Add New Webhook to Workspace** and choose a channel.
34
+ 4. Copy the webhook URL into your shell environment.
35
+
36
+ ### 2. Set environment variables
37
+
38
+ | Variable | Required | Default | Description |
39
+ |---|---|---|---|
40
+ | `PM_SLACK_WEBHOOK` | **Yes** | — | Slack incoming webhook URL |
41
+ | `PM_SLACK_CHANNEL` | No | — | Channel hint appended to messages (e.g. `#pm-alerts`) |
42
+ | `PM_SLACK_MIN_PRIORITY` | No | `1` | Minimum priority to notify (1=critical, 2=high, 3=medium, 4=low) |
43
+ | `PM_SLACK_EVENTS` | No | `create,close,block` | Comma-separated list of events to notify on |
44
+
45
+ Export them in your shell profile or `.env`:
46
+
47
+ ```bash
48
+ export PM_SLACK_WEBHOOK="<slack-webhook-url>"
49
+ export PM_SLACK_CHANNEL="#pm-alerts"
50
+ export PM_SLACK_MIN_PRIORITY=2 # only critical + high
51
+ export PM_SLACK_EVENTS="create,close" # skip block notifications
52
+ ```
53
+
54
+ ---
55
+
56
+ ## Event Types
57
+
58
+ | Event | Trigger commands | Notes |
59
+ |---|---|---|
60
+ | `create` | `pm add`, `pm create`, `pm new` | Fires when a new item is created |
61
+ | `close` | `pm close`, `pm done`, `pm complete` | Fires when an item is closed/resolved |
62
+ | `block` | `pm update --status blocked`, `pm set status blocked` | Fires when an item's status changes to blocked |
63
+
64
+ ---
65
+
66
+ ## Message Format
67
+
68
+ ### Item created
69
+
70
+ ```
71
+ *[Feature]* Auth system created 🆕
72
+ Priority: high • Type: Feature • By: alice
73
+ ```
74
+
75
+ ### Item closed
76
+
77
+ ```
78
+ *[Issue]* Login redirect bug closed ✅
79
+ Reason: Fixed in commit abc123
80
+ ```
81
+
82
+ ### Item blocked
83
+
84
+ ```
85
+ *[Epic]* Dashboard redesign is blocked 🚫
86
+ Reason: Waiting on design approval
87
+ ```
88
+
89
+ When `PM_SLACK_CHANNEL` is set, a channel hint is appended to every message:
90
+
91
+ ```
92
+ *[Feature]* Auth system created 🆕
93
+ Priority: high • Type: Feature • By: alice
94
+ _Channel: #pm-alerts_
95
+ ```
96
+
97
+ ---
98
+
99
+ ## Filtering
100
+
101
+ ### By priority
102
+
103
+ Only notify for high-priority and above:
104
+
105
+ ```bash
106
+ PM_SLACK_MIN_PRIORITY=2
107
+ ```
108
+
109
+ Priority scale: `1` = critical, `2` = high, `3` = medium, `4` = low.
110
+ The filter passes items whose priority number is **less than or equal** to the minimum (i.e. higher priority).
111
+
112
+ ### By event type
113
+
114
+ Only notify on create and close, not block:
115
+
116
+ ```bash
117
+ PM_SLACK_EVENTS="create,close"
118
+ ```
119
+
120
+ ---
121
+
122
+ ## Error Handling
123
+
124
+ - If `PM_SLACK_WEBHOOK` is not set, the extension silently skips all notifications and logs a debug message.
125
+ - If the webhook URL is invalid, the extension logs an error and continues without crashing pm-cli.
126
+ - HTTP errors from Slack (non-2xx responses) are logged but do not fail the pm-cli command.
127
+ - Network timeouts are set to 10 seconds.
128
+
129
+ ---
130
+
131
+ ## Development
132
+
133
+ ```bash
134
+ npm install
135
+ npm run build # compile TypeScript → dist/
136
+ npm run dev # watch mode
137
+ ```
138
+
139
+ The extension uses only Node.js built-ins (`node:https`) — no external runtime dependencies.
140
+
141
+ ---
142
+
143
+ ## Manifest
144
+
145
+ ```json
146
+ {
147
+ "name": "pm-slack",
148
+ "version": "0.1.0",
149
+ "description": "Slack notifications for pm item lifecycle events",
150
+ "author": "@unbraind",
151
+ "entry": "index.js",
152
+ "priority": 50,
153
+ "capabilities": ["hooks", "services"]
154
+ }
155
+ ```
156
+
157
+ ---
158
+
159
+ ## License
160
+
161
+ MIT
162
+
163
+ ## Release Automation
164
+
165
+ This package is release-ready for GitHub, npm, and Bun-compatible installs. CI runs type checking, build, production dependency audit, package packing, Bun install verification, and pm-changelog validation. The daily release workflow publishes only when commits exist after the latest release tag and uses pm-changelog to generate CHANGELOG.md and GitHub release notes.
@@ -0,0 +1,16 @@
1
+ /**
2
+ * pm-slack — Slack notifications for pm-cli item lifecycle events
3
+ *
4
+ * Env vars:
5
+ * PM_SLACK_WEBHOOK (required) Slack incoming webhook URL
6
+ * PM_SLACK_CHANNEL (optional) Override channel, e.g. #pm-alerts
7
+ * PM_SLACK_MIN_PRIORITY (optional) Minimum priority to notify (1=critical … 4=low), default 1 (all)
8
+ * PM_SLACK_EVENTS (optional) Comma-separated subset: create,close,block (default: all)
9
+ */
10
+ declare const _default: {
11
+ name: string;
12
+ version: string;
13
+ activate(api: import("@unbrained/pm-cli/sdk").ExtensionApi): void;
14
+ };
15
+ export default _default;
16
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;;;;;;AA4PH,wBAqFG"}
package/dist/index.js ADDED
@@ -0,0 +1,260 @@
1
+ /**
2
+ * pm-slack — Slack notifications for pm-cli item lifecycle events
3
+ *
4
+ * Env vars:
5
+ * PM_SLACK_WEBHOOK (required) Slack incoming webhook URL
6
+ * PM_SLACK_CHANNEL (optional) Override channel, e.g. #pm-alerts
7
+ * PM_SLACK_MIN_PRIORITY (optional) Minimum priority to notify (1=critical … 4=low), default 1 (all)
8
+ * PM_SLACK_EVENTS (optional) Comma-separated subset: create,close,block (default: all)
9
+ */
10
+ import https from "node:https";
11
+ const defineExtension = ((extension) => extension);
12
+ function loadConfig() {
13
+ const webhookUrl = process.env.PM_SLACK_WEBHOOK ?? "";
14
+ if (!webhookUrl) {
15
+ console.error("[pm-slack] PM_SLACK_WEBHOOK not set — notifications disabled");
16
+ return null;
17
+ }
18
+ // Validate URL
19
+ try {
20
+ new URL(webhookUrl);
21
+ }
22
+ catch {
23
+ console.error("[pm-slack] PM_SLACK_WEBHOOK is not a valid URL — notifications disabled");
24
+ return null;
25
+ }
26
+ const channel = process.env.PM_SLACK_CHANNEL?.trim() || undefined;
27
+ const rawPriority = parseInt(process.env.PM_SLACK_MIN_PRIORITY ?? "1", 10);
28
+ const minPriority = rawPriority >= 1 && rawPriority <= 4 ? rawPriority : 1;
29
+ const rawEvents = process.env.PM_SLACK_EVENTS;
30
+ const allEvents = ["create", "close", "block"];
31
+ let events;
32
+ if (rawEvents) {
33
+ const parsed = rawEvents
34
+ .split(",")
35
+ .map((e) => e.trim().toLowerCase())
36
+ .filter((e) => allEvents.includes(e));
37
+ events = parsed.length > 0 ? new Set(parsed) : new Set(allEvents);
38
+ }
39
+ else {
40
+ events = new Set(allEvents);
41
+ }
42
+ return { webhookUrl, channel, minPriority, events };
43
+ }
44
+ // ---------------------------------------------------------------------------
45
+ // Priority helpers
46
+ // ---------------------------------------------------------------------------
47
+ const PRIORITY_LABELS = {
48
+ 1: "critical",
49
+ 2: "high",
50
+ 3: "medium",
51
+ 4: "low",
52
+ };
53
+ function priorityLabel(p) {
54
+ return p !== undefined ? PRIORITY_LABELS[p] ?? "unknown" : "unknown";
55
+ }
56
+ function meetsMinPriority(item, minPriority) {
57
+ // Lower number = higher priority; 1 = critical
58
+ if (item.priority === undefined)
59
+ return true; // unknown priority always passes
60
+ return item.priority <= minPriority;
61
+ }
62
+ // ---------------------------------------------------------------------------
63
+ // Message formatting
64
+ // ---------------------------------------------------------------------------
65
+ function itemTypeLabel(item) {
66
+ return item.type ?? "Item";
67
+ }
68
+ function buildCreateMessage(item, channel) {
69
+ const type = itemTypeLabel(item);
70
+ const pri = priorityLabel(item.priority);
71
+ const author = item.author ?? "unknown";
72
+ let msg = `*[${type}]* ${item.title} created 🆕\n` +
73
+ `Priority: ${pri} • Type: ${type} • By: ${author}`;
74
+ if (channel)
75
+ msg += `\n_Channel: ${channel}_`;
76
+ return msg;
77
+ }
78
+ function buildCloseMessage(item, channel) {
79
+ const type = itemTypeLabel(item);
80
+ const reason = item.closedReason?.trim() || "no reason given";
81
+ let msg = `*[${type}]* ${item.title} closed ✅\n` + `Reason: ${reason}`;
82
+ if (channel)
83
+ msg += `\n_Channel: ${channel}_`;
84
+ return msg;
85
+ }
86
+ function buildBlockMessage(item, channel) {
87
+ const type = itemTypeLabel(item);
88
+ const reason = item.blockedReason?.trim() || "no reason given";
89
+ let msg = `*[${type}]* ${item.title} is blocked 🚫\n` + `Reason: ${reason}`;
90
+ if (channel)
91
+ msg += `\n_Channel: ${channel}_`;
92
+ return msg;
93
+ }
94
+ // ---------------------------------------------------------------------------
95
+ // Slack HTTP POST
96
+ // ---------------------------------------------------------------------------
97
+ function postToSlack(webhookUrl, text) {
98
+ return new Promise((resolve, reject) => {
99
+ const body = JSON.stringify({ text, mrkdwn: true });
100
+ const parsed = new URL(webhookUrl);
101
+ const options = {
102
+ hostname: parsed.hostname,
103
+ port: parsed.port ? parseInt(parsed.port, 10) : 443,
104
+ path: parsed.pathname + parsed.search,
105
+ method: "POST",
106
+ headers: {
107
+ "Content-Type": "application/json",
108
+ "Content-Length": Buffer.byteLength(body),
109
+ },
110
+ };
111
+ const req = https.request(options, (res) => {
112
+ let data = "";
113
+ res.on("data", (chunk) => {
114
+ data += chunk.toString();
115
+ });
116
+ res.on("end", () => {
117
+ const status = res.statusCode ?? 0;
118
+ if (status >= 200 && status < 300) {
119
+ resolve();
120
+ }
121
+ else {
122
+ reject(new Error(`Slack webhook returned HTTP ${status}: ${data.slice(0, 200)}`));
123
+ }
124
+ });
125
+ });
126
+ req.on("error", (err) => {
127
+ reject(new Error(`Slack webhook request failed: ${err.message}`));
128
+ });
129
+ req.setTimeout(10_000, () => {
130
+ req.destroy(new Error("Slack webhook request timed out after 10s"));
131
+ });
132
+ req.write(body);
133
+ req.end();
134
+ });
135
+ }
136
+ // ---------------------------------------------------------------------------
137
+ // Event detection
138
+ // ---------------------------------------------------------------------------
139
+ /** Commands that create a new item */
140
+ const CREATE_COMMANDS = new Set(["add", "create", "new"]);
141
+ /** Commands that close/complete an item */
142
+ const CLOSE_COMMANDS = new Set(["close", "done", "complete", "finish", "resolve"]);
143
+ /** Commands that update an item's status or attributes */
144
+ const UPDATE_COMMANDS = new Set(["update", "edit", "set", "status"]);
145
+ function detectEvent(ctx) {
146
+ const cmd = ctx.command?.toLowerCase() ?? "";
147
+ if (CREATE_COMMANDS.has(cmd))
148
+ return "create";
149
+ if (CLOSE_COMMANDS.has(cmd))
150
+ return "close";
151
+ if (UPDATE_COMMANDS.has(cmd)) {
152
+ // Detect a block status being set via options or result
153
+ const newStatus = ctx.options?.["status"] ??
154
+ ctx.result?.item?.status ??
155
+ "";
156
+ if (newStatus.toLowerCase() === "blocked")
157
+ return "block";
158
+ // Also check result item for blocked status transition
159
+ const resultItem = ctx.result?.item;
160
+ if (resultItem?.status?.toLowerCase() === "blocked")
161
+ return "block";
162
+ }
163
+ return null;
164
+ }
165
+ function extractItem(ctx) {
166
+ const result = ctx.result;
167
+ const item = result?.item;
168
+ if (item && item.id)
169
+ return item;
170
+ // Some commands return a list (e.g. bulk add) — take the first
171
+ const items = result?.items;
172
+ if (Array.isArray(items) && items.length > 0 && items[0].id) {
173
+ return items[0];
174
+ }
175
+ return null;
176
+ }
177
+ // ---------------------------------------------------------------------------
178
+ // Extension entry point
179
+ // ---------------------------------------------------------------------------
180
+ export default defineExtension({
181
+ name: "pm-slack",
182
+ version: "0.1.0",
183
+ activate(api) {
184
+ // ---------------------------------------------------------------------------
185
+ // afterCommand hook — fires after every pm-cli command completes
186
+ // ---------------------------------------------------------------------------
187
+ if (typeof api.hooks?.afterCommand === "function") {
188
+ api.hooks.afterCommand(async (ctx) => {
189
+ const config = loadConfig();
190
+ if (!config)
191
+ return;
192
+ const event = detectEvent(ctx);
193
+ if (!event)
194
+ return;
195
+ if (!config.events.has(event)) {
196
+ console.error(`[pm-slack] Event "${event}" filtered by PM_SLACK_EVENTS`);
197
+ return;
198
+ }
199
+ const item = extractItem(ctx);
200
+ if (!item) {
201
+ console.error("[pm-slack] Could not extract item from result — skipping");
202
+ return;
203
+ }
204
+ if (!meetsMinPriority(item, config.minPriority)) {
205
+ console.error(`[pm-slack] Item priority ${item.priority} below minimum ${config.minPriority} — skipping`);
206
+ return;
207
+ }
208
+ let text;
209
+ switch (event) {
210
+ case "create":
211
+ text = buildCreateMessage(item, config.channel);
212
+ break;
213
+ case "close":
214
+ text = buildCloseMessage(item, config.channel);
215
+ break;
216
+ case "block":
217
+ text = buildBlockMessage(item, config.channel);
218
+ break;
219
+ }
220
+ try {
221
+ await postToSlack(config.webhookUrl, text);
222
+ console.error(`[pm-slack] Notification sent for event "${event}" on item ${item.id}`);
223
+ }
224
+ catch (err) {
225
+ const message = err instanceof Error ? err.message : String(err);
226
+ console.error(`[pm-slack] Failed to send Slack notification: ${message}`);
227
+ }
228
+ });
229
+ }
230
+ else {
231
+ // Fallback: use beforeCommand if afterCommand is unavailable
232
+ // (result data will be unavailable, so we can only notify on command name)
233
+ api.hooks.beforeCommand(async (ctx) => {
234
+ console.error("[pm-slack] afterCommand not available — limited event detection active");
235
+ const config = loadConfig();
236
+ if (!config)
237
+ return;
238
+ const cmd = ctx.command?.toLowerCase() ?? "";
239
+ let event = null;
240
+ if (CREATE_COMMANDS.has(cmd))
241
+ event = "create";
242
+ else if (CLOSE_COMMANDS.has(cmd))
243
+ event = "close";
244
+ if (!event || !config.events.has(event))
245
+ return;
246
+ // Without result we can only build a generic message
247
+ const cmdArgs = (ctx.args ?? []).join(" ");
248
+ const text = `pm command \`${ctx.command}\` triggered event *${event}*\n${cmdArgs}`;
249
+ try {
250
+ await postToSlack(config.webhookUrl, text);
251
+ }
252
+ catch (err) {
253
+ const message = err instanceof Error ? err.message : String(err);
254
+ console.error(`[pm-slack] Failed to send Slack notification: ${message}`);
255
+ }
256
+ });
257
+ }
258
+ },
259
+ });
260
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"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"}
package/manifest.json ADDED
@@ -0,0 +1,14 @@
1
+ {
2
+ "name": "pm-slack",
3
+ "version": "0.1.0",
4
+ "description": "Slack notifications for pm item lifecycle events",
5
+ "author": "@unbraind",
6
+ "entry": "./dist/index.js",
7
+ "priority": 50,
8
+ "capabilities": [
9
+ "hooks"
10
+ ],
11
+ "pm": {
12
+ "compatibility": "v2"
13
+ }
14
+ }
package/package.json ADDED
@@ -0,0 +1,88 @@
1
+ {
2
+ "name": "pm-slack",
3
+ "version": "0.1.0",
4
+ "description": "Slack notifications for pm item lifecycle events",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+https://github.com/unbraind/pm-slack.git"
8
+ },
9
+ "bugs": {
10
+ "url": "https://github.com/unbraind/pm-slack/issues"
11
+ },
12
+ "homepage": "https://github.com/unbraind/pm-slack#readme",
13
+ "type": "module",
14
+ "main": "dist/index.js",
15
+ "types": "dist/index.d.ts",
16
+ "files": [
17
+ "dist/",
18
+ "manifest.json",
19
+ "README.md",
20
+ "CHANGELOG.md"
21
+ ],
22
+ "scripts": {
23
+ "build": "tsc",
24
+ "dev": "tsc --watch",
25
+ "prepack": "npm run build",
26
+ "typecheck": "tsc --noEmit",
27
+ "check": "npm run typecheck",
28
+ "audit:prod": "npm audit --omit=dev",
29
+ "pack:dry-run": "npm pack --dry-run",
30
+ "changelog": "pm-changelog --pm-root .agents/pm --mode prepend --output CHANGELOG.md --release-version-from-package --since-previous-tag --until-release-tag --item-url-base https://github.com/unbraind/pm-slack/blob/main/.agents/pm",
31
+ "changelog:full": "pm-changelog --pm-root .agents/pm --mode replace --output CHANGELOG.md --all-release-tags --release-version-from-package --item-url-base https://github.com/unbraind/pm-slack/blob/main/.agents/pm",
32
+ "changelog:check": "pm-changelog --pm-root .agents/pm --mode replace --output CHANGELOG.md --all-release-tags --release-version-from-package --item-url-base https://github.com/unbraind/pm-slack/blob/main/.agents/pm --check",
33
+ "release:check": "npm run typecheck && npm run build && npm run audit:prod && npm run pack:dry-run && npm run changelog:check"
34
+ },
35
+ "peerDependencies": {
36
+ "@unbrained/pm-cli": ">=2026.5.24"
37
+ },
38
+ "devDependencies": {
39
+ "@unbrained/pm-cli": "^2026.5.24",
40
+ "typescript": "^6.0.3",
41
+ "pm-changelog": "^2026.5.25",
42
+ "@types/node": "^25.9.1"
43
+ },
44
+ "engines": {
45
+ "node": ">=20.0.0"
46
+ },
47
+ "keywords": [
48
+ "extension",
49
+ "notifications",
50
+ "pm-cli",
51
+ "pm-extension",
52
+ "pm-package",
53
+ "slack"
54
+ ],
55
+ "license": "MIT",
56
+ "author": "@unbraind",
57
+ "pm": {
58
+ "aliases": [
59
+ "slack"
60
+ ],
61
+ "extensions": [
62
+ "."
63
+ ],
64
+ "catalog": {
65
+ "display_name": "Slack Notifications",
66
+ "category": "notifications",
67
+ "summary": "Slack notifications for pm item lifecycle events",
68
+ "tags": [
69
+ "slack",
70
+ "notifications",
71
+ "hooks"
72
+ ],
73
+ "links": {
74
+ "docs": "https://github.com/unbraind/pm-slack#readme",
75
+ "npm": "https://www.npmjs.com/package/pm-slack",
76
+ "repository": "https://github.com/unbraind/pm-slack",
77
+ "report": "https://github.com/unbraind/pm-slack/issues"
78
+ }
79
+ },
80
+ "docs": [
81
+ "README.md",
82
+ "CHANGELOG.md"
83
+ ],
84
+ "examples": [
85
+ "README.md"
86
+ ]
87
+ }
88
+ }