panopticon-cli 0.5.3 → 0.5.6

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 (122) hide show
  1. package/dist/{agents-DMPT32H7.js → agents-5HWTDR4S.js} +12 -9
  2. package/dist/archive-planning-U3AZAKWI.js +16 -0
  3. package/dist/{chunk-KBHRXV5T.js → chunk-43F4LDZ4.js} +3 -3
  4. package/dist/chunk-6OYUJ4AJ.js +146 -0
  5. package/dist/chunk-6OYUJ4AJ.js.map +1 -0
  6. package/dist/{chunk-MOPGR3CL.js → chunk-AAP4G6U7.js} +1 -1
  7. package/dist/chunk-AAP4G6U7.js.map +1 -0
  8. package/dist/{chunk-4HST45MO.js → chunk-BYWVPPAZ.js} +19 -12
  9. package/dist/chunk-BYWVPPAZ.js.map +1 -0
  10. package/dist/{chunk-CFCUOV3Q.js → chunk-DMRTN432.js} +4 -1
  11. package/dist/chunk-DMRTN432.js.map +1 -0
  12. package/dist/{chunk-HOGYHJ2G.js → chunk-DW3PKGIS.js} +2 -2
  13. package/dist/{chunk-D67AQTHF.js → chunk-FUUP55PE.js} +108 -46
  14. package/dist/chunk-FUUP55PE.js.map +1 -0
  15. package/dist/chunk-GUV2EPBG.js +692 -0
  16. package/dist/chunk-GUV2EPBG.js.map +1 -0
  17. package/dist/{chunk-44EOY2ZL.js → chunk-HHL3AWXA.js} +46 -2
  18. package/dist/chunk-HHL3AWXA.js.map +1 -0
  19. package/dist/{chunk-6N2KBSJA.js → chunk-IZIXJYXZ.js} +40 -6
  20. package/dist/chunk-IZIXJYXZ.js.map +1 -0
  21. package/dist/chunk-MJXYTGK5.js +64 -0
  22. package/dist/chunk-MJXYTGK5.js.map +1 -0
  23. package/dist/chunk-OJF4QS3S.js +269 -0
  24. package/dist/chunk-OJF4QS3S.js.map +1 -0
  25. package/dist/{chunk-FQ66DECN.js → chunk-QAJAJBFW.js} +1 -1
  26. package/dist/chunk-QAJAJBFW.js.map +1 -0
  27. package/dist/chunk-R4KPLLRB.js +36 -0
  28. package/dist/chunk-R4KPLLRB.js.map +1 -0
  29. package/dist/{chunk-DFNVHK3N.js → chunk-SUM2WVPF.js} +4 -4
  30. package/dist/{chunk-T7BBPDEJ.js → chunk-UKSGE6RH.js} +45 -15
  31. package/dist/chunk-UKSGE6RH.js.map +1 -0
  32. package/dist/chunk-W2OTF6OS.js +201 -0
  33. package/dist/chunk-W2OTF6OS.js.map +1 -0
  34. package/dist/chunk-WEQW3EAT.js +78 -0
  35. package/dist/chunk-WEQW3EAT.js.map +1 -0
  36. package/dist/{chunk-2V2DQ3IX.js → chunk-WJJ3ZIQ6.js} +112 -45
  37. package/dist/chunk-WJJ3ZIQ6.js.map +1 -0
  38. package/dist/chunk-YAAT66RT.js +70 -0
  39. package/dist/chunk-YAAT66RT.js.map +1 -0
  40. package/dist/{chunk-RLZQB7HS.js → chunk-ZMJFEHGF.js} +13 -1
  41. package/dist/chunk-ZMJFEHGF.js.map +1 -0
  42. package/dist/{chunk-HRU7S4TA.js → chunk-ZN5RHWGR.js} +18 -208
  43. package/dist/{chunk-HRU7S4TA.js.map → chunk-ZN5RHWGR.js.map} +1 -1
  44. package/dist/{chunk-ZTYHZMEC.js → chunk-ZWZNEA26.js} +2 -2
  45. package/dist/clean-planning-7Z5YY64X.js +9 -0
  46. package/dist/cli/index.js +1314 -2146
  47. package/dist/cli/index.js.map +1 -1
  48. package/dist/close-issue-CTZK777I.js +9 -0
  49. package/dist/compact-beads-72SHALOL.js +9 -0
  50. package/dist/{config-4CJNUE3O.js → config-FFTMBVHM.js} +2 -2
  51. package/dist/dashboard/public/assets/{index-BJKEp64j.css → index-Bx4NCn9A.css} +1 -1
  52. package/dist/dashboard/public/assets/index-Db9NOz4z.js +756 -0
  53. package/dist/dashboard/public/index.html +3 -2
  54. package/dist/dashboard/server.js +34785 -34330
  55. package/dist/{feedback-writer-T43PI5S2.js → feedback-writer-T2WCT6EZ.js} +2 -2
  56. package/dist/{hume-CKJJ3OUU.js → hume-GVTB5BKW.js} +3 -3
  57. package/dist/index.d.ts +24 -16
  58. package/dist/index.js +4 -4
  59. package/dist/label-cleanup-4HJVX6NP.js +103 -0
  60. package/dist/label-cleanup-4HJVX6NP.js.map +1 -0
  61. package/dist/merge-agent-WM7ZKUET.js +1725 -0
  62. package/dist/merge-agent-WM7ZKUET.js.map +1 -0
  63. package/dist/{projects-KVM3MN3Y.js → projects-3CRF57ZU.js} +2 -2
  64. package/dist/{rally-RKFSWC7E.js → rally-LBY24P4C.js} +2 -2
  65. package/dist/{remote-agents-ULPD6C5U.js → remote-agents-3NZPSHYG.js} +2 -3
  66. package/dist/{remote-workspace-XX6ARE6I.js → remote-workspace-M4IULGFZ.js} +24 -49
  67. package/dist/remote-workspace-M4IULGFZ.js.map +1 -0
  68. package/dist/{review-status-XKUKZF6J.js → review-status-J2YJGL3E.js} +2 -2
  69. package/dist/{specialist-context-53AWO6AE.js → specialist-context-74RQF5SR.js} +7 -5
  70. package/dist/{specialist-context-53AWO6AE.js.map → specialist-context-74RQF5SR.js.map} +1 -1
  71. package/dist/{specialist-logs-QREUJ4HN.js → specialist-logs-T5GW7CSU.js} +6 -4
  72. package/dist/{specialists-2DBBXRCK.js → specialists-HTYYFXHQ.js} +6 -4
  73. package/dist/specialists-HTYYFXHQ.js.map +1 -0
  74. package/dist/tmux-X2I5SAIJ.js +31 -0
  75. package/dist/tmux-X2I5SAIJ.js.map +1 -0
  76. package/dist/{traefik-5GL3Q7DJ.js → traefik-QXLZ4PO2.js} +4 -4
  77. package/dist/traefik-QXLZ4PO2.js.map +1 -0
  78. package/dist/{tunnel-BKC7KLBX.js → tunnel-7IOSRZVH.js} +3 -3
  79. package/dist/tunnel-7IOSRZVH.js.map +1 -0
  80. package/dist/{workspace-manager-ALBR62AS.js → workspace-manager-G6TTBPC3.js} +6 -6
  81. package/dist/workspace-manager-G6TTBPC3.js.map +1 -0
  82. package/package.json +2 -2
  83. package/scripts/build-cost-script.mjs +17 -0
  84. package/scripts/heartbeat-hook +28 -8
  85. package/scripts/record-cost-event.js +46 -7
  86. package/scripts/record-cost-event.ts +2 -1
  87. package/scripts/recover-costs-deep.mjs +209 -0
  88. package/scripts/recover-costs-proportional.mjs +206 -0
  89. package/scripts/recover-costs.mjs +169 -0
  90. package/dist/chunk-2V2DQ3IX.js.map +0 -1
  91. package/dist/chunk-44EOY2ZL.js.map +0 -1
  92. package/dist/chunk-4HST45MO.js.map +0 -1
  93. package/dist/chunk-565HZ6VV.js +0 -159
  94. package/dist/chunk-565HZ6VV.js.map +0 -1
  95. package/dist/chunk-6N2KBSJA.js.map +0 -1
  96. package/dist/chunk-CFCUOV3Q.js.map +0 -1
  97. package/dist/chunk-D67AQTHF.js.map +0 -1
  98. package/dist/chunk-FQ66DECN.js.map +0 -1
  99. package/dist/chunk-MOPGR3CL.js.map +0 -1
  100. package/dist/chunk-RLZQB7HS.js.map +0 -1
  101. package/dist/chunk-T7BBPDEJ.js.map +0 -1
  102. package/dist/chunk-ZDNQFWR5.js +0 -650
  103. package/dist/chunk-ZDNQFWR5.js.map +0 -1
  104. package/dist/dashboard/public/assets/index-CgJjqjAV.js +0 -767
  105. package/dist/remote-workspace-XX6ARE6I.js.map +0 -1
  106. /package/dist/{agents-DMPT32H7.js.map → agents-5HWTDR4S.js.map} +0 -0
  107. /package/dist/{config-4CJNUE3O.js.map → archive-planning-U3AZAKWI.js.map} +0 -0
  108. /package/dist/{chunk-KBHRXV5T.js.map → chunk-43F4LDZ4.js.map} +0 -0
  109. /package/dist/{chunk-HOGYHJ2G.js.map → chunk-DW3PKGIS.js.map} +0 -0
  110. /package/dist/{chunk-DFNVHK3N.js.map → chunk-SUM2WVPF.js.map} +0 -0
  111. /package/dist/{chunk-ZTYHZMEC.js.map → chunk-ZWZNEA26.js.map} +0 -0
  112. /package/dist/{hume-CKJJ3OUU.js.map → clean-planning-7Z5YY64X.js.map} +0 -0
  113. /package/dist/{projects-KVM3MN3Y.js.map → close-issue-CTZK777I.js.map} +0 -0
  114. /package/dist/{rally-RKFSWC7E.js.map → compact-beads-72SHALOL.js.map} +0 -0
  115. /package/dist/{remote-agents-ULPD6C5U.js.map → config-FFTMBVHM.js.map} +0 -0
  116. /package/dist/{feedback-writer-T43PI5S2.js.map → feedback-writer-T2WCT6EZ.js.map} +0 -0
  117. /package/dist/{review-status-XKUKZF6J.js.map → hume-GVTB5BKW.js.map} +0 -0
  118. /package/dist/{specialist-logs-QREUJ4HN.js.map → projects-3CRF57ZU.js.map} +0 -0
  119. /package/dist/{specialists-2DBBXRCK.js.map → rally-LBY24P4C.js.map} +0 -0
  120. /package/dist/{traefik-5GL3Q7DJ.js.map → remote-agents-3NZPSHYG.js.map} +0 -0
  121. /package/dist/{tunnel-BKC7KLBX.js.map → review-status-J2YJGL3E.js.map} +0 -0
  122. /package/dist/{workspace-manager-ALBR62AS.js.map → specialist-logs-T5GW7CSU.js.map} +0 -0
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  init_projects,
3
3
  resolveProjectFromIssue
4
- } from "./chunk-RLZQB7HS.js";
4
+ } from "./chunk-ZMJFEHGF.js";
5
5
  import "./chunk-ZTFNYOC7.js";
6
6
  import {
7
7
  __esm,
@@ -112,4 +112,4 @@ init_feedback_writer();
112
112
  export {
113
113
  writeFeedbackFile
114
114
  };
115
- //# sourceMappingURL=feedback-writer-T43PI5S2.js.map
115
+ //# sourceMappingURL=feedback-writer-T2WCT6EZ.js.map
@@ -2,12 +2,12 @@ import {
2
2
  createHumeConfig,
3
3
  deleteHumeConfig,
4
4
  init_hume
5
- } from "./chunk-HOGYHJ2G.js";
6
- import "./chunk-MOPGR3CL.js";
5
+ } from "./chunk-DW3PKGIS.js";
6
+ import "./chunk-AAP4G6U7.js";
7
7
  import "./chunk-ZHC57RCV.js";
8
8
  init_hume();
9
9
  export {
10
10
  createHumeConfig,
11
11
  deleteHumeConfig
12
12
  };
13
- //# sourceMappingURL=hume-CKJJ3OUU.js.map
13
+ //# sourceMappingURL=hume-GVTB5BKW.js.map
package/dist/index.d.ts CHANGED
@@ -67,7 +67,7 @@ declare const INIT_DIRS: string[];
67
67
  * (Linear, GitHub Issues, GitLab Issues, etc.)
68
68
  */
69
69
  type TrackerType = 'linear' | 'github' | 'gitlab' | 'rally';
70
- type IssueState = 'open' | 'in_progress' | 'closed';
70
+ type IssueState = 'open' | 'in_progress' | 'in_review' | 'closed';
71
71
  interface Issue {
72
72
  /** Tracker-specific unique ID */
73
73
  id: string;
@@ -238,29 +238,37 @@ interface TrackersConfig {
238
238
  gitlab?: GitLabConfig;
239
239
  rally?: RallyConfig;
240
240
  }
241
- interface RemoteExeConfig {
242
- /** Shared infrastructure VM for postgres/redis/traefik */
243
- infra_vm?: string;
244
- /** Postgres settings on infra VM */
245
- postgres_host?: string;
246
- postgres_port?: number;
247
- postgres_user?: string;
248
- postgres_password_env?: string;
249
- /** Redis settings on infra VM */
250
- redis_host?: string;
251
- redis_port?: number;
241
+ interface RemoteFlyConfig {
242
+ /** Fly.io app name for workspace machines */
243
+ app?: string;
244
+ /** Fly.io org slug */
245
+ org?: string;
246
+ /** Default region (e.g. 'iad') */
247
+ region?: string;
248
+ /** Machine size (e.g. 'shared-cpu-2x') */
249
+ vm_size?: string;
250
+ /** Memory in MB */
251
+ vm_memory?: number;
252
+ /** Docker image for workspace machines */
253
+ image?: string;
254
+ /** Stop machine when agent is idle */
255
+ auto_stop?: boolean;
256
+ /** Seconds of inactivity before stop */
257
+ auto_stop_timeout?: number;
258
+ /** Env var name for API token (default: FLY_API_TOKEN) */
259
+ api_token_env?: string;
252
260
  }
253
261
  interface RemoteConfig {
254
262
  /** Enable remote workspace support */
255
263
  enabled: boolean;
256
264
  /** Remote provider type */
257
- provider?: 'exe';
265
+ provider?: 'fly';
258
266
  /** Default location for new workspaces */
259
267
  default_location?: 'local' | 'remote';
260
268
  /** Auto-hibernate idle workspaces after N minutes (0 = disabled) */
261
269
  auto_hibernate_minutes?: number;
262
- /** exe.dev specific configuration */
263
- exe?: RemoteExeConfig;
270
+ /** Fly.io specific configuration */
271
+ fly?: RemoteFlyConfig;
264
272
  }
265
273
  interface ShadowConfig {
266
274
  enabled: boolean;
@@ -841,4 +849,4 @@ declare function setupCredentialFileAuth(provider: ProviderConfig, workspacePath
841
849
  */
842
850
  declare function clearCredentialFileAuth(workspacePath: string): void;
843
851
 
844
- export { AGENTS_DIR, ARCHIVES_DIR, type AnthropicModel, type ApiKeysConfig, BACKUPS_DIR, BIN_DIR, type BackupInfo, CACHE_AGENTS_DIR, CACHE_MANIFEST, CACHE_RULES_DIR, CACHE_SKILLS_DIR, CERTS_DIR, CLAUDE_DIR, CLAUDE_MD_TEMPLATES, COMMANDS_DIR, CONFIG_DIR, CONFIG_FILE, COSTS_DIR, type Comment, type ComplexityLevel, type ComplexityModels, DOCS_DIR, type DevrootSyncItem, type GitHubConfig, GitHubTracker, type GitLabConfig, GitLabTracker, type GoogleModel, HEARTBEATS_DIR, type HookItem, INIT_DIRS, type Issue, type IssueFilters, IssueNotFoundError, type IssueState, type IssueTracker, type IssueUpdate, type KimiModel, LEGACY_RUNTIME_DIRS, type LinearConfig, LinearTracker, type LinkDirection, LinkManager, type MigrationResult, type ModelId, type ModelsConfig, type NewIssue, NotImplementedError, type OpenAIModel, PANOPTICON_HOME, PRDS_DIR, PRD_DRAFTS_DIR, PRD_PUBLISHED_DIR, PROJECT_DOCS_SUBDIR, PROJECT_PRDS_ACTIVE_SUBDIR, PROJECT_PRDS_COMPLETED_SUBDIR, PROJECT_PRDS_PLANNED_SUBDIR, PROJECT_PRDS_SUBDIR, PROVIDERS, type PanopticonConfig, type ProviderAuthType, type ProviderCompatibility, type ProviderConfig, type ProviderName, type RallyConfig, type RefreshCacheResult, type RemoteConfig, type RemoteExeConfig, SETTINGS_FILE, SKILLS_DIR, SOURCE_AGENTS_DIR, SOURCE_DEV_SKILLS_DIR, SOURCE_RULES_DIR, SOURCE_SCRIPTS_DIR, SOURCE_SKILLS_DIR, SOURCE_TEMPLATES_DIR, SOURCE_TRAEFIK_TEMPLATES, SYNC_TARGET, type SettingsConfig, type ShadowConfig, type Shell, type SpecialistModels, type SyncItem, type SyncOptions, type SyncPlan, type SyncResult, TEMPLATES_DIR, TRAEFIK_CERTS_DIR, TRAEFIK_DIR, TRAEFIK_DYNAMIC_DIR, TrackerAuthError, type TrackerConfig, type TrackerConfigItem, type TrackerLink, type TrackerType, type TrackersConfig, type ZAIModel, addAlias, cleanOldBackups, clearCredentialFileAuth, createBackup, createBackupTimestamp, createTracker, createTrackerFromConfig, detectShell, executeSync, findDevrootForProject, formatIssueRef, getAgentCommand, getAliasInstructions, getAllTrackers, getAvailableModels, getClaudeModelFlag, getDashboardApiUrl, getDefaultConfig, getDefaultSettings, getDevrootPath, getDirectProviders, getLinkManager, getPanopticonHome, getPrimaryTracker, getProviderEnv, getProviderForModel, getRouterProviders, getSecondaryTracker, getShellRcFile, hasAlias, isAnthropicModel, isDevMode, isPanopticonSymlink, listBackups, loadConfig, loadSettings, migrateFromPersonalSymlinks, needsRouter, parseIssueRef, planHooksSync, planSync, refreshCache, requiresRouter, restoreBackup, saveConfig, saveSettings, setupCredentialFileAuth, syncHooks, syncStatusline, validateSettings };
852
+ export { AGENTS_DIR, ARCHIVES_DIR, type AnthropicModel, type ApiKeysConfig, BACKUPS_DIR, BIN_DIR, type BackupInfo, CACHE_AGENTS_DIR, CACHE_MANIFEST, CACHE_RULES_DIR, CACHE_SKILLS_DIR, CERTS_DIR, CLAUDE_DIR, CLAUDE_MD_TEMPLATES, COMMANDS_DIR, CONFIG_DIR, CONFIG_FILE, COSTS_DIR, type Comment, type ComplexityLevel, type ComplexityModels, DOCS_DIR, type DevrootSyncItem, type GitHubConfig, GitHubTracker, type GitLabConfig, GitLabTracker, type GoogleModel, HEARTBEATS_DIR, type HookItem, INIT_DIRS, type Issue, type IssueFilters, IssueNotFoundError, type IssueState, type IssueTracker, type IssueUpdate, type KimiModel, LEGACY_RUNTIME_DIRS, type LinearConfig, LinearTracker, type LinkDirection, LinkManager, type MigrationResult, type ModelId, type ModelsConfig, type NewIssue, NotImplementedError, type OpenAIModel, PANOPTICON_HOME, PRDS_DIR, PRD_DRAFTS_DIR, PRD_PUBLISHED_DIR, PROJECT_DOCS_SUBDIR, PROJECT_PRDS_ACTIVE_SUBDIR, PROJECT_PRDS_COMPLETED_SUBDIR, PROJECT_PRDS_PLANNED_SUBDIR, PROJECT_PRDS_SUBDIR, PROVIDERS, type PanopticonConfig, type ProviderAuthType, type ProviderCompatibility, type ProviderConfig, type ProviderName, type RallyConfig, type RefreshCacheResult, type RemoteConfig, type RemoteFlyConfig, SETTINGS_FILE, SKILLS_DIR, SOURCE_AGENTS_DIR, SOURCE_DEV_SKILLS_DIR, SOURCE_RULES_DIR, SOURCE_SCRIPTS_DIR, SOURCE_SKILLS_DIR, SOURCE_TEMPLATES_DIR, SOURCE_TRAEFIK_TEMPLATES, SYNC_TARGET, type SettingsConfig, type ShadowConfig, type Shell, type SpecialistModels, type SyncItem, type SyncOptions, type SyncPlan, type SyncResult, TEMPLATES_DIR, TRAEFIK_CERTS_DIR, TRAEFIK_DIR, TRAEFIK_DYNAMIC_DIR, TrackerAuthError, type TrackerConfig, type TrackerConfigItem, type TrackerLink, type TrackerType, type TrackersConfig, type ZAIModel, addAlias, cleanOldBackups, clearCredentialFileAuth, createBackup, createBackupTimestamp, createTracker, createTrackerFromConfig, detectShell, executeSync, findDevrootForProject, formatIssueRef, getAgentCommand, getAliasInstructions, getAllTrackers, getAvailableModels, getClaudeModelFlag, getDashboardApiUrl, getDefaultConfig, getDefaultSettings, getDevrootPath, getDirectProviders, getLinkManager, getPanopticonHome, getPrimaryTracker, getProviderEnv, getProviderForModel, getRouterProviders, getSecondaryTracker, getShellRcFile, hasAlias, isAnthropicModel, isDevMode, isPanopticonSymlink, listBackups, loadConfig, loadSettings, migrateFromPersonalSymlinks, needsRouter, parseIssueRef, planHooksSync, planSync, refreshCache, requiresRouter, restoreBackup, saveConfig, saveSettings, setupCredentialFileAuth, syncHooks, syncStatusline, validateSettings };
package/dist/index.js CHANGED
@@ -21,7 +21,7 @@ import {
21
21
  restoreBackup,
22
22
  syncHooks,
23
23
  syncStatusline
24
- } from "./chunk-DFNVHK3N.js";
24
+ } from "./chunk-SUM2WVPF.js";
25
25
  import "./chunk-AQXETQHW.js";
26
26
  import {
27
27
  GitHubTracker,
@@ -32,7 +32,7 @@ import {
32
32
  getAllTrackers,
33
33
  getPrimaryTracker,
34
34
  getSecondaryTracker
35
- } from "./chunk-T7BBPDEJ.js";
35
+ } from "./chunk-UKSGE6RH.js";
36
36
  import {
37
37
  PROVIDERS,
38
38
  clearCredentialFileAuth,
@@ -62,13 +62,13 @@ import {
62
62
  init_config,
63
63
  loadConfig,
64
64
  saveConfig
65
- } from "./chunk-FQ66DECN.js";
65
+ } from "./chunk-QAJAJBFW.js";
66
66
  import "./chunk-ZP6EWSZV.js";
67
67
  import {
68
68
  IssueNotFoundError,
69
69
  NotImplementedError,
70
70
  TrackerAuthError
71
- } from "./chunk-CFCUOV3Q.js";
71
+ } from "./chunk-DMRTN432.js";
72
72
  import {
73
73
  AGENTS_DIR,
74
74
  ARCHIVES_DIR,
@@ -0,0 +1,103 @@
1
+ import {
2
+ getLinearApiKey,
3
+ stepFailed,
4
+ stepOk,
5
+ stepSkipped
6
+ } from "./chunk-R4KPLLRB.js";
7
+ import {
8
+ init_esm_shims
9
+ } from "./chunk-ZHC57RCV.js";
10
+
11
+ // src/lib/lifecycle/label-cleanup.ts
12
+ init_esm_shims();
13
+ import { exec } from "child_process";
14
+ import { promisify } from "util";
15
+ var execAsync = promisify(exec);
16
+ var MERGED_LABEL = "merged";
17
+ var MERGED_COLOR = "0e8a16";
18
+ var LABELS_TO_REMOVE = ["in-review", "in-progress", "merge-agent"];
19
+ async function cleanupMergedLabels(ctx) {
20
+ const step = "label-cleanup:merged";
21
+ if (ctx.github) {
22
+ return cleanupLabelsGitHub(ctx);
23
+ }
24
+ const linearApiKey = getLinearApiKey();
25
+ if (linearApiKey) {
26
+ return cleanupLabelsLinear(ctx, linearApiKey);
27
+ }
28
+ return stepSkipped(step, ["No tracker available for label cleanup"]);
29
+ }
30
+ async function cleanupLabelsGitHub(ctx) {
31
+ const step = "label-cleanup:merged";
32
+ if (!ctx.github) return stepSkipped(step);
33
+ const { owner, repo, number } = ctx.github;
34
+ try {
35
+ await execAsync(
36
+ `gh label create "${MERGED_LABEL}" --repo ${owner}/${repo} --color "${MERGED_COLOR}" --description "Merged to main" --force 2>/dev/null || true`,
37
+ { encoding: "utf-8" }
38
+ );
39
+ await execAsync(
40
+ `gh issue edit ${number} --repo ${owner}/${repo} --add-label "${MERGED_LABEL}"`,
41
+ { encoding: "utf-8" }
42
+ );
43
+ for (const label of LABELS_TO_REMOVE) {
44
+ await execAsync(
45
+ `gh issue edit ${number} --repo ${owner}/${repo} --remove-label "${label}" 2>/dev/null || true`,
46
+ { encoding: "utf-8" }
47
+ );
48
+ }
49
+ return stepOk(step, [
50
+ `Applied '${MERGED_LABEL}' label on GitHub #${number}`,
51
+ `Removed: ${LABELS_TO_REMOVE.join(", ")}`
52
+ ]);
53
+ } catch (err) {
54
+ return stepFailed(step, `Label cleanup failed: ${err.message}`);
55
+ }
56
+ }
57
+ async function cleanupLabelsLinear(ctx, apiKey) {
58
+ const step = "label-cleanup:merged";
59
+ try {
60
+ const { LinearClient } = await import("@linear/sdk");
61
+ const client = new LinearClient({ apiKey });
62
+ const issueNum = parseInt(ctx.issueId.split("-").pop() || "0", 10);
63
+ const teamKey = ctx.issueId.split("-")[0].toUpperCase();
64
+ const results = await client.issues({
65
+ filter: {
66
+ number: { eq: issueNum },
67
+ team: { key: { eq: teamKey } }
68
+ },
69
+ first: 1
70
+ });
71
+ if (results.nodes.length === 0) {
72
+ return stepSkipped(step, ["Issue not found for label cleanup"]);
73
+ }
74
+ const issue = results.nodes[0];
75
+ const labelSearch = await client.issueLabels({ filter: { name: { eq: MERGED_LABEL } } });
76
+ let mergedLabelId;
77
+ if (labelSearch.nodes.length > 0) {
78
+ mergedLabelId = labelSearch.nodes[0].id;
79
+ } else {
80
+ const created = await client.createIssueLabel({ name: MERGED_LABEL, color: `#${MERGED_COLOR}` });
81
+ const createdLabel = await created.issueLabel;
82
+ mergedLabelId = createdLabel ? createdLabel.id : "";
83
+ }
84
+ if (mergedLabelId) {
85
+ const existingLabels = await issue.labels();
86
+ const filteredIds = existingLabels.nodes.filter((l) => !LABELS_TO_REMOVE.includes(l.name)).map((l) => l.id);
87
+ if (!filteredIds.includes(mergedLabelId)) {
88
+ filteredIds.push(mergedLabelId);
89
+ }
90
+ await issue.update({ labelIds: filteredIds });
91
+ }
92
+ return stepOk(step, [
93
+ `Applied '${MERGED_LABEL}' label on Linear ${ctx.issueId}`,
94
+ `Removed: ${LABELS_TO_REMOVE.join(", ")}`
95
+ ]);
96
+ } catch (err) {
97
+ return stepFailed(step, `Linear label cleanup failed: ${err.message}`);
98
+ }
99
+ }
100
+ export {
101
+ cleanupMergedLabels
102
+ };
103
+ //# sourceMappingURL=label-cleanup-4HJVX6NP.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/lifecycle/label-cleanup.ts"],"sourcesContent":["/**\n * label-cleanup — Remove workflow labels and apply 'merged' label after merge.\n *\n * Runs as part of postMergeLifecycle (step 3b), independently of close-issue.\n * Labels are cleaned even if the issue close step fails.\n *\n * Removes: in-review, in-progress, merge-agent\n * Adds: merged\n */\n\nimport { exec } from 'child_process';\nimport { promisify } from 'util';\nimport type { LifecycleContext, StepResult } from './types.js';\nimport { stepOk, stepSkipped, stepFailed, getLinearApiKey } from './types.js';\n\nconst execAsync = promisify(exec);\n\nconst MERGED_LABEL = 'merged';\nconst MERGED_COLOR = '0e8a16'; // green\nconst LABELS_TO_REMOVE = ['in-review', 'in-progress', 'merge-agent'];\n\n/**\n * Remove workflow labels and apply 'merged' label.\n * Non-fatal: label management failure does not block the merge lifecycle.\n */\nexport async function cleanupMergedLabels(ctx: LifecycleContext): Promise<StepResult> {\n const step = 'label-cleanup:merged';\n\n if (ctx.github) {\n return cleanupLabelsGitHub(ctx);\n }\n\n const linearApiKey = getLinearApiKey();\n if (linearApiKey) {\n return cleanupLabelsLinear(ctx, linearApiKey);\n }\n\n return stepSkipped(step, ['No tracker available for label cleanup']);\n}\n\nasync function cleanupLabelsGitHub(ctx: LifecycleContext): Promise<StepResult> {\n const step = 'label-cleanup:merged';\n if (!ctx.github) return stepSkipped(step);\n const { owner, repo, number } = ctx.github;\n\n try {\n // Ensure merged label exists\n await execAsync(\n `gh label create \"${MERGED_LABEL}\" --repo ${owner}/${repo} --color \"${MERGED_COLOR}\" --description \"Merged to main\" --force 2>/dev/null || true`,\n { encoding: 'utf-8' },\n );\n\n // Add merged label\n await execAsync(\n `gh issue edit ${number} --repo ${owner}/${repo} --add-label \"${MERGED_LABEL}\"`,\n { encoding: 'utf-8' },\n );\n\n // Remove workflow labels (best-effort — skip if not present)\n for (const label of LABELS_TO_REMOVE) {\n await execAsync(\n `gh issue edit ${number} --repo ${owner}/${repo} --remove-label \"${label}\" 2>/dev/null || true`,\n { encoding: 'utf-8' },\n );\n }\n\n return stepOk(step, [\n `Applied '${MERGED_LABEL}' label on GitHub #${number}`,\n `Removed: ${LABELS_TO_REMOVE.join(', ')}`,\n ]);\n } catch (err) {\n return stepFailed(step, `Label cleanup failed: ${(err as Error).message}`);\n }\n}\n\nasync function cleanupLabelsLinear(ctx: LifecycleContext, apiKey: string): Promise<StepResult> {\n const step = 'label-cleanup:merged';\n try {\n const { LinearClient } = await import('@linear/sdk');\n const client = new LinearClient({ apiKey });\n\n const issueNum = parseInt(ctx.issueId.split('-').pop() || '0', 10);\n const teamKey = ctx.issueId.split('-')[0].toUpperCase();\n const results = await client.issues({\n filter: {\n number: { eq: issueNum },\n team: { key: { eq: teamKey } },\n },\n first: 1,\n });\n\n if (results.nodes.length === 0) {\n return stepSkipped(step, ['Issue not found for label cleanup']);\n }\n\n const issue = results.nodes[0];\n\n // Find or create merged label\n const labelSearch = await client.issueLabels({ filter: { name: { eq: MERGED_LABEL } } });\n let mergedLabelId: string;\n if (labelSearch.nodes.length > 0) {\n mergedLabelId = labelSearch.nodes[0].id;\n } else {\n const created = await client.createIssueLabel({ name: MERGED_LABEL, color: `#${MERGED_COLOR}` });\n const createdLabel = await created.issueLabel;\n mergedLabelId = createdLabel ? createdLabel.id : '';\n }\n\n if (mergedLabelId) {\n const existingLabels = await issue.labels();\n // Remove workflow labels, add merged\n const filteredIds = existingLabels.nodes\n .filter(l => !LABELS_TO_REMOVE.includes(l.name))\n .map(l => l.id);\n if (!filteredIds.includes(mergedLabelId)) {\n filteredIds.push(mergedLabelId);\n }\n await issue.update({ labelIds: filteredIds });\n }\n\n return stepOk(step, [\n `Applied '${MERGED_LABEL}' label on Linear ${ctx.issueId}`,\n `Removed: ${LABELS_TO_REMOVE.join(', ')}`,\n ]);\n } catch (err) {\n return stepFailed(step, `Linear label cleanup failed: ${(err as Error).message}`);\n }\n}\n"],"mappings":"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","names":[]}