@planckspace/cli 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (190) hide show
  1. package/README.md +24 -1
  2. package/dist/anomaly/constants.d.ts +13 -0
  3. package/dist/anomaly/constants.d.ts.map +1 -0
  4. package/dist/anomaly/constants.js +13 -0
  5. package/dist/anomaly/constants.js.map +1 -0
  6. package/dist/anomaly/detector.d.ts +12 -0
  7. package/dist/anomaly/detector.d.ts.map +1 -0
  8. package/dist/anomaly/detector.js +98 -0
  9. package/dist/anomaly/detector.js.map +1 -0
  10. package/dist/anomaly/types.d.ts +19 -0
  11. package/dist/anomaly/types.d.ts.map +1 -0
  12. package/dist/anomaly/types.js +2 -0
  13. package/dist/anomaly/types.js.map +1 -0
  14. package/dist/commands/budget.d.ts +26 -0
  15. package/dist/commands/budget.d.ts.map +1 -0
  16. package/dist/commands/budget.js +91 -0
  17. package/dist/commands/budget.js.map +1 -0
  18. package/dist/commands/config.d.ts +4 -0
  19. package/dist/commands/config.d.ts.map +1 -0
  20. package/dist/commands/config.js +45 -0
  21. package/dist/commands/config.js.map +1 -0
  22. package/dist/commands/connect.d.ts +17 -0
  23. package/dist/commands/connect.d.ts.map +1 -0
  24. package/dist/commands/connect.js +191 -0
  25. package/dist/commands/connect.js.map +1 -0
  26. package/dist/commands/daemon.d.ts +8 -0
  27. package/dist/commands/daemon.d.ts.map +1 -0
  28. package/dist/commands/daemon.js +310 -0
  29. package/dist/commands/daemon.js.map +1 -0
  30. package/dist/commands/diagnose.d.ts +2 -0
  31. package/dist/commands/diagnose.d.ts.map +1 -0
  32. package/dist/commands/diagnose.js +81 -0
  33. package/dist/commands/diagnose.js.map +1 -0
  34. package/dist/commands/doctor.d.ts +2 -0
  35. package/dist/commands/doctor.d.ts.map +1 -0
  36. package/dist/commands/doctor.js +67 -0
  37. package/dist/commands/doctor.js.map +1 -0
  38. package/dist/commands/export.d.ts +40 -0
  39. package/dist/commands/export.d.ts.map +1 -0
  40. package/dist/commands/export.js +184 -0
  41. package/dist/commands/export.js.map +1 -0
  42. package/dist/commands/init.d.ts +3 -1
  43. package/dist/commands/init.d.ts.map +1 -1
  44. package/dist/commands/init.js +14 -1
  45. package/dist/commands/init.js.map +1 -1
  46. package/dist/commands/insights.d.ts +2 -0
  47. package/dist/commands/insights.d.ts.map +1 -0
  48. package/dist/commands/insights.js +71 -0
  49. package/dist/commands/insights.js.map +1 -0
  50. package/dist/commands/inspect.d.ts +2 -0
  51. package/dist/commands/inspect.d.ts.map +1 -0
  52. package/dist/commands/inspect.js +81 -0
  53. package/dist/commands/inspect.js.map +1 -0
  54. package/dist/commands/integrations.d.ts +2 -0
  55. package/dist/commands/integrations.d.ts.map +1 -0
  56. package/dist/commands/integrations.js +46 -0
  57. package/dist/commands/integrations.js.map +1 -0
  58. package/dist/commands/login.d.ts +1 -1
  59. package/dist/commands/login.d.ts.map +1 -1
  60. package/dist/commands/login.js +45 -6
  61. package/dist/commands/login.js.map +1 -1
  62. package/dist/commands/metrics.d.ts +6 -0
  63. package/dist/commands/metrics.d.ts.map +1 -0
  64. package/dist/commands/metrics.js +85 -0
  65. package/dist/commands/metrics.js.map +1 -0
  66. package/dist/commands/reconcile.d.ts +2 -0
  67. package/dist/commands/reconcile.d.ts.map +1 -0
  68. package/dist/commands/reconcile.js +63 -0
  69. package/dist/commands/reconcile.js.map +1 -0
  70. package/dist/commands/scan.d.ts.map +1 -1
  71. package/dist/commands/scan.js +53 -10
  72. package/dist/commands/scan.js.map +1 -1
  73. package/dist/commands/status.d.ts +1 -1
  74. package/dist/commands/status.d.ts.map +1 -1
  75. package/dist/commands/status.js +84 -14
  76. package/dist/commands/status.js.map +1 -1
  77. package/dist/commands/subscription.d.ts +15 -0
  78. package/dist/commands/subscription.d.ts.map +1 -0
  79. package/dist/commands/subscription.js +62 -0
  80. package/dist/commands/subscription.js.map +1 -0
  81. package/dist/commands/sync.d.ts +1 -1
  82. package/dist/commands/sync.d.ts.map +1 -1
  83. package/dist/commands/sync.js +77 -10
  84. package/dist/commands/sync.js.map +1 -1
  85. package/dist/commands/value.d.ts +5 -0
  86. package/dist/commands/value.d.ts.map +1 -0
  87. package/dist/commands/value.js +95 -0
  88. package/dist/commands/value.js.map +1 -0
  89. package/dist/config.d.ts +28 -3
  90. package/dist/config.d.ts.map +1 -1
  91. package/dist/config.js +9 -1
  92. package/dist/config.js.map +1 -1
  93. package/dist/correlate.d.ts +7 -0
  94. package/dist/correlate.d.ts.map +1 -1
  95. package/dist/correlate.js +102 -15
  96. package/dist/correlate.js.map +1 -1
  97. package/dist/daemon/daemon.d.ts +2 -0
  98. package/dist/daemon/daemon.d.ts.map +1 -0
  99. package/dist/daemon/daemon.js +188 -0
  100. package/dist/daemon/daemon.js.map +1 -0
  101. package/dist/daemon/daemonState.d.ts +25 -0
  102. package/dist/daemon/daemonState.d.ts.map +1 -0
  103. package/dist/daemon/daemonState.js +82 -0
  104. package/dist/daemon/daemonState.js.map +1 -0
  105. package/dist/daemon/logger.d.ts +7 -0
  106. package/dist/daemon/logger.d.ts.map +1 -0
  107. package/dist/daemon/logger.js +61 -0
  108. package/dist/daemon/logger.js.map +1 -0
  109. package/dist/daemon/syncLoop.d.ts +38 -0
  110. package/dist/daemon/syncLoop.d.ts.map +1 -0
  111. package/dist/daemon/syncLoop.js +119 -0
  112. package/dist/daemon/syncLoop.js.map +1 -0
  113. package/dist/daemon/watcher.d.ts +26 -0
  114. package/dist/daemon/watcher.d.ts.map +1 -0
  115. package/dist/daemon/watcher.js +187 -0
  116. package/dist/daemon/watcher.js.map +1 -0
  117. package/dist/db/store.d.ts +123 -2
  118. package/dist/db/store.d.ts.map +1 -1
  119. package/dist/db/store.js +397 -11
  120. package/dist/db/store.js.map +1 -1
  121. package/dist/detectors/cache-gap.d.ts +3 -0
  122. package/dist/detectors/cache-gap.d.ts.map +1 -0
  123. package/dist/detectors/cache-gap.js +70 -0
  124. package/dist/detectors/cache-gap.js.map +1 -0
  125. package/dist/detectors/context-bloat.d.ts +3 -0
  126. package/dist/detectors/context-bloat.d.ts.map +1 -0
  127. package/dist/detectors/context-bloat.js +68 -0
  128. package/dist/detectors/context-bloat.js.map +1 -0
  129. package/dist/detectors/fileTokens.d.ts +3 -0
  130. package/dist/detectors/fileTokens.d.ts.map +1 -0
  131. package/dist/detectors/fileTokens.js +12 -0
  132. package/dist/detectors/fileTokens.js.map +1 -0
  133. package/dist/detectors/index.d.ts +20 -0
  134. package/dist/detectors/index.d.ts.map +1 -0
  135. package/dist/detectors/index.js +41 -0
  136. package/dist/detectors/index.js.map +1 -0
  137. package/dist/detectors/model-routing.d.ts +3 -0
  138. package/dist/detectors/model-routing.d.ts.map +1 -0
  139. package/dist/detectors/model-routing.js +71 -0
  140. package/dist/detectors/model-routing.js.map +1 -0
  141. package/dist/detectors/repeat-read.d.ts +3 -0
  142. package/dist/detectors/repeat-read.d.ts.map +1 -0
  143. package/dist/detectors/repeat-read.js +69 -0
  144. package/dist/detectors/repeat-read.js.map +1 -0
  145. package/dist/detectors/seat-efficiency.d.ts +4 -0
  146. package/dist/detectors/seat-efficiency.d.ts.map +1 -0
  147. package/dist/detectors/seat-efficiency.js +86 -0
  148. package/dist/detectors/seat-efficiency.js.map +1 -0
  149. package/dist/detectors/types.d.ts +46 -0
  150. package/dist/detectors/types.d.ts.map +1 -0
  151. package/dist/detectors/types.js +2 -0
  152. package/dist/detectors/types.js.map +1 -0
  153. package/dist/health.d.ts +59 -0
  154. package/dist/health.d.ts.map +1 -0
  155. package/dist/health.js +106 -0
  156. package/dist/health.js.map +1 -0
  157. package/dist/index.js +389 -5
  158. package/dist/index.js.map +1 -1
  159. package/dist/metrics.d.ts +29 -0
  160. package/dist/metrics.d.ts.map +1 -0
  161. package/dist/metrics.js +205 -0
  162. package/dist/metrics.js.map +1 -0
  163. package/dist/scrapers/claudeCode.d.ts +1 -0
  164. package/dist/scrapers/claudeCode.d.ts.map +1 -1
  165. package/dist/scrapers/claudeCode.js +43 -13
  166. package/dist/scrapers/claudeCode.js.map +1 -1
  167. package/dist/scrapers/cursor.d.ts +3 -2
  168. package/dist/scrapers/cursor.d.ts.map +1 -1
  169. package/dist/scrapers/cursor.js +56 -16
  170. package/dist/scrapers/cursor.js.map +1 -1
  171. package/dist/scrapers/jetbrains.d.ts +15 -0
  172. package/dist/scrapers/jetbrains.d.ts.map +1 -0
  173. package/dist/scrapers/jetbrains.js +232 -0
  174. package/dist/scrapers/jetbrains.js.map +1 -0
  175. package/dist/scrapers/types.d.ts +4 -1
  176. package/dist/scrapers/types.d.ts.map +1 -1
  177. package/dist/scrapers/windsurf.d.ts +3 -2
  178. package/dist/scrapers/windsurf.d.ts.map +1 -1
  179. package/dist/scrapers/windsurf.js +25 -9
  180. package/dist/scrapers/windsurf.js.map +1 -1
  181. package/dist/sync/payload.d.ts +4 -5
  182. package/dist/sync/payload.d.ts.map +1 -1
  183. package/dist/sync/payload.js +88 -7
  184. package/dist/sync/payload.js.map +1 -1
  185. package/dist/sync/syncEngine.d.ts +19 -3
  186. package/dist/sync/syncEngine.d.ts.map +1 -1
  187. package/dist/sync/syncEngine.js +116 -10
  188. package/dist/sync/syncEngine.js.map +1 -1
  189. package/install.sh +27 -10
  190. package/package.json +43 -42
@@ -1,6 +1,7 @@
1
- import { initDb } from "../db/store.js";
1
+ import { initDb, getSessionCount } from "../db/store.js";
2
2
  import { readConfig, writeConfig, resolveApiUrl } from "../config.js";
3
3
  import { syncOnce } from "../sync/syncEngine.js";
4
+ import { preflightHealth, reconcileWithManifest, commitHealthState, } from "../health.js";
4
5
  /**
5
6
  * Resolve the connection details sync needs, or null if not connected.
6
7
  * Honors login's "workspace resolves on first sync" promise by hitting /api/me
@@ -37,15 +38,83 @@ async function resolveSyncDeps() {
37
38
  return {
38
39
  apiUrl,
39
40
  token: config.token,
40
- // Backend schema requires a non-empty workspaceId but always overrides it
41
- // with the token's workspace, so a placeholder is safe when unresolved.
42
41
  workspaceId: workspaceId ?? "unknown",
42
+ workspaceSubscriptions: config.subscriptions ?? [],
43
+ budgets: config.budgets ?? [],
43
44
  };
44
45
  }
45
- /** Run one sync pass and print the standard summary line. */
46
+ /** Format and print the sync result summary. */
47
+ function printSyncSummary(result, totalSessions) {
48
+ if (result.authWarnings.length > 0) {
49
+ console.warn(` auth failure on: ${result.authWarnings.join(", ")} — your token may be invalid, re-run \`planck login\``);
50
+ }
51
+ const syncedParts = [];
52
+ if (result.synced > 0) {
53
+ syncedParts.push(`${result.synced} session${result.synced !== 1 ? "s" : ""}`);
54
+ }
55
+ if (result.subscriptionCount > 0) {
56
+ syncedParts.push(`${result.subscriptionCount} subscription${result.subscriptionCount !== 1 ? "s" : ""}`);
57
+ }
58
+ if (result.failed > 0) {
59
+ const syncedStr = syncedParts.length > 0 ? syncedParts.join(", ") : "none";
60
+ console.log(`synced: ${syncedStr} | failed: ${result.failed} session${result.failed !== 1 ? "s" : ""}`);
61
+ }
62
+ else if (syncedParts.length > 0) {
63
+ console.log(`synced: ${syncedParts.join(", ")}`);
64
+ }
65
+ else {
66
+ // Nothing to sync and preflight passed — all local sessions are confirmed current.
67
+ console.log(`everything in sync (${totalSessions} local session${totalSessions !== 1 ? "s" : ""} all confirmed in backend manifest)`);
68
+ }
69
+ if (result.pending.length > 0) {
70
+ const pendingStr = result.pending
71
+ .map((p) => `${p} (endpoint not deployed)`)
72
+ .join(", ");
73
+ console.log(`pending: ${pendingStr}`);
74
+ }
75
+ }
76
+ /**
77
+ * Run one preflight → (reconcile if drift) → sync pass.
78
+ * Exits non-zero if the token is missing, invalid, or the backend is unreachable.
79
+ */
80
+ async function runOneSyncPass(deps) {
81
+ const apiUrl = resolveApiUrl();
82
+ const health = await preflightHealth();
83
+ if (!health.ok) {
84
+ if (health.reason === "db-reset" || health.reason === "workspace-changed") {
85
+ const label = health.reason === "db-reset" ? "backend database reset" : "workspace changed";
86
+ console.log(`Detected ${label} — reconciling local sync state...`);
87
+ const { reset } = await reconcileWithManifest();
88
+ if (reset > 0) {
89
+ console.log(` reconciled ${reset} session${reset !== 1 ? "s" : ""} (will be re-synced)`);
90
+ }
91
+ // Commit the new values now that drift is resolved.
92
+ if (health.reason === "db-reset") {
93
+ commitHealthState(health.current, health.workspaceId);
94
+ }
95
+ else {
96
+ commitHealthState(health.dbInstanceId, health.current);
97
+ }
98
+ // Fall through to sync — the reconciled sessions are now unsynced and ready.
99
+ }
100
+ else {
101
+ const msg = health.reason === "no-token"
102
+ ? "not connected — run `planck login <token>`"
103
+ : health.reason === "invalid-token"
104
+ ? "your token is no longer valid — get a new one from the dashboard and run `planck login <new-token>`"
105
+ : `couldn't reach backend at ${apiUrl} — is the server running?`;
106
+ console.error(msg);
107
+ process.exit(1);
108
+ }
109
+ }
110
+ const totalSessions = getSessionCount();
111
+ const result = await syncOnce(deps);
112
+ printSyncSummary(result, totalSessions);
113
+ }
114
+ /** Run one sync pass and print the standard summary (used by `scan --sync`). */
46
115
  export async function syncAndReport(deps) {
47
- const { synced, failed } = await syncOnce(deps);
48
- console.log(`synced ${synced}, failed ${failed}`);
116
+ const result = await syncOnce(deps);
117
+ printSyncSummary(result, getSessionCount());
49
118
  }
50
119
  /**
51
120
  * Build sync deps for callers that have already confirmed connection
@@ -64,14 +133,12 @@ export async function runSync(options = {}) {
64
133
  if (options.watch) {
65
134
  const intervalSec = options.interval && options.interval > 0 ? options.interval : 60;
66
135
  console.log(`Watching — syncing every ${intervalSec}s. Press Ctrl+C to stop.`);
67
- // Simple loop for MVP. Each pass re-reads unsynced rows, so newly scraped
68
- // sessions get picked up without restarting.
69
136
  // eslint-disable-next-line no-constant-condition
70
137
  while (true) {
71
- await syncAndReport(deps);
138
+ await runOneSyncPass(deps);
72
139
  await new Promise((resolve) => setTimeout(resolve, intervalSec * 1000));
73
140
  }
74
141
  }
75
- await syncAndReport(deps);
142
+ await runOneSyncPass(deps);
76
143
  }
77
144
  //# sourceMappingURL=sync.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/commands/sync.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/commands/sync.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AACtE,OAAO,EAAE,QAAQ,EAAkC,MAAM,uBAAuB,CAAC;AACjF,OAAO,EACL,eAAe,EACf,qBAAqB,EACrB,iBAAiB,GAClB,MAAM,cAAc,CAAC;AAUtB;;;;GAIG;AACH,KAAK,UAAU,eAAe;IAC5B,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,IAAI,CAAC,MAAM,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IAE/B,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;IAC/B,IAAI,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC;IAErC,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,MAAM,SAAS,EAAE;gBAC1C,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,MAAM,CAAC,KAAK,EAAE,EAAE;aACrD,CAAC,CAAC;YACH,IAAI,GAAG,CAAC,EAAE,EAAE,CAAC;gBACX,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAe,CAAC;gBAC9C,WAAW,GAAG,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC;gBACvC,IAAI,WAAW,EAAE,CAAC;oBAChB,WAAW,CAAC;wBACV,GAAG,MAAM;wBACT,WAAW;wBACX,aAAa,EAAE,IAAI,CAAC,aAAa,IAAI,MAAM,CAAC,aAAa;qBAC1D,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,uEAAuE;YACvE,qEAAqE;QACvE,CAAC;IACH,CAAC;IAED,OAAO;QACL,MAAM;QACN,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,WAAW,EAAE,WAAW,IAAI,SAAS;QACrC,sBAAsB,EAAE,MAAM,CAAC,aAAa,IAAI,EAAE;QAClD,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,EAAE;KAC9B,CAAC;AACJ,CAAC;AAED,gDAAgD;AAChD,SAAS,gBAAgB,CAAC,MAAkB,EAAE,aAAqB;IACjE,IAAI,MAAM,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACnC,OAAO,CAAC,IAAI,CACV,sBAAsB,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,uDAAuD,CAC5G,CAAC;IACJ,CAAC;IAED,MAAM,WAAW,GAAa,EAAE,CAAC;IACjC,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,WAAW,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,WAAW,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAChF,CAAC;IACD,IAAI,MAAM,CAAC,iBAAiB,GAAG,CAAC,EAAE,CAAC;QACjC,WAAW,CAAC,IAAI,CACd,GAAG,MAAM,CAAC,iBAAiB,gBAAgB,MAAM,CAAC,iBAAiB,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CACvF,CAAC;IACJ,CAAC;IAED,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,MAAM,SAAS,GAAG,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;QAC3E,OAAO,CAAC,GAAG,CACT,WAAW,SAAS,gBAAgB,MAAM,CAAC,MAAM,WAAW,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAC7F,CAAC;IACJ,CAAC;SAAM,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAClC,OAAO,CAAC,GAAG,CAAC,WAAW,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACnD,CAAC;SAAM,CAAC;QACN,mFAAmF;QACnF,OAAO,CAAC,GAAG,CACT,uBAAuB,aAAa,iBAAiB,aAAa,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,qCAAqC,CACzH,CAAC;IACJ,CAAC;IAED,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9B,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO;aAC9B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,0BAA0B,CAAC;aAC1C,IAAI,CAAC,IAAI,CAAC,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,YAAY,UAAU,EAAE,CAAC,CAAC;IACxC,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,KAAK,UAAU,cAAc,CAAC,IAAc;IAC1C,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;IAC/B,MAAM,MAAM,GAAG,MAAM,eAAe,EAAE,CAAC;IAEvC,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;QACf,IAAI,MAAM,CAAC,MAAM,KAAK,UAAU,IAAI,MAAM,CAAC,MAAM,KAAK,mBAAmB,EAAE,CAAC;YAC1E,MAAM,KAAK,GACT,MAAM,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC,CAAC,mBAAmB,CAAC;YAChF,OAAO,CAAC,GAAG,CAAC,YAAY,KAAK,oCAAoC,CAAC,CAAC;YACnE,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,qBAAqB,EAAE,CAAC;YAChD,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;gBACd,OAAO,CAAC,GAAG,CACT,gBAAgB,KAAK,WAAW,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,sBAAsB,CAC7E,CAAC;YACJ,CAAC;YACD,oDAAoD;YACpD,IAAI,MAAM,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;gBACjC,iBAAiB,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC;YACxD,CAAC;iBAAM,CAAC;gBACN,iBAAiB,CAAC,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;YACzD,CAAC;YACD,6EAA6E;QAC/E,CAAC;aAAM,CAAC;YACN,MAAM,GAAG,GACP,MAAM,CAAC,MAAM,KAAK,UAAU;gBAC1B,CAAC,CAAC,4CAA4C;gBAC9C,CAAC,CAAC,MAAM,CAAC,MAAM,KAAK,eAAe;oBACnC,CAAC,CAAC,qGAAqG;oBACvG,CAAC,CAAC,6BAA6B,MAAM,2BAA2B,CAAC;YACrE,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACnB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAED,MAAM,aAAa,GAAG,eAAe,EAAE,CAAC;IACxC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,CAAC;IACpC,gBAAgB,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;AAC1C,CAAC;AAED,gFAAgF;AAChF,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAc;IAChD,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,CAAC;IACpC,gBAAgB,CAAC,MAAM,EAAE,eAAe,EAAE,CAAC,CAAC;AAC9C,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,OAAO,eAAe,EAAE,CAAC;AAC3B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,UAAuB,EAAE;IACrD,MAAM,EAAE,CAAC;IAET,MAAM,IAAI,GAAG,MAAM,eAAe,EAAE,CAAC;IACrC,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,CAAC,KAAK,CAAC,kDAAkD,CAAC,CAAC;QAClE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;QAClB,MAAM,WAAW,GAAG,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;QACrF,OAAO,CAAC,GAAG,CACT,4BAA4B,WAAW,0BAA0B,CAClE,CAAC;QACF,iDAAiD;QACjD,OAAO,IAAI,EAAE,CAAC;YACZ,MAAM,cAAc,CAAC,IAAI,CAAC,CAAC;YAC3B,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC,CAAC,CAAC;QAC1E,CAAC;IACH,CAAC;IAED,MAAM,cAAc,CAAC,IAAI,CAAC,CAAC;AAC7B,CAAC"}
@@ -0,0 +1,5 @@
1
+ export type ValueOptions = {
2
+ tool?: string;
3
+ };
4
+ export declare function runValue(options?: ValueOptions): void;
5
+ //# sourceMappingURL=value.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"value.d.ts","sourceRoot":"","sources":["../../src/commands/value.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,YAAY,GAAG;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAsF7C,wBAAgB,QAAQ,CAAC,OAAO,GAAE,YAAiB,GAAG,IAAI,CA4BzD"}
@@ -0,0 +1,95 @@
1
+ import { initDb, getSessionsForValue } from "../db/store.js";
2
+ import { readConfig } from "../config.js";
3
+ const THIRTY_DAYS_MS = 30 * 24 * 60 * 60 * 1000;
4
+ function since30DaysIso() {
5
+ return new Date(Date.now() - THIRTY_DAYS_MS).toISOString();
6
+ }
7
+ /** Group sessions by gitAuthorEmail, sum consumptionValueUsd per user. */
8
+ function groupByUser(rows) {
9
+ const map = new Map();
10
+ for (const r of rows) {
11
+ const key = r.gitAuthorEmail ?? "(unattributed)";
12
+ map.set(key, (map.get(key) ?? 0) + r.costUsd);
13
+ }
14
+ return map;
15
+ }
16
+ function formatLeverage(leverage) {
17
+ const arrow = leverage >= 1 ? ">" : "<";
18
+ const verdict = leverage >= 1 ? "under-paying (good value)" : "over-paying (low utilisation)";
19
+ return `${leverage.toFixed(2)}x ${arrow}1 = ${verdict}`;
20
+ }
21
+ function printToolReport(tool, subscriptions, sinceIso) {
22
+ const subs = subscriptions.filter((s) => s.tool === tool);
23
+ if (subs.length === 0) {
24
+ console.log(`\n ${tool}: no subscription declared.`);
25
+ console.log(` → Declare one with: planck subscription add --tool ${tool} --plan <plan> --seats <n> --seat-cost <usd>`);
26
+ return;
27
+ }
28
+ const rows = getSessionsForValue(tool, sinceIso);
29
+ // consumptionValueUsd = costUsd (same number; label depends on costType)
30
+ const totalConsumption = rows.reduce((s, r) => s + r.costUsd, 0);
31
+ for (const sub of subs) {
32
+ const seatCostPaid = sub.seatCount * sub.seatCostUsdMonthly;
33
+ const leverage = seatCostPaid > 0 ? totalConsumption / seatCostPaid : Infinity;
34
+ const valueLabel = sub.billingMode === "imputed"
35
+ ? "Consumption value (API-equivalent rates, NOT a charge)"
36
+ : "Consumption value (billed usage)";
37
+ console.log(`\n ${tool} plan=${sub.plan} ${sub.seatCount} seat(s)`);
38
+ console.log(" ─────────────────────────────────────────────────────");
39
+ console.log(` Seat cost paid (last 30 days) : $${seatCostPaid.toFixed(2)} ($${sub.seatCostUsdMonthly}/seat/mo × ${sub.seatCount})`);
40
+ console.log(` ${valueLabel.padEnd(37)}: $${totalConsumption.toFixed(4)}`);
41
+ console.log(` Leverage ratio (value / paid) : ${seatCostPaid > 0 ? formatLeverage(leverage) : "n/a (no seat cost set)"}`);
42
+ console.log(` Sessions in window : ${rows.length}`);
43
+ // Per-seat distribution.
44
+ const byUser = groupByUser(rows);
45
+ if (byUser.size === 0) {
46
+ console.log("\n Per-seat distribution: no sessions with git attribution in this window.");
47
+ }
48
+ else {
49
+ const sorted = [...byUser.entries()].sort((a, b) => b[1] - a[1]);
50
+ const showTop = Math.min(5, sorted.length);
51
+ const showBottom = sorted.length > showTop ? Math.min(3, sorted.length - showTop) : 0;
52
+ console.log("\n Per-seat distribution (top consumers):");
53
+ for (const [email, val] of sorted.slice(0, showTop)) {
54
+ console.log(` ${email.padEnd(38)} $${val.toFixed(4)}`);
55
+ }
56
+ if (showBottom > 0) {
57
+ console.log("\n Dormant / lowest consumers:");
58
+ for (const [email, val] of sorted.slice(sorted.length - showBottom)) {
59
+ console.log(` ${email.padEnd(38)} $${val.toFixed(4)}`);
60
+ }
61
+ }
62
+ const unattributed = byUser.get("(unattributed)") ?? 0;
63
+ if (unattributed > 0) {
64
+ console.log(`\n Note: $${unattributed.toFixed(4)} from sessions with no git attribution (run \`planck scan\` to correlate).`);
65
+ }
66
+ }
67
+ }
68
+ }
69
+ export function runValue(options = {}) {
70
+ initDb();
71
+ const config = readConfig();
72
+ const { subscriptions } = config;
73
+ const sinceIso = since30DaysIso();
74
+ console.log("PlanckSpace Value Report (last 30 days)");
75
+ console.log("═════════════════════════════════════════════════════════");
76
+ if (options.tool) {
77
+ printToolReport(options.tool, subscriptions, sinceIso);
78
+ }
79
+ else {
80
+ // Show report for every subscribed tool, plus a prompt for any unsubscribed known tools.
81
+ const subscribedTools = [...new Set(subscriptions.map((s) => s.tool))];
82
+ if (subscribedTools.length === 0) {
83
+ console.log("\nNo subscriptions declared.");
84
+ console.log("Use `planck subscription add --tool <tool> --plan <plan> --seats <n> --seat-cost <usd>` to get started.");
85
+ return;
86
+ }
87
+ for (const tool of subscribedTools) {
88
+ printToolReport(tool, subscriptions, sinceIso);
89
+ }
90
+ }
91
+ console.log("\n─────────────────────────────────────────────────────────");
92
+ console.log("Leverage >1 = you're getting more value than you're paying for.");
93
+ console.log("Leverage <1 = seats underutilised — consider rightsizing or training.");
94
+ }
95
+ //# sourceMappingURL=value.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"value.js","sourceRoot":"","sources":["../../src/commands/value.ts"],"names":[],"mappings":"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"}
package/dist/config.d.ts CHANGED
@@ -1,6 +1,31 @@
1
- import type { PlanckConfig } from "@planckspace/core";
2
- export declare function readConfig(): PlanckConfig;
3
- export declare function writeConfig(config: PlanckConfig): void;
1
+ import type { PlanckConfig, SubscriptionContext } from "@planckspace/core";
2
+ export type { SubscriptionContext };
3
+ export type Budget = {
4
+ scope: "repo" | "workspace";
5
+ /** Repo name (scope=repo) or workspace label (scope=workspace). */
6
+ name: string;
7
+ /** Monthly budget cap in USD. */
8
+ monthly: number;
9
+ };
10
+ export type TeamMapping = {
11
+ team: string;
12
+ /** Glob patterns matched against repoName (supports * and ?). */
13
+ repos: string[];
14
+ };
15
+ /** PlanckConfig extended with fields that live only in the CLI config file. */
16
+ export type LocalConfig = PlanckConfig & {
17
+ budgets: Budget[];
18
+ teamMappings: TeamMapping[];
19
+ /**
20
+ * Controls whether per-developer email is included in exports.
21
+ * "collaborative" = omit developerEmail from all chargeback exports.
22
+ * "individual" (default) = include developerEmail when available.
23
+ */
24
+ privacyMode: "individual" | "collaborative";
25
+ };
26
+ export declare const CONFIG_PATH: string;
27
+ export declare function readConfig(): LocalConfig;
28
+ export declare function writeConfig(config: LocalConfig): void;
4
29
  /** apiUrl precedence: PLANCKSPACE_API_URL env → config file → hardcoded default */
5
30
  export declare function resolveApiUrl(): string;
6
31
  //# sourceMappingURL=config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAYtD,wBAAgB,UAAU,IAAI,YAAY,CAczC;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAOtD;AAED,mFAAmF;AACnF,wBAAgB,aAAa,IAAI,MAAM,CAEtC"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAE3E,YAAY,EAAE,mBAAmB,EAAE,CAAC;AAEpC,MAAM,MAAM,MAAM,GAAG;IACnB,KAAK,EAAE,MAAM,GAAG,WAAW,CAAC;IAC5B,mEAAmE;IACnE,IAAI,EAAE,MAAM,CAAC;IACb,iCAAiC;IACjC,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,iEAAiE;IACjE,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB,CAAC;AAEF,+EAA+E;AAC/E,MAAM,MAAM,WAAW,GAAG,YAAY,GAAG;IACvC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B;;;;OAIG;IACH,WAAW,EAAE,YAAY,GAAG,eAAe,CAAC;CAC7C,CAAC;AAEF,eAAO,MAAM,WAAW,QAAyD,CAAC;AAclF,wBAAgB,UAAU,IAAI,WAAW,CAkBxC;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAOrD;AAED,mFAAmF;AACnF,wBAAgB,aAAa,IAAI,MAAM,CAEtC"}
package/dist/config.js CHANGED
@@ -1,13 +1,17 @@
1
1
  import fs from "fs";
2
2
  import os from "os";
3
3
  import path from "path";
4
- const CONFIG_PATH = path.join(os.homedir(), ".planckspace", "config.json");
4
+ export const CONFIG_PATH = path.join(os.homedir(), ".planckspace", "config.json");
5
5
  const DEFAULTS = {
6
6
  apiUrl: "https://api.planckspace.dev",
7
7
  token: null,
8
8
  workspaceId: null,
9
9
  workspaceName: null,
10
10
  pausedWorkspaces: [],
11
+ subscriptions: [],
12
+ budgets: [],
13
+ teamMappings: [],
14
+ privacyMode: "individual",
11
15
  };
12
16
  export function readConfig() {
13
17
  try {
@@ -19,6 +23,10 @@ export function readConfig() {
19
23
  workspaceId: parsed.workspaceId ?? null,
20
24
  workspaceName: parsed.workspaceName ?? null,
21
25
  pausedWorkspaces: parsed.pausedWorkspaces ?? [],
26
+ subscriptions: parsed.subscriptions ?? [],
27
+ budgets: parsed.budgets ?? [],
28
+ teamMappings: parsed.teamMappings ?? [],
29
+ privacyMode: parsed.privacyMode ?? "individual",
22
30
  };
23
31
  }
24
32
  catch {
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AAGxB,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,cAAc,EAAE,aAAa,CAAC,CAAC;AAE3E,MAAM,QAAQ,GAAiB;IAC7B,MAAM,EAAE,6BAA6B;IACrC,KAAK,EAAE,IAAI;IACX,WAAW,EAAE,IAAI;IACjB,aAAa,EAAE,IAAI;IACnB,gBAAgB,EAAE,EAAE;CACrB,CAAC;AAEF,MAAM,UAAU,UAAU;IACxB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QAClD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAA0B,CAAC;QACxD,OAAO;YACL,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,QAAQ,CAAC,MAAM;YACxC,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,IAAI;YAC3B,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,IAAI;YACvC,aAAa,EAAE,MAAM,CAAC,aAAa,IAAI,IAAI;YAC3C,gBAAgB,EAAE,MAAM,CAAC,gBAAgB,IAAI,EAAE;SAChD,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,GAAG,QAAQ,EAAE,CAAC;IACzB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,MAAoB;IAC9C,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IACtC,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACpD,EAAE,CAAC,aAAa,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE;QAC7D,IAAI,EAAE,KAAK;QACX,QAAQ,EAAE,OAAO;KAClB,CAAC,CAAC;AACL,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,aAAa;IAC3B,OAAO,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,UAAU,EAAE,CAAC,MAAM,CAAC;AAChE,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AA+BxB,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,cAAc,EAAE,aAAa,CAAC,CAAC;AAElF,MAAM,QAAQ,GAAgB;IAC5B,MAAM,EAAE,6BAA6B;IACrC,KAAK,EAAE,IAAI;IACX,WAAW,EAAE,IAAI;IACjB,aAAa,EAAE,IAAI;IACnB,gBAAgB,EAAE,EAAE;IACpB,aAAa,EAAE,EAAE;IACjB,OAAO,EAAE,EAAE;IACX,YAAY,EAAE,EAAE;IAChB,WAAW,EAAE,YAAY;CAC1B,CAAC;AAEF,MAAM,UAAU,UAAU;IACxB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QAClD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAyB,CAAC;QACvD,OAAO;YACL,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,QAAQ,CAAC,MAAM;YACxC,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,IAAI;YAC3B,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,IAAI;YACvC,aAAa,EAAE,MAAM,CAAC,aAAa,IAAI,IAAI;YAC3C,gBAAgB,EAAE,MAAM,CAAC,gBAAgB,IAAI,EAAE;YAC/C,aAAa,EAAE,MAAM,CAAC,aAAa,IAAI,EAAE;YACzC,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,EAAE;YAC7B,YAAY,EAAE,MAAM,CAAC,YAAY,IAAI,EAAE;YACvC,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,YAAY;SAChD,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,GAAG,QAAQ,EAAE,CAAC;IACzB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,MAAmB;IAC7C,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IACtC,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACpD,EAAE,CAAC,aAAa,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE;QAC7D,IAAI,EAAE,KAAK;QACX,QAAQ,EAAE,OAAO;KAClB,CAAC,CAAC;AACL,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,aAAa;IAC3B,OAAO,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,UAAU,EAAE,CAAC,MAAM,CAAC;AAChE,CAAC"}
@@ -7,6 +7,13 @@ export declare const UNKNOWN_WINDOW_DAYS = 7;
7
7
  /** Branch names treated as the repo's default/trunk, in priority order. */
8
8
  export declare const DEFAULT_BRANCH_CANDIDATES: readonly ["main", "master"];
9
9
  export type Outcome = "shipped" | "partial" | "abandoned" | "errored" | "unknown";
10
+ export type ClassifyResult = {
11
+ outcome: Outcome;
12
+ /** ISO date when the work landed on the default branch (set only for "shipped"). */
13
+ mergedAt: string | null;
14
+ /** PR number extracted from the merge/squash commit message (set only for "shipped"). */
15
+ mergedPrNumber: number | null;
16
+ };
10
17
  /**
11
18
  * Correlate every stored session that has a repoName + workingDir against its
12
19
  * git repo, recording the git author email and a recomputed outcome.
@@ -1 +1 @@
1
- {"version":3,"file":"correlate.d.ts","sourceRoot":"","sources":["../src/correlate.ts"],"names":[],"mappings":"AAaA,+FAA+F;AAC/F,eAAO,MAAM,yBAAyB,IAAI,CAAC;AAC3C,oFAAoF;AACpF,eAAO,MAAM,qBAAqB,KAAK,CAAC;AACxC,6FAA6F;AAC7F,eAAO,MAAM,mBAAmB,IAAI,CAAC;AACrC,2EAA2E;AAC3E,eAAO,MAAM,yBAAyB,6BAA8B,CAAC;AAKrE,MAAM,MAAM,OAAO,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,SAAS,CAAC;AAsKlF;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CAAC,GAAG,GAAE,MAAmB,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CA6B9F"}
1
+ {"version":3,"file":"correlate.d.ts","sourceRoot":"","sources":["../src/correlate.ts"],"names":[],"mappings":"AAeA,+FAA+F;AAC/F,eAAO,MAAM,yBAAyB,IAAI,CAAC;AAC3C,oFAAoF;AACpF,eAAO,MAAM,qBAAqB,KAAK,CAAC;AACxC,6FAA6F;AAC7F,eAAO,MAAM,mBAAmB,IAAI,CAAC;AACrC,2EAA2E;AAC3E,eAAO,MAAM,yBAAyB,6BAA8B,CAAC;AAKrE,MAAM,MAAM,OAAO,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,SAAS,CAAC;AAelF,MAAM,MAAM,cAAc,GAAG;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,oFAAoF;IACpF,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,yFAAyF;IACzF,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B,CAAC;AA4OF;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CAAC,GAAG,GAAE,MAAmB,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAoD9F"}
package/dist/correlate.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import fs from "fs";
2
2
  import { simpleGit } from "simple-git";
3
- import { getSessionsForCorrelation, setSessionCorrelation, } from "./db/store.js";
3
+ import { getSessionsForCorrelation, setSessionCorrelation, setSessionMergeInfo, resetSyncStateForIds, } from "./db/store.js";
4
4
  // ── Heuristics & time windows ───────────────────────────────────────────────
5
5
  // All correlation thresholds live here. Outcomes are recomputed on every run
6
6
  // (branches merge later, sessions age past a window), so these are read fresh
@@ -17,7 +17,8 @@ const HOUR_MS = 60 * 60 * 1000;
17
17
  const DAY_MS = 24 * HOUR_MS;
18
18
  // Unit separator keeps the format unambiguous even if an author name contains spaces/pipes.
19
19
  const FIELD_SEP = "\x1f";
20
- const COMMIT_FORMAT = ["%H", "%ae", "%aI", "%cI"].join(FIELD_SEP);
20
+ // %s = commit subject (first line of message) — used to extract PR numbers
21
+ const COMMIT_FORMAT = ["%H", "%ae", "%aI", "%cI", "%s"].join(FIELD_SEP);
21
22
  // ── Low-level git probes (each fails closed, never throws) ───────────────────
22
23
  async function isGitRepo(git) {
23
24
  try {
@@ -73,7 +74,8 @@ async function commitsOnBranch(git, branch) {
73
74
  const trimmed = line.trim();
74
75
  if (!trimmed)
75
76
  continue;
76
- const [hash, authorEmail, authorDate, committerDate] = trimmed.split(FIELD_SEP);
77
+ const parts = trimmed.split(FIELD_SEP);
78
+ const [hash, authorEmail, authorDate, committerDate, ...rest] = parts;
77
79
  if (!hash)
78
80
  continue;
79
81
  commits.push({
@@ -81,6 +83,7 @@ async function commitsOnBranch(git, branch) {
81
83
  authorEmail: authorEmail ?? "",
82
84
  authorDate: authorDate ?? "",
83
85
  committerDate: committerDate ?? "",
86
+ subject: rest.join(FIELD_SEP), // subject may contain the separator
84
87
  });
85
88
  }
86
89
  return commits;
@@ -104,16 +107,67 @@ async function reachableFrom(git, ref) {
104
107
  return new Set();
105
108
  }
106
109
  }
110
+ // ── PR / merge metadata ──────────────────────────────────────────────────────
111
+ /** Extract a PR number from a commit subject line. Works for GitHub merge ("Merge pull request #42")
112
+ * and squash ("My feature (#42)") strategies. */
113
+ function extractPrNumber(subject) {
114
+ const m = subject.match(/#(\d+)/);
115
+ return m ? parseInt(m[1], 10) : null;
116
+ }
117
+ /**
118
+ * Given the first session commit that landed on the default branch, find the
119
+ * best-available merge timestamp and PR number.
120
+ *
121
+ * Strategy 1 (regular merge): look for a merge commit on the default branch whose
122
+ * message references the feature branch name — that commit is the merge commit and
123
+ * its committer date is the actual merge timestamp.
124
+ * Strategy 2 (squash / rebase / fast-forward fallback): use the landed commit's own
125
+ * committer date and subject.
126
+ */
127
+ async function resolveMergeInfo(git, landedCommit, defaultBranch, featureBranch) {
128
+ if (featureBranch) {
129
+ try {
130
+ const fmt = ["%cI", "%s"].join(FIELD_SEP);
131
+ const raw = await git.raw([
132
+ "log", defaultBranch, "--merges",
133
+ `--grep=${featureBranch}`,
134
+ `--pretty=format:${fmt}`,
135
+ "-1",
136
+ ]);
137
+ const trimmed = raw.trim();
138
+ if (trimmed) {
139
+ const sepIdx = trimmed.indexOf(FIELD_SEP);
140
+ if (sepIdx !== -1) {
141
+ const mergedAt = trimmed.slice(0, sepIdx).trim();
142
+ const subject = trimmed.slice(sepIdx + 1).trim();
143
+ return { mergedAt, mergedPrNumber: extractPrNumber(subject) };
144
+ }
145
+ }
146
+ }
147
+ catch {
148
+ // fall through to the commit-level fallback below
149
+ }
150
+ }
151
+ return {
152
+ mergedAt: landedCommit.committerDate || null,
153
+ mergedPrNumber: extractPrNumber(landedCommit.subject),
154
+ };
155
+ }
107
156
  // ── Classification ───────────────────────────────────────────────────────────
108
157
  /**
109
158
  * Decide the outcome for one session. Pure with respect to `now` so tests can
110
159
  * pin the clock; all real git state comes through `git`.
111
160
  */
112
161
  async function classify(git, session, email, now) {
162
+ const simple = (outcome) => ({
163
+ outcome,
164
+ mergedAt: null,
165
+ mergedPrNumber: null,
166
+ });
113
167
  // A non-zero exit / error captured by the scraper is authoritative — git
114
168
  // history can't un-error a crashed session, so we never override it.
115
169
  if (session.outcome === "errored")
116
- return "errored";
170
+ return simple("errored");
117
171
  const startedMs = Date.parse(session.startedAt);
118
172
  const endedMs = Date.parse(session.endedAt);
119
173
  // Commits by this session's git author, on its branch, after it began.
@@ -144,23 +198,38 @@ async function classify(git, session, email, now) {
144
198
  const withinWindow = Number.isNaN(mergedMs) || Number.isNaN(startedMs)
145
199
  ? true
146
200
  : mergedMs - startedMs <= SHIPPED_MERGE_WINDOW_DAYS * DAY_MS;
147
- if (withinWindow)
148
- return "shipped";
201
+ if (withinWindow) {
202
+ const mergeInfo = await resolveMergeInfo(git, commit, defaultBranch, session.gitBranch);
203
+ return { outcome: "shipped", ...mergeInfo };
204
+ }
205
+ }
206
+ }
207
+ // Commits exist but none reached the default branch yet (or no default branch).
208
+ // If any session commit has been pushed to the remote tracking branch, the
209
+ // developer has shipped their work — it just hasn't been merged to main yet.
210
+ if (session.gitBranch) {
211
+ const remoteCommits = await reachableFrom(git, `origin/${session.gitBranch}`);
212
+ const pushedCommit = sessionCommits.find((c) => remoteCommits.has(c.hash));
213
+ if (pushedCommit) {
214
+ return {
215
+ outcome: "shipped",
216
+ mergedAt: pushedCommit.committerDate || null,
217
+ mergedPrNumber: null,
218
+ };
149
219
  }
150
220
  }
151
- // Committed but not merged into default (within window). Hold the verdict
152
- // open while we're still inside the window — it may yet ship.
221
+ // Committed locally but not pushed and not merged. Hold verdict open while fresh.
153
222
  if (!Number.isNaN(startedMs) && now - startedMs <= UNKNOWN_WINDOW_DAYS * DAY_MS) {
154
- return "unknown";
223
+ return simple("unknown");
155
224
  }
156
- return "partial";
225
+ return simple("partial");
157
226
  }
158
227
  // No attributable commits. Once enough time has passed with nothing produced,
159
228
  // call it abandoned; otherwise it's too early to say.
160
229
  if (!Number.isNaN(endedMs) && now - endedMs > ABANDONED_AFTER_HOURS * HOUR_MS) {
161
- return "abandoned";
230
+ return simple("abandoned");
162
231
  }
163
- return "unknown";
232
+ return simple("unknown");
164
233
  }
165
234
  // ── Entry point ───────────────────────────────────────────────────────────────
166
235
  /**
@@ -189,9 +258,27 @@ export async function correlateSessions(now = Date.now()) {
189
258
  if (!(await isGitRepo(git)))
190
259
  continue; // workingDir is no longer a git repo
191
260
  try {
192
- const email = await getAuthorEmail(git);
193
- const outcome = await classify(git, session, email, now);
194
- setSessionCorrelation(session.id, outcome, email);
261
+ // Fall back to the previously stored email when git config is unavailable.
262
+ // This prevents a transient failure from erasing known-good attribution and
263
+ // ensures commit filtering works even if local git config changes.
264
+ const email = (await getAuthorEmail(git)) ?? session.gitAuthorEmail ?? null;
265
+ const result = await classify(git, session, email, now);
266
+ setSessionCorrelation(session.id, result.outcome, email);
267
+ // If the outcome changed, the session was already synced with the old
268
+ // outcome — reset sync state so the next push re-sends the updated row.
269
+ if (result.outcome !== session.outcome) {
270
+ resetSyncStateForIds([session.id], "outcome-changed");
271
+ }
272
+ if (result.outcome === "shipped") {
273
+ const timeToMergeMs = result.mergedAt && session.startedAt
274
+ ? Date.parse(result.mergedAt) - Date.parse(session.startedAt)
275
+ : null;
276
+ setSessionMergeInfo(session.id, result.mergedPrNumber ?? null, result.mergedAt, timeToMergeMs !== null && Number.isFinite(timeToMergeMs) ? timeToMergeMs : null);
277
+ }
278
+ else {
279
+ // Clear stale merge info if the session re-correlates away from "shipped"
280
+ setSessionMergeInfo(session.id, null, null, null);
281
+ }
195
282
  updated++;
196
283
  }
197
284
  catch {
@@ -1 +1 @@
1
- {"version":3,"file":"correlate.js","sourceRoot":"","sources":["../src/correlate.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"correlate.js","sourceRoot":"","sources":["../src/correlate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,SAAS,EAAkB,MAAM,YAAY,CAAC;AACvD,OAAO,EACL,yBAAyB,EACzB,qBAAqB,EACrB,mBAAmB,EACnB,oBAAoB,GAErB,MAAM,eAAe,CAAC;AAEvB,+EAA+E;AAC/E,6EAA6E;AAC7E,8EAA8E;AAC9E,qDAAqD;AAErD,+FAA+F;AAC/F,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,CAAC;AAC3C,oFAAoF;AACpF,MAAM,CAAC,MAAM,qBAAqB,GAAG,EAAE,CAAC;AACxC,6FAA6F;AAC7F,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC;AACrC,2EAA2E;AAC3E,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAU,CAAC;AAErE,MAAM,OAAO,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAC/B,MAAM,MAAM,GAAG,EAAE,GAAG,OAAO,CAAC;AAI5B,4FAA4F;AAC5F,MAAM,SAAS,GAAG,MAAM,CAAC;AACzB,2EAA2E;AAC3E,MAAM,aAAa,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;AAkBxE,gFAAgF;AAEhF,KAAK,UAAU,SAAS,CAAC,GAAc;IACrC,IAAI,CAAC;QACH,OAAO,MAAM,GAAG,CAAC,WAAW,EAAE,CAAC;IACjC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,2EAA2E;AAC3E,KAAK,UAAU,cAAc,CAAC,GAAc;IAC1C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;QAC9C,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC;QAChC,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;IAC9B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,KAAK,UAAU,oBAAoB,CAAC,GAAc;IAChD,wEAAwE;IACxE,8EAA8E;IAC9E,8EAA8E;IAC9E,uDAAuD;IACvD,IAAI,KAAe,CAAC;IACpB,IAAI,CAAC;QACH,KAAK,GAAG,CAAC,MAAM,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,GAAG,CAAC;IACxC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC,CAAC,4CAA4C;IAC3D,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,yBAAyB,EAAE,CAAC;QAC7C,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;IACxC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;GAGG;AACH,KAAK,UAAU,eAAe,CAAC,GAAc,EAAE,MAAc;IAC3D,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,GAAG,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,mBAAmB,aAAa,EAAE,CAAC,CAAC,CAAC;IAC3E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,OAAO,GAAiB,EAAE,CAAC;IACjC,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACnC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,CAAC,OAAO;YAAE,SAAS;QACvB,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QACvC,MAAM,CAAC,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,aAAa,EAAE,GAAG,IAAI,CAAC,GAAG,KAAK,CAAC;QACtE,IAAI,CAAC,IAAI;YAAE,SAAS;QACpB,OAAO,CAAC,IAAI,CAAC;YACX,IAAI;YACJ,WAAW,EAAE,WAAW,IAAI,EAAE;YAC9B,UAAU,EAAE,UAAU,IAAI,EAAE;YAC5B,aAAa,EAAE,aAAa,IAAI,EAAE;YAClC,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,oCAAoC;SACpE,CAAC,CAAC;IACL,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;GAKG;AACH,KAAK,UAAU,aAAa,CAAC,GAAc,EAAE,GAAW;IACtD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,CAAC;QAC7C,MAAM,MAAM,GAAG,GAAG;aACf,KAAK,CAAC,IAAI,CAAC;aACX,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;aACpB,MAAM,CAAC,OAAO,CAAC,CAAC;QACnB,OAAO,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,GAAG,EAAE,CAAC;IACnB,CAAC;AACH,CAAC;AAED,gFAAgF;AAEhF;kDACkD;AAClD,SAAS,eAAe,CAAC,OAAe;IACtC,MAAM,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAClC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACvC,CAAC;AAED;;;;;;;;;GASG;AACH,KAAK,UAAU,gBAAgB,CAC7B,GAAc,EACd,YAAwB,EACxB,aAAqB,EACrB,aAA4B;IAE5B,IAAI,aAAa,EAAE,CAAC;QAClB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAC1C,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,GAAG,CAAC;gBACxB,KAAK,EAAE,aAAa,EAAE,UAAU;gBAChC,UAAU,aAAa,EAAE;gBACzB,mBAAmB,GAAG,EAAE;gBACxB,IAAI;aACL,CAAC,CAAC;YACH,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;YAC3B,IAAI,OAAO,EAAE,CAAC;gBACZ,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;gBAC1C,IAAI,MAAM,KAAK,CAAC,CAAC,EAAE,CAAC;oBAClB,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;oBACjD,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;oBACjD,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,eAAe,CAAC,OAAO,CAAC,EAAE,CAAC;gBAChE,CAAC;YACH,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,kDAAkD;QACpD,CAAC;IACH,CAAC;IAED,OAAO;QACL,QAAQ,EAAE,YAAY,CAAC,aAAa,IAAI,IAAI;QAC5C,cAAc,EAAE,eAAe,CAAC,YAAY,CAAC,OAAO,CAAC;KACtD,CAAC;AACJ,CAAC;AAED,gFAAgF;AAEhF;;;GAGG;AACH,KAAK,UAAU,QAAQ,CACrB,GAAc,EACd,OAA8B,EAC9B,KAAoB,EACpB,GAAW;IAEX,MAAM,MAAM,GAAG,CAAC,OAAgB,EAAkB,EAAE,CAAC,CAAC;QACpD,OAAO;QACP,QAAQ,EAAE,IAAI;QACd,cAAc,EAAE,IAAI;KACrB,CAAC,CAAC;IAEH,yEAAyE;IACzE,qEAAqE;IACrE,IAAI,OAAO,CAAC,OAAO,KAAK,SAAS;QAAE,OAAO,MAAM,CAAC,SAAS,CAAC,CAAC;IAE5D,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAE5C,uEAAuE;IACvE,0EAA0E;IAC1E,IAAI,cAAc,GAAiB,EAAE,CAAC;IACtC,IAAI,OAAO,CAAC,SAAS,IAAI,KAAK,EAAE,CAAC;QAC/B,MAAM,OAAO,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;QACpC,MAAM,aAAa,GAAG,MAAM,eAAe,CAAC,GAAG,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;QACpE,cAAc,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;YAC1C,IAAI,CAAC,CAAC,WAAW,CAAC,WAAW,EAAE,KAAK,OAAO;gBAAE,OAAO,KAAK,CAAC;YAC1D,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;YAC5C,sEAAsE;YACtE,+CAA+C;YAC/C,IAAI,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC;gBAAE,OAAO,IAAI,CAAC;YACrE,OAAO,UAAU,IAAI,SAAS,CAAC;QACjC,CAAC,CAAC,CAAC;IACL,CAAC;IAED,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9B,MAAM,aAAa,GAAG,MAAM,oBAAoB,CAAC,GAAG,CAAC,CAAC;QACtD,IAAI,aAAa,EAAE,CAAC;YAClB,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC;YACvD,KAAK,MAAM,MAAM,IAAI,cAAc,EAAE,CAAC;gBACpC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC;oBAAE,SAAS;gBACvC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;gBAClD,MAAM,YAAY,GAChB,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC;oBAC/C,CAAC,CAAC,IAAI;oBACN,CAAC,CAAC,QAAQ,GAAG,SAAS,IAAI,yBAAyB,GAAG,MAAM,CAAC;gBACjE,IAAI,YAAY,EAAE,CAAC;oBACjB,MAAM,SAAS,GAAG,MAAM,gBAAgB,CACtC,GAAG,EAAE,MAAM,EAAE,aAAa,EAAE,OAAO,CAAC,SAAS,CAC9C,CAAC;oBACF,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,SAAS,EAAE,CAAC;gBAC9C,CAAC;YACH,CAAC;QACH,CAAC;QAED,gFAAgF;QAChF,2EAA2E;QAC3E,6EAA6E;QAC7E,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;YACtB,MAAM,aAAa,GAAG,MAAM,aAAa,CAAC,GAAG,EAAE,UAAU,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;YAC9E,MAAM,YAAY,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;YAC3E,IAAI,YAAY,EAAE,CAAC;gBACjB,OAAO;oBACL,OAAO,EAAE,SAAS;oBAClB,QAAQ,EAAE,YAAY,CAAC,aAAa,IAAI,IAAI;oBAC5C,cAAc,EAAE,IAAI;iBACrB,CAAC;YACJ,CAAC;QACH,CAAC;QAED,kFAAkF;QAClF,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,GAAG,GAAG,SAAS,IAAI,mBAAmB,GAAG,MAAM,EAAE,CAAC;YAChF,OAAO,MAAM,CAAC,SAAS,CAAC,CAAC;QAC3B,CAAC;QACD,OAAO,MAAM,CAAC,SAAS,CAAC,CAAC;IAC3B,CAAC;IAED,8EAA8E;IAC9E,sDAAsD;IACtD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,GAAG,GAAG,OAAO,GAAG,qBAAqB,GAAG,OAAO,EAAE,CAAC;QAC9E,OAAO,MAAM,CAAC,WAAW,CAAC,CAAC;IAC7B,CAAC;IACD,OAAO,MAAM,CAAC,SAAS,CAAC,CAAC;AAC3B,CAAC;AAED,iFAAiF;AAEjF;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,MAAc,IAAI,CAAC,GAAG,EAAE;IAC9D,MAAM,QAAQ,GAAG,yBAAyB,EAAE,CAAC;IAC7C,IAAI,OAAO,GAAG,CAAC,CAAC;IAEhB,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,IAAI,CAAC,OAAO,CAAC,QAAQ,IAAI,CAAC,OAAO,CAAC,UAAU;YAAE,SAAS;QACvD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,UAAU,CAAC;YAAE,SAAS;QAEjD,IAAI,GAAc,CAAC;QACnB,IAAI,CAAC;YACH,GAAG,GAAG,SAAS,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QACtC,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QAED,IAAI,CAAC,CAAC,MAAM,SAAS,CAAC,GAAG,CAAC,CAAC;YAAE,SAAS,CAAC,qCAAqC;QAE5E,IAAI,CAAC;YACH,2EAA2E;YAC3E,4EAA4E;YAC5E,mEAAmE;YACnE,MAAM,KAAK,GAAG,CAAC,MAAM,cAAc,CAAC,GAAG,CAAC,CAAC,IAAI,OAAO,CAAC,cAAc,IAAI,IAAI,CAAC;YAC5E,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;YACxD,qBAAqB,CAAC,OAAO,CAAC,EAAE,EAAE,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;YACzD,sEAAsE;YACtE,wEAAwE;YACxE,IAAI,MAAM,CAAC,OAAO,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC;gBACvC,oBAAoB,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,iBAAiB,CAAC,CAAC;YACxD,CAAC;YACD,IAAI,MAAM,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;gBACjC,MAAM,aAAa,GACjB,MAAM,CAAC,QAAQ,IAAI,OAAO,CAAC,SAAS;oBAClC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC;oBAC7D,CAAC,CAAC,IAAI,CAAC;gBACX,mBAAmB,CACjB,OAAO,CAAC,EAAE,EACV,MAAM,CAAC,cAAc,IAAI,IAAI,EAC7B,MAAM,CAAC,QAAQ,EACf,aAAa,KAAK,IAAI,IAAI,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAChF,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACN,0EAA0E;gBAC1E,mBAAmB,CAAC,OAAO,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;YACpD,CAAC;YACD,OAAO,EAAE,CAAC;QACZ,CAAC;QAAC,MAAM,CAAC;YACP,gEAAgE;YAChE,SAAS;QACX,CAAC;IACH,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,CAAC;AACrB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function runDaemon(): Promise<void>;
2
+ //# sourceMappingURL=daemon.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon.d.ts","sourceRoot":"","sources":["../../src/daemon/daemon.ts"],"names":[],"mappings":"AAyFA,wBAAsB,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CA4H/C"}