claude-code-session-manager 0.122.0 → 0.123.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 (93) hide show
  1. package/dist/assets/{AgentLibrary-BmJ8hIPw.js → AgentLibrary-DxWN3FSN.js} +2 -2
  2. package/dist/assets/{Button-BS4kmz4p.js → Button-CISLFSKb.js} +1 -1
  3. package/dist/assets/DataModel-CYPbhGrx.js +1 -0
  4. package/dist/assets/{History-pg00b2Gd.js → History-Fhouektw.js} +2 -2
  5. package/dist/assets/{Hooks-BTEs0UZY.js → Hooks-COfIcyYV.js} +3 -3
  6. package/dist/assets/{Library-DuaJ-VSn.js → Library-Bt5WOyyu.js} +7 -7
  7. package/dist/assets/ListDetail-DH7uzYd5.js +1 -0
  8. package/dist/assets/{McpServers-Dy-wnG_X.js → McpServers-CwyVEzMN.js} +2 -2
  9. package/dist/assets/{Memory-Bs1T1Jo7.js → Memory-k9TWT9N4.js} +8 -8
  10. package/dist/assets/{Panel-8UhLXEOW.js → Panel-Di8JqCYN.js} +1 -1
  11. package/dist/assets/{Permissions-BfwzvmBS.js → Permissions-FFs6Rq1H.js} +3 -3
  12. package/dist/assets/{Plugins-McjyvvKh.js → Plugins-uK5vl_RE.js} +2 -2
  13. package/dist/assets/{ProvenanceBadge-D0Ov_6WJ.js → ProvenanceBadge-CGDyGDoN.js} +1 -1
  14. package/dist/assets/{SaveBar-Cd6hJR6K.js → SaveBar-Cnwc_XfF.js} +1 -1
  15. package/dist/assets/{Scheduler-BZXKqYJP.js → Scheduler-aACa6_mC.js} +7 -7
  16. package/dist/assets/{ScopeSwitcher-C24ysV1K.js → ScopeSwitcher-CoG3CSlC.js} +1 -1
  17. package/dist/assets/Settings-BG0RM6Di.js +4 -0
  18. package/dist/assets/{SkillReferenceGraph-BsWuiTbw.js → SkillReferenceGraph-COffGu_A.js} +1 -1
  19. package/dist/assets/Skills--qQpFjjf.js +2 -0
  20. package/dist/assets/SystemPrompt-Cr9RRSiZ.js +1 -0
  21. package/dist/assets/TagLibrary-D_ZbXwBv.js +1 -0
  22. package/dist/assets/{TiptapBody-C4kIvIMH.js → TiptapBody-CCHsa8Jv.js} +1 -1
  23. package/dist/assets/{Toggle-pP19zlyk.js → Toggle-BUOj4pws.js} +1 -1
  24. package/dist/assets/{ViewTabs-CpzN8e5I.js → ViewTabs-BdpsL7yr.js} +1 -1
  25. package/dist/assets/{historyTotals-Caq78bb5.js → historyTotals-Dx6ca881.js} +1 -1
  26. package/dist/assets/{index-Dd7UQabV.css → index-BnKaYERU.css} +1 -1
  27. package/dist/assets/{index-Bjtguv6I.js → index-CkNGj8FA.js} +151 -151
  28. package/dist/assets/{settingsSchema-CC2ySu3d.js → settingsSchema-BZhkpr9e.js} +1 -1
  29. package/dist/assets/{skillFrontmatter-hDhNo8jE.js → skillFrontmatter-N13KGqbs.js} +1 -1
  30. package/dist/assets/{useAgentsDirWatch-BuOtY25U.js → useAgentsDirWatch-De9UsbDt.js} +1 -1
  31. package/dist/index.html +2 -2
  32. package/package.json +1 -1
  33. package/plugins/session-manager-dev/skills/develop/SKILL.md +29 -24
  34. package/scripts/scheduler-mcp-server.cjs +142 -78
  35. package/src/main/agentLibrary.cjs +8 -3
  36. package/src/main/build-info.json +4 -4
  37. package/src/main/crashDiagnostics.cjs +24 -0
  38. package/src/main/historyAggregator.cjs +41 -7
  39. package/src/main/index.cjs +13 -3
  40. package/src/main/ipcSchemas.cjs +30 -22
  41. package/src/main/lib/activeSessions.cjs +93 -32
  42. package/src/main/lib/epic/delegationReadiness.cjs +2 -0
  43. package/src/main/lib/epic/delegationSelfHeal.cjs +77 -0
  44. package/src/main/lib/epic/epicMint.cjs +1 -1
  45. package/src/main/lib/epic/epicStandingInstructions.cjs +73 -0
  46. package/src/main/lib/epic/guardSpawnSettings.cjs +76 -0
  47. package/src/main/lib/feedback-remote/crossProjectFeedback.cjs +9 -2
  48. package/src/main/lib/feedback-remote/remoteClientSessions.cjs +3 -11
  49. package/src/main/lib/feedback-remote/remoteE2eCrypto.cjs +1 -1
  50. package/src/main/lib/git/gitWorktree.cjs +9 -4
  51. package/src/main/lib/git/worktreeDeps.cjs +13 -2
  52. package/src/main/lib/git/worktreeSetup.cjs +212 -0
  53. package/src/main/lib/mcpToolCatalog.cjs +36 -9
  54. package/src/main/lib/persona-macro/agentPersonaSchema.cjs +4 -0
  55. package/src/main/lib/persona-macro/shippedPersonaSeeds.cjs +23 -0
  56. package/src/main/lib/prd/prdAgentType.cjs +28 -0
  57. package/src/main/lib/prd/prdBodyPatch.cjs +138 -0
  58. package/src/main/lib/prd/prdCreate.cjs +245 -27
  59. package/src/main/lib/prd/prdGateFiles.cjs +31 -0
  60. package/src/main/lib/scheduler/definitionOfDone.cjs +24 -3
  61. package/src/main/lib/scheduler/queueStore.cjs +5 -4
  62. package/src/main/lib/scheduler/scheduleJobSchema.cjs +1 -0
  63. package/src/main/lib/scheduler/schedulerBatch.cjs +43 -5
  64. package/src/main/lib/scheduler/schedulerPaths.cjs +2 -0
  65. package/src/main/lib/scheduler/watchdogHelpers.cjs +114 -22
  66. package/src/main/lib/telemetry/mainHeapSnapshot.cjs +69 -0
  67. package/src/main/lib/telemetry/telemetryBoot.cjs +25 -3
  68. package/src/main/lib/telemetry/telemetryClient.cjs +12 -0
  69. package/src/main/lib/telemetry/telemetryCounters.cjs +25 -2
  70. package/src/main/pty.cjs +0 -53
  71. package/src/main/runVerify.cjs +38 -11
  72. package/src/main/scheduler/prdParser.cjs +3 -0
  73. package/src/main/scheduler/prdPaths.cjs +48 -2
  74. package/src/main/scheduler.cjs +135 -31
  75. package/src/main/seedDevPlugin.cjs +1 -1
  76. package/src/main/seedSchedulerMcp.cjs +1 -1
  77. package/src/main/templates/PRD_AUTHORING.md +8 -4
  78. package/src/main/webRemote.cjs +38 -132
  79. package/src/preload/api.d.ts +4 -52
  80. package/src/preload/index.cjs +0 -24
  81. package/src/seed/agents/dev-lead.md +2 -1
  82. package/src/seed/agents/validator.md +2 -1
  83. package/dist/assets/DataModel-DZHBZrfL.js +0 -1
  84. package/dist/assets/ListDetail-Cud72s-O.js +0 -1
  85. package/dist/assets/RemoteMachines-gOlFTvWq.js +0 -3
  86. package/dist/assets/Settings-DWnN2qxn.js +0 -4
  87. package/dist/assets/Skills-6pHn6glu.js +0 -2
  88. package/dist/assets/SystemPrompt-DT0LBH-K.js +0 -1
  89. package/dist/assets/TagLibrary-DbJ0zbYL.js +0 -1
  90. package/dist/assets/useRemotePeers-CNQmRBpt.js +0 -1
  91. package/src/main/lib/feedback-remote/relayClientAuth.cjs +0 -133
  92. package/src/main/remoteClient.cjs +0 -334
  93. package/src/main/remoteClientIpc.cjs +0 -133
package/src/main/pty.cjs CHANGED
@@ -111,44 +111,6 @@ class PtyManager {
111
111
  this.outBuffers = new Map();
112
112
  this.flushTimers = new Map(); // tabId -> Timeout
113
113
  this.window = null;
114
- this.outputListeners = new Map(); // tabId -> Set<{onData,onExit}>
115
- }
116
-
117
- /**
118
- * Observe a tab's coalesced output (the same string the renderer gets) and
119
- * its exit from the main process. Returns an unsubscribe function.
120
- * @param {string} tabId
121
- * @param {(tabId: string, chunk: string) => void} onData
122
- * @param {(tabId: string, info: {exitCode: number, signal?: number}) => void} [onExit]
123
- */
124
- addOutputListener(tabId, onData, onExit) {
125
- const entry = { onData, onExit };
126
- let set = this.outputListeners.get(tabId);
127
- if (!set) {
128
- set = new Set();
129
- this.outputListeners.set(tabId, set);
130
- }
131
- set.add(entry);
132
- return () => {
133
- const cur = this.outputListeners.get(tabId);
134
- if (!cur) return;
135
- cur.delete(entry);
136
- if (cur.size === 0) this.outputListeners.delete(tabId);
137
- };
138
- }
139
-
140
- /** Fire every onExit listener for `tabId` once (errors isolated), then drop them. */
141
- #notifyExit(tabId, info) {
142
- const set = this.outputListeners.get(tabId);
143
- this.outputListeners.delete(tabId);
144
- if (!set) return;
145
- for (const l of [...set]) {
146
- try {
147
- l.onExit?.(tabId, info);
148
- } catch (err) {
149
- console.warn('[pty] output listener onExit threw', err);
150
- }
151
- }
152
114
  }
153
115
 
154
116
  /** Send any pending buffered output for `tabId` now, and clear its timer. */
@@ -162,16 +124,6 @@ class PtyManager {
162
124
  if (pending) {
163
125
  this.outBuffers.delete(tabId);
164
126
  sendIfAlive(this.window, `pty:data:${tabId}`, pending);
165
- const set = this.outputListeners.get(tabId);
166
- if (set) {
167
- for (const l of [...set]) {
168
- try {
169
- l.onData?.(tabId, pending);
170
- } catch (err) {
171
- console.warn('[pty] output listener onData threw', err);
172
- }
173
- }
174
- }
175
127
  }
176
128
  }
177
129
 
@@ -376,7 +328,6 @@ class PtyManager {
376
328
  this.sessions.delete(tabId);
377
329
  this.buffers.delete(tabId);
378
330
  this.#dropOutput(tabId);
379
- this.#notifyExit(tabId, { exitCode, signal });
380
331
  return;
381
332
  }
382
333
  // Flush any still-buffered output BEFORE the exit event so the renderer
@@ -398,7 +349,6 @@ class PtyManager {
398
349
  });
399
350
  }
400
351
  sendIfAlive(this.window, `pty:exit:${tabId}`, { exitCode, signal });
401
- this.#notifyExit(tabId, { exitCode, signal });
402
352
  this.sessions.delete(tabId);
403
353
  this.buffers.delete(tabId);
404
354
  });
@@ -461,9 +411,6 @@ class PtyManager {
461
411
  this.sessions.delete(tabId);
462
412
  this.buffers.delete(tabId);
463
413
  this.#dropOutput(tabId);
464
- // Listeners learn the tab is gone now; the suppressed exit event that
465
- // follows finds none left, so each fires exactly once.
466
- this.#notifyExit(tabId, { exitCode: 0, signal: undefined });
467
414
  }
468
415
  }
469
416
 
@@ -21,7 +21,8 @@
21
21
  *
22
22
  * Downgrade policy:
23
23
  * clean → null (caller stamps 'completed')
24
- * halt → 'pending' (re-fires automatically next slot)
24
+ * halt → 'pending' (re-fires automatically next slot; only for
25
+ * a run that printed no SCHEDULER_VERDICT line)
25
26
  * deps_unmet → 'pending' (re-fires when deps clear)
26
27
  * transcript_errors → historical rows only; no longer emitted
27
28
  * verify_unavailable → 'needs_review' (unreadable log / verifier threw)
@@ -297,6 +298,30 @@ function scanSentinel(resultEvent, events) {
297
298
  return null;
298
299
  }
299
300
 
301
+ /**
302
+ * First line that starts at column 0 with the exact uppercase halt marker
303
+ * (`HALT:`) outside a fenced block, else null. Line-anchored and fence-aware
304
+ * because reports quote the marker in prose and paste tool output in fences,
305
+ * and PRD_AUTHORING.md §4/§9/§10 tell scripts to print it on failure — neither
306
+ * is the executor's own stop signal.
307
+ * @param {unknown} text
308
+ * @returns {string | null}
309
+ */
310
+ function scanHaltLine(text) {
311
+ if (typeof text !== 'string') return null;
312
+ let inFence = false;
313
+ for (const raw of text.split('\n')) {
314
+ const line = raw.replace(/\r$/, '').trimEnd();
315
+ const t = line.trimStart();
316
+ if (t.startsWith('```') || t.startsWith('~~~')) {
317
+ inFence = !inFence;
318
+ continue;
319
+ }
320
+ if (!inFence && line.startsWith('HALT:')) return line;
321
+ }
322
+ return null;
323
+ }
324
+
300
325
  /**
301
326
  * One-line reason after `SCHEDULER_VERDICT: FAIL` (same two-source scan order
302
327
  * as scanSentinel). Trimmed, capped at 300 chars; '' when absent.
@@ -742,13 +767,17 @@ async function verifyRun({
742
767
  else if (commitEvidence) commitEvidenceSource = 'transcript';
743
768
  }
744
769
 
745
- // ── 3. HALT detection ─────────────────────────────────────────────────
746
- // Primary: check the final `{"type":"result"}` event's `result` text.
747
- if (resultEvent) {
748
- const rt = resultEvent.resultText;
749
- if (/\bHALT:/i.test(rt) || /^HALT\b/m.test(rt)) {
750
- const firstLine = rt.split('\n')[0].slice(0, 200);
751
- let reason = `Agent HALTed: ${firstLine}`;
770
+ // ── 3. HALT detection (fallback only) ─────────────────────────────────
771
+ // The SCHEDULER_VERDICT line is the executor's final say (FINISH_PROTOCOL
772
+ // VERDICT LINE step); the halt check is a fallback for runs that printed
773
+ // none. Incident: Rabbits-Game 163-attack-scorecard, 2026-10-24 — a PASS
774
+ // report quoting the marker in backticks was re-queued as a halt.
775
+ const sentinel = scanSentinel(resultEvent, events);
776
+ if (resultEvent && sentinel === null) {
777
+ const haltLine = scanHaltLine(resultEvent.resultText);
778
+ if (haltLine) {
779
+ const rt = resultEvent.resultText;
780
+ let reason = `Agent HALTed: ${haltLine.slice(0, 200)}`;
752
781
  // Embed machine-parseable floor date if present in HALT message.
753
782
  const dateMatch = rt.match(/~?(\d{4}-\d{2}-\d{2})/);
754
783
  if (dateMatch) reason += ` (eligible from: ${dateMatch[1]})`;
@@ -773,9 +802,6 @@ async function verifyRun({
773
802
  }
774
803
  }
775
804
 
776
- // Scan for the SCHEDULER_VERDICT sentinel emitted by the finish protocol.
777
- const sentinel = scanSentinel(resultEvent, events);
778
-
779
805
  // An explicit executor FAIL is always blocking — outranks every other
780
806
  // verdict and every override below (early return). Transcript issues are
781
807
  // kept as annotations so nothing is lost.
@@ -1022,6 +1048,7 @@ module.exports = {
1022
1048
  checkDeps,
1023
1049
  parseLog,
1024
1050
  scanSentinel,
1051
+ scanHaltLine,
1025
1052
  scanSentinelReason,
1026
1053
  scanHumanQuestion,
1027
1054
  scanForeignWipPathsClaim,
@@ -19,6 +19,7 @@ const os = require('node:os');
19
19
  const path = require('node:path');
20
20
  const { splitFrontmatter } = require('../lib/prd/prdFrontmatter.cjs');
21
21
  const { deriveEpicIdFromPrdPath } = require('../lib/prd/prdLocations.cjs');
22
+ const { parseFilesSection } = require('../lib/prd/prdGateFiles.cjs');
22
23
  const { reportDanglingAgentTypeOnce } = require('../lib/prd/prdAgentType.cjs');
23
24
 
24
25
  /**
@@ -100,6 +101,8 @@ async function parsePrdRaw(filePath) {
100
101
  // queue row is completed (a slug with no row is treated as already
101
102
  // done/archived, matching retireCompletedSlugs semantics).
102
103
  dependsOn: parseDependsOn(fm.dependsOn),
104
+ // Declared touch-list from the body's `# Files` section ([] when absent).
105
+ files: parseFilesSection(body),
103
106
  // Provenance stamp (PRD-authoring lockdown): set only by prdCreate.cjs's
104
107
  // buildPrdBody (create) or the update-prd route's legacy-adopt patch
105
108
  // (migration/manual adopt). A PRD discovered on disk with no value here
@@ -16,6 +16,7 @@ const { DEFAULT_PROJECT_CWD } = require('../lib/scheduler/schedulerBatch.cjs');
16
16
  const { resolvePrdsDirs, resolveArchivedPrdsDirs, resolvePrdWriteDir, listEpicPrdDirs, resolveEpicPrdWriteDir, isSafeEpicId, listArchivedPrdDirs, ancestorEpicPrdDirs, ancestorEpicArchivedPrdDirs } = require('../lib/prd/prdLocations.cjs');
17
17
  const { migratePrds, consolidateFlatPrds, legacyAdoptExistingPrds } = require('../lib/prd/prdMigration.cjs');
18
18
  const { opsPath } = require('../lib/opsOwnership.cjs');
19
+ const { bareSlug, resolveDepSlug } = require('../lib/prd/depSlugResolve.cjs');
19
20
  const { allProjectCwds, projectRootOf } = require('../lib/activeSessions.cjs');
20
21
 
21
22
  /**
@@ -268,6 +269,50 @@ async function safeSlugPath(slug) {
268
269
  return module.exports.safeSlugPathIn(dir, slug);
269
270
  }
270
271
 
272
+ /**
273
+ * Resolve a BARE slug (no `NN-` prefix) to the unique NN-prefixed PRD file —
274
+ * for a caller whose create response was lost and never learned the NN.
275
+ * Scans the live PRD dirs, the archive dirs, and one level of
276
+ * `prds-archived/<ts>/`, matching with depSlugResolve's rule. `cwd` narrows to
277
+ * one project; omitted, it searches every candidate dir. Returns
278
+ * `{ ok: true, path, dir }`, `{ ok: false, reason: 'not-found' }`, or
279
+ * `{ ok: false, reason: 'ambiguous', files, error }` (never guesses).
280
+ */
281
+ async function resolveBareSlugFile(slug, cwd) {
282
+ if (typeof slug !== 'string' || !slug || bareSlug(slug) !== slug) return { ok: false, reason: 'not-found' };
283
+ const live = cwd ? [module.exports.prdDirForCwd(cwd), ...listEpicPrdDirs(cwd)] : module.exports.candidatePrdsDirs();
284
+ const archived = cwd ? listArchivedPrdDirs(cwd) : module.exports.candidateArchivedPrdsDirs();
285
+ const dirs = [...live];
286
+ for (const a of archived) {
287
+ dirs.push(a);
288
+ const subs = await fsp.readdir(a, { withFileTypes: true }).catch(() => []);
289
+ for (const ent of subs) if (ent.isDirectory()) dirs.push(path.join(a, ent.name));
290
+ }
291
+ const found = []; // { slug, dir, file }
292
+ const seen = new Set();
293
+ for (const dir of dirs) {
294
+ const names = await fsp.readdir(dir).catch(() => []);
295
+ for (const n of names) {
296
+ if (!n.endsWith('.md')) continue;
297
+ const file = path.join(dir, n);
298
+ if (seen.has(file)) continue;
299
+ seen.add(file);
300
+ found.push({ slug: n.slice(0, -3), dir, file });
301
+ }
302
+ }
303
+ const matched = new Set(resolveDepSlug(slug, found.map((f) => f.slug)));
304
+ const hits = found.filter((f) => matched.has(f.slug));
305
+ if (hits.length === 0) return { ok: false, reason: 'not-found' };
306
+ if (hits.length > 1) {
307
+ const files = hits.map((h) => h.file);
308
+ return { ok: false, reason: 'ambiguous', files, error: `ambiguous slug "${slug}": matches ${files.join(' and ')} — use the full NN-prefixed slug` };
309
+ }
310
+ const only = hits[0];
311
+ const safe = module.exports.safeSlugPathIn(only.dir, only.slug);
312
+ if (!safe) return { ok: false, reason: 'not-found' };
313
+ return { ok: true, path: safe, dir: only.dir };
314
+ }
315
+
271
316
  /**
272
317
  * The two distinct failure modes safeSlugPath collapses into one nullable
273
318
  * return (the defect this fixes — see the PRD that added this helper's
@@ -291,10 +336,10 @@ async function resolveSlugOrReason(slug, cwd) {
291
336
  return { ok: true, path: p };
292
337
  } catch { /* not in this dir — try the next candidate */ }
293
338
  }
294
- return { ok: false, reason: 'not-found' };
339
+ return module.exports.resolveBareSlugFile(slug, cwd);
295
340
  }
296
341
  const dir = await module.exports.findPrdDir(slug);
297
- if (!dir) return { ok: false, reason: 'not-found' };
342
+ if (!dir) return module.exports.resolveBareSlugFile(slug, cwd);
298
343
  const p = module.exports.safeSlugPathIn(dir, slug);
299
344
  if (!p) return { ok: false, reason: 'not-found' };
300
345
  return { ok: true, path: p };
@@ -522,6 +567,7 @@ module.exports = {
522
567
  safeSlugPathIn,
523
568
  realPrdsDir,
524
569
  safeSlugPath,
570
+ resolveBareSlugFile,
525
571
  resolveSlugOrReason,
526
572
  jobMatchesSlugAndCwd,
527
573
  unknownSlugMessage,