claude-code-session-manager 0.75.1 → 0.75.3
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-CGplUKxY.js → AgentLibrary-CzQqcObq.js} +1 -1
- package/dist/assets/{DataModel-DQ15KxVb.js → DataModel-Bj_WlLz8.js} +1 -1
- package/dist/assets/{History-v2TSC_6A.js → History-DnSi_OHm.js} +1 -1
- package/dist/assets/{Hooks-Co7s6BNB.js → Hooks-0BB0dp3S.js} +1 -1
- package/dist/assets/{HostBilko-DJj8FWPK.js → HostBilko-DHpwwsLQ.js} +1 -1
- package/dist/assets/{Library-DQaC9VQ1.js → Library-CaJVqVvi.js} +1 -1
- package/dist/assets/{ListDetail-BwFRfAZm.js → ListDetail-C1W2HmC2.js} +1 -1
- package/dist/assets/{MarkdownEditor-C155gNpc.js → MarkdownEditor-5Ob9FW3z.js} +1 -1
- package/dist/assets/{McpServers-BmLgE_gS.js → McpServers-JxCSfm1S.js} +1 -1
- package/dist/assets/{Memory-ISwNcS5j.js → Memory-BDeqlqwH.js} +1 -1
- package/dist/assets/{Panel-1adjEpj-.js → Panel-Dh9ZHuEj.js} +1 -1
- package/dist/assets/{Permissions-FrCz5cGa.js → Permissions-DXy-CbEY.js} +1 -1
- package/dist/assets/{Plugins-zUssKp_b.js → Plugins-_n1Iuc8T.js} +2 -2
- package/dist/assets/{ProvenanceBadge-CAXqA_HX.js → ProvenanceBadge-BP_evfxE.js} +1 -1
- package/dist/assets/{SaveBar-D9cqms3Y.js → SaveBar-D-gCUx4n.js} +1 -1
- package/dist/assets/{Scheduler-dNNc9S11.js → Scheduler-Bpd4OGju.js} +3 -3
- package/dist/assets/{ScopeSwitcher-1wBTne7S.js → ScopeSwitcher-CAWzM6RI.js} +1 -1
- package/dist/assets/{Settings-BT_expIg.js → Settings-DRRozLyT.js} +1 -1
- package/dist/assets/{SkillReferenceGraph-CVccq4Cu.js → SkillReferenceGraph-DGHDWlz4.js} +1 -1
- package/dist/assets/{Skills-xFpRY0ld.js → Skills-D8L66eiX.js} +1 -1
- package/dist/assets/{SystemPrompt-CEk_71th.js → SystemPrompt-CYtUsonD.js} +1 -1
- package/dist/assets/{TagLibrary-C2zhihQG.js → TagLibrary-E5CLeuVk.js} +1 -1
- package/dist/assets/{TiptapBody-CQKcHKaD.js → TiptapBody-B2hRgbPE.js} +1 -1
- package/dist/assets/{Toggle-CQ-IBb8m.js → Toggle-BTwsbxam.js} +1 -1
- package/dist/assets/{index-Dbo9R4e0.css → index-CMLnzdZC.css} +1 -1
- package/dist/assets/{index-BgbV3sKX.js → index-DijufvkJ.js} +4 -4
- package/dist/assets/{settingsSchema-D6ccSKqm.js → settingsSchema-D6wzxAi6.js} +1 -1
- package/dist/index.html +2 -2
- package/package.json +1 -1
- package/scripts/lib/activeSessions.cjs +35 -3
- package/scripts/scheduler-mcp-server.cjs +16 -1
- package/src/main/__tests__/prdAdminRoutes.test.cjs +100 -0
- package/src/main/__tests__/queueHistory.test.cjs +7 -0
- package/src/main/__tests__/scheduleJobSchema.test.cjs +1 -1
- package/src/main/__tests__/scheduleJobStatusDrift.test.cjs +1 -1
- package/src/main/__tests__/scheduleJobTransitions.test.cjs +24 -0
- package/src/main/__tests__/scheduler-clear-queue-history.test.cjs +134 -0
- package/src/main/__tests__/scheduler-prd-missing-skip.test.cjs +5 -1
- package/src/main/ipcSchemas.cjs +10 -0
- package/src/main/lib/__tests__/opsRootAbsoluteCwd.test.cjs +51 -0
- package/src/main/lib/__tests__/opsRootNestedWrite.test.cjs +51 -0
- package/src/main/lib/__tests__/schedulerBatchDepends.test.cjs +26 -0
- package/src/main/lib/prdAdminRoutes.cjs +12 -2
- package/src/main/lib/queueHistory.cjs +6 -4
- package/src/main/lib/queueStore.cjs +42 -6
- package/src/main/lib/scheduleJobSchema.cjs +1 -1
- package/src/main/lib/scheduleJobTransitions.cjs +19 -6
- package/src/main/lib/schedulerBatch.cjs +17 -1
- package/src/main/scheduler.cjs +89 -16
- package/src/preload/api.d.ts +1 -1
package/src/main/scheduler.cjs
CHANGED
|
@@ -100,7 +100,7 @@ const queueOps = require('./queueOps.cjs');
|
|
|
100
100
|
// home-dir layout.
|
|
101
101
|
const { resolvePrdsDirs, resolveArchivedPrdsDirs, resolvePrdWriteDir, listEpicPrdDirs, listArchivedPrdDirs } = require('./lib/prdLocations.cjs');
|
|
102
102
|
const { ensureEpic, appendPrdCreatedEvent, readActiveIndex } = require('./lib/epicMint.cjs');
|
|
103
|
-
const { transitionJob } = require('./lib/scheduleJobTransitions.cjs');
|
|
103
|
+
const { transitionJob, STATUS_HISTORY_CAP } = require('./lib/scheduleJobTransitions.cjs');
|
|
104
104
|
const { buildContextDigest, composeExecutorPrompt } = require('./lib/epicContextDigest.cjs');
|
|
105
105
|
const { JOB_STATUSES } = require('./lib/scheduleJobSchema.cjs');
|
|
106
106
|
const { appendAuditEvent } = require('./lib/auditLog.cjs');
|
|
@@ -1424,7 +1424,7 @@ async function reconcile(state) {
|
|
|
1424
1424
|
seen.add(job.slug);
|
|
1425
1425
|
next.push({ ...job });
|
|
1426
1426
|
console.warn(`[scheduler] reconcile: keeping ${job.status} job ${job.slug} — PRD source not visible in any candidate dir`);
|
|
1427
|
-
} else if (job.status === 'completed' || job.status === 'failed') {
|
|
1427
|
+
} else if (job.status === 'completed' || job.status === 'failed' || job.status === 'skipped') {
|
|
1428
1428
|
terminalDroppedNeedingHistoryCheck.push(job);
|
|
1429
1429
|
}
|
|
1430
1430
|
continue;
|
|
@@ -2104,7 +2104,7 @@ async function clearPause(source) {
|
|
|
2104
2104
|
* already-'completed' job, and that path is exactly what this guards.
|
|
2105
2105
|
*/
|
|
2106
2106
|
function resetJobFields(job, errorMsg, opts = {}) {
|
|
2107
|
-
if (job.status === 'completed' && opts.force !== true) return false;
|
|
2107
|
+
if ((job.status === 'completed' || job.status === 'skipped') && opts.force !== true) return false;
|
|
2108
2108
|
if (!transitionJob(job, 'pending', { reason: errorMsg ?? 'reset to pending', source: opts.source ?? 'resetJobFields' })) return false;
|
|
2109
2109
|
job.runId = null;
|
|
2110
2110
|
job.startedAt = null;
|
|
@@ -3486,13 +3486,18 @@ async function spawnJob(job, runId, runDir, defaultCwd) {
|
|
|
3486
3486
|
// Stale queue entry: the PRD was archived (already shipped) or is gone
|
|
3487
3487
|
// from disk entirely (deleted before dispatch). Both are retire-not-fail
|
|
3488
3488
|
// results from prdArchivedSkipResult with exitCode 0 and no transcript —
|
|
3489
|
-
//
|
|
3490
|
-
//
|
|
3489
|
+
// no verify pass, no commit guard, no RCA feedback item — but only
|
|
3490
|
+
// 'prd-archived' actually means the work shipped (archivedTwinExists
|
|
3491
|
+
// found the file under a prds-archived/ dir). 'prd-missing' means no
|
|
3492
|
+
// executor ever ran at all, so it must NOT land on the same 'completed'
|
|
3493
|
+
// status a genuine successful run produces — that conflation is what let
|
|
3494
|
+
// 20 never-executed sigma PRDs read as shipped (2026-08-30 incident).
|
|
3491
3495
|
if (res.skipped) {
|
|
3496
|
+
const targetStatus = res.skipped === 'prd-missing' ? 'skipped' : 'completed';
|
|
3492
3497
|
await mutate((s) => {
|
|
3493
3498
|
const idx = s.jobs.findIndex((x) => x.slug === job.slug);
|
|
3494
3499
|
if (idx >= 0) {
|
|
3495
|
-
transitionJob(s.jobs[idx],
|
|
3500
|
+
transitionJob(s.jobs[idx], targetStatus, { reason: res.note ?? 'PRD archived or missing — treated as already-shipped', source: 'spawnJob:skip-archived' });
|
|
3496
3501
|
s.jobs[idx].finishedAt = new Date().toISOString();
|
|
3497
3502
|
s.jobs[idx].exitCode = 0;
|
|
3498
3503
|
s.jobs[idx].error = null;
|
|
@@ -4297,7 +4302,7 @@ async function pollLoop() {
|
|
|
4297
4302
|
// callers/tests that only pass `jobs` are unaffected.
|
|
4298
4303
|
function selectHistoryJobs(jobs, limit, historyEntries = []) {
|
|
4299
4304
|
const cap = Math.max(1, Math.min(500, Number.isFinite(limit) ? Math.floor(limit) : 50));
|
|
4300
|
-
const hot = (Array.isArray(jobs) ? jobs : []).filter((j) => j && (j.status === 'completed' || j.status === 'failed'));
|
|
4305
|
+
const hot = (Array.isArray(jobs) ? jobs : []).filter((j) => j && (j.status === 'completed' || j.status === 'failed' || j.status === 'skipped'));
|
|
4301
4306
|
const seen = new Set(hot.map((j) => `${j.slug}|${j.runId ?? ''}`));
|
|
4302
4307
|
const archived = (Array.isArray(historyEntries) ? historyEntries : []).filter((j) => {
|
|
4303
4308
|
if (!j) return false;
|
|
@@ -4743,6 +4748,43 @@ async function reverifyNeedsReview() {
|
|
|
4743
4748
|
return { rescanned: candidates.length, healed, leftForReview };
|
|
4744
4749
|
}
|
|
4745
4750
|
|
|
4751
|
+
/**
|
|
4752
|
+
* schedule:clear-queue's core state mutation, split out so it's testable
|
|
4753
|
+
* without ipcMain/electron: every victim (non-running job whose slug is in
|
|
4754
|
+
* `victimSlugs`) must leave a durable history.jsonl record before it
|
|
4755
|
+
* disappears from queue.json — a manual clear used to just filter the row
|
|
4756
|
+
* out with no trace (a job could vanish with zero audit trail; see the
|
|
4757
|
+
* 2026-08-30 sigma `788-pr-sweep-final-gate` incident). Non-terminal victims
|
|
4758
|
+
* (pending/investigating/needs_review/quarantined) are force-transitioned to
|
|
4759
|
+
* 'skipped' — never 'completed', since a manually-cleared job did not ship.
|
|
4760
|
+
* Victims already terminal (completed/failed/skipped) keep their real
|
|
4761
|
+
* status; they just get a statusHistory note + a history row so they don't
|
|
4762
|
+
* silently drop before aging past HISTORY_RETENTION_MS.
|
|
4763
|
+
*
|
|
4764
|
+
* Mutates `state.jobs` in place (drops the victims, same contract as
|
|
4765
|
+
* reconcile()) and returns the job snapshots to append to history.jsonl.
|
|
4766
|
+
*/
|
|
4767
|
+
function applyClearQueueVictims(state, victimSlugs, archiveNoteBySlug, archiveDir) {
|
|
4768
|
+
const historyEntries = [];
|
|
4769
|
+
for (const job of state.jobs) {
|
|
4770
|
+
if (!victimSlugs.has(job.slug)) continue;
|
|
4771
|
+
const reason = archiveNoteBySlug?.get(job.slug) ?? `PRD archived to ${archiveDir}`;
|
|
4772
|
+
if (job.status === 'completed' || job.status === 'failed' || job.status === 'skipped') {
|
|
4773
|
+
// Already terminal — keep the real status, just record the clear.
|
|
4774
|
+
const history = Array.isArray(job.statusHistory) ? job.statusHistory : [];
|
|
4775
|
+
history.push({ from: job.status, to: job.status, reason, source: 'clear-queue', at: new Date().toISOString() });
|
|
4776
|
+
while (history.length > STATUS_HISTORY_CAP) history.shift();
|
|
4777
|
+
job.statusHistory = history;
|
|
4778
|
+
} else {
|
|
4779
|
+
transitionJob(job, 'skipped', { reason, source: 'clear-queue' });
|
|
4780
|
+
}
|
|
4781
|
+
if (!job.finishedAt) job.finishedAt = new Date().toISOString();
|
|
4782
|
+
historyEntries.push({ ...job });
|
|
4783
|
+
}
|
|
4784
|
+
state.jobs = state.jobs.filter((j) => !victimSlugs.has(j.slug));
|
|
4785
|
+
return historyEntries;
|
|
4786
|
+
}
|
|
4787
|
+
|
|
4746
4788
|
function registerScheduleHandlers() {
|
|
4747
4789
|
ensureDirs();
|
|
4748
4790
|
supervisor.registerHandlers();
|
|
@@ -4905,10 +4947,6 @@ function registerScheduleHandlers() {
|
|
|
4905
4947
|
return { ok: true, kind: 'info', message };
|
|
4906
4948
|
});
|
|
4907
4949
|
|
|
4908
|
-
// Archive every non-running PRD and drop its entry from queue.json.
|
|
4909
|
-
// Running entries are kept (would orphan an in-flight job). PRD files are
|
|
4910
|
-
// moved (not deleted) to prds-archived/<ISO>/ so the user can recover them.
|
|
4911
|
-
// Path containment is enforced — only files inside PRDS_DIR are moved.
|
|
4912
4950
|
ipcMain.handle('schedule:clear-queue', async () => {
|
|
4913
4951
|
ensureDirs();
|
|
4914
4952
|
const ts = new Date().toISOString().replace(/[:.]/g, '-');
|
|
@@ -4920,6 +4958,7 @@ function registerScheduleHandlers() {
|
|
|
4920
4958
|
}
|
|
4921
4959
|
await fsp.mkdir(archiveDir, { recursive: true });
|
|
4922
4960
|
let archived = 0;
|
|
4961
|
+
const archiveNoteBySlug = new Map();
|
|
4923
4962
|
for (const job of victims) {
|
|
4924
4963
|
const srcDir = await findPrdDir(job.slug) ?? prdDirForCwd(job.cwd);
|
|
4925
4964
|
const src = path.resolve(path.join(srcDir, `${job.slug}.md`));
|
|
@@ -4928,17 +4967,27 @@ function registerScheduleHandlers() {
|
|
|
4928
4967
|
try {
|
|
4929
4968
|
await fsp.rename(src, dst);
|
|
4930
4969
|
archived++;
|
|
4970
|
+
archiveNoteBySlug.set(job.slug, `PRD file archived to ${archiveDir}`);
|
|
4931
4971
|
} catch (e) {
|
|
4932
4972
|
// ENOENT: the .md is already gone (reconcile would drop it on next
|
|
4933
4973
|
// read anyway). Either way, fall through and remove from queue.
|
|
4934
4974
|
if (e?.code !== 'ENOENT') {
|
|
4935
4975
|
logs.writeLine({ level: 'warn', scope: 'scheduler', message: 'clear-queue: rename failed', meta: { slug: job.slug, error: e?.message } });
|
|
4936
4976
|
}
|
|
4977
|
+
archiveNoteBySlug.set(job.slug, `PRD file already gone (ENOENT) when archiving to ${archiveDir}`);
|
|
4937
4978
|
}
|
|
4938
4979
|
}
|
|
4939
4980
|
await mutate(async (s) => {
|
|
4940
4981
|
const victimSlugs = new Set(victims.map((j) => j.slug));
|
|
4941
|
-
|
|
4982
|
+
const historyEntries = applyClearQueueVictims(s, victimSlugs, archiveNoteBySlug, archiveDir);
|
|
4983
|
+
// Append BEFORE this mutate's writeQueue persists s.jobs without the
|
|
4984
|
+
// victims (mutate() only writes after this callback resolves) — same
|
|
4985
|
+
// append-before-drop ordering queueHistory.cjs's reconcile() callers
|
|
4986
|
+
// use, so a crash right after this handler returns can never leave a
|
|
4987
|
+
// row gone from queue.json with nothing in history.jsonl yet.
|
|
4988
|
+
if (historyEntries.length > 0) {
|
|
4989
|
+
await queueHistory.appendHistory(historyEntries);
|
|
4990
|
+
}
|
|
4942
4991
|
await reconcile(s);
|
|
4943
4992
|
return null;
|
|
4944
4993
|
});
|
|
@@ -5353,6 +5402,20 @@ async function init() {
|
|
|
5353
5402
|
}
|
|
5354
5403
|
}
|
|
5355
5404
|
|
|
5405
|
+
// Measured against this repo's own live+archived PRD set (868 entries
|
|
5406
|
+
// across every local project — the admin route has no cwd filter by
|
|
5407
|
+
// default): no single field dominates a listPrdsInternal() entry: title is
|
|
5408
|
+
// the largest at ~30% of payload bytes, followed by slug/cwd/sourcePromptId/
|
|
5409
|
+
// epicId at 12-14% each — the 353KB the route was shipping came from
|
|
5410
|
+
// returning the full unbounded row count, not from one oversized field.
|
|
5411
|
+
// This trims the fields an agent doesn't need to answer "what PRDs are
|
|
5412
|
+
// there" (parallelGroup/estimateMinutes/sourcePromptId/epicId/
|
|
5413
|
+
// archivedStatus); `fields=full` restores them.
|
|
5414
|
+
function toCompactPrdEntry(entry) {
|
|
5415
|
+
const { slug, title, cwd, mtimeMs, archived, status } = entry;
|
|
5416
|
+
return { slug, title, cwd, mtimeMs, archived, status };
|
|
5417
|
+
}
|
|
5418
|
+
|
|
5356
5419
|
/**
|
|
5357
5420
|
* listPrdsInternal() → every live + archived PRD across every project,
|
|
5358
5421
|
* with each entry's real job status folded in (`status`: the live queue
|
|
@@ -5612,15 +5675,25 @@ const remote = {
|
|
|
5612
5675
|
|
|
5613
5676
|
// Every live+archived PRD across every project (listPrdsInternal, shared
|
|
5614
5677
|
// with the renderer's schedule:list-prds IPC handler), filtered by the
|
|
5615
|
-
// admin route's cwd/epicId/status query params
|
|
5678
|
+
// admin route's cwd/epicId/status query params and paged by
|
|
5679
|
+
// limit/offset. Sort order is listPrdsInternal's own slug.localeCompare
|
|
5680
|
+
// (numeric) — stable across calls since it's a pure string sort, so
|
|
5681
|
+
// paging by offset can't skip or duplicate an entry between requests as
|
|
5682
|
+
// long as the underlying PRD set doesn't change mid-page.
|
|
5616
5683
|
async listPrds(filter = {}) {
|
|
5617
5684
|
const all = await listPrdsInternal();
|
|
5618
|
-
|
|
5685
|
+
const filtered = all.filter((entry) => {
|
|
5619
5686
|
if (filter.cwd && entry.cwd !== filter.cwd) return false;
|
|
5620
5687
|
if (filter.epicId && entry.epicId !== filter.epicId) return false;
|
|
5621
5688
|
if (filter.status && entry.status !== filter.status) return false;
|
|
5622
5689
|
return true;
|
|
5623
5690
|
});
|
|
5691
|
+
const total = filtered.length;
|
|
5692
|
+
const limit = filter.limit ?? 100;
|
|
5693
|
+
const offset = filter.offset ?? 0;
|
|
5694
|
+
const page = filtered.slice(offset, offset + limit);
|
|
5695
|
+
const prds = filter.fields === 'full' ? page : page.map(toCompactPrdEntry);
|
|
5696
|
+
return { prds, total, limit, offset, hasMore: offset + page.length < total };
|
|
5624
5697
|
},
|
|
5625
5698
|
|
|
5626
5699
|
// Full body + parsed frontmatter for one PRD, live or archived. Mirrors
|
|
@@ -5759,7 +5832,7 @@ const remote = {
|
|
|
5759
5832
|
const state = await readQueue();
|
|
5760
5833
|
const job = state.jobs.find((j) => j.slug === slug);
|
|
5761
5834
|
if (!job) return { ok: false, error: 'not found' };
|
|
5762
|
-
if (job.status === 'completed' || job.status === 'failed' || job.status === 'needs_review') {
|
|
5835
|
+
if (job.status === 'completed' || job.status === 'failed' || job.status === 'needs_review' || job.status === 'skipped') {
|
|
5763
5836
|
return { ok: false, error: `job already terminal (status: "${job.status}") — nothing to cancel` };
|
|
5764
5837
|
}
|
|
5765
5838
|
const wasRunning = job.status === 'running';
|
|
@@ -5821,4 +5894,4 @@ function registerAdminRoutes(adminHttp, remoteObj = remote) {
|
|
|
5821
5894
|
});
|
|
5822
5895
|
}
|
|
5823
5896
|
|
|
5824
|
-
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, isExhaustedAutoFix, isPlanUnqueued, fixSlugFor, 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, resolveFixPlanPath, resolveNotifyPrd, runPrdMigration, consolidateAllFlatPrds, shouldSkipInvestigationForCleanRun, archiveCompletedPrd, retireCompletedSlugs, SCHEDULER_BOOTED_AT, SCHEDULER_CODE_SHA, resetJobFields, executeJob, prdArchivedSkipResult, spawnJob, listPrdsInternal, computeStallSummary, findStaleQuarantinedJobs, QUARANTINE_ESCALATE_MS };
|
|
5897
|
+
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, isExhaustedAutoFix, isPlanUnqueued, fixSlugFor, 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, resolveFixPlanPath, resolveNotifyPrd, runPrdMigration, consolidateAllFlatPrds, shouldSkipInvestigationForCleanRun, archiveCompletedPrd, retireCompletedSlugs, SCHEDULER_BOOTED_AT, SCHEDULER_CODE_SHA, resetJobFields, executeJob, prdArchivedSkipResult, spawnJob, listPrdsInternal, computeStallSummary, findStaleQuarantinedJobs, QUARANTINE_ESCALATE_MS, applyClearQueueVictims };
|
package/src/preload/api.d.ts
CHANGED
|
@@ -391,7 +391,7 @@ export interface ScheduleConfig {
|
|
|
391
391
|
* so this union is a manually-kept copy; drift from JOB_STATUSES (and from
|
|
392
392
|
* the renderer's own mirrors in StatusBadge.tsx/SchedulePanel.tsx) is
|
|
393
393
|
* caught by src/main/__tests__/scheduleJobStatusDrift.test.cjs. */
|
|
394
|
-
export type ScheduleJobStatus = 'pending' | 'running' | 'investigating' | 'completed' | 'failed' | 'needs_review' | 'quarantined';
|
|
394
|
+
export type ScheduleJobStatus = 'pending' | 'running' | 'investigating' | 'completed' | 'skipped' | 'failed' | 'needs_review' | 'quarantined';
|
|
395
395
|
|
|
396
396
|
export interface ScheduleJobRuntime {
|
|
397
397
|
pid: number;
|