claude-code-session-manager 0.122.0 → 0.123.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-BmJ8hIPw.js → AgentLibrary-DxWN3FSN.js} +2 -2
- package/dist/assets/{Button-BS4kmz4p.js → Button-CISLFSKb.js} +1 -1
- package/dist/assets/DataModel-CYPbhGrx.js +1 -0
- package/dist/assets/{History-pg00b2Gd.js → History-Fhouektw.js} +2 -2
- package/dist/assets/{Hooks-BTEs0UZY.js → Hooks-COfIcyYV.js} +3 -3
- package/dist/assets/{Library-DuaJ-VSn.js → Library-Bt5WOyyu.js} +7 -7
- package/dist/assets/ListDetail-DH7uzYd5.js +1 -0
- package/dist/assets/{McpServers-Dy-wnG_X.js → McpServers-CwyVEzMN.js} +2 -2
- package/dist/assets/{Memory-Bs1T1Jo7.js → Memory-k9TWT9N4.js} +8 -8
- package/dist/assets/{Panel-8UhLXEOW.js → Panel-Di8JqCYN.js} +1 -1
- package/dist/assets/{Permissions-BfwzvmBS.js → Permissions-FFs6Rq1H.js} +3 -3
- package/dist/assets/{Plugins-McjyvvKh.js → Plugins-uK5vl_RE.js} +2 -2
- package/dist/assets/{ProvenanceBadge-D0Ov_6WJ.js → ProvenanceBadge-CGDyGDoN.js} +1 -1
- package/dist/assets/{SaveBar-Cd6hJR6K.js → SaveBar-Cnwc_XfF.js} +1 -1
- package/dist/assets/{Scheduler-BZXKqYJP.js → Scheduler-aACa6_mC.js} +7 -7
- package/dist/assets/{ScopeSwitcher-C24ysV1K.js → ScopeSwitcher-CoG3CSlC.js} +1 -1
- package/dist/assets/Settings-BG0RM6Di.js +4 -0
- package/dist/assets/{SkillReferenceGraph-BsWuiTbw.js → SkillReferenceGraph-COffGu_A.js} +1 -1
- package/dist/assets/Skills--qQpFjjf.js +2 -0
- package/dist/assets/SystemPrompt-Cr9RRSiZ.js +1 -0
- package/dist/assets/TagLibrary-D_ZbXwBv.js +1 -0
- package/dist/assets/{TiptapBody-C4kIvIMH.js → TiptapBody-CCHsa8Jv.js} +1 -1
- package/dist/assets/{Toggle-pP19zlyk.js → Toggle-BUOj4pws.js} +1 -1
- package/dist/assets/{ViewTabs-CpzN8e5I.js → ViewTabs-BdpsL7yr.js} +1 -1
- package/dist/assets/{historyTotals-Caq78bb5.js → historyTotals-Dx6ca881.js} +1 -1
- package/dist/assets/{index-Dd7UQabV.css → index-BnKaYERU.css} +1 -1
- package/dist/assets/{index-Bjtguv6I.js → index-CkNGj8FA.js} +151 -151
- package/dist/assets/{settingsSchema-CC2ySu3d.js → settingsSchema-BZhkpr9e.js} +1 -1
- package/dist/assets/{skillFrontmatter-hDhNo8jE.js → skillFrontmatter-N13KGqbs.js} +1 -1
- package/dist/assets/{useAgentsDirWatch-BuOtY25U.js → useAgentsDirWatch-De9UsbDt.js} +1 -1
- package/dist/index.html +2 -2
- package/package.json +1 -1
- package/plugins/session-manager-dev/skills/develop/SKILL.md +29 -24
- package/scripts/scheduler-mcp-server.cjs +142 -78
- package/src/main/agentLibrary.cjs +8 -3
- package/src/main/build-info.json +4 -4
- package/src/main/crashDiagnostics.cjs +24 -0
- package/src/main/historyAggregator.cjs +41 -7
- package/src/main/index.cjs +13 -3
- package/src/main/ipcSchemas.cjs +30 -22
- package/src/main/lib/activeSessions.cjs +93 -32
- package/src/main/lib/epic/delegationReadiness.cjs +2 -0
- package/src/main/lib/epic/delegationSelfHeal.cjs +77 -0
- package/src/main/lib/epic/epicMint.cjs +1 -1
- package/src/main/lib/epic/epicStandingInstructions.cjs +73 -0
- package/src/main/lib/epic/guardSpawnSettings.cjs +76 -0
- package/src/main/lib/feedback-remote/crossProjectFeedback.cjs +9 -2
- package/src/main/lib/feedback-remote/remoteClientSessions.cjs +3 -11
- package/src/main/lib/feedback-remote/remoteE2eCrypto.cjs +1 -1
- package/src/main/lib/git/gitWorktree.cjs +9 -4
- package/src/main/lib/git/worktreeDeps.cjs +13 -2
- package/src/main/lib/git/worktreeSetup.cjs +212 -0
- package/src/main/lib/mcpToolCatalog.cjs +36 -9
- package/src/main/lib/persona-macro/agentPersonaSchema.cjs +4 -0
- package/src/main/lib/persona-macro/shippedPersonaSeeds.cjs +23 -0
- package/src/main/lib/prd/prdAgentType.cjs +28 -0
- package/src/main/lib/prd/prdBodyPatch.cjs +138 -0
- package/src/main/lib/prd/prdCreate.cjs +245 -27
- package/src/main/lib/prd/prdGateFiles.cjs +31 -0
- package/src/main/lib/scheduler/definitionOfDone.cjs +24 -3
- package/src/main/lib/scheduler/queueStore.cjs +5 -4
- package/src/main/lib/scheduler/scheduleJobSchema.cjs +1 -0
- package/src/main/lib/scheduler/schedulerBatch.cjs +43 -5
- package/src/main/lib/scheduler/schedulerPaths.cjs +2 -0
- package/src/main/lib/scheduler/watchdogHelpers.cjs +114 -22
- package/src/main/lib/telemetry/mainHeapSnapshot.cjs +69 -0
- package/src/main/lib/telemetry/telemetryBoot.cjs +25 -3
- package/src/main/lib/telemetry/telemetryClient.cjs +12 -0
- package/src/main/lib/telemetry/telemetryCounters.cjs +25 -2
- package/src/main/pty.cjs +0 -53
- package/src/main/runVerify.cjs +38 -11
- package/src/main/scheduler/prdParser.cjs +3 -0
- package/src/main/scheduler/prdPaths.cjs +48 -2
- package/src/main/scheduler.cjs +135 -31
- package/src/main/seedDevPlugin.cjs +1 -1
- package/src/main/seedSchedulerMcp.cjs +1 -1
- package/src/main/templates/PRD_AUTHORING.md +8 -4
- package/src/main/webRemote.cjs +38 -132
- package/src/preload/api.d.ts +4 -52
- package/src/preload/index.cjs +0 -24
- package/src/seed/agents/dev-lead.md +2 -1
- package/src/seed/agents/validator.md +2 -1
- package/dist/assets/DataModel-DZHBZrfL.js +0 -1
- package/dist/assets/ListDetail-Cud72s-O.js +0 -1
- package/dist/assets/RemoteMachines-gOlFTvWq.js +0 -3
- package/dist/assets/Settings-DWnN2qxn.js +0 -4
- package/dist/assets/Skills-6pHn6glu.js +0 -2
- package/dist/assets/SystemPrompt-DT0LBH-K.js +0 -1
- package/dist/assets/TagLibrary-DbJ0zbYL.js +0 -1
- package/dist/assets/useRemotePeers-CNQmRBpt.js +0 -1
- package/src/main/lib/feedback-remote/relayClientAuth.cjs +0 -133
- package/src/main/remoteClient.cjs +0 -334
- package/src/main/remoteClientIpc.cjs +0 -133
package/src/main/pty.cjs
CHANGED
|
@@ -111,44 +111,6 @@ class PtyManager {
|
|
|
111
111
|
this.outBuffers = new Map();
|
|
112
112
|
this.flushTimers = new Map(); // tabId -> Timeout
|
|
113
113
|
this.window = null;
|
|
114
|
-
this.outputListeners = new Map(); // tabId -> Set<{onData,onExit}>
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* Observe a tab's coalesced output (the same string the renderer gets) and
|
|
119
|
-
* its exit from the main process. Returns an unsubscribe function.
|
|
120
|
-
* @param {string} tabId
|
|
121
|
-
* @param {(tabId: string, chunk: string) => void} onData
|
|
122
|
-
* @param {(tabId: string, info: {exitCode: number, signal?: number}) => void} [onExit]
|
|
123
|
-
*/
|
|
124
|
-
addOutputListener(tabId, onData, onExit) {
|
|
125
|
-
const entry = { onData, onExit };
|
|
126
|
-
let set = this.outputListeners.get(tabId);
|
|
127
|
-
if (!set) {
|
|
128
|
-
set = new Set();
|
|
129
|
-
this.outputListeners.set(tabId, set);
|
|
130
|
-
}
|
|
131
|
-
set.add(entry);
|
|
132
|
-
return () => {
|
|
133
|
-
const cur = this.outputListeners.get(tabId);
|
|
134
|
-
if (!cur) return;
|
|
135
|
-
cur.delete(entry);
|
|
136
|
-
if (cur.size === 0) this.outputListeners.delete(tabId);
|
|
137
|
-
};
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/** Fire every onExit listener for `tabId` once (errors isolated), then drop them. */
|
|
141
|
-
#notifyExit(tabId, info) {
|
|
142
|
-
const set = this.outputListeners.get(tabId);
|
|
143
|
-
this.outputListeners.delete(tabId);
|
|
144
|
-
if (!set) return;
|
|
145
|
-
for (const l of [...set]) {
|
|
146
|
-
try {
|
|
147
|
-
l.onExit?.(tabId, info);
|
|
148
|
-
} catch (err) {
|
|
149
|
-
console.warn('[pty] output listener onExit threw', err);
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
114
|
}
|
|
153
115
|
|
|
154
116
|
/** Send any pending buffered output for `tabId` now, and clear its timer. */
|
|
@@ -162,16 +124,6 @@ class PtyManager {
|
|
|
162
124
|
if (pending) {
|
|
163
125
|
this.outBuffers.delete(tabId);
|
|
164
126
|
sendIfAlive(this.window, `pty:data:${tabId}`, pending);
|
|
165
|
-
const set = this.outputListeners.get(tabId);
|
|
166
|
-
if (set) {
|
|
167
|
-
for (const l of [...set]) {
|
|
168
|
-
try {
|
|
169
|
-
l.onData?.(tabId, pending);
|
|
170
|
-
} catch (err) {
|
|
171
|
-
console.warn('[pty] output listener onData threw', err);
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
127
|
}
|
|
176
128
|
}
|
|
177
129
|
|
|
@@ -376,7 +328,6 @@ class PtyManager {
|
|
|
376
328
|
this.sessions.delete(tabId);
|
|
377
329
|
this.buffers.delete(tabId);
|
|
378
330
|
this.#dropOutput(tabId);
|
|
379
|
-
this.#notifyExit(tabId, { exitCode, signal });
|
|
380
331
|
return;
|
|
381
332
|
}
|
|
382
333
|
// Flush any still-buffered output BEFORE the exit event so the renderer
|
|
@@ -398,7 +349,6 @@ class PtyManager {
|
|
|
398
349
|
});
|
|
399
350
|
}
|
|
400
351
|
sendIfAlive(this.window, `pty:exit:${tabId}`, { exitCode, signal });
|
|
401
|
-
this.#notifyExit(tabId, { exitCode, signal });
|
|
402
352
|
this.sessions.delete(tabId);
|
|
403
353
|
this.buffers.delete(tabId);
|
|
404
354
|
});
|
|
@@ -461,9 +411,6 @@ class PtyManager {
|
|
|
461
411
|
this.sessions.delete(tabId);
|
|
462
412
|
this.buffers.delete(tabId);
|
|
463
413
|
this.#dropOutput(tabId);
|
|
464
|
-
// Listeners learn the tab is gone now; the suppressed exit event that
|
|
465
|
-
// follows finds none left, so each fires exactly once.
|
|
466
|
-
this.#notifyExit(tabId, { exitCode: 0, signal: undefined });
|
|
467
414
|
}
|
|
468
415
|
}
|
|
469
416
|
|
package/src/main/runVerify.cjs
CHANGED
|
@@ -21,7 +21,8 @@
|
|
|
21
21
|
*
|
|
22
22
|
* Downgrade policy:
|
|
23
23
|
* clean → null (caller stamps 'completed')
|
|
24
|
-
* halt → 'pending' (re-fires automatically next slot
|
|
24
|
+
* halt → 'pending' (re-fires automatically next slot; only for
|
|
25
|
+
* a run that printed no SCHEDULER_VERDICT line)
|
|
25
26
|
* deps_unmet → 'pending' (re-fires when deps clear)
|
|
26
27
|
* transcript_errors → historical rows only; no longer emitted
|
|
27
28
|
* verify_unavailable → 'needs_review' (unreadable log / verifier threw)
|
|
@@ -297,6 +298,30 @@ function scanSentinel(resultEvent, events) {
|
|
|
297
298
|
return null;
|
|
298
299
|
}
|
|
299
300
|
|
|
301
|
+
/**
|
|
302
|
+
* First line that starts at column 0 with the exact uppercase halt marker
|
|
303
|
+
* (`HALT:`) outside a fenced block, else null. Line-anchored and fence-aware
|
|
304
|
+
* because reports quote the marker in prose and paste tool output in fences,
|
|
305
|
+
* and PRD_AUTHORING.md §4/§9/§10 tell scripts to print it on failure — neither
|
|
306
|
+
* is the executor's own stop signal.
|
|
307
|
+
* @param {unknown} text
|
|
308
|
+
* @returns {string | null}
|
|
309
|
+
*/
|
|
310
|
+
function scanHaltLine(text) {
|
|
311
|
+
if (typeof text !== 'string') return null;
|
|
312
|
+
let inFence = false;
|
|
313
|
+
for (const raw of text.split('\n')) {
|
|
314
|
+
const line = raw.replace(/\r$/, '').trimEnd();
|
|
315
|
+
const t = line.trimStart();
|
|
316
|
+
if (t.startsWith('```') || t.startsWith('~~~')) {
|
|
317
|
+
inFence = !inFence;
|
|
318
|
+
continue;
|
|
319
|
+
}
|
|
320
|
+
if (!inFence && line.startsWith('HALT:')) return line;
|
|
321
|
+
}
|
|
322
|
+
return null;
|
|
323
|
+
}
|
|
324
|
+
|
|
300
325
|
/**
|
|
301
326
|
* One-line reason after `SCHEDULER_VERDICT: FAIL` (same two-source scan order
|
|
302
327
|
* as scanSentinel). Trimmed, capped at 300 chars; '' when absent.
|
|
@@ -742,13 +767,17 @@ async function verifyRun({
|
|
|
742
767
|
else if (commitEvidence) commitEvidenceSource = 'transcript';
|
|
743
768
|
}
|
|
744
769
|
|
|
745
|
-
// ── 3. HALT detection
|
|
746
|
-
//
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
770
|
+
// ── 3. HALT detection (fallback only) ─────────────────────────────────
|
|
771
|
+
// The SCHEDULER_VERDICT line is the executor's final say (FINISH_PROTOCOL
|
|
772
|
+
// VERDICT LINE step); the halt check is a fallback for runs that printed
|
|
773
|
+
// none. Incident: Rabbits-Game 163-attack-scorecard, 2026-10-24 — a PASS
|
|
774
|
+
// report quoting the marker in backticks was re-queued as a halt.
|
|
775
|
+
const sentinel = scanSentinel(resultEvent, events);
|
|
776
|
+
if (resultEvent && sentinel === null) {
|
|
777
|
+
const haltLine = scanHaltLine(resultEvent.resultText);
|
|
778
|
+
if (haltLine) {
|
|
779
|
+
const rt = resultEvent.resultText;
|
|
780
|
+
let reason = `Agent HALTed: ${haltLine.slice(0, 200)}`;
|
|
752
781
|
// Embed machine-parseable floor date if present in HALT message.
|
|
753
782
|
const dateMatch = rt.match(/~?(\d{4}-\d{2}-\d{2})/);
|
|
754
783
|
if (dateMatch) reason += ` (eligible from: ${dateMatch[1]})`;
|
|
@@ -773,9 +802,6 @@ async function verifyRun({
|
|
|
773
802
|
}
|
|
774
803
|
}
|
|
775
804
|
|
|
776
|
-
// Scan for the SCHEDULER_VERDICT sentinel emitted by the finish protocol.
|
|
777
|
-
const sentinel = scanSentinel(resultEvent, events);
|
|
778
|
-
|
|
779
805
|
// An explicit executor FAIL is always blocking — outranks every other
|
|
780
806
|
// verdict and every override below (early return). Transcript issues are
|
|
781
807
|
// kept as annotations so nothing is lost.
|
|
@@ -1022,6 +1048,7 @@ module.exports = {
|
|
|
1022
1048
|
checkDeps,
|
|
1023
1049
|
parseLog,
|
|
1024
1050
|
scanSentinel,
|
|
1051
|
+
scanHaltLine,
|
|
1025
1052
|
scanSentinelReason,
|
|
1026
1053
|
scanHumanQuestion,
|
|
1027
1054
|
scanForeignWipPathsClaim,
|
|
@@ -19,6 +19,7 @@ const os = require('node:os');
|
|
|
19
19
|
const path = require('node:path');
|
|
20
20
|
const { splitFrontmatter } = require('../lib/prd/prdFrontmatter.cjs');
|
|
21
21
|
const { deriveEpicIdFromPrdPath } = require('../lib/prd/prdLocations.cjs');
|
|
22
|
+
const { parseFilesSection } = require('../lib/prd/prdGateFiles.cjs');
|
|
22
23
|
const { reportDanglingAgentTypeOnce } = require('../lib/prd/prdAgentType.cjs');
|
|
23
24
|
|
|
24
25
|
/**
|
|
@@ -100,6 +101,8 @@ async function parsePrdRaw(filePath) {
|
|
|
100
101
|
// queue row is completed (a slug with no row is treated as already
|
|
101
102
|
// done/archived, matching retireCompletedSlugs semantics).
|
|
102
103
|
dependsOn: parseDependsOn(fm.dependsOn),
|
|
104
|
+
// Declared touch-list from the body's `# Files` section ([] when absent).
|
|
105
|
+
files: parseFilesSection(body),
|
|
103
106
|
// Provenance stamp (PRD-authoring lockdown): set only by prdCreate.cjs's
|
|
104
107
|
// buildPrdBody (create) or the update-prd route's legacy-adopt patch
|
|
105
108
|
// (migration/manual adopt). A PRD discovered on disk with no value here
|
|
@@ -16,6 +16,7 @@ const { DEFAULT_PROJECT_CWD } = require('../lib/scheduler/schedulerBatch.cjs');
|
|
|
16
16
|
const { resolvePrdsDirs, resolveArchivedPrdsDirs, resolvePrdWriteDir, listEpicPrdDirs, resolveEpicPrdWriteDir, isSafeEpicId, listArchivedPrdDirs, ancestorEpicPrdDirs, ancestorEpicArchivedPrdDirs } = require('../lib/prd/prdLocations.cjs');
|
|
17
17
|
const { migratePrds, consolidateFlatPrds, legacyAdoptExistingPrds } = require('../lib/prd/prdMigration.cjs');
|
|
18
18
|
const { opsPath } = require('../lib/opsOwnership.cjs');
|
|
19
|
+
const { bareSlug, resolveDepSlug } = require('../lib/prd/depSlugResolve.cjs');
|
|
19
20
|
const { allProjectCwds, projectRootOf } = require('../lib/activeSessions.cjs');
|
|
20
21
|
|
|
21
22
|
/**
|
|
@@ -268,6 +269,50 @@ async function safeSlugPath(slug) {
|
|
|
268
269
|
return module.exports.safeSlugPathIn(dir, slug);
|
|
269
270
|
}
|
|
270
271
|
|
|
272
|
+
/**
|
|
273
|
+
* Resolve a BARE slug (no `NN-` prefix) to the unique NN-prefixed PRD file —
|
|
274
|
+
* for a caller whose create response was lost and never learned the NN.
|
|
275
|
+
* Scans the live PRD dirs, the archive dirs, and one level of
|
|
276
|
+
* `prds-archived/<ts>/`, matching with depSlugResolve's rule. `cwd` narrows to
|
|
277
|
+
* one project; omitted, it searches every candidate dir. Returns
|
|
278
|
+
* `{ ok: true, path, dir }`, `{ ok: false, reason: 'not-found' }`, or
|
|
279
|
+
* `{ ok: false, reason: 'ambiguous', files, error }` (never guesses).
|
|
280
|
+
*/
|
|
281
|
+
async function resolveBareSlugFile(slug, cwd) {
|
|
282
|
+
if (typeof slug !== 'string' || !slug || bareSlug(slug) !== slug) return { ok: false, reason: 'not-found' };
|
|
283
|
+
const live = cwd ? [module.exports.prdDirForCwd(cwd), ...listEpicPrdDirs(cwd)] : module.exports.candidatePrdsDirs();
|
|
284
|
+
const archived = cwd ? listArchivedPrdDirs(cwd) : module.exports.candidateArchivedPrdsDirs();
|
|
285
|
+
const dirs = [...live];
|
|
286
|
+
for (const a of archived) {
|
|
287
|
+
dirs.push(a);
|
|
288
|
+
const subs = await fsp.readdir(a, { withFileTypes: true }).catch(() => []);
|
|
289
|
+
for (const ent of subs) if (ent.isDirectory()) dirs.push(path.join(a, ent.name));
|
|
290
|
+
}
|
|
291
|
+
const found = []; // { slug, dir, file }
|
|
292
|
+
const seen = new Set();
|
|
293
|
+
for (const dir of dirs) {
|
|
294
|
+
const names = await fsp.readdir(dir).catch(() => []);
|
|
295
|
+
for (const n of names) {
|
|
296
|
+
if (!n.endsWith('.md')) continue;
|
|
297
|
+
const file = path.join(dir, n);
|
|
298
|
+
if (seen.has(file)) continue;
|
|
299
|
+
seen.add(file);
|
|
300
|
+
found.push({ slug: n.slice(0, -3), dir, file });
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
const matched = new Set(resolveDepSlug(slug, found.map((f) => f.slug)));
|
|
304
|
+
const hits = found.filter((f) => matched.has(f.slug));
|
|
305
|
+
if (hits.length === 0) return { ok: false, reason: 'not-found' };
|
|
306
|
+
if (hits.length > 1) {
|
|
307
|
+
const files = hits.map((h) => h.file);
|
|
308
|
+
return { ok: false, reason: 'ambiguous', files, error: `ambiguous slug "${slug}": matches ${files.join(' and ')} — use the full NN-prefixed slug` };
|
|
309
|
+
}
|
|
310
|
+
const only = hits[0];
|
|
311
|
+
const safe = module.exports.safeSlugPathIn(only.dir, only.slug);
|
|
312
|
+
if (!safe) return { ok: false, reason: 'not-found' };
|
|
313
|
+
return { ok: true, path: safe, dir: only.dir };
|
|
314
|
+
}
|
|
315
|
+
|
|
271
316
|
/**
|
|
272
317
|
* The two distinct failure modes safeSlugPath collapses into one nullable
|
|
273
318
|
* return (the defect this fixes — see the PRD that added this helper's
|
|
@@ -291,10 +336,10 @@ async function resolveSlugOrReason(slug, cwd) {
|
|
|
291
336
|
return { ok: true, path: p };
|
|
292
337
|
} catch { /* not in this dir — try the next candidate */ }
|
|
293
338
|
}
|
|
294
|
-
return
|
|
339
|
+
return module.exports.resolveBareSlugFile(slug, cwd);
|
|
295
340
|
}
|
|
296
341
|
const dir = await module.exports.findPrdDir(slug);
|
|
297
|
-
if (!dir) return
|
|
342
|
+
if (!dir) return module.exports.resolveBareSlugFile(slug, cwd);
|
|
298
343
|
const p = module.exports.safeSlugPathIn(dir, slug);
|
|
299
344
|
if (!p) return { ok: false, reason: 'not-found' };
|
|
300
345
|
return { ok: true, path: p };
|
|
@@ -522,6 +567,7 @@ module.exports = {
|
|
|
522
567
|
safeSlugPathIn,
|
|
523
568
|
realPrdsDir,
|
|
524
569
|
safeSlugPath,
|
|
570
|
+
resolveBareSlugFile,
|
|
525
571
|
resolveSlugOrReason,
|
|
526
572
|
jobMatchesSlugAndCwd,
|
|
527
573
|
unknownSlugMessage,
|