claude-code-session-manager 0.111.0 → 0.113.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.
- package/.claude-plugin/marketplace.json +2 -2
- package/dist/assets/{AgentLibrary-rBO1daqM.js → AgentLibrary-wvrcLGGS.js} +2 -2
- package/dist/assets/{Button-DsEYRZg0.js → Button-B6h0F0XT.js} +1 -1
- package/dist/assets/{DataModel-D8sbvvBC.js → DataModel-C5pW9E3u.js} +1 -1
- package/dist/assets/{History-BEHLtxia.js → History-BV4e8YOM.js} +2 -2
- package/dist/assets/{Hooks-CKpvlXrg.js → Hooks-CrFSv4x1.js} +3 -3
- package/dist/assets/{Library-CeF4qh9d.js → Library-D-GIt3EY.js} +5 -5
- package/dist/assets/{ListDetail-DcfmxPFk.js → ListDetail-Bco_wfs6.js} +1 -1
- package/dist/assets/{MarkdownEditor-CvK1pyto.js → MarkdownEditor-C-yHSXNV.js} +1 -1
- package/dist/assets/{McpServers-D-h2ihzJ.js → McpServers-CfDekadG.js} +2 -2
- package/dist/assets/{Memory-BnF89x8v.js → Memory-CGGLexkR.js} +4 -4
- package/dist/assets/{Panel-CQY5zano.js → Panel-DGMEuYYG.js} +1 -1
- package/dist/assets/{Permissions-DLukmmsz.js → Permissions-Cx2zjtYZ.js} +3 -3
- package/dist/assets/{Plugins-0Pf0OZ4l.js → Plugins-Bc_W3IyR.js} +2 -2
- package/dist/assets/ProvenanceBadge-DiKAUR1u.js +1 -0
- package/dist/assets/RemoteMachines-8_77-WPD.js +3 -0
- package/dist/assets/{SaveBar-DjijiUb0.js → SaveBar-Blpzdq1R.js} +1 -1
- package/dist/assets/{Scheduler-Cm3EXZvE.js → Scheduler-Bd70AM4X.js} +9 -9
- package/dist/assets/{ScopeSwitcher-B-P-kSfq.js → ScopeSwitcher-wxN0h4YW.js} +1 -1
- package/dist/assets/Settings-CQ7DA3zW.js +4 -0
- package/dist/assets/{SkillReferenceGraph-Epv2GJmj.js → SkillReferenceGraph-DH1NLOiS.js} +1 -1
- package/dist/assets/Skills-CmyRyu4_.js +2 -0
- package/dist/assets/SystemPrompt-KAc3UMCd.js +1 -0
- package/dist/assets/TagLibrary-C8EvHnpg.js +1 -0
- package/dist/assets/{TiptapBody-DAMO3DhO.js → TiptapBody-d423mH6D.js} +1 -1
- package/dist/assets/{Toggle-Ba_f7q_m.js → Toggle-D1wsGE9S.js} +1 -1
- package/dist/assets/{ViewTabs-CGX6MAhc.js → ViewTabs-CjHw3kGY.js} +1 -1
- package/dist/assets/{historyTotals-vgfk8EOL.js → historyTotals-DFHzqLt7.js} +1 -1
- package/dist/assets/{index-CPieAFsl.js → index-Ci1u018F.js} +266 -266
- package/dist/assets/{settingsSchema-D0FxNrTy.js → settingsSchema-Ctf3pZVI.js} +1 -1
- package/dist/assets/{useAgentsDirWatch-DCu6BNYN.js → useAgentsDirWatch-B1NBmOAe.js} +1 -1
- package/dist/assets/{useRemotePeers-D4cdJDyh.js → useRemotePeers-BHjSJs9D.js} +1 -1
- package/dist/index.html +1 -1
- package/package.json +3 -2
- package/plugins/CLAUDE.md +5 -8
- package/plugins/session-manager-dev/.claude-plugin/plugin.json +3 -6
- package/plugins/session-manager-dev/skills/builder/1-classify-and-bump/SKILL.md +2 -2
- package/plugins/session-manager-dev/skills/builder/SKILL.md +2 -3
- package/plugins/session-manager-dev/skills/develop/SKILL.md +1 -1
- package/plugins/session-manager-dev/skills/develop/standards.md +3 -3
- package/plugins/session-manager-dev/skills/send-feedback/SKILL.md +13 -0
- package/scripts/README.md +3 -3
- package/scripts/audit-ops-hygiene.cjs +4 -4
- package/scripts/hooks/guard-destructive-git.cjs +4 -4
- package/scripts/hooks/guard-inline-implementation.cjs +1 -1
- package/scripts/hooks/guard-prd-writes.cjs +2 -2
- package/scripts/hooks/lib/guard-destructive-git-policy.cjs +1 -1
- package/scripts/mint-epic.cjs +2 -2
- package/scripts/scheduler-mcp-server.cjs +27 -9
- package/src/main/agentLibrary.cjs +5 -5
- package/src/main/agentsIpc.cjs +76 -0
- package/src/main/build-info.json +4 -4
- package/src/main/chatRunner.cjs +30 -13
- package/src/main/config.cjs +20 -3
- package/src/main/crashDiagnostics.cjs +2 -2
- package/src/main/docEdit.cjs +5 -5
- package/src/main/files.cjs +2 -2
- package/src/main/git.cjs +1 -1
- package/src/main/health.cjs +20 -18
- package/src/main/heapSnapshot.cjs +1 -1
- package/src/main/historyAggregator.cjs +2 -2
- package/src/main/index.cjs +50 -132
- package/src/main/ipcSchemas.cjs +13 -10
- package/src/main/lib/CLAUDE.md +48 -0
- package/src/main/lib/activeSessions.cjs +14 -1
- package/src/main/lib/classifyPromptTicket.cjs +2 -2
- package/src/main/lib/{agentModelResolve.cjs → claude/agentModelResolve.cjs} +7 -7
- package/src/main/lib/{claudeBin.cjs → claude/claudeBin.cjs} +4 -4
- package/src/main/lib/{effectiveModelInfo.cjs → claude/effectiveModelInfo.cjs} +9 -9
- package/src/main/lib/{modelCatalog.cjs → claude/modelCatalog.cjs} +3 -3
- package/src/main/lib/claude/rateLimitDetect.cjs +54 -0
- package/src/main/lib/{rateLimitWindow.cjs → claude/rateLimitWindow.cjs} +24 -12
- package/src/main/lib/{runClaudeP.cjs → claude/runClaudeP.cjs} +1 -1
- package/src/main/lib/credentials.cjs +18 -92
- package/src/main/lib/cwdClassify.cjs +1 -1
- package/src/main/lib/{activeIndexMerge.cjs → epic/activeIndexMerge.cjs} +3 -3
- package/src/main/lib/{activeIndexRebuild.cjs → epic/activeIndexRebuild.cjs} +1 -1
- package/src/main/lib/{delegationReadiness.cjs → epic/delegationReadiness.cjs} +21 -29
- package/src/main/lib/{epicContextDigest.cjs → epic/epicContextDigest.cjs} +1 -1
- package/src/main/lib/{epicDelegationStats.cjs → epic/epicDelegationStats.cjs} +2 -2
- package/src/main/lib/{epicMint.cjs → epic/epicMint.cjs} +11 -11
- package/src/main/lib/{epicSpawnPlan.cjs → epic/epicSpawnPlan.cjs} +3 -3
- package/src/main/lib/{epicStatusMirror.cjs → epic/epicStatusMirror.cjs} +2 -2
- package/src/main/lib/{epicTranscriptDiagnostic.cjs → epic/epicTranscriptDiagnostic.cjs} +2 -2
- package/src/main/lib/{epicTranscriptPath.cjs → epic/epicTranscriptPath.cjs} +2 -2
- package/src/main/lib/{epicValidationHook.cjs → epic/epicValidationHook.cjs} +3 -3
- package/src/main/lib/{epicWorktreeBoot.cjs → epic/epicWorktreeBoot.cjs} +1 -1
- package/src/main/lib/{epicWorktreeMerge.cjs → epic/epicWorktreeMerge.cjs} +3 -3
- package/src/main/lib/{epicWorktreeMint.cjs → epic/epicWorktreeMint.cjs} +3 -3
- package/src/main/lib/{epicWorktreeProjectConfig.cjs → epic/epicWorktreeProjectConfig.cjs} +4 -4
- package/src/main/lib/{promptSessionsCreateEpic.cjs → epic/promptSessionsCreateEpic.cjs} +4 -4
- package/src/main/lib/{crossProjectFeedback.cjs → feedback-remote/crossProjectFeedback.cjs} +114 -16
- package/src/main/lib/{customerFeedbackClient.cjs → feedback-remote/customerFeedbackClient.cjs} +3 -3
- package/src/main/lib/{customerFeedbackInbox.cjs → feedback-remote/customerFeedbackInbox.cjs} +2 -2
- package/src/main/lib/{customerFeedbackIpc.cjs → feedback-remote/customerFeedbackIpc.cjs} +1 -1
- package/src/main/lib/feedback-remote/humanPromptLedger.cjs +93 -0
- package/src/main/lib/{localAdminHttp.cjs → feedback-remote/localAdminHttp.cjs} +2 -2
- package/src/main/lib/{macroAdminRoutes.cjs → feedback-remote/macroAdminRoutes.cjs} +1 -1
- package/src/main/lib/{projectHomeAdminRoutes.cjs → feedback-remote/projectHomeAdminRoutes.cjs} +4 -4
- package/src/main/lib/{relayClientAuth.cjs → feedback-remote/relayClientAuth.cjs} +2 -2
- package/src/main/lib/{remoteClientSessions.cjs → feedback-remote/remoteClientSessions.cjs} +1 -1
- package/src/main/lib/{gitWorktree.cjs → git/gitWorktree.cjs} +7 -7
- package/src/main/lib/historyRollup.cjs +1 -1
- package/src/main/lib/importReferences.cjs +1 -1
- package/src/main/lib/machineProfile.cjs +1 -1
- package/src/main/lib/mcpToolCatalog.cjs +9 -3
- package/src/main/lib/openExternalApp.cjs +1 -1
- package/src/main/lib/opsOwnership.cjs +3 -3
- package/src/main/lib/{agentPersonaSchema.cjs → persona-macro/agentPersonaSchema.cjs} +2 -2
- package/src/main/lib/{macroLibrary.cjs → persona-macro/macroLibrary.cjs} +5 -5
- package/src/main/lib/{personaMerge.cjs → persona-macro/personaMerge.cjs} +4 -4
- package/src/main/lib/{depSlugResolve.cjs → prd/depSlugResolve.cjs} +16 -1
- package/src/main/lib/{prdAdminRoutes.cjs → prd/prdAdminRoutes.cjs} +7 -7
- package/src/main/lib/{prdAgentType.cjs → prd/prdAgentType.cjs} +3 -3
- package/src/main/lib/{prdCreate.cjs → prd/prdCreate.cjs} +12 -12
- package/src/main/lib/{prdDeclaredPaths.cjs → prd/prdDeclaredPaths.cjs} +1 -1
- package/src/main/lib/{prdGateFiles.cjs → prd/prdGateFiles.cjs} +1 -1
- package/src/main/lib/{prdLocations.cjs → prd/prdLocations.cjs} +2 -2
- package/src/main/lib/{prdMigration.cjs → prd/prdMigration.cjs} +3 -3
- package/src/main/lib/prereqs.cjs +2 -2
- package/src/main/lib/{instanceLock.cjs → process/instanceLock.cjs} +4 -11
- package/src/main/lib/{pidAlive.cjs → process/pidAlive.cjs} +1 -1
- package/src/main/lib/{procName.cjs → process/procName.cjs} +2 -2
- package/src/main/lib/{timeoutShim.cjs → process/timeoutShim.cjs} +1 -1
- package/src/main/lib/projectRootResolve.cjs +1 -1
- package/src/main/lib/promptSessionSchema.cjs +1 -1
- package/src/main/lib/{definitionOfDone.cjs → scheduler/definitionOfDone.cjs} +6 -12
- package/src/main/lib/scheduler/finalizeReason.cjs +30 -0
- package/src/main/lib/{fixChainDepth.cjs → scheduler/fixChainDepth.cjs} +1 -1
- package/src/main/lib/scheduler/flatSweepThrottle.cjs +17 -0
- package/src/main/lib/{jobDirtFilter.cjs → scheduler/jobDirtFilter.cjs} +1 -1
- package/src/main/lib/{jobSupervisorRecord.cjs → scheduler/jobSupervisorRecord.cjs} +1 -1
- package/src/main/lib/{launchFailure.cjs → scheduler/launchFailure.cjs} +2 -2
- package/src/main/lib/{queueStore.cjs → scheduler/queueStore.cjs} +6 -6
- package/src/main/lib/{quietMachineLease.cjs → scheduler/quietMachineLease.cjs} +1 -1
- package/src/main/lib/{rcaReport.cjs → scheduler/rcaReport.cjs} +4 -4
- package/src/main/lib/{reaperHelpers.cjs → scheduler/reaperHelpers.cjs} +3 -3
- package/src/main/lib/{reservationExpiry.cjs → scheduler/reservationExpiry.cjs} +4 -11
- package/src/main/lib/{reviewNotice.cjs → scheduler/reviewNotice.cjs} +1 -1
- package/src/main/lib/{runLogRetention.cjs → scheduler/runLogRetention.cjs} +34 -13
- package/src/main/lib/{scheduleJobTransitions.cjs → scheduler/scheduleJobTransitions.cjs} +3 -3
- package/src/main/lib/{schedulerBatch.cjs → scheduler/schedulerBatch.cjs} +9 -13
- package/src/main/lib/{schedulerConfig.cjs → scheduler/schedulerConfig.cjs} +1 -1
- package/src/main/lib/{schedulerRuntimeState.cjs → scheduler/schedulerRuntimeState.cjs} +1 -1
- package/src/main/lib/{sessionSlots.cjs → scheduler/sessionSlots.cjs} +2 -2
- package/src/main/lib/{upgradeDrain.cjs → scheduler/upgradeDrain.cjs} +8 -11
- package/src/main/lib/{watchdogHelpers.cjs → scheduler/watchdogHelpers.cjs} +5 -19
- package/src/main/lib/{auditLog.cjs → telemetry/auditLog.cjs} +1 -1
- package/src/main/lib/{opsErrorLog.cjs → telemetry/opsErrorLog.cjs} +4 -4
- package/src/main/lib/{telemetryBacklog.cjs → telemetry/telemetryBacklog.cjs} +4 -4
- package/src/main/lib/{telemetryBoot.cjs → telemetry/telemetryBoot.cjs} +1 -1
- package/src/main/lib/{telemetryClient.cjs → telemetry/telemetryClient.cjs} +12 -8
- package/src/main/lib/{telemetrySettings.cjs → telemetry/telemetrySettings.cjs} +1 -1
- package/src/main/lib/{atomicFs.cjs → util/atomicFs.cjs} +42 -0
- package/src/main/lib/{loopDelay.cjs → util/loopDelay.cjs} +1 -1
- package/src/main/logs.cjs +1 -1
- package/src/main/mcpStatus.cjs +2 -2
- package/src/main/memoryAggregate.cjs +3 -3
- package/src/main/memoryTool.cjs +1 -1
- package/src/main/otel.cjs +2 -2
- package/src/main/pluginInstall.cjs +29 -3
- package/src/main/projectBrief.cjs +6 -6
- package/src/main/projectPages.cjs +1 -1
- package/src/main/promptSessionEvents.cjs +2 -2
- package/src/main/pty.cjs +7 -7
- package/src/main/queueOps.cjs +6 -6
- package/src/main/remoteClient.cjs +4 -4
- package/src/main/remoteClientIpc.cjs +1 -1
- package/src/main/runVerify.cjs +6 -3
- package/src/main/scheduler/CLAUDE.md +26 -0
- package/src/main/scheduler/budget.cjs +576 -0
- package/src/main/scheduler/gitTreeGuard.cjs +672 -0
- package/src/main/scheduler/prdParser.cjs +4 -4
- package/src/main/scheduler/prdPaths.cjs +487 -0
- package/src/main/scheduler/reviewLadder.cjs +1011 -0
- package/src/main/scheduler/starvation.cjs +390 -0
- package/src/main/scheduler.cjs +331 -3320
- package/src/main/seedAgentPersonas.cjs +5 -5
- package/src/main/seedDevPlugin.cjs +70 -3
- package/src/main/seedSchedulerMcp.cjs +2 -2
- package/src/main/supervisor.cjs +50 -27
- package/src/main/telemetryIpc.cjs +51 -0
- package/src/main/transcripts.cjs +3 -3
- package/src/main/updaterIpc.cjs +1 -1
- package/src/main/usage.cjs +1 -1
- package/src/main/watchers.cjs +1 -1
- package/src/main/webRemote.cjs +22 -7
- package/src/preload/api.d.ts +14 -8
- package/src/preload/index.cjs +9 -3
- package/dist/assets/ProvenanceBadge-vC7Tj-JP.js +0 -1
- package/dist/assets/RemoteMachines-CWnKbFHc.js +0 -3
- package/dist/assets/Settings-DYDlp2m_.js +0 -4
- package/dist/assets/Skills-DHO0N0C2.js +0 -2
- package/dist/assets/SystemPrompt-DxeNofL9.js +0 -1
- package/dist/assets/TagLibrary-QOAs7ISO.js +0 -1
- package/plugins/session-manager-dev/skills/blog-for-project-feature/0-select/SKILL.md +0 -39
- package/plugins/session-manager-dev/skills/blog-for-project-feature/1-research/SKILL.md +0 -37
- package/plugins/session-manager-dev/skills/blog-for-project-feature/2-storyboard/SKILL.md +0 -64
- package/plugins/session-manager-dev/skills/blog-for-project-feature/3-capture/SKILL.md +0 -52
- package/plugins/session-manager-dev/skills/blog-for-project-feature/4-draft-copy/SKILL.md +0 -37
- package/plugins/session-manager-dev/skills/blog-for-project-feature/5-illustrate/SKILL.md +0 -50
- package/plugins/session-manager-dev/skills/blog-for-project-feature/6-compose/SKILL.md +0 -51
- package/plugins/session-manager-dev/skills/blog-for-project-feature/7-review/SKILL.md +0 -54
- package/plugins/session-manager-dev/skills/blog-for-project-feature/SKILL.md +0 -144
- package/plugins/session-manager-dev/skills/blog-for-project-feature/feature.config.yaml +0 -90
- package/plugins/session-manager-dev/skills/discover-features/SKILL.md +0 -95
- package/plugins/session-manager-dev/skills/explain-to-me/SKILL.md +0 -205
- package/plugins/session-manager-dev/skills/explain-to-me/assets/style-reference.html +0 -163
- package/plugins/session-manager-dev/skills/find-opportunity/SKILL.md +0 -83
- package/plugins/session-manager-dev/skills/issue-address/0-select/0-fetch-pool/SKILL.md +0 -38
- package/plugins/session-manager-dev/skills/issue-address/0-select/1-reject-fixed/SKILL.md +0 -64
- package/plugins/session-manager-dev/skills/issue-address/0-select/2-reject-claimed/SKILL.md +0 -71
- package/plugins/session-manager-dev/skills/issue-address/0-select/3-rank-impact/SKILL.md +0 -39
- package/plugins/session-manager-dev/skills/issue-address/0-select/SKILL.md +0 -75
- package/plugins/session-manager-dev/skills/issue-address/1-confirm-open/SKILL.md +0 -39
- package/plugins/session-manager-dev/skills/issue-address/2-claim/SKILL.md +0 -57
- package/plugins/session-manager-dev/skills/issue-address/3-reproduce/SKILL.md +0 -40
- package/plugins/session-manager-dev/skills/issue-address/4-fix/SKILL.md +0 -33
- package/plugins/session-manager-dev/skills/issue-address/5-verify/SKILL.md +0 -40
- package/plugins/session-manager-dev/skills/issue-address/SKILL.md +0 -120
- package/plugins/session-manager-dev/skills/local-project-health/SKILL.md +0 -58
- package/plugins/session-manager-dev/skills/memory-sanitation/SKILL.md +0 -147
- package/plugins/session-manager-dev/skills/ops-sweep/SKILL.md +0 -137
- package/plugins/session-manager-dev/skills/pr-review-sweep/0-fetch/SKILL.md +0 -41
- package/plugins/session-manager-dev/skills/pr-review-sweep/1-classify/SKILL.md +0 -56
- package/plugins/session-manager-dev/skills/pr-review-sweep/2-check-fixed/SKILL.md +0 -49
- package/plugins/session-manager-dev/skills/pr-review-sweep/3-queue/SKILL.md +0 -57
- package/plugins/session-manager-dev/skills/pr-review-sweep/4-land-and-resolve/SKILL.md +0 -60
- package/plugins/session-manager-dev/skills/pr-review-sweep/SKILL.md +0 -124
- package/plugins/session-manager-dev/skills/pr-signal/SKILL.md +0 -67
- package/plugins/session-manager-dev/skills/project-status/SKILL.md +0 -243
- package/plugins/session-manager-dev/skills/requesting-code-review/SKILL.md +0 -98
- package/plugins/session-manager-dev/skills/requesting-code-review/code-reviewer.md +0 -146
- package/src/main/lib/rateLimitDetect.cjs +0 -35
- /package/src/main/lib/{agentEffortResolve.cjs → claude/agentEffortResolve.cjs} +0 -0
- /package/src/main/lib/{claudeCliCaps.cjs → claude/claudeCliCaps.cjs} +0 -0
- /package/src/main/lib/{usageCircuit.cjs → claude/usageCircuit.cjs} +0 -0
- /package/src/main/lib/{epicSpawnCwd.cjs → epic/epicSpawnCwd.cjs} +0 -0
- /package/src/main/lib/{customerFeedbackAdminRoutes.cjs → feedback-remote/customerFeedbackAdminRoutes.cjs} +0 -0
- /package/src/main/lib/{remoteE2eCrypto.cjs → feedback-remote/remoteE2eCrypto.cjs} +0 -0
- /package/src/main/lib/{branchSweep.cjs → git/branchSweep.cjs} +0 -0
- /package/src/main/lib/{gitExec.cjs → git/gitExec.cjs} +0 -0
- /package/src/main/lib/{jobWorktree.cjs → git/jobWorktree.cjs} +0 -0
- /package/src/main/lib/{jobWorktreeBootLive.cjs → git/jobWorktreeBootLive.cjs} +0 -0
- /package/src/main/lib/{jobWorktreeTerminalOrphanLive.cjs → git/jobWorktreeTerminalOrphanLive.cjs} +0 -0
- /package/src/main/lib/{builtinMacros.cjs → persona-macro/builtinMacros.cjs} +0 -0
- /package/src/main/lib/{personaImportHealth.cjs → persona-macro/personaImportHealth.cjs} +0 -0
- /package/src/main/lib/{shippedPersonaSeeds.cjs → persona-macro/shippedPersonaSeeds.cjs} +0 -0
- /package/src/main/lib/{planValidator.cjs → prd/planValidator.cjs} +0 -0
- /package/src/main/lib/{prdAuthoringSeed.cjs → prd/prdAuthoringSeed.cjs} +0 -0
- /package/src/main/lib/{prdDisposition.cjs → prd/prdDisposition.cjs} +0 -0
- /package/src/main/lib/{prdFrontmatter.cjs → prd/prdFrontmatter.cjs} +0 -0
- /package/src/main/lib/{prdSizing.cjs → prd/prdSizing.cjs} +0 -0
- /package/src/main/lib/{workTypeLibrary.cjs → prd/workTypeLibrary.cjs} +0 -0
- /package/src/main/lib/{childWithLog.cjs → process/childWithLog.cjs} +0 -0
- /package/src/main/lib/{cleanEnv.cjs → process/cleanEnv.cjs} +0 -0
- /package/src/main/lib/{defaultShell.cjs → process/defaultShell.cjs} +0 -0
- /package/src/main/lib/{killTree.cjs → process/killTree.cjs} +0 -0
- /package/src/main/lib/{loginShellPath.cjs → process/loginShellPath.cjs} +0 -0
- /package/src/main/lib/{procIdentity.cjs → process/procIdentity.cjs} +0 -0
- /package/src/main/lib/{singleInstanceGuard.cjs → process/singleInstanceGuard.cjs} +0 -0
- /package/src/main/lib/{smProcNames.cjs → process/smProcNames.cjs} +0 -0
- /package/src/main/lib/{timeoutShimScript.cjs → process/timeoutShimScript.cjs} +0 -0
- /package/src/main/lib/{winSpawn.cjs → process/winSpawn.cjs} +0 -0
- /package/src/main/lib/{adoptedRunSupervisor.cjs → scheduler/adoptedRunSupervisor.cjs} +0 -0
- /package/src/main/lib/{dispatchLoop.cjs → scheduler/dispatchLoop.cjs} +0 -0
- /package/src/main/lib/{dodDrainHook.cjs → scheduler/dodDrainHook.cjs} +0 -0
- /package/src/main/lib/{fixPlanSlug.cjs → scheduler/fixPlanSlug.cjs} +0 -0
- /package/src/main/lib/{gateAuthority.cjs → scheduler/gateAuthority.cjs} +0 -0
- /package/src/main/lib/{landedSinceRun.cjs → scheduler/landedSinceRun.cjs} +0 -0
- /package/src/main/lib/{loadGate.cjs → scheduler/loadGate.cjs} +0 -0
- /package/src/main/lib/{needsReviewLedger.cjs → scheduler/needsReviewLedger.cjs} +0 -0
- /package/src/main/lib/{queueHealth.cjs → scheduler/queueHealth.cjs} +0 -0
- /package/src/main/lib/{queueHistory.cjs → scheduler/queueHistory.cjs} +0 -0
- /package/src/main/lib/{scheduleJobSchema.cjs → scheduler/scheduleJobSchema.cjs} +0 -0
- /package/src/main/lib/{schedulerPaths.cjs → scheduler/schedulerPaths.cjs} +0 -0
- /package/src/main/lib/{terminalRunOutcome.cjs → scheduler/terminalRunOutcome.cjs} +0 -0
- /package/src/main/lib/{validationSentinels.cjs → scheduler/validationSentinels.cjs} +0 -0
- /package/src/main/lib/{crashTelemetry.cjs → telemetry/crashTelemetry.cjs} +0 -0
- /package/src/main/lib/{otlpTraceExporter.cjs → telemetry/otlpTraceExporter.cjs} +0 -0
- /package/src/main/lib/{telemetryConsent.cjs → telemetry/telemetryConsent.cjs} +0 -0
- /package/src/main/lib/{telemetryCounters.cjs → telemetry/telemetryCounters.cjs} +0 -0
- /package/src/main/lib/{encodeCwd.cjs → util/encodeCwd.cjs} +0 -0
- /package/src/main/lib/{expandHome.cjs → util/expandHome.cjs} +0 -0
- /package/src/main/lib/{extractJson.cjs → util/extractJson.cjs} +0 -0
- /package/src/main/lib/{fileTail.cjs → util/fileTail.cjs} +0 -0
- /package/src/main/lib/{headTailBuffer.cjs → util/headTailBuffer.cjs} +0 -0
- /package/src/main/lib/{kebabCase.cjs → util/kebabCase.cjs} +0 -0
- /package/src/main/lib/{lruCache.cjs → util/lruCache.cjs} +0 -0
- /package/src/main/lib/{withTimeout.cjs → util/withTimeout.cjs} +0 -0
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
* rather than a second hardcoded literal — this file matches git-porcelain
|
|
34
34
|
* RELATIVE paths, never builds an fs path, so opsPath() itself doesn't apply.
|
|
35
35
|
*/
|
|
36
|
-
const { OPS_ROOT_DIR: OPS_ROOT_SEGMENT } = require('
|
|
36
|
+
const { OPS_ROOT_DIR: OPS_ROOT_SEGMENT } = require('../opsOwnership.cjs');
|
|
37
37
|
|
|
38
38
|
/** True when `p` lives under an app-owned operations root. Pure. */
|
|
39
39
|
function isAppOwnedChurn(p) {
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
const fs = require('node:fs');
|
|
21
21
|
const path = require('node:path');
|
|
22
22
|
const { writeJsonAtomicSync } = require('./queueStore.cjs');
|
|
23
|
-
const { isDifferentProcess } = require('
|
|
23
|
+
const { isDifferentProcess } = require('../process/procIdentity.cjs');
|
|
24
24
|
|
|
25
25
|
const SUFFIX = '.supervisor.json';
|
|
26
26
|
const META_SUFFIX = '.meta.json';
|
|
@@ -39,8 +39,8 @@
|
|
|
39
39
|
|
|
40
40
|
const fs = require('node:fs');
|
|
41
41
|
const path = require('node:path');
|
|
42
|
-
const { readTail } = require('
|
|
43
|
-
const atomicFs = require('
|
|
42
|
+
const { readTail } = require('../util/fileTail.cjs');
|
|
43
|
+
const atomicFs = require('../util/atomicFs.cjs');
|
|
44
44
|
|
|
45
45
|
const LAUNCH_FAILURE_KINDS = Object.freeze({
|
|
46
46
|
/** HTTP 400 naming a thinking/effort/config parameter the model rejects — the issue-#11 signature. */
|
|
@@ -32,9 +32,9 @@ const fs = require('node:fs');
|
|
|
32
32
|
const fsp = require('node:fs/promises');
|
|
33
33
|
const path = require('node:path');
|
|
34
34
|
const crypto = require('node:crypto');
|
|
35
|
-
const { allProjectCwds, activeProjectCwds, bustProjectCwdCache } = require('
|
|
36
|
-
const { classifyCwd } = require('
|
|
37
|
-
const { assertOpsWrite, resolveOpsRoot, OPS_ROOT_DIR } = require('
|
|
35
|
+
const { allProjectCwds, activeProjectCwds, bustProjectCwdCache } = require('../activeSessions.cjs');
|
|
36
|
+
const { classifyCwd } = require('../cwdClassify.cjs');
|
|
37
|
+
const { assertOpsWrite, resolveOpsRoot, OPS_ROOT_DIR } = require('../opsOwnership.cjs');
|
|
38
38
|
const { ScheduleJobSchema } = require('./scheduleJobSchema.cjs');
|
|
39
39
|
const schedulerPaths = require('./schedulerPaths.cjs');
|
|
40
40
|
|
|
@@ -238,11 +238,11 @@ function shapeMachine(data) {
|
|
|
238
238
|
// classifyQueueStarvation's header for why the two must never merge.
|
|
239
239
|
lastDispatchAttemptAt: data.lastDispatchAttemptAt ?? null,
|
|
240
240
|
paused: data.paused ?? null,
|
|
241
|
-
// Upgrade-drain state (lib/upgradeDrain.cjs): deliberately NOT part of
|
|
241
|
+
// Upgrade-drain state (lib/scheduler/upgradeDrain.cjs): deliberately NOT part of
|
|
242
242
|
// `paused`, so a rate-limit pause can neither overwrite it nor have the
|
|
243
243
|
// manual-clear cooldown swallow it.
|
|
244
244
|
drain: data.drain && typeof data.drain === 'object' ? data.drain : null,
|
|
245
|
-
// Launch circuit breaker (lib/launchFailure.cjs): per-persona blocks and
|
|
245
|
+
// Launch circuit breaker (lib/scheduler/launchFailure.cjs): per-persona blocks and
|
|
246
246
|
// the degraded-mode env a persona is currently launching with. Machine
|
|
247
247
|
// state, not per-project: the broken thing is the installed CLI.
|
|
248
248
|
launchBlocks: data.launchBlocks && typeof data.launchBlocks === 'object' ? data.launchBlocks : {},
|
|
@@ -315,7 +315,7 @@ const PAUSED_HINT_RE = /"paused"|resumeAt/;
|
|
|
315
315
|
|
|
316
316
|
function logMachineStateRecovery({ level, message, meta }) {
|
|
317
317
|
try {
|
|
318
|
-
const { appendError } = require('
|
|
318
|
+
const { appendError } = require('../telemetry/opsErrorLog.cjs');
|
|
319
319
|
appendError({ cwd: schedulerPaths.machineStateLogCwd(), scope: 'scheduler', level, message, meta });
|
|
320
320
|
} catch { /* durable logging must never block recovery */ }
|
|
321
321
|
console.error(`[queueStore] ${message}`);
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
*/
|
|
13
13
|
'use strict';
|
|
14
14
|
|
|
15
|
-
const { appendAuditEvent } = require('
|
|
15
|
+
const { appendAuditEvent } = require('../telemetry/auditLog.cjs');
|
|
16
16
|
const { isProvablyDead, DEFAULT_GRACE_MS } = require('./reservationExpiry.cjs');
|
|
17
17
|
|
|
18
18
|
// slug of the job currently holding the lease, or null.
|
|
@@ -32,10 +32,10 @@
|
|
|
32
32
|
|
|
33
33
|
const fs = require('node:fs');
|
|
34
34
|
const path = require('node:path');
|
|
35
|
-
const { splitFrontmatter } = require('
|
|
36
|
-
const { readTail } = require('
|
|
37
|
-
const { resolvePrdWriteDir } = require('
|
|
38
|
-
const atomicFs = require('
|
|
35
|
+
const { splitFrontmatter } = require('../prd/prdFrontmatter.cjs');
|
|
36
|
+
const { readTail } = require('../util/fileTail.cjs');
|
|
37
|
+
const { resolvePrdWriteDir } = require('../prd/prdLocations.cjs');
|
|
38
|
+
const atomicFs = require('../util/atomicFs.cjs');
|
|
39
39
|
|
|
40
40
|
// ─── VERDICT_LABELS — deliberate duplicate ──────────────────────────────────
|
|
41
41
|
// Mirrors src/renderer/components/tabs/scheduler/sched-primitives.tsx:123-131.
|
|
@@ -9,9 +9,9 @@
|
|
|
9
9
|
|
|
10
10
|
const fs = require('node:fs');
|
|
11
11
|
const path = require('node:path');
|
|
12
|
-
const { readTail } = require('
|
|
13
|
-
const { detectRateLimitInLog } = require('
|
|
14
|
-
const { pidAlive } = require('
|
|
12
|
+
const { readTail } = require('../util/fileTail.cjs');
|
|
13
|
+
const { detectRateLimitInLog } = require('../claude/rateLimitDetect.cjs');
|
|
14
|
+
const { pidAlive } = require('../process/pidAlive.cjs');
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* Return true if pid is alive AND its cmdline looks like a claude process.
|
|
@@ -9,27 +9,20 @@
|
|
|
9
9
|
*/
|
|
10
10
|
'use strict';
|
|
11
11
|
|
|
12
|
-
const { pidAlive } = require('
|
|
12
|
+
const { pidAlive } = require('../process/pidAlive.cjs');
|
|
13
13
|
|
|
14
14
|
const DEFAULT_GRACE_MS = 10 * 60 * 1000;
|
|
15
15
|
|
|
16
|
-
// Thin alias over pidAlive.cjs's shared pidAlive() — kept as its own named
|
|
17
|
-
// export (rather than inlining the require at every call site) so existing
|
|
18
|
-
// imports of `defaultPidAlive` from this module keep working unchanged.
|
|
19
|
-
function defaultPidAlive(pid) {
|
|
20
|
-
return pidAlive(pid);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
16
|
/**
|
|
24
17
|
* @param {{ claimedAt: number, pid: number|null }} res
|
|
25
18
|
* @param {{ live: boolean, pidAlive?: (pid:number)=>boolean, now: number, graceMs?: number }} ctx
|
|
26
19
|
*/
|
|
27
|
-
function isProvablyDead(res, { live, pidAlive =
|
|
20
|
+
function isProvablyDead(res, { live, pidAlive: isAlive = pidAlive, now, graceMs = DEFAULT_GRACE_MS }) {
|
|
28
21
|
if (live) return false;
|
|
29
22
|
// Made after the pass began (i.e. this tick) — never expire it.
|
|
30
23
|
if (!Number.isFinite(res.claimedAt) || res.claimedAt > now) return false;
|
|
31
|
-
if (Number.isInteger(res.pid) && res.pid > 0) return !
|
|
24
|
+
if (Number.isInteger(res.pid) && res.pid > 0) return !isAlive(res.pid);
|
|
32
25
|
return now - res.claimedAt > graceMs;
|
|
33
26
|
}
|
|
34
27
|
|
|
35
|
-
module.exports = { isProvablyDead,
|
|
28
|
+
module.exports = { isProvablyDead, DEFAULT_GRACE_MS };
|
|
@@ -43,7 +43,7 @@ const DEFAULT_HOLD_MINUTES = 240;
|
|
|
43
43
|
// `NN-`) — reused here, not reimplemented, so formatReviewNotice's "blocks"
|
|
44
44
|
// wording can never disagree with what actually holds a dependent `pending`
|
|
45
45
|
// row in the real queue.
|
|
46
|
-
const { bareSlug } = require('
|
|
46
|
+
const { bareSlug } = require('../prd/depSlugResolve.cjs');
|
|
47
47
|
|
|
48
48
|
/**
|
|
49
49
|
* buildReviewNotice({ job, report, epicId, now, prior }) → ReviewNotice
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* runLogRetention.cjs — computes
|
|
5
|
-
* applies) a retention policy over `scheduled-plans/runs/`.
|
|
4
|
+
* runLogRetention.cjs — computes and applies a retention policy over `scheduled-plans/runs/`.
|
|
6
5
|
*
|
|
7
6
|
* That directory is a machine-level Session-Manager runtime artifact store
|
|
8
7
|
* (execution logs of the scheduler's own `claude -p` runs), not anything
|
|
@@ -26,10 +25,10 @@
|
|
|
26
25
|
* slug's own files.
|
|
27
26
|
*
|
|
28
27
|
* SAFETY MODEL (the point of this module — see the PRD that added it):
|
|
29
|
-
* -
|
|
30
|
-
* `schedulerRunLogRetention
|
|
31
|
-
*
|
|
32
|
-
*
|
|
28
|
+
* - Retention is ON by default (DEFAULT_RUN_LOG_RETENTION) when settings
|
|
29
|
+
* carry no `schedulerRunLogRetention`. An explicit `enabled: false` (or a
|
|
30
|
+
* config with no non-empty policy) opts out: computeReport, and
|
|
31
|
+
* applyRetention when opted out, only READ the filesystem.
|
|
33
32
|
* - An entry belonging to a job that is currently live — status `pending`
|
|
34
33
|
* (queued), `running`, `needs_review`, or `investigating` (the exact
|
|
35
34
|
* literals scheduler.cjs uses; see LIVE_STATUSES) — is never eligible,
|
|
@@ -51,6 +50,16 @@ const schedulerPaths = require('./schedulerPaths.cjs');
|
|
|
51
50
|
// checks) — 'completed' and 'failed' are the only terminal ones.
|
|
52
51
|
const LIVE_STATUSES = new Set(['pending', 'running', 'needs_review', 'investigating']);
|
|
53
52
|
|
|
53
|
+
/**
|
|
54
|
+
* Built-in policy applied when settings carry no `schedulerRunLogRetention`:
|
|
55
|
+
* drop runs older than 14 days but always keep each slug's newest 3.
|
|
56
|
+
* (Policy keys follow the module's own names: maxAgeDays / keepPerSlug.)
|
|
57
|
+
*/
|
|
58
|
+
const DEFAULT_RUN_LOG_RETENTION = Object.freeze({
|
|
59
|
+
enabled: true,
|
|
60
|
+
policy: Object.freeze({ maxAgeDays: 14, keepPerSlug: 3 }),
|
|
61
|
+
});
|
|
62
|
+
|
|
54
63
|
const META_SUFFIX = '.meta.json';
|
|
55
64
|
const DAY_MS = 24 * 60 * 60 * 1000;
|
|
56
65
|
|
|
@@ -259,11 +268,21 @@ function computeReport(runsDir, policy, opts) {
|
|
|
259
268
|
}
|
|
260
269
|
|
|
261
270
|
/**
|
|
262
|
-
*
|
|
263
|
-
*
|
|
271
|
+
* The effective retention config: the caller's `schedulerRunLogRetention`
|
|
272
|
+
* when present, else DEFAULT_RUN_LOG_RETENTION.
|
|
264
273
|
*/
|
|
265
|
-
function
|
|
274
|
+
function resolveRetentionConfig(settings) {
|
|
266
275
|
const cfg = settings && settings.schedulerRunLogRetention;
|
|
276
|
+
return cfg == null ? DEFAULT_RUN_LOG_RETENTION : cfg;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* True when the effective config (see resolveRetentionConfig) has
|
|
281
|
+
* `enabled === true` plus a non-empty policy. An absent setting resolves to
|
|
282
|
+
* the default (enabled); an explicit `enabled: false` opts out.
|
|
283
|
+
*/
|
|
284
|
+
function isRetentionEnabled(settings) {
|
|
285
|
+
const cfg = resolveRetentionConfig(settings);
|
|
267
286
|
if (!cfg || cfg.enabled !== true) return false;
|
|
268
287
|
const policy = cfg.policy;
|
|
269
288
|
return !!policy && (policy.maxAgeDays != null || policy.keepPerSlug != null);
|
|
@@ -372,7 +391,7 @@ function sweepOrphanDirs(runsDir, runningRunIds, errors) {
|
|
|
372
391
|
* nothing removed.
|
|
373
392
|
*/
|
|
374
393
|
function applyRetention(runsDir, settings, opts) {
|
|
375
|
-
const cfg = (settings
|
|
394
|
+
const cfg = resolveRetentionConfig(settings);
|
|
376
395
|
const policy = (cfg && cfg.policy) || {};
|
|
377
396
|
const enabled = isRetentionEnabled(settings);
|
|
378
397
|
const liveKeys = resolveLiveKeysForApply(runsDir, opts, enabled);
|
|
@@ -381,7 +400,7 @@ function applyRetention(runsDir, settings, opts) {
|
|
|
381
400
|
if (!enabled) {
|
|
382
401
|
return {
|
|
383
402
|
deleted: false,
|
|
384
|
-
reason: 'dry-run: schedulerRunLogRetention
|
|
403
|
+
reason: 'dry-run: schedulerRunLogRetention is disabled (enabled !== true, or has no policy)',
|
|
385
404
|
report,
|
|
386
405
|
};
|
|
387
406
|
}
|
|
@@ -424,8 +443,8 @@ function applyRetention(runsDir, settings, opts) {
|
|
|
424
443
|
* applyRetention's own internal queueStore fallback (resolveLiveKeysForApply
|
|
425
444
|
* above), which exists only as a defensive net for callers who forget to
|
|
426
445
|
* thread live-job info through, not as this module's primary path. Deletion
|
|
427
|
-
*
|
|
428
|
-
* schedulerRunLogRetention.enabled ===
|
|
446
|
+
* happens unless the read config opts out with
|
|
447
|
+
* schedulerRunLogRetention.enabled === false (see isRetentionEnabled).
|
|
429
448
|
*
|
|
430
449
|
* Intended to be called once per app boot (see index.cjs's deferred 30s
|
|
431
450
|
* startup timer, alongside finalizeClosedDays) — never on its own timer.
|
|
@@ -438,6 +457,8 @@ function runBootSweep(opts) {
|
|
|
438
457
|
}
|
|
439
458
|
|
|
440
459
|
module.exports = {
|
|
460
|
+
DEFAULT_RUN_LOG_RETENTION,
|
|
461
|
+
resolveRetentionConfig,
|
|
441
462
|
LIVE_STATUSES,
|
|
442
463
|
isLiveJob,
|
|
443
464
|
liveKeysFromJobs,
|
|
@@ -30,8 +30,8 @@
|
|
|
30
30
|
*/
|
|
31
31
|
'use strict';
|
|
32
32
|
|
|
33
|
-
const { appendAuditEvent } = require('
|
|
34
|
-
const telemetryCounters = require('
|
|
33
|
+
const { appendAuditEvent } = require('../telemetry/auditLog.cjs');
|
|
34
|
+
const telemetryCounters = require('../telemetry/telemetryCounters.cjs');
|
|
35
35
|
const queueHistory = require('./queueHistory.cjs');
|
|
36
36
|
const { buildNeedsReviewEntryLine, buildNeedsReviewResolutionLine } = require('./needsReviewLedger.cjs');
|
|
37
37
|
|
|
@@ -42,7 +42,7 @@ const { buildNeedsReviewEntryLine, buildNeedsReviewResolutionLine } = require('.
|
|
|
42
42
|
const FINISH_STATUSES = new Set(['completed', 'failed', 'skipped', 'needs_review']);
|
|
43
43
|
|
|
44
44
|
// Bounded so queue.json (mutation cost, broadcast payload, pickNextBatch
|
|
45
|
-
// scan) stays small — same rationale as lib/queueHistory.cjs's retention
|
|
45
|
+
// scan) stays small — same rationale as lib/scheduler/queueHistory.cjs's retention
|
|
46
46
|
// window.
|
|
47
47
|
const STATUS_HISTORY_CAP = 20;
|
|
48
48
|
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
const path = require('node:path');
|
|
16
16
|
const os = require('node:os');
|
|
17
17
|
const { projectJobCap, quietMachineWaitMs } = require('./schedulerConfig.cjs');
|
|
18
|
-
const { bareSlug } = require('
|
|
18
|
+
const { bareSlug, isSatisfiedDepRow } = require('../prd/depSlugResolve.cjs');
|
|
19
19
|
|
|
20
20
|
const DEFAULT_PROJECT_CWD = path.join(os.homedir(), 'Projects', 'session-manager');
|
|
21
21
|
|
|
@@ -127,20 +127,16 @@ function findUnresolvableDepRoots(projectJobs, satisfiedSlugs = new Set()) {
|
|
|
127
127
|
|
|
128
128
|
function findBlockingDep(job, projectJobs, satisfiedSlugs = new Set()) {
|
|
129
129
|
const { rowsForDep, isKnownSatisfied } = makeDepResolver(projectJobs, satisfiedSlugs);
|
|
130
|
-
// A dep row is blocking unless
|
|
131
|
-
//
|
|
132
|
-
// auto-resolve terminal decision (scheduler.cjs's
|
|
133
|
-
// applyNeedsReviewAutoResolve). That skip is deliberately NOT the
|
|
130
|
+
// A dep row is blocking unless isSatisfiedDepRow — 'completed', or a
|
|
131
|
+
// `needsReviewAutoResolvedSkip` skip. That skip is deliberately NOT the
|
|
134
132
|
// "PRD source vanished, a human must author a fresh PRD" skip the
|
|
135
|
-
// heldBySkippedDep messaging
|
|
136
|
-
//
|
|
137
|
-
//
|
|
138
|
-
//
|
|
139
|
-
const isSatisfiedRow = (dep) => dep.status === 'completed'
|
|
140
|
-
|| (dep.status === 'skipped' && dep.needsReviewAutoResolvedSkip === true);
|
|
133
|
+
// heldBySkippedDep messaging describes — it already got every bounded
|
|
134
|
+
// chance to resolve itself, so treating it as a permanent dependsOn block
|
|
135
|
+
// would defeat the auto-resolve pass. runVerify.checkDeps MUST use the same
|
|
136
|
+
// predicate, or every run of the dependent is downgraded and re-dispatched.
|
|
141
137
|
return (job.dependsOn ?? []).find((slug) => {
|
|
142
138
|
const rows = rowsForDep(slug);
|
|
143
|
-
if (rows.length > 0) return rows.some((dep) => !
|
|
139
|
+
if (rows.length > 0) return rows.some((dep) => !isSatisfiedDepRow(dep));
|
|
144
140
|
return !isKnownSatisfied(slug);
|
|
145
141
|
});
|
|
146
142
|
}
|
|
@@ -250,7 +246,7 @@ function pickForProject(projectJobs, runningSlugsInProject, slots, heldSlugs = n
|
|
|
250
246
|
// (evaluated before this function is ever called) is the only path that
|
|
251
247
|
// can fire one, since dispatching one is a whole-tick, all-projects
|
|
252
248
|
// exclusive decision this per-project function can't see.
|
|
253
|
-
// Launch-gate holds (lib/launchFailure.cjs, issue #11): a pending row
|
|
249
|
+
// Launch-gate holds (lib/scheduler/launchFailure.cjs, issue #11): a pending row
|
|
254
250
|
// whose launch persona is circuit-broken is NOT a candidate this tick and
|
|
255
251
|
// must not shadow a pickable sibling behind it. It still gets a per-row
|
|
256
252
|
// hold record so the Queue UI says why it is waiting.
|
|
@@ -68,7 +68,7 @@ module.exports = {
|
|
|
68
68
|
RECONCILE_SLOW_PASS_MS: 2_000,
|
|
69
69
|
// Terminal (completed/failed) jobs older than this move from queue.json's
|
|
70
70
|
// hot jobs[] into the append-only history.jsonl sidecar. See
|
|
71
|
-
// src/main/lib/queueHistory.cjs.
|
|
71
|
+
// src/main/lib/scheduler/queueHistory.cjs.
|
|
72
72
|
HISTORY_RETENTION_MS: 7 * 24 * 60 * 60_000,
|
|
73
73
|
// Cadence for the in-app intraday refresher that keeps TODAY's History
|
|
74
74
|
// rollup line current (see historyAggregator.cjs's refreshIntradayToday).
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
'use strict';
|
|
9
9
|
|
|
10
|
-
const { appendAuditEvent } = require('
|
|
10
|
+
const { appendAuditEvent } = require('../telemetry/auditLog.cjs');
|
|
11
11
|
const { isProvablyDead, DEFAULT_GRACE_MS } = require('./reservationExpiry.cjs');
|
|
12
12
|
|
|
13
13
|
const investigations = new Map(); // slug -> { claimedAt, pid }
|
|
@@ -27,8 +27,8 @@ const crypto = require('node:crypto');
|
|
|
27
27
|
const fs = require('node:fs');
|
|
28
28
|
const path = require('node:path');
|
|
29
29
|
const { sessionSlotsConfigPath } = require('./schedulerPaths.cjs');
|
|
30
|
-
const { appendAuditEvent } = require('
|
|
31
|
-
const atomicFs = require('
|
|
30
|
+
const { appendAuditEvent } = require('../telemetry/auditLog.cjs');
|
|
31
|
+
const atomicFs = require('../util/atomicFs.cjs');
|
|
32
32
|
const { isProvablyDead, DEFAULT_GRACE_MS } = require('./reservationExpiry.cjs');
|
|
33
33
|
|
|
34
34
|
const MIN_SLOTS = 0;
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
const fs = require('node:fs');
|
|
25
25
|
const path = require('node:path');
|
|
26
26
|
const schedulerPaths = require('./schedulerPaths.cjs');
|
|
27
|
-
const atomicFs = require('
|
|
27
|
+
const atomicFs = require('../util/atomicFs.cjs');
|
|
28
28
|
|
|
29
29
|
// Observed max job run is 240 min; 4 h converts a stuck drain to an abort.
|
|
30
30
|
const DEFAULT_DRAIN_DEADLINE_MS = 4 * 60 * 60_000;
|
|
@@ -32,11 +32,8 @@ const DEFAULT_DRAIN_DEADLINE_MS = 4 * 60 * 60_000;
|
|
|
32
32
|
// relaunch is picked up by the watchdog again.
|
|
33
33
|
const RESTARTING_MARKER_TTL_MS = 5 * 60_000;
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function readJsonSafe(file) {
|
|
35
|
+
/** Object-or-null view over atomicFs.readJsonOrSync (arrays/scalars → null). */
|
|
36
|
+
function readJsonObject(file) {
|
|
40
37
|
const v = atomicFs.readJsonOrSync(file, null);
|
|
41
38
|
return v && typeof v === 'object' ? v : null;
|
|
42
39
|
}
|
|
@@ -44,7 +41,7 @@ function readJsonSafe(file) {
|
|
|
44
41
|
// ---------- request file ----------
|
|
45
42
|
|
|
46
43
|
function readRestartRequest(file = schedulerPaths.restartRequestPath()) {
|
|
47
|
-
return
|
|
44
|
+
return readJsonObject(file);
|
|
48
45
|
}
|
|
49
46
|
|
|
50
47
|
/**
|
|
@@ -60,7 +57,7 @@ function requestRestart({ reason, requestedBy } = {}, { file = schedulerPaths.re
|
|
|
60
57
|
requestedBy: typeof requestedBy === 'string' && requestedBy ? requestedBy : 'unknown',
|
|
61
58
|
requestedAt: new Date(now).toISOString(),
|
|
62
59
|
};
|
|
63
|
-
writeJsonAtomicSync(file, request);
|
|
60
|
+
atomicFs.writeJsonAtomicSync(file, request);
|
|
64
61
|
return request;
|
|
65
62
|
}
|
|
66
63
|
|
|
@@ -69,7 +66,7 @@ function stampDrainCompleted(now = Date.now(), file = schedulerPaths.restartRequ
|
|
|
69
66
|
const existing = readRestartRequest(file);
|
|
70
67
|
if (!existing) return null;
|
|
71
68
|
const stamped = { ...existing, drainCompletedAt: new Date(now).toISOString() };
|
|
72
|
-
writeJsonAtomicSync(file, stamped);
|
|
69
|
+
atomicFs.writeJsonAtomicSync(file, stamped);
|
|
73
70
|
return stamped;
|
|
74
71
|
}
|
|
75
72
|
|
|
@@ -151,7 +148,7 @@ function installedBuildDiffers({ running, installed } = {}) {
|
|
|
151
148
|
// ---------- restarting marker (watchdog) ----------
|
|
152
149
|
|
|
153
150
|
function markRestarting({ file = schedulerPaths.restartingMarkerPath(), now = Date.now(), ttlMs = RESTARTING_MARKER_TTL_MS } = {}) {
|
|
154
|
-
writeJsonAtomicSync(file, { pid: process.pid, at: now, expiresAt: now + ttlMs });
|
|
151
|
+
atomicFs.writeJsonAtomicSync(file, { pid: process.pid, at: now, expiresAt: now + ttlMs });
|
|
155
152
|
}
|
|
156
153
|
|
|
157
154
|
function clearRestartingMarker(file = schedulerPaths.restartingMarkerPath()) {
|
|
@@ -160,7 +157,7 @@ function clearRestartingMarker(file = schedulerPaths.restartingMarkerPath()) {
|
|
|
160
157
|
|
|
161
158
|
/** True while the marker exists and has not expired (bounded lifetime). */
|
|
162
159
|
function isRestartingMarkerActive({ file = schedulerPaths.restartingMarkerPath(), now = Date.now() } = {}) {
|
|
163
|
-
const m =
|
|
160
|
+
const m = readJsonObject(file);
|
|
164
161
|
return Boolean(m) && typeof m.expiresAt === 'number' && now < m.expiresAt;
|
|
165
162
|
}
|
|
166
163
|
|
|
@@ -7,9 +7,9 @@ const fs = require('node:fs');
|
|
|
7
7
|
const path = require('node:path');
|
|
8
8
|
const schedulerPaths = require('./schedulerPaths.cjs');
|
|
9
9
|
const { isRestartingMarkerActive } = require('./upgradeDrain.cjs');
|
|
10
|
-
const { pidAlive
|
|
11
|
-
const atomicFs = require('
|
|
12
|
-
const { isPackagedApp } = require('
|
|
10
|
+
const { pidAlive } = require('../process/pidAlive.cjs');
|
|
11
|
+
const atomicFs = require('../util/atomicFs.cjs');
|
|
12
|
+
const { isPackagedApp } = require('../appRuntime.cjs');
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
|
|
@@ -142,19 +142,6 @@ function evaluateDispatchLiveness(entry, now = Date.now(), { deadMs = DEFAULT_DI
|
|
|
142
142
|
return { dead: true, reason: 'dispatch-dead' };
|
|
143
143
|
}
|
|
144
144
|
|
|
145
|
-
/**
|
|
146
|
-
* isPidAlive(pid) → boolean
|
|
147
|
-
*
|
|
148
|
-
* Thin alias over pidAlive.cjs's shared pidAlive() — single source of truth
|
|
149
|
-
* for the "is this recorded pid still alive" check used by
|
|
150
|
-
* checkAppLiveness's defense-in-depth relaunch gate. Kept as a named export
|
|
151
|
-
* here (rather than inlining the require at every call site) so existing
|
|
152
|
-
* imports of `isPidAlive` from this module keep working unchanged.
|
|
153
|
-
*/
|
|
154
|
-
function isPidAlive(pid) {
|
|
155
|
-
return pidAliveCore(pid);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
145
|
// Offline queue.json reconciliation (orphaned 'running' jobs whose pid died
|
|
159
146
|
// while Electron wasn't running) used to live here as reconcileQueueOffline().
|
|
160
147
|
// PRD 686 moved that responsibility into src/main/scheduler.cjs's own boot
|
|
@@ -188,7 +175,7 @@ function checkAppLiveness({
|
|
|
188
175
|
return { alive: true, reason: 'heartbeat-fresh' };
|
|
189
176
|
}
|
|
190
177
|
const last = readLastHeartbeat(heartbeatPath);
|
|
191
|
-
if (last !== null && typeof last.pid === 'number' &&
|
|
178
|
+
if (last !== null && typeof last.pid === 'number' && pidAlive(last.pid)) {
|
|
192
179
|
return { alive: true, reason: 'pid-alive-heartbeat-stale' };
|
|
193
180
|
}
|
|
194
181
|
return { alive: false, reason: 'stale-and-dead' };
|
|
@@ -408,7 +395,7 @@ function releaseLock(lockPath) {
|
|
|
408
395
|
* dependency fails inside maybeFinalizeHistory's try/catch, not at require
|
|
409
396
|
* time for the whole watchdog script. */
|
|
410
397
|
function defaultFinalizeClosedDays(opts) {
|
|
411
|
-
const { finalizeClosedDays } = require('
|
|
398
|
+
const { finalizeClosedDays } = require('../../historyAggregator.cjs');
|
|
412
399
|
return finalizeClosedDays(opts);
|
|
413
400
|
}
|
|
414
401
|
|
|
@@ -470,7 +457,6 @@ module.exports = {
|
|
|
470
457
|
readLastHeartbeatTs,
|
|
471
458
|
heartbeatFresh,
|
|
472
459
|
evaluateDispatchLiveness,
|
|
473
|
-
isPidAlive,
|
|
474
460
|
localDateStr,
|
|
475
461
|
maybeFinalizeHistory,
|
|
476
462
|
tryAcquireLock,
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
const fs = require('node:fs');
|
|
19
19
|
const path = require('node:path');
|
|
20
20
|
|
|
21
|
-
const { auditLogPath } = require('
|
|
21
|
+
const { auditLogPath } = require('../scheduler/schedulerPaths.cjs');
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
24
|
* Best-effort identity of the process making this call — there is no
|
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
const fs = require('node:fs');
|
|
15
15
|
const os = require('node:os');
|
|
16
16
|
const path = require('node:path');
|
|
17
|
-
const { assertOpsWrite } = require('
|
|
18
|
-
const { isEphemeralCwd } = require('
|
|
17
|
+
const { assertOpsWrite } = require('../opsOwnership.cjs');
|
|
18
|
+
const { isEphemeralCwd } = require('../ephemeralCwd.cjs');
|
|
19
19
|
|
|
20
20
|
// Same redaction policy as logs.cjs's sanitizeMeta — kept independent (not
|
|
21
21
|
// shared/required) so this module has no dependency on the Electron `app`
|
|
@@ -33,7 +33,7 @@ function sanitizeMeta(meta) {
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
function logsDir(cwd) {
|
|
36
|
-
const { opsPath } = require('
|
|
36
|
+
const { opsPath } = require('../opsOwnership.cjs');
|
|
37
37
|
return opsPath(cwd, 'logs');
|
|
38
38
|
}
|
|
39
39
|
|
|
@@ -108,7 +108,7 @@ function writeLocalLine({ cwd, scope, level, tabId, epicId, tags, message, meta
|
|
|
108
108
|
function reportToTelemetry({ cwd, scope, level, tabId, epicId, tags, message }) {
|
|
109
109
|
try {
|
|
110
110
|
const telemetryClient = require('./telemetryClient.cjs');
|
|
111
|
-
const { projectRootOf } = require('
|
|
111
|
+
const { projectRootOf } = require('../activeSessions.cjs');
|
|
112
112
|
const normalizedCwd = projectRootOf(cwd) || cwd;
|
|
113
113
|
const autoTags = [
|
|
114
114
|
`scope:${scope || 'unknown'}`,
|
|
@@ -70,7 +70,7 @@ const os = require('node:os');
|
|
|
70
70
|
const path = require('node:path');
|
|
71
71
|
const crypto = require('node:crypto');
|
|
72
72
|
|
|
73
|
-
const config = require('
|
|
73
|
+
const config = require('../../config.cjs');
|
|
74
74
|
|
|
75
75
|
const DEFAULT_LIMIT = 500;
|
|
76
76
|
const RETENTION_DAYS = 30;
|
|
@@ -97,9 +97,9 @@ function watermarksPath() {
|
|
|
97
97
|
|
|
98
98
|
function resolveDeps(deps = {}) {
|
|
99
99
|
return {
|
|
100
|
-
sessionsStore: deps.sessionsStore || require('
|
|
101
|
-
isEphemeralCwd: deps.isEphemeralCwd || require('
|
|
102
|
-
resolveProjectContext: deps.resolveProjectContext || require('
|
|
100
|
+
sessionsStore: deps.sessionsStore || require('../../sessionsStore.cjs'),
|
|
101
|
+
isEphemeralCwd: deps.isEphemeralCwd || require('../ephemeralCwd.cjs').isEphemeralCwd,
|
|
102
|
+
resolveProjectContext: deps.resolveProjectContext || require('../projectRootResolve.cjs').resolveProjectContext,
|
|
103
103
|
telemetryClient: deps.telemetryClient || require('./telemetryClient.cjs'),
|
|
104
104
|
opsErrorLog: deps.opsErrorLog || require('./opsErrorLog.cjs'),
|
|
105
105
|
config: deps.config || config,
|
|
@@ -22,7 +22,7 @@ function resolveDeps(deps = {}) {
|
|
|
22
22
|
return {
|
|
23
23
|
telemetrySettings: deps.telemetrySettings || require('./telemetrySettings.cjs'),
|
|
24
24
|
telemetryClient: deps.telemetryClient || require('./telemetryClient.cjs'),
|
|
25
|
-
buildMachineProfile: deps.buildMachineProfile || require('
|
|
25
|
+
buildMachineProfile: deps.buildMachineProfile || require('../machineProfile.cjs').buildMachineProfile,
|
|
26
26
|
telemetryCounters: deps.telemetryCounters || require('./telemetryCounters.cjs'),
|
|
27
27
|
};
|
|
28
28
|
}
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
* returned promise resolves once accepted/dropped, but callers are free to
|
|
21
21
|
* not await it). Telemetry failing must stay invisible to the user.
|
|
22
22
|
*
|
|
23
|
-
* Single-writer precedent (../lib/instanceLock.cjs): this module assumes the
|
|
23
|
+
* Single-writer precedent (../lib/process/instanceLock.cjs): this module assumes the
|
|
24
24
|
* app's main process is the only writer of the queue/sent-set files for a
|
|
25
25
|
* given machine. It does not itself arbitrate multiple OS processes.
|
|
26
26
|
*
|
|
@@ -35,9 +35,9 @@ const os = require('node:os');
|
|
|
35
35
|
const path = require('node:path');
|
|
36
36
|
const crypto = require('node:crypto');
|
|
37
37
|
|
|
38
|
-
const config = require('
|
|
38
|
+
const config = require('../../config.cjs');
|
|
39
39
|
const telemetrySettings = require('./telemetrySettings.cjs');
|
|
40
|
-
const machineProfile = require('
|
|
40
|
+
const machineProfile = require('../machineProfile.cjs');
|
|
41
41
|
|
|
42
42
|
const MAX_BATCH = 50;
|
|
43
43
|
const QUEUE_CAP_COUNT = 5000;
|
|
@@ -104,7 +104,7 @@ const S = {
|
|
|
104
104
|
*/
|
|
105
105
|
function logWarn(message, meta) {
|
|
106
106
|
try {
|
|
107
|
-
const fn = S.logger || require('
|
|
107
|
+
const fn = S.logger || require('../../logs.cjs').writeLine;
|
|
108
108
|
fn({ scope: 'telemetry', level: 'warn', message, meta });
|
|
109
109
|
} catch { /* logs unavailable outside an Electron runtime */ }
|
|
110
110
|
}
|
|
@@ -647,18 +647,20 @@ function describeFailureStatus(status) {
|
|
|
647
647
|
return status === 0 ? 'network error' : `HTTP ${status}`;
|
|
648
648
|
}
|
|
649
649
|
|
|
650
|
-
function applyFailureBackoff(status) {
|
|
650
|
+
function applyFailureBackoff(status, channel) {
|
|
651
651
|
if (status === 429 || status === 0 || status >= 500) {
|
|
652
652
|
S.consecutiveFailures += 1;
|
|
653
653
|
const ms = Math.min(BACKOFF_BASE_MS * (2 ** (S.consecutiveFailures - 1)), BACKOFF_MAX_MS);
|
|
654
654
|
S.backoffUntil = Date.now() + ms;
|
|
655
655
|
S.lastError = { status, message: describeFailureStatus(status), at: Date.now() };
|
|
656
|
+
logWarn('telemetry send failed', { channel, status, consecutiveFailures: S.consecutiveFailures, backoffMs: ms });
|
|
656
657
|
return;
|
|
657
658
|
}
|
|
658
659
|
if (status >= 400 && status < 500) {
|
|
659
660
|
// Malformed-contract circuit breaker (includes 401) — not retried.
|
|
660
661
|
S.disabledForProcess = true;
|
|
661
662
|
S.lastError = { status, message: describeFailureStatus(status), at: Date.now() };
|
|
663
|
+
logWarn('telemetry disabled for process', { status });
|
|
662
664
|
}
|
|
663
665
|
}
|
|
664
666
|
|
|
@@ -705,7 +707,7 @@ async function flushImpl(reason) {
|
|
|
705
707
|
result.sent.push(r.recordId);
|
|
706
708
|
} else {
|
|
707
709
|
result.failed.push(r.recordId);
|
|
708
|
-
applyFailureBackoff(res.status);
|
|
710
|
+
applyFailureBackoff(res.status, channel);
|
|
709
711
|
sawFailure = true;
|
|
710
712
|
break;
|
|
711
713
|
}
|
|
@@ -726,7 +728,7 @@ async function flushImpl(reason) {
|
|
|
726
728
|
}
|
|
727
729
|
} else {
|
|
728
730
|
for (const r of batch) result.failed.push(r.recordId);
|
|
729
|
-
applyFailureBackoff(res.status);
|
|
731
|
+
applyFailureBackoff(res.status, channel);
|
|
730
732
|
sawFailure = true;
|
|
731
733
|
break;
|
|
732
734
|
}
|
|
@@ -739,7 +741,9 @@ async function flushImpl(reason) {
|
|
|
739
741
|
if (safeReason === 'daily' && result.failed.length === 0) {
|
|
740
742
|
S.settings = await telemetrySettings.save({ lastDailyFlushAt: new Date().toISOString() });
|
|
741
743
|
}
|
|
742
|
-
} catch {
|
|
744
|
+
} catch (e) {
|
|
745
|
+
logWarn('telemetry flush threw', { error: e && e.message ? e.message : String(e) });
|
|
746
|
+
}
|
|
743
747
|
S.lastFlushAt = Date.now();
|
|
744
748
|
S.lastFlushReason = safeReason;
|
|
745
749
|
return result;
|
|
@@ -26,7 +26,7 @@ const fsp = require('node:fs/promises');
|
|
|
26
26
|
const path = require('node:path');
|
|
27
27
|
const os = require('node:os');
|
|
28
28
|
const crypto = require('node:crypto');
|
|
29
|
-
const config = require('
|
|
29
|
+
const config = require('../../config.cjs');
|
|
30
30
|
|
|
31
31
|
const SCHEMA_VERSION = 1;
|
|
32
32
|
const DAY_MS = 24 * 60 * 60 * 1000;
|