@elnora-ai/linear 1.1.0 → 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.
@@ -91,4 +91,20 @@ export class LabelValidationError extends ValidationError {
91
91
  this.name = "LabelValidationError";
92
92
  }
93
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
+ }
94
110
  //# sourceMappingURL=errors.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,EAAE;AACF,8EAA8E;AAC9E,8EAA8E;AAC9E,6EAA6E;AAE7E;;;GAGG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG;IACzB,OAAO,EAAE,CAAC;IACV,OAAO,EAAE,CAAC;IACV,UAAU,EAAE,CAAC;IACb,IAAI,EAAE,CAAC;IACP,SAAS,EAAE,CAAC;CACH,CAAC;AAEX,MAAM,OAAO,QAAS,SAAQ,KAAK;IACzB,WAAW,CAAS;IACpB,UAAU,CAAU;IACpB,QAAQ,CAAS;IAC1B;;;;;OAKG;IACM,IAAI,CAA2B;IAExC,YAAY,OAAe,EAAE,OAAoF;QAChH,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;QACvB,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC;QAC3B,IAAI,CAAC,UAAU,GAAG,OAAO,EAAE,UAAU,CAAC;QACtC,IAAI,CAAC,QAAQ,GAAG,OAAO,EAAE,QAAQ,IAAI,UAAU,CAAC,OAAO,CAAC;QACxD,IAAI,CAAC,IAAI,GAAG,OAAO,EAAE,IAAI,CAAC;IAC3B,CAAC;CACD;AAED,MAAM,OAAO,SAAU,SAAQ,QAAQ;IACtC,YAAY,OAAgB;QAC3B,KAAK,CAAC,OAAO,IAAI,kEAAkE,EAAE;YACpF,UAAU,EACT,8GAA8G;YAC/G,QAAQ,EAAE,UAAU,CAAC,IAAI;SACzB,CAAC,CAAC;QACH,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;IACzB,CAAC;CACD;AAED,qEAAqE;AACrE,MAAM,oBAAoB,GAA2B;IACpD,IAAI,EAAE,0BAA0B;IAChC,OAAO,EAAE,6BAA6B;IACtC,IAAI,EAAE,0BAA0B;IAChC,KAAK,EAAE,2BAA2B;IAClC,KAAK,EAAE,yCAAyC;IAChD,KAAK,EAAE,2BAA2B;IAClC,UAAU,EAAE,gCAAgC;IAC5C,SAAS,EAAE,mDAAmD;IAC9D,gBAAgB,EAAE,yCAAyC;CAC3D,CAAC;AAEF,MAAM,OAAO,aAAc,SAAQ,QAAQ;IAC1C,YAAY,MAAc,EAAE,UAAkB;QAC7C,MAAM,OAAO,GAAG,oBAAoB,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,IAAI,iBAAiB,MAAM,CAAC,WAAW,EAAE,QAAQ,CAAC;QAC5G,KAAK,CAAC,GAAG,MAAM,eAAe,UAAU,EAAE,EAAE;YAC3C,UAAU,EAAE,4CAA4C,OAAO,sBAAsB,MAAM,CAAC,WAAW,EAAE,IAAI;YAC7G,QAAQ,EAAE,UAAU,CAAC,SAAS;SAC9B,CAAC,CAAC;QACH,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC7B,CAAC;CACD;AAED,MAAM,OAAO,eAAgB,SAAQ,QAAQ;IAC5C,YAAY,OAAe,EAAE,UAAmB,EAAE,IAA8B;QAC/E,KAAK,CAAC,OAAO,EAAE,EAAE,UAAU,EAAE,QAAQ,EAAE,UAAU,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC;QACtE,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAC/B,CAAC;CACD;AAED;;;;GAIG;AACH,MAAM,OAAO,oBAAqB,SAAQ,eAAe;IACxD,YAAY,IASX;QACA,MAAM,OAAO,GAAa,EAAE,CAAC;QAC7B,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAC9B,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACnE,CAAC;QACD,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAC7B,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC;QACpE,CAAC;QACD,MAAM,OAAO,GAAG,oCAAoC,IAAI,CAAC,IAAI,MAAM,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;QACzF,MAAM,UAAU,GACf,4GAA4G,CAAC;QAC9G,KAAK,CAAC,OAAO,EAAE,UAAU,EAAE,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC;QACxC,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;IACpC,CAAC;CACD;AAED;;;;;GAKG;AACH,MAAM,OAAO,sBAAuB,SAAQ,eAAe;IAC1D,YAAY,IAMX;QACA,MAAM,OAAO,GACZ,IAAI,CAAC,iBAAiB,CAAC,MAAM,KAAK,CAAC;YAClC,CAAC,CAAC,SAAS,IAAI,CAAC,IAAI,yDAAyD,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI;YAC/G,CAAC,CAAC,SAAS,IAAI,CAAC,IAAI,6CAA6C,IAAI,CAAC,iBAAiB,CAAC,MAAM,sBAAsB,CAAC;QACvH,MAAM,UAAU,GACf,sJAAsJ,CAAC;QACxJ,KAAK,CAAC,OAAO,EAAE,UAAU,EAAE,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC;QACxC,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAC;IACtC,CAAC;CACD"}
@@ -27,6 +27,13 @@ export declare function loadLabelPolicies(opts?: LoadLabelPolicyOptions): LabelP
27
27
  /** Reset the module-level cache (used in tests). */
28
28
  export declare function resetLabelPolicyCache(): void;
29
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;
30
37
  /**
31
38
  * Group labels by their first matching prefix. Labels not matching any known
32
39
  * prefix go to "_unprefixed". Order of knownPrefixes matters: the first match
@@ -1 +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"}
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"}
@@ -29,6 +29,16 @@ export function resetLabelPolicyCache() {
29
29
  export function getTeamLabelPolicy(teamKey, opts = {}) {
30
30
  return loadLabelPolicies(opts).policies[teamKey] ?? null;
31
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
+ }
32
42
  /**
33
43
  * Group labels by their first matching prefix. Labels not matching any known
34
44
  * prefix go to "_unprefixed". Order of knownPrefixes matters: the first match
@@ -1 +1 @@
1
- {"version":3,"file":"label-policy.js","sourceRoot":"","sources":["../../src/utils/label-policy.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"label-policy.js","sourceRoot":"","sources":["../../src/utils/label-policy.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elnora-ai/linear",
3
- "version": "1.1.0",
3
+ "version": "2.0.0",
4
4
  "description": "Linear workspace for Claude Code — search, bulk edit, agents, and a config-driven curator",
5
5
  "type": "module",
6
6
  "bin": {
@@ -13,6 +13,7 @@
13
13
  "commands/",
14
14
  "skills/",
15
15
  "schemas/",
16
+ "scripts/postinstall.mjs",
16
17
  "references/*.md",
17
18
  "references/*.placeholder.json",
18
19
  "references/*.example.json",
@@ -36,7 +37,8 @@
36
37
  "lint": "biome check src/ __tests__/",
37
38
  "lint:fix": "biome check --write src/ __tests__/",
38
39
  "format": "biome format --write src/ __tests__/",
39
- "typecheck": "tsc --noEmit"
40
+ "typecheck": "tsc --noEmit",
41
+ "postinstall": "node scripts/postinstall.mjs"
40
42
  },
41
43
  "keywords": [
42
44
  "linear",
@@ -4,6 +4,8 @@ Edit this file to tune the curator's behavior. Loaded at runtime by the curator
4
4
 
5
5
  The curator scores every open issue (Todo / In Progress / Backlog) on the teams listed in `teams.json` against the rules below and picks the highest-confidence tier that fires.
6
6
 
7
+ > **Implementation status (2026-05):** the HIGH tier (auto-apply) and LOW tier (report only) are fully wired. The MEDIUM tier currently stages questions in `~/.config/elnora-linear/state/curator-state.json` only — the Slack-posting and DM-back paths described below (top-level channel posts, threaded LLM-classified replies, label-allowlist DMs) are part of the design contract but **not yet shipped**. The orchestrator that posts to Slack, classifies replies, and applies the result is a follow-up release. Treat the Slack language as planned behavior; today, a human reads the state file (or the `linear-state-curator` agent does).
8
+
7
9
  ## HIGH — auto-apply state changes (cap: 20 per run)
8
10
 
9
11
  Any one of these fires the HIGH tier. The curator updates state via `elnora-linear issues update`, posts a rationale comment on the issue with cited signals, and lists the action in the daily summary.
@@ -29,14 +29,6 @@
29
29
  "command": "ci-cli list-failing-builds --json",
30
30
  "parse_as": "json",
31
31
  "issue_match_field": "linear_issue_id"
32
- },
33
- {
34
- "type": "mcp_tool",
35
- "name": "stripe-payment-failures",
36
- "enabled": false,
37
- "server": "stripe-cli",
38
- "tool": "list_failed_payments",
39
- "args": { "lookback_hours": 24 }
40
32
  }
41
33
  ]
42
34
  }
@@ -60,7 +60,7 @@
60
60
  },
61
61
  "requiresProject": {
62
62
  "type": "boolean",
63
- "description": "If true, every new issue on this team must have a project set."
63
+ "description": "If true (default), every new issue on this team must have a project set; `issues create` exits 2 with a structured ProjectValidationError when --project is omitted. Set false to allow issues without a project. Teams with zero projects available auto-pass regardless. Bypass per-call with --skip-project-check."
64
64
  }
65
65
  }
66
66
  }
@@ -0,0 +1,195 @@
1
+ #!/usr/bin/env node
2
+ // Postinstall hook for @elnora-ai/linear.
3
+ //
4
+ // Goal: after the user installs the package, automatically populate the
5
+ // reference files (teams/projects/users/workflows) from their Linear workspace
6
+ // so the agents and slash commands are personalised on first use — without
7
+ // requiring a manual `elnora-linear sync all` step.
8
+ //
9
+ // Behaviour:
10
+ // - If no API key is reachable, print a friendly notice telling the user how
11
+ // to enable the sync. Never block the install.
12
+ // - If a key is reachable (LINEAR_API_KEY env var, or already saved in
13
+ // ~/.config/elnora-linear/.env), run `sync all` with a hard timeout.
14
+ // Network/API failures degrade to a printed notice.
15
+ // - Always exits 0. A postinstall hook that fails the install is worse than
16
+ // no postinstall hook at all.
17
+ //
18
+ // Escape hatches (set any of these to skip the auto-sync entirely):
19
+ // - ELNORA_LINEAR_SKIP_POSTINSTALL=1
20
+ // - CI=true (most CI systems set this)
21
+ // - npm_config_global=false (local installs in a project)
22
+ //
23
+ // The "local install" skip prevents this from firing on every fresh
24
+ // node_modules in CI builds, monorepo workspaces, Docker layer caches, etc.
25
+ // Global installs (`npm install -g @elnora-ai/linear`) are the user-facing
26
+ // path we want to personalise.
27
+
28
+ import { spawn } from "node:child_process";
29
+ import { existsSync, readFileSync } from "node:fs";
30
+ import { homedir } from "node:os";
31
+ import { dirname, join } from "node:path";
32
+ import { fileURLToPath } from "node:url";
33
+
34
+ const __filename = fileURLToPath(import.meta.url);
35
+ const __dirname = dirname(__filename);
36
+ const PACKAGE_ROOT = dirname(__dirname);
37
+ const CLI_ENTRY = join(PACKAGE_ROOT, "dist", "cli.js");
38
+ const ENV_FILE = join(homedir(), ".config", "elnora-linear", ".env");
39
+
40
+ const SYNC_TIMEOUT_MS = 60_000;
41
+
42
+ const ESC = "\x1b[";
43
+ const useColor = () => process.stdout.isTTY && !process.env.NO_COLOR;
44
+ const COLORS = {
45
+ dim: (s) => (useColor() ? `${ESC}2m${s}${ESC}0m` : s),
46
+ yellow: (s) => (useColor() ? `${ESC}33m${s}${ESC}0m` : s),
47
+ green: (s) => (useColor() ? `${ESC}32m${s}${ESC}0m` : s),
48
+ cyan: (s) => (useColor() ? `${ESC}36m${s}${ESC}0m` : s),
49
+ };
50
+
51
+ function log(line) {
52
+ process.stdout.write(`${line}\n`);
53
+ }
54
+
55
+ export function shouldSkip(env = process.env) {
56
+ if (env.ELNORA_LINEAR_SKIP_POSTINSTALL === "1") {
57
+ return "ELNORA_LINEAR_SKIP_POSTINSTALL=1 is set";
58
+ }
59
+ if (env.CI === "true" || env.CI === "1") {
60
+ return "running in CI";
61
+ }
62
+ // npm sets npm_config_global=true for `-g` installs. Anything else (a local
63
+ // install, a yarn workspace, a pnpm dep resolution) skips. Note: npm sets
64
+ // the env var as a literal string.
65
+ if (env.npm_config_global !== undefined && env.npm_config_global !== "true") {
66
+ return "not a global install";
67
+ }
68
+ return null;
69
+ }
70
+
71
+ export function findApiKey(env = process.env, envFile = ENV_FILE) {
72
+ const raw = env.LINEAR_API_KEY?.trim().replace(/^["']|["']$/g, "");
73
+ if (raw?.startsWith("lin_api_")) {
74
+ return { source: "env", value: raw };
75
+ }
76
+ if (existsSync(envFile)) {
77
+ try {
78
+ const content = readFileSync(envFile, "utf8");
79
+ for (const line of content.split("\n")) {
80
+ const match = line.match(/^LINEAR_API_KEY\s*=\s*(.+?)\s*$/);
81
+ if (match) {
82
+ const value = match[1].replace(/^["']|["']$/g, "");
83
+ if (value.startsWith("lin_api_")) {
84
+ return { source: envFile, value };
85
+ }
86
+ }
87
+ }
88
+ } catch {
89
+ // Unreadable env file — fall through to no-key.
90
+ }
91
+ }
92
+ return null;
93
+ }
94
+
95
+ function printNoKeyNotice() {
96
+ log("");
97
+ log(COLORS.yellow("⚠ elnora-linear: could not personalise your Linear agents."));
98
+ log("");
99
+ log(" No Linear API key was found, so the reference files");
100
+ log(" (teams, projects, users, workflows) were not populated from");
101
+ log(" your Linear workspace.");
102
+ log("");
103
+ log(" To finish setup:");
104
+ log(` 1. Get a key at ${COLORS.cyan("https://linear.app/settings/api")}`);
105
+ log(` 2. ${COLORS.cyan("export LINEAR_API_KEY=lin_api_...")}`);
106
+ log(` 3. ${COLORS.cyan("elnora-linear sync all")}`);
107
+ log("");
108
+ log(COLORS.dim(" (Skip this notice with ELNORA_LINEAR_SKIP_POSTINSTALL=1.)"));
109
+ log("");
110
+ }
111
+
112
+ function printFailureNotice(reason) {
113
+ log("");
114
+ log(COLORS.yellow("⚠ elnora-linear: auto-sync did not complete."));
115
+ log(` ${reason}`);
116
+ log("");
117
+ log(` You can rerun it any time: ${COLORS.cyan("elnora-linear sync all")}`);
118
+ log("");
119
+ }
120
+
121
+ function printSuccessNotice() {
122
+ log("");
123
+ log(COLORS.green("✓ elnora-linear: reference files populated from your Linear workspace."));
124
+ log(COLORS.dim(" (teams, projects, users, workflows — refresh any time with `elnora-linear sync all`.)"));
125
+ log("");
126
+ }
127
+
128
+ function runSync(apiKey, cliEntry = CLI_ENTRY, timeoutMs = SYNC_TIMEOUT_MS) {
129
+ return new Promise((resolve) => {
130
+ if (!existsSync(cliEntry)) {
131
+ resolve({ ok: false, reason: `CLI entry not found at ${cliEntry}` });
132
+ return;
133
+ }
134
+ const child = spawn(process.execPath, [cliEntry, "sync", "all", "--output", "json"], {
135
+ env: { ...process.env, LINEAR_API_KEY: apiKey },
136
+ stdio: ["ignore", "pipe", "pipe"],
137
+ });
138
+ let stderr = "";
139
+ child.stderr.on("data", (chunk) => {
140
+ stderr += chunk.toString();
141
+ });
142
+ // Drain stdout so the child doesn't block on a full pipe buffer.
143
+ child.stdout.on("data", () => {});
144
+
145
+ const timer = setTimeout(() => {
146
+ child.kill("SIGTERM");
147
+ resolve({ ok: false, reason: `sync timed out after ${timeoutMs / 1000}s` });
148
+ }, timeoutMs);
149
+
150
+ child.on("error", (err) => {
151
+ clearTimeout(timer);
152
+ resolve({ ok: false, reason: err.message });
153
+ });
154
+ child.on("exit", (code) => {
155
+ clearTimeout(timer);
156
+ if (code === 0) {
157
+ resolve({ ok: true });
158
+ } else {
159
+ const tail = stderr.trim().split("\n").slice(-3).join(" | ") || `exit ${code}`;
160
+ resolve({ ok: false, reason: tail });
161
+ }
162
+ });
163
+ });
164
+ }
165
+
166
+ async function main() {
167
+ if (shouldSkip()) {
168
+ // Silent on skip — postinstall noise during CI/local installs is annoying.
169
+ return;
170
+ }
171
+
172
+ const key = findApiKey();
173
+ if (!key) {
174
+ printNoKeyNotice();
175
+ return;
176
+ }
177
+
178
+ const result = await runSync(key.value);
179
+ if (result.ok) {
180
+ printSuccessNotice();
181
+ } else {
182
+ printFailureNotice(result.reason);
183
+ }
184
+ }
185
+
186
+ // Only run when invoked directly (not when imported by tests).
187
+ const invokedDirectly = process.argv[1] && fileURLToPath(import.meta.url) === process.argv[1];
188
+ if (invokedDirectly) {
189
+ main().catch((err) => {
190
+ // Truly defensive: any uncaught error must not fail the install.
191
+ printFailureNotice(err?.message ?? String(err));
192
+ });
193
+ }
194
+
195
+ export const _internal = { runSync, ENV_FILE, CLI_ENTRY };