claude-code-session-manager 0.111.0 → 0.112.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 (282) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/dist/assets/{AgentLibrary-rBO1daqM.js → AgentLibrary-RwPvEgqm.js} +2 -2
  3. package/dist/assets/{Button-DsEYRZg0.js → Button-36j3PzYv.js} +1 -1
  4. package/dist/assets/{DataModel-D8sbvvBC.js → DataModel-DUhANo4l.js} +1 -1
  5. package/dist/assets/{History-BEHLtxia.js → History-BeZzNjmv.js} +2 -2
  6. package/dist/assets/{Hooks-CKpvlXrg.js → Hooks-iQ8845Hp.js} +3 -3
  7. package/dist/assets/{Library-CeF4qh9d.js → Library-DPE1h-1L.js} +6 -6
  8. package/dist/assets/{ListDetail-DcfmxPFk.js → ListDetail-PStOuQAo.js} +1 -1
  9. package/dist/assets/{MarkdownEditor-CvK1pyto.js → MarkdownEditor-DPw-N2-m.js} +1 -1
  10. package/dist/assets/{McpServers-D-h2ihzJ.js → McpServers-CUyRTNep.js} +2 -2
  11. package/dist/assets/{Memory-BnF89x8v.js → Memory-bZ2xjBGy.js} +3 -3
  12. package/dist/assets/{Panel-CQY5zano.js → Panel-_VZ_uXNg.js} +1 -1
  13. package/dist/assets/{Permissions-DLukmmsz.js → Permissions-PPRmfNbK.js} +3 -3
  14. package/dist/assets/{Plugins-0Pf0OZ4l.js → Plugins-BFcvfvlx.js} +2 -2
  15. package/dist/assets/{ProvenanceBadge-vC7Tj-JP.js → ProvenanceBadge-B1WUknak.js} +1 -1
  16. package/dist/assets/RemoteMachines-D5V0lzgW.js +3 -0
  17. package/dist/assets/{SaveBar-DjijiUb0.js → SaveBar-Dw64FVdM.js} +1 -1
  18. package/dist/assets/{Scheduler-Cm3EXZvE.js → Scheduler-C8s_pJ3I.js} +9 -9
  19. package/dist/assets/{ScopeSwitcher-B-P-kSfq.js → ScopeSwitcher-D-nKDMAE.js} +1 -1
  20. package/dist/assets/{Settings-DYDlp2m_.js → Settings-CQSrR4mO.js} +4 -4
  21. package/dist/assets/{SkillReferenceGraph-Epv2GJmj.js → SkillReferenceGraph-BbZFMHim.js} +1 -1
  22. package/dist/assets/{Skills-DHO0N0C2.js → Skills-Bzyrh6EQ.js} +1 -1
  23. package/dist/assets/SystemPrompt-DP6i3Dx0.js +1 -0
  24. package/dist/assets/TagLibrary-iip0C6Bl.js +1 -0
  25. package/dist/assets/{TiptapBody-DAMO3DhO.js → TiptapBody-Cr-hxX8L.js} +1 -1
  26. package/dist/assets/Toggle-7WpPzcZH.js +1 -0
  27. package/dist/assets/{ViewTabs-CGX6MAhc.js → ViewTabs-9lQCRwWJ.js} +1 -1
  28. package/dist/assets/{historyTotals-vgfk8EOL.js → historyTotals-BrFxw5J1.js} +1 -1
  29. package/dist/assets/{index-CPieAFsl.js → index-CTBpf-26.js} +250 -250
  30. package/dist/assets/{settingsSchema-D0FxNrTy.js → settingsSchema-Dh5Kl7VO.js} +1 -1
  31. package/dist/assets/{useAgentsDirWatch-DCu6BNYN.js → useAgentsDirWatch-CMpx0d04.js} +1 -1
  32. package/dist/assets/{useRemotePeers-D4cdJDyh.js → useRemotePeers-CI2axd-L.js} +1 -1
  33. package/dist/index.html +1 -1
  34. package/package.json +3 -2
  35. package/plugins/CLAUDE.md +5 -8
  36. package/plugins/session-manager-dev/.claude-plugin/plugin.json +3 -6
  37. package/plugins/session-manager-dev/skills/builder/1-classify-and-bump/SKILL.md +2 -2
  38. package/plugins/session-manager-dev/skills/builder/SKILL.md +2 -3
  39. package/plugins/session-manager-dev/skills/develop/SKILL.md +1 -1
  40. package/plugins/session-manager-dev/skills/develop/standards.md +3 -3
  41. package/scripts/README.md +3 -3
  42. package/scripts/audit-ops-hygiene.cjs +4 -4
  43. package/scripts/hooks/guard-destructive-git.cjs +4 -4
  44. package/scripts/hooks/guard-inline-implementation.cjs +1 -1
  45. package/scripts/hooks/guard-prd-writes.cjs +2 -2
  46. package/scripts/hooks/lib/guard-destructive-git-policy.cjs +1 -1
  47. package/scripts/mint-epic.cjs +2 -2
  48. package/scripts/scheduler-mcp-server.cjs +4 -4
  49. package/src/main/agentLibrary.cjs +5 -5
  50. package/src/main/agentsIpc.cjs +76 -0
  51. package/src/main/build-info.json +4 -4
  52. package/src/main/chatRunner.cjs +12 -12
  53. package/src/main/config.cjs +2 -2
  54. package/src/main/crashDiagnostics.cjs +2 -2
  55. package/src/main/docEdit.cjs +5 -5
  56. package/src/main/files.cjs +2 -2
  57. package/src/main/git.cjs +1 -1
  58. package/src/main/health.cjs +20 -18
  59. package/src/main/heapSnapshot.cjs +1 -1
  60. package/src/main/historyAggregator.cjs +2 -2
  61. package/src/main/index.cjs +44 -132
  62. package/src/main/ipcSchemas.cjs +10 -10
  63. package/src/main/lib/CLAUDE.md +48 -0
  64. package/src/main/lib/activeSessions.cjs +1 -1
  65. package/src/main/lib/classifyPromptTicket.cjs +2 -2
  66. package/src/main/lib/{agentModelResolve.cjs → claude/agentModelResolve.cjs} +7 -7
  67. package/src/main/lib/{claudeBin.cjs → claude/claudeBin.cjs} +4 -4
  68. package/src/main/lib/{effectiveModelInfo.cjs → claude/effectiveModelInfo.cjs} +9 -9
  69. package/src/main/lib/{modelCatalog.cjs → claude/modelCatalog.cjs} +3 -3
  70. package/src/main/lib/{rateLimitDetect.cjs → claude/rateLimitDetect.cjs} +1 -1
  71. package/src/main/lib/{rateLimitWindow.cjs → claude/rateLimitWindow.cjs} +1 -1
  72. package/src/main/lib/{runClaudeP.cjs → claude/runClaudeP.cjs} +1 -1
  73. package/src/main/lib/credentials.cjs +3 -3
  74. package/src/main/lib/cwdClassify.cjs +1 -1
  75. package/src/main/lib/{activeIndexMerge.cjs → epic/activeIndexMerge.cjs} +3 -3
  76. package/src/main/lib/{activeIndexRebuild.cjs → epic/activeIndexRebuild.cjs} +1 -1
  77. package/src/main/lib/{delegationReadiness.cjs → epic/delegationReadiness.cjs} +21 -29
  78. package/src/main/lib/{epicContextDigest.cjs → epic/epicContextDigest.cjs} +1 -1
  79. package/src/main/lib/{epicDelegationStats.cjs → epic/epicDelegationStats.cjs} +2 -2
  80. package/src/main/lib/{epicMint.cjs → epic/epicMint.cjs} +11 -11
  81. package/src/main/lib/{epicSpawnPlan.cjs → epic/epicSpawnPlan.cjs} +3 -3
  82. package/src/main/lib/{epicStatusMirror.cjs → epic/epicStatusMirror.cjs} +2 -2
  83. package/src/main/lib/{epicTranscriptDiagnostic.cjs → epic/epicTranscriptDiagnostic.cjs} +2 -2
  84. package/src/main/lib/{epicTranscriptPath.cjs → epic/epicTranscriptPath.cjs} +2 -2
  85. package/src/main/lib/{epicValidationHook.cjs → epic/epicValidationHook.cjs} +3 -3
  86. package/src/main/lib/{epicWorktreeBoot.cjs → epic/epicWorktreeBoot.cjs} +1 -1
  87. package/src/main/lib/{epicWorktreeMerge.cjs → epic/epicWorktreeMerge.cjs} +3 -3
  88. package/src/main/lib/{epicWorktreeMint.cjs → epic/epicWorktreeMint.cjs} +3 -3
  89. package/src/main/lib/{epicWorktreeProjectConfig.cjs → epic/epicWorktreeProjectConfig.cjs} +4 -4
  90. package/src/main/lib/{promptSessionsCreateEpic.cjs → epic/promptSessionsCreateEpic.cjs} +4 -4
  91. package/src/main/lib/{crossProjectFeedback.cjs → feedback-remote/crossProjectFeedback.cjs} +7 -7
  92. package/src/main/lib/{customerFeedbackClient.cjs → feedback-remote/customerFeedbackClient.cjs} +3 -3
  93. package/src/main/lib/{customerFeedbackInbox.cjs → feedback-remote/customerFeedbackInbox.cjs} +2 -2
  94. package/src/main/lib/{customerFeedbackIpc.cjs → feedback-remote/customerFeedbackIpc.cjs} +1 -1
  95. package/src/main/lib/{localAdminHttp.cjs → feedback-remote/localAdminHttp.cjs} +2 -2
  96. package/src/main/lib/{macroAdminRoutes.cjs → feedback-remote/macroAdminRoutes.cjs} +1 -1
  97. package/src/main/lib/{projectHomeAdminRoutes.cjs → feedback-remote/projectHomeAdminRoutes.cjs} +4 -4
  98. package/src/main/lib/{relayClientAuth.cjs → feedback-remote/relayClientAuth.cjs} +2 -2
  99. package/src/main/lib/{remoteClientSessions.cjs → feedback-remote/remoteClientSessions.cjs} +1 -1
  100. package/src/main/lib/{gitWorktree.cjs → git/gitWorktree.cjs} +7 -7
  101. package/src/main/lib/historyRollup.cjs +1 -1
  102. package/src/main/lib/importReferences.cjs +1 -1
  103. package/src/main/lib/machineProfile.cjs +1 -1
  104. package/src/main/lib/openExternalApp.cjs +1 -1
  105. package/src/main/lib/opsOwnership.cjs +3 -3
  106. package/src/main/lib/{agentPersonaSchema.cjs → persona-macro/agentPersonaSchema.cjs} +2 -2
  107. package/src/main/lib/{macroLibrary.cjs → persona-macro/macroLibrary.cjs} +5 -5
  108. package/src/main/lib/{personaMerge.cjs → persona-macro/personaMerge.cjs} +4 -4
  109. package/src/main/lib/{prdAdminRoutes.cjs → prd/prdAdminRoutes.cjs} +7 -7
  110. package/src/main/lib/{prdAgentType.cjs → prd/prdAgentType.cjs} +3 -3
  111. package/src/main/lib/{prdCreate.cjs → prd/prdCreate.cjs} +12 -12
  112. package/src/main/lib/{prdDeclaredPaths.cjs → prd/prdDeclaredPaths.cjs} +1 -1
  113. package/src/main/lib/{prdGateFiles.cjs → prd/prdGateFiles.cjs} +1 -1
  114. package/src/main/lib/{prdLocations.cjs → prd/prdLocations.cjs} +2 -2
  115. package/src/main/lib/{prdMigration.cjs → prd/prdMigration.cjs} +3 -3
  116. package/src/main/lib/prereqs.cjs +2 -2
  117. package/src/main/lib/{instanceLock.cjs → process/instanceLock.cjs} +4 -11
  118. package/src/main/lib/{pidAlive.cjs → process/pidAlive.cjs} +1 -1
  119. package/src/main/lib/{procName.cjs → process/procName.cjs} +2 -2
  120. package/src/main/lib/{timeoutShim.cjs → process/timeoutShim.cjs} +1 -1
  121. package/src/main/lib/projectRootResolve.cjs +1 -1
  122. package/src/main/lib/promptSessionSchema.cjs +1 -1
  123. package/src/main/lib/{definitionOfDone.cjs → scheduler/definitionOfDone.cjs} +6 -12
  124. package/src/main/lib/{fixChainDepth.cjs → scheduler/fixChainDepth.cjs} +1 -1
  125. package/src/main/lib/{jobDirtFilter.cjs → scheduler/jobDirtFilter.cjs} +1 -1
  126. package/src/main/lib/{jobSupervisorRecord.cjs → scheduler/jobSupervisorRecord.cjs} +1 -1
  127. package/src/main/lib/{launchFailure.cjs → scheduler/launchFailure.cjs} +2 -2
  128. package/src/main/lib/{queueStore.cjs → scheduler/queueStore.cjs} +6 -6
  129. package/src/main/lib/{quietMachineLease.cjs → scheduler/quietMachineLease.cjs} +1 -1
  130. package/src/main/lib/{rcaReport.cjs → scheduler/rcaReport.cjs} +4 -4
  131. package/src/main/lib/{reaperHelpers.cjs → scheduler/reaperHelpers.cjs} +3 -3
  132. package/src/main/lib/{reservationExpiry.cjs → scheduler/reservationExpiry.cjs} +4 -11
  133. package/src/main/lib/{reviewNotice.cjs → scheduler/reviewNotice.cjs} +1 -1
  134. package/src/main/lib/{scheduleJobTransitions.cjs → scheduler/scheduleJobTransitions.cjs} +3 -3
  135. package/src/main/lib/{schedulerBatch.cjs → scheduler/schedulerBatch.cjs} +2 -2
  136. package/src/main/lib/{schedulerConfig.cjs → scheduler/schedulerConfig.cjs} +1 -1
  137. package/src/main/lib/{schedulerRuntimeState.cjs → scheduler/schedulerRuntimeState.cjs} +1 -1
  138. package/src/main/lib/{sessionSlots.cjs → scheduler/sessionSlots.cjs} +2 -2
  139. package/src/main/lib/{upgradeDrain.cjs → scheduler/upgradeDrain.cjs} +8 -11
  140. package/src/main/lib/{watchdogHelpers.cjs → scheduler/watchdogHelpers.cjs} +5 -19
  141. package/src/main/lib/{auditLog.cjs → telemetry/auditLog.cjs} +1 -1
  142. package/src/main/lib/{opsErrorLog.cjs → telemetry/opsErrorLog.cjs} +4 -4
  143. package/src/main/lib/{telemetryBacklog.cjs → telemetry/telemetryBacklog.cjs} +4 -4
  144. package/src/main/lib/{telemetryBoot.cjs → telemetry/telemetryBoot.cjs} +1 -1
  145. package/src/main/lib/{telemetryClient.cjs → telemetry/telemetryClient.cjs} +4 -4
  146. package/src/main/lib/{telemetrySettings.cjs → telemetry/telemetrySettings.cjs} +1 -1
  147. package/src/main/logs.cjs +1 -1
  148. package/src/main/mcpStatus.cjs +2 -2
  149. package/src/main/memoryAggregate.cjs +3 -3
  150. package/src/main/memoryTool.cjs +1 -1
  151. package/src/main/otel.cjs +2 -2
  152. package/src/main/pluginInstall.cjs +29 -3
  153. package/src/main/projectBrief.cjs +6 -6
  154. package/src/main/projectPages.cjs +1 -1
  155. package/src/main/promptSessionEvents.cjs +2 -2
  156. package/src/main/pty.cjs +7 -7
  157. package/src/main/queueOps.cjs +6 -6
  158. package/src/main/remoteClient.cjs +4 -4
  159. package/src/main/remoteClientIpc.cjs +1 -1
  160. package/src/main/runVerify.cjs +1 -1
  161. package/src/main/scheduler/CLAUDE.md +26 -0
  162. package/src/main/scheduler/budget.cjs +576 -0
  163. package/src/main/scheduler/gitTreeGuard.cjs +672 -0
  164. package/src/main/scheduler/prdParser.cjs +4 -4
  165. package/src/main/scheduler/prdPaths.cjs +487 -0
  166. package/src/main/scheduler/reviewLadder.cjs +1011 -0
  167. package/src/main/scheduler/starvation.cjs +390 -0
  168. package/src/main/scheduler.cjs +289 -3311
  169. package/src/main/seedAgentPersonas.cjs +5 -5
  170. package/src/main/seedDevPlugin.cjs +70 -3
  171. package/src/main/seedSchedulerMcp.cjs +2 -2
  172. package/src/main/supervisor.cjs +5 -5
  173. package/src/main/telemetryIpc.cjs +51 -0
  174. package/src/main/transcripts.cjs +3 -3
  175. package/src/main/updaterIpc.cjs +1 -1
  176. package/src/main/usage.cjs +1 -1
  177. package/src/main/watchers.cjs +1 -1
  178. package/src/main/webRemote.cjs +7 -7
  179. package/src/preload/api.d.ts +8 -8
  180. package/src/preload/index.cjs +3 -3
  181. package/dist/assets/RemoteMachines-CWnKbFHc.js +0 -3
  182. package/dist/assets/SystemPrompt-DxeNofL9.js +0 -1
  183. package/dist/assets/TagLibrary-QOAs7ISO.js +0 -1
  184. package/dist/assets/Toggle-Ba_f7q_m.js +0 -1
  185. package/plugins/session-manager-dev/skills/blog-for-project-feature/0-select/SKILL.md +0 -39
  186. package/plugins/session-manager-dev/skills/blog-for-project-feature/1-research/SKILL.md +0 -37
  187. package/plugins/session-manager-dev/skills/blog-for-project-feature/2-storyboard/SKILL.md +0 -64
  188. package/plugins/session-manager-dev/skills/blog-for-project-feature/3-capture/SKILL.md +0 -52
  189. package/plugins/session-manager-dev/skills/blog-for-project-feature/4-draft-copy/SKILL.md +0 -37
  190. package/plugins/session-manager-dev/skills/blog-for-project-feature/5-illustrate/SKILL.md +0 -50
  191. package/plugins/session-manager-dev/skills/blog-for-project-feature/6-compose/SKILL.md +0 -51
  192. package/plugins/session-manager-dev/skills/blog-for-project-feature/7-review/SKILL.md +0 -54
  193. package/plugins/session-manager-dev/skills/blog-for-project-feature/SKILL.md +0 -144
  194. package/plugins/session-manager-dev/skills/blog-for-project-feature/feature.config.yaml +0 -90
  195. package/plugins/session-manager-dev/skills/discover-features/SKILL.md +0 -95
  196. package/plugins/session-manager-dev/skills/explain-to-me/SKILL.md +0 -205
  197. package/plugins/session-manager-dev/skills/explain-to-me/assets/style-reference.html +0 -163
  198. package/plugins/session-manager-dev/skills/find-opportunity/SKILL.md +0 -83
  199. package/plugins/session-manager-dev/skills/issue-address/0-select/0-fetch-pool/SKILL.md +0 -38
  200. package/plugins/session-manager-dev/skills/issue-address/0-select/1-reject-fixed/SKILL.md +0 -64
  201. package/plugins/session-manager-dev/skills/issue-address/0-select/2-reject-claimed/SKILL.md +0 -71
  202. package/plugins/session-manager-dev/skills/issue-address/0-select/3-rank-impact/SKILL.md +0 -39
  203. package/plugins/session-manager-dev/skills/issue-address/0-select/SKILL.md +0 -75
  204. package/plugins/session-manager-dev/skills/issue-address/1-confirm-open/SKILL.md +0 -39
  205. package/plugins/session-manager-dev/skills/issue-address/2-claim/SKILL.md +0 -57
  206. package/plugins/session-manager-dev/skills/issue-address/3-reproduce/SKILL.md +0 -40
  207. package/plugins/session-manager-dev/skills/issue-address/4-fix/SKILL.md +0 -33
  208. package/plugins/session-manager-dev/skills/issue-address/5-verify/SKILL.md +0 -40
  209. package/plugins/session-manager-dev/skills/issue-address/SKILL.md +0 -120
  210. package/plugins/session-manager-dev/skills/local-project-health/SKILL.md +0 -58
  211. package/plugins/session-manager-dev/skills/memory-sanitation/SKILL.md +0 -147
  212. package/plugins/session-manager-dev/skills/ops-sweep/SKILL.md +0 -137
  213. package/plugins/session-manager-dev/skills/pr-review-sweep/0-fetch/SKILL.md +0 -41
  214. package/plugins/session-manager-dev/skills/pr-review-sweep/1-classify/SKILL.md +0 -56
  215. package/plugins/session-manager-dev/skills/pr-review-sweep/2-check-fixed/SKILL.md +0 -49
  216. package/plugins/session-manager-dev/skills/pr-review-sweep/3-queue/SKILL.md +0 -57
  217. package/plugins/session-manager-dev/skills/pr-review-sweep/4-land-and-resolve/SKILL.md +0 -60
  218. package/plugins/session-manager-dev/skills/pr-review-sweep/SKILL.md +0 -124
  219. package/plugins/session-manager-dev/skills/pr-signal/SKILL.md +0 -67
  220. package/plugins/session-manager-dev/skills/project-status/SKILL.md +0 -243
  221. package/plugins/session-manager-dev/skills/requesting-code-review/SKILL.md +0 -98
  222. package/plugins/session-manager-dev/skills/requesting-code-review/code-reviewer.md +0 -146
  223. /package/src/main/lib/{agentEffortResolve.cjs → claude/agentEffortResolve.cjs} +0 -0
  224. /package/src/main/lib/{claudeCliCaps.cjs → claude/claudeCliCaps.cjs} +0 -0
  225. /package/src/main/lib/{usageCircuit.cjs → claude/usageCircuit.cjs} +0 -0
  226. /package/src/main/lib/{epicSpawnCwd.cjs → epic/epicSpawnCwd.cjs} +0 -0
  227. /package/src/main/lib/{customerFeedbackAdminRoutes.cjs → feedback-remote/customerFeedbackAdminRoutes.cjs} +0 -0
  228. /package/src/main/lib/{remoteE2eCrypto.cjs → feedback-remote/remoteE2eCrypto.cjs} +0 -0
  229. /package/src/main/lib/{branchSweep.cjs → git/branchSweep.cjs} +0 -0
  230. /package/src/main/lib/{gitExec.cjs → git/gitExec.cjs} +0 -0
  231. /package/src/main/lib/{jobWorktree.cjs → git/jobWorktree.cjs} +0 -0
  232. /package/src/main/lib/{jobWorktreeBootLive.cjs → git/jobWorktreeBootLive.cjs} +0 -0
  233. /package/src/main/lib/{jobWorktreeTerminalOrphanLive.cjs → git/jobWorktreeTerminalOrphanLive.cjs} +0 -0
  234. /package/src/main/lib/{builtinMacros.cjs → persona-macro/builtinMacros.cjs} +0 -0
  235. /package/src/main/lib/{personaImportHealth.cjs → persona-macro/personaImportHealth.cjs} +0 -0
  236. /package/src/main/lib/{shippedPersonaSeeds.cjs → persona-macro/shippedPersonaSeeds.cjs} +0 -0
  237. /package/src/main/lib/{depSlugResolve.cjs → prd/depSlugResolve.cjs} +0 -0
  238. /package/src/main/lib/{planValidator.cjs → prd/planValidator.cjs} +0 -0
  239. /package/src/main/lib/{prdAuthoringSeed.cjs → prd/prdAuthoringSeed.cjs} +0 -0
  240. /package/src/main/lib/{prdDisposition.cjs → prd/prdDisposition.cjs} +0 -0
  241. /package/src/main/lib/{prdFrontmatter.cjs → prd/prdFrontmatter.cjs} +0 -0
  242. /package/src/main/lib/{prdSizing.cjs → prd/prdSizing.cjs} +0 -0
  243. /package/src/main/lib/{workTypeLibrary.cjs → prd/workTypeLibrary.cjs} +0 -0
  244. /package/src/main/lib/{childWithLog.cjs → process/childWithLog.cjs} +0 -0
  245. /package/src/main/lib/{cleanEnv.cjs → process/cleanEnv.cjs} +0 -0
  246. /package/src/main/lib/{defaultShell.cjs → process/defaultShell.cjs} +0 -0
  247. /package/src/main/lib/{killTree.cjs → process/killTree.cjs} +0 -0
  248. /package/src/main/lib/{loginShellPath.cjs → process/loginShellPath.cjs} +0 -0
  249. /package/src/main/lib/{procIdentity.cjs → process/procIdentity.cjs} +0 -0
  250. /package/src/main/lib/{singleInstanceGuard.cjs → process/singleInstanceGuard.cjs} +0 -0
  251. /package/src/main/lib/{smProcNames.cjs → process/smProcNames.cjs} +0 -0
  252. /package/src/main/lib/{timeoutShimScript.cjs → process/timeoutShimScript.cjs} +0 -0
  253. /package/src/main/lib/{winSpawn.cjs → process/winSpawn.cjs} +0 -0
  254. /package/src/main/lib/{adoptedRunSupervisor.cjs → scheduler/adoptedRunSupervisor.cjs} +0 -0
  255. /package/src/main/lib/{dispatchLoop.cjs → scheduler/dispatchLoop.cjs} +0 -0
  256. /package/src/main/lib/{dodDrainHook.cjs → scheduler/dodDrainHook.cjs} +0 -0
  257. /package/src/main/lib/{fixPlanSlug.cjs → scheduler/fixPlanSlug.cjs} +0 -0
  258. /package/src/main/lib/{gateAuthority.cjs → scheduler/gateAuthority.cjs} +0 -0
  259. /package/src/main/lib/{landedSinceRun.cjs → scheduler/landedSinceRun.cjs} +0 -0
  260. /package/src/main/lib/{loadGate.cjs → scheduler/loadGate.cjs} +0 -0
  261. /package/src/main/lib/{needsReviewLedger.cjs → scheduler/needsReviewLedger.cjs} +0 -0
  262. /package/src/main/lib/{queueHealth.cjs → scheduler/queueHealth.cjs} +0 -0
  263. /package/src/main/lib/{queueHistory.cjs → scheduler/queueHistory.cjs} +0 -0
  264. /package/src/main/lib/{runLogRetention.cjs → scheduler/runLogRetention.cjs} +0 -0
  265. /package/src/main/lib/{scheduleJobSchema.cjs → scheduler/scheduleJobSchema.cjs} +0 -0
  266. /package/src/main/lib/{schedulerPaths.cjs → scheduler/schedulerPaths.cjs} +0 -0
  267. /package/src/main/lib/{terminalRunOutcome.cjs → scheduler/terminalRunOutcome.cjs} +0 -0
  268. /package/src/main/lib/{validationSentinels.cjs → scheduler/validationSentinels.cjs} +0 -0
  269. /package/src/main/lib/{crashTelemetry.cjs → telemetry/crashTelemetry.cjs} +0 -0
  270. /package/src/main/lib/{otlpTraceExporter.cjs → telemetry/otlpTraceExporter.cjs} +0 -0
  271. /package/src/main/lib/{telemetryConsent.cjs → telemetry/telemetryConsent.cjs} +0 -0
  272. /package/src/main/lib/{telemetryCounters.cjs → telemetry/telemetryCounters.cjs} +0 -0
  273. /package/src/main/lib/{atomicFs.cjs → util/atomicFs.cjs} +0 -0
  274. /package/src/main/lib/{encodeCwd.cjs → util/encodeCwd.cjs} +0 -0
  275. /package/src/main/lib/{expandHome.cjs → util/expandHome.cjs} +0 -0
  276. /package/src/main/lib/{extractJson.cjs → util/extractJson.cjs} +0 -0
  277. /package/src/main/lib/{fileTail.cjs → util/fileTail.cjs} +0 -0
  278. /package/src/main/lib/{headTailBuffer.cjs → util/headTailBuffer.cjs} +0 -0
  279. /package/src/main/lib/{kebabCase.cjs → util/kebabCase.cjs} +0 -0
  280. /package/src/main/lib/{loopDelay.cjs → util/loopDelay.cjs} +0 -0
  281. /package/src/main/lib/{lruCache.cjs → util/lruCache.cjs} +0 -0
  282. /package/src/main/lib/{withTimeout.cjs → util/withTimeout.cjs} +0 -0
@@ -0,0 +1,48 @@
1
+ # src/main/lib/ — scoped context
2
+
3
+ Shared main-process helpers (CommonJS `.cjs`). Layout source of truth: `scripts/lib-layout.json`.
4
+
5
+ ## What's here
6
+
7
+ - `claude/` — claude CLI binary, caps, model/effort resolution.
8
+ - `epic/` — Epic mint, worktrees, active index, spawn plan/cwd, transcripts.
9
+ - `feedback-remote/` — cross-project and customer feedback conduits.
10
+ - `git/` — git exec, worktrees, branch sweeps, job worktrees.
11
+ - `persona-macro/` — agent persona schema/merge, macro library, builtin macros.
12
+ - `prd/` — PRD parsing helpers, admin routes, dep-slug resolution, plan validation.
13
+ - `process/` — child processes, kill tree, env cleaning, pid liveness, instance lock.
14
+ - `scheduler/` — dispatch loop, session slots, gates, supervisors, queue helpers.
15
+ - `telemetry/` — audit/ops error logs, crash and OTLP telemetry.
16
+ - `util/` — generic pure helpers (atomic fs, kebab, home/cwd encoding, JSON extract, tail).
17
+ - top-level files — cross-cutting modules that fit no domain (`opsOwnership`, `activeSessions`, `projectRootResolve`, `cwdClassify`).
18
+ - `__tests__/` — tests for top-level modules; subfolders carry their own.
19
+
20
+ ## Where a new module goes
21
+
22
+ Put it in the subfolder whose domain it serves; pure and domain-free goes in `util/`.
23
+ A new top-level `lib/` module needs a stated reason (no domain fits) in its header comment,
24
+ and a `scripts/lib-layout.json` entry. Never add a subfolder for one file.
25
+
26
+ ## Reuse before writing
27
+
28
+ Each of these was found duplicated once. Grep first; extend the canonical one.
29
+
30
+ | Need | Canonical | Function |
31
+ | --- | --- | --- |
32
+ | Atomic write (tmp+rename) | `util/atomicFs.cjs` | `writeTextAtomic[Sync]`, `writeJsonAtomic[Sync]` |
33
+ | JSON read with fallback | `util/atomicFs.cjs` | `readJsonOr`, `readJsonOrSync` |
34
+ | PID liveness | `process/pidAlive.cjs` | `pidAlive` |
35
+ | Kebab / slug | `util/kebabCase.cjs` | `kebabCase` |
36
+ | Project root, read-only/total (never throws) | `activeSessions.cjs` | `projectRootOf` |
37
+ | Project root, validated; `opsInternal:'refuse'` for writers | `opsOwnership.cjs` | `resolveProjectRoot` |
38
+ | Project root + Epic from session/epic hints | `projectRootResolve.cjs` | `resolveProjectContext` |
39
+ | Ops-root path (single-writer law) | `opsOwnership.cjs` | `opsPath` |
40
+ | Run git | `git/gitExec.cjs` | `execGit` |
41
+ | Spawn `claude -p` (only machine-wide cap) | `scheduler/sessionSlots.cjs` | `acquire`, `release` |
42
+
43
+ Pin `--model` on every `claude -p` spawn.
44
+
45
+ ## What must NOT be assumed
46
+
47
+ - Never `path.join` an agent cwd to build an ops path — use `opsPath`.
48
+ - No private process caps, no hand-rolled tmp+rename, no new `JSON.parse(readFileSync)` fallbacks.
@@ -12,7 +12,7 @@ const fs = require('node:fs');
12
12
  const fsp = require('node:fs/promises');
13
13
  const os = require('node:os');
14
14
  const path = require('node:path');
15
- const { KIND_CONFIG: WORKTREE_KIND_CONFIG } = require('./gitWorktree.cjs');
15
+ const { KIND_CONFIG: WORKTREE_KIND_CONFIG } = require('./git/gitWorktree.cjs');
16
16
  const { OPS_ROOT_DIR } = require('./opsOwnership.cjs');
17
17
  const { classifyCwd, worktreeMainRootOf } = require('./cwdClassify.cjs');
18
18
 
@@ -16,8 +16,8 @@
16
16
  */
17
17
 
18
18
  const { spawn } = require('node:child_process');
19
- const { resolveClaudeBin, claudeSpawnTarget } = require('./claudeBin.cjs');
20
- const { cleanChildEnv, pathWithUserBins } = require('./cleanEnv.cjs');
19
+ const { resolveClaudeBin, claudeSpawnTarget } = require('./claude/claudeBin.cjs');
20
+ const { cleanChildEnv, pathWithUserBins } = require('./process/cleanEnv.cjs');
21
21
 
22
22
  const CLASSIFY_TIMEOUT_MS = 30_000;
23
23
  const CLASSIFY_MODEL = 'sonnet';
@@ -29,10 +29,10 @@
29
29
 
30
30
  const path = require('node:path');
31
31
  const os = require('node:os');
32
- const { splitFrontmatter } = require('./prdFrontmatter.cjs');
33
- const { readActiveIndex, resolvePersonaPaths } = require('./epicMint.cjs');
34
- const { resolveMergedPersona, PERSONA_NAME_RE } = require('./personaMerge.cjs');
35
- const configMgr = require('../config.cjs');
32
+ const { splitFrontmatter } = require('../prd/prdFrontmatter.cjs');
33
+ const { readActiveIndex, resolvePersonaPaths } = require('../epic/epicMint.cjs');
34
+ const { resolveMergedPersona, PERSONA_NAME_RE } = require('../persona-macro/personaMerge.cjs');
35
+ const configMgr = require('../../config.cjs');
36
36
 
37
37
  /** The hardcoded floor every branch of resolveEpicModel falls back to — --model must never be omitted (CLAUDE.md "Automation model pinning"). */
38
38
  const FALLBACK_MODEL = 'sonnet';
@@ -55,7 +55,7 @@ function logDanglingPersonaOnce(cwd, agentType) {
55
55
  // Required lazily: opsErrorLog.cjs is a leaf module with no Electron
56
56
  // dependency, but keeping this require inside the miss path avoids
57
57
  // paying for it on the (overwhelmingly common) hit path.
58
- const { appendError } = require('./opsErrorLog.cjs');
58
+ const { appendError } = require('../telemetry/opsErrorLog.cjs');
59
59
  appendError({
60
60
  cwd,
61
61
  scope: 'agentModelResolve',
@@ -218,10 +218,10 @@ async function resolvePrdPersonaForSpawn({ cwd, agentType, fallbackModel = FALLB
218
218
  const miss = { model: fallbackModel, systemPrompt: null, personaPath: null };
219
219
  if (!agentType) return miss;
220
220
  try {
221
- const getBody = deps.getPersonaBody || require('../agentLibrary.cjs').getPersonaBody;
221
+ const getBody = deps.getPersonaBody || require('../../agentLibrary.cjs').getPersonaBody;
222
222
  const persona = await getBody({ cwd, name: agentType });
223
223
  if (!persona) {
224
- const reportOnce = deps.reportDanglingAgentTypeOnce || require('./prdAgentType.cjs').reportDanglingAgentTypeOnce;
224
+ const reportOnce = deps.reportDanglingAgentTypeOnce || require('../prd/prdAgentType.cjs').reportDanglingAgentTypeOnce;
225
225
  reportOnce(cwd, agentType, deps);
226
226
  return miss;
227
227
  }
@@ -68,7 +68,7 @@ function __resetForTests() { cached = null; }
68
68
  //
69
69
  // Every `claude` spawn goes through claudeSpawnTarget so GNOME System Monitor
70
70
  // shows a distinct comm per role (sm-claude-job / -chat / -aux) and a labelled
71
- // argv0. See lib/procName.cjs for the mechanics. Invariants:
71
+ // argv0. See lib/process/procName.cjs for the mechanics. Invariants:
72
72
  // - SM_CLAUDE_BIN set → aliasing SKIPPED, raw value used verbatim (tests point
73
73
  // it at self-locating stubs; it must stay ONE binary, no path splitting).
74
74
  // - aliasBinFor fails open (returns realBin) → no argv0 is set either, so the
@@ -92,7 +92,7 @@ function claudeSpawnTarget(role, detail, realBin = resolveClaudeBin(), args = []
92
92
  const platform = winOpts.platform || process.platform;
93
93
  if (platform !== 'win32' || !/\.(cmd|bat)$/i.test(base.command)) return base;
94
94
  // Node refuses to spawn a .cmd/.bat without a shell (EINVAL) — wrap in cmd.exe argv.
95
- const { resolveSpawn } = require('./winSpawn.cjs');
95
+ const { resolveSpawn } = require('../process/winSpawn.cjs');
96
96
  const wrapped = resolveSpawn(base.command, args, { platform, ...(winOpts.env ? { env: winOpts.env } : {}), ...(winOpts.exists ? { exists: winOpts.exists } : {}) });
97
97
  return { ...base, ...wrapped };
98
98
  }
@@ -102,7 +102,7 @@ function baseSpawnTarget(role, detail, realBin) {
102
102
  const alias = ROLE_ALIASES[role];
103
103
  if (!alias) return { command: realBin };
104
104
  try {
105
- const { aliasBinFor, smArgv0 } = require('./procName.cjs');
105
+ const { aliasBinFor, smArgv0 } = require('../process/procName.cjs');
106
106
  const command = aliasBinFor(realBin, alias);
107
107
  if (command === realBin) return { command: realBin };
108
108
  return { command, argv0: smArgv0(role, detail) };
@@ -114,7 +114,7 @@ function baseSpawnTarget(role, detail, realBin) {
114
114
  // ---------- version probe ----------
115
115
  //
116
116
  // `claude --version`, cached. The scheduler's launch circuit breaker
117
- // (lib/launchFailure.cjs) records the CLI version a launch block was armed
117
+ // (lib/scheduler/launchFailure.cjs) records the CLI version a launch block was armed
118
118
  // under and drops the block the moment the version changes — the incident
119
119
  // behind it (issue #11: an outdated CLI sending a thinking parameter the
120
120
  // model rejects) is fixed by `claude update`, and the queue must notice
@@ -26,9 +26,9 @@
26
26
  const fs = require('node:fs');
27
27
  const path = require('node:path');
28
28
  const os = require('node:os');
29
- const { splitFrontmatter } = require('./prdFrontmatter.cjs');
30
- const { resolveEpicTranscriptPath } = require('./epicTranscriptPath.cjs');
31
- const schedulerPaths = require('./schedulerPaths.cjs');
29
+ const { splitFrontmatter } = require('../prd/prdFrontmatter.cjs');
30
+ const { resolveEpicTranscriptPath } = require('../epic/epicTranscriptPath.cjs');
31
+ const schedulerPaths = require('../scheduler/schedulerPaths.cjs');
32
32
 
33
33
  // Deliberately stays a FIXED alias set (reviewed against the catalog-driven raw picker): it answers
34
34
  // "alias vs concrete id", not "which options to offer", so live catalog ids must not enter it.
@@ -70,7 +70,7 @@ function isConcreteModelId(modelAlias) {
70
70
  */
71
71
  function computeEffortEnvReachable(deps) {
72
72
  try {
73
- const { cleanChildEnv } = deps.cleanEnv || require('./cleanEnv.cjs');
73
+ const { cleanChildEnv } = deps.cleanEnv || require('../process/cleanEnv.cjs');
74
74
  const probe = cleanChildEnv({ CLAUDE_EFFORT: 'high', CLAUDE_CODE_EFFORT_LEVEL: 'high' });
75
75
  return Boolean(probe.CLAUDE_EFFORT || probe.CLAUDE_CODE_EFFORT_LEVEL);
76
76
  } catch {
@@ -93,7 +93,7 @@ function computeEffortEnvReachable(deps) {
93
93
  * for the same dangling reference.
94
94
  */
95
95
  async function resolvePersonaModelAlias(cwd, agentType, deps) {
96
- const getPersonaBody = deps.getPersonaBody || require('../agentLibrary.cjs').getPersonaBody;
96
+ const getPersonaBody = deps.getPersonaBody || require('../../agentLibrary.cjs').getPersonaBody;
97
97
  // The overlay-vs-global provenance question itself ("which of
98
98
  // resolvePersonaPaths' two candidates won") is answered by
99
99
  // agentModelResolve.cjs's isProjectOverlayPersonaPath, not re-derived here
@@ -125,7 +125,7 @@ async function resolvePersonaModelAlias(cwd, agentType, deps) {
125
125
 
126
126
  /** Best-effort read of `<cwd>/session-manager-operations/scheduler/state/queue.json`'s hot jobs[]. */
127
127
  function readHotJobsForCwd(cwd, deps) {
128
- const { projectQueuePath } = deps.queueStore || require('./queueStore.cjs');
128
+ const { projectQueuePath } = deps.queueStore || require('../scheduler/queueStore.cjs');
129
129
  try {
130
130
  const data = JSON.parse(fs.readFileSync(projectQueuePath(cwd), 'utf8'));
131
131
  return Array.isArray(data.jobs) ? data.jobs : [];
@@ -136,7 +136,7 @@ function readHotJobsForCwd(cwd, deps) {
136
136
 
137
137
  /** Best-effort read of `<cwd>/session-manager-operations/scheduler/state/history.jsonl`'s archived rows. */
138
138
  function readHistoryEntriesForCwd(cwd, deps) {
139
- const { projectHistoryPath } = deps.queueStore || require('./queueStore.cjs');
139
+ const { projectHistoryPath } = deps.queueStore || require('../scheduler/queueStore.cjs');
140
140
  let text;
141
141
  try {
142
142
  text = fs.readFileSync(projectHistoryPath(cwd), 'utf8');
@@ -246,7 +246,7 @@ function findLatestSchedulerModel(cwd, agentType, deps) {
246
246
  * O(min(transcriptSize, cap)) per transcript read.
247
247
  */
248
248
  function findLatestTranscriptModel(cwd, agentType, deps) {
249
- const readActiveIndex = deps.readActiveIndex || require('./epicMint.cjs').readActiveIndex;
249
+ const readActiveIndex = deps.readActiveIndex || require('../epic/epicMint.cjs').readActiveIndex;
250
250
  let sessions;
251
251
  try {
252
252
  ({ sessions } = readActiveIndex(cwd));
@@ -296,7 +296,7 @@ async function resolveEffectiveModelInfo({ cwd, agentType, deps = {} } = {}) {
296
296
  if (!cwd || !agentType) return miss;
297
297
 
298
298
  try {
299
- const { projectRootOf } = deps.activeSessions || require('./activeSessions.cjs');
299
+ const { projectRootOf } = deps.activeSessions || require('../activeSessions.cjs');
300
300
  const normalizedCwd = projectRootOf(path.resolve(cwd));
301
301
  if (!normalizedCwd) return miss;
302
302
 
@@ -29,7 +29,7 @@ const SCAN_OVERLAP_BYTES = 128;
29
29
  const MODEL_ID_RE = /claude-(?:opus|sonnet|haiku|fable)-[0-9][0-9-]*/g;
30
30
  // A real CLI binary is tens of MB; test stubs and launcher shims are tiny shell scripts.
31
31
  const MIN_SCAN_BYTES = 1024 * 1024;
32
- const SCHEMA_PATH = path.join(__dirname, '..', '..', 'renderer', 'data', 'claude-settings-schema.json');
32
+ const SCHEMA_PATH = path.join(__dirname, '..', '..', '..', 'renderer', 'data', 'claude-settings-schema.json');
33
33
 
34
34
  const CATALOG_FLOOR = Object.freeze({
35
35
  aliases: Object.freeze(['haiku', 'sonnet', 'opus', 'fable']),
@@ -118,7 +118,7 @@ function readAvailableModels(cwd, d, fsImpl) {
118
118
  const home = d.homeDir ? d.homeDir() : os.homedir();
119
119
  let root = null;
120
120
  if (cwd) {
121
- try { root = (d.projectRootOf || require('./activeSessions.cjs').projectRootOf)(path.resolve(cwd)); } catch { root = path.resolve(cwd); }
121
+ try { root = (d.projectRootOf || require('../activeSessions.cjs').projectRootOf)(path.resolve(cwd)); } catch { root = path.resolve(cwd); }
122
122
  }
123
123
  const files = [path.join(home, '.claude', 'settings.json')];
124
124
  if (root) files.push(path.join(root, '.claude', 'settings.json'), path.join(root, '.claude', 'settings.local.json'));
@@ -221,7 +221,7 @@ async function doResolve({ cwd, force, deps }) {
221
221
  };
222
222
  // Unknown version = unknown cache key: writing it would stamp `claudeVersion: null` over a real entry.
223
223
  if (!degraded && cacheFile && claudeVersion) {
224
- try { await (d.writeJson || require('../config.cjs').writeJson)(cacheFile, catalog); } catch { /* cache is best-effort */ }
224
+ try { await (d.writeJson || require('../../config.cjs').writeJson)(cacheFile, catalog); } catch { /* cache is best-effort */ }
225
225
  }
226
226
  return catalog;
227
227
  }
@@ -11,7 +11,7 @@
11
11
  * never be a second, independently-drifting regex set at either call site.
12
12
  */
13
13
 
14
- const { readTail } = require('./fileTail.cjs');
14
+ const { readTail } = require('../util/fileTail.cjs');
15
15
 
16
16
  /** Scan the tail of a job's log for the canonical rate-limit signal. We look
17
17
  * at the last 16 KB — final result event always lands at the end. Covers
@@ -13,7 +13,7 @@
13
13
  * unit-testable without scheduler.cjs (mirrors reaperHelpers.cjs's split).
14
14
  */
15
15
 
16
- const { readTail } = require('./fileTail.cjs');
16
+ const { readTail } = require('../util/fileTail.cjs');
17
17
 
18
18
  // Authoritative window block rides on the LAST rate_limit_event in the log
19
19
  // (often the one attached to the final result), so mirror classifyRunOutcome's
@@ -17,7 +17,7 @@
17
17
  const { spawn } = require('node:child_process');
18
18
  const { resolveClaudeBin, claudeSpawnTarget } = require('./claudeBin.cjs');
19
19
  const { headlessPermissionArgs, ensureCliCapsProbed } = require('./claudeCliCaps.cjs');
20
- const { withProcRole } = require('./cleanEnv.cjs');
20
+ const { withProcRole } = require('../process/cleanEnv.cjs');
21
21
 
22
22
  const MAX_OUT_BYTES = 8 * 1024 * 1024;
23
23
 
@@ -5,9 +5,9 @@ const fs = require('node:fs');
5
5
  const path = require('node:path');
6
6
  const os = require('node:os');
7
7
  const { spawn, execFileSync } = require('node:child_process');
8
- const { cleanChildEnv, pathWithUserBins } = require('./cleanEnv.cjs');
9
- const atomicFs = require('./atomicFs.cjs');
10
- const { resolveClaudeBin, claudeSpawnTarget } = require('./claudeBin.cjs');
8
+ const { cleanChildEnv, pathWithUserBins } = require('./process/cleanEnv.cjs');
9
+ const atomicFs = require('./util/atomicFs.cjs');
10
+ const { resolveClaudeBin, claudeSpawnTarget } = require('./claude/claudeBin.cjs');
11
11
 
12
12
  const CREDS_PATH = path.join(os.homedir(), '.claude', '.credentials.json');
13
13
 
@@ -41,7 +41,7 @@
41
41
  const fs = require('node:fs');
42
42
  const os = require('node:os');
43
43
  const path = require('node:path');
44
- const schedulerPaths = require('./schedulerPaths.cjs');
44
+ const schedulerPaths = require('./scheduler/schedulerPaths.cjs');
45
45
 
46
46
  const OPS_DIRNAME = 'session-manager-operations';
47
47
  const WORKTREES_MARKER = `${path.sep}.git${path.sep}worktrees${path.sep}`;
@@ -35,7 +35,7 @@
35
35
 
36
36
  const path = require('path');
37
37
  const { activeIndexPath, withPathLock } = require('./epicMint.cjs');
38
- const config = require('../config.cjs');
38
+ const config = require('../../config.cjs');
39
39
  const { mirrorEpicStatus } = require('./epicStatusMirror.cjs');
40
40
 
41
41
  function hasOwn(obj, key) {
@@ -73,7 +73,7 @@ async function mergeActiveIndex(cwd, { sessions: rawMemorySessions = {}, events:
73
73
  if (!cwd || typeof cwd !== 'string') throw new Error('mergeActiveIndex: cwd is required');
74
74
  // Register this project's cwd as a write-allowed root (config.cjs's
75
75
  // validateWrite gate) — mirrors the precedent + comment in
76
- // lib/prdCreate.cjs:152-155. A chat-only Epic (headless claude -p, no
76
+ // lib/prd/prdCreate.cjs:152-155. A chat-only Epic (headless claude -p, no
77
77
  // Terminal PTY ever spawned for this cwd) reaches this merge on a cold
78
78
  // boot before pty.cjs's addAllowedRoot call has ever run for it — without
79
79
  // this, every active-index.json write for such a project fails with
@@ -181,7 +181,7 @@ async function mergeActiveIndex(cwd, { sessions: rawMemorySessions = {}, events:
181
181
 
182
182
  function registerActiveIndexMergeHandlers() {
183
183
  const { ipcMain } = require('electron');
184
- const { schemas: s, validated: v } = require('../ipcSchemas.cjs');
184
+ const { schemas: s, validated: v } = require('../../ipcSchemas.cjs');
185
185
  ipcMain.handle(
186
186
  'promptSessions:merge-active-index',
187
187
  v(s.promptSessionsMergeActiveIndex, ({ cwd, sessions, events, removedIds }) =>
@@ -20,7 +20,7 @@ const path = require('node:path');
20
20
  const { activeIndexPath, readActiveIndex, writeActiveIndex, withPathLock } = require('./epicMint.cjs');
21
21
 
22
22
  function promptSessionsDir(cwd) {
23
- const { opsPath } = require('./opsOwnership.cjs');
23
+ const { opsPath } = require('../opsOwnership.cjs');
24
24
  return opsPath(cwd, 'prompt-sessions');
25
25
  }
26
26
 
@@ -20,36 +20,28 @@ const fs = require('node:fs');
20
20
  const path = require('node:path');
21
21
  const os = require('node:os');
22
22
  const { spawn } = require('node:child_process');
23
- const { writeJson, addAllowedRoot } = require('../config.cjs');
24
- const { cleanChildEnv, pathWithUserBins } = require('./cleanEnv.cjs');
25
- const { shimPath: guardShimPath, resolveShimTarget, ensureGuardShimsOrError } = require('./guardShims.cjs');
26
- const { resolveProjectRoot } = require('./opsOwnership.cjs');
27
- const { nodeShellCommand } = require('./appRuntime.cjs');
23
+ const { writeJson, addAllowedRoot } = require('../../config.cjs');
24
+ const { cleanChildEnv, pathWithUserBins } = require('../process/cleanEnv.cjs');
25
+ const { shimPath: guardShimPath, resolveShimTarget, ensureGuardShimsOrError } = require('../guardShims.cjs');
26
+ const { resolveProjectRoot } = require('../opsOwnership.cjs');
27
+ const { nodeShellCommand } = require('../appRuntime.cjs');
28
+ const { readJsonOrSync } = require('../util/atomicFs.cjs');
28
29
 
29
30
  const SCHEDULER_MCP_NAME = 'session-manager-scheduler';
30
31
  const DEV_PLUGIN_ENABLED_KEY = 'session-manager-dev@session-manager';
31
- const SCHEDULER_MCP_SERVER_SCRIPT = path.resolve(__dirname, '..', '..', '..', 'scripts', 'scheduler-mcp-server.cjs');
32
- const PRD_WRITE_GUARD_SCRIPT = path.resolve(__dirname, '..', '..', '..', 'scripts', 'hooks', 'guard-prd-writes.cjs');
32
+ const SCHEDULER_MCP_SERVER_SCRIPT = path.resolve(__dirname, '..', '..', '..', '..', 'scripts', 'scheduler-mcp-server.cjs');
33
+ const PRD_WRITE_GUARD_SCRIPT = path.resolve(__dirname, '..', '..', '..', '..', 'scripts', 'hooks', 'guard-prd-writes.cjs');
33
34
  const PRD_WRITE_GUARD_MATCHER = 'Write|Edit|NotebookEdit';
34
- const DESTRUCTIVE_GIT_GUARD_SCRIPT = path.resolve(__dirname, '..', '..', '..', 'scripts', 'hooks', 'guard-destructive-git.cjs');
35
+ const DESTRUCTIVE_GIT_GUARD_SCRIPT = path.resolve(__dirname, '..', '..', '..', '..', 'scripts', 'hooks', 'guard-destructive-git.cjs');
35
36
  const DESTRUCTIVE_GIT_GUARD_MATCHER = 'Bash';
36
- const INLINE_IMPLEMENTATION_GUARD_SCRIPT = path.resolve(__dirname, '..', '..', '..', 'scripts', 'hooks', 'guard-inline-implementation.cjs');
37
+ const INLINE_IMPLEMENTATION_GUARD_SCRIPT = path.resolve(__dirname, '..', '..', '..', '..', 'scripts', 'hooks', 'guard-inline-implementation.cjs');
37
38
  const INLINE_IMPLEMENTATION_GUARD_MATCHER = 'Write|Edit|NotebookEdit';
38
- const SELF_SCHEDULE_GUARD_SCRIPT = path.resolve(__dirname, '..', '..', '..', 'scripts', 'hooks', 'guard-self-schedule.cjs');
39
+ const SELF_SCHEDULE_GUARD_SCRIPT = path.resolve(__dirname, '..', '..', '..', '..', 'scripts', 'hooks', 'guard-self-schedule.cjs');
39
40
  const SELF_SCHEDULE_GUARD_MATCHER = 'ScheduleWakeup|CronCreate|Task|Agent';
40
41
  const LIVE_PROBE_TIMEOUT_MS = 10_000;
41
42
  const LIVE_PROBE_TTL_MS = 60_000;
42
43
  const REQUIRED_LIVE_TOOLS = ['scheduler_create_prd', 'session_manager_help'];
43
44
 
44
- /** Read + JSON.parse a file, returning `fallback` on any read/parse failure. */
45
- function readJsonSafe(absPath, fallback) {
46
- try {
47
- return JSON.parse(fs.readFileSync(absPath, 'utf8'));
48
- } catch {
49
- return fallback;
50
- }
51
- }
52
-
53
45
  /** Lazy (not a module-load constant) so tests can toggle packaged mode. */
54
46
  function schedulerMcpFixCmd() {
55
47
  const cmd = nodeShellCommand(SCHEDULER_MCP_SERVER_SCRIPT);
@@ -68,10 +60,10 @@ function schedulerMcpFixCmd() {
68
60
  * which is the incident this PRD closes.
69
61
  */
70
62
  function checkSchedulerMcp({ cwd, homeDir }) {
71
- const userConfig = readJsonSafe(path.join(homeDir, '.claude.json'), null);
63
+ const userConfig = readJsonOrSync(path.join(homeDir, '.claude.json'), null);
72
64
  const userEntry = userConfig?.mcpServers?.[SCHEDULER_MCP_NAME];
73
65
 
74
- const projectConfig = readJsonSafe(path.join(cwd, '.mcp.json'), null);
66
+ const projectConfig = readJsonOrSync(path.join(cwd, '.mcp.json'), null);
75
67
  const projectHas = !!projectConfig?.mcpServers?.[SCHEDULER_MCP_NAME];
76
68
 
77
69
  if (userEntry) {
@@ -129,10 +121,10 @@ function checkSchedulerMcp({ cwd, homeDir }) {
129
121
  * (enableAllProjectMcpServers), not something this probe decides.
130
122
  */
131
123
  function checkSchedulerMcpProjectDuplicate({ cwd, homeDir }) {
132
- const userConfig = readJsonSafe(path.join(homeDir, '.claude.json'), null);
124
+ const userConfig = readJsonOrSync(path.join(homeDir, '.claude.json'), null);
133
125
  const userHas = !!userConfig?.mcpServers?.[SCHEDULER_MCP_NAME];
134
126
 
135
- const projectConfig = readJsonSafe(path.join(cwd, '.mcp.json'), null);
127
+ const projectConfig = readJsonOrSync(path.join(cwd, '.mcp.json'), null);
136
128
  const projectHas = !!projectConfig?.mcpServers?.[SCHEDULER_MCP_NAME];
137
129
 
138
130
  const warn = userHas && projectHas;
@@ -289,7 +281,7 @@ async function checkSchedulerMcpLive({ cwd, homeDir, schedulerMcpCheck }) {
289
281
  // executed the moment its cwd is merely probed, bypassing that approval
290
282
  // entirely. Auto-approving project-scope servers is explicitly out of
291
283
  // scope for this probe — see this PRD's "Out of scope".
292
- const userConfig = readJsonSafe(path.join(homeDir, '.claude.json'), null);
284
+ const userConfig = readJsonOrSync(path.join(homeDir, '.claude.json'), null);
293
285
  const entry = userConfig?.mcpServers?.[SCHEDULER_MCP_NAME];
294
286
 
295
287
  if (!entry?.command) {
@@ -312,7 +304,7 @@ async function checkSchedulerMcpLive({ cwd, homeDir, schedulerMcpCheck }) {
312
304
  }
313
305
 
314
306
  function checkDevPlugin({ homeDir }) {
315
- const settings = readJsonSafe(path.join(homeDir, '.claude', 'settings.json'), null);
307
+ const settings = readJsonOrSync(path.join(homeDir, '.claude', 'settings.json'), null);
316
308
  const ok = settings?.enabledPlugins?.[DEV_PLUGIN_ENABLED_KEY] === true;
317
309
 
318
310
  return {
@@ -444,7 +436,7 @@ const GUARD_DEFS = {
444
436
  * while reporting green" failure mode, one hop downstream of the hook command.
445
437
  */
446
438
  function checkGuard(def, { cwd, homeDir = os.homedir() }) {
447
- const settings = readJsonSafe(path.join(cwd, '.claude', 'settings.json'), null);
439
+ const settings = readJsonOrSync(path.join(cwd, '.claude', 'settings.json'), null);
448
440
  const preToolUse = Array.isArray(settings?.hooks?.PreToolUse) ? settings.hooks.PreToolUse : [];
449
441
 
450
442
  let mentioned = false;
@@ -536,7 +528,7 @@ async function installGuard(def, { cwd, homeDir = os.homedir(), skipShimEnsure =
536
528
  // documents for PromptSession archive writes. `cwd` here IS a project root.
537
529
  addAllowedRoot(cwd);
538
530
 
539
- const existing = fs.existsSync(settingsPath) ? readJsonSafe(settingsPath, undefined) : {};
531
+ const existing = fs.existsSync(settingsPath) ? readJsonOrSync(settingsPath, undefined) : {};
540
532
  if (existing === undefined) {
541
533
  // Unparseable settings — refuse rather than silently discarding whatever
542
534
  // the human has in there.
@@ -629,7 +621,7 @@ async function installSelfScheduleGuard({ cwd, homeDir = os.homedir(), skipShimE
629
621
 
630
622
  /**
631
623
  * Runs all eight delegation-readiness checks for `cwd`. Every filesystem read
632
- * is wrapped (readJsonSafe / try-catch) so a missing or unparseable file
624
+ * is wrapped (readJsonOrSync / try-catch) so a missing or unparseable file
633
625
  * yields ok:false with a detail, never a thrown exception. Async because
634
626
  * scheduler-mcp-live genuinely spawns a process and waits on it (bounded by
635
627
  * LIVE_PROBE_TIMEOUT_MS, and memoized per registration signature so repeat
@@ -673,7 +665,7 @@ function logAutoInstallEvent({ cwd, guard, action, error }) {
673
665
  // A no-op outcome is not an event worth an error-log row (24 rows/3 days of boot noise).
674
666
  if (action === 'already-installed') return;
675
667
  try {
676
- const opsErrorLog = require('./opsErrorLog.cjs');
668
+ const opsErrorLog = require('../telemetry/opsErrorLog.cjs');
677
669
  opsErrorLog.appendError({
678
670
  cwd,
679
671
  scope: 'delegationReadiness',
@@ -13,7 +13,7 @@
13
13
  * scheduler.cjs.
14
14
  */
15
15
 
16
- const { readTurns } = require('../promptSessionTranscript.cjs');
16
+ const { readTurns } = require('../../promptSessionTranscript.cjs');
17
17
  const { readActiveIndex } = require('./epicMint.cjs');
18
18
 
19
19
  const DEFAULT_MAX_CHARS = 4000;
@@ -28,7 +28,7 @@ const fs = require('node:fs');
28
28
  const os = require('node:os');
29
29
  const path = require('node:path');
30
30
  const { resolveEpicTranscriptPath } = require('./epicTranscriptPath.cjs');
31
- const { classifyLine } = require('./classifyTranscriptLine.cjs');
31
+ const { classifyLine } = require('../classifyTranscriptLine.cjs');
32
32
 
33
33
  // Same cap transcripts.cjs's readDelta uses for a single pass — bounds
34
34
  // memory/time on a very large transcript instead of reading it whole.
@@ -40,7 +40,7 @@ const APPLICATION_SOURCE_PREFIXES = ['src/', 'scripts/', 'plugins/', 'bin/'];
40
40
  function countPrdsQueued(cwd, epicId, deps = {}) {
41
41
  const readdirSync = deps.readdirSync || fs.readdirSync;
42
42
  try {
43
- const { opsPath } = require('./opsOwnership.cjs');
43
+ const { opsPath } = require('../opsOwnership.cjs');
44
44
  const dir = opsPath(cwd, 'scheduler', 'epics', epicId, 'prds');
45
45
  return readdirSync(dir).filter((name) => name.endsWith('.md')).length;
46
46
  } catch {
@@ -31,20 +31,20 @@ const fs = require('node:fs');
31
31
  const os = require('node:os');
32
32
  const path = require('node:path');
33
33
  const crypto = require('node:crypto');
34
- const { resolveEpicPrdWriteDir } = require('./prdLocations.cjs');
35
- const { assertOpsWrite } = require('./opsOwnership.cjs');
36
- const { appendAuditEvent } = require('./auditLog.cjs');
34
+ const { resolveEpicPrdWriteDir } = require('../prd/prdLocations.cjs');
35
+ const { assertOpsWrite } = require('../opsOwnership.cjs');
36
+ const { appendAuditEvent } = require('../telemetry/auditLog.cjs');
37
37
  const { mirrorEpicStatus, removeEpicMirror } = require('./epicStatusMirror.cjs');
38
- const atomicFs = require('./atomicFs.cjs');
39
- const telemetryCounters = require('./telemetryCounters.cjs');
38
+ const atomicFs = require('../util/atomicFs.cjs');
39
+ const telemetryCounters = require('../telemetry/telemetryCounters.cjs');
40
40
  // Required as the module object (not destructured) so a test can
41
41
  // monkeypatch promptSessionSchema.assertValidPromptSession in place to
42
42
  // simulate a corrupted construction — the real construction below is
43
43
  // hardcoded and always valid.
44
- const promptSessionSchema = require('./promptSessionSchema.cjs');
44
+ const promptSessionSchema = require('../promptSessionSchema.cjs');
45
45
 
46
46
  // The one token that unlocks ensureEpic's mint branch. Held by
47
- // lib/promptSessionsCreateEpic.cjs (the New Epic card's IPC handler) and
47
+ // lib/epic/promptSessionsCreateEpic.cjs (the New Epic card's IPC handler) and
48
48
  // nothing else — grep for it before adding a second holder, that is a
49
49
  // deliberate domain-model change, not a convenience.
50
50
  const MINT_AUTHORITY_NEW_EPIC_UI = 'new-epic-ui';
@@ -56,7 +56,7 @@ const MINT_AUTHORITY_NEW_EPIC_UI = 'new-epic-ui';
56
56
  // the `feedback/` folder retired (2026-08-02) and the scheduler correctly
57
57
  // locked down to join-only, an agent working in Project-A had NO way to hand
58
58
  // a finding to Project-B — the finding either died in a transcript or the
59
- // human had to relay it by hand. `lib/crossProjectFeedback.cjs` restores that
59
+ // human had to relay it by hand. `lib/feedback-remote/crossProjectFeedback.cjs` restores that
60
60
  // conduit, and it is the sole holder of this token.
61
61
  //
62
62
  // What makes it safe is the part of the SINGLE-CREATOR LAW that actually
@@ -79,7 +79,7 @@ const MINT_AUTHORITIES = Object.freeze([
79
79
  function activeIndexPath(cwd) {
80
80
  // Lazy: opsOwnership → ephemeralCwd → activeSessions; this module is
81
81
  // required early by several of those neighbours.
82
- const { opsPath } = require('./opsOwnership.cjs');
82
+ const { opsPath } = require('../opsOwnership.cjs');
83
83
  return opsPath(cwd, 'prompt-sessions', 'active-index.json');
84
84
  }
85
85
 
@@ -93,7 +93,7 @@ function readActiveIndex(cwd) {
93
93
  // doesn't resurrect completed/deleted Epics on its own), but every
94
94
  // caller here does read-modify-write on the object this returns, so
95
95
  // dropping the field would silently erase the removal tombstones
96
- // lib/activeIndexMerge.cjs's mergeActiveIndex records the next time any
96
+ // lib/epic/activeIndexMerge.cjs's mergeActiveIndex records the next time any
97
97
  // of ensureEpic/appendPrdCreatedEvent/removeEpic writes this file.
98
98
  tombstones: parsed && typeof parsed.tombstones === 'object' && parsed.tombstones ? parsed.tombstones : {},
99
99
  };
@@ -450,7 +450,7 @@ module.exports = {
450
450
  writeActiveIndex,
451
451
  personaFileExists,
452
452
  resolvePersonaPaths,
453
- // Exported so lib/activeIndexMerge.cjs's renderer-facing merge IPC handler
453
+ // Exported so lib/epic/activeIndexMerge.cjs's renderer-facing merge IPC handler
454
454
  // serializes through the SAME lock instance as ensureEpic/
455
455
  // appendPrdCreatedEvent (module-level Map, shared via Node's require
456
456
  // cache) — one lock per active-index.json path across both callers, not
@@ -27,8 +27,8 @@
27
27
  const fs = require('node:fs');
28
28
  const os = require('node:os');
29
29
  const path = require('node:path');
30
- const { encodeCwd } = require('./encodeCwd.cjs');
31
- const { projectRootOf } = require('./activeSessions.cjs');
30
+ const { encodeCwd } = require('../util/encodeCwd.cjs');
31
+ const { projectRootOf } = require('../activeSessions.cjs');
32
32
  const { readActiveIndex } = require('./epicMint.cjs');
33
33
  const { resolveEpicSpawnCwd } = require('./epicSpawnCwd.cjs');
34
34
  const { resolveEpicTranscriptPath } = require('./epicTranscriptPath.cjs');
@@ -56,7 +56,7 @@ function findEpic(cwd, claudeSessionId, deps) {
56
56
  }
57
57
  } catch { /* unreadable index → try archives */ }
58
58
  try {
59
- const { opsPath } = require('./opsOwnership.cjs');
59
+ const { opsPath } = require('../opsOwnership.cjs');
60
60
  const dir = opsPath(cwd, 'prompt-sessions');
61
61
  for (const name of fs.readdirSync(dir)) {
62
62
  if (!name.endsWith('.json') || name === 'active-index.json') continue;
@@ -26,8 +26,8 @@
26
26
  */
27
27
 
28
28
  const fs = require('node:fs');
29
- const { assertOpsWrite, opsPath } = require('./opsOwnership.cjs');
30
- const atomicFs = require('./atomicFs.cjs');
29
+ const { assertOpsWrite, opsPath } = require('../opsOwnership.cjs');
30
+ const atomicFs = require('../util/atomicFs.cjs');
31
31
 
32
32
  function epicMirrorPath(cwd, epicId) {
33
33
  return opsPath(cwd, 'prompt-sessions', `${epicId}.json`);
@@ -17,9 +17,9 @@
17
17
  const fs = require('node:fs');
18
18
  const os = require('node:os');
19
19
  const path = require('node:path');
20
- const { encodeCwd } = require('./encodeCwd.cjs');
20
+ const { encodeCwd } = require('../util/encodeCwd.cjs');
21
21
  const { readActiveIndex } = require('./epicMint.cjs');
22
- const { opsPath } = require('./opsOwnership.cjs');
22
+ const { opsPath } = require('../opsOwnership.cjs');
23
23
  const { resolveEpicTranscriptPath } = require('./epicTranscriptPath.cjs');
24
24
 
25
25
  /** [epicId, session] pairs: active-index rows plus archived per-Epic `<id>.json` records. */
@@ -25,7 +25,7 @@
25
25
  const fs = require('node:fs');
26
26
  const os = require('node:os');
27
27
  const path = require('node:path');
28
- const { encodeCwd } = require('./encodeCwd.cjs');
28
+ const { encodeCwd } = require('../util/encodeCwd.cjs');
29
29
  const { readActiveIndex } = require('./epicMint.cjs');
30
30
  const { resolveEpicSpawnCwd } = require('./epicSpawnCwd.cjs');
31
31
 
@@ -53,7 +53,7 @@ function statKey(statSync, p) {
53
53
  }
54
54
 
55
55
  function opsFile(cwd, ...segments) {
56
- const { opsPath } = require('./opsOwnership.cjs');
56
+ const { opsPath } = require('../opsOwnership.cjs');
57
57
  return opsPath(cwd, 'prompt-sessions', ...segments);
58
58
  }
59
59