@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.
- package/.claude-plugin/marketplace.json +7 -2
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +25 -1
- package/README.md +275 -25
- package/agents/linear-issue-creator.md +135 -17
- package/agents/linear-issue-reviewer.md +122 -23
- package/agents/linear-issue-updater.md +137 -25
- package/agents/linear-state-curator.md +173 -0
- package/agents/linear-url-to-issues.md +190 -26
- package/commands/linear-cleanup.md +64 -29
- package/dist/cli.js +69 -1
- package/dist/cli.js.map +1 -1
- package/dist/client/auth.d.ts +10 -0
- package/dist/client/auth.d.ts.map +1 -1
- package/dist/client/auth.js +50 -3
- package/dist/client/auth.js.map +1 -1
- package/dist/client/linear-client.d.ts +7 -0
- package/dist/client/linear-client.d.ts.map +1 -1
- package/dist/client/linear-client.js +13 -1
- package/dist/client/linear-client.js.map +1 -1
- package/dist/commands/agent-activities.d.ts +3 -0
- package/dist/commands/agent-activities.d.ts.map +1 -0
- package/dist/commands/agent-activities.js +144 -0
- package/dist/commands/agent-activities.js.map +1 -0
- package/dist/commands/agent-sessions.d.ts +3 -0
- package/dist/commands/agent-sessions.d.ts.map +1 -0
- package/dist/commands/agent-sessions.js +132 -0
- package/dist/commands/agent-sessions.js.map +1 -0
- package/dist/commands/attachments.d.ts +3 -0
- package/dist/commands/attachments.d.ts.map +1 -0
- package/dist/commands/attachments.js +265 -0
- package/dist/commands/attachments.js.map +1 -0
- package/dist/commands/audit.d.ts +3 -0
- package/dist/commands/audit.d.ts.map +1 -0
- package/dist/commands/audit.js +73 -0
- package/dist/commands/audit.js.map +1 -0
- package/dist/commands/comments.d.ts +3 -0
- package/dist/commands/comments.d.ts.map +1 -0
- package/dist/commands/comments.js +107 -0
- package/dist/commands/comments.js.map +1 -0
- package/dist/commands/completion.d.ts +3 -0
- package/dist/commands/completion.d.ts.map +1 -0
- package/dist/commands/completion.js +62 -0
- package/dist/commands/completion.js.map +1 -0
- package/dist/commands/context.d.ts +3 -0
- package/dist/commands/context.d.ts.map +1 -0
- package/dist/commands/context.js +94 -0
- package/dist/commands/context.js.map +1 -0
- package/dist/commands/curator.d.ts +14 -0
- package/dist/commands/curator.d.ts.map +1 -1
- package/dist/commands/curator.js +97 -19
- package/dist/commands/curator.js.map +1 -1
- package/dist/commands/customer-needs.d.ts +3 -0
- package/dist/commands/customer-needs.d.ts.map +1 -0
- package/dist/commands/customer-needs.js +198 -0
- package/dist/commands/customer-needs.js.map +1 -0
- package/dist/commands/customers.d.ts +5 -0
- package/dist/commands/customers.d.ts.map +1 -0
- package/dist/commands/customers.js +201 -0
- package/dist/commands/customers.js.map +1 -0
- package/dist/commands/cycles.d.ts +3 -0
- package/dist/commands/cycles.d.ts.map +1 -0
- package/dist/commands/cycles.js +67 -0
- package/dist/commands/cycles.js.map +1 -0
- package/dist/commands/documents.d.ts +3 -0
- package/dist/commands/documents.d.ts.map +1 -0
- package/dist/commands/documents.js +105 -0
- package/dist/commands/documents.js.map +1 -0
- package/dist/commands/favorites.d.ts +3 -0
- package/dist/commands/favorites.d.ts.map +1 -0
- package/dist/commands/favorites.js +101 -0
- package/dist/commands/favorites.js.map +1 -0
- package/dist/commands/index.d.ts +30 -0
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/index.js +30 -0
- package/dist/commands/index.js.map +1 -1
- package/dist/commands/initiatives.d.ts +3 -0
- package/dist/commands/initiatives.d.ts.map +1 -0
- package/dist/commands/initiatives.js +106 -0
- package/dist/commands/initiatives.js.map +1 -0
- package/dist/commands/issues.d.ts +21 -0
- package/dist/commands/issues.d.ts.map +1 -0
- package/dist/commands/issues.js +1083 -0
- package/dist/commands/issues.js.map +1 -0
- package/dist/commands/labels.d.ts +3 -0
- package/dist/commands/labels.d.ts.map +1 -0
- package/dist/commands/labels.js +111 -0
- package/dist/commands/labels.js.map +1 -0
- package/dist/commands/milestones.d.ts +3 -0
- package/dist/commands/milestones.d.ts.map +1 -0
- package/dist/commands/milestones.js +94 -0
- package/dist/commands/milestones.js.map +1 -0
- package/dist/commands/notifications.d.ts +3 -0
- package/dist/commands/notifications.d.ts.map +1 -0
- package/dist/commands/notifications.js +130 -0
- package/dist/commands/notifications.js.map +1 -0
- package/dist/commands/project-labels.d.ts +3 -0
- package/dist/commands/project-labels.d.ts.map +1 -0
- package/dist/commands/project-labels.js +80 -0
- package/dist/commands/project-labels.js.map +1 -0
- package/dist/commands/project-relations.d.ts +3 -0
- package/dist/commands/project-relations.d.ts.map +1 -0
- package/dist/commands/project-relations.js +96 -0
- package/dist/commands/project-relations.js.map +1 -0
- package/dist/commands/projects.d.ts +3 -0
- package/dist/commands/projects.d.ts.map +1 -0
- package/dist/commands/projects.js +263 -0
- package/dist/commands/projects.js.map +1 -0
- package/dist/commands/quota.d.ts +3 -0
- package/dist/commands/quota.d.ts.map +1 -0
- package/dist/commands/quota.js +28 -0
- package/dist/commands/quota.js.map +1 -0
- package/dist/commands/reactions.d.ts +7 -0
- package/dist/commands/reactions.d.ts.map +1 -0
- package/dist/commands/reactions.js +53 -0
- package/dist/commands/reactions.js.map +1 -0
- package/dist/commands/relations.d.ts +3 -0
- package/dist/commands/relations.d.ts.map +1 -0
- package/dist/commands/relations.js +73 -0
- package/dist/commands/relations.js.map +1 -0
- package/dist/commands/states.d.ts +3 -0
- package/dist/commands/states.d.ts.map +1 -0
- package/dist/commands/states.js +52 -0
- package/dist/commands/states.js.map +1 -0
- package/dist/commands/status-updates.d.ts +3 -0
- package/dist/commands/status-updates.d.ts.map +1 -0
- package/dist/commands/status-updates.js +117 -0
- package/dist/commands/status-updates.js.map +1 -0
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +58 -18
- package/dist/commands/sync.js.map +1 -1
- package/dist/commands/teams.d.ts +3 -0
- package/dist/commands/teams.d.ts.map +1 -0
- package/dist/commands/teams.js +135 -0
- package/dist/commands/teams.js.map +1 -0
- package/dist/commands/templates.d.ts +3 -0
- package/dist/commands/templates.d.ts.map +1 -0
- package/dist/commands/templates.js +76 -0
- package/dist/commands/templates.js.map +1 -0
- package/dist/commands/users.d.ts +3 -0
- package/dist/commands/users.d.ts.map +1 -0
- package/dist/commands/users.js +40 -0
- package/dist/commands/users.js.map +1 -0
- package/dist/commands/views.d.ts +3 -0
- package/dist/commands/views.d.ts.map +1 -0
- package/dist/commands/views.js +177 -0
- package/dist/commands/views.js.map +1 -0
- package/dist/commands/webhooks.d.ts +3 -0
- package/dist/commands/webhooks.d.ts.map +1 -0
- package/dist/commands/webhooks.js +234 -0
- package/dist/commands/webhooks.js.map +1 -0
- package/dist/config/loader.d.ts.map +1 -1
- package/dist/config/loader.js +3 -0
- package/dist/config/loader.js.map +1 -1
- package/dist/config/types.d.ts +15 -1
- package/dist/config/types.d.ts.map +1 -1
- package/dist/config/types.js +1 -0
- package/dist/config/types.js.map +1 -1
- package/dist/curator/dispatch.d.ts +52 -0
- package/dist/curator/dispatch.d.ts.map +1 -0
- package/dist/curator/dispatch.js +144 -0
- package/dist/curator/dispatch.js.map +1 -0
- package/dist/curator/index.d.ts +5 -0
- package/dist/curator/index.d.ts.map +1 -0
- package/dist/curator/index.js +5 -0
- package/dist/curator/index.js.map +1 -0
- package/dist/curator/llm.d.ts +70 -0
- package/dist/curator/llm.d.ts.map +1 -0
- package/dist/curator/llm.js +107 -0
- package/dist/curator/llm.js.map +1 -0
- package/dist/curator/snapshot.d.ts +34 -0
- package/dist/curator/snapshot.d.ts.map +1 -0
- package/dist/curator/snapshot.js +127 -0
- package/dist/curator/snapshot.js.map +1 -0
- package/dist/curator/state.d.ts +50 -0
- package/dist/curator/state.d.ts.map +1 -0
- package/dist/curator/state.js +125 -0
- package/dist/curator/state.js.map +1 -0
- package/dist/lib/bulk-graphql.d.ts +144 -0
- package/dist/lib/bulk-graphql.d.ts.map +1 -0
- package/dist/lib/bulk-graphql.js +380 -0
- package/dist/lib/bulk-graphql.js.map +1 -0
- package/dist/lib/index.d.ts +2 -0
- package/dist/lib/index.d.ts.map +1 -0
- package/dist/lib/index.js +2 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/output/cli.d.ts +17 -0
- package/dist/output/cli.d.ts.map +1 -0
- package/dist/output/cli.js +252 -0
- package/dist/output/cli.js.map +1 -0
- package/dist/output/formatter.d.ts +6 -0
- package/dist/output/formatter.d.ts.map +1 -1
- package/dist/output/formatter.js +10 -0
- package/dist/output/formatter.js.map +1 -1
- package/dist/output/index.d.ts +1 -0
- package/dist/output/index.d.ts.map +1 -1
- package/dist/output/index.js +1 -0
- package/dist/output/index.js.map +1 -1
- package/dist/scripts/sync-linear-templates.d.ts +26 -0
- package/dist/scripts/sync-linear-templates.d.ts.map +1 -0
- package/dist/scripts/sync-linear-templates.js +115 -0
- package/dist/scripts/sync-linear-templates.js.map +1 -0
- package/dist/signals/github-commits.d.ts +31 -0
- package/dist/signals/github-commits.d.ts.map +1 -0
- package/dist/signals/github-commits.js +127 -0
- package/dist/signals/github-commits.js.map +1 -0
- package/dist/signals/github-pr.d.ts +16 -0
- package/dist/signals/github-pr.d.ts.map +1 -0
- package/dist/signals/github-pr.js +98 -0
- package/dist/signals/github-pr.js.map +1 -0
- package/dist/signals/index.d.ts +4 -0
- package/dist/signals/index.d.ts.map +1 -1
- package/dist/signals/index.js +4 -0
- package/dist/signals/index.js.map +1 -1
- package/dist/signals/linear-issues.d.ts +20 -0
- package/dist/signals/linear-issues.d.ts.map +1 -0
- package/dist/signals/linear-issues.js +115 -0
- package/dist/signals/linear-issues.js.map +1 -0
- package/dist/signals/registry.d.ts +4 -3
- package/dist/signals/registry.d.ts.map +1 -1
- package/dist/signals/registry.js +33 -11
- package/dist/signals/registry.js.map +1 -1
- package/dist/signals/slack-messages.d.ts +20 -0
- package/dist/signals/slack-messages.d.ts.map +1 -0
- package/dist/signals/slack-messages.js +129 -0
- package/dist/signals/slack-messages.js.map +1 -0
- package/dist/utils/errors.d.ts +81 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +110 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/index.d.ts +9 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +9 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/label-policy.d.ts +60 -0
- package/dist/utils/label-policy.d.ts.map +1 -0
- package/dist/utils/label-policy.js +103 -0
- package/dist/utils/label-policy.js.map +1 -0
- package/dist/utils/parse.d.ts +48 -0
- package/dist/utils/parse.d.ts.map +1 -0
- package/dist/utils/parse.js +133 -0
- package/dist/utils/parse.js.map +1 -0
- package/dist/utils/project-status.d.ts +6 -0
- package/dist/utils/project-status.d.ts.map +1 -0
- package/dist/utils/project-status.js +33 -0
- package/dist/utils/project-status.js.map +1 -0
- package/dist/utils/rate-limit.d.ts +24 -0
- package/dist/utils/rate-limit.d.ts.map +1 -0
- package/dist/utils/rate-limit.js +89 -0
- package/dist/utils/rate-limit.js.map +1 -0
- package/dist/utils/resolve.d.ts +84 -0
- package/dist/utils/resolve.d.ts.map +1 -0
- package/dist/utils/resolve.js +172 -0
- package/dist/utils/resolve.js.map +1 -0
- package/dist/utils/sleep.d.ts +2 -0
- package/dist/utils/sleep.d.ts.map +1 -0
- package/dist/utils/sleep.js +4 -0
- package/dist/utils/sleep.js.map +1 -0
- package/dist/utils/webhook-verify.d.ts +42 -0
- package/dist/utils/webhook-verify.d.ts.map +1 -0
- package/dist/utils/webhook-verify.js +65 -0
- package/dist/utils/webhook-verify.js.map +1 -0
- package/package.json +7 -2
- package/references/agent-description-template.md +31 -0
- package/references/cli-reference.md +227 -0
- package/references/curator-tiering-rules.md +78 -0
- package/references/label-policy.example.json +37 -0
- package/references/label-policy.placeholder.json +6 -0
- package/references/settings-template.md +30 -0
- package/references/signal-sources.example.json +0 -8
- package/references/sla-reference.md +70 -0
- package/references/template-index.md +34 -0
- package/references/workspace-labels.md +124 -0
- package/references/workspace-projects.md +56 -0
- package/references/workspace-routing.md +58 -0
- package/schemas/label-policy.json +72 -0
- package/scripts/postinstall.mjs +195 -0
- package/skills/linear-workspace/SKILL.md +65 -4
- package/templates/ACC-PRO-provision.md +74 -0
- package/templates/ACC-PRV-privileged.md +66 -0
- package/templates/ACC-QTR-review.md +77 -0
- package/templates/ACC-REV-revoke.md +67 -0
- package/templates/AI-USE-capability.md +111 -0
- package/templates/AUD-CAP-corrective.md +89 -0
- package/templates/AUD-INT-internal.md +92 -0
- package/templates/AUD-MGT-management.md +110 -0
- package/templates/CHG-MAJ-major.md +110 -0
- package/templates/CHG-SIG-significant.md +83 -0
- package/templates/CHG-STD-standard.md +47 -0
- package/templates/LRN-DOC-lessons.md +75 -0
- package/templates/OPS-BCK-backup.md +99 -0
- package/templates/OPS-DAT-data-mod.md +98 -0
- package/templates/RCA-DOC-root-cause.md +105 -0
- package/templates/RSK-ASS-assessment.md +87 -0
- package/templates/RSK-VND-vendor.md +113 -0
- package/templates/SEC-INC-incident.md +76 -0
- package/templates/SEC-PEN-pentest.md +58 -0
- package/templates/SEC-VLN-vulnerability.md +69 -0
- package/templates/SLA-AVL-availability.md +86 -0
- package/templates/SLA-OPS-operational.md +70 -0
- package/templates/agent-server-template/README.md +88 -0
- package/templates/agent-server-template/server.example.ts +185 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dedicated exit codes per error type.
|
|
3
|
+
* 0 = success, 1 = general/unknown, 2 = validation, 3 = auth, 4 = not found.
|
|
4
|
+
*/
|
|
5
|
+
export declare const EXIT_CODES: {
|
|
6
|
+
readonly SUCCESS: 0;
|
|
7
|
+
readonly GENERAL: 1;
|
|
8
|
+
readonly VALIDATION: 2;
|
|
9
|
+
readonly AUTH: 3;
|
|
10
|
+
readonly NOT_FOUND: 4;
|
|
11
|
+
};
|
|
12
|
+
export declare class CliError extends Error {
|
|
13
|
+
readonly userMessage: string;
|
|
14
|
+
readonly suggestion?: string;
|
|
15
|
+
readonly exitCode: number;
|
|
16
|
+
/**
|
|
17
|
+
* Optional structured payload merged into the JSON error envelope. Used by
|
|
18
|
+
* validation errors that need to expose machine-readable detail (e.g. which
|
|
19
|
+
* labels are missing, what the team's accepted set is) so an agent can
|
|
20
|
+
* self-correct without re-reading reference files.
|
|
21
|
+
*/
|
|
22
|
+
readonly data?: Record<string, unknown>;
|
|
23
|
+
constructor(message: string, options?: {
|
|
24
|
+
suggestion?: string;
|
|
25
|
+
exitCode?: number;
|
|
26
|
+
data?: Record<string, unknown>;
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
export declare class AuthError extends CliError {
|
|
30
|
+
constructor(message?: string);
|
|
31
|
+
}
|
|
32
|
+
export declare class NotFoundError extends CliError {
|
|
33
|
+
constructor(entity: string, identifier: string);
|
|
34
|
+
}
|
|
35
|
+
export declare class ValidationError extends CliError {
|
|
36
|
+
constructor(message: string, suggestion?: string, data?: Record<string, unknown>);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Specialized validation error for label-policy violations on `issues create`.
|
|
40
|
+
* The structured `data` field is the load-bearing part — agents read it to
|
|
41
|
+
* self-correct in one retry instead of re-reading workspace-labels.md.
|
|
42
|
+
*/
|
|
43
|
+
export declare class LabelValidationError extends ValidationError {
|
|
44
|
+
constructor(data: {
|
|
45
|
+
error: "labels_invalid";
|
|
46
|
+
team: string;
|
|
47
|
+
teamKey: string;
|
|
48
|
+
missing: {
|
|
49
|
+
prefixes: string[];
|
|
50
|
+
min: number;
|
|
51
|
+
description?: string;
|
|
52
|
+
}[];
|
|
53
|
+
excess: {
|
|
54
|
+
prefixes: string[];
|
|
55
|
+
max: number;
|
|
56
|
+
passed: string[];
|
|
57
|
+
}[];
|
|
58
|
+
passed: string[];
|
|
59
|
+
availableForPrefix: Record<string, string[]>;
|
|
60
|
+
suggestedRetry: string;
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Specialized validation error for project-policy violations on `issues create`.
|
|
65
|
+
* Fires when a team requires a project (default) and `--project` was not passed,
|
|
66
|
+
* provided the team has at least one project to choose from. Structured `data`
|
|
67
|
+
* lets the agent self-correct in one retry.
|
|
68
|
+
*/
|
|
69
|
+
export declare class ProjectValidationError extends ValidationError {
|
|
70
|
+
constructor(data: {
|
|
71
|
+
error: "project_required";
|
|
72
|
+
team: string;
|
|
73
|
+
teamKey: string;
|
|
74
|
+
availableProjects: {
|
|
75
|
+
name: string;
|
|
76
|
+
status: string | null;
|
|
77
|
+
}[];
|
|
78
|
+
suggestedRetry: string;
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -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;AAED;;;;;GAKG;AACH,qBAAa,sBAAuB,SAAQ,eAAe;gBAC9C,IAAI,EAAE;QACjB,KAAK,EAAE,kBAAkB,CAAC;QAC1B,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,iBAAiB,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;SAAE,EAAE,CAAC;QAC7D,cAAc,EAAE,MAAM,CAAC;KACvB;CAUD"}
|
|
@@ -0,0 +1,110 @@
|
|
|
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
|
+
/**
|
|
95
|
+
* Specialized validation error for project-policy violations on `issues create`.
|
|
96
|
+
* Fires when a team requires a project (default) and `--project` was not passed,
|
|
97
|
+
* provided the team has at least one project to choose from. Structured `data`
|
|
98
|
+
* lets the agent self-correct in one retry.
|
|
99
|
+
*/
|
|
100
|
+
export class ProjectValidationError extends ValidationError {
|
|
101
|
+
constructor(data) {
|
|
102
|
+
const message = data.availableProjects.length === 1
|
|
103
|
+
? `Team "${data.team}" requires every issue to have a project. Available: "${data.availableProjects[0].name}".`
|
|
104
|
+
: `Team "${data.team}" requires every issue to have a project. ${data.availableProjects.length} projects available.`;
|
|
105
|
+
const suggestion = "Pass --project <name> from availableProjects, or re-run the suggestedRetry command. To bypass (e.g. a placeholder issue), pass --skip-project-check.";
|
|
106
|
+
super(message, suggestion, { ...data });
|
|
107
|
+
this.name = "ProjectValidationError";
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
//# 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,60 @@
|
|
|
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
|
+
* Resolve whether a team requires every issue to have a project. Default is
|
|
32
|
+
* `true` — workspaces opt out per-team by setting `requiresProject: false` in
|
|
33
|
+
* `label-policy.json`. Unknown teams (no policy entry) also default to `true`.
|
|
34
|
+
* Callers must still allow the create when the team has zero projects.
|
|
35
|
+
*/
|
|
36
|
+
export declare function teamRequiresProject(teamKey: string, opts?: LoadLabelPolicyOptions): boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Group labels by their first matching prefix. Labels not matching any known
|
|
39
|
+
* prefix go to "_unprefixed". Order of knownPrefixes matters: the first match
|
|
40
|
+
* wins, so put more specific prefixes earlier if any overlap.
|
|
41
|
+
*/
|
|
42
|
+
export declare function groupLabelsByPrefix(labelNames: string[], knownPrefixes: string[]): Record<string, string[]>;
|
|
43
|
+
export interface LabelValidationFailure {
|
|
44
|
+
group: RequirementGroup;
|
|
45
|
+
count: number;
|
|
46
|
+
reason: "missing" | "excess";
|
|
47
|
+
}
|
|
48
|
+
export interface LabelValidationResult {
|
|
49
|
+
valid: boolean;
|
|
50
|
+
failures: LabelValidationFailure[];
|
|
51
|
+
passed: string[];
|
|
52
|
+
availableForPrefix: Record<string, string[]>;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Validate that the proposed labels satisfy the team's required prefix groups.
|
|
56
|
+
* Unknown teams pass through (no enforcement) so workspaces without a config
|
|
57
|
+
* entry don't break.
|
|
58
|
+
*/
|
|
59
|
+
export declare function validateLabelsAgainstTeam(teamKey: string, passedLabels: string[], teamLabelCatalog: string[], opts?: LoadLabelPolicyOptions): LabelValidationResult;
|
|
60
|
+
//# 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;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,GAAE,sBAA2B,GAAG,OAAO,CAG/F;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,103 @@
|
|
|
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
|
+
* Resolve whether a team requires every issue to have a project. Default is
|
|
34
|
+
* `true` — workspaces opt out per-team by setting `requiresProject: false` in
|
|
35
|
+
* `label-policy.json`. Unknown teams (no policy entry) also default to `true`.
|
|
36
|
+
* Callers must still allow the create when the team has zero projects.
|
|
37
|
+
*/
|
|
38
|
+
export function teamRequiresProject(teamKey, opts = {}) {
|
|
39
|
+
const policy = getTeamLabelPolicy(teamKey, opts);
|
|
40
|
+
return policy?.requiresProject ?? true;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Group labels by their first matching prefix. Labels not matching any known
|
|
44
|
+
* prefix go to "_unprefixed". Order of knownPrefixes matters: the first match
|
|
45
|
+
* wins, so put more specific prefixes earlier if any overlap.
|
|
46
|
+
*/
|
|
47
|
+
export function groupLabelsByPrefix(labelNames, knownPrefixes) {
|
|
48
|
+
const result = { _unprefixed: [] };
|
|
49
|
+
for (const prefix of knownPrefixes)
|
|
50
|
+
result[prefix] = [];
|
|
51
|
+
for (const name of labelNames) {
|
|
52
|
+
const prefix = knownPrefixes.find((p) => name.startsWith(p));
|
|
53
|
+
if (prefix) {
|
|
54
|
+
result[prefix].push(name);
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
result._unprefixed.push(name);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return result;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Validate that the proposed labels satisfy the team's required prefix groups.
|
|
64
|
+
* Unknown teams pass through (no enforcement) so workspaces without a config
|
|
65
|
+
* entry don't break.
|
|
66
|
+
*/
|
|
67
|
+
export function validateLabelsAgainstTeam(teamKey, passedLabels, teamLabelCatalog, opts = {}) {
|
|
68
|
+
const policy = getTeamLabelPolicy(teamKey, opts);
|
|
69
|
+
if (!policy) {
|
|
70
|
+
return { valid: true, failures: [], passed: passedLabels, availableForPrefix: {} };
|
|
71
|
+
}
|
|
72
|
+
const passedByPrefix = groupLabelsByPrefix(passedLabels, policy.allowedPrefixes);
|
|
73
|
+
const catalogByPrefix = groupLabelsByPrefix(teamLabelCatalog, policy.allowedPrefixes);
|
|
74
|
+
const failures = [];
|
|
75
|
+
const failedPrefixes = new Set();
|
|
76
|
+
for (const group of policy.required) {
|
|
77
|
+
let count = 0;
|
|
78
|
+
for (const prefix of group.prefixes) {
|
|
79
|
+
count += (passedByPrefix[prefix] ?? []).length;
|
|
80
|
+
}
|
|
81
|
+
if (count < group.min) {
|
|
82
|
+
failures.push({ group, count, reason: "missing" });
|
|
83
|
+
for (const p of group.prefixes)
|
|
84
|
+
failedPrefixes.add(p);
|
|
85
|
+
}
|
|
86
|
+
else if (group.max != null && count > group.max) {
|
|
87
|
+
failures.push({ group, count, reason: "excess" });
|
|
88
|
+
for (const p of group.prefixes)
|
|
89
|
+
failedPrefixes.add(p);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
const availableForPrefix = {};
|
|
93
|
+
for (const prefix of failedPrefixes) {
|
|
94
|
+
availableForPrefix[prefix] = catalogByPrefix[prefix] ?? [];
|
|
95
|
+
}
|
|
96
|
+
return {
|
|
97
|
+
valid: failures.length === 0,
|
|
98
|
+
failures,
|
|
99
|
+
passed: passedLabels,
|
|
100
|
+
availableForPrefix,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
//# 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 @@
|
|
|
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"}
|