claude-code-session-manager 0.83.0 → 0.84.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 (92) hide show
  1. package/dist/assets/{AgentLibrary-B-OM-4gk.js → AgentLibrary-CCVIpoSz.js} +1 -1
  2. package/dist/assets/{DataModel-BC6ppcBr.js → DataModel-BltREYde.js} +1 -1
  3. package/dist/assets/{History-D3Qw2BWn.js → History-BZxFkOp6.js} +2 -2
  4. package/dist/assets/{Hooks-OxBQ0nIc.js → Hooks-Bznlfaaa.js} +1 -1
  5. package/dist/assets/{HostBilko-BNFC6bNZ.js → HostBilko-DUG5YHA_.js} +1 -1
  6. package/dist/assets/{Library-DAMyrUtY.js → Library-Bi2Fn3w9.js} +1 -1
  7. package/dist/assets/{ListDetail-BwywrpvE.js → ListDetail-4VBvXKrz.js} +1 -1
  8. package/dist/assets/{MarkdownEditor-HEwjN1bp.js → MarkdownEditor-D2ft_v5j.js} +1 -1
  9. package/dist/assets/{McpServers-D1VZF7Ix.js → McpServers-FDekKkyE.js} +1 -1
  10. package/dist/assets/{Memory-CgYJ_QqD.js → Memory-Dkl80uj_.js} +6 -6
  11. package/dist/assets/{Panel-dTNWC59Q.js → Panel-LurG5VfD.js} +1 -1
  12. package/dist/assets/{Permissions-qI_NKi1b.js → Permissions-D2wHBCFA.js} +1 -1
  13. package/dist/assets/{Plugins-DZ0_CHiF.js → Plugins-CTw_wwbI.js} +2 -2
  14. package/dist/assets/{ProvenanceBadge-B2i_uxCu.js → ProvenanceBadge-CW6HNUv6.js} +1 -1
  15. package/dist/assets/{SaveBar-4tNMCjUd.js → SaveBar-alDHG6cP.js} +1 -1
  16. package/dist/assets/{Scheduler-CUen18Gc.js → Scheduler-DxiPcaiW.js} +7 -7
  17. package/dist/assets/{ScopeSwitcher-Co3tkLTT.js → ScopeSwitcher-DzFXUKLZ.js} +1 -1
  18. package/dist/assets/Settings-B6H3v2am.js +3 -0
  19. package/dist/assets/{SkillReferenceGraph-BKcHtMPc.js → SkillReferenceGraph-B8EZalpN.js} +1 -1
  20. package/dist/assets/{Skills-DHb4INtF.js → Skills-DwuHuA08.js} +2 -2
  21. package/dist/assets/SystemPrompt-CMMqpGYn.js +1 -0
  22. package/dist/assets/{TagLibrary-xLP5dJvh.js → TagLibrary-C2N5C1n9.js} +1 -1
  23. package/dist/assets/{TiptapBody-T-ULTjK4.js → TiptapBody-btlID-dQ.js} +1 -1
  24. package/dist/assets/{Toggle-B-5M2hGe.js → Toggle-BGOn3DZj.js} +1 -1
  25. package/dist/assets/{index-CzAxC432.js → index-QLRf0epp.js} +316 -314
  26. package/dist/assets/{index-CYhdtisq.css → index-mnjNDpb1.css} +1 -1
  27. package/dist/assets/{settingsSchema-C_nsemcF.js → settingsSchema-DA3N2Up3.js} +1 -1
  28. package/dist/index.html +2 -2
  29. package/package.json +4 -1
  30. package/scripts/hooks/guard-destructive-git.cjs +514 -0
  31. package/scripts/hooks/guard-inline-implementation.cjs +219 -0
  32. package/scripts/hooks/guard-prd-writes.cjs +200 -0
  33. package/src/main/__tests__/epicMintTelemetryTap.test.cjs +64 -0
  34. package/src/main/__tests__/health-delegation-chain.test.cjs +2 -1
  35. package/src/main/__tests__/health-queue-dispatch.test.cjs +84 -0
  36. package/src/main/__tests__/health-usage-poller.test.cjs +97 -0
  37. package/src/main/__tests__/health-worktree-cap-blocked.test.cjs +65 -0
  38. package/src/main/__tests__/opsErrorLogTelemetryTap.test.cjs +143 -0
  39. package/src/main/__tests__/pollLoop-dispatch-on-failure.test.cjs +120 -0
  40. package/src/main/__tests__/promptSessionTranscript.test.cjs +0 -0
  41. package/src/main/__tests__/queue-starvation-dispatch-driver.test.cjs +143 -0
  42. package/src/main/__tests__/rateLimitPollerStreak.test.cjs +79 -0
  43. package/src/main/__tests__/scheduleJobTransitionsTelemetryTap.test.cjs +72 -0
  44. package/src/main/__tests__/scheduler-inplace-salvage.test.cjs +74 -0
  45. package/src/main/__tests__/scheduler-job-overrun.test.cjs +58 -0
  46. package/src/main/__tests__/scheduler-notify-originating-tab-transcript.test.cjs +1 -0
  47. package/src/main/__tests__/scheduler-periodic-reverify-guard.test.cjs +134 -2
  48. package/src/main/__tests__/scheduler-reap-dead-running-jobs.test.cjs +33 -0
  49. package/src/main/__tests__/scheduler-stuck-failed-escalation.test.cjs +136 -0
  50. package/src/main/__tests__/telemetryClient.test.cjs +66 -0
  51. package/src/main/__tests__/telemetryContract.test.cjs +883 -0
  52. package/src/main/crashDiagnostics.cjs +29 -1
  53. package/src/main/health.cjs +197 -3
  54. package/src/main/index.cjs +65 -6
  55. package/src/main/ipcSchemas.cjs +19 -2
  56. package/src/main/lib/__tests__/crashTelemetry.test.cjs +97 -0
  57. package/src/main/lib/__tests__/delegationReadiness.test.cjs +302 -4
  58. package/src/main/lib/__tests__/fixtures/scheduler-machine.json.corrupt-1789147548 +34 -0
  59. package/src/main/lib/__tests__/gitWorktree.test.cjs +413 -1
  60. package/src/main/lib/__tests__/jobWorktreeBootLive.test.cjs +71 -0
  61. package/src/main/lib/__tests__/queueStoreAtomicWrite.test.cjs +88 -0
  62. package/src/main/lib/__tests__/queueStoreMachineStateRecovery.test.cjs +123 -0
  63. package/src/main/lib/__tests__/reaperHelpers.test.cjs +58 -0
  64. package/src/main/lib/__tests__/telemetryBacklog.test.cjs +620 -0
  65. package/src/main/lib/__tests__/telemetryBoot.test.cjs +125 -0
  66. package/src/main/lib/__tests__/telemetryConsent.test.cjs +130 -0
  67. package/src/main/lib/__tests__/telemetryCounters.test.cjs +57 -0
  68. package/src/main/lib/__tests__/telemetryCountersMetadataColumn.test.cjs +89 -0
  69. package/src/main/lib/crashTelemetry.cjs +37 -0
  70. package/src/main/lib/delegationReadiness.cjs +119 -1
  71. package/src/main/lib/epicMint.cjs +2 -0
  72. package/src/main/lib/gitWorktree.cjs +427 -17
  73. package/src/main/lib/jobWorktree.cjs +2 -1
  74. package/src/main/lib/jobWorktreeBootLive.cjs +51 -0
  75. package/src/main/lib/jobWorktreeTerminalOrphanLive.cjs +68 -0
  76. package/src/main/lib/opsErrorLog.cjs +78 -25
  77. package/src/main/lib/queueStore.cjs +233 -20
  78. package/src/main/lib/reaperHelpers.cjs +23 -1
  79. package/src/main/lib/scheduleJobSchema.cjs +7 -0
  80. package/src/main/lib/scheduleJobTransitions.cjs +12 -0
  81. package/src/main/lib/telemetryBacklog.cjs +601 -0
  82. package/src/main/lib/telemetryBoot.cjs +71 -0
  83. package/src/main/lib/telemetryClient.cjs +31 -0
  84. package/src/main/lib/telemetryConsent.cjs +34 -0
  85. package/src/main/lib/telemetryCounters.cjs +45 -0
  86. package/src/main/promptSessionTranscript.cjs +0 -0
  87. package/src/main/pty.cjs +2 -0
  88. package/src/main/scheduler.cjs +481 -33
  89. package/src/preload/api.d.ts +84 -4
  90. package/src/preload/index.cjs +9 -0
  91. package/dist/assets/Settings-DXVgKLUx.js +0 -3
  92. package/dist/assets/SystemPrompt-BjqFOHSk.js +0 -1
@@ -83,6 +83,9 @@ const S = {
83
83
  errSeen: new Map(),
84
84
  dailyTimer: null,
85
85
  flushChain: Promise.resolve(),
86
+ lastError: null,
87
+ lastFlushAt: null,
88
+ lastFlushReason: null,
86
89
  };
87
90
 
88
91
  function queuePath() {
@@ -493,16 +496,22 @@ async function sendBatch(channel, wireBatch) {
493
496
  }
494
497
  }
495
498
 
499
+ function describeFailureStatus(status) {
500
+ return status === 0 ? 'network error' : `HTTP ${status}`;
501
+ }
502
+
496
503
  function applyFailureBackoff(status) {
497
504
  if (status === 429 || status === 0 || status >= 500) {
498
505
  S.consecutiveFailures += 1;
499
506
  const ms = Math.min(BACKOFF_BASE_MS * (2 ** (S.consecutiveFailures - 1)), BACKOFF_MAX_MS);
500
507
  S.backoffUntil = Date.now() + ms;
508
+ S.lastError = { status, message: describeFailureStatus(status), at: Date.now() };
501
509
  return;
502
510
  }
503
511
  if (status >= 400 && status < 500) {
504
512
  // Malformed-contract circuit breaker (includes 401) — not retried.
505
513
  S.disabledForProcess = true;
514
+ S.lastError = { status, message: describeFailureStatus(status), at: Date.now() };
506
515
  }
507
516
  }
508
517
 
@@ -543,6 +552,7 @@ async function flushImpl(reason) {
543
552
  if (res.ok) {
544
553
  S.consecutiveFailures = 0;
545
554
  S.backoffUntil = 0;
555
+ S.lastError = null;
546
556
  for (const r of batch) {
547
557
  removeFromQueue(r.recordId);
548
558
  addToSent(r.recordId);
@@ -564,6 +574,8 @@ async function flushImpl(reason) {
564
574
  S.settings = await telemetrySettings.save({ ...S.settings, lastDailyFlushAt: new Date().toISOString() });
565
575
  }
566
576
  } catch { /* fail-inert */ }
577
+ S.lastFlushAt = Date.now();
578
+ S.lastFlushReason = safeReason;
567
579
  return result;
568
580
  }
569
581
 
@@ -584,6 +596,9 @@ function status() {
584
596
  consecutiveFailures: S.consecutiveFailures,
585
597
  backoffUntil: S.backoffUntil,
586
598
  profileBuildCount: S.profileBuildCount,
599
+ lastError: S.lastError,
600
+ lastFlushAt: S.lastFlushAt,
601
+ lastFlushReason: S.lastFlushReason,
587
602
  };
588
603
  }
589
604
 
@@ -591,6 +606,21 @@ function recentRecords() {
591
606
  return S.recent.slice();
592
607
  }
593
608
 
609
+ /**
610
+ * Opt-out side effect: drops every not-yet-sent record from disk + memory so
611
+ * a re-enable later never resends a payload that was only ever queued while
612
+ * the user was opted out. Does NOT touch telemetry-sent.json or the backlog
613
+ * watermarks — those describe history that already left the machine, and
614
+ * clearing them would make a re-enable resend it. Never throws.
615
+ */
616
+ async function clearQueue() {
617
+ S.queue = [];
618
+ S.queueIds = new Set();
619
+ try {
620
+ await config.writeTextAtomic(queuePath(), '', { mode: 0o600 });
621
+ } catch { /* best-effort */ }
622
+ }
623
+
594
624
  async function isPending(recordId) {
595
625
  await ensureInit();
596
626
  return S.queueIds.has(recordId);
@@ -615,6 +645,7 @@ module.exports = {
615
645
  status,
616
646
  recentRecords,
617
647
  isPending,
648
+ clearQueue,
618
649
  queuePath,
619
650
  sentPath,
620
651
  _setFetchImpl,
@@ -0,0 +1,34 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * telemetryConsent — the write-path the `telemetry:set-config` IPC handler
5
+ * delegates to, pulled out of src/main/index.cjs so it can be unit-tested
6
+ * without an Electron runtime (index.cjs requires('electron') at module
7
+ * load, which vitest can't satisfy).
8
+ *
9
+ * The one side effect beyond a plain settings save: turning telemetry OFF
10
+ * clears the pending queue file, so a later re-enable never resends a
11
+ * payload that only ever accumulated while the user was opted out. It does
12
+ * NOT touch telemetry-sent.json or the backlog watermarks — those describe
13
+ * history already delivered, and clearing them would make a re-enable
14
+ * resend it. See session-manager-operations/architecture/telemetry.md.
15
+ */
16
+
17
+ function resolveDeps(deps = {}) {
18
+ return {
19
+ telemetrySettings: deps.telemetrySettings || require('./telemetrySettings.cjs'),
20
+ telemetryClient: deps.telemetryClient || require('./telemetryClient.cjs'),
21
+ };
22
+ }
23
+
24
+ async function applyConsentUpdate(cfg, depsOverride) {
25
+ const deps = resolveDeps(depsOverride);
26
+ const before = await deps.telemetrySettings.load();
27
+ const saved = await deps.telemetrySettings.save(cfg);
28
+ if (before.enabled && !saved.enabled) {
29
+ await deps.telemetryClient.clearQueue();
30
+ }
31
+ return saved;
32
+ }
33
+
34
+ module.exports = { applyConsentUpdate };
@@ -0,0 +1,45 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * telemetryCounters.cjs — the ONE place every usage counter event is emitted
5
+ * from, so 'session.open'/'epic.create'/'scheduler.job.finish'/'app.launch'
6
+ * each have exactly one call site's worth of shape logic even though they're
7
+ * fired from four different subsystems (pty.cjs, epicMint.cjs,
8
+ * scheduleJobTransitions.cjs, telemetryBoot.cjs).
9
+ *
10
+ * Structural props only — no free text, no cwd, no path — so a counter event
11
+ * can never carry a prompt/transcript/project-name leak by accident. Lazily
12
+ * requires telemetryClient.cjs (mirrors opsErrorLog.cjs's lazy require of
13
+ * opsOwnership.cjs) so this module stays Electron-free and importable from a
14
+ * plain-Node test.
15
+ */
16
+
17
+ function track(name, props, deps) {
18
+ try {
19
+ const telemetryClient = (deps && deps.telemetryClient) || require('./telemetryClient.cjs');
20
+ telemetryClient.track(name, props);
21
+ } catch { /* counters must never break the caller */ }
22
+ }
23
+
24
+ function trackAppLaunch({ installChannel, appVersion } = {}, deps) {
25
+ track('app.launch', { installChannel: installChannel || null, appVersion: appVersion || null }, deps);
26
+ }
27
+
28
+ function trackSessionOpen(deps) {
29
+ track('session.open', {}, deps);
30
+ }
31
+
32
+ function trackEpicCreate(deps) {
33
+ track('epic.create', {}, deps);
34
+ }
35
+
36
+ function trackSchedulerJobFinish({ status } = {}, deps) {
37
+ track('scheduler.job.finish', { status: status || null }, deps);
38
+ }
39
+
40
+ module.exports = {
41
+ trackAppLaunch,
42
+ trackSessionOpen,
43
+ trackEpicCreate,
44
+ trackSchedulerJobFinish,
45
+ };
package/src/main/pty.cjs CHANGED
@@ -22,6 +22,7 @@ const { checkInsideHome } = require('./lib/insideHome.cjs');
22
22
  const { sendIfAlive } = require('./lib/sendToRenderer.cjs');
23
23
  const opsErrorLog = require('./lib/opsErrorLog.cjs');
24
24
  const { resolveEpicSpawnCwd } = require('./lib/epicSpawnCwd.cjs');
25
+ const telemetryCounters = require('./lib/telemetryCounters.cjs');
25
26
 
26
27
  // Absolute path to the installed package root (src/main/ -> ../../), shown in
27
28
  // the remediation message so the user can cd there and rebuild.
@@ -200,6 +201,7 @@ class PtyManager {
200
201
  return { pid: null, cwd, reattached: false, error: String(err?.message || 'spawn-failed') };
201
202
  }
202
203
  console.log('[pty] spawned pid=', proc.pid, 'for tabId=', tabId);
204
+ telemetryCounters.trackSessionOpen();
203
205
 
204
206
  const spawnedAt = Date.now();
205
207
  let gotData = false;