@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":"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;AAKzC,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 } 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: policy?.requiresProject ?? false,
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`;
@@ -1 +1 @@
1
- {"version":3,"file":"curator.js","sourceRoot":"","sources":["../../src/commands/curator.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"curator.js","sourceRoot":"","sources":["../../src/commands/curator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from "commander";
2
+ export declare function setupCustomerNeedsCommand(program: Command): void;
3
+ //# sourceMappingURL=customer-needs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"customer-needs.d.ts","sourceRoot":"","sources":["../../src/commands/customer-needs.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAqEzC,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAkKhE"}
@@ -0,0 +1,198 @@
1
+ // `elnora-linear customer-needs` — customer requests / feedback (asks).
2
+ //
3
+ // Each need anchors to either an issue or a project (Linear requires one).
4
+ // `list` uses raw GraphQL with customer/issue/project/creator embedded to
5
+ // avoid 4N+1 round-trips.
6
+ import { getClient } from "../client/index.js";
7
+ import { gqlRequest } from "../lib/bulk-graphql.js";
8
+ import { handleAsyncCommand, outputSuccess } from "../output/index.js";
9
+ import { CliError, findIssueByIdentifier, parseLimit, parsePriority, requireNonEmptyUpdate, requireYes, resolveProject, ValidationError, } from "../utils/index.js";
10
+ import { resolveCustomer } from "./customers.js";
11
+ const NEED_GRAPHQL_FIELDS = `
12
+ id body priority archivedAt createdAt
13
+ customer { id name }
14
+ issue { identifier }
15
+ project { name }
16
+ creator { name }
17
+ `;
18
+ function formatNeedNode(n) {
19
+ return {
20
+ id: n.id,
21
+ body: n.body,
22
+ customer: n.customer?.name ?? null,
23
+ customerId: n.customer?.id ?? null,
24
+ issue: n.issue?.identifier ?? null,
25
+ project: n.project?.name ?? null,
26
+ creator: n.creator?.name ?? null,
27
+ priority: n.priority,
28
+ archivedAt: n.archivedAt,
29
+ createdAt: n.createdAt,
30
+ };
31
+ }
32
+ async function formatNeed(n) {
33
+ const [customer, issue, project, creator] = await Promise.all([n.customer, n.issue, n.project, n.creator]);
34
+ return formatNeedNode({
35
+ id: n.id,
36
+ body: n.body ?? null,
37
+ priority: n.priority ?? null,
38
+ archivedAt: n.archivedAt ? n.archivedAt.toISOString() : null,
39
+ createdAt: n.createdAt.toISOString(),
40
+ customer: customer ? { id: customer.id, name: customer.name } : null,
41
+ issue: issue ? { identifier: issue.identifier } : null,
42
+ project: project ? { name: project.name } : null,
43
+ creator: creator ? { name: creator.name } : null,
44
+ });
45
+ }
46
+ export function setupCustomerNeedsCommand(program) {
47
+ const needs = program.command("customer-needs").description("Manage customer requests / feedback (asks)");
48
+ needs
49
+ .command("list")
50
+ .description("List customer needs")
51
+ .option("--customer <idOrName>", "Filter by customer (UUID, externalId, or name)")
52
+ .option("--project <name>", "Filter by project name")
53
+ .option("--limit <n>", "Max results", "50")
54
+ .action(handleAsyncCommand(async (opts) => {
55
+ const client = await getClient();
56
+ const filter = {};
57
+ if (opts.customer) {
58
+ const c = await resolveCustomer(client, opts.customer);
59
+ filter.customer = { id: { eq: c.id } };
60
+ }
61
+ if (opts.project) {
62
+ const p = await resolveProject(client, opts.project);
63
+ filter.project = { id: { eq: p.id } };
64
+ }
65
+ const res = await gqlRequest(`query($filter: CustomerNeedFilter, $first: Int!) {
66
+ customerNeeds(first: $first, filter: $filter) {
67
+ nodes { ${NEED_GRAPHQL_FIELDS} }
68
+ }
69
+ }`, { filter, first: parseLimit(opts.limit) });
70
+ if (res.errors) {
71
+ throw new CliError(`customer-needs list: ${res.errors.map((e) => e.message).join("; ")}`);
72
+ }
73
+ const items = (res.data?.customerNeeds.nodes ?? []).map(formatNeedNode);
74
+ outputSuccess({ needs: items, count: items.length });
75
+ }));
76
+ needs
77
+ .command("get <id>")
78
+ .description("Get a customer need by UUID")
79
+ .action(handleAsyncCommand(async (id) => {
80
+ const client = await getClient();
81
+ const need = await client.customerNeed({ id });
82
+ outputSuccess(await formatNeed(need));
83
+ }));
84
+ needs
85
+ .command("create")
86
+ .description("Create a customer need (must be linked to an issue or project)")
87
+ .requiredOption("--body <markdown>", "Need body (markdown)")
88
+ .option("--customer <idOrName>", "Customer (UUID, externalId, or exact name)")
89
+ .option("--customer-external-id <id>", "Customer external ID (alternative to --customer)")
90
+ .option("--issue <id>", "Link to issue (ENG-123 or UUID)")
91
+ .option("--project <name>", "Link to project (name or UUID)")
92
+ .option("--priority <0-4>", "Priority")
93
+ .option("--attachment <id>", "Existing attachment UUID to associate as the source")
94
+ .option("--attachment-url <url>", "URL to create an attachment from")
95
+ .action(handleAsyncCommand(async (opts) => {
96
+ if (!opts.issue && !opts.project) {
97
+ throw new ValidationError("Customer needs must link to an issue or a project — pass --issue or --project.");
98
+ }
99
+ if (opts.issue && opts.project) {
100
+ throw new ValidationError("Pass only one of --issue or --project, not both.");
101
+ }
102
+ const client = await getClient();
103
+ const input = { body: opts.body };
104
+ if (opts.customer) {
105
+ const c = await resolveCustomer(client, opts.customer);
106
+ input.customerId = c.id;
107
+ }
108
+ else if (opts.customerExternalId) {
109
+ input.customerExternalId = opts.customerExternalId;
110
+ }
111
+ if (opts.issue) {
112
+ const issue = await findIssueByIdentifier(client, opts.issue);
113
+ input.issueId = issue.id;
114
+ }
115
+ if (opts.project) {
116
+ const p = await resolveProject(client, opts.project);
117
+ input.projectId = p.id;
118
+ }
119
+ if (opts.priority)
120
+ input.priority = parsePriority(opts.priority);
121
+ if (opts.attachment)
122
+ input.attachmentId = opts.attachment;
123
+ if (opts.attachmentUrl)
124
+ input.attachmentUrl = opts.attachmentUrl;
125
+ const payload = await client.createCustomerNeed(input);
126
+ if (!payload.success)
127
+ throw new CliError("Failed to create customer need");
128
+ const need = await payload.need;
129
+ outputSuccess({
130
+ created: true,
131
+ need: need ? await formatNeed(need) : null,
132
+ });
133
+ }));
134
+ needs
135
+ .command("from-attachment <attachmentId>")
136
+ .description("Create a customer need from an existing issue attachment")
137
+ .action(handleAsyncCommand(async (attachmentId) => {
138
+ const client = await getClient();
139
+ const payload = await client.customerNeedCreateFromAttachment({ attachmentId });
140
+ if (!payload.success)
141
+ throw new CliError("Failed to create need from attachment");
142
+ const need = await payload.need;
143
+ outputSuccess({
144
+ created: true,
145
+ need: need ? await formatNeed(need) : null,
146
+ });
147
+ }));
148
+ needs
149
+ .command("update <id>")
150
+ .description("Update a customer need")
151
+ .option("--body <markdown>", "New body")
152
+ .option("--customer <idOrName>", "Move to a different customer")
153
+ .option("--issue <id>", "Move to a different issue (ENG-123 or UUID)")
154
+ .option("--project <name>", "Move to a different project")
155
+ .option("--priority <0-4>", "New priority")
156
+ .action(handleAsyncCommand(async (id, opts) => {
157
+ const client = await getClient();
158
+ const update = {};
159
+ if (opts.body)
160
+ update.body = opts.body;
161
+ if (opts.priority)
162
+ update.priority = parsePriority(opts.priority);
163
+ if (opts.customer) {
164
+ const c = await resolveCustomer(client, opts.customer);
165
+ update.customerId = c.id;
166
+ }
167
+ if (opts.issue) {
168
+ const issue = await findIssueByIdentifier(client, opts.issue);
169
+ update.issueId = issue.id;
170
+ }
171
+ if (opts.project) {
172
+ const p = await resolveProject(client, opts.project);
173
+ update.projectId = p.id;
174
+ }
175
+ requireNonEmptyUpdate(update);
176
+ const payload = await client.updateCustomerNeed(id, update);
177
+ if (!payload.success)
178
+ throw new CliError("Failed to update customer need");
179
+ const need = await payload.need;
180
+ outputSuccess({
181
+ updated: true,
182
+ need: need ? await formatNeed(need) : null,
183
+ });
184
+ }));
185
+ needs
186
+ .command("archive <id>")
187
+ .description("Archive a customer need (irreversible — requires --yes)")
188
+ .option("--yes", "Confirm")
189
+ .action(handleAsyncCommand(async (id, opts) => {
190
+ requireYes(opts, `archive customer need ${id}`);
191
+ const client = await getClient();
192
+ const payload = await client.archiveCustomerNeed(id);
193
+ if (!payload.success)
194
+ throw new CliError("Failed to archive customer need");
195
+ outputSuccess({ archived: true, id });
196
+ }));
197
+ }
198
+ //# sourceMappingURL=customer-needs.js.map