claude-code-session-manager 0.75.3 → 0.77.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-CzQqcObq.js → AgentLibrary-B2ie8bbw.js} +2 -2
- package/dist/assets/{DataModel-Bj_WlLz8.js → DataModel-BIJPYw32.js} +1 -1
- package/dist/assets/{History-DnSi_OHm.js → History-CeY6dk9S.js} +2 -2
- package/dist/assets/{Hooks-0BB0dp3S.js → Hooks-BFH2ocKg.js} +2 -2
- package/dist/assets/{HostBilko-DHpwwsLQ.js → HostBilko-36gj9wLz.js} +1 -1
- package/dist/assets/{Library-CaJVqVvi.js → Library-C-hBct39.js} +1 -1
- package/dist/assets/{ListDetail-C1W2HmC2.js → ListDetail-CNq64VWV.js} +1 -1
- package/dist/assets/{MarkdownEditor-5Ob9FW3z.js → MarkdownEditor-Bh3qt5-1.js} +1 -1
- package/dist/assets/{McpServers-JxCSfm1S.js → McpServers-DpGN0oyz.js} +1 -1
- package/dist/assets/{Memory-BDeqlqwH.js → Memory-D59hUjC4.js} +6 -6
- package/dist/assets/{Panel-Dh9ZHuEj.js → Panel-DCgbaoci.js} +1 -1
- package/dist/assets/{Permissions-DXy-CbEY.js → Permissions-DAmQ0DYV.js} +2 -2
- package/dist/assets/{Plugins-_n1Iuc8T.js → Plugins-Dyfgn6Is.js} +2 -2
- package/dist/assets/{ProvenanceBadge-BP_evfxE.js → ProvenanceBadge-BiYhPO1U.js} +1 -1
- package/dist/assets/SaveBar-RV7B6sOh.js +1 -0
- package/dist/assets/Scheduler-BPaNqx1b.js +14 -0
- package/dist/assets/{ScopeSwitcher-CAWzM6RI.js → ScopeSwitcher-P4mdLGNU.js} +1 -1
- package/dist/assets/{Settings-DRRozLyT.js → Settings-BL4vf5aX.js} +1 -1
- package/dist/assets/{SkillReferenceGraph-DGHDWlz4.js → SkillReferenceGraph-BRBDyi1_.js} +1 -1
- package/dist/assets/{Skills-D8L66eiX.js → Skills-BV08gDUH.js} +2 -2
- package/dist/assets/{SystemPrompt-CYtUsonD.js → SystemPrompt-CLftSsDw.js} +1 -1
- package/dist/assets/TagLibrary-Bp8jGsd5.js +1 -0
- package/dist/assets/{TiptapBody-B2hRgbPE.js → TiptapBody-jCpuB6E5.js} +1 -1
- package/dist/assets/{Toggle-BTwsbxam.js → Toggle-D2paA1xf.js} +1 -1
- package/dist/assets/{index-DijufvkJ.js → index-BDRSqBl3.js} +704 -704
- package/dist/assets/{index-CMLnzdZC.css → index-CYhdtisq.css} +1 -1
- package/dist/assets/{settingsSchema-D6wzxAi6.js → settingsSchema-6IOLjZZN.js} +1 -1
- package/dist/index.html +2 -2
- package/package.json +8 -2
- package/plugins/session-manager-dev/skills/develop/standards.md +1 -1
- package/scripts/lib/activeSessions.cjs +116 -6
- package/scripts/project-pages-logic/dist/logic.cjs +4709 -0
- package/scripts/render-project-pages/dist/renderer.cjs +18900 -0
- package/scripts/render-project-pages.cjs +70 -0
- package/scripts/scheduler-mcp-server.cjs +269 -96
- package/scripts/validate-project-pages-summary.cjs +62 -0
- package/src/main/__tests__/agentModelResolve.test.cjs +66 -0
- package/src/main/__tests__/epicStatusMirror.test.cjs +110 -0
- package/src/main/__tests__/health-delegation-chain.test.cjs +106 -0
- package/src/main/__tests__/prdAdminRoutes.test.cjs +295 -0
- package/src/main/__tests__/prdAgentType.test.cjs +103 -0
- package/src/main/__tests__/prdCreate.test.cjs +247 -0
- package/src/main/__tests__/prdFrontmatterAgentType.test.cjs +117 -0
- package/src/main/__tests__/prdFrontmatterQuietMachine.test.cjs +108 -0
- package/src/main/__tests__/projectHomeAdminRoutes.test.cjs +485 -0
- package/src/main/__tests__/projectPages.test.cjs +73 -1
- package/src/main/__tests__/rcaReport.test.cjs +54 -0
- package/src/main/__tests__/runVerify.test.cjs +94 -0
- package/src/main/__tests__/scheduler-autofix-select.test.cjs +58 -3
- package/src/main/__tests__/scheduler-bash-timeout-env.test.cjs +103 -0
- package/src/main/__tests__/scheduler-commit-guard-noop.test.cjs +41 -0
- package/src/main/__tests__/scheduler-effective-concurrency.test.cjs +10 -0
- package/src/main/__tests__/scheduler-foreign-wip-manifest.test.cjs +78 -0
- package/src/main/__tests__/scheduler-inplace-salvage.test.cjs +242 -0
- package/src/main/__tests__/scheduler-investigation-prompt.test.cjs +31 -0
- package/src/main/__tests__/scheduler-launch-failure.test.cjs +201 -0
- package/src/main/__tests__/scheduler-leftover-fields.test.cjs +52 -0
- package/src/main/__tests__/scheduler-looks-done.test.cjs +241 -0
- package/src/main/__tests__/scheduler-prd-persona-spawn.test.cjs +135 -0
- package/src/main/__tests__/scheduler-quiet-machine-lease.test.cjs +222 -0
- package/src/main/__tests__/scheduler-reap-dead-running-jobs.test.cjs +207 -1
- package/src/main/__tests__/scheduler-shared-tree-guard.test.cjs +212 -0
- package/src/main/__tests__/scheduler-stranded-investigation.test.cjs +185 -0
- package/src/main/__tests__/scheduler-worktree-cap-defer.test.cjs +194 -0
- package/src/main/__tests__/seedAgentPersonas.test.cjs +75 -14
- package/src/main/__tests__/seedSchedulerMcp.test.cjs +66 -0
- package/src/main/__tests__/uniquePrdNumbers.test.cjs +14 -5
- package/src/main/bilkoHost.cjs +4 -3
- package/src/main/chatRunner.cjs +6 -1
- package/src/main/config.cjs +25 -33
- package/src/main/health.cjs +153 -2
- package/src/main/index.cjs +64 -5
- package/src/main/ipcSchemas.cjs +69 -1
- package/src/main/lib/__tests__/activeIndexRebuild.test.cjs +179 -0
- package/src/main/lib/__tests__/childWithLog.test.cjs +141 -0
- package/src/main/lib/__tests__/delegationReadiness.test.cjs +391 -42
- package/src/main/lib/__tests__/ephemeralCwd.test.cjs +91 -0
- package/src/main/lib/__tests__/epicWorktreeMint.test.cjs +5 -3
- package/src/main/lib/__tests__/fixChainDepth.test.cjs +40 -0
- package/src/main/lib/__tests__/gitWorktree.test.cjs +290 -5
- package/src/main/lib/__tests__/gitWorktreeSalvage.test.cjs +107 -0
- package/src/main/lib/__tests__/gitWorktreeSalvageDelta.test.cjs +153 -0
- package/src/main/lib/__tests__/jobWorktree.test.cjs +6 -4
- package/src/main/lib/__tests__/landedSinceRun.test.cjs +73 -0
- package/src/main/lib/__tests__/launchFailure.test.cjs +220 -0
- package/src/main/lib/__tests__/loadGate.test.cjs +159 -0
- package/src/main/lib/__tests__/mcpToolCatalog.test.cjs +102 -0
- package/src/main/lib/__tests__/opsOwnership.test.cjs +7 -0
- package/src/main/lib/__tests__/opsRootAbsoluteCwd.test.cjs +151 -0
- package/src/main/lib/__tests__/opsRootResolve.test.cjs +149 -0
- package/src/main/lib/__tests__/prdDeclaredPaths.test.cjs +82 -0
- package/src/main/lib/__tests__/projectRootResolve.test.cjs +148 -0
- package/src/main/lib/__tests__/queueHealth.test.cjs +58 -0
- package/src/main/lib/__tests__/quietMachineLease.test.cjs +39 -0
- package/src/main/lib/__tests__/reaperHelpers.test.cjs +133 -0
- package/src/main/lib/__tests__/schedulerBatchDepends.test.cjs +19 -9
- package/src/main/lib/__tests__/schedulerBatchFairness.test.cjs +213 -0
- package/src/main/lib/__tests__/schedulerBatchLaunchHold.test.cjs +125 -0
- package/src/main/lib/__tests__/schedulerBatchProjectCap.test.cjs +127 -0
- package/src/main/lib/__tests__/schedulerBatchQuietMachine.test.cjs +109 -0
- package/src/main/lib/__tests__/schedulerMcpServerHeadlessRefusal.test.cjs +71 -0
- package/src/main/lib/__tests__/schedulerMcpServerHelp.test.cjs +217 -0
- package/src/main/lib/__tests__/schedulerMcpServerProjectHome.test.cjs +350 -0
- package/src/main/lib/activeIndexMerge.cjs +15 -0
- package/src/main/lib/activeIndexRebuild.cjs +133 -0
- package/src/main/lib/agentModelResolve.cjs +58 -0
- package/src/main/lib/buildTarget.cjs +3 -2
- package/src/main/lib/childWithLog.cjs +69 -2
- package/src/main/lib/claudeBin.cjs +54 -1
- package/src/main/lib/crossProjectFeedback.cjs +8 -1
- package/src/main/lib/definitionOfDone.cjs +3 -2
- package/src/main/lib/delegationReadiness.cjs +514 -26
- package/src/main/lib/ephemeralCwd.cjs +78 -0
- package/src/main/lib/epicDelegationStats.cjs +2 -1
- package/src/main/lib/epicMint.cjs +17 -1
- package/src/main/lib/epicStatusMirror.cjs +95 -0
- package/src/main/lib/epicValidationHook.cjs +2 -1
- package/src/main/lib/epicWorktreeMint.cjs +5 -2
- package/src/main/lib/fixChainDepth.cjs +45 -0
- package/src/main/lib/gitWorktree.cjs +520 -21
- package/src/main/lib/jobWorktree.cjs +2 -0
- package/src/main/lib/landedSinceRun.cjs +55 -0
- package/src/main/lib/launchFailure.cjs +357 -0
- package/src/main/lib/loadGate.cjs +134 -0
- package/src/main/lib/mcpToolCatalog.cjs +370 -0
- package/src/main/lib/opsErrorLog.cjs +12 -1
- package/src/main/lib/opsOwnership.cjs +106 -0
- package/src/main/lib/prdAdminRoutes.cjs +43 -3
- package/src/main/lib/prdAgentType.cjs +84 -0
- package/src/main/lib/prdCreate.cjs +103 -15
- package/src/main/lib/prdDeclaredPaths.cjs +70 -0
- package/src/main/lib/prdFrontmatter.cjs +17 -3
- package/src/main/lib/prdLocations.cjs +13 -6
- package/src/main/lib/projectHomeAdminRoutes.cjs +402 -0
- package/src/main/lib/projectPageSummarySchema.cjs +181 -0
- package/src/main/lib/projectRootResolve.cjs +134 -0
- package/src/main/lib/promptSessionSchema.cjs +7 -0
- package/src/main/lib/queueHealth.cjs +38 -0
- package/src/main/lib/queueStore.cjs +40 -7
- package/src/main/lib/quietMachineLease.cjs +48 -0
- package/src/main/lib/rcaReport.cjs +54 -4
- package/src/main/lib/reaperHelpers.cjs +64 -1
- package/src/main/lib/scheduleJobSchema.cjs +31 -0
- package/src/main/lib/scheduleJobTransitions.cjs +6 -2
- package/src/main/lib/schedulerBatch.cjs +301 -55
- package/src/main/lib/schedulerConfig.cjs +99 -0
- package/src/main/projectBrief.cjs +3 -2
- package/src/main/projectPages.cjs +162 -3
- package/src/main/promptSessionTranscript.cjs +0 -0
- package/src/main/pty.cjs +5 -0
- package/src/main/queueOps.cjs +15 -8
- package/src/main/runVerify.cjs +50 -9
- package/src/main/scheduler/prdParser.cjs +18 -1
- package/src/main/scheduler.cjs +1701 -130
- package/src/main/seedAgentPersonas.cjs +62 -21
- package/src/main/seedSchedulerMcp.cjs +58 -4
- package/src/main/templates/project-pages-catalog.json +741 -0
- package/src/main/templates/project-pages-pipeline.md +417 -0
- package/src/preload/api.d.ts +187 -3
- package/src/preload/index.cjs +9 -0
- package/src/seed/agents/project-home-builder.md +59 -0
- package/dist/assets/SaveBar-D-gCUx4n.js +0 -1
- package/dist/assets/Scheduler-Bpd4OGju.js +0 -14
- package/dist/assets/TagLibrary-E5CLeuVk.js +0 -1
|
@@ -40,7 +40,8 @@ const APPLICATION_SOURCE_PREFIXES = ['src/', 'scripts/', 'plugins/', 'bin/'];
|
|
|
40
40
|
function countPrdsQueued(cwd, epicId, deps = {}) {
|
|
41
41
|
const readdirSync = deps.readdirSync || fs.readdirSync;
|
|
42
42
|
try {
|
|
43
|
-
const
|
|
43
|
+
const { opsPath } = require('./opsOwnership.cjs');
|
|
44
|
+
const dir = opsPath(cwd, 'scheduler', 'epics', epicId, 'prds');
|
|
44
45
|
return readdirSync(dir).filter((name) => name.endsWith('.md')).length;
|
|
45
46
|
} catch {
|
|
46
47
|
return 0;
|
|
@@ -34,6 +34,7 @@ const crypto = require('node:crypto');
|
|
|
34
34
|
const { resolveEpicPrdWriteDir } = require('./prdLocations.cjs');
|
|
35
35
|
const { assertOpsWrite } = require('./opsOwnership.cjs');
|
|
36
36
|
const { appendAuditEvent } = require('./auditLog.cjs');
|
|
37
|
+
const { mirrorEpicStatus, removeEpicMirror } = require('./epicStatusMirror.cjs');
|
|
37
38
|
// Required as the module object (not destructured) so a test can
|
|
38
39
|
// monkeypatch promptSessionSchema.assertValidPromptSession in place to
|
|
39
40
|
// simulate a corrupted construction — the real construction below is
|
|
@@ -74,7 +75,10 @@ const MINT_AUTHORITIES = Object.freeze([
|
|
|
74
75
|
]);
|
|
75
76
|
|
|
76
77
|
function activeIndexPath(cwd) {
|
|
77
|
-
|
|
78
|
+
// Lazy: opsOwnership → ephemeralCwd → activeSessions; this module is
|
|
79
|
+
// required early by several of those neighbours.
|
|
80
|
+
const { opsPath } = require('./opsOwnership.cjs');
|
|
81
|
+
return opsPath(cwd, 'prompt-sessions', 'active-index.json');
|
|
78
82
|
}
|
|
79
83
|
|
|
80
84
|
function readActiveIndex(cwd) {
|
|
@@ -362,6 +366,13 @@ function ensureEpic(cwd, { goalText, tag, epicId: explicitEpicId, status = 'prop
|
|
|
362
366
|
index.sessions[epicId] = session;
|
|
363
367
|
index.events[epicId] = [firstEvent];
|
|
364
368
|
writeActiveIndex(cwd, index);
|
|
369
|
+
// Status mirror (see epicStatusMirror.cjs's header) — every Epic is born
|
|
370
|
+
// 'proposed', so this is the FIRST mirror write for this id, inside the
|
|
371
|
+
// same withPathLock task the index write above just ran in. Carries the
|
|
372
|
+
// full validated `session` object (not just status) so a later rebuild
|
|
373
|
+
// (activeIndexRebuild.cjs) can reconstruct a complete row from this file
|
|
374
|
+
// alone.
|
|
375
|
+
mirrorEpicStatus(cwd, epicId, { session, status });
|
|
365
376
|
|
|
366
377
|
// Every mint is logged — the trace-back point for "who created this Epic"
|
|
367
378
|
// (see auditLog.cjs).
|
|
@@ -416,6 +427,10 @@ function removeEpic(cwd, epicId) {
|
|
|
416
427
|
delete index.sessions[epicId];
|
|
417
428
|
delete index.events[epicId];
|
|
418
429
|
writeActiveIndex(cwd, index);
|
|
430
|
+
// Undo the mirror written by ensureEpic's mint branch too — otherwise
|
|
431
|
+
// the rolled-back id would linger as an orphan_file (a mirrored status
|
|
432
|
+
// with no index row and no tombstone) in health.cjs's epic_index check.
|
|
433
|
+
removeEpicMirror(cwd, epicId);
|
|
419
434
|
return true;
|
|
420
435
|
});
|
|
421
436
|
}
|
|
@@ -429,6 +444,7 @@ module.exports = {
|
|
|
429
444
|
removeEpic,
|
|
430
445
|
activeIndexPath,
|
|
431
446
|
readActiveIndex,
|
|
447
|
+
writeActiveIndex,
|
|
432
448
|
personaFileExists,
|
|
433
449
|
resolvePersonaPaths,
|
|
434
450
|
// Exported so lib/activeIndexMerge.cjs's renderer-facing merge IPC handler
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* epicStatusMirror.cjs — mirrors an Epic's lifecycle `status` onto its own
|
|
5
|
+
* durable file, `prompt-sessions/<epicId>.json`, every time a write path
|
|
6
|
+
* changes that status in `active-index.json`.
|
|
7
|
+
*
|
|
8
|
+
* Why this exists: `active-index.json` is the ONLY place an Epic's status
|
|
9
|
+
* lives today. A lost, clobbered, git-reverted, or worktree-snapshotted index
|
|
10
|
+
* silently erases every open Epic it held, with no way to recover them —
|
|
11
|
+
* `activeIndexRebuild.cjs`'s `rebuildActiveIndex` is that recovery path, and
|
|
12
|
+
* it reconstructs rows from exactly the mirror this module writes. The
|
|
13
|
+
* archive file `markCompleted()` already writes at completion (session/
|
|
14
|
+
* events/transcript/archivedAt — see prompt-sessions/README.md) is the same
|
|
15
|
+
* file this module targets; a live (proposed/active) Epic gets a sparse
|
|
16
|
+
* mirror here instead, later overwritten wholesale by the real archive.
|
|
17
|
+
*
|
|
18
|
+
* Raw fs tmp+rename — NOT config.cjs's `writeJson` — so this module stays
|
|
19
|
+
* requirable from epicMint.cjs, which is deliberately Electron-free (its own
|
|
20
|
+
* header: "so the external watchdog scripts can require it"; config.cjs
|
|
21
|
+
* requires 'electron' at module load). The write shape matches config.cjs's
|
|
22
|
+
* writeJson exactly (`JSON.stringify(data, null, 2) + '\n'`, `<path>.tmp-
|
|
23
|
+
* <pid>` then rename) so main-process callers (activeIndexMerge.cjs) and
|
|
24
|
+
* epicMint.cjs never diverge in format despite using different write paths.
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
const fs = require('node:fs');
|
|
28
|
+
const path = require('node:path');
|
|
29
|
+
const { assertOpsWrite, opsPath } = require('./opsOwnership.cjs');
|
|
30
|
+
|
|
31
|
+
function epicMirrorPath(cwd, epicId) {
|
|
32
|
+
return opsPath(cwd, 'prompt-sessions', `${epicId}.json`);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function readExistingMirror(file) {
|
|
36
|
+
try {
|
|
37
|
+
const parsed = JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
38
|
+
return parsed && typeof parsed === 'object' && !Array.isArray(parsed) ? parsed : {};
|
|
39
|
+
} catch {
|
|
40
|
+
return {};
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* mirrorEpicStatus(cwd, epicId, { session?, status?, archivedAt?, writer? })
|
|
46
|
+
* — read-merge-write onto `prompt-sessions/<epicId>.json`, preserving
|
|
47
|
+
* whatever else is already there (e.g. a full `PromptSessionArchive` written
|
|
48
|
+
* by `markCompleted`, or a prior mirror).
|
|
49
|
+
*
|
|
50
|
+
* When `session` (the full PromptSession record) is given, it is spread onto
|
|
51
|
+
* the file too — not just the four mirror fields — so a live (proposed/
|
|
52
|
+
* active) Epic's file alone is enough for `activeIndexRebuild.cjs` to
|
|
53
|
+
* reconstruct a complete `active-index.json` row, not just its status.
|
|
54
|
+
* `status`/`archivedAt` may be passed independently of `session` (or to
|
|
55
|
+
* override `session.status`) for callers that only know the status.
|
|
56
|
+
*
|
|
57
|
+
* Never throws on a read failure (a missing/corrupt existing file is treated
|
|
58
|
+
* as "start fresh"); a write failure propagates, matching every other atomic
|
|
59
|
+
* writer in this codebase (config.cjs's writeTextAtomic, epicMint.cjs's own
|
|
60
|
+
* writeActiveIndex).
|
|
61
|
+
*/
|
|
62
|
+
function mirrorEpicStatus(cwd, epicId, { session = null, status = null, archivedAt = null, writer = 'epics' } = {}) {
|
|
63
|
+
const resolvedStatus = status || (session && session.status) || null;
|
|
64
|
+
if (!cwd || !epicId || !resolvedStatus) return;
|
|
65
|
+
const file = epicMirrorPath(cwd, epicId);
|
|
66
|
+
assertOpsWrite(file, writer);
|
|
67
|
+
const existing = readExistingMirror(file);
|
|
68
|
+
const merged = {
|
|
69
|
+
...existing,
|
|
70
|
+
...(session || {}),
|
|
71
|
+
id: epicId,
|
|
72
|
+
cwd,
|
|
73
|
+
status: resolvedStatus,
|
|
74
|
+
archivedAt: archivedAt ?? existing.archivedAt ?? null,
|
|
75
|
+
indexedAt: new Date().toISOString(),
|
|
76
|
+
};
|
|
77
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
78
|
+
const tmp = `${file}.tmp-${process.pid}`;
|
|
79
|
+
fs.writeFileSync(tmp, JSON.stringify(merged, null, 2) + '\n');
|
|
80
|
+
fs.renameSync(tmp, file);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* removeEpicMirror(cwd, epicId) — best-effort delete of the mirror file, used
|
|
85
|
+
* only by epicMint.cjs's removeEpic() rollback (undoing a mint whose caller
|
|
86
|
+
* failed to complete its own work). Never throws — a missing file is a no-op.
|
|
87
|
+
*/
|
|
88
|
+
function removeEpicMirror(cwd, epicId) {
|
|
89
|
+
if (!cwd || !epicId) return;
|
|
90
|
+
try {
|
|
91
|
+
fs.unlinkSync(epicMirrorPath(cwd, epicId));
|
|
92
|
+
} catch { /* never existed, or already gone */ }
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
module.exports = { mirrorEpicStatus, removeEpicMirror, epicMirrorPath };
|
|
@@ -62,7 +62,8 @@ function pairKey(epicId, prdSlug) {
|
|
|
62
62
|
*/
|
|
63
63
|
function defaultReadActiveIndex(cwd) {
|
|
64
64
|
try {
|
|
65
|
-
const
|
|
65
|
+
const { opsPath } = require('./opsOwnership.cjs');
|
|
66
|
+
const p = opsPath(cwd, 'prompt-sessions', 'active-index.json');
|
|
66
67
|
return JSON.parse(fs.readFileSync(p, 'utf8'));
|
|
67
68
|
} catch {
|
|
68
69
|
return null;
|
|
@@ -13,8 +13,11 @@
|
|
|
13
13
|
* that can only run main-process side, so approveProposed fires this IPC
|
|
14
14
|
* call fire-and-forget and patches `worktree` onto the session once it
|
|
15
15
|
* resolves — the transition itself is never blocked or delayed by it, and a
|
|
16
|
-
* failure (not a repo /
|
|
17
|
-
* leaves `worktree` unset, exactly as if this call
|
|
16
|
+
* failure (not a repo / disabled / cap reached / carry-over of a dirty base
|
|
17
|
+
* tree's WIP failed) simply leaves `worktree` unset, exactly as if this call
|
|
18
|
+
* had never been made. A dirty base tree itself no longer disables
|
|
19
|
+
* isolation — its outstanding diff is carried into the fresh worktree
|
|
20
|
+
* instead (gitWorktree.cjs's createWorktree).
|
|
18
21
|
*
|
|
19
22
|
* Mirrors promptSessionsCreateEpic.cjs's shape: `validatePath(cwd)` closes
|
|
20
23
|
* the same "arbitrary renderer-supplied cwd" gap that handler documents,
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* fixChainDepth.cjs — pure slug-inspection helpers for the fix-chain depth
|
|
3
|
+
* guard (PRD 1113). Generalizes scheduler.cjs's `isFixPlanSlug` (`^\d+-fix-`)
|
|
4
|
+
* into a counter: how many CONSECUTIVE '-fix-' segments immediately follow
|
|
5
|
+
* the leading `NN-` prefix. Only a run starting right at the prefix counts —
|
|
6
|
+
* a later segment that happens to read 'fix' (e.g.
|
|
7
|
+
* '13-fix-loop-extraction-and-round-trip', where 'loop' breaks the run right
|
|
8
|
+
* after the first 'fix') does not extend the count, and a segment that only
|
|
9
|
+
* contains 'fix' as a substring (e.g. '113-prefix-foo') never matches at all
|
|
10
|
+
* since segments are compared for exact equality after splitting on '-'.
|
|
11
|
+
*
|
|
12
|
+
* No filesystem access, no scheduler.cjs dependency — safe to require from
|
|
13
|
+
* lib/prdCreate.cjs without pulling in the scheduler module graph.
|
|
14
|
+
*/
|
|
15
|
+
'use strict';
|
|
16
|
+
|
|
17
|
+
function fixChainDepthOf(slug) {
|
|
18
|
+
const rest = String(slug).replace(/^\d+-/, '');
|
|
19
|
+
const segments = rest.split('-');
|
|
20
|
+
let depth = 0;
|
|
21
|
+
for (const seg of segments) {
|
|
22
|
+
if (seg !== 'fix') break;
|
|
23
|
+
depth += 1;
|
|
24
|
+
}
|
|
25
|
+
return depth;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Strips the leading consecutive '-fix-' chain a slug carries, returning the
|
|
30
|
+
* base slug the chain descends from — e.g. '113-fix-fix-foo' -> '113-foo'.
|
|
31
|
+
* Used only for error messages (naming what actually failed to close).
|
|
32
|
+
*/
|
|
33
|
+
function baseSlugOf(slug) {
|
|
34
|
+
const str = String(slug);
|
|
35
|
+
const prefixMatch = str.match(/^(\d+)-/);
|
|
36
|
+
const prefix = prefixMatch ? prefixMatch[1] : '';
|
|
37
|
+
const rest = str.replace(/^\d+-/, '');
|
|
38
|
+
const segments = rest.split('-');
|
|
39
|
+
let i = 0;
|
|
40
|
+
while (i < segments.length && segments[i] === 'fix') i += 1;
|
|
41
|
+
const remainder = segments.slice(i).join('-');
|
|
42
|
+
return prefix ? `${prefix}-${remainder}` : remainder;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
module.exports = { fixChainDepthOf, baseSlugOf };
|