claude-code-session-manager 0.67.0 → 0.69.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/dist/assets/{AgentLibrary-CiqimwWl.js → AgentLibrary-DngWZmn2.js} +1 -1
- package/dist/assets/{History-DbzjII2Z.js → History-CiqbZNCW.js} +1 -1
- package/dist/assets/{Hooks-C0PTplI_.js → Hooks-1LHEEKhK.js} +1 -1
- package/dist/assets/{HostBilko-vGc1FYLD.js → HostBilko-DruBVVx_.js} +1 -1
- package/dist/assets/{Library-4tU4rg2h.js → Library-BXt58QDN.js} +1 -1
- package/dist/assets/{ListDetail-BGIvkCwZ.js → ListDetail-V5JV-SVN.js} +1 -1
- package/dist/assets/{MarkdownEditor-ChFdpCam.js → MarkdownEditor-BYUdiq8p.js} +1 -1
- package/dist/assets/{McpServers-DsRWWpU3.js → McpServers-C3b18FY5.js} +1 -1
- package/dist/assets/{Memory-DmxoxxxY.js → Memory-MyToD3ri.js} +1 -1
- package/dist/assets/{Panel-KC-rv3jS.js → Panel-D1z0ZvX_.js} +1 -1
- package/dist/assets/{Permissions-DrDjCRFl.js → Permissions-BDRMk8Uu.js} +1 -1
- package/dist/assets/{Plugins-KexSQwk0.js → Plugins-Bd1wIgVW.js} +2 -2
- package/dist/assets/{ProvenanceBadge-Rg-jL94y.js → ProvenanceBadge-BIX0JW7m.js} +1 -1
- package/dist/assets/{SaveBar-BbEo8U2e.js → SaveBar-DOJnzj3n.js} +1 -1
- package/dist/assets/{Scheduler-C4Ti9TCc.js → Scheduler-LdawPR1e.js} +1 -1
- package/dist/assets/{ScopeSwitcher-Di9BmYze.js → ScopeSwitcher-Cl3g7YOM.js} +1 -1
- package/dist/assets/{Settings-CxyhPuYQ.js → Settings-7jHzkgfK.js} +1 -1
- package/dist/assets/{SkillReferenceGraph-0q26RHrn.js → SkillReferenceGraph-B_KqYC6R.js} +1 -1
- package/dist/assets/{Skills-BXkVyCo5.js → Skills-H8pCR_6D.js} +1 -1
- package/dist/assets/{SystemPrompt-Bwe3NTbi.js → SystemPrompt-fCD2rD2R.js} +1 -1
- package/dist/assets/{TagLibrary-CnwEf6EI.js → TagLibrary-erEiP4bj.js} +1 -1
- package/dist/assets/{TiptapBody-faCtLj9L.js → TiptapBody-A93HQtTH.js} +1 -1
- package/dist/assets/{Toggle-Bw7G_-RR.js → Toggle-CoFtvmoX.js} +1 -1
- package/dist/assets/{index-CEnMgeQU.css → index-B77KHr7n.css} +1 -1
- package/dist/assets/{index-B6dJ2CsU.js → index-C-iwyX_s.js} +356 -355
- package/dist/assets/{settingsSchema-B5C9hZoS.js → settingsSchema-DHDH8NJR.js} +1 -1
- package/dist/index.html +2 -2
- package/package.json +1 -1
- package/plugins/session-manager-dev/.claude-plugin/plugin.json +1 -1
- package/plugins/session-manager-dev/skills/send-feedback/SKILL.md +149 -0
- package/src/main/__tests__/crossProjectFeedback.test.cjs +327 -0
- package/src/main/__tests__/crossProjectFeedbackRoutes.test.cjs +154 -0
- package/src/main/__tests__/health-per-project-stall.test.cjs +4 -2
- package/src/main/__tests__/scheduler-job-overrun.test.cjs +117 -0
- package/src/main/__tests__/scheduler-stall-per-project.test.cjs +6 -2
- package/src/main/index.cjs +5 -0
- package/src/main/lib/buildTarget.cjs +15 -0
- package/src/main/lib/crossProjectFeedback.cjs +545 -0
- package/src/main/lib/epicMint.cjs +38 -7
- package/src/main/lib/promptSessionSchema.cjs +7 -1
- package/src/main/lib/schedulerConfig.cjs +15 -0
- package/src/main/scheduler.cjs +73 -1
package/src/main/scheduler.cjs
CHANGED
|
@@ -76,10 +76,18 @@ const {
|
|
|
76
76
|
MAX_JOB_DURATION_MS,
|
|
77
77
|
BROADCAST_COALESCE_MS,
|
|
78
78
|
QUARANTINE_ESCALATE_MS: QUARANTINE_ESCALATE_MS_DEFAULT,
|
|
79
|
+
JOB_OVERRUN_FACTOR: JOB_OVERRUN_FACTOR_DEFAULT,
|
|
80
|
+
JOB_OVERRUN_FLOOR_MS: JOB_OVERRUN_FLOOR_MS_DEFAULT,
|
|
79
81
|
} = require('./lib/schedulerConfig.cjs');
|
|
80
82
|
const QUARANTINE_ESCALATE_MS = process.env.SM_QUARANTINE_ESCALATE_HOURS
|
|
81
83
|
? Number(process.env.SM_QUARANTINE_ESCALATE_HOURS) * 60 * 60_000
|
|
82
84
|
: QUARANTINE_ESCALATE_MS_DEFAULT;
|
|
85
|
+
const JOB_OVERRUN_FACTOR = process.env.SM_JOB_OVERRUN_FACTOR
|
|
86
|
+
? Number(process.env.SM_JOB_OVERRUN_FACTOR)
|
|
87
|
+
: JOB_OVERRUN_FACTOR_DEFAULT;
|
|
88
|
+
const JOB_OVERRUN_FLOOR_MS = process.env.SM_JOB_OVERRUN_FLOOR_MINUTES
|
|
89
|
+
? Number(process.env.SM_JOB_OVERRUN_FLOOR_MINUTES) * 60_000
|
|
90
|
+
: JOB_OVERRUN_FLOOR_MS_DEFAULT;
|
|
83
91
|
const { pickForProject, pickNextBatch, DEFAULT_PROJECT_CWD } = require('./lib/schedulerBatch.cjs');
|
|
84
92
|
const { runDefinitionOfDoneOnDrain } = require('./lib/dodDrainHook.cjs');
|
|
85
93
|
const { writeRcaReport, extractRcaBlock } = require('./lib/rcaReport.cjs');
|
|
@@ -1043,6 +1051,52 @@ function findStaleQuarantinedJobs(jobs, now, thresholdMs) {
|
|
|
1043
1051
|
return stale;
|
|
1044
1052
|
}
|
|
1045
1053
|
|
|
1054
|
+
/**
|
|
1055
|
+
* findOverrunningJobs(jobs, now, { factor, floorMs }) → [{ slug, cwd, estimateMinutes, ranMs, ratio }]
|
|
1056
|
+
*
|
|
1057
|
+
* Pure, no IO. A RUNNING job whose elapsed time exceeds
|
|
1058
|
+
* `max(estimateMinutes * factor, floorMs)` is overrunning its own PRD's
|
|
1059
|
+
* declared estimate.
|
|
1060
|
+
*
|
|
1061
|
+
* This closes the gap between the two existing kill paths, which a
|
|
1062
|
+
* long-running-but-chatty job slips straight through:
|
|
1063
|
+
* - MAX_JOB_DURATION_MS (4h) is a deadman — a 20-minute PRD at 3h is 9x
|
|
1064
|
+
* over estimate and still an hour away from it.
|
|
1065
|
+
* - IDLE_OUTPUT_KILL_MS (20m) only fires when the log mtime STALLS; an
|
|
1066
|
+
* agent stuck in a productive-looking loop keeps writing and never trips it.
|
|
1067
|
+
* `estimateMinutes` was parsed, stored and displayed but never once compared
|
|
1068
|
+
* against actual runtime, so the only thing standing between a runaway job
|
|
1069
|
+
* and the 4h ceiling was a human noticing. (2026-08-08: a PRD ran 3h+ and was
|
|
1070
|
+
* caught only because the operator opened a second session to look.)
|
|
1071
|
+
*
|
|
1072
|
+
* Escalation only — see JOB_OVERRUN_FACTOR's note on why this must not kill.
|
|
1073
|
+
* A job with no usable estimate is skipped rather than guessed at.
|
|
1074
|
+
*/
|
|
1075
|
+
function findOverrunningJobs(jobs, now, { factor, floorMs } = {}) {
|
|
1076
|
+
const f = typeof factor === 'number' && factor > 0 ? factor : JOB_OVERRUN_FACTOR;
|
|
1077
|
+
const floor = typeof floorMs === 'number' && floorMs >= 0 ? floorMs : JOB_OVERRUN_FLOOR_MS;
|
|
1078
|
+
const out = [];
|
|
1079
|
+
for (const j of jobs ?? []) {
|
|
1080
|
+
if (j.status !== 'running') continue;
|
|
1081
|
+
const est = Number(j.estimateMinutes);
|
|
1082
|
+
if (!Number.isFinite(est) || est <= 0) continue; // no estimate to overrun
|
|
1083
|
+
const startedAt = Date.parse(j.startedAt ?? '');
|
|
1084
|
+
if (Number.isNaN(startedAt)) continue;
|
|
1085
|
+
const ranMs = now - startedAt;
|
|
1086
|
+
if (ranMs <= 0) continue;
|
|
1087
|
+
const thresholdMs = Math.max(est * 60_000 * f, floor);
|
|
1088
|
+
if (ranMs < thresholdMs) continue;
|
|
1089
|
+
out.push({
|
|
1090
|
+
slug: j.slug,
|
|
1091
|
+
cwd: j.cwd ?? null,
|
|
1092
|
+
estimateMinutes: est,
|
|
1093
|
+
ranMs,
|
|
1094
|
+
ratio: ranMs / (est * 60_000),
|
|
1095
|
+
});
|
|
1096
|
+
}
|
|
1097
|
+
return out;
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1046
1100
|
// An empty queue and an unreadable queue are NOT the same thing, and
|
|
1047
1101
|
// conflating them is destructive: reconcile() treats every PRD .md with no
|
|
1048
1102
|
// matching jobs[] row as a brand-new goal and re-mints it as 'pending', so a
|
|
@@ -5042,6 +5096,24 @@ async function init() {
|
|
|
5042
5096
|
);
|
|
5043
5097
|
appendAuditEvent('prd_quarantine_stale', { slug: stale.slug, cwd: stale.cwd, ageMs: stale.ageMs });
|
|
5044
5098
|
}
|
|
5099
|
+
|
|
5100
|
+
// Estimate-relative overrun escalation. Sits in the blind spot between
|
|
5101
|
+
// the 4h deadman and the 20-minute idle-output watchdog: a job that keeps
|
|
5102
|
+
// producing output while looping trips neither, so nothing noticed a PRD
|
|
5103
|
+
// running 9x its own estimate until a human went looking. Escalate loudly;
|
|
5104
|
+
// never kill on an estimate (see JOB_OVERRUN_FACTOR).
|
|
5105
|
+
for (const over of findOverrunningJobs(s.jobs, Date.now())) {
|
|
5106
|
+
console.warn(
|
|
5107
|
+
`[scheduler] JOB OVERRUNNING ESTIMATE: project=${over.cwd ?? '(unknown)'} slug=${over.slug} `
|
|
5108
|
+
+ `ran=${Math.round(over.ranMs / 60_000)}m vs estimate=${over.estimateMinutes}m `
|
|
5109
|
+
+ `(${over.ratio.toFixed(1)}x, threshold ${JOB_OVERRUN_FACTOR}x floor ${Math.round(JOB_OVERRUN_FLOOR_MS / 60_000)}m) — `
|
|
5110
|
+
+ `still running; the ${Math.round(MAX_JOB_DURATION_MS / 3_600_000)}h deadman has NOT fired yet. `
|
|
5111
|
+
+ `Check the run log, then let it finish or cancel it via scheduler_cancel_job`,
|
|
5112
|
+
);
|
|
5113
|
+
appendAuditEvent('job_overrunning_estimate', {
|
|
5114
|
+
slug: over.slug, cwd: over.cwd, estimateMinutes: over.estimateMinutes, ranMs: over.ranMs, ratio: over.ratio,
|
|
5115
|
+
});
|
|
5116
|
+
}
|
|
5045
5117
|
}, 10 * 60_000);
|
|
5046
5118
|
|
|
5047
5119
|
// Self-rescheduling poll loop with exponential backoff. Replaces the
|
|
@@ -5626,4 +5698,4 @@ function registerAdminRoutes(adminHttp, remoteObj = remote) {
|
|
|
5626
5698
|
});
|
|
5627
5699
|
}
|
|
5628
5700
|
|
|
5629
|
-
module.exports = { registerScheduleHandlers, attachWindow, init, ROOT, PRDS_DIR, healRefusalReason, writeQueue, reconcile, reconcileSourcePromptId, allocateParallelGroup, selectHistoryJobs, parsePorcelain, FINISH_PROTOCOL, remote, pickNextBatch, pickForProject, reapDeadRunningJobs, pollRecoveryClearSource, memoryLimitedBatchSize, availableForJobs, reverifyNeedsReview, isRescanCandidate, isPromotableOriginal, selectAutoFixTargets, isEligibleForImmediateAutoFix, resolveRunId, isUnresolvableNeedsReview, healTargetForFix, buildInvestigationPrompt, isGitRepoSync, committedInWindow, computeCommittedDuringRun, classifySigtermWithCommit, isFixPlanSlug, isFixPlanBeyondDepthCap, MAX_INVESTIGATION_DEPTH, forceTickOutcome, applyPauseCleared, detectNetworkErrorInLog, detectRateLimitInLog, classifyFailureOutcome, commitGuardVerdict, TRANSIENT_RETRY_CAP, buildScheduleStatePayload, partitionBootOrphans, applyOrphanOutcome, BOOT_ORPHAN_KILL_GRACE_MS, registerAdminRoutes, notifyOriginatingTab, notifyNeedsReview, isNotifiableTerminalStatus, extractResultTextFromLog, candidatePrdsDirs, candidateArchivedPrdsDirs, resolveArchivedPrdStatus, prdDirForCwd, prdPathForJob, archivedPrdPathForJob, archivedTwinExists, findPrdDir, resolveVerifyPrdPath, resolveNotifyPrd, runPrdMigration, consolidateAllFlatPrds, shouldSkipInvestigationForCleanRun, archiveCompletedPrd, retireCompletedSlugs, SCHEDULER_BOOTED_AT, SCHEDULER_CODE_SHA, resetJobFields, executeJob, prdArchivedSkipResult, spawnJob, listPrdsInternal, computeStallSummary, findStaleQuarantinedJobs, QUARANTINE_ESCALATE_MS };
|
|
5701
|
+
module.exports = { findOverrunningJobs, JOB_OVERRUN_FACTOR, JOB_OVERRUN_FLOOR_MS, registerScheduleHandlers, attachWindow, init, ROOT, PRDS_DIR, healRefusalReason, writeQueue, reconcile, reconcileSourcePromptId, allocateParallelGroup, selectHistoryJobs, parsePorcelain, FINISH_PROTOCOL, remote, pickNextBatch, pickForProject, reapDeadRunningJobs, pollRecoveryClearSource, memoryLimitedBatchSize, availableForJobs, reverifyNeedsReview, isRescanCandidate, isPromotableOriginal, selectAutoFixTargets, isEligibleForImmediateAutoFix, resolveRunId, isUnresolvableNeedsReview, healTargetForFix, buildInvestigationPrompt, isGitRepoSync, committedInWindow, computeCommittedDuringRun, classifySigtermWithCommit, isFixPlanSlug, isFixPlanBeyondDepthCap, MAX_INVESTIGATION_DEPTH, forceTickOutcome, applyPauseCleared, detectNetworkErrorInLog, detectRateLimitInLog, classifyFailureOutcome, commitGuardVerdict, TRANSIENT_RETRY_CAP, buildScheduleStatePayload, partitionBootOrphans, applyOrphanOutcome, BOOT_ORPHAN_KILL_GRACE_MS, registerAdminRoutes, notifyOriginatingTab, notifyNeedsReview, isNotifiableTerminalStatus, extractResultTextFromLog, candidatePrdsDirs, candidateArchivedPrdsDirs, resolveArchivedPrdStatus, prdDirForCwd, prdPathForJob, archivedPrdPathForJob, archivedTwinExists, findPrdDir, resolveVerifyPrdPath, resolveNotifyPrd, runPrdMigration, consolidateAllFlatPrds, shouldSkipInvestigationForCleanRun, archiveCompletedPrd, retireCompletedSlugs, SCHEDULER_BOOTED_AT, SCHEDULER_CODE_SHA, resetJobFields, executeJob, prdArchivedSkipResult, spawnJob, listPrdsInternal, computeStallSummary, findStaleQuarantinedJobs, QUARANTINE_ESCALATE_MS };
|