claude-code-session-manager 0.86.0 → 0.88.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/README.md +26 -53
- package/dist/assets/AgentLibrary-BZ6IY2g1.js +3 -0
- package/dist/assets/{DataModel-Q4jhl24R.js → DataModel-dAoGAODX.js} +1 -1
- package/dist/assets/{History-Cj2FejEo.js → History-CF157HyX.js} +2 -2
- package/dist/assets/{Hooks-CaelQI6t.js → Hooks-CCPPipBk.js} +3 -3
- package/dist/assets/{HostBilko--v7cMR8I.js → HostBilko-Dlmz2m06.js} +1 -1
- package/dist/assets/{Library-DgI9oCCZ.js → Library-BaXcboWX.js} +1 -1
- package/dist/assets/{ListDetail-DYUZN-x-.js → ListDetail-CoUCzG5S.js} +1 -1
- package/dist/assets/MarkdownEditor-DTg3JlOT.js +1 -0
- package/dist/assets/{McpServers-ypCYURh3.js → McpServers-DdjY1sA3.js} +2 -2
- package/dist/assets/{Memory-C2qYp-3M.js → Memory-BJ3Jlw0C.js} +4 -4
- package/dist/assets/{Panel-Cj2kw-Zv.js → Panel-ygRSgc41.js} +1 -1
- package/dist/assets/Permissions-m0KAnccF.js +3 -0
- package/dist/assets/{Plugins-C1Vj8_dU.js → Plugins-CJRl6B3Q.js} +2 -2
- package/dist/assets/{ProvenanceBadge-DczPNM5U.js → ProvenanceBadge-w8cnlVvW.js} +1 -1
- package/dist/assets/{SaveBar-Cd_7U6Gb.js → SaveBar-BpyPcUIk.js} +1 -1
- package/dist/assets/Scheduler-D2ppxSfy.js +14 -0
- package/dist/assets/{ScopeSwitcher-DVSyI44-.js → ScopeSwitcher-EyuIwt-j.js} +1 -1
- package/dist/assets/Settings-BHSGGFEc.js +3 -0
- package/dist/assets/{SkillReferenceGraph-CUv1_Q2c.js → SkillReferenceGraph-BNaZ2JCF.js} +1 -1
- package/dist/assets/{Skills-C_YHkAy-.js → Skills-Dl3q75QV.js} +2 -2
- package/dist/assets/{SystemPrompt-B8R7T9xn.js → SystemPrompt-Bg6F-Cyp.js} +1 -1
- package/dist/assets/{TagLibrary-dj9YHWyy.js → TagLibrary-BSutflCy.js} +1 -1
- package/dist/assets/{TiptapBody-DnSBUjHE.js → TiptapBody-CXih4xrc.js} +1 -1
- package/dist/assets/{Toggle-CjV_BJn6.js → Toggle-2qtUHhA9.js} +1 -1
- package/dist/assets/{index-CXFQIPhO.js → index-B3emy2oI.js} +583 -583
- package/dist/assets/{index-CDo9xBR9.css → index-BHTX4OTc.css} +1 -1
- package/dist/assets/settingsSchema-CdzxaqwM.js +3 -0
- package/dist/assets/{whisperWorker-Dbia1OpC.js → whisperWorker-C7ZGQwKg.js} +7 -7
- package/dist/index.html +2 -2
- package/dist/vad/ort-wasm-simd-threaded.asyncify.mjs +106 -110
- package/dist/vad/ort-wasm-simd-threaded.asyncify.wasm +0 -0
- package/dist/vad/ort-wasm-simd-threaded.jsep.mjs +98 -98
- package/dist/vad/ort-wasm-simd-threaded.jsep.wasm +0 -0
- package/dist/vad/ort-wasm-simd-threaded.jspi.mjs +99 -102
- package/dist/vad/ort-wasm-simd-threaded.jspi.wasm +0 -0
- package/dist/vad/ort-wasm-simd-threaded.mjs +46 -46
- package/dist/vad/ort-wasm-simd-threaded.wasm +0 -0
- package/package.json +14 -17
- package/plugins/CLAUDE.md +61 -0
- package/plugins/session-manager-dev/.claude-plugin/plugin.json +1 -1
- package/plugins/session-manager-dev/skills/builder/4-manual/SKILL.md +1 -1
- package/plugins/session-manager-dev/skills/ops-sweep/SKILL.md +1 -1
- package/scripts/README.md +59 -0
- package/scripts/audit-ops-hygiene.cjs +350 -0
- package/scripts/hooks/guard-destructive-git.cjs +10 -34
- package/scripts/hooks/guard-inline-implementation.cjs +14 -8
- package/scripts/hooks/guard-prd-writes.cjs +7 -36
- package/scripts/hooks/guard-self-schedule.cjs +175 -0
- package/scripts/ops-sweep.cjs +355 -0
- package/scripts/scheduler-mcp-server.cjs +35 -71
- package/src/main/__tests__/agentModelResolve.test.cjs +100 -9
- package/src/main/__tests__/bilkoHost-integration.test.cjs +3 -3
- package/src/main/__tests__/broadcastCoalescer.test.cjs +18 -0
- package/src/main/__tests__/chat-cancel-terminal.test.cjs +6 -9
- package/src/main/__tests__/chat-exit-close-race.test.cjs +3 -3
- package/src/main/__tests__/chat-mcp-consent-notice.test.cjs +4 -5
- package/src/main/__tests__/chat-queue.test.cjs +2 -2
- package/src/main/__tests__/chat-stop-signal.test.cjs +2 -2
- package/src/main/__tests__/dep-orphan-archive-health.test.cjs +77 -0
- package/src/main/__tests__/dod-batchkey.test.cjs +2 -2
- package/src/main/__tests__/dod-drain-hook.test.cjs +2 -2
- package/src/main/__tests__/dod-report.test.cjs +2 -2
- package/src/main/__tests__/dod-reverify.test.cjs +2 -2
- package/src/main/__tests__/epicMint.test.cjs +4 -4
- package/src/main/__tests__/exchanges.test.cjs +2 -2
- package/src/main/__tests__/extractJson.test.cjs +2 -2
- package/src/main/__tests__/files-reject-credentials.test.cjs +1 -1
- package/src/main/__tests__/fixtures/1218-fo-01-move-scripts-lib-into-src-main-lib.log +556 -0
- package/src/main/__tests__/health-build-freshness.test.cjs +39 -0
- package/src/main/__tests__/health-delegation-chain.test.cjs +17 -2
- package/src/main/__tests__/health-queue-dispatch.test.cjs +58 -7
- package/src/main/__tests__/health-tick-liveness.test.cjs +11 -3
- package/src/main/__tests__/health-usage-poller.test.cjs +70 -23
- package/src/main/__tests__/historyRollup.test.cjs +2 -2
- package/src/main/__tests__/kg-augment.test.cjs +2 -2
- package/src/main/__tests__/mcpStatus.test.cjs +2 -2
- package/src/main/__tests__/memoryAggregate.test.cjs +1 -1
- package/src/main/__tests__/memoryStale.test.cjs +1 -1
- package/src/main/__tests__/needsReviewLedger.test.cjs +162 -0
- package/src/main/__tests__/opsErrorLogTelemetryTap.test.cjs +28 -4
- package/src/main/__tests__/pollLoop-dispatch-on-failure.test.cjs +48 -4
- package/src/main/__tests__/prd-group-allocator.test.cjs +2 -2
- package/src/main/__tests__/prdAdminRouteParity.test.cjs +2 -0
- package/src/main/__tests__/prdAdminRoutes.test.cjs +14 -2
- package/src/main/__tests__/prdAuthoringSeed.test.cjs +39 -0
- package/src/main/__tests__/prdCreateDisposition.test.cjs +201 -0
- package/src/main/__tests__/prdFrontmatterDisposition.test.cjs +125 -0
- package/src/main/__tests__/prdLocations.test.cjs +100 -2
- package/src/main/__tests__/prdLocationsArchived.test.cjs +50 -1
- package/src/main/__tests__/prdSetDisposition.test.cjs +222 -0
- package/src/main/__tests__/proc-role-env.test.cjs +125 -0
- package/src/main/__tests__/procname-claude-spawn-sites.test.cjs +304 -0
- package/src/main/__tests__/procname-sm-processes.test.cjs +127 -0
- package/src/main/__tests__/projectHomeAdminRoutes.test.cjs +81 -401
- package/src/main/__tests__/projectPages.test.cjs +63 -149
- package/src/main/__tests__/queue-health-verdict.test.cjs +170 -0
- package/src/main/__tests__/queue-starvation-dispatch-driver.test.cjs +117 -20
- package/src/main/__tests__/queue-starvation-per-project.test.cjs +14 -2
- package/src/main/__tests__/queueHistory.test.cjs +65 -2
- package/src/main/__tests__/rateLimitPollerStreak.test.cjs +38 -3
- package/src/main/__tests__/reconcileTiming.test.cjs +135 -0
- package/src/main/__tests__/runVerify-landed-commit-outranks.test.cjs +181 -0
- package/src/main/__tests__/runVerify.test.cjs +5 -5
- package/src/main/__tests__/scheduleJobStatusDrift.test.cjs +3 -3
- package/src/main/__tests__/scheduleJobTransitions.test.cjs +103 -3
- package/src/main/__tests__/scheduler-adopted-run-supervision.test.cjs +143 -0
- package/src/main/__tests__/scheduler-autofix-select.test.cjs +2 -2
- package/src/main/__tests__/scheduler-autopromote.test.cjs +2 -2
- package/src/main/__tests__/scheduler-bash-timeout-env.test.cjs +3 -5
- package/src/main/__tests__/scheduler-boot-orphans.test.cjs +79 -98
- package/src/main/__tests__/scheduler-broadcast-reconcile.test.cjs +121 -0
- package/src/main/__tests__/scheduler-cross-project-batch.test.cjs +43 -0
- package/src/main/__tests__/scheduler-default-eligible-heal.test.cjs +161 -0
- package/src/main/__tests__/scheduler-dispatch-loop.test.cjs +58 -0
- package/src/main/__tests__/scheduler-epic-digest.test.cjs +3 -5
- package/src/main/__tests__/scheduler-force-tick-outcome.test.cjs +2 -2
- package/src/main/__tests__/scheduler-gate-shadow.test.cjs +119 -0
- package/src/main/__tests__/scheduler-guard-verdict-autoresolve.test.cjs +390 -0
- package/src/main/__tests__/scheduler-heartbeat-payload.test.cjs +80 -0
- package/src/main/__tests__/scheduler-inplace-salvage.test.cjs +25 -18
- package/src/main/__tests__/scheduler-investigation-prompt.test.cjs +4 -4
- package/src/main/__tests__/scheduler-job-budget.test.cjs +172 -0
- package/src/main/__tests__/scheduler-launch-failure.test.cjs +3 -5
- package/src/main/__tests__/scheduler-looks-done.test.cjs +119 -10
- package/src/main/__tests__/scheduler-manual-pause.test.cjs +118 -0
- package/src/main/__tests__/scheduler-meta-code-sha.test.cjs +26 -3
- package/src/main/__tests__/scheduler-porcelain-rename.test.cjs +164 -0
- package/src/main/__tests__/scheduler-prd-missing-skip.test.cjs +17 -2
- package/src/main/__tests__/scheduler-prd-persona-spawn.test.cjs +3 -5
- package/src/main/__tests__/scheduler-quiet-machine-lease.test.cjs +41 -6
- package/src/main/__tests__/scheduler-rate-limit-pause.test.cjs +62 -6
- package/src/main/__tests__/scheduler-rate-limit-spin-guard.test.cjs +3 -5
- package/src/main/__tests__/scheduler-reap-dead-running-jobs.test.cjs +182 -3
- package/src/main/__tests__/scheduler-reaper-helpers-basics.test.cjs +87 -0
- package/src/main/__tests__/scheduler-reconcile-cwd-preserve.test.cjs +100 -0
- package/src/main/__tests__/scheduler-reconcile-invalid-repair.test.cjs +3 -3
- package/src/main/__tests__/scheduler-reconcile-quarantine.test.cjs +4 -4
- package/src/main/__tests__/scheduler-shard-quarantine.test.cjs +110 -0
- package/src/main/__tests__/scheduler-shared-tree-guard.test.cjs +168 -0
- package/src/main/__tests__/scheduler-starve-escalation.test.cjs +18 -8
- package/src/main/__tests__/scheduler-stranded-autofix-park.test.cjs +245 -0
- package/src/main/__tests__/scheduler-supervisor-record.test.cjs +81 -0
- package/src/main/__tests__/scheduler-tick-cancel-token.test.cjs +2 -2
- package/src/main/__tests__/scheduler-tick-wedge.test.cjs +172 -0
- package/src/main/__tests__/scheduler-transient-failure.test.cjs +2 -2
- package/src/main/__tests__/scheduler-worktree-cap-defer.test.cjs +51 -11
- package/src/main/__tests__/scheduler-worktree-exec-cwd.test.cjs +3 -5
- package/src/main/__tests__/usageSingleFlight.test.cjs +157 -0
- package/src/main/__tests__/workTypeLibrary.test.cjs +1 -1
- package/src/main/bilkoHost.cjs +16 -7
- package/src/main/build-info.json +8 -0
- package/src/main/chatRunner.cjs +12 -7
- package/src/main/config.cjs +2 -3
- package/src/main/docEdit.cjs +4 -2
- package/src/main/health.cjs +268 -52
- package/src/main/heapSnapshot.cjs +2 -2
- package/src/main/historyAggregator.cjs +6 -1
- package/src/main/index.cjs +152 -50
- package/src/main/ipcSchemas.cjs +53 -17
- package/src/main/lib/__tests__/active-sessions.test.cjs +251 -0
- package/src/main/lib/__tests__/auditLog.test.cjs +38 -0
- package/src/main/lib/__tests__/bootSelfHeal.test.cjs +107 -0
- package/src/main/lib/__tests__/buildIdentity.test.cjs +121 -0
- package/src/main/lib/__tests__/cwdClassify.test.cjs +111 -0
- package/src/main/lib/__tests__/definitionOfDoneSequence.test.cjs +95 -0
- package/src/main/lib/__tests__/delegationReadiness.test.cjs +323 -44
- package/src/main/lib/__tests__/dispatchLoop.test.cjs +63 -0
- package/src/main/lib/__tests__/effectiveModelInfo.test.cjs +239 -0
- package/src/main/lib/__tests__/gateFixtures.json +20 -0
- package/src/main/lib/__tests__/gitWorktree.test.cjs +97 -1
- package/src/main/lib/__tests__/guardShims.test.cjs +151 -0
- package/src/main/lib/__tests__/instanceLock.test.cjs +93 -7
- package/src/main/lib/__tests__/jobSupervisorRecord.test.cjs +78 -0
- package/src/main/lib/__tests__/jobWorktreeBootLive.test.cjs +11 -0
- package/src/main/lib/__tests__/localAdminHttp.test.cjs +1 -1
- package/src/main/lib/__tests__/mcpToolCatalog.test.cjs +6 -1
- package/src/main/lib/__tests__/opsRootAbsoluteCwd.test.cjs +5 -5
- package/src/main/lib/__tests__/prdDisposition.test.cjs +224 -0
- package/src/main/lib/__tests__/procIdentity.test.cjs +119 -0
- package/src/main/lib/__tests__/procName.test.cjs +92 -0
- package/src/main/lib/__tests__/queueStoreMachineStateRecovery.test.cjs +67 -0
- package/src/main/lib/__tests__/reaperHelpers.test.cjs +179 -1
- package/src/main/lib/__tests__/schedulerMcpServerHelp.test.cjs +6 -7
- package/src/main/lib/__tests__/schedulerMcpServerProjectHome.test.cjs +37 -204
- package/src/main/lib/__tests__/schedulerPaths.test.cjs +226 -0
- package/src/main/lib/__tests__/schedulerPathsWorktree.test.cjs +94 -0
- package/src/main/lib/__tests__/schedulerRuntimeState.test.cjs +56 -0
- package/src/main/lib/__tests__/sessionSlots.test.cjs +45 -0
- package/src/main/lib/__tests__/telemetryBacklog.test.cjs +1 -1
- package/src/main/lib/__tests__/upgradeDrain.test.cjs +130 -0
- package/src/main/lib/__tests__/usageCircuit.test.cjs +285 -0
- package/src/main/lib/__tests__/watchdog-helpers.test.cjs +375 -0
- package/src/main/lib/__tests__/watchdog-relaunch.test.cjs +266 -0
- package/src/main/lib/activeIndexRebuild.cjs +1 -3
- package/{scripts → src/main}/lib/activeSessions.cjs +67 -89
- package/src/main/lib/adoptedRunSupervisor.cjs +136 -0
- package/src/main/lib/agentModelResolve.cjs +94 -24
- package/src/main/lib/agentPersonaSchema.cjs +2 -2
- package/src/main/lib/auditLog.cjs +30 -5
- package/src/main/lib/bootSelfHeal.cjs +88 -0
- package/src/main/lib/buildIdentity.cjs +113 -0
- package/src/main/lib/classifyPromptTicket.cjs +3 -2
- package/src/main/lib/claudeBin.cjs +37 -2
- package/src/main/lib/cleanEnv.cjs +27 -1
- package/src/main/lib/credentials.cjs +4 -2
- package/src/main/lib/cwdClassify.cjs +185 -0
- package/src/main/lib/definitionOfDone.cjs +296 -52
- package/src/main/lib/delegationReadiness.cjs +290 -225
- package/src/main/lib/dispatchLoop.cjs +40 -0
- package/src/main/lib/effectiveModelInfo.cjs +332 -0
- package/src/main/lib/ephemeralCwd.cjs +7 -28
- package/src/main/lib/epicMint.cjs +3 -3
- package/src/main/lib/gitWorktree.cjs +136 -19
- package/src/main/lib/guardShims.cjs +156 -0
- package/src/main/lib/historyRollup.cjs +6 -7
- package/src/main/lib/instanceLock.cjs +32 -5
- package/src/main/lib/jobDirtFilter.cjs +7 -2
- package/src/main/lib/jobSupervisorRecord.cjs +147 -0
- package/src/main/lib/jobWorktreeBootLive.cjs +9 -5
- package/src/main/lib/launchFailure.cjs +2 -1
- package/src/main/lib/localAdminHttp.cjs +9 -27
- package/src/main/lib/mcpToolCatalog.cjs +33 -78
- package/src/main/lib/needsReviewLedger.cjs +205 -0
- package/src/main/lib/opsErrorLog.cjs +1 -1
- package/src/main/lib/opsOwnership.cjs +27 -19
- package/src/main/lib/prdAuthoringSeed.cjs +36 -0
- package/src/main/lib/prdCreate.cjs +56 -1
- package/src/main/lib/prdDisposition.cjs +199 -0
- package/src/main/lib/prdFrontmatter.cjs +8 -2
- package/src/main/lib/prdLocations.cjs +214 -45
- package/src/main/lib/procIdentity.cjs +126 -0
- package/src/main/lib/procName.cjs +98 -0
- package/src/main/lib/projectHomeAdminRoutes.cjs +56 -327
- package/src/main/lib/projectRootResolve.cjs +1 -1
- package/src/main/lib/queueHistory.cjs +27 -8
- package/src/main/lib/queueStore.cjs +63 -38
- package/src/main/lib/quietMachineLease.cjs +19 -2
- package/src/main/lib/reaperHelpers.cjs +181 -15
- package/src/main/lib/reservationExpiry.cjs +30 -0
- package/src/main/lib/runClaudeP.cjs +4 -2
- package/src/main/lib/runLogRetention.cjs +3 -2
- package/src/main/lib/scheduleJobSchema.cjs +10 -2
- package/src/main/lib/scheduleJobTransitions.cjs +60 -0
- package/src/main/lib/schedulerBatch.cjs +27 -2
- package/src/main/lib/schedulerConfig.cjs +24 -0
- package/src/main/lib/schedulerPaths.cjs +175 -0
- package/src/main/lib/schedulerRuntimeState.cjs +59 -0
- package/src/main/lib/sessionSlots.cjs +47 -9
- package/src/main/lib/smProcNames.cjs +51 -0
- package/src/main/lib/upgradeDrain.cjs +188 -0
- package/src/main/lib/usageCircuit.cjs +206 -0
- package/{scripts → src/main}/lib/watchdogHelpers.cjs +71 -38
- package/src/main/lib/withTimeout.cjs +33 -0
- package/src/main/mcpStatus.cjs +4 -2
- package/src/main/pluginInstall.cjs +6 -2
- package/src/main/projectPages.cjs +41 -145
- package/src/main/pty.cjs +8 -1
- package/src/main/queueOps.cjs +10 -10
- package/src/main/runVerify.cjs +69 -3
- package/src/main/scheduler/prdParser.cjs +13 -0
- package/src/main/scheduler.cjs +2841 -482
- package/src/main/seedAgentPersonas.cjs +1 -1
- package/src/main/seedDevPlugin.cjs +1 -1
- package/src/main/seedSchedulerMcp.cjs +7 -6
- package/src/main/seedStatus.cjs +1 -1
- package/src/main/supervisor.cjs +5 -3
- package/src/main/templates/PRD_AUTHORING.md +50 -0
- package/src/main/usage.cjs +140 -58
- package/src/preload/api.d.ts +110 -65
- package/src/preload/index.cjs +12 -4
- package/src/seed/agents/project-home-builder.md +31 -48
- package/dist/assets/AgentLibrary-DTFL7y8G.js +0 -3
- package/dist/assets/MarkdownEditor-DCIubYWf.js +0 -1
- package/dist/assets/Permissions-BiYZNGYW.js +0 -3
- package/dist/assets/Scheduler-DcLBiJBq.js +0 -14
- package/dist/assets/Settings-Cv-pRyms.js +0 -3
- package/dist/assets/settingsSchema-BJVciriw.js +0 -3
- package/screenshots/.gitkeep +0 -0
- package/screenshots/README-screenshots.md +0 -13
- package/scripts/project-pages-logic/dist/logic.cjs +0 -4709
- package/scripts/render-project-pages/dist/renderer.cjs +0 -18900
- package/scripts/render-project-pages.cjs +0 -70
- package/scripts/validate-project-pages-summary.cjs +0 -62
- package/src/main/lib/projectPageSummarySchema.cjs +0 -181
- package/src/main/teams.cjs +0 -95
- package/src/main/templates/project-pages-catalog.json +0 -741
- package/src/main/templates/project-pages-default-home.html +0 -123
- package/src/main/templates/project-pages-pipeline.md +0 -417
- package/src/seed/prompts/code-review/ac-coverage-check.md +0 -8
- package/src/seed/prompts/code-review/correctness-only.md +0 -8
- package/src/seed/prompts/code-review/full-spectrum-high.md +0 -8
- package/src/seed/prompts/code-review/hallucination-check.md +0 -8
- package/src/seed/prompts/code-review/public-api-compat.md +0 -8
- package/src/seed/prompts/code-review/readability-naming.md +0 -8
- package/src/seed/prompts/debugging/bug-as-failing-test.md +0 -8
- package/src/seed/prompts/debugging/git-bisect-regression.md +0 -8
- package/src/seed/prompts/debugging/instrument-intermittent-bug.md +0 -8
- package/src/seed/prompts/debugging/localize-pipeline-failure.md +0 -8
- package/src/seed/prompts/debugging/reproduce-then-diagnose.md +0 -8
- package/src/seed/prompts/documentation/adr-from-change.md +0 -8
- package/src/seed/prompts/documentation/module-readme.md +0 -8
- package/src/seed/prompts/documentation/onboarding-plan.md +0 -8
- package/src/seed/prompts/documentation/refresh-claude-md.md +0 -8
- package/src/seed/prompts/documentation/tsdoc-public-exports.md +0 -8
- package/src/seed/prompts/git-pr/conventional-commit.md +0 -8
- package/src/seed/prompts/git-pr/draft-pr-title-body.md +0 -8
- package/src/seed/prompts/git-pr/pre-commit-safety-sweep.md +0 -8
- package/src/seed/prompts/git-pr/release-notes-block.md +0 -8
- package/src/seed/prompts/git-pr/split-large-pr.md +0 -8
- package/src/seed/prompts/performance/bundle-startup-audit.md +0 -8
- package/src/seed/prompts/performance/complexity-audit.md +0 -8
- package/src/seed/prompts/performance/cpu-profile-hot-path.md +0 -8
- package/src/seed/prompts/performance/db-query-plan-review.md +0 -8
- package/src/seed/prompts/performance/memory-leak-hunt.md +0 -8
- package/src/seed/prompts/qa/api-contract-tests.md +0 -8
- package/src/seed/prompts/qa/e2e-critical-path.md +0 -8
- package/src/seed/prompts/qa/failing-test-for-bug.md +0 -8
- package/src/seed/prompts/qa/find-missing-test-coverage.md +0 -8
- package/src/seed/prompts/qa/stabilize-flaky-test.md +0 -8
- package/src/seed/prompts/qa/tdd-red-first.md +0 -8
- package/src/seed/prompts/qa/visual-regression-review.md +0 -8
- package/src/seed/prompts/qa/wcag-axe-scan.md +0 -8
- package/src/seed/prompts/refactoring/dead-code-sweep.md +0 -8
- package/src/seed/prompts/refactoring/extract-duplicated-pattern.md +0 -8
- package/src/seed/prompts/refactoring/modernize-legacy-file.md +0 -8
- package/src/seed/prompts/refactoring/reduce-cyclomatic-complexity.md +0 -8
- package/src/seed/prompts/refactoring/tighten-module-boundaries.md +0 -8
- package/src/seed/prompts/security/authz-audit.md +0 -8
- package/src/seed/prompts/security/crypto-correctness.md +0 -8
- package/src/seed/prompts/security/cwe-top-25-hunt.md +0 -8
- package/src/seed/prompts/security/dependency-audit.md +0 -8
- package/src/seed/prompts/security/ipc-boundary-hardening.md +0 -8
- package/src/seed/prompts/security/owasp-top-10-staged-diff.md +0 -8
- package/src/seed/prompts/security/secret-credential-scan.md +0 -8
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* dispatchLoop.cjs — dispatch's own periodic driver. Cadence is owned here and
|
|
5
|
+
* nothing else can degrade it: no billing backoff, utilization, fire policy or
|
|
6
|
+
* cancel token is read. It only calls the injected `tick` (scheduler's
|
|
7
|
+
* tickQueue, which funnels through sessionSlots/pickNextBatch).
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const RECONCILE_INTERVAL_MS = 30_000;
|
|
11
|
+
const MIN_INTERVAL_MS = 10_000;
|
|
12
|
+
const MAX_INTERVAL_MS = 300_000;
|
|
13
|
+
|
|
14
|
+
/** Pure: env override (SM_DISPATCH_LOOP_INTERVAL_MS) or explicit value, clamped to [10s, 300s]. */
|
|
15
|
+
function resolveIntervalMs(intervalMs, env = process.env) {
|
|
16
|
+
const raw = intervalMs ?? env.SM_DISPATCH_LOOP_INTERVAL_MS;
|
|
17
|
+
const n = Number(raw);
|
|
18
|
+
if (raw === undefined || raw === null || raw === '' || !Number.isFinite(n)) return RECONCILE_INTERVAL_MS;
|
|
19
|
+
return Math.min(MAX_INTERVAL_MS, Math.max(MIN_INTERVAL_MS, Math.floor(n)));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @param {{ tick: () => any, intervalMs?: number, onError?: (e: Error) => void }} opts
|
|
24
|
+
* @returns {{ stop: () => void }}
|
|
25
|
+
*/
|
|
26
|
+
function startDispatchLoop({ tick, intervalMs, onError } = {}) {
|
|
27
|
+
if (typeof tick !== 'function') throw new TypeError('startDispatchLoop: tick must be a function');
|
|
28
|
+
if (process.env.SM_DISPATCH_LOOP_DISABLE === '1') return { stop() {} };
|
|
29
|
+
let running = false;
|
|
30
|
+
const report = (e) => { try { if (onError) onError(e); } catch { /* reporting must not throw */ } };
|
|
31
|
+
const timer = setInterval(async () => {
|
|
32
|
+
if (running) return; // previous pass still in flight — no pile-up
|
|
33
|
+
running = true;
|
|
34
|
+
try { await tick(); } catch (e) { report(e); } finally { running = false; }
|
|
35
|
+
}, resolveIntervalMs(intervalMs));
|
|
36
|
+
if (timer.unref) timer.unref();
|
|
37
|
+
return { stop() { clearInterval(timer); } };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
module.exports = { startDispatchLoop, resolveIntervalMs, RECONCILE_INTERVAL_MS, MIN_INTERVAL_MS, MAX_INTERVAL_MS };
|
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* effectiveModelInfo.cjs — read-only observer answering "what will this
|
|
5
|
+
* Epic's agentType actually run as": the persona's model alias, the
|
|
6
|
+
* concrete model id evidence points at, and the provenance of each. Sits
|
|
7
|
+
* BESIDE agentModelResolve.cjs (which decides what a launch actually passes
|
|
8
|
+
* to `--model`) rather than replacing it — nothing here feeds a spawn
|
|
9
|
+
* decision, and agentModelResolve.cjs's own resolution is unchanged.
|
|
10
|
+
*
|
|
11
|
+
* Provenance is the entire point: a caller must be able to tell "we KNOW
|
|
12
|
+
* this alias last ran as claude-opus-5 because a real run resolved it" from
|
|
13
|
+
* "we don't know; the CLI resolves this alias at launch." The two must
|
|
14
|
+
* never collapse into one optimistic string.
|
|
15
|
+
*
|
|
16
|
+
* Effort-level resolution is deliberately NOT here — it already exists,
|
|
17
|
+
* unused, in the renderer's `useEffectiveSettings.ts` (a scope-chain reader
|
|
18
|
+
* with a file watcher). This module supplies only the half that genuinely
|
|
19
|
+
* needs main-process filesystem access: persona lookup (overlay-aware) and
|
|
20
|
+
* concrete-model evidence (scheduler run logs, session transcripts).
|
|
21
|
+
*
|
|
22
|
+
* Never throws — every lookup failure degrades a field to null, same
|
|
23
|
+
* contract as agentModelResolve.cjs's resolveEpicModel.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
const fs = require('node:fs');
|
|
27
|
+
const path = require('node:path');
|
|
28
|
+
const os = require('node:os');
|
|
29
|
+
const { splitFrontmatter } = require('./prdFrontmatter.cjs');
|
|
30
|
+
const { encodeCwd } = require('./encodeCwd.cjs');
|
|
31
|
+
|
|
32
|
+
// Mirrors rawSessionModel.ts's RAW_MODELS — duplicated rather than imported
|
|
33
|
+
// because that file is a renderer ES module and this is a main-process CJS
|
|
34
|
+
// module (CLAUDE.md: "No CommonJS in renderer, no ES modules in main").
|
|
35
|
+
// Anything NOT in this set is treated as an already-concrete pinned model id
|
|
36
|
+
// (e.g. 'claude-opus-5'), never as an alias needing evidence.
|
|
37
|
+
const KNOWN_MODEL_ALIASES = new Set(['opus', 'sonnet', 'haiku', 'fable']);
|
|
38
|
+
|
|
39
|
+
// Run-log evidence (scheduler.cjs's executeJob, ~line 4473) is written
|
|
40
|
+
// essentially at dispatch time, before any of the run's own stdout streams
|
|
41
|
+
// in — so a bounded HEAD read (not a tail) is both correct and cheap even
|
|
42
|
+
// against a run log that grows to tens of MB. O(min(size, cap)) time/space.
|
|
43
|
+
const MAX_RUN_LOG_HEAD_BYTES = 64 * 1024;
|
|
44
|
+
|
|
45
|
+
// Same bound epicDelegationStats.cjs's readTranscriptTail uses for a single
|
|
46
|
+
// pass over a transcript that can reach tens of MB. O(min(size, cap)).
|
|
47
|
+
const MAX_TRANSCRIPT_TAIL_BYTES = 8 * 1024 * 1024;
|
|
48
|
+
|
|
49
|
+
// Mirrors scheduler.cjs's own ROOT/RUNS_DIR constants (same convention as
|
|
50
|
+
// queueStore.cjs's LEGACY_QUEUE_PATH, which duplicates this literal rather
|
|
51
|
+
// than requiring scheduler.cjs's ~530KB module graph for one path).
|
|
52
|
+
function runsDir(homeDir) {
|
|
53
|
+
return path.join(homeDir, '.claude', 'session-manager', 'scheduled-plans', 'runs');
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function isConcreteModelId(modelAlias) {
|
|
57
|
+
return Boolean(modelAlias) && !KNOWN_MODEL_ALIASES.has(modelAlias);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* True when this app's spawn path (cleanEnv.cjs's cleanChildEnv) would strip
|
|
62
|
+
* an effort env var before a child ever saw it — i.e. whether the settings
|
|
63
|
+
* schema's env-var effort configuration path is actually reachable for an
|
|
64
|
+
* app-launched session. Derived by probing cleanChildEnv itself rather than
|
|
65
|
+
* hardcoding a boolean, so this self-corrects if that deletion list ever
|
|
66
|
+
* changes instead of silently drifting stale.
|
|
67
|
+
*/
|
|
68
|
+
function computeEffortReachable(deps) {
|
|
69
|
+
try {
|
|
70
|
+
const { cleanChildEnv } = deps.cleanEnv || require('./cleanEnv.cjs');
|
|
71
|
+
const probe = cleanChildEnv({ CLAUDE_EFFORT: 'high', CLAUDE_CODE_EFFORT_LEVEL: 'high' });
|
|
72
|
+
return Boolean(probe.CLAUDE_EFFORT || probe.CLAUDE_CODE_EFFORT_LEVEL);
|
|
73
|
+
} catch {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Resolves a persona's model alias, overlay-aware (agentLibrary.cjs's
|
|
80
|
+
* getPersonaBody: project overlay at `<cwd>/.claude/agents/<name>.md` wins
|
|
81
|
+
* over the global `~/.claude/agents/<name>.md` — the same precedence
|
|
82
|
+
* `resolvePrdPersonaForSpawn` already uses, unlike `listPersonas`/
|
|
83
|
+
* `readPersonaModel`, which only ever see the global directory).
|
|
84
|
+
*
|
|
85
|
+
* Never throws: a missing/unreadable persona (dangling agentType) resolves
|
|
86
|
+
* to `{ modelAlias: null, modelSource: 'fallback' }` without logging —
|
|
87
|
+
* agentModelResolve.cjs's own `logDanglingPersonaOnce`/`reportDanglingAgentTypeOnce`
|
|
88
|
+
* dedup-per-(cwd,agentType) already covers that diagnostic on the LAUNCH
|
|
89
|
+
* path; this read-only observer deliberately does not add a second logger
|
|
90
|
+
* for the same dangling reference.
|
|
91
|
+
*/
|
|
92
|
+
async function resolvePersonaModelAlias(cwd, agentType, deps) {
|
|
93
|
+
const getPersonaBody = deps.getPersonaBody || require('../agentLibrary.cjs').getPersonaBody;
|
|
94
|
+
// The overlay-vs-global provenance question itself ("which of
|
|
95
|
+
// resolvePersonaPaths' two candidates won") is answered by
|
|
96
|
+
// agentModelResolve.cjs's isProjectOverlayPersonaPath, not re-derived here
|
|
97
|
+
// — that module already owns this precedence decision for the launch
|
|
98
|
+
// path (readOverlayAwarePersonaModel), and this observer must never let
|
|
99
|
+
// its own copy of the comparison drift from the one that actually decides
|
|
100
|
+
// what gets spawned.
|
|
101
|
+
const { isProjectOverlayPersonaPath } = deps.agentModelResolve || require('./agentModelResolve.cjs');
|
|
102
|
+
|
|
103
|
+
let persona;
|
|
104
|
+
try {
|
|
105
|
+
persona = await getPersonaBody({ cwd, name: agentType });
|
|
106
|
+
} catch {
|
|
107
|
+
persona = null;
|
|
108
|
+
}
|
|
109
|
+
if (!persona) return { modelAlias: null, modelSource: 'fallback' };
|
|
110
|
+
|
|
111
|
+
const { fm } = splitFrontmatter(persona.text);
|
|
112
|
+
const fromOverlay = isProjectOverlayPersonaPath(cwd, agentType, persona.path, deps);
|
|
113
|
+
|
|
114
|
+
if (fm.model && fm.model !== 'inherit') {
|
|
115
|
+
return { modelAlias: fm.model, modelSource: fromOverlay ? 'persona-overlay' : 'persona' };
|
|
116
|
+
}
|
|
117
|
+
return { modelAlias: null, modelSource: 'inherit' };
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/** Best-effort read of `<cwd>/session-manager-operations/scheduler/state/queue.json`'s hot jobs[]. */
|
|
121
|
+
function readHotJobsForCwd(cwd, deps) {
|
|
122
|
+
const { projectQueuePath } = deps.queueStore || require('./queueStore.cjs');
|
|
123
|
+
try {
|
|
124
|
+
const data = JSON.parse(fs.readFileSync(projectQueuePath(cwd), 'utf8'));
|
|
125
|
+
return Array.isArray(data.jobs) ? data.jobs : [];
|
|
126
|
+
} catch {
|
|
127
|
+
return [];
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/** Best-effort read of `<cwd>/session-manager-operations/scheduler/state/history.jsonl`'s archived rows. */
|
|
132
|
+
function readHistoryEntriesForCwd(cwd, deps) {
|
|
133
|
+
const { projectHistoryPath } = deps.queueStore || require('./queueStore.cjs');
|
|
134
|
+
let text;
|
|
135
|
+
try {
|
|
136
|
+
text = fs.readFileSync(projectHistoryPath(cwd), 'utf8');
|
|
137
|
+
} catch {
|
|
138
|
+
return [];
|
|
139
|
+
}
|
|
140
|
+
const entries = [];
|
|
141
|
+
for (const line of text.split('\n')) {
|
|
142
|
+
if (!line.trim()) continue;
|
|
143
|
+
try {
|
|
144
|
+
const j = JSON.parse(line);
|
|
145
|
+
// needs_review_entry/needs_review_resolution lines (needsReviewLedger.cjs)
|
|
146
|
+
// share history.jsonl with terminal job rows but carry no `agentType` —
|
|
147
|
+
// findLatestSchedulerModel's own `j.agentType === agentType` filter
|
|
148
|
+
// already excludes them, but skip explicitly here too so this reader
|
|
149
|
+
// stays correct even if a future ledger line shape happens to pick up
|
|
150
|
+
// an agentType-shaped field.
|
|
151
|
+
if (j?.kind && j.kind !== 'terminal') continue;
|
|
152
|
+
entries.push(j);
|
|
153
|
+
} catch {
|
|
154
|
+
// corrupt/partial line — skip
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return entries;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function jobTimestampMs(job) {
|
|
161
|
+
return Date.parse(job?.finishedAt || job?.startedAt || job?.queuedAt || 0) || 0;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/** Bounded HEAD read of an absolute file path; null on any read failure. */
|
|
165
|
+
function readHead(filePath, maxBytes, deps) {
|
|
166
|
+
const statSync = deps.statSync || fs.statSync;
|
|
167
|
+
const openSync = deps.openSync || fs.openSync;
|
|
168
|
+
const readSync = deps.readSync || fs.readSync;
|
|
169
|
+
const closeSync = deps.closeSync || fs.closeSync;
|
|
170
|
+
try {
|
|
171
|
+
const size = statSync(filePath).size;
|
|
172
|
+
const length = Math.min(maxBytes, size);
|
|
173
|
+
const buffer = Buffer.alloc(length);
|
|
174
|
+
const fd = openSync(filePath, 'r');
|
|
175
|
+
try {
|
|
176
|
+
readSync(fd, buffer, 0, length, 0);
|
|
177
|
+
} finally {
|
|
178
|
+
closeSync(fd);
|
|
179
|
+
}
|
|
180
|
+
return buffer.toString('utf8');
|
|
181
|
+
} catch {
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/** Bounded TAIL read of an absolute file path; null on any read failure. */
|
|
187
|
+
function readTail(filePath, maxBytes, deps) {
|
|
188
|
+
const statSync = deps.statSync || fs.statSync;
|
|
189
|
+
const openSync = deps.openSync || fs.openSync;
|
|
190
|
+
const readSync = deps.readSync || fs.readSync;
|
|
191
|
+
const closeSync = deps.closeSync || fs.closeSync;
|
|
192
|
+
try {
|
|
193
|
+
const size = statSync(filePath).size;
|
|
194
|
+
const start = Math.max(0, size - maxBytes);
|
|
195
|
+
const length = size - start;
|
|
196
|
+
const buffer = Buffer.alloc(length);
|
|
197
|
+
const fd = openSync(filePath, 'r');
|
|
198
|
+
try {
|
|
199
|
+
readSync(fd, buffer, 0, length, start);
|
|
200
|
+
} finally {
|
|
201
|
+
closeSync(fd);
|
|
202
|
+
}
|
|
203
|
+
const text = buffer.toString('utf8');
|
|
204
|
+
return start > 0 ? text.slice(text.indexOf('\n') + 1) : text;
|
|
205
|
+
} catch {
|
|
206
|
+
return null;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Evidence source 1: the scheduler already logs the persona-resolved model
|
|
212
|
+
* at dispatch (scheduler.cjs's executeJob, ~line 4473: `[scheduler]
|
|
213
|
+
* agentType=... persona=... model=...`). Scans this project's hot queue.json
|
|
214
|
+
* jobs[] AND its archived history.jsonl for the most recent job whose
|
|
215
|
+
* agentType matches, then reads that job's own run log for the line. O(J log
|
|
216
|
+
* J) to sort J candidate jobs, O(min(logSize, cap)) per log read.
|
|
217
|
+
*/
|
|
218
|
+
function findLatestSchedulerModel(cwd, agentType, deps) {
|
|
219
|
+
const jobs = [...readHotJobsForCwd(cwd, deps), ...readHistoryEntriesForCwd(cwd, deps)];
|
|
220
|
+
const matches = jobs.filter((j) => j && j.agentType === agentType && j.runId && j.slug);
|
|
221
|
+
matches.sort((a, b) => jobTimestampMs(b) - jobTimestampMs(a));
|
|
222
|
+
|
|
223
|
+
const homeDir = deps.homeDir || os.homedir();
|
|
224
|
+
const re = /\[scheduler\] agentType=\S+ persona=.*? model=(\S+)/g;
|
|
225
|
+
for (const job of matches) {
|
|
226
|
+
const logPath = path.join(runsDir(homeDir), job.runId, `${job.slug}.log`);
|
|
227
|
+
const head = readHead(logPath, MAX_RUN_LOG_HEAD_BYTES, deps);
|
|
228
|
+
if (!head) continue;
|
|
229
|
+
let match;
|
|
230
|
+
let last = null;
|
|
231
|
+
while ((match = re.exec(head))) last = match[1];
|
|
232
|
+
if (last) return last;
|
|
233
|
+
}
|
|
234
|
+
return null;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Evidence source 2: the most recent Epic (active-index.json entry) created
|
|
239
|
+
* with this agentType, read via its own claude-session transcript's last
|
|
240
|
+
* `"model":"..."` occurrence. O(E log E) to sort E candidate Epics,
|
|
241
|
+
* O(min(transcriptSize, cap)) per transcript read.
|
|
242
|
+
*/
|
|
243
|
+
function findLatestTranscriptModel(cwd, agentType, deps) {
|
|
244
|
+
const readActiveIndex = deps.readActiveIndex || require('./epicMint.cjs').readActiveIndex;
|
|
245
|
+
let sessions;
|
|
246
|
+
try {
|
|
247
|
+
({ sessions } = readActiveIndex(cwd));
|
|
248
|
+
} catch {
|
|
249
|
+
return null;
|
|
250
|
+
}
|
|
251
|
+
const matches = Object.values(sessions || {}).filter((s) => s && s.agentType === agentType && s.claudeSessionId);
|
|
252
|
+
matches.sort((a, b) => (Date.parse(b.createdAt || 0) || 0) - (Date.parse(a.createdAt || 0) || 0));
|
|
253
|
+
|
|
254
|
+
const homeDir = deps.homeDir || os.homedir();
|
|
255
|
+
const encodeCwdFn = deps.encodeCwd || encodeCwd;
|
|
256
|
+
const re = /"model":"([^"]+)"/g;
|
|
257
|
+
for (const session of matches) {
|
|
258
|
+
const filePath = path.join(homeDir, '.claude', 'projects', encodeCwdFn(cwd), `${session.claudeSessionId}.jsonl`);
|
|
259
|
+
const tail = readTail(filePath, MAX_TRANSCRIPT_TAIL_BYTES, deps);
|
|
260
|
+
if (!tail) continue;
|
|
261
|
+
let match;
|
|
262
|
+
let last = null;
|
|
263
|
+
while ((match = re.exec(tail))) last = match[1];
|
|
264
|
+
if (last) return last;
|
|
265
|
+
}
|
|
266
|
+
return null;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* resolveEffectiveModelInfo({ cwd, agentType, deps? }) →
|
|
271
|
+
* { agentType, modelAlias, modelSource, resolvedModelId, resolvedFrom, effortReachable }
|
|
272
|
+
*
|
|
273
|
+
* Never throws. `cwd` is normalized through the same worktree/ops-internal
|
|
274
|
+
* -aware resolver every ops-root reader goes through, so a job worktree cwd
|
|
275
|
+
* resolves to its main project tree before anything is looked up.
|
|
276
|
+
*/
|
|
277
|
+
async function resolveEffectiveModelInfo({ cwd, agentType, deps = {} } = {}) {
|
|
278
|
+
const effortReachable = computeEffortReachable(deps);
|
|
279
|
+
const miss = {
|
|
280
|
+
agentType: agentType || null,
|
|
281
|
+
modelAlias: null,
|
|
282
|
+
modelSource: 'fallback',
|
|
283
|
+
resolvedModelId: null,
|
|
284
|
+
resolvedFrom: null,
|
|
285
|
+
effortReachable,
|
|
286
|
+
};
|
|
287
|
+
if (!cwd || !agentType) return miss;
|
|
288
|
+
|
|
289
|
+
try {
|
|
290
|
+
const { projectRootOf } = deps.activeSessions || require('./activeSessions.cjs');
|
|
291
|
+
const normalizedCwd = projectRootOf(path.resolve(cwd));
|
|
292
|
+
if (!normalizedCwd) return miss;
|
|
293
|
+
|
|
294
|
+
const { modelAlias, modelSource } = await resolvePersonaModelAlias(normalizedCwd, agentType, deps);
|
|
295
|
+
const result = { agentType, modelAlias, modelSource, resolvedModelId: null, resolvedFrom: null, effortReachable };
|
|
296
|
+
|
|
297
|
+
if (isConcreteModelId(modelAlias)) {
|
|
298
|
+
// Already a concrete pinned id — echo it back, fabricate no evidence.
|
|
299
|
+
result.resolvedModelId = modelAlias;
|
|
300
|
+
return result;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// Evidence is never derived via historyAggregator.cjs's resolvePricingKey
|
|
304
|
+
// (which buckets any unknown id to 'sonnet' with estimated:true) —
|
|
305
|
+
// deliberately: that is a pricing heuristic, and borrowing it here would
|
|
306
|
+
// turn "we don't know" into a confident wrong answer.
|
|
307
|
+
const schedulerHit = findLatestSchedulerModel(normalizedCwd, agentType, deps);
|
|
308
|
+
if (schedulerHit) {
|
|
309
|
+
result.resolvedModelId = schedulerHit;
|
|
310
|
+
result.resolvedFrom = 'scheduler-run';
|
|
311
|
+
return result;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
const transcriptHit = findLatestTranscriptModel(normalizedCwd, agentType, deps);
|
|
315
|
+
if (transcriptHit) {
|
|
316
|
+
result.resolvedModelId = transcriptHit;
|
|
317
|
+
result.resolvedFrom = 'transcript';
|
|
318
|
+
return result;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
return result;
|
|
322
|
+
} catch {
|
|
323
|
+
return miss;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
module.exports = {
|
|
328
|
+
resolveEffectiveModelInfo,
|
|
329
|
+
isConcreteModelId,
|
|
330
|
+
computeEffortReachable,
|
|
331
|
+
KNOWN_MODEL_ALIASES,
|
|
332
|
+
};
|
|
@@ -35,44 +35,23 @@
|
|
|
35
35
|
* unrelated use that a blanket match would wrongly refuse.
|
|
36
36
|
*/
|
|
37
37
|
|
|
38
|
-
const os = require('node:os');
|
|
39
38
|
const path = require('node:path');
|
|
40
|
-
const {
|
|
41
|
-
const { KIND_CONFIG } = require('./gitWorktree.cjs');
|
|
42
|
-
|
|
43
|
-
const TMPDIR = path.resolve(os.tmpdir());
|
|
44
|
-
const MANAGED_WORKTREE_ROOTS = [KIND_CONFIG.job.root, KIND_CONFIG.epic.root].map((p) => path.resolve(p));
|
|
45
|
-
|
|
46
|
-
function isExactlyTmpdir(absCwd) {
|
|
47
|
-
return absCwd === TMPDIR;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
function isUnderManagedWorktreeRoot(absCwd) {
|
|
51
|
-
return MANAGED_WORKTREE_ROOTS.some((root) => {
|
|
52
|
-
const rel = path.relative(root, absCwd);
|
|
53
|
-
return rel === '' || (!rel.startsWith('..') && !path.isAbsolute(rel));
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
function isLinkedWorktreeRoot(absCwd) {
|
|
58
|
-
const mainRoot = worktreeMainRootOf(absCwd);
|
|
59
|
-
return Boolean(mainRoot) && path.resolve(mainRoot) !== absCwd;
|
|
60
|
-
}
|
|
39
|
+
const { classifyCwd } = require('./cwdClassify.cjs');
|
|
61
40
|
|
|
62
41
|
/**
|
|
63
42
|
* isEphemeralCwd(cwd) → true when `cwd` must never have ops state written
|
|
64
43
|
* into it (tmpdir-resident, or a linked git worktree root). Pure, synchronous,
|
|
65
44
|
* never throws — an unresolvable or non-absolute cwd is treated as NOT
|
|
66
45
|
* ephemeral so this predicate only ever adds refusals, never masks the
|
|
67
|
-
* existing "cwd must be absolute" checks callers already perform.
|
|
46
|
+
* existing "cwd must be absolute" checks callers already perform. The
|
|
47
|
+
* unprovable-worktree case is NOT ephemeral here: it is kind `unknown`, which
|
|
48
|
+
* opsOwnership.assertOpsWrite refuses separately (writes only — dispatch and
|
|
49
|
+
* reads stay open).
|
|
68
50
|
*/
|
|
69
51
|
function isEphemeralCwd(cwd) {
|
|
70
52
|
if (!cwd || typeof cwd !== 'string' || !path.isAbsolute(cwd)) return false;
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
if (isUnderManagedWorktreeRoot(absCwd)) return true;
|
|
74
|
-
if (isLinkedWorktreeRoot(absCwd)) return true;
|
|
75
|
-
return false;
|
|
53
|
+
const { kind } = classifyCwd(path.resolve(cwd));
|
|
54
|
+
return kind === 'ephemeral' || kind === 'worktree';
|
|
76
55
|
}
|
|
77
56
|
|
|
78
57
|
module.exports = { isEphemeralCwd };
|
|
@@ -161,7 +161,7 @@ function resolvePersonaPaths(cwd, agentType, deps = {}) {
|
|
|
161
161
|
* a readable `.md` persona file, checking the project overlay before the
|
|
162
162
|
* global agents dir. Never throws (a traversal attempt or missing file is
|
|
163
163
|
* treated as "doesn't exist", same fail-closed spirit as
|
|
164
|
-
* agentModelResolve.cjs's
|
|
164
|
+
* agentModelResolve.cjs's readOverlayAwarePersonaModel).
|
|
165
165
|
*/
|
|
166
166
|
function personaFileExists(cwd, agentType, deps = {}) {
|
|
167
167
|
const projectDir = deps.projectDir || path.join(cwd, '.claude', 'agents');
|
|
@@ -289,8 +289,8 @@ function ensureEpic(cwd, { goalText, tag, epicId: explicitEpicId, status = 'prop
|
|
|
289
289
|
}
|
|
290
290
|
|
|
291
291
|
// WRITE-TIME FK CHECK (throw on write, report on read — see this file's
|
|
292
|
-
// header + agentModelResolve.cjs's
|
|
293
|
-
// side of this same FK and stays permissive on purpose). A mint whose
|
|
292
|
+
// header + agentModelResolve.cjs's readOverlayAwarePersonaModel, which is
|
|
293
|
+
// the READ side of this same FK and stays permissive on purpose). A mint whose
|
|
294
294
|
// agentType names a persona that doesn't resolve is a bug in the caller
|
|
295
295
|
// (a typo, or a persona deleted between the picker loading and the mint
|
|
296
296
|
// landing) — refuse it now rather than silently orphaning the Epic.
|