@elnora-ai/linear 1.0.1 → 2.0.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 (302) hide show
  1. package/.claude-plugin/marketplace.json +7 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +25 -1
  4. package/README.md +275 -25
  5. package/agents/linear-issue-creator.md +135 -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 +190 -26
  10. package/commands/linear-cleanup.md +64 -29
  11. package/dist/cli.js +69 -1
  12. package/dist/cli.js.map +1 -1
  13. package/dist/client/auth.d.ts +10 -0
  14. package/dist/client/auth.d.ts.map +1 -1
  15. package/dist/client/auth.js +50 -3
  16. package/dist/client/auth.js.map +1 -1
  17. package/dist/client/linear-client.d.ts +7 -0
  18. package/dist/client/linear-client.d.ts.map +1 -1
  19. package/dist/client/linear-client.js +13 -1
  20. package/dist/client/linear-client.js.map +1 -1
  21. package/dist/commands/agent-activities.d.ts +3 -0
  22. package/dist/commands/agent-activities.d.ts.map +1 -0
  23. package/dist/commands/agent-activities.js +144 -0
  24. package/dist/commands/agent-activities.js.map +1 -0
  25. package/dist/commands/agent-sessions.d.ts +3 -0
  26. package/dist/commands/agent-sessions.d.ts.map +1 -0
  27. package/dist/commands/agent-sessions.js +132 -0
  28. package/dist/commands/agent-sessions.js.map +1 -0
  29. package/dist/commands/attachments.d.ts +3 -0
  30. package/dist/commands/attachments.d.ts.map +1 -0
  31. package/dist/commands/attachments.js +265 -0
  32. package/dist/commands/attachments.js.map +1 -0
  33. package/dist/commands/audit.d.ts +3 -0
  34. package/dist/commands/audit.d.ts.map +1 -0
  35. package/dist/commands/audit.js +73 -0
  36. package/dist/commands/audit.js.map +1 -0
  37. package/dist/commands/comments.d.ts +3 -0
  38. package/dist/commands/comments.d.ts.map +1 -0
  39. package/dist/commands/comments.js +107 -0
  40. package/dist/commands/comments.js.map +1 -0
  41. package/dist/commands/completion.d.ts +3 -0
  42. package/dist/commands/completion.d.ts.map +1 -0
  43. package/dist/commands/completion.js +62 -0
  44. package/dist/commands/completion.js.map +1 -0
  45. package/dist/commands/context.d.ts +3 -0
  46. package/dist/commands/context.d.ts.map +1 -0
  47. package/dist/commands/context.js +94 -0
  48. package/dist/commands/context.js.map +1 -0
  49. package/dist/commands/curator.d.ts +14 -0
  50. package/dist/commands/curator.d.ts.map +1 -1
  51. package/dist/commands/curator.js +97 -19
  52. package/dist/commands/curator.js.map +1 -1
  53. package/dist/commands/customer-needs.d.ts +3 -0
  54. package/dist/commands/customer-needs.d.ts.map +1 -0
  55. package/dist/commands/customer-needs.js +198 -0
  56. package/dist/commands/customer-needs.js.map +1 -0
  57. package/dist/commands/customers.d.ts +5 -0
  58. package/dist/commands/customers.d.ts.map +1 -0
  59. package/dist/commands/customers.js +201 -0
  60. package/dist/commands/customers.js.map +1 -0
  61. package/dist/commands/cycles.d.ts +3 -0
  62. package/dist/commands/cycles.d.ts.map +1 -0
  63. package/dist/commands/cycles.js +67 -0
  64. package/dist/commands/cycles.js.map +1 -0
  65. package/dist/commands/documents.d.ts +3 -0
  66. package/dist/commands/documents.d.ts.map +1 -0
  67. package/dist/commands/documents.js +105 -0
  68. package/dist/commands/documents.js.map +1 -0
  69. package/dist/commands/favorites.d.ts +3 -0
  70. package/dist/commands/favorites.d.ts.map +1 -0
  71. package/dist/commands/favorites.js +101 -0
  72. package/dist/commands/favorites.js.map +1 -0
  73. package/dist/commands/index.d.ts +30 -0
  74. package/dist/commands/index.d.ts.map +1 -1
  75. package/dist/commands/index.js +30 -0
  76. package/dist/commands/index.js.map +1 -1
  77. package/dist/commands/initiatives.d.ts +3 -0
  78. package/dist/commands/initiatives.d.ts.map +1 -0
  79. package/dist/commands/initiatives.js +106 -0
  80. package/dist/commands/initiatives.js.map +1 -0
  81. package/dist/commands/issues.d.ts +21 -0
  82. package/dist/commands/issues.d.ts.map +1 -0
  83. package/dist/commands/issues.js +1083 -0
  84. package/dist/commands/issues.js.map +1 -0
  85. package/dist/commands/labels.d.ts +3 -0
  86. package/dist/commands/labels.d.ts.map +1 -0
  87. package/dist/commands/labels.js +111 -0
  88. package/dist/commands/labels.js.map +1 -0
  89. package/dist/commands/milestones.d.ts +3 -0
  90. package/dist/commands/milestones.d.ts.map +1 -0
  91. package/dist/commands/milestones.js +94 -0
  92. package/dist/commands/milestones.js.map +1 -0
  93. package/dist/commands/notifications.d.ts +3 -0
  94. package/dist/commands/notifications.d.ts.map +1 -0
  95. package/dist/commands/notifications.js +130 -0
  96. package/dist/commands/notifications.js.map +1 -0
  97. package/dist/commands/project-labels.d.ts +3 -0
  98. package/dist/commands/project-labels.d.ts.map +1 -0
  99. package/dist/commands/project-labels.js +80 -0
  100. package/dist/commands/project-labels.js.map +1 -0
  101. package/dist/commands/project-relations.d.ts +3 -0
  102. package/dist/commands/project-relations.d.ts.map +1 -0
  103. package/dist/commands/project-relations.js +96 -0
  104. package/dist/commands/project-relations.js.map +1 -0
  105. package/dist/commands/projects.d.ts +3 -0
  106. package/dist/commands/projects.d.ts.map +1 -0
  107. package/dist/commands/projects.js +263 -0
  108. package/dist/commands/projects.js.map +1 -0
  109. package/dist/commands/quota.d.ts +3 -0
  110. package/dist/commands/quota.d.ts.map +1 -0
  111. package/dist/commands/quota.js +28 -0
  112. package/dist/commands/quota.js.map +1 -0
  113. package/dist/commands/reactions.d.ts +7 -0
  114. package/dist/commands/reactions.d.ts.map +1 -0
  115. package/dist/commands/reactions.js +53 -0
  116. package/dist/commands/reactions.js.map +1 -0
  117. package/dist/commands/relations.d.ts +3 -0
  118. package/dist/commands/relations.d.ts.map +1 -0
  119. package/dist/commands/relations.js +73 -0
  120. package/dist/commands/relations.js.map +1 -0
  121. package/dist/commands/states.d.ts +3 -0
  122. package/dist/commands/states.d.ts.map +1 -0
  123. package/dist/commands/states.js +52 -0
  124. package/dist/commands/states.js.map +1 -0
  125. package/dist/commands/status-updates.d.ts +3 -0
  126. package/dist/commands/status-updates.d.ts.map +1 -0
  127. package/dist/commands/status-updates.js +117 -0
  128. package/dist/commands/status-updates.js.map +1 -0
  129. package/dist/commands/sync.d.ts.map +1 -1
  130. package/dist/commands/sync.js +58 -18
  131. package/dist/commands/sync.js.map +1 -1
  132. package/dist/commands/teams.d.ts +3 -0
  133. package/dist/commands/teams.d.ts.map +1 -0
  134. package/dist/commands/teams.js +135 -0
  135. package/dist/commands/teams.js.map +1 -0
  136. package/dist/commands/templates.d.ts +3 -0
  137. package/dist/commands/templates.d.ts.map +1 -0
  138. package/dist/commands/templates.js +76 -0
  139. package/dist/commands/templates.js.map +1 -0
  140. package/dist/commands/users.d.ts +3 -0
  141. package/dist/commands/users.d.ts.map +1 -0
  142. package/dist/commands/users.js +40 -0
  143. package/dist/commands/users.js.map +1 -0
  144. package/dist/commands/views.d.ts +3 -0
  145. package/dist/commands/views.d.ts.map +1 -0
  146. package/dist/commands/views.js +177 -0
  147. package/dist/commands/views.js.map +1 -0
  148. package/dist/commands/webhooks.d.ts +3 -0
  149. package/dist/commands/webhooks.d.ts.map +1 -0
  150. package/dist/commands/webhooks.js +234 -0
  151. package/dist/commands/webhooks.js.map +1 -0
  152. package/dist/config/loader.d.ts.map +1 -1
  153. package/dist/config/loader.js +3 -0
  154. package/dist/config/loader.js.map +1 -1
  155. package/dist/config/types.d.ts +15 -1
  156. package/dist/config/types.d.ts.map +1 -1
  157. package/dist/config/types.js +1 -0
  158. package/dist/config/types.js.map +1 -1
  159. package/dist/curator/dispatch.d.ts +52 -0
  160. package/dist/curator/dispatch.d.ts.map +1 -0
  161. package/dist/curator/dispatch.js +144 -0
  162. package/dist/curator/dispatch.js.map +1 -0
  163. package/dist/curator/index.d.ts +5 -0
  164. package/dist/curator/index.d.ts.map +1 -0
  165. package/dist/curator/index.js +5 -0
  166. package/dist/curator/index.js.map +1 -0
  167. package/dist/curator/llm.d.ts +70 -0
  168. package/dist/curator/llm.d.ts.map +1 -0
  169. package/dist/curator/llm.js +107 -0
  170. package/dist/curator/llm.js.map +1 -0
  171. package/dist/curator/snapshot.d.ts +34 -0
  172. package/dist/curator/snapshot.d.ts.map +1 -0
  173. package/dist/curator/snapshot.js +127 -0
  174. package/dist/curator/snapshot.js.map +1 -0
  175. package/dist/curator/state.d.ts +50 -0
  176. package/dist/curator/state.d.ts.map +1 -0
  177. package/dist/curator/state.js +125 -0
  178. package/dist/curator/state.js.map +1 -0
  179. package/dist/lib/bulk-graphql.d.ts +144 -0
  180. package/dist/lib/bulk-graphql.d.ts.map +1 -0
  181. package/dist/lib/bulk-graphql.js +380 -0
  182. package/dist/lib/bulk-graphql.js.map +1 -0
  183. package/dist/lib/index.d.ts +2 -0
  184. package/dist/lib/index.d.ts.map +1 -0
  185. package/dist/lib/index.js +2 -0
  186. package/dist/lib/index.js.map +1 -0
  187. package/dist/output/cli.d.ts +17 -0
  188. package/dist/output/cli.d.ts.map +1 -0
  189. package/dist/output/cli.js +252 -0
  190. package/dist/output/cli.js.map +1 -0
  191. package/dist/output/formatter.d.ts +6 -0
  192. package/dist/output/formatter.d.ts.map +1 -1
  193. package/dist/output/formatter.js +10 -0
  194. package/dist/output/formatter.js.map +1 -1
  195. package/dist/output/index.d.ts +1 -0
  196. package/dist/output/index.d.ts.map +1 -1
  197. package/dist/output/index.js +1 -0
  198. package/dist/output/index.js.map +1 -1
  199. package/dist/scripts/sync-linear-templates.d.ts +26 -0
  200. package/dist/scripts/sync-linear-templates.d.ts.map +1 -0
  201. package/dist/scripts/sync-linear-templates.js +115 -0
  202. package/dist/scripts/sync-linear-templates.js.map +1 -0
  203. package/dist/signals/github-commits.d.ts +31 -0
  204. package/dist/signals/github-commits.d.ts.map +1 -0
  205. package/dist/signals/github-commits.js +127 -0
  206. package/dist/signals/github-commits.js.map +1 -0
  207. package/dist/signals/github-pr.d.ts +16 -0
  208. package/dist/signals/github-pr.d.ts.map +1 -0
  209. package/dist/signals/github-pr.js +98 -0
  210. package/dist/signals/github-pr.js.map +1 -0
  211. package/dist/signals/index.d.ts +4 -0
  212. package/dist/signals/index.d.ts.map +1 -1
  213. package/dist/signals/index.js +4 -0
  214. package/dist/signals/index.js.map +1 -1
  215. package/dist/signals/linear-issues.d.ts +20 -0
  216. package/dist/signals/linear-issues.d.ts.map +1 -0
  217. package/dist/signals/linear-issues.js +115 -0
  218. package/dist/signals/linear-issues.js.map +1 -0
  219. package/dist/signals/registry.d.ts +4 -3
  220. package/dist/signals/registry.d.ts.map +1 -1
  221. package/dist/signals/registry.js +33 -11
  222. package/dist/signals/registry.js.map +1 -1
  223. package/dist/signals/slack-messages.d.ts +20 -0
  224. package/dist/signals/slack-messages.d.ts.map +1 -0
  225. package/dist/signals/slack-messages.js +129 -0
  226. package/dist/signals/slack-messages.js.map +1 -0
  227. package/dist/utils/errors.d.ts +81 -0
  228. package/dist/utils/errors.d.ts.map +1 -0
  229. package/dist/utils/errors.js +110 -0
  230. package/dist/utils/errors.js.map +1 -0
  231. package/dist/utils/index.d.ts +9 -0
  232. package/dist/utils/index.d.ts.map +1 -0
  233. package/dist/utils/index.js +9 -0
  234. package/dist/utils/index.js.map +1 -0
  235. package/dist/utils/label-policy.d.ts +60 -0
  236. package/dist/utils/label-policy.d.ts.map +1 -0
  237. package/dist/utils/label-policy.js +103 -0
  238. package/dist/utils/label-policy.js.map +1 -0
  239. package/dist/utils/parse.d.ts +48 -0
  240. package/dist/utils/parse.d.ts.map +1 -0
  241. package/dist/utils/parse.js +133 -0
  242. package/dist/utils/parse.js.map +1 -0
  243. package/dist/utils/project-status.d.ts +6 -0
  244. package/dist/utils/project-status.d.ts.map +1 -0
  245. package/dist/utils/project-status.js +33 -0
  246. package/dist/utils/project-status.js.map +1 -0
  247. package/dist/utils/rate-limit.d.ts +24 -0
  248. package/dist/utils/rate-limit.d.ts.map +1 -0
  249. package/dist/utils/rate-limit.js +89 -0
  250. package/dist/utils/rate-limit.js.map +1 -0
  251. package/dist/utils/resolve.d.ts +84 -0
  252. package/dist/utils/resolve.d.ts.map +1 -0
  253. package/dist/utils/resolve.js +172 -0
  254. package/dist/utils/resolve.js.map +1 -0
  255. package/dist/utils/sleep.d.ts +2 -0
  256. package/dist/utils/sleep.d.ts.map +1 -0
  257. package/dist/utils/sleep.js +4 -0
  258. package/dist/utils/sleep.js.map +1 -0
  259. package/dist/utils/webhook-verify.d.ts +42 -0
  260. package/dist/utils/webhook-verify.d.ts.map +1 -0
  261. package/dist/utils/webhook-verify.js +65 -0
  262. package/dist/utils/webhook-verify.js.map +1 -0
  263. package/package.json +7 -2
  264. package/references/agent-description-template.md +31 -0
  265. package/references/cli-reference.md +227 -0
  266. package/references/curator-tiering-rules.md +78 -0
  267. package/references/label-policy.example.json +37 -0
  268. package/references/label-policy.placeholder.json +6 -0
  269. package/references/settings-template.md +30 -0
  270. package/references/signal-sources.example.json +0 -8
  271. package/references/sla-reference.md +70 -0
  272. package/references/template-index.md +34 -0
  273. package/references/workspace-labels.md +124 -0
  274. package/references/workspace-projects.md +56 -0
  275. package/references/workspace-routing.md +58 -0
  276. package/schemas/label-policy.json +72 -0
  277. package/scripts/postinstall.mjs +195 -0
  278. package/skills/linear-workspace/SKILL.md +65 -4
  279. package/templates/ACC-PRO-provision.md +74 -0
  280. package/templates/ACC-PRV-privileged.md +66 -0
  281. package/templates/ACC-QTR-review.md +77 -0
  282. package/templates/ACC-REV-revoke.md +67 -0
  283. package/templates/AI-USE-capability.md +111 -0
  284. package/templates/AUD-CAP-corrective.md +89 -0
  285. package/templates/AUD-INT-internal.md +92 -0
  286. package/templates/AUD-MGT-management.md +110 -0
  287. package/templates/CHG-MAJ-major.md +110 -0
  288. package/templates/CHG-SIG-significant.md +83 -0
  289. package/templates/CHG-STD-standard.md +47 -0
  290. package/templates/LRN-DOC-lessons.md +75 -0
  291. package/templates/OPS-BCK-backup.md +99 -0
  292. package/templates/OPS-DAT-data-mod.md +98 -0
  293. package/templates/RCA-DOC-root-cause.md +105 -0
  294. package/templates/RSK-ASS-assessment.md +87 -0
  295. package/templates/RSK-VND-vendor.md +113 -0
  296. package/templates/SEC-INC-incident.md +76 -0
  297. package/templates/SEC-PEN-pentest.md +58 -0
  298. package/templates/SEC-VLN-vulnerability.md +69 -0
  299. package/templates/SLA-AVL-availability.md +86 -0
  300. package/templates/SLA-OPS-operational.md +70 -0
  301. package/templates/agent-server-template/README.md +88 -0
  302. package/templates/agent-server-template/server.example.ts +185 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attachments.js","sourceRoot":"","sources":["../../src/commands/attachments.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from "commander";
2
+ export declare function setupAuditCommand(program: Command): void;
3
+ //# sourceMappingURL=audit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../../src/commands/audit.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQzC,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA8ExD"}
@@ -0,0 +1,73 @@
1
+ // `elnora-linear audit` — read-only access to Linear's audit log.
2
+ //
3
+ // Useful for SOC 2 / compliance evidence pulls. IPs and key IDs/labels redacted
4
+ // by default; opt in via `--unsafe-include-pii` and treat the output as
5
+ // confidential.
6
+ import { getClient } from "../client/index.js";
7
+ import { handleAsyncCommand, outputSuccess, redactAuditEntry } from "../output/index.js";
8
+ import { parseLimit, ValidationError } from "../utils/index.js";
9
+ export function setupAuditCommand(program) {
10
+ const audit = program.command("audit").description("Read Linear audit log entries (compliance / SOC 2 evidence)");
11
+ audit
12
+ .command("entries")
13
+ .description("List audit entries, newest first. IPs and key IDs redacted by default.")
14
+ .option("--limit <n>", "Max results", "50")
15
+ .option("--since <iso>", "Only entries created after this ISO timestamp")
16
+ .option("--type <type>", "Filter by audit entry type (see `audit types`)")
17
+ .option("--unsafe-include-pii", "Return raw IPs, API key IDs/labels, and OAuth client names. Treat output as confidential.")
18
+ .action(handleAsyncCommand(async (opts) => {
19
+ const client = await getClient();
20
+ const filter = {};
21
+ if (opts.since) {
22
+ const d = new Date(String(opts.since));
23
+ if (Number.isNaN(d.getTime())) {
24
+ throw new ValidationError(`Invalid --since: "${opts.since}". Use an ISO timestamp.`);
25
+ }
26
+ filter.createdAt = { gt: d };
27
+ }
28
+ if (opts.type) {
29
+ filter.type = { eq: String(opts.type) };
30
+ }
31
+ const vars = {
32
+ first: parseLimit(typeof opts.limit === "string" ? opts.limit : undefined),
33
+ };
34
+ if (Object.keys(filter).length > 0) {
35
+ vars.filter = filter;
36
+ }
37
+ const conn = await client.auditEntries(vars);
38
+ const entries = await Promise.all(conn.nodes.map(async (e) => {
39
+ const actor = await e.actor;
40
+ return {
41
+ id: e.id,
42
+ type: e.type,
43
+ actor: actor?.name ?? null,
44
+ actorId: e.actorId ?? null,
45
+ countryCode: e.countryCode ?? null,
46
+ ip: e.ip ?? null,
47
+ createdAt: e.createdAt,
48
+ metadata: e.metadata ?? null,
49
+ };
50
+ }));
51
+ if (opts.unsafeIncludePii) {
52
+ process.stderr.write("Warning: --unsafe-include-pii is on; output contains IPs and API key IDs. Treat as confidential.\n");
53
+ outputSuccess({ entries, count: entries.length });
54
+ return;
55
+ }
56
+ const redacted = entries.map((e) => redactAuditEntry(e));
57
+ outputSuccess({ entries: redacted, count: redacted.length });
58
+ }));
59
+ audit
60
+ .command("types")
61
+ .description("List available audit entry types")
62
+ .option("--prefix <str>", "Filter types by case-sensitive prefix")
63
+ .action(handleAsyncCommand(async (opts) => {
64
+ const client = await getClient();
65
+ const types = await client.auditEntryTypes;
66
+ const filtered = opts.prefix ? types.filter((t) => t.type.startsWith(opts.prefix)) : types;
67
+ outputSuccess({
68
+ types: filtered.map((t) => ({ type: t.type, description: t.description })),
69
+ count: filtered.length,
70
+ });
71
+ }));
72
+ }
73
+ //# sourceMappingURL=audit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit.js","sourceRoot":"","sources":["../../src/commands/audit.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from "commander";
2
+ export declare function setupCommentsCommand(program: Command): void;
3
+ //# sourceMappingURL=comments.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"comments.d.ts","sourceRoot":"","sources":["../../src/commands/comments.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AASzC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA0H3D"}
@@ -0,0 +1,107 @@
1
+ // `elnora-linear comments` — manage issue comments.
2
+ //
3
+ // `list` uses raw GraphQL with an embedded user{name} subquery to avoid N+1
4
+ // round-trips when rendering threads.
5
+ import { getClient } from "../client/index.js";
6
+ import { gqlRequest } from "../lib/bulk-graphql.js";
7
+ import { handleAsyncCommand, outputSuccess } from "../output/index.js";
8
+ import { CliError, findIssueByIdentifier, NotFoundError, requireYes } from "../utils/index.js";
9
+ export function setupCommentsCommand(program) {
10
+ const comments = program.command("comments").description("Manage issue comments");
11
+ comments
12
+ .command("list <issueId>")
13
+ .description("List comments on an issue")
14
+ .action(handleAsyncCommand(async (issueId) => {
15
+ const m = issueId.match(/^([A-Z]+)-(\d+)$/);
16
+ const filter = m
17
+ ? { team: { key: { eq: m[1] } }, number: { eq: parseInt(m[2], 10) } }
18
+ : { id: { eq: issueId } };
19
+ const res = await gqlRequest(`query($filter: IssueFilter!) {
20
+ issues(first: 1, filter: $filter) {
21
+ nodes {
22
+ comments(first: 100) {
23
+ nodes { id body createdAt updatedAt user { name } }
24
+ }
25
+ }
26
+ }
27
+ }`, { filter });
28
+ if (res.errors) {
29
+ throw new CliError(`comments list: ${res.errors.map((e) => e.message).join("; ")}`);
30
+ }
31
+ const issue = res.data?.issues.nodes[0];
32
+ if (!issue)
33
+ throw new NotFoundError("Issue", issueId);
34
+ const rows = issue.comments.nodes.map((c) => ({
35
+ id: c.id,
36
+ author: c.user?.name ?? null,
37
+ body: c.body,
38
+ createdAt: c.createdAt,
39
+ updatedAt: c.updatedAt,
40
+ }));
41
+ outputSuccess({ comments: rows, count: rows.length });
42
+ }));
43
+ comments
44
+ .command("create <issueId>")
45
+ .description("Add a comment to an issue")
46
+ .requiredOption("--body <text>", "Comment text (markdown)")
47
+ .action(handleAsyncCommand(async (issueId, opts) => {
48
+ const client = await getClient();
49
+ const issue = await findIssueByIdentifier(client, issueId);
50
+ const input = { issueId: issue.id, body: opts.body };
51
+ const payload = await client.createComment(input);
52
+ if (!payload.success)
53
+ throw new CliError("Failed to create comment");
54
+ const comment = await payload.comment;
55
+ outputSuccess({
56
+ created: true,
57
+ comment: comment ? { id: comment.id, body: comment.body } : null,
58
+ });
59
+ }));
60
+ comments
61
+ .command("update <commentId>")
62
+ .description("Update an existing comment")
63
+ .requiredOption("--body <text>", "New comment text (markdown)")
64
+ .action(handleAsyncCommand(async (commentId, opts) => {
65
+ const client = await getClient();
66
+ const update = { body: opts.body };
67
+ const payload = await client.updateComment(commentId, update);
68
+ if (!payload.success)
69
+ throw new CliError("Failed to update comment");
70
+ const comment = await payload.comment;
71
+ outputSuccess({
72
+ updated: true,
73
+ comment: comment ? { id: comment.id, body: comment.body } : null,
74
+ });
75
+ }));
76
+ comments
77
+ .command("delete <commentId>")
78
+ .description("Permanently delete a comment (irreversible — requires --yes)")
79
+ .option("--yes", "Confirm permanent deletion")
80
+ .action(handleAsyncCommand(async (commentId, opts) => {
81
+ requireYes(opts, `permanently delete comment ${commentId}`);
82
+ const client = await getClient();
83
+ const payload = await client.deleteComment(commentId);
84
+ outputSuccess({ deleted: payload.success });
85
+ }));
86
+ comments
87
+ .command("resolve <commentId>")
88
+ .description("Mark a comment thread as resolved")
89
+ .action(handleAsyncCommand(async (commentId) => {
90
+ const client = await getClient();
91
+ const payload = await client.commentResolve(commentId);
92
+ if (!payload.success)
93
+ throw new CliError("Failed to resolve comment");
94
+ outputSuccess({ resolved: true, id: commentId });
95
+ }));
96
+ comments
97
+ .command("unresolve <commentId>")
98
+ .description("Reopen a resolved comment thread")
99
+ .action(handleAsyncCommand(async (commentId) => {
100
+ const client = await getClient();
101
+ const payload = await client.commentUnresolve(commentId);
102
+ if (!payload.success)
103
+ throw new CliError("Failed to unresolve comment");
104
+ outputSuccess({ unresolved: true, id: commentId });
105
+ }));
106
+ }
107
+ //# sourceMappingURL=comments.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"comments.js","sourceRoot":"","sources":["../../src/commands/comments.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from "commander";
2
+ export declare function setupCompletionCommand(program: Command): void;
3
+ //# sourceMappingURL=completion.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"completion.d.ts","sourceRoot":"","sources":["../../src/commands/completion.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGzC,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA2D7D"}
@@ -0,0 +1,62 @@
1
+ // `elnora-linear completion <shell>` — emit shell completion script.
2
+ //
3
+ // Reads the program's top-level subcommand list at runtime so adding new commands
4
+ // in cli.ts automatically extends completion without touching this file.
5
+ import { EXIT_CODES } from "../utils/index.js";
6
+ export function setupCompletionCommand(program) {
7
+ const cliName = program.name();
8
+ program
9
+ .command("completion")
10
+ .description("Generate shell completion script")
11
+ .argument("<shell>", "Shell type: bash, zsh, fish, powershell")
12
+ .action((shell) => {
13
+ const commands = program.commands.filter((c) => c.name() !== "completion").map((c) => c.name());
14
+ const commandList = commands.join(" ");
15
+ switch (shell) {
16
+ case "bash":
17
+ process.stdout.write(`# ${cliName} bash completion — add to ~/.bashrc
18
+ _${cliName.replace(/-/g, "_")}_completions() {
19
+ local cur="\${COMP_WORDS[COMP_CWORD]}"
20
+ local commands="${commandList}"
21
+ local global_opts="--help --version"
22
+ if [ "\${COMP_CWORD}" -eq 1 ]; then
23
+ COMPREPLY=( $(compgen -W "\${commands} \${global_opts}" -- "\${cur}") )
24
+ fi
25
+ }
26
+ complete -F _${cliName.replace(/-/g, "_")}_completions ${cliName}\n`);
27
+ break;
28
+ case "zsh":
29
+ process.stdout.write(`# ${cliName} zsh completion — add to ~/.zshrc
30
+ _${cliName.replace(/-/g, "_")}() {
31
+ local commands=(${commands.map((c) => `"${c}"`).join(" ")})
32
+ local global_opts=(--help --version)
33
+ _describe 'command' commands
34
+ _describe 'option' global_opts
35
+ }
36
+ compdef _${cliName.replace(/-/g, "_")} ${cliName}\n`);
37
+ break;
38
+ case "fish":
39
+ process.stdout.write(`# ${cliName} fish completion — save to ~/.config/fish/completions/${cliName}.fish
40
+ ${commands.map((c) => `complete -c ${cliName} -n "__fish_use_subcommand" -a "${c}" -d "Manage ${c}"`).join("\n")}
41
+ complete -c ${cliName} -l help -d "Show help"
42
+ complete -c ${cliName} -l version -d "Show version"\n`);
43
+ break;
44
+ case "powershell":
45
+ process.stdout.write(`# ${cliName} PowerShell completion — add to your $PROFILE
46
+ Register-ArgumentCompleter -CommandName ${cliName} -ScriptBlock {
47
+ param($commandName, $wordToComplete, $cursorPosition)
48
+ $commands = @(${commands.map((c) => `'${c}'`).join(", ")})
49
+ $globalOpts = @('--help', '--version')
50
+ $all = $commands + $globalOpts
51
+ $all | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object {
52
+ [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
53
+ }
54
+ }\n`);
55
+ break;
56
+ default:
57
+ process.stderr.write(`${JSON.stringify({ error: `Unknown shell: ${shell}. Supported: bash, zsh, fish, powershell` }, null, 2)}\n`);
58
+ process.exit(EXIT_CODES.VALIDATION);
59
+ }
60
+ });
61
+ }
62
+ //# sourceMappingURL=completion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"completion.js","sourceRoot":"","sources":["../../src/commands/completion.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,EAAE;AACF,kFAAkF;AAClF,yEAAyE;AAGzE,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/C,MAAM,UAAU,sBAAsB,CAAC,OAAgB;IACtD,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAE/B,OAAO;SACL,OAAO,CAAC,YAAY,CAAC;SACrB,WAAW,CAAC,kCAAkC,CAAC;SAC/C,QAAQ,CAAC,SAAS,EAAE,yCAAyC,CAAC;SAC9D,MAAM,CAAC,CAAC,KAAa,EAAE,EAAE;QACzB,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,YAAY,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QAChG,MAAM,WAAW,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAEvC,QAAQ,KAAK,EAAE,CAAC;YACf,KAAK,MAAM;gBACV,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,OAAO;GACnC,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC;;oBAET,WAAW;;;;;;eAMhB,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,gBAAgB,OAAO,IAAI,CAAC,CAAC;gBACjE,MAAM;YACP,KAAK,KAAK;gBACT,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,OAAO;GACnC,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC;oBACT,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;;;;;WAKhD,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,OAAO,IAAI,CAAC,CAAC;gBACjD,MAAM;YACP,KAAK,MAAM;gBACV,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,OAAO,yDAAyD,OAAO;EACpG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,eAAe,OAAO,mCAAmC,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;cAClG,OAAO;cACP,OAAO,iCAAiC,CAAC,CAAC;gBACnD,MAAM;YACP,KAAK,YAAY;gBAChB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,OAAO;0CACI,OAAO;;kBAE/B,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;;;;;;IAMtD,CAAC,CAAC;gBACD,MAAM;YACP;gBACC,OAAO,CAAC,MAAM,CAAC,KAAK,CACnB,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,kBAAkB,KAAK,0CAA0C,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAC5G,CAAC;gBACF,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;QACtC,CAAC;IACF,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from "commander";
2
+ export declare function setupContextCommand(program: Command): void;
3
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/commands/context.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAWzC,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA+F1D"}
@@ -0,0 +1,94 @@
1
+ // `elnora-linear context --team <name>` — one-shot team context primitive.
2
+ //
3
+ // Cold-start primitive for agent workflows: a single CLI call that returns
4
+ // members, projects (with statuses + recommendedIssueState), workflow states,
5
+ // the team's label catalog grouped by prefix, the required-label policy, and
6
+ // Template:* names. Replaces the 4-call sequence (`teams get` + `projects list
7
+ // --team` + `states list --team` + `labels list --team`) with one parallel
8
+ // fetch — total wall-clock is bounded by the slowest of 5 fanned-out queries.
9
+ import { getClient } from "../client/index.js";
10
+ import { handleAsyncCommand, outputSuccess } from "../output/index.js";
11
+ import { getTeamLabelPolicy, groupLabelsByPrefix, recommendedStateForStatus, resolveTeam, teamRequiresProject, } from "../utils/index.js";
12
+ export function setupContextCommand(program) {
13
+ program
14
+ .command("context")
15
+ .description("One-call team context: members, projects (with statuses), workflow states, labels grouped by prefix, required-label policy. Use this once at the start of a workflow instead of calling teams/projects/states/labels separately.")
16
+ .requiredOption("--team <team>", "Team name or key")
17
+ .option("--exclude-projects", "Skip the projects fetch (fastest mode for label/state-only lookups)")
18
+ .option("--exclude-members", "Skip the members fetch (saves a round-trip if you don't need assignees)")
19
+ .action(handleAsyncCommand(async (opts) => {
20
+ const client = await getClient();
21
+ const team = await resolveTeam(client, opts.team);
22
+ const policy = getTeamLabelPolicy(team.key);
23
+ const allowedPrefixes = policy?.allowedPrefixes ?? [];
24
+ const skipProjects = Boolean(opts.excludeProjects);
25
+ const skipMembers = Boolean(opts.excludeMembers);
26
+ const [projectsConn, statesConn, teamLabelsConn, workspaceLabelsConn, membersConn] = await Promise.all([
27
+ skipProjects
28
+ ? Promise.resolve(null)
29
+ : client.projects({
30
+ first: 100,
31
+ filter: { accessibleTeams: { id: { eq: team.id } } },
32
+ }),
33
+ client.workflowStates({
34
+ first: 100,
35
+ filter: { team: { id: { eq: team.id } } },
36
+ }),
37
+ client.issueLabels({
38
+ first: 250,
39
+ filter: { team: { id: { eq: team.id } } },
40
+ }),
41
+ client.issueLabels({
42
+ first: 250,
43
+ filter: { team: { null: true } },
44
+ }),
45
+ skipMembers
46
+ ? Promise.resolve(null)
47
+ : client.users({
48
+ first: 100,
49
+ filter: { active: { eq: true } },
50
+ }),
51
+ ]);
52
+ const projects = projectsConn
53
+ ? await Promise.all(projectsConn.nodes.map(async (p) => {
54
+ const status = await p.status;
55
+ const recommended = recommendedStateForStatus(status?.type);
56
+ return {
57
+ name: p.name,
58
+ status: status?.name ?? null,
59
+ statusType: status?.type ?? null,
60
+ recommendedIssueState: recommended.state,
61
+ ...(recommended.warning ? { warning: recommended.warning } : {}),
62
+ url: p.url,
63
+ };
64
+ }))
65
+ : null;
66
+ const states = (statesConn?.nodes ?? []).map((s) => ({
67
+ name: s.name,
68
+ type: s.type,
69
+ }));
70
+ const allLabels = [
71
+ ...(teamLabelsConn?.nodes ?? []).map((l) => l.name),
72
+ ...(workspaceLabelsConn?.nodes ?? []).map((l) => l.name),
73
+ ];
74
+ const dedupedLabels = Array.from(new Set(allLabels));
75
+ const labelsByPrefix = groupLabelsByPrefix(dedupedLabels, allowedPrefixes);
76
+ const members = membersConn ? membersConn.nodes.map((u) => ({ name: u.name, email: u.email })) : null;
77
+ const templates = (labelsByPrefix["Template:"] ?? []).map((name) => name.replace(/^Template: /, ""));
78
+ const result = {
79
+ team: { key: team.key, name: team.name },
80
+ states,
81
+ labels: { byPrefix: labelsByPrefix, all: dedupedLabels },
82
+ requiredLabels: policy?.required ?? [],
83
+ allowedLabelPrefixes: allowedPrefixes,
84
+ requiresProject: teamRequiresProject(team.key),
85
+ templates,
86
+ };
87
+ if (projects !== null)
88
+ result.projects = projects;
89
+ if (members !== null)
90
+ result.members = members;
91
+ outputSuccess(result);
92
+ }));
93
+ }
94
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/commands/context.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { type CuratorResponse, type DispatchResult } from "../curator/index.js";
1
2
  import type { OutputMode } from "../output/index.js";
2
3
  import { type Signal } from "../signals/index.js";
3
4
  export interface CuratorOptions {
@@ -5,6 +6,12 @@ export interface CuratorOptions {
5
6
  source?: string;
6
7
  referencesDir?: string;
7
8
  output: OutputMode;
9
+ /** Skip the LLM phase even if ANTHROPIC_API_KEY is set. */
10
+ collectOnly?: boolean;
11
+ /** Stage HIGH actions in the report but do not call the Linear API. */
12
+ dryRun?: boolean;
13
+ /** Override state directory (defaults to ~/.config/elnora-linear/state/). */
14
+ stateDir?: string;
8
15
  }
9
16
  export interface CuratorSourceReport {
10
17
  name: string;
@@ -16,6 +23,13 @@ export interface CuratorSourceReport {
16
23
  }
17
24
  export interface CuratorReport {
18
25
  sources: CuratorSourceReport[];
26
+ pipeline?: {
27
+ ranLlm: boolean;
28
+ skippedReason?: string;
29
+ llm?: CuratorResponse;
30
+ dispatch?: DispatchResult;
31
+ error?: string;
32
+ };
19
33
  }
20
34
  export declare function runCurator(opts: CuratorOptions): Promise<CuratorReport>;
21
35
  /** Pure: render a curator report as human-readable text. */
@@ -1 +1 @@
1
- {"version":3,"file":"curator.d.ts","sourceRoot":"","sources":["../../src/commands/curator.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAqB,KAAK,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAErE,MAAM,WAAW,cAAc;IAC9B,iEAAiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,UAAU,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,aAAa;IAC7B,OAAO,EAAE,mBAAmB,EAAE,CAAC;CAC/B;AAED,wBAAsB,UAAU,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC,CAiC7E;AAED,4DAA4D;AAC5D,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CAqBjE"}
1
+ {"version":3,"file":"curator.d.ts","sourceRoot":"","sources":["../../src/commands/curator.ts"],"names":[],"mappings":"AAeA,OAAO,EACN,KAAK,eAAe,EAEpB,KAAK,cAAc,EAInB,MAAM,qBAAqB,CAAC;AAG7B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAqB,KAAK,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAErE,MAAM,WAAW,cAAc;IAC9B,iEAAiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,UAAU,CAAC;IACnB,2DAA2D;IAC3D,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,uEAAuE;IACvE,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,mBAAmB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,aAAa;IAC7B,OAAO,EAAE,mBAAmB,EAAE,CAAC;IAC/B,QAAQ,CAAC,EAAE;QACV,MAAM,EAAE,OAAO,CAAC;QAChB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,GAAG,CAAC,EAAE,eAAe,CAAC;QACtB,QAAQ,CAAC,EAAE,cAAc,CAAC;QAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;CACF;AAED,wBAAsB,UAAU,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC,CA2C7E;AAoDD,4DAA4D;AAC5D,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CAmCjE"}
@@ -1,10 +1,20 @@
1
- // `elnora-linear curator-run` — collect signals from configured signal sources.
1
+ // `elnora-linear curator-run` — collect signals, build a snapshot, call the
2
+ // LLM rule engine, dispatch HIGH/MEDIUM/LOW actions per tier.
2
3
  //
3
- // This PR ships the COLLECTION + REPORTING half of the curator. A follow-up PR
4
- // will add the rule engine that consumes these signals + the workflows.json
5
- // rules and proposes/applies issue mutations. For now, curator-run is a
6
- // diagnostic it tells you what each configured signal source is seeing.
4
+ // Without ANTHROPIC_API_KEY (or with --collect-only), the curator stays in
5
+ // diagnostic mode and just reports collected signals. With the key set the
6
+ // full pipeline runs:
7
+ // 1. Collect signals from every enabled source.
8
+ // 2. List open issues for curator-active teams via bulk-graphql.
9
+ // 3. Build a markdown snapshot.
10
+ // 4. Call Anthropic with the curator system prompt.
11
+ // 5. Dispatch the actions (HIGH auto-apply, MEDIUM queue, LOW report).
12
+ // 6. Persist state + append jsonl report.
13
+ import { getClient } from "../client/index.js";
7
14
  import { loadConfig } from "../config/index.js";
15
+ import { callCuratorLlm, dispatchActions, loadState, saveState, } from "../curator/index.js";
16
+ import { buildSnapshot } from "../curator/snapshot.js";
17
+ import { bulkListIssues } from "../lib/bulk-graphql.js";
8
18
  import { buildSignalSource } from "../signals/index.js";
9
19
  export async function runCurator(opts) {
10
20
  const cfg = loadConfig({ referencesDir: opts.referencesDir, strict: false });
@@ -13,6 +23,7 @@ export async function runCurator(opts) {
13
23
  const targeted = opts.source ? enabledSources.filter((s) => s.name === opts.source) : enabledSources;
14
24
  const now = new Date();
15
25
  const report = { sources: [] };
26
+ const allSignals = [];
16
27
  for (const sourceConfig of targeted) {
17
28
  const entry = {
18
29
  name: sourceConfig.name,
@@ -22,16 +33,24 @@ export async function runCurator(opts) {
22
33
  signals: [],
23
34
  };
24
35
  try {
25
- const source = buildSignalSource(sourceConfig);
36
+ const source = buildSignalSource(sourceConfig, cfg);
26
37
  const signals = await source.collect({ now });
27
38
  entry.signalCount = signals.length;
28
39
  entry.signals = signals;
40
+ allSignals.push(...signals);
29
41
  }
30
42
  catch (err) {
31
43
  entry.error = err instanceof Error ? err.message : String(err);
32
44
  }
33
45
  report.sources.push(entry);
34
46
  }
47
+ const llmGate = shouldRunLlm(opts);
48
+ if (!llmGate.run) {
49
+ report.pipeline = { ranLlm: false, skippedReason: llmGate.reason };
50
+ }
51
+ else {
52
+ report.pipeline = await runRuleEnginePhase(allSignals, opts);
53
+ }
35
54
  if (opts.output === "json") {
36
55
  process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
37
56
  }
@@ -40,25 +59,84 @@ export async function runCurator(opts) {
40
59
  }
41
60
  return report;
42
61
  }
62
+ function shouldRunLlm(opts) {
63
+ if (opts.collectOnly)
64
+ return { run: false, reason: "--collect-only passed" };
65
+ if (!process.env.ANTHROPIC_API_KEY) {
66
+ return { run: false, reason: "ANTHROPIC_API_KEY not set" };
67
+ }
68
+ return { run: true };
69
+ }
70
+ async function runRuleEnginePhase(signals, opts) {
71
+ try {
72
+ const client = await getClient();
73
+ // Pull a workspace-wide bulk list — for production deployments this should
74
+ // be team-filtered via the curator config. v1 keeps it simple.
75
+ const issues = await bulkListIssues({ state: { type: { in: ["unstarted", "started", "backlog"] } } }, { max: 500, includeDescription: true });
76
+ const state = loadState({ stateDir: opts.stateDir });
77
+ const snapshot = buildSnapshot({
78
+ issues,
79
+ signals,
80
+ pendingQuestions: state.pending_questions,
81
+ referencesDir: opts.referencesDir,
82
+ });
83
+ const llm = await callCuratorLlm(snapshot);
84
+ const dispatch = await dispatchActions(client, llm.actions, state, {
85
+ dryRun: opts.dryRun,
86
+ stateDir: opts.stateDir,
87
+ });
88
+ state.last_run_ended_at = new Date().toISOString();
89
+ state.stats.push({
90
+ ranAt: state.last_run_ended_at,
91
+ durationMs: 0,
92
+ signalsCollected: signals.length,
93
+ highApplied: dispatch.applied.length,
94
+ mediumQueued: dispatch.queued.length,
95
+ lowReported: dispatch.reported.length,
96
+ errors: [],
97
+ });
98
+ saveState(state, { stateDir: opts.stateDir });
99
+ return { ranLlm: true, llm, dispatch };
100
+ }
101
+ catch (err) {
102
+ const msg = err instanceof Error ? err.message : String(err);
103
+ return { ranLlm: false, skippedReason: "error", error: msg };
104
+ }
105
+ }
43
106
  /** Pure: render a curator report as human-readable text. */
44
107
  export function formatCuratorReport(report) {
108
+ const lines = [];
45
109
  if (report.sources.length === 0) {
46
- return "No enabled signal sources configured. Add entries to references/signal-sources.json and rerun.\n";
110
+ lines.push("No enabled signal sources configured. Add entries to references/signal-sources.json and rerun.");
47
111
  }
48
- const lines = [];
49
- for (const s of report.sources) {
50
- if (s.error) {
51
- lines.push(`[!!] ${s.name} (${s.type}) — error: ${s.error}`);
52
- continue;
112
+ else {
113
+ for (const s of report.sources) {
114
+ if (s.error) {
115
+ lines.push(`[!!] ${s.name} (${s.type}) — error: ${s.error}`);
116
+ continue;
117
+ }
118
+ lines.push(`[ok] ${s.name} (${s.type}): ${s.signalCount} signal(s)`);
119
+ for (const sig of s.signals.slice(0, 10)) {
120
+ const id = sig.issueIdentifier ?? "-";
121
+ const preview = JSON.stringify(sig.payload).slice(0, 80);
122
+ lines.push(` ${id.padEnd(10)} ${preview}`);
123
+ }
124
+ if (s.signals.length > 10) {
125
+ lines.push(` … ${s.signals.length - 10} more`);
126
+ }
127
+ }
128
+ }
129
+ if (report.pipeline) {
130
+ lines.push("");
131
+ if (report.pipeline.ranLlm && report.pipeline.dispatch) {
132
+ const d = report.pipeline.dispatch;
133
+ lines.push(`[curator] HIGH: ${d.applied.length} applied | MEDIUM: ${d.queued.length} queued | LOW: ${d.reported.length} reported | SKIPPED: ${d.skipped.length}`);
53
134
  }
54
- lines.push(`[ok] ${s.name} (${s.type}): ${s.signalCount} signal(s)`);
55
- for (const sig of s.signals.slice(0, 10)) {
56
- const id = sig.issueIdentifier ?? "-";
57
- const preview = JSON.stringify(sig.payload).slice(0, 80);
58
- lines.push(` ${id.padEnd(10)} ${preview}`);
135
+ else if (report.pipeline.error) {
136
+ lines.push(`[curator] rule engine error: ${report.pipeline.error}`);
59
137
  }
60
- if (s.signals.length > 10) {
61
- lines.push(` ${s.signals.length - 10} more`);
138
+ else if (report.pipeline.skippedReason) {
139
+ lines.push(`[curator] rule engine skipped: ${report.pipeline.skippedReason}`);
62
140
  }
63
141
  }
64
142
  return `${lines.join("\n")}\n`;