@elnora-ai/linear 1.0.0 → 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 (306) hide show
  1. package/.claude-plugin/marketplace.json +7 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +20 -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 +135 -23
  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 +83 -7
  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/bulk.d.ts.map +1 -1
  37. package/dist/commands/bulk.js +6 -1
  38. package/dist/commands/bulk.js.map +1 -1
  39. package/dist/commands/cleanup.d.ts.map +1 -1
  40. package/dist/commands/cleanup.js +8 -1
  41. package/dist/commands/cleanup.js.map +1 -1
  42. package/dist/commands/comments.d.ts +3 -0
  43. package/dist/commands/comments.d.ts.map +1 -0
  44. package/dist/commands/comments.js +107 -0
  45. package/dist/commands/comments.js.map +1 -0
  46. package/dist/commands/completion.d.ts +3 -0
  47. package/dist/commands/completion.d.ts.map +1 -0
  48. package/dist/commands/completion.js +62 -0
  49. package/dist/commands/completion.js.map +1 -0
  50. package/dist/commands/context.d.ts +3 -0
  51. package/dist/commands/context.d.ts.map +1 -0
  52. package/dist/commands/context.js +94 -0
  53. package/dist/commands/context.js.map +1 -0
  54. package/dist/commands/curator.d.ts +14 -0
  55. package/dist/commands/curator.d.ts.map +1 -1
  56. package/dist/commands/curator.js +97 -19
  57. package/dist/commands/curator.js.map +1 -1
  58. package/dist/commands/customer-needs.d.ts +3 -0
  59. package/dist/commands/customer-needs.d.ts.map +1 -0
  60. package/dist/commands/customer-needs.js +198 -0
  61. package/dist/commands/customer-needs.js.map +1 -0
  62. package/dist/commands/customers.d.ts +5 -0
  63. package/dist/commands/customers.d.ts.map +1 -0
  64. package/dist/commands/customers.js +201 -0
  65. package/dist/commands/customers.js.map +1 -0
  66. package/dist/commands/cycles.d.ts +3 -0
  67. package/dist/commands/cycles.d.ts.map +1 -0
  68. package/dist/commands/cycles.js +67 -0
  69. package/dist/commands/cycles.js.map +1 -0
  70. package/dist/commands/documents.d.ts +3 -0
  71. package/dist/commands/documents.d.ts.map +1 -0
  72. package/dist/commands/documents.js +105 -0
  73. package/dist/commands/documents.js.map +1 -0
  74. package/dist/commands/favorites.d.ts +3 -0
  75. package/dist/commands/favorites.d.ts.map +1 -0
  76. package/dist/commands/favorites.js +101 -0
  77. package/dist/commands/favorites.js.map +1 -0
  78. package/dist/commands/index.d.ts +30 -0
  79. package/dist/commands/index.d.ts.map +1 -1
  80. package/dist/commands/index.js +30 -0
  81. package/dist/commands/index.js.map +1 -1
  82. package/dist/commands/initiatives.d.ts +3 -0
  83. package/dist/commands/initiatives.d.ts.map +1 -0
  84. package/dist/commands/initiatives.js +106 -0
  85. package/dist/commands/initiatives.js.map +1 -0
  86. package/dist/commands/issues.d.ts +21 -0
  87. package/dist/commands/issues.d.ts.map +1 -0
  88. package/dist/commands/issues.js +993 -0
  89. package/dist/commands/issues.js.map +1 -0
  90. package/dist/commands/labels.d.ts +3 -0
  91. package/dist/commands/labels.d.ts.map +1 -0
  92. package/dist/commands/labels.js +111 -0
  93. package/dist/commands/labels.js.map +1 -0
  94. package/dist/commands/milestones.d.ts +3 -0
  95. package/dist/commands/milestones.d.ts.map +1 -0
  96. package/dist/commands/milestones.js +94 -0
  97. package/dist/commands/milestones.js.map +1 -0
  98. package/dist/commands/notifications.d.ts +3 -0
  99. package/dist/commands/notifications.d.ts.map +1 -0
  100. package/dist/commands/notifications.js +130 -0
  101. package/dist/commands/notifications.js.map +1 -0
  102. package/dist/commands/project-labels.d.ts +3 -0
  103. package/dist/commands/project-labels.d.ts.map +1 -0
  104. package/dist/commands/project-labels.js +80 -0
  105. package/dist/commands/project-labels.js.map +1 -0
  106. package/dist/commands/project-relations.d.ts +3 -0
  107. package/dist/commands/project-relations.d.ts.map +1 -0
  108. package/dist/commands/project-relations.js +96 -0
  109. package/dist/commands/project-relations.js.map +1 -0
  110. package/dist/commands/projects.d.ts +3 -0
  111. package/dist/commands/projects.d.ts.map +1 -0
  112. package/dist/commands/projects.js +263 -0
  113. package/dist/commands/projects.js.map +1 -0
  114. package/dist/commands/quota.d.ts +3 -0
  115. package/dist/commands/quota.d.ts.map +1 -0
  116. package/dist/commands/quota.js +28 -0
  117. package/dist/commands/quota.js.map +1 -0
  118. package/dist/commands/reactions.d.ts +7 -0
  119. package/dist/commands/reactions.d.ts.map +1 -0
  120. package/dist/commands/reactions.js +53 -0
  121. package/dist/commands/reactions.js.map +1 -0
  122. package/dist/commands/relations.d.ts +3 -0
  123. package/dist/commands/relations.d.ts.map +1 -0
  124. package/dist/commands/relations.js +73 -0
  125. package/dist/commands/relations.js.map +1 -0
  126. package/dist/commands/states.d.ts +3 -0
  127. package/dist/commands/states.d.ts.map +1 -0
  128. package/dist/commands/states.js +52 -0
  129. package/dist/commands/states.js.map +1 -0
  130. package/dist/commands/status-updates.d.ts +3 -0
  131. package/dist/commands/status-updates.d.ts.map +1 -0
  132. package/dist/commands/status-updates.js +117 -0
  133. package/dist/commands/status-updates.js.map +1 -0
  134. package/dist/commands/sync.d.ts.map +1 -1
  135. package/dist/commands/sync.js +58 -18
  136. package/dist/commands/sync.js.map +1 -1
  137. package/dist/commands/teams.d.ts +3 -0
  138. package/dist/commands/teams.d.ts.map +1 -0
  139. package/dist/commands/teams.js +135 -0
  140. package/dist/commands/teams.js.map +1 -0
  141. package/dist/commands/templates.d.ts +3 -0
  142. package/dist/commands/templates.d.ts.map +1 -0
  143. package/dist/commands/templates.js +76 -0
  144. package/dist/commands/templates.js.map +1 -0
  145. package/dist/commands/users.d.ts +3 -0
  146. package/dist/commands/users.d.ts.map +1 -0
  147. package/dist/commands/users.js +40 -0
  148. package/dist/commands/users.js.map +1 -0
  149. package/dist/commands/views.d.ts +3 -0
  150. package/dist/commands/views.d.ts.map +1 -0
  151. package/dist/commands/views.js +177 -0
  152. package/dist/commands/views.js.map +1 -0
  153. package/dist/commands/webhooks.d.ts +3 -0
  154. package/dist/commands/webhooks.d.ts.map +1 -0
  155. package/dist/commands/webhooks.js +234 -0
  156. package/dist/commands/webhooks.js.map +1 -0
  157. package/dist/config/loader.d.ts.map +1 -1
  158. package/dist/config/loader.js +3 -0
  159. package/dist/config/loader.js.map +1 -1
  160. package/dist/config/types.d.ts +16 -2
  161. package/dist/config/types.d.ts.map +1 -1
  162. package/dist/config/types.js +1 -0
  163. package/dist/config/types.js.map +1 -1
  164. package/dist/curator/dispatch.d.ts +52 -0
  165. package/dist/curator/dispatch.d.ts.map +1 -0
  166. package/dist/curator/dispatch.js +144 -0
  167. package/dist/curator/dispatch.js.map +1 -0
  168. package/dist/curator/index.d.ts +5 -0
  169. package/dist/curator/index.d.ts.map +1 -0
  170. package/dist/curator/index.js +5 -0
  171. package/dist/curator/index.js.map +1 -0
  172. package/dist/curator/llm.d.ts +70 -0
  173. package/dist/curator/llm.d.ts.map +1 -0
  174. package/dist/curator/llm.js +107 -0
  175. package/dist/curator/llm.js.map +1 -0
  176. package/dist/curator/snapshot.d.ts +34 -0
  177. package/dist/curator/snapshot.d.ts.map +1 -0
  178. package/dist/curator/snapshot.js +127 -0
  179. package/dist/curator/snapshot.js.map +1 -0
  180. package/dist/curator/state.d.ts +50 -0
  181. package/dist/curator/state.d.ts.map +1 -0
  182. package/dist/curator/state.js +125 -0
  183. package/dist/curator/state.js.map +1 -0
  184. package/dist/lib/bulk-graphql.d.ts +144 -0
  185. package/dist/lib/bulk-graphql.d.ts.map +1 -0
  186. package/dist/lib/bulk-graphql.js +380 -0
  187. package/dist/lib/bulk-graphql.js.map +1 -0
  188. package/dist/lib/index.d.ts +2 -0
  189. package/dist/lib/index.d.ts.map +1 -0
  190. package/dist/lib/index.js +2 -0
  191. package/dist/lib/index.js.map +1 -0
  192. package/dist/output/cli.d.ts +17 -0
  193. package/dist/output/cli.d.ts.map +1 -0
  194. package/dist/output/cli.js +252 -0
  195. package/dist/output/cli.js.map +1 -0
  196. package/dist/output/formatter.d.ts +6 -0
  197. package/dist/output/formatter.d.ts.map +1 -1
  198. package/dist/output/formatter.js +10 -0
  199. package/dist/output/formatter.js.map +1 -1
  200. package/dist/output/index.d.ts +1 -0
  201. package/dist/output/index.d.ts.map +1 -1
  202. package/dist/output/index.js +1 -0
  203. package/dist/output/index.js.map +1 -1
  204. package/dist/scripts/sync-linear-templates.d.ts +26 -0
  205. package/dist/scripts/sync-linear-templates.d.ts.map +1 -0
  206. package/dist/scripts/sync-linear-templates.js +115 -0
  207. package/dist/scripts/sync-linear-templates.js.map +1 -0
  208. package/dist/signals/github-commits.d.ts +31 -0
  209. package/dist/signals/github-commits.d.ts.map +1 -0
  210. package/dist/signals/github-commits.js +127 -0
  211. package/dist/signals/github-commits.js.map +1 -0
  212. package/dist/signals/github-pr.d.ts +16 -0
  213. package/dist/signals/github-pr.d.ts.map +1 -0
  214. package/dist/signals/github-pr.js +98 -0
  215. package/dist/signals/github-pr.js.map +1 -0
  216. package/dist/signals/index.d.ts +4 -0
  217. package/dist/signals/index.d.ts.map +1 -1
  218. package/dist/signals/index.js +4 -0
  219. package/dist/signals/index.js.map +1 -1
  220. package/dist/signals/linear-issues.d.ts +20 -0
  221. package/dist/signals/linear-issues.d.ts.map +1 -0
  222. package/dist/signals/linear-issues.js +115 -0
  223. package/dist/signals/linear-issues.js.map +1 -0
  224. package/dist/signals/registry.d.ts +4 -3
  225. package/dist/signals/registry.d.ts.map +1 -1
  226. package/dist/signals/registry.js +33 -11
  227. package/dist/signals/registry.js.map +1 -1
  228. package/dist/signals/slack-messages.d.ts +20 -0
  229. package/dist/signals/slack-messages.d.ts.map +1 -0
  230. package/dist/signals/slack-messages.js +129 -0
  231. package/dist/signals/slack-messages.js.map +1 -0
  232. package/dist/utils/errors.d.ts +63 -0
  233. package/dist/utils/errors.d.ts.map +1 -0
  234. package/dist/utils/errors.js +94 -0
  235. package/dist/utils/errors.js.map +1 -0
  236. package/dist/utils/index.d.ts +9 -0
  237. package/dist/utils/index.d.ts.map +1 -0
  238. package/dist/utils/index.js +9 -0
  239. package/dist/utils/index.js.map +1 -0
  240. package/dist/utils/label-policy.d.ts +53 -0
  241. package/dist/utils/label-policy.d.ts.map +1 -0
  242. package/dist/utils/label-policy.js +93 -0
  243. package/dist/utils/label-policy.js.map +1 -0
  244. package/dist/utils/parse.d.ts +48 -0
  245. package/dist/utils/parse.d.ts.map +1 -0
  246. package/dist/utils/parse.js +133 -0
  247. package/dist/utils/parse.js.map +1 -0
  248. package/dist/utils/project-status.d.ts +6 -0
  249. package/dist/utils/project-status.d.ts.map +1 -0
  250. package/dist/utils/project-status.js +33 -0
  251. package/dist/utils/project-status.js.map +1 -0
  252. package/dist/utils/rate-limit.d.ts +24 -0
  253. package/dist/utils/rate-limit.d.ts.map +1 -0
  254. package/dist/utils/rate-limit.js +89 -0
  255. package/dist/utils/rate-limit.js.map +1 -0
  256. package/dist/utils/resolve.d.ts +84 -0
  257. package/dist/utils/resolve.d.ts.map +1 -0
  258. package/dist/utils/resolve.js +172 -0
  259. package/dist/utils/resolve.js.map +1 -0
  260. package/dist/utils/sleep.d.ts +2 -0
  261. package/dist/utils/sleep.d.ts.map +1 -0
  262. package/dist/utils/sleep.js +4 -0
  263. package/dist/utils/sleep.js.map +1 -0
  264. package/dist/utils/webhook-verify.d.ts +42 -0
  265. package/dist/utils/webhook-verify.d.ts.map +1 -0
  266. package/dist/utils/webhook-verify.js +65 -0
  267. package/dist/utils/webhook-verify.js.map +1 -0
  268. package/package.json +4 -3
  269. package/references/agent-description-template.md +31 -0
  270. package/references/cli-reference.md +227 -0
  271. package/references/curator-tiering-rules.md +76 -0
  272. package/references/label-policy.example.json +37 -0
  273. package/references/label-policy.placeholder.json +6 -0
  274. package/references/settings-template.md +30 -0
  275. package/references/sla-reference.md +70 -0
  276. package/references/template-index.md +34 -0
  277. package/references/workspace-labels.md +124 -0
  278. package/references/workspace-projects.md +56 -0
  279. package/references/workspace-routing.md +58 -0
  280. package/schemas/label-policy.json +72 -0
  281. package/schemas/signal-sources.json +1 -1
  282. package/skills/linear-workspace/SKILL.md +65 -4
  283. package/templates/ACC-PRO-provision.md +74 -0
  284. package/templates/ACC-PRV-privileged.md +66 -0
  285. package/templates/ACC-QTR-review.md +77 -0
  286. package/templates/ACC-REV-revoke.md +67 -0
  287. package/templates/AI-USE-capability.md +111 -0
  288. package/templates/AUD-CAP-corrective.md +89 -0
  289. package/templates/AUD-INT-internal.md +92 -0
  290. package/templates/AUD-MGT-management.md +110 -0
  291. package/templates/CHG-MAJ-major.md +110 -0
  292. package/templates/CHG-SIG-significant.md +83 -0
  293. package/templates/CHG-STD-standard.md +47 -0
  294. package/templates/LRN-DOC-lessons.md +75 -0
  295. package/templates/OPS-BCK-backup.md +99 -0
  296. package/templates/OPS-DAT-data-mod.md +98 -0
  297. package/templates/RCA-DOC-root-cause.md +105 -0
  298. package/templates/RSK-ASS-assessment.md +87 -0
  299. package/templates/RSK-VND-vendor.md +113 -0
  300. package/templates/SEC-INC-incident.md +76 -0
  301. package/templates/SEC-PEN-pentest.md +58 -0
  302. package/templates/SEC-VLN-vulnerability.md +69 -0
  303. package/templates/SLA-AVL-availability.md +86 -0
  304. package/templates/SLA-OPS-operational.md +70 -0
  305. package/templates/agent-server-template/README.md +88 -0
  306. package/templates/agent-server-template/server.example.ts +185 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"AAMA;;;GAGG;AACH,eAAO,MAAM,UAAU;;;;;;CAMb,CAAC;AAEX,qBAAa,QAAS,SAAQ,KAAK;IAClC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B;;;;;OAKG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;gBAE5B,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE;CAQjH;AAED,qBAAa,SAAU,SAAQ,QAAQ;gBAC1B,OAAO,CAAC,EAAE,MAAM;CAQ5B;AAeD,qBAAa,aAAc,SAAQ,QAAQ;gBAC9B,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM;CAQ9C;AAED,qBAAa,eAAgB,SAAQ,QAAQ;gBAChC,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAIhF;AAED;;;;GAIG;AACH,qBAAa,oBAAqB,SAAQ,eAAe;gBAC5C,IAAI,EAAE;QACjB,KAAK,EAAE,gBAAgB,CAAC;QACxB,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE;YAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;YAAC,GAAG,EAAE,MAAM,CAAC;YAAC,WAAW,CAAC,EAAE,MAAM,CAAA;SAAE,EAAE,CAAC;QACrE,MAAM,EAAE;YAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;YAAC,GAAG,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,EAAE,CAAA;SAAE,EAAE,CAAC;QAChE,MAAM,EAAE,MAAM,EAAE,CAAC;QACjB,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;QAC7C,cAAc,EAAE,MAAM,CAAC;KACvB;CAcD"}
@@ -0,0 +1,94 @@
1
+ // Error hierarchy for elnora-linear CLI.
2
+ //
3
+ // Every error class carries a userMessage + suggestion + structured exit code
4
+ // so the CLI dispatcher can map them to predictable shell exit codes and emit
5
+ // machine-readable JSON envelopes that agents can parse + self-correct from.
6
+ /**
7
+ * Dedicated exit codes per error type.
8
+ * 0 = success, 1 = general/unknown, 2 = validation, 3 = auth, 4 = not found.
9
+ */
10
+ export const EXIT_CODES = {
11
+ SUCCESS: 0,
12
+ GENERAL: 1,
13
+ VALIDATION: 2,
14
+ AUTH: 3,
15
+ NOT_FOUND: 4,
16
+ };
17
+ export class CliError extends Error {
18
+ userMessage;
19
+ suggestion;
20
+ exitCode;
21
+ /**
22
+ * Optional structured payload merged into the JSON error envelope. Used by
23
+ * validation errors that need to expose machine-readable detail (e.g. which
24
+ * labels are missing, what the team's accepted set is) so an agent can
25
+ * self-correct without re-reading reference files.
26
+ */
27
+ data;
28
+ constructor(message, options) {
29
+ super(message);
30
+ this.name = "CliError";
31
+ this.userMessage = message;
32
+ this.suggestion = options?.suggestion;
33
+ this.exitCode = options?.exitCode ?? EXIT_CODES.GENERAL;
34
+ this.data = options?.data;
35
+ }
36
+ }
37
+ export class AuthError extends CliError {
38
+ constructor(message) {
39
+ super(message ?? "No Linear API key found. Set LINEAR_API_KEY in your environment.", {
40
+ suggestion: "Add LINEAR_API_KEY=lin_api_... to your environment, or place it in ~/.config/elnora-linear/.env (mode 0600).",
41
+ exitCode: EXIT_CODES.AUTH,
42
+ });
43
+ this.name = "AuthError";
44
+ }
45
+ }
46
+ /** Maps entity names to the correct CLI command for listing them. */
47
+ const ENTITY_LIST_COMMANDS = {
48
+ team: "elnora-linear teams list",
49
+ project: "elnora-linear projects list",
50
+ user: "elnora-linear users list",
51
+ label: "elnora-linear labels list",
52
+ state: "elnora-linear states list --team <team>",
53
+ issue: "elnora-linear issues list",
54
+ initiative: "elnora-linear initiatives list",
55
+ milestone: "elnora-linear milestones list --project <project>",
56
+ "workflow state": "elnora-linear states list --team <team>",
57
+ };
58
+ export class NotFoundError extends CliError {
59
+ constructor(entity, identifier) {
60
+ const command = ENTITY_LIST_COMMANDS[entity.toLowerCase()] ?? `elnora-linear ${entity.toLowerCase()}s list`;
61
+ super(`${entity} not found: ${identifier}`, {
62
+ suggestion: `Check the identifier and try again. Use '${command}' to see available ${entity.toLowerCase()}s.`,
63
+ exitCode: EXIT_CODES.NOT_FOUND,
64
+ });
65
+ this.name = "NotFoundError";
66
+ }
67
+ }
68
+ export class ValidationError extends CliError {
69
+ constructor(message, suggestion, data) {
70
+ super(message, { suggestion, exitCode: EXIT_CODES.VALIDATION, data });
71
+ this.name = "ValidationError";
72
+ }
73
+ }
74
+ /**
75
+ * Specialized validation error for label-policy violations on `issues create`.
76
+ * The structured `data` field is the load-bearing part — agents read it to
77
+ * self-correct in one retry instead of re-reading workspace-labels.md.
78
+ */
79
+ export class LabelValidationError extends ValidationError {
80
+ constructor(data) {
81
+ const summary = [];
82
+ for (const m of data.missing) {
83
+ summary.push(`missing ≥${m.min} from ${m.prefixes.join(" or ")}`);
84
+ }
85
+ for (const e of data.excess) {
86
+ summary.push(`too many ${e.prefixes.join(" or ")} (max ${e.max})`);
87
+ }
88
+ const message = `Label policy violation for team "${data.team}": ${summary.join("; ")}.`;
89
+ const suggestion = "Pass labels matching the prefixes shown in availableForPrefix, or run the suggestedRetry command verbatim.";
90
+ super(message, suggestion, { ...data });
91
+ this.name = "LabelValidationError";
92
+ }
93
+ }
94
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export * from "./errors.js";
2
+ export * from "./label-policy.js";
3
+ export * from "./parse.js";
4
+ export * from "./project-status.js";
5
+ export * from "./rate-limit.js";
6
+ export * from "./resolve.js";
7
+ export * from "./sleep.js";
8
+ export * from "./webhook-verify.js";
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC"}
@@ -0,0 +1,9 @@
1
+ export * from "./errors.js";
2
+ export * from "./label-policy.js";
3
+ export * from "./parse.js";
4
+ export * from "./project-status.js";
5
+ export * from "./rate-limit.js";
6
+ export * from "./resolve.js";
7
+ export * from "./sleep.js";
8
+ export * from "./webhook-verify.js";
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC"}
@@ -0,0 +1,53 @@
1
+ export interface RequirementGroup {
2
+ prefixes: string[];
3
+ min: number;
4
+ max?: number | null;
5
+ description?: string;
6
+ }
7
+ export interface TeamLabelPolicy {
8
+ name: string;
9
+ required: RequirementGroup[];
10
+ allowedPrefixes: string[];
11
+ requiresProject?: boolean;
12
+ }
13
+ export interface LabelPolicyConfig {
14
+ $schema?: string;
15
+ _placeholder?: boolean;
16
+ _example?: boolean;
17
+ _populated_by?: string;
18
+ policies: Record<string, TeamLabelPolicy>;
19
+ }
20
+ export interface LoadLabelPolicyOptions {
21
+ referencesDir?: string;
22
+ /** Force reload (default false — module-level cache used for repeat calls in the same process). */
23
+ noCache?: boolean;
24
+ }
25
+ /** Load the label-policy config from references/label-policy.json. */
26
+ export declare function loadLabelPolicies(opts?: LoadLabelPolicyOptions): LabelPolicyConfig;
27
+ /** Reset the module-level cache (used in tests). */
28
+ export declare function resetLabelPolicyCache(): void;
29
+ export declare function getTeamLabelPolicy(teamKey: string, opts?: LoadLabelPolicyOptions): TeamLabelPolicy | null;
30
+ /**
31
+ * Group labels by their first matching prefix. Labels not matching any known
32
+ * prefix go to "_unprefixed". Order of knownPrefixes matters: the first match
33
+ * wins, so put more specific prefixes earlier if any overlap.
34
+ */
35
+ export declare function groupLabelsByPrefix(labelNames: string[], knownPrefixes: string[]): Record<string, string[]>;
36
+ export interface LabelValidationFailure {
37
+ group: RequirementGroup;
38
+ count: number;
39
+ reason: "missing" | "excess";
40
+ }
41
+ export interface LabelValidationResult {
42
+ valid: boolean;
43
+ failures: LabelValidationFailure[];
44
+ passed: string[];
45
+ availableForPrefix: Record<string, string[]>;
46
+ }
47
+ /**
48
+ * Validate that the proposed labels satisfy the team's required prefix groups.
49
+ * Unknown teams pass through (no enforcement) so workspaces without a config
50
+ * entry don't break.
51
+ */
52
+ export declare function validateLabelsAgainstTeam(teamKey: string, passedLabels: string[], teamLabelCatalog: string[], opts?: LoadLabelPolicyOptions): LabelValidationResult;
53
+ //# sourceMappingURL=label-policy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"label-policy.d.ts","sourceRoot":"","sources":["../../src/utils/label-policy.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,gBAAgB;IAChC,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,eAAe;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAC7B,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,eAAe,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,iBAAiB;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;CAC1C;AAED,MAAM,WAAW,sBAAsB;IACtC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,mGAAmG;IACnG,OAAO,CAAC,EAAE,OAAO,CAAC;CAClB;AAKD,sEAAsE;AACtE,wBAAgB,iBAAiB,CAAC,IAAI,GAAE,sBAA2B,GAAG,iBAAiB,CAOtF;AAED,oDAAoD;AACpD,wBAAgB,qBAAqB,IAAI,IAAI,CAG5C;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,GAAE,sBAA2B,GAAG,eAAe,GAAG,IAAI,CAE7G;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,aAAa,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAY3G;AAED,MAAM,WAAW,sBAAsB;IACtC,KAAK,EAAE,gBAAgB,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,SAAS,GAAG,QAAQ,CAAC;CAC7B;AAED,MAAM,WAAW,qBAAqB;IACrC,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,EAAE,sBAAsB,EAAE,CAAC;IACnC,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;CAC7C;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CACxC,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EAAE,EACtB,gBAAgB,EAAE,MAAM,EAAE,EAC1B,IAAI,GAAE,sBAA2B,GAC/B,qBAAqB,CAqCvB"}
@@ -0,0 +1,93 @@
1
+ // Team-specific label requirements.
2
+ //
3
+ // Source of truth for which labels each team requires on every issue. Read by
4
+ // `projects get`, `teams get`, `context`, and the `issues create` validator.
5
+ // Agents never read the underlying JSON directly — they consume policies
6
+ // through the CLI responses, which is the point: keep the policy in one place
7
+ // and let the CLI expose it instead of having every agent re-encode it.
8
+ //
9
+ // Loaded via the existing config layer (LinearConfig) so it honors the same
10
+ // placeholder + sync + sanitization-gate machinery as the other references.
11
+ import { loadConfig } from "../config/index.js";
12
+ let cached = null;
13
+ let cachedKey;
14
+ /** Load the label-policy config from references/label-policy.json. */
15
+ export function loadLabelPolicies(opts = {}) {
16
+ const key = opts.referencesDir ?? "(default)";
17
+ if (!opts.noCache && cached && cachedKey === key)
18
+ return cached;
19
+ const cfg = loadConfig({ referencesDir: opts.referencesDir, strict: false });
20
+ cached = cfg.labelPolicy;
21
+ cachedKey = key;
22
+ return cached;
23
+ }
24
+ /** Reset the module-level cache (used in tests). */
25
+ export function resetLabelPolicyCache() {
26
+ cached = null;
27
+ cachedKey = undefined;
28
+ }
29
+ export function getTeamLabelPolicy(teamKey, opts = {}) {
30
+ return loadLabelPolicies(opts).policies[teamKey] ?? null;
31
+ }
32
+ /**
33
+ * Group labels by their first matching prefix. Labels not matching any known
34
+ * prefix go to "_unprefixed". Order of knownPrefixes matters: the first match
35
+ * wins, so put more specific prefixes earlier if any overlap.
36
+ */
37
+ export function groupLabelsByPrefix(labelNames, knownPrefixes) {
38
+ const result = { _unprefixed: [] };
39
+ for (const prefix of knownPrefixes)
40
+ result[prefix] = [];
41
+ for (const name of labelNames) {
42
+ const prefix = knownPrefixes.find((p) => name.startsWith(p));
43
+ if (prefix) {
44
+ result[prefix].push(name);
45
+ }
46
+ else {
47
+ result._unprefixed.push(name);
48
+ }
49
+ }
50
+ return result;
51
+ }
52
+ /**
53
+ * Validate that the proposed labels satisfy the team's required prefix groups.
54
+ * Unknown teams pass through (no enforcement) so workspaces without a config
55
+ * entry don't break.
56
+ */
57
+ export function validateLabelsAgainstTeam(teamKey, passedLabels, teamLabelCatalog, opts = {}) {
58
+ const policy = getTeamLabelPolicy(teamKey, opts);
59
+ if (!policy) {
60
+ return { valid: true, failures: [], passed: passedLabels, availableForPrefix: {} };
61
+ }
62
+ const passedByPrefix = groupLabelsByPrefix(passedLabels, policy.allowedPrefixes);
63
+ const catalogByPrefix = groupLabelsByPrefix(teamLabelCatalog, policy.allowedPrefixes);
64
+ const failures = [];
65
+ const failedPrefixes = new Set();
66
+ for (const group of policy.required) {
67
+ let count = 0;
68
+ for (const prefix of group.prefixes) {
69
+ count += (passedByPrefix[prefix] ?? []).length;
70
+ }
71
+ if (count < group.min) {
72
+ failures.push({ group, count, reason: "missing" });
73
+ for (const p of group.prefixes)
74
+ failedPrefixes.add(p);
75
+ }
76
+ else if (group.max != null && count > group.max) {
77
+ failures.push({ group, count, reason: "excess" });
78
+ for (const p of group.prefixes)
79
+ failedPrefixes.add(p);
80
+ }
81
+ }
82
+ const availableForPrefix = {};
83
+ for (const prefix of failedPrefixes) {
84
+ availableForPrefix[prefix] = catalogByPrefix[prefix] ?? [];
85
+ }
86
+ return {
87
+ valid: failures.length === 0,
88
+ failures,
89
+ passed: passedLabels,
90
+ availableForPrefix,
91
+ };
92
+ }
93
+ //# sourceMappingURL=label-policy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"label-policy.js","sourceRoot":"","sources":["../../src/utils/label-policy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Parse and validate a --limit option (or any positive-integer flag capped at
3
+ * Linear's 250-per-page API max). Returns the parsed number. Throws
4
+ * ValidationError for invalid values. Pass `flagName` to customize the label
5
+ * that appears in the error and warning text — defaults to "--limit".
6
+ */
7
+ export declare function parseLimit(value: string | undefined, defaultValue?: number, flagName?: string): number;
8
+ /**
9
+ * Parse a positive integer with no upper cap. Use for flags like --max where
10
+ * the value can legitimately exceed the API page limit (we just paginate).
11
+ * Returns `defaultValue` (default Infinity) when unset.
12
+ */
13
+ export declare function parsePositiveInt(value: string | undefined, flagName: string, defaultValue?: number): number;
14
+ /**
15
+ * Parse and validate a --priority option. Returns the parsed number. Throws
16
+ * ValidationError for invalid values (must be 0-4).
17
+ */
18
+ export declare function parsePriority(value: string | undefined): number | undefined;
19
+ /**
20
+ * Parse and validate a date option (YYYY-MM-DD). Returns the validated string
21
+ * or undefined if not provided.
22
+ */
23
+ export declare function parseDate(value: string | undefined): string | undefined;
24
+ /**
25
+ * Parse and validate a hex color option. Accepts formats: #RGB, #RRGGBB
26
+ * (with or without #).
27
+ */
28
+ export declare function parseColor(value: string | undefined): string | undefined;
29
+ export declare function parseHealth(value: string | undefined): string | undefined;
30
+ export declare function parseProjectState(value: string | undefined): string | undefined;
31
+ /**
32
+ * Parse and validate a --timeout value (seconds). Returns milliseconds for
33
+ * direct use with setTimeout. Accepts fractional values; rejects 0, negatives,
34
+ * NaN, and Infinity.
35
+ */
36
+ export declare function parseTimeoutSeconds(value: string): number;
37
+ /**
38
+ * Guard: throws if an update object has no fields set. Use in update commands
39
+ * to catch empty updates before sending to the API.
40
+ */
41
+ export declare function requireNonEmptyUpdate(update: Record<string, unknown>): void;
42
+ /**
43
+ * Guard: throws if `--yes` flag isn't set on a destructive command. Forces an
44
+ * explicit confirmation step that prompt-injected agents can't skip by talking
45
+ * themselves out of it.
46
+ */
47
+ export declare function requireYes(opts: Record<string, unknown>, action: string): void;
48
+ //# sourceMappingURL=parse.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../src/utils/parse.ts"],"names":[],"mappings":"AAKA;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,YAAY,SAAK,EAAE,QAAQ,SAAY,GAAG,MAAM,CAWrG;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,YAAY,GAAE,MAAiB,GAAG,MAAM,CAOrH;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAS3E;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAcvE;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAOxE;AAID,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAMzE;AAID,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAM/E;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAMzD;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAK3E;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAO9E"}
@@ -0,0 +1,133 @@
1
+ // Input parsing and validation utilities.
2
+ // Pure functions — no side effects, no API calls.
3
+ import { ValidationError } from "./errors.js";
4
+ /**
5
+ * Parse and validate a --limit option (or any positive-integer flag capped at
6
+ * Linear's 250-per-page API max). Returns the parsed number. Throws
7
+ * ValidationError for invalid values. Pass `flagName` to customize the label
8
+ * that appears in the error and warning text — defaults to "--limit".
9
+ */
10
+ export function parseLimit(value, defaultValue = 50, flagName = "--limit") {
11
+ if (!value)
12
+ return defaultValue;
13
+ const n = Number(value);
14
+ if (!Number.isInteger(n) || n <= 0) {
15
+ throw new ValidationError(`Invalid ${flagName} value: "${value}". Must be a positive integer.`);
16
+ }
17
+ if (n > 250) {
18
+ process.stderr.write(`Warning: ${flagName} ${n} capped to 250 (Linear API max).\n`);
19
+ return 250;
20
+ }
21
+ return n;
22
+ }
23
+ /**
24
+ * Parse a positive integer with no upper cap. Use for flags like --max where
25
+ * the value can legitimately exceed the API page limit (we just paginate).
26
+ * Returns `defaultValue` (default Infinity) when unset.
27
+ */
28
+ export function parsePositiveInt(value, flagName, defaultValue = Infinity) {
29
+ if (!value)
30
+ return defaultValue;
31
+ const n = Number(value);
32
+ if (!Number.isInteger(n) || n <= 0) {
33
+ throw new ValidationError(`Invalid ${flagName} value: "${value}". Must be a positive integer.`);
34
+ }
35
+ return n;
36
+ }
37
+ /**
38
+ * Parse and validate a --priority option. Returns the parsed number. Throws
39
+ * ValidationError for invalid values (must be 0-4).
40
+ */
41
+ export function parsePriority(value) {
42
+ if (!value)
43
+ return undefined;
44
+ const n = parseInt(value, 10);
45
+ if (Number.isNaN(n) || n < 0 || n > 4) {
46
+ throw new ValidationError(`Invalid --priority value: "${value}". Must be 0 (None), 1 (Urgent), 2 (High), 3 (Normal), or 4 (Low).`);
47
+ }
48
+ return n;
49
+ }
50
+ /**
51
+ * Parse and validate a date option (YYYY-MM-DD). Returns the validated string
52
+ * or undefined if not provided.
53
+ */
54
+ export function parseDate(value) {
55
+ if (!value)
56
+ return undefined;
57
+ if (!/^\d{4}-\d{2}-\d{2}$/.test(value)) {
58
+ throw new ValidationError(`Invalid date: "${value}". Must be in YYYY-MM-DD format.`);
59
+ }
60
+ const d = new Date(`${value}T00:00:00Z`);
61
+ if (Number.isNaN(d.getTime())) {
62
+ throw new ValidationError(`Invalid date: "${value}". Not a valid calendar date.`);
63
+ }
64
+ // Reject silent rollover (e.g., 2026-02-30 → 2026-03-02).
65
+ if (d.toISOString().slice(0, 10) !== value) {
66
+ throw new ValidationError(`Invalid date: "${value}". Not a real calendar date.`);
67
+ }
68
+ return value;
69
+ }
70
+ /**
71
+ * Parse and validate a hex color option. Accepts formats: #RGB, #RRGGBB
72
+ * (with or without #).
73
+ */
74
+ export function parseColor(value) {
75
+ if (!value)
76
+ return undefined;
77
+ const hex = value.startsWith("#") ? value : `#${value}`;
78
+ if (!/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(hex)) {
79
+ throw new ValidationError(`Invalid color: "${value}". Must be a hex color (e.g., #FF0000 or #F00).`);
80
+ }
81
+ return hex;
82
+ }
83
+ const VALID_HEALTH_VALUES = ["onTrack", "atRisk", "offTrack"];
84
+ export function parseHealth(value) {
85
+ if (!value)
86
+ return undefined;
87
+ if (!VALID_HEALTH_VALUES.includes(value)) {
88
+ throw new ValidationError(`Invalid --health value: "${value}". Must be one of: ${VALID_HEALTH_VALUES.join(", ")}.`);
89
+ }
90
+ return value;
91
+ }
92
+ const VALID_PROJECT_STATES = ["backlog", "planned", "started", "paused", "completed", "canceled"];
93
+ export function parseProjectState(value) {
94
+ if (!value)
95
+ return undefined;
96
+ if (!VALID_PROJECT_STATES.includes(value)) {
97
+ throw new ValidationError(`Invalid --state value: "${value}". Must be one of: ${VALID_PROJECT_STATES.join(", ")}.`);
98
+ }
99
+ return value;
100
+ }
101
+ /**
102
+ * Parse and validate a --timeout value (seconds). Returns milliseconds for
103
+ * direct use with setTimeout. Accepts fractional values; rejects 0, negatives,
104
+ * NaN, and Infinity.
105
+ */
106
+ export function parseTimeoutSeconds(value) {
107
+ const n = Number(value);
108
+ if (value === "" || !Number.isFinite(n) || n <= 0) {
109
+ throw new ValidationError(`Invalid --timeout value: "${value}". Must be a positive number of seconds.`);
110
+ }
111
+ return Math.round(n * 1000);
112
+ }
113
+ /**
114
+ * Guard: throws if an update object has no fields set. Use in update commands
115
+ * to catch empty updates before sending to the API.
116
+ */
117
+ export function requireNonEmptyUpdate(update) {
118
+ const keys = Object.keys(update).filter((k) => update[k] !== undefined);
119
+ if (keys.length === 0) {
120
+ throw new ValidationError("No update options provided. Use --help to see available options.");
121
+ }
122
+ }
123
+ /**
124
+ * Guard: throws if `--yes` flag isn't set on a destructive command. Forces an
125
+ * explicit confirmation step that prompt-injected agents can't skip by talking
126
+ * themselves out of it.
127
+ */
128
+ export function requireYes(opts, action) {
129
+ if (!opts.yes) {
130
+ throw new ValidationError(`Refusing to ${action} without --yes. This operation is irreversible.`, "Re-run with --yes to confirm.");
131
+ }
132
+ }
133
+ //# sourceMappingURL=parse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse.js","sourceRoot":"","sources":["../../src/utils/parse.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export interface RecommendedState {
2
+ state: string | null;
3
+ warning?: string;
4
+ }
5
+ export declare function recommendedStateForStatus(type: string | null | undefined): RecommendedState;
6
+ //# sourceMappingURL=project-status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-status.d.ts","sourceRoot":"","sources":["../../src/utils/project-status.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,gBAAgB;IAChC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,gBAAgB,CAyB3F"}
@@ -0,0 +1,33 @@
1
+ // Mapping from Linear's project status `type` to a sensible default issue
2
+ // state for new issues filed in that project. Used by `projects get` and
3
+ // `context` so agents don't have to encode this mapping themselves.
4
+ //
5
+ // Conservative: paused/completed/canceled return null with a warning so the
6
+ // agent flags it instead of silently dropping the issue into a closed project.
7
+ export function recommendedStateForStatus(type) {
8
+ switch (type) {
9
+ case "backlog":
10
+ return { state: "Backlog" };
11
+ case "planned":
12
+ case "started":
13
+ return { state: "Todo" };
14
+ case "paused":
15
+ return {
16
+ state: null,
17
+ warning: "project is paused; confirm with the project lead before filing",
18
+ };
19
+ case "completed":
20
+ return {
21
+ state: null,
22
+ warning: "project is completed; pick a different project for new work",
23
+ };
24
+ case "canceled":
25
+ return {
26
+ state: null,
27
+ warning: "project is canceled; pick a different project for new work",
28
+ };
29
+ default:
30
+ return { state: null };
31
+ }
32
+ }
33
+ //# sourceMappingURL=project-status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-status.js","sourceRoot":"","sources":["../../src/utils/project-status.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,yEAAyE;AACzE,oEAAoE;AACpE,EAAE;AACF,4EAA4E;AAC5E,+EAA+E;AAO/E,MAAM,UAAU,yBAAyB,CAAC,IAA+B;IACxE,QAAQ,IAAI,EAAE,CAAC;QACd,KAAK,SAAS;YACb,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;QAC7B,KAAK,SAAS,CAAC;QACf,KAAK,SAAS;YACb,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QAC1B,KAAK,QAAQ;YACZ,OAAO;gBACN,KAAK,EAAE,IAAI;gBACX,OAAO,EAAE,gEAAgE;aACzE,CAAC;QACH,KAAK,WAAW;YACf,OAAO;gBACN,KAAK,EAAE,IAAI;gBACX,OAAO,EAAE,6DAA6D;aACtE,CAAC;QACH,KAAK,UAAU;YACd,OAAO;gBACN,KAAK,EAAE,IAAI;gBACX,OAAO,EAAE,4DAA4D;aACrE,CAAC;QACH;YACC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IACzB,CAAC;AACF,CAAC"}
@@ -0,0 +1,24 @@
1
+ declare function isRateLimitError(error: unknown): boolean;
2
+ /**
3
+ * Pull the retry delay (ms) out of a Linear SDK error.
4
+ *
5
+ * RatelimitedLinearError exposes `retryAfter` (seconds) directly — the SDK
6
+ * already parsed the retry-after header into a number. Earlier code tried to
7
+ * read `error.response.headers["retry-after"]`, but `headers` is a Fetch
8
+ * Headers object whose values are only readable via `.get()` — bracket access
9
+ * always returned undefined, so the wrapper silently fell back to the 60s
10
+ * default on every retry instead of honouring Linear's hint.
11
+ */
12
+ declare function parseRetryAfter(error: unknown): number;
13
+ /**
14
+ * Run fn, retry on 429 with Retry-After. Max 3 retries — after that the
15
+ * original error propagates.
16
+ */
17
+ export declare function withRateLimit<T>(fn: () => Promise<T>): Promise<T>;
18
+ export declare const _internal: {
19
+ isRateLimitError: typeof isRateLimitError;
20
+ parseRetryAfter: typeof parseRetryAfter;
21
+ MAX_RETRY_AFTER_MS: number;
22
+ };
23
+ export {};
24
+ //# sourceMappingURL=rate-limit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limit.d.ts","sourceRoot":"","sources":["../../src/utils/rate-limit.ts"],"names":[],"mappings":"AAmBA,iBAAS,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAejD;AAED;;;;;;;;;GASG;AACH,iBAAS,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAI/C;AA2BD;;;GAGG;AACH,wBAAsB,aAAa,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAgBvE;AAGD,eAAO,MAAM,SAAS;;;;CAA4D,CAAC"}