@elnora-ai/linear 1.0.1 → 1.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.
Files changed (299) hide show
  1. package/.claude-plugin/marketplace.json +7 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +13 -1
  4. package/README.md +116 -26
  5. package/agents/linear-issue-creator.md +129 -17
  6. package/agents/linear-issue-reviewer.md +122 -23
  7. package/agents/linear-issue-updater.md +137 -25
  8. package/agents/linear-state-curator.md +173 -0
  9. package/agents/linear-url-to-issues.md +189 -26
  10. package/commands/linear-cleanup.md +64 -29
  11. package/dist/cli.js +64 -1
  12. package/dist/cli.js.map +1 -1
  13. package/dist/client/auth.d.ts.map +1 -1
  14. package/dist/client/auth.js +13 -2
  15. package/dist/client/auth.js.map +1 -1
  16. package/dist/client/linear-client.d.ts +7 -0
  17. package/dist/client/linear-client.d.ts.map +1 -1
  18. package/dist/client/linear-client.js +13 -1
  19. package/dist/client/linear-client.js.map +1 -1
  20. package/dist/commands/agent-activities.d.ts +3 -0
  21. package/dist/commands/agent-activities.d.ts.map +1 -0
  22. package/dist/commands/agent-activities.js +144 -0
  23. package/dist/commands/agent-activities.js.map +1 -0
  24. package/dist/commands/agent-sessions.d.ts +3 -0
  25. package/dist/commands/agent-sessions.d.ts.map +1 -0
  26. package/dist/commands/agent-sessions.js +132 -0
  27. package/dist/commands/agent-sessions.js.map +1 -0
  28. package/dist/commands/attachments.d.ts +3 -0
  29. package/dist/commands/attachments.d.ts.map +1 -0
  30. package/dist/commands/attachments.js +265 -0
  31. package/dist/commands/attachments.js.map +1 -0
  32. package/dist/commands/audit.d.ts +3 -0
  33. package/dist/commands/audit.d.ts.map +1 -0
  34. package/dist/commands/audit.js +73 -0
  35. package/dist/commands/audit.js.map +1 -0
  36. package/dist/commands/comments.d.ts +3 -0
  37. package/dist/commands/comments.d.ts.map +1 -0
  38. package/dist/commands/comments.js +107 -0
  39. package/dist/commands/comments.js.map +1 -0
  40. package/dist/commands/completion.d.ts +3 -0
  41. package/dist/commands/completion.d.ts.map +1 -0
  42. package/dist/commands/completion.js +62 -0
  43. package/dist/commands/completion.js.map +1 -0
  44. package/dist/commands/context.d.ts +3 -0
  45. package/dist/commands/context.d.ts.map +1 -0
  46. package/dist/commands/context.js +94 -0
  47. package/dist/commands/context.js.map +1 -0
  48. package/dist/commands/curator.d.ts +14 -0
  49. package/dist/commands/curator.d.ts.map +1 -1
  50. package/dist/commands/curator.js +97 -19
  51. package/dist/commands/curator.js.map +1 -1
  52. package/dist/commands/customer-needs.d.ts +3 -0
  53. package/dist/commands/customer-needs.d.ts.map +1 -0
  54. package/dist/commands/customer-needs.js +198 -0
  55. package/dist/commands/customer-needs.js.map +1 -0
  56. package/dist/commands/customers.d.ts +5 -0
  57. package/dist/commands/customers.d.ts.map +1 -0
  58. package/dist/commands/customers.js +201 -0
  59. package/dist/commands/customers.js.map +1 -0
  60. package/dist/commands/cycles.d.ts +3 -0
  61. package/dist/commands/cycles.d.ts.map +1 -0
  62. package/dist/commands/cycles.js +67 -0
  63. package/dist/commands/cycles.js.map +1 -0
  64. package/dist/commands/documents.d.ts +3 -0
  65. package/dist/commands/documents.d.ts.map +1 -0
  66. package/dist/commands/documents.js +105 -0
  67. package/dist/commands/documents.js.map +1 -0
  68. package/dist/commands/favorites.d.ts +3 -0
  69. package/dist/commands/favorites.d.ts.map +1 -0
  70. package/dist/commands/favorites.js +101 -0
  71. package/dist/commands/favorites.js.map +1 -0
  72. package/dist/commands/index.d.ts +30 -0
  73. package/dist/commands/index.d.ts.map +1 -1
  74. package/dist/commands/index.js +30 -0
  75. package/dist/commands/index.js.map +1 -1
  76. package/dist/commands/initiatives.d.ts +3 -0
  77. package/dist/commands/initiatives.d.ts.map +1 -0
  78. package/dist/commands/initiatives.js +106 -0
  79. package/dist/commands/initiatives.js.map +1 -0
  80. package/dist/commands/issues.d.ts +21 -0
  81. package/dist/commands/issues.d.ts.map +1 -0
  82. package/dist/commands/issues.js +993 -0
  83. package/dist/commands/issues.js.map +1 -0
  84. package/dist/commands/labels.d.ts +3 -0
  85. package/dist/commands/labels.d.ts.map +1 -0
  86. package/dist/commands/labels.js +111 -0
  87. package/dist/commands/labels.js.map +1 -0
  88. package/dist/commands/milestones.d.ts +3 -0
  89. package/dist/commands/milestones.d.ts.map +1 -0
  90. package/dist/commands/milestones.js +94 -0
  91. package/dist/commands/milestones.js.map +1 -0
  92. package/dist/commands/notifications.d.ts +3 -0
  93. package/dist/commands/notifications.d.ts.map +1 -0
  94. package/dist/commands/notifications.js +130 -0
  95. package/dist/commands/notifications.js.map +1 -0
  96. package/dist/commands/project-labels.d.ts +3 -0
  97. package/dist/commands/project-labels.d.ts.map +1 -0
  98. package/dist/commands/project-labels.js +80 -0
  99. package/dist/commands/project-labels.js.map +1 -0
  100. package/dist/commands/project-relations.d.ts +3 -0
  101. package/dist/commands/project-relations.d.ts.map +1 -0
  102. package/dist/commands/project-relations.js +96 -0
  103. package/dist/commands/project-relations.js.map +1 -0
  104. package/dist/commands/projects.d.ts +3 -0
  105. package/dist/commands/projects.d.ts.map +1 -0
  106. package/dist/commands/projects.js +263 -0
  107. package/dist/commands/projects.js.map +1 -0
  108. package/dist/commands/quota.d.ts +3 -0
  109. package/dist/commands/quota.d.ts.map +1 -0
  110. package/dist/commands/quota.js +28 -0
  111. package/dist/commands/quota.js.map +1 -0
  112. package/dist/commands/reactions.d.ts +7 -0
  113. package/dist/commands/reactions.d.ts.map +1 -0
  114. package/dist/commands/reactions.js +53 -0
  115. package/dist/commands/reactions.js.map +1 -0
  116. package/dist/commands/relations.d.ts +3 -0
  117. package/dist/commands/relations.d.ts.map +1 -0
  118. package/dist/commands/relations.js +73 -0
  119. package/dist/commands/relations.js.map +1 -0
  120. package/dist/commands/states.d.ts +3 -0
  121. package/dist/commands/states.d.ts.map +1 -0
  122. package/dist/commands/states.js +52 -0
  123. package/dist/commands/states.js.map +1 -0
  124. package/dist/commands/status-updates.d.ts +3 -0
  125. package/dist/commands/status-updates.d.ts.map +1 -0
  126. package/dist/commands/status-updates.js +117 -0
  127. package/dist/commands/status-updates.js.map +1 -0
  128. package/dist/commands/sync.d.ts.map +1 -1
  129. package/dist/commands/sync.js +58 -18
  130. package/dist/commands/sync.js.map +1 -1
  131. package/dist/commands/teams.d.ts +3 -0
  132. package/dist/commands/teams.d.ts.map +1 -0
  133. package/dist/commands/teams.js +135 -0
  134. package/dist/commands/teams.js.map +1 -0
  135. package/dist/commands/templates.d.ts +3 -0
  136. package/dist/commands/templates.d.ts.map +1 -0
  137. package/dist/commands/templates.js +76 -0
  138. package/dist/commands/templates.js.map +1 -0
  139. package/dist/commands/users.d.ts +3 -0
  140. package/dist/commands/users.d.ts.map +1 -0
  141. package/dist/commands/users.js +40 -0
  142. package/dist/commands/users.js.map +1 -0
  143. package/dist/commands/views.d.ts +3 -0
  144. package/dist/commands/views.d.ts.map +1 -0
  145. package/dist/commands/views.js +177 -0
  146. package/dist/commands/views.js.map +1 -0
  147. package/dist/commands/webhooks.d.ts +3 -0
  148. package/dist/commands/webhooks.d.ts.map +1 -0
  149. package/dist/commands/webhooks.js +234 -0
  150. package/dist/commands/webhooks.js.map +1 -0
  151. package/dist/config/loader.d.ts.map +1 -1
  152. package/dist/config/loader.js +3 -0
  153. package/dist/config/loader.js.map +1 -1
  154. package/dist/config/types.d.ts +15 -1
  155. package/dist/config/types.d.ts.map +1 -1
  156. package/dist/config/types.js +1 -0
  157. package/dist/config/types.js.map +1 -1
  158. package/dist/curator/dispatch.d.ts +52 -0
  159. package/dist/curator/dispatch.d.ts.map +1 -0
  160. package/dist/curator/dispatch.js +144 -0
  161. package/dist/curator/dispatch.js.map +1 -0
  162. package/dist/curator/index.d.ts +5 -0
  163. package/dist/curator/index.d.ts.map +1 -0
  164. package/dist/curator/index.js +5 -0
  165. package/dist/curator/index.js.map +1 -0
  166. package/dist/curator/llm.d.ts +70 -0
  167. package/dist/curator/llm.d.ts.map +1 -0
  168. package/dist/curator/llm.js +107 -0
  169. package/dist/curator/llm.js.map +1 -0
  170. package/dist/curator/snapshot.d.ts +34 -0
  171. package/dist/curator/snapshot.d.ts.map +1 -0
  172. package/dist/curator/snapshot.js +127 -0
  173. package/dist/curator/snapshot.js.map +1 -0
  174. package/dist/curator/state.d.ts +50 -0
  175. package/dist/curator/state.d.ts.map +1 -0
  176. package/dist/curator/state.js +125 -0
  177. package/dist/curator/state.js.map +1 -0
  178. package/dist/lib/bulk-graphql.d.ts +144 -0
  179. package/dist/lib/bulk-graphql.d.ts.map +1 -0
  180. package/dist/lib/bulk-graphql.js +380 -0
  181. package/dist/lib/bulk-graphql.js.map +1 -0
  182. package/dist/lib/index.d.ts +2 -0
  183. package/dist/lib/index.d.ts.map +1 -0
  184. package/dist/lib/index.js +2 -0
  185. package/dist/lib/index.js.map +1 -0
  186. package/dist/output/cli.d.ts +17 -0
  187. package/dist/output/cli.d.ts.map +1 -0
  188. package/dist/output/cli.js +252 -0
  189. package/dist/output/cli.js.map +1 -0
  190. package/dist/output/formatter.d.ts +6 -0
  191. package/dist/output/formatter.d.ts.map +1 -1
  192. package/dist/output/formatter.js +10 -0
  193. package/dist/output/formatter.js.map +1 -1
  194. package/dist/output/index.d.ts +1 -0
  195. package/dist/output/index.d.ts.map +1 -1
  196. package/dist/output/index.js +1 -0
  197. package/dist/output/index.js.map +1 -1
  198. package/dist/scripts/sync-linear-templates.d.ts +26 -0
  199. package/dist/scripts/sync-linear-templates.d.ts.map +1 -0
  200. package/dist/scripts/sync-linear-templates.js +115 -0
  201. package/dist/scripts/sync-linear-templates.js.map +1 -0
  202. package/dist/signals/github-commits.d.ts +31 -0
  203. package/dist/signals/github-commits.d.ts.map +1 -0
  204. package/dist/signals/github-commits.js +127 -0
  205. package/dist/signals/github-commits.js.map +1 -0
  206. package/dist/signals/github-pr.d.ts +16 -0
  207. package/dist/signals/github-pr.d.ts.map +1 -0
  208. package/dist/signals/github-pr.js +98 -0
  209. package/dist/signals/github-pr.js.map +1 -0
  210. package/dist/signals/index.d.ts +4 -0
  211. package/dist/signals/index.d.ts.map +1 -1
  212. package/dist/signals/index.js +4 -0
  213. package/dist/signals/index.js.map +1 -1
  214. package/dist/signals/linear-issues.d.ts +20 -0
  215. package/dist/signals/linear-issues.d.ts.map +1 -0
  216. package/dist/signals/linear-issues.js +115 -0
  217. package/dist/signals/linear-issues.js.map +1 -0
  218. package/dist/signals/registry.d.ts +4 -3
  219. package/dist/signals/registry.d.ts.map +1 -1
  220. package/dist/signals/registry.js +33 -11
  221. package/dist/signals/registry.js.map +1 -1
  222. package/dist/signals/slack-messages.d.ts +20 -0
  223. package/dist/signals/slack-messages.d.ts.map +1 -0
  224. package/dist/signals/slack-messages.js +129 -0
  225. package/dist/signals/slack-messages.js.map +1 -0
  226. package/dist/utils/errors.d.ts +63 -0
  227. package/dist/utils/errors.d.ts.map +1 -0
  228. package/dist/utils/errors.js +94 -0
  229. package/dist/utils/errors.js.map +1 -0
  230. package/dist/utils/index.d.ts +9 -0
  231. package/dist/utils/index.d.ts.map +1 -0
  232. package/dist/utils/index.js +9 -0
  233. package/dist/utils/index.js.map +1 -0
  234. package/dist/utils/label-policy.d.ts +53 -0
  235. package/dist/utils/label-policy.d.ts.map +1 -0
  236. package/dist/utils/label-policy.js +93 -0
  237. package/dist/utils/label-policy.js.map +1 -0
  238. package/dist/utils/parse.d.ts +48 -0
  239. package/dist/utils/parse.d.ts.map +1 -0
  240. package/dist/utils/parse.js +133 -0
  241. package/dist/utils/parse.js.map +1 -0
  242. package/dist/utils/project-status.d.ts +6 -0
  243. package/dist/utils/project-status.d.ts.map +1 -0
  244. package/dist/utils/project-status.js +33 -0
  245. package/dist/utils/project-status.js.map +1 -0
  246. package/dist/utils/rate-limit.d.ts +24 -0
  247. package/dist/utils/rate-limit.d.ts.map +1 -0
  248. package/dist/utils/rate-limit.js +89 -0
  249. package/dist/utils/rate-limit.js.map +1 -0
  250. package/dist/utils/resolve.d.ts +84 -0
  251. package/dist/utils/resolve.d.ts.map +1 -0
  252. package/dist/utils/resolve.js +172 -0
  253. package/dist/utils/resolve.js.map +1 -0
  254. package/dist/utils/sleep.d.ts +2 -0
  255. package/dist/utils/sleep.d.ts.map +1 -0
  256. package/dist/utils/sleep.js +4 -0
  257. package/dist/utils/sleep.js.map +1 -0
  258. package/dist/utils/webhook-verify.d.ts +42 -0
  259. package/dist/utils/webhook-verify.d.ts.map +1 -0
  260. package/dist/utils/webhook-verify.js +65 -0
  261. package/dist/utils/webhook-verify.js.map +1 -0
  262. package/package.json +4 -1
  263. package/references/agent-description-template.md +31 -0
  264. package/references/cli-reference.md +227 -0
  265. package/references/curator-tiering-rules.md +76 -0
  266. package/references/label-policy.example.json +37 -0
  267. package/references/label-policy.placeholder.json +6 -0
  268. package/references/settings-template.md +30 -0
  269. package/references/sla-reference.md +70 -0
  270. package/references/template-index.md +34 -0
  271. package/references/workspace-labels.md +124 -0
  272. package/references/workspace-projects.md +56 -0
  273. package/references/workspace-routing.md +58 -0
  274. package/schemas/label-policy.json +72 -0
  275. package/skills/linear-workspace/SKILL.md +65 -4
  276. package/templates/ACC-PRO-provision.md +74 -0
  277. package/templates/ACC-PRV-privileged.md +66 -0
  278. package/templates/ACC-QTR-review.md +77 -0
  279. package/templates/ACC-REV-revoke.md +67 -0
  280. package/templates/AI-USE-capability.md +111 -0
  281. package/templates/AUD-CAP-corrective.md +89 -0
  282. package/templates/AUD-INT-internal.md +92 -0
  283. package/templates/AUD-MGT-management.md +110 -0
  284. package/templates/CHG-MAJ-major.md +110 -0
  285. package/templates/CHG-SIG-significant.md +83 -0
  286. package/templates/CHG-STD-standard.md +47 -0
  287. package/templates/LRN-DOC-lessons.md +75 -0
  288. package/templates/OPS-BCK-backup.md +99 -0
  289. package/templates/OPS-DAT-data-mod.md +98 -0
  290. package/templates/RCA-DOC-root-cause.md +105 -0
  291. package/templates/RSK-ASS-assessment.md +87 -0
  292. package/templates/RSK-VND-vendor.md +113 -0
  293. package/templates/SEC-INC-incident.md +76 -0
  294. package/templates/SEC-PEN-pentest.md +58 -0
  295. package/templates/SEC-VLN-vulnerability.md +69 -0
  296. package/templates/SLA-AVL-availability.md +86 -0
  297. package/templates/SLA-OPS-operational.md +70 -0
  298. package/templates/agent-server-template/README.md +88 -0
  299. package/templates/agent-server-template/server.example.ts +185 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github-commits.js","sourceRoot":"","sources":["../../src/signals/github-commits.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import type { LinearConfig } from "../config/types.js";
2
+ import type { Signal, SignalSourceContext, SignalSourceImpl } from "./types.js";
3
+ export interface GithubPrConfig {
4
+ type: "github_pr";
5
+ name: string;
6
+ enabled?: boolean;
7
+ repos?: string[];
8
+ limit?: number;
9
+ }
10
+ export declare class GithubPrSource implements SignalSourceImpl {
11
+ readonly config: GithubPrConfig;
12
+ private readonly linearConfig;
13
+ constructor(config: GithubPrConfig, linearConfig: LinearConfig);
14
+ collect(ctx: SignalSourceContext): Promise<Signal[]>;
15
+ }
16
+ //# sourceMappingURL=github-pr.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github-pr.d.ts","sourceRoot":"","sources":["../../src/signals/github-pr.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,OAAO,KAAK,EAAE,MAAM,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAOhF,MAAM,WAAW,cAAc;IAC9B,IAAI,EAAE,WAAW,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAYD,qBAAa,cAAe,YAAW,gBAAgB;IACtD,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAe;gBAEhC,MAAM,EAAE,cAAc,EAAE,YAAY,EAAE,YAAY;IAKxD,OAAO,CAAC,GAAG,EAAE,mBAAmB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;CAiF1D"}
@@ -0,0 +1,98 @@
1
+ // `github_pr` signal source.
2
+ //
3
+ // Uses the GitHub CLI (`gh pr list`) to enumerate pull requests across the
4
+ // configured repos. Issue identifiers are extracted from PR title + body
5
+ // using the team-prefix regex derived from references/teams.json.
6
+ //
7
+ // Required: the `gh` CLI must be installed and authenticated (`gh auth status`).
8
+ // Without it, the source emits one warning signal and returns.
9
+ import { execFile } from "node:child_process";
10
+ import { promisify } from "node:util";
11
+ import { _internal as commitsInternal } from "./github-commits.js";
12
+ const runCmd = promisify(execFile);
13
+ const PR_LIMIT_DEFAULT = 100;
14
+ const MAX_BUFFER = 10_000_000;
15
+ const TIMEOUT_MS = 30_000;
16
+ export class GithubPrSource {
17
+ config;
18
+ linearConfig;
19
+ constructor(config, linearConfig) {
20
+ this.config = config;
21
+ this.linearConfig = linearConfig;
22
+ }
23
+ async collect(ctx) {
24
+ const receivedAt = ctx.now.toISOString();
25
+ const teamKeys = this.linearConfig.teams.teams.map((t) => t.key);
26
+ const issueRegex = commitsInternal.buildTeamRegex(teamKeys);
27
+ const limit = this.config.limit ?? PR_LIMIT_DEFAULT;
28
+ const repoNames = this.config.repos ?? this.linearConfig.repos.repos.map((r) => r.name);
29
+ const reposByName = new Map(this.linearConfig.repos.repos.map((r) => [r.name, r]));
30
+ const signals = [];
31
+ for (const name of repoNames) {
32
+ const repo = reposByName.get(name);
33
+ if (!repo?.org) {
34
+ signals.push({
35
+ source: this.config.name,
36
+ type: this.config.type,
37
+ payload: { warning: `repo "${name}" has no org configured; skipped` },
38
+ receivedAt,
39
+ });
40
+ continue;
41
+ }
42
+ const slug = `${repo.org}/${name}`;
43
+ let prs;
44
+ try {
45
+ const { stdout } = await runCmd("gh", [
46
+ "pr",
47
+ "list",
48
+ "--repo",
49
+ slug,
50
+ "--state",
51
+ "all",
52
+ "--limit",
53
+ String(limit),
54
+ "--json",
55
+ "number,title,body,state,mergedAt,author,url",
56
+ ], { timeout: TIMEOUT_MS, maxBuffer: MAX_BUFFER });
57
+ prs = JSON.parse(stdout);
58
+ }
59
+ catch (err) {
60
+ signals.push({
61
+ source: this.config.name,
62
+ type: this.config.type,
63
+ payload: { warning: `gh pr list failed for "${slug}": ${err.message}` },
64
+ receivedAt,
65
+ });
66
+ continue;
67
+ }
68
+ for (const pr of prs) {
69
+ const haystack = `${pr.title}\n${pr.body ?? ""}`;
70
+ const ids = commitsInternal.extractIssueIds(haystack, issueRegex);
71
+ const payload = {
72
+ repo: name,
73
+ number: pr.number,
74
+ title: pr.title,
75
+ state: pr.state,
76
+ mergedAt: pr.mergedAt,
77
+ author: pr.author?.login ?? null,
78
+ url: pr.url,
79
+ };
80
+ if (ids.length === 0) {
81
+ signals.push({ source: this.config.name, type: this.config.type, payload, receivedAt });
82
+ continue;
83
+ }
84
+ for (const id of ids) {
85
+ signals.push({
86
+ source: this.config.name,
87
+ type: this.config.type,
88
+ issueIdentifier: id,
89
+ payload,
90
+ receivedAt,
91
+ });
92
+ }
93
+ }
94
+ }
95
+ return signals;
96
+ }
97
+ }
98
+ //# sourceMappingURL=github-pr.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github-pr.js","sourceRoot":"","sources":["../../src/signals/github-pr.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,8 @@
1
1
  export * from "./external-command.js";
2
+ export * from "./github-commits.js";
3
+ export * from "./github-pr.js";
4
+ export * from "./linear-issues.js";
2
5
  export * from "./registry.js";
6
+ export * from "./slack-messages.js";
3
7
  export * from "./types.js";
4
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/signals/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/signals/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC;AACpC,cAAc,YAAY,CAAC"}
@@ -1,4 +1,8 @@
1
1
  export * from "./external-command.js";
2
+ export * from "./github-commits.js";
3
+ export * from "./github-pr.js";
4
+ export * from "./linear-issues.js";
2
5
  export * from "./registry.js";
6
+ export * from "./slack-messages.js";
3
7
  export * from "./types.js";
4
8
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/signals/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/signals/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC;AACpC,cAAc,YAAY,CAAC"}
@@ -0,0 +1,20 @@
1
+ import type { Signal, SignalSourceContext, SignalSourceImpl } from "./types.js";
2
+ export interface LinearIssuesConfig {
3
+ type: "linear_issues";
4
+ name: string;
5
+ enabled?: boolean;
6
+ teams?: string[];
7
+ lookback_days?: number;
8
+ near_duplicate_threshold?: number;
9
+ }
10
+ /**
11
+ * Jaccard similarity over whitespace-tokenised word sets.
12
+ * Cheap, language-agnostic, good enough for "did someone just file the same thing".
13
+ */
14
+ export declare function titleSimilarity(a: string, b: string): number;
15
+ export declare class LinearIssuesSource implements SignalSourceImpl {
16
+ readonly config: LinearIssuesConfig;
17
+ constructor(config: LinearIssuesConfig);
18
+ collect(ctx: SignalSourceContext): Promise<Signal[]>;
19
+ }
20
+ //# sourceMappingURL=linear-issues.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"linear-issues.d.ts","sourceRoot":"","sources":["../../src/signals/linear-issues.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,MAAM,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAIhF,MAAM,WAAW,kBAAkB;IAClC,IAAI,EAAE,eAAe,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,wBAAwB,CAAC,EAAE,MAAM,CAAC;CAClC;AASD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAQ5D;AAED,qBAAa,kBAAmB,YAAW,gBAAgB;IAC1D,QAAQ,CAAC,MAAM,EAAE,kBAAkB,CAAC;gBAExB,MAAM,EAAE,kBAAkB;IAIhC,OAAO,CAAC,GAAG,EAAE,mBAAmB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;CAyE1D"}
@@ -0,0 +1,115 @@
1
+ // `linear_issues` signal source.
2
+ //
3
+ // Cross-issue scanning against Linear itself. Surfaces title near-duplicates,
4
+ // issues that mention other issue IDs in description, and orphan candidates
5
+ // (no project, no assignee, no parent). Used by curator M5 (title near-dup)
6
+ // and H3 (duplicate-of-Done) class rules.
7
+ //
8
+ // Uses the bulk-graphql helper to keep round-trips low — one paginated query
9
+ // returns identifier + title + description + state.type + project + assignee
10
+ // + parent in a single GraphQL call.
11
+ import { bulkListIssues } from "../lib/bulk-graphql.js";
12
+ import { _internal as commitsInternal } from "./github-commits.js";
13
+ const DEFAULT_LOOKBACK_DAYS = 30;
14
+ function normaliseTitle(title) {
15
+ return title
16
+ .toLowerCase()
17
+ .replace(/[^\p{L}\p{N}]+/gu, " ")
18
+ .trim();
19
+ }
20
+ /**
21
+ * Jaccard similarity over whitespace-tokenised word sets.
22
+ * Cheap, language-agnostic, good enough for "did someone just file the same thing".
23
+ */
24
+ export function titleSimilarity(a, b) {
25
+ const ta = new Set(normaliseTitle(a).split(/\s+/).filter(Boolean));
26
+ const tb = new Set(normaliseTitle(b).split(/\s+/).filter(Boolean));
27
+ if (ta.size === 0 || tb.size === 0)
28
+ return 0;
29
+ let inter = 0;
30
+ for (const t of ta)
31
+ if (tb.has(t))
32
+ inter++;
33
+ const union = ta.size + tb.size - inter;
34
+ return union === 0 ? 0 : inter / union;
35
+ }
36
+ export class LinearIssuesSource {
37
+ config;
38
+ constructor(config) {
39
+ this.config = config;
40
+ }
41
+ async collect(ctx) {
42
+ const receivedAt = ctx.now.toISOString();
43
+ const lookbackDays = this.config.lookback_days ?? DEFAULT_LOOKBACK_DAYS;
44
+ const threshold = this.config.near_duplicate_threshold ?? 0.7;
45
+ const cutoff = new Date(ctx.now.getTime() - lookbackDays * 24 * 3600 * 1000).toISOString();
46
+ const filter = { updatedAt: { gt: cutoff } };
47
+ if (this.config.teams && this.config.teams.length > 0) {
48
+ filter.team = { key: { in: this.config.teams } };
49
+ }
50
+ const nodes = await bulkListIssues(filter, { includeDescription: true, includeRelations: true });
51
+ const signals = [];
52
+ const teamKeys = [...new Set(nodes.map((n) => n.team?.key).filter((k) => Boolean(k)))];
53
+ const issueRegex = commitsInternal.buildTeamRegex(teamKeys);
54
+ const knownIds = new Set(nodes.map((n) => n.identifier));
55
+ for (const node of nodes) {
56
+ if (!node.description)
57
+ continue;
58
+ const refs = commitsInternal.extractIssueIds(node.description, issueRegex);
59
+ for (const ref of refs) {
60
+ if (ref === node.identifier)
61
+ continue;
62
+ if (!knownIds.has(ref))
63
+ continue;
64
+ signals.push({
65
+ source: this.config.name,
66
+ type: this.config.type,
67
+ issueIdentifier: node.identifier,
68
+ payload: { kind: "cross_reference", references: ref },
69
+ receivedAt,
70
+ });
71
+ }
72
+ }
73
+ for (let i = 0; i < nodes.length; i++) {
74
+ for (let j = i + 1; j < nodes.length; j++) {
75
+ const a = nodes[i];
76
+ const b = nodes[j];
77
+ if (a.team?.key !== b.team?.key)
78
+ continue;
79
+ const sim = titleSimilarity(a.title, b.title);
80
+ if (sim < threshold)
81
+ continue;
82
+ signals.push({
83
+ source: this.config.name,
84
+ type: this.config.type,
85
+ issueIdentifier: a.identifier,
86
+ payload: {
87
+ kind: "near_duplicate",
88
+ with: b.identifier,
89
+ similarity: Math.round(sim * 100) / 100,
90
+ },
91
+ receivedAt,
92
+ });
93
+ }
94
+ }
95
+ for (const node of nodes) {
96
+ if (node.state?.type !== "unstarted" && node.state?.type !== "backlog")
97
+ continue;
98
+ if (node.project || node.assignee || node.parent)
99
+ continue;
100
+ signals.push({
101
+ source: this.config.name,
102
+ type: this.config.type,
103
+ issueIdentifier: node.identifier,
104
+ payload: {
105
+ kind: "orphan",
106
+ title: node.title,
107
+ state: node.state?.name ?? null,
108
+ },
109
+ receivedAt,
110
+ });
111
+ }
112
+ return signals;
113
+ }
114
+ }
115
+ //# sourceMappingURL=linear-issues.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"linear-issues.js","sourceRoot":"","sources":["../../src/signals/linear-issues.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,6 @@
1
- import type { SignalSource as ConfigSignalSource } from "../config/types.js";
1
+ import type { SignalSource as ConfigSignalSource, LinearConfig } from "../config/types.js";
2
2
  import type { SignalSourceImpl } from "./types.js";
3
- export declare const IMPLEMENTED_SIGNAL_SOURCE_TYPES: readonly ["external_command"];
4
- export declare function buildSignalSource(config: ConfigSignalSource): SignalSourceImpl;
3
+ export declare const IMPLEMENTED_SIGNAL_SOURCE_TYPES: readonly ["external_command", "github_commits", "github_pr", "slack_messages", "linear_issues"];
4
+ export declare const EXTERNAL_COMMAND_ENV_FLAG = "LINEAR_ALLOW_EXTERNAL_COMMAND";
5
+ export declare function buildSignalSource(config: ConfigSignalSource, linearConfig: LinearConfig): SignalSourceImpl;
5
6
  //# sourceMappingURL=registry.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/signals/registry.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,YAAY,IAAI,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAG7E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD,eAAO,MAAM,+BAA+B,+BAAgC,CAAC;AAU7E,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,kBAAkB,GAAG,gBAAgB,CAc9E"}
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/signals/registry.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,YAAY,IAAI,kBAAkB,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAO3F,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD,eAAO,MAAM,+BAA+B,iGAMlC,CAAC;AAIX,eAAO,MAAM,yBAAyB,kCAAkC,CAAC;AAOzE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,kBAAkB,EAAE,YAAY,EAAE,YAAY,GAAG,gBAAgB,CA2B1G"}
@@ -1,24 +1,46 @@
1
1
  // Build a runtime SignalSource from a config entry.
2
2
  //
3
- // Only `external_command` is implemented in this PR. The other config types
4
- // declared in schemas/signal-sources.json (github_commits, github_pr,
5
- // slack_messages, linear_issues, mcp_tool) throw a "not yet implemented"
6
- // error so they surface clearly in curator reports rather than silently
7
- // being skipped. Adding a new type means: implement a SignalSourceImpl,
8
- // register it here, and add it to IMPLEMENTED_SIGNAL_SOURCE_TYPES.
3
+ // Implementations are:
4
+ // external_command — generic shell extension point
5
+ // github_commits — git log on configured local repos
6
+ // github_pr — gh CLI against the configured GitHub repos
7
+ // slack_messages — Slack conversations.history via SLACK_TOKEN
8
+ // linear_issues — cross-issue scans (near-dup, x-ref, orphans)
9
+ //
10
+ // `mcp_tool` is declared in the schema but deferred to a future release.
9
11
  import { ExternalCommandSource } from "./external-command.js";
10
- export const IMPLEMENTED_SIGNAL_SOURCE_TYPES = ["external_command"];
11
- const DECLARED_BUT_NOT_IMPLEMENTED = new Set([
12
+ import { GithubCommitsSource } from "./github-commits.js";
13
+ import { GithubPrSource } from "./github-pr.js";
14
+ import { LinearIssuesSource } from "./linear-issues.js";
15
+ import { SlackMessagesSource } from "./slack-messages.js";
16
+ export const IMPLEMENTED_SIGNAL_SOURCE_TYPES = [
17
+ "external_command",
12
18
  "github_commits",
13
19
  "github_pr",
14
20
  "slack_messages",
15
21
  "linear_issues",
16
- "mcp_tool",
17
- ]);
18
- export function buildSignalSource(config) {
22
+ ];
23
+ const DECLARED_BUT_NOT_IMPLEMENTED = new Set(["mcp_tool"]);
24
+ export const EXTERNAL_COMMAND_ENV_FLAG = "LINEAR_ALLOW_EXTERNAL_COMMAND";
25
+ function externalCommandAllowed() {
26
+ const v = process.env[EXTERNAL_COMMAND_ENV_FLAG];
27
+ return v === "1" || v === "true";
28
+ }
29
+ export function buildSignalSource(config, linearConfig) {
19
30
  switch (config.type) {
20
31
  case "external_command":
32
+ if (!externalCommandAllowed()) {
33
+ throw new Error(`Signal source "${config.name}" is type "external_command" which executes arbitrary commands from references/signal-sources.json. Refusing to load: set ${EXTERNAL_COMMAND_ENV_FLAG}=1 to opt in. See SAFETY.md for details.`);
34
+ }
21
35
  return new ExternalCommandSource(config);
36
+ case "github_commits":
37
+ return new GithubCommitsSource(config, linearConfig);
38
+ case "github_pr":
39
+ return new GithubPrSource(config, linearConfig);
40
+ case "slack_messages":
41
+ return new SlackMessagesSource(config, linearConfig);
42
+ case "linear_issues":
43
+ return new LinearIssuesSource(config);
22
44
  default:
23
45
  if (DECLARED_BUT_NOT_IMPLEMENTED.has(config.type)) {
24
46
  throw new Error(`Signal source type "${config.type}" is declared in the schema but not yet implemented in this version. Currently supported: ${IMPLEMENTED_SIGNAL_SOURCE_TYPES.join(", ")}.`);
@@ -1 +1 @@
1
- {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/signals/registry.ts"],"names":[],"mappings":"AAAA,oDAAoD;AACpD,EAAE;AACF,4EAA4E;AAC5E,sEAAsE;AACtE,yEAAyE;AACzE,wEAAwE;AACxE,wEAAwE;AACxE,mEAAmE;AAInE,OAAO,EAA8B,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAG1F,MAAM,CAAC,MAAM,+BAA+B,GAAG,CAAC,kBAAkB,CAAU,CAAC;AAE7E,MAAM,4BAA4B,GAAwB,IAAI,GAAG,CAAC;IACjE,gBAAgB;IAChB,WAAW;IACX,gBAAgB;IAChB,eAAe;IACf,UAAU;CACV,CAAC,CAAC;AAEH,MAAM,UAAU,iBAAiB,CAAC,MAA0B;IAC3D,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;QACrB,KAAK,kBAAkB;YACtB,OAAO,IAAI,qBAAqB,CAAC,MAA+B,CAAC,CAAC;QACnE;YACC,IAAI,4BAA4B,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;gBACnD,MAAM,IAAI,KAAK,CACd,uBAAuB,MAAM,CAAC,IAAI,6FAA6F,+BAA+B,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAC5K,CAAC;YACH,CAAC;YACD,MAAM,IAAI,KAAK,CACd,+BAA+B,MAAM,CAAC,IAAI,iBAAiB,+BAA+B,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CACxG,CAAC;IACJ,CAAC;AACF,CAAC"}
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/signals/registry.ts"],"names":[],"mappings":"AAAA,oDAAoD;AACpD,EAAE;AACF,uBAAuB;AACvB,uDAAuD;AACvD,2DAA2D;AAC3D,oEAAoE;AACpE,qEAAqE;AACrE,sEAAsE;AACtE,EAAE;AACF,yEAAyE;AAIzE,OAAO,EAA8B,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC1F,OAAO,EAA4B,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AACpF,OAAO,EAAuB,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACrE,OAAO,EAA2B,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACjF,OAAO,EAA4B,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAGpF,MAAM,CAAC,MAAM,+BAA+B,GAAG;IAC9C,kBAAkB;IAClB,gBAAgB;IAChB,WAAW;IACX,gBAAgB;IAChB,eAAe;CACN,CAAC;AAEX,MAAM,4BAA4B,GAAwB,IAAI,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;AAEhF,MAAM,CAAC,MAAM,yBAAyB,GAAG,+BAA+B,CAAC;AAEzE,SAAS,sBAAsB;IAC9B,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;IACjD,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,MAAM,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,MAA0B,EAAE,YAA0B;IACvF,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;QACrB,KAAK,kBAAkB;YACtB,IAAI,CAAC,sBAAsB,EAAE,EAAE,CAAC;gBAC/B,MAAM,IAAI,KAAK,CACd,kBAAkB,MAAM,CAAC,IAAI,6HAA6H,yBAAyB,0CAA0C,CAC7N,CAAC;YACH,CAAC;YACD,OAAO,IAAI,qBAAqB,CAAC,MAA+B,CAAC,CAAC;QACnE,KAAK,gBAAgB;YACpB,OAAO,IAAI,mBAAmB,CAAC,MAA6B,EAAE,YAAY,CAAC,CAAC;QAC7E,KAAK,WAAW;YACf,OAAO,IAAI,cAAc,CAAC,MAAwB,EAAE,YAAY,CAAC,CAAC;QACnE,KAAK,gBAAgB;YACpB,OAAO,IAAI,mBAAmB,CAAC,MAA6B,EAAE,YAAY,CAAC,CAAC;QAC7E,KAAK,eAAe;YACnB,OAAO,IAAI,kBAAkB,CAAC,MAA4B,CAAC,CAAC;QAC7D;YACC,IAAI,4BAA4B,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;gBACnD,MAAM,IAAI,KAAK,CACd,uBAAuB,MAAM,CAAC,IAAI,6FAA6F,+BAA+B,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAC5K,CAAC;YACH,CAAC;YACD,MAAM,IAAI,KAAK,CACd,+BAA+B,MAAM,CAAC,IAAI,iBAAiB,+BAA+B,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CACxG,CAAC;IACJ,CAAC;AACF,CAAC"}
@@ -0,0 +1,20 @@
1
+ import type { LinearConfig } from "../config/types.js";
2
+ import type { Signal, SignalSourceContext, SignalSourceImpl } from "./types.js";
3
+ export interface SlackMessagesConfig {
4
+ type: "slack_messages";
5
+ name: string;
6
+ enabled?: boolean;
7
+ channels?: string[];
8
+ match_patterns?: string[];
9
+ lookback_hours?: number;
10
+ }
11
+ type FetchLike = typeof fetch;
12
+ export declare function setSlackFetchForTesting(impl: FetchLike | null): void;
13
+ export declare class SlackMessagesSource implements SignalSourceImpl {
14
+ readonly config: SlackMessagesConfig;
15
+ private readonly linearConfig;
16
+ constructor(config: SlackMessagesConfig, linearConfig: LinearConfig);
17
+ collect(ctx: SignalSourceContext): Promise<Signal[]>;
18
+ }
19
+ export {};
20
+ //# sourceMappingURL=slack-messages.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slack-messages.d.ts","sourceRoot":"","sources":["../../src/signals/slack-messages.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,OAAO,KAAK,EAAE,MAAM,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAOhF,MAAM,WAAW,mBAAmB;IACnC,IAAI,EAAE,gBAAgB,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB;AAeD,KAAK,SAAS,GAAG,OAAO,KAAK,CAAC;AAE9B,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI,GAAG,IAAI,CAEpE;AAOD,qBAAa,mBAAoB,YAAW,gBAAgB;IAC3D,QAAQ,CAAC,MAAM,EAAE,mBAAmB,CAAC;IACrC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAe;gBAEhC,MAAM,EAAE,mBAAmB,EAAE,YAAY,EAAE,YAAY;IAK7D,OAAO,CAAC,GAAG,EAAE,mBAAmB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;CAqG1D"}
@@ -0,0 +1,129 @@
1
+ // `slack_messages` signal source.
2
+ //
3
+ // Polls Slack `conversations.history` for the configured channel IDs and
4
+ // filters messages by `match_patterns` — each pattern is compiled to a
5
+ // case-insensitive, word-boundary regex (so "prod" doesn't match "reproduce").
6
+ // Regex metacharacters in the user-supplied pattern are escaped. Issue
7
+ // identifiers in matched messages are extracted via the team-prefix regex
8
+ // derived from references/teams.json.
9
+ //
10
+ // Auth: requires SLACK_TOKEN (Bot or User token) in the environment. Without
11
+ // it the source emits one warning signal and returns.
12
+ import { _internal as commitsInternal } from "./github-commits.js";
13
+ const SLACK_API = "https://slack.com/api";
14
+ const DEFAULT_LOOKBACK_HOURS = 24;
15
+ const HISTORY_LIMIT = 200;
16
+ const TIMEOUT_MS = 30_000;
17
+ let fetchImpl = fetch;
18
+ export function setSlackFetchForTesting(impl) {
19
+ fetchImpl = impl ?? fetch;
20
+ }
21
+ function toWordBoundaryRegex(pattern) {
22
+ const escaped = pattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
23
+ return new RegExp(`\\b${escaped}\\b`, "i");
24
+ }
25
+ export class SlackMessagesSource {
26
+ config;
27
+ linearConfig;
28
+ constructor(config, linearConfig) {
29
+ this.config = config;
30
+ this.linearConfig = linearConfig;
31
+ }
32
+ async collect(ctx) {
33
+ const receivedAt = ctx.now.toISOString();
34
+ const token = process.env.SLACK_TOKEN;
35
+ if (!token) {
36
+ return [
37
+ {
38
+ source: this.config.name,
39
+ type: this.config.type,
40
+ payload: { warning: "SLACK_TOKEN not set; skipped" },
41
+ receivedAt,
42
+ },
43
+ ];
44
+ }
45
+ const teamKeys = this.linearConfig.teams.teams.map((t) => t.key);
46
+ const issueRegex = commitsInternal.buildTeamRegex(teamKeys);
47
+ // Compile each match pattern as a case-insensitive, word-boundary regex
48
+ // so e.g. "prod" doesn't fire on "reproduce" or "qa" on "equal". Anything
49
+ // that doesn't compile (user-supplied regex metachars) is treated as a
50
+ // plain word and escaped.
51
+ const patterns = (this.config.match_patterns ?? []).map(toWordBoundaryRegex);
52
+ const lookback = (this.config.lookback_hours ?? DEFAULT_LOOKBACK_HOURS) * 3600;
53
+ const oldest = (ctx.now.getTime() / 1000 - lookback).toFixed(3);
54
+ const channels = this.config.channels && this.config.channels.length > 0
55
+ ? this.config.channels
56
+ : this.linearConfig.slack.allowed_channels;
57
+ const signals = [];
58
+ for (const channel of channels) {
59
+ let payload;
60
+ try {
61
+ const url = new URL(`${SLACK_API}/conversations.history`);
62
+ url.searchParams.set("channel", channel);
63
+ url.searchParams.set("limit", String(HISTORY_LIMIT));
64
+ url.searchParams.set("oldest", oldest);
65
+ const controller = new AbortController();
66
+ const timer = setTimeout(() => controller.abort(), TIMEOUT_MS);
67
+ let res;
68
+ try {
69
+ res = await fetchImpl(url, {
70
+ headers: { Authorization: `Bearer ${token}` },
71
+ signal: controller.signal,
72
+ });
73
+ }
74
+ finally {
75
+ clearTimeout(timer);
76
+ }
77
+ payload = (await res.json());
78
+ }
79
+ catch (err) {
80
+ signals.push({
81
+ source: this.config.name,
82
+ type: this.config.type,
83
+ payload: { warning: `slack history failed for "${channel}": ${err.message}` },
84
+ receivedAt,
85
+ });
86
+ continue;
87
+ }
88
+ if (!payload.ok) {
89
+ signals.push({
90
+ source: this.config.name,
91
+ type: this.config.type,
92
+ payload: { warning: `slack returned error for "${channel}": ${payload.error ?? "unknown"}` },
93
+ receivedAt,
94
+ });
95
+ continue;
96
+ }
97
+ for (const msg of payload.messages ?? []) {
98
+ if (!msg.text)
99
+ continue;
100
+ if (msg.subtype === "bot_message" || msg.subtype === "channel_join")
101
+ continue;
102
+ if (patterns.length > 0 && !patterns.some((re) => re.test(msg.text)))
103
+ continue;
104
+ const ids = commitsInternal.extractIssueIds(msg.text, issueRegex);
105
+ const base = {
106
+ channel,
107
+ ts: msg.ts,
108
+ user: msg.user ?? null,
109
+ text: msg.text,
110
+ };
111
+ if (ids.length === 0) {
112
+ signals.push({ source: this.config.name, type: this.config.type, payload: base, receivedAt });
113
+ continue;
114
+ }
115
+ for (const id of ids) {
116
+ signals.push({
117
+ source: this.config.name,
118
+ type: this.config.type,
119
+ issueIdentifier: id,
120
+ payload: base,
121
+ receivedAt,
122
+ });
123
+ }
124
+ }
125
+ }
126
+ return signals;
127
+ }
128
+ }
129
+ //# sourceMappingURL=slack-messages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slack-messages.js","sourceRoot":"","sources":["../../src/signals/slack-messages.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Dedicated exit codes per error type.
3
+ * 0 = success, 1 = general/unknown, 2 = validation, 3 = auth, 4 = not found.
4
+ */
5
+ export declare const EXIT_CODES: {
6
+ readonly SUCCESS: 0;
7
+ readonly GENERAL: 1;
8
+ readonly VALIDATION: 2;
9
+ readonly AUTH: 3;
10
+ readonly NOT_FOUND: 4;
11
+ };
12
+ export declare class CliError extends Error {
13
+ readonly userMessage: string;
14
+ readonly suggestion?: string;
15
+ readonly exitCode: number;
16
+ /**
17
+ * Optional structured payload merged into the JSON error envelope. Used by
18
+ * validation errors that need to expose machine-readable detail (e.g. which
19
+ * labels are missing, what the team's accepted set is) so an agent can
20
+ * self-correct without re-reading reference files.
21
+ */
22
+ readonly data?: Record<string, unknown>;
23
+ constructor(message: string, options?: {
24
+ suggestion?: string;
25
+ exitCode?: number;
26
+ data?: Record<string, unknown>;
27
+ });
28
+ }
29
+ export declare class AuthError extends CliError {
30
+ constructor(message?: string);
31
+ }
32
+ export declare class NotFoundError extends CliError {
33
+ constructor(entity: string, identifier: string);
34
+ }
35
+ export declare class ValidationError extends CliError {
36
+ constructor(message: string, suggestion?: string, data?: Record<string, unknown>);
37
+ }
38
+ /**
39
+ * Specialized validation error for label-policy violations on `issues create`.
40
+ * The structured `data` field is the load-bearing part — agents read it to
41
+ * self-correct in one retry instead of re-reading workspace-labels.md.
42
+ */
43
+ export declare class LabelValidationError extends ValidationError {
44
+ constructor(data: {
45
+ error: "labels_invalid";
46
+ team: string;
47
+ teamKey: string;
48
+ missing: {
49
+ prefixes: string[];
50
+ min: number;
51
+ description?: string;
52
+ }[];
53
+ excess: {
54
+ prefixes: string[];
55
+ max: number;
56
+ passed: string[];
57
+ }[];
58
+ passed: string[];
59
+ availableForPrefix: Record<string, string[]>;
60
+ suggestedRetry: string;
61
+ });
62
+ }
63
+ //# sourceMappingURL=errors.d.ts.map