opencode-swarm 7.87.1 → 7.87.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/cli/{evidence-summary-service-gg5m9z57.js → evidence-summary-service-5me91eq8.js} +1 -1
- package/dist/cli/{guardrail-explain-scym5r5y.js → guardrail-explain-2q9myk7c.js} +4 -4
- package/dist/cli/{index-s8bj492g.js → index-32axfg6h.js} +23 -7
- package/dist/cli/{index-89xjr3h4.js → index-8y7qetpg.js} +48 -19
- package/dist/cli/{index-ts2j1wjr.js → index-amwa268r.js} +1 -1
- package/dist/cli/{index-gwzpy671.js → index-kz1bmebr.js} +694 -322
- package/dist/cli/{index-dsjyfd3g.js → index-r3f47swm.js} +4 -4
- package/dist/cli/index.js +3 -3
- package/dist/cli/{skill-generator-3pvpk4y2.js → skill-generator-kz4q8e49.js} +3 -1
- package/dist/commands/close.d.ts +6 -0
- package/dist/git/branch.d.ts +5 -0
- package/dist/git/pr.d.ts +18 -0
- package/dist/hooks/knowledge-reader.d.ts +2 -0
- package/dist/hooks/knowledge-types.d.ts +3 -0
- package/dist/index.js +1281 -850
- package/dist/services/skill-generator.d.ts +10 -0
- package/dist/services/skill-improver.d.ts +25 -1
- package/dist/tools/checkpoint.d.ts +1 -0
- package/dist/utils/transient-retry.d.ts +30 -0
- package/package.json +1 -1
|
@@ -11,14 +11,16 @@ import {
|
|
|
11
11
|
quarantineEntry,
|
|
12
12
|
readKnowledgeCounterRollups,
|
|
13
13
|
readKnowledgeEvents,
|
|
14
|
+
regenerateSkill,
|
|
14
15
|
resolveKnowledgeEventsPath,
|
|
15
16
|
resolveUnactionablePath,
|
|
16
17
|
restoreEntry,
|
|
18
|
+
retireSkill,
|
|
17
19
|
selectCandidateEntries,
|
|
18
20
|
validateActionability,
|
|
19
21
|
validateActionableFields,
|
|
20
22
|
validateLesson
|
|
21
|
-
} from "./index-
|
|
23
|
+
} from "./index-32axfg6h.js";
|
|
22
24
|
import {
|
|
23
25
|
appendKnowledge,
|
|
24
26
|
appendRejectedLesson,
|
|
@@ -60,6 +62,7 @@ import {
|
|
|
60
62
|
stripKnownSwarmPrefix
|
|
61
63
|
} from "./index-q9h0wb04.js";
|
|
62
64
|
import {
|
|
65
|
+
MAX_TRANSIENT_RETRIES,
|
|
63
66
|
PlanSchema,
|
|
64
67
|
RetrospectiveEvidenceSchema,
|
|
65
68
|
appendLedgerEvent,
|
|
@@ -81,6 +84,7 @@ import {
|
|
|
81
84
|
isGlobalFile,
|
|
82
85
|
isProtectedPath,
|
|
83
86
|
isStateUnreadable,
|
|
87
|
+
isTransientSpawnError,
|
|
84
88
|
isValidEvidenceType,
|
|
85
89
|
listEvidenceTaskIds,
|
|
86
90
|
loadEpicSessionState,
|
|
@@ -97,9 +101,10 @@ import {
|
|
|
97
101
|
sanitizeTaskId,
|
|
98
102
|
saveEvidence,
|
|
99
103
|
savePlan,
|
|
104
|
+
transientBackoff,
|
|
100
105
|
validateProjectRoot,
|
|
101
106
|
writeProjectedSpecSync
|
|
102
|
-
} from "./index-
|
|
107
|
+
} from "./index-8y7qetpg.js";
|
|
103
108
|
import {
|
|
104
109
|
_internals as _internals2,
|
|
105
110
|
_internals1 as _internals3,
|
|
@@ -894,7 +899,7 @@ var init_executor = __esm(() => {
|
|
|
894
899
|
// package.json
|
|
895
900
|
var package_default = {
|
|
896
901
|
name: "opencode-swarm",
|
|
897
|
-
version: "7.87.
|
|
902
|
+
version: "7.87.3",
|
|
898
903
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
899
904
|
main: "dist/index.js",
|
|
900
905
|
types: "dist/index.d.ts",
|
|
@@ -5231,6 +5236,7 @@ function createSwarmTool(opts) {
|
|
|
5231
5236
|
var CHECKPOINT_LOG_PATH = ".swarm/checkpoints.json";
|
|
5232
5237
|
var MAX_LABEL_LENGTH = 100;
|
|
5233
5238
|
var GIT_TIMEOUT_MS = 30000;
|
|
5239
|
+
var GIT_MAX_BUFFER_BYTES = 5 * 1024 * 1024;
|
|
5234
5240
|
var SHELL_METACHARACTERS = /[;|&$`(){}<>!'"]/;
|
|
5235
5241
|
var SAFE_LABEL_PATTERN = /^[a-zA-Z0-9_ -]+$/;
|
|
5236
5242
|
var CONTROL_CHAR_PATTERN = /[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/;
|
|
@@ -5305,20 +5311,31 @@ function writeCheckpointLog(log2, directory) {
|
|
|
5305
5311
|
fs7.renameSync(tempPath, logPath);
|
|
5306
5312
|
}
|
|
5307
5313
|
function gitExec(args, cwd) {
|
|
5308
|
-
|
|
5309
|
-
|
|
5310
|
-
|
|
5311
|
-
|
|
5312
|
-
|
|
5313
|
-
|
|
5314
|
-
|
|
5315
|
-
|
|
5316
|
-
|
|
5317
|
-
|
|
5318
|
-
|
|
5314
|
+
for (let attempt = 0;attempt < MAX_TRANSIENT_RETRIES; attempt++) {
|
|
5315
|
+
const result = child_process.spawnSync("git", args, {
|
|
5316
|
+
cwd,
|
|
5317
|
+
encoding: "utf-8",
|
|
5318
|
+
timeout: GIT_TIMEOUT_MS,
|
|
5319
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
5320
|
+
windowsHide: true,
|
|
5321
|
+
maxBuffer: GIT_MAX_BUFFER_BYTES
|
|
5322
|
+
});
|
|
5323
|
+
if (result.error) {
|
|
5324
|
+
const code = result.error.code;
|
|
5325
|
+
const message = result.error.message ?? "";
|
|
5326
|
+
const isTransient = isTransientSpawnError(result.error) || /ETIMEDOUT|timed out/i.test(message);
|
|
5327
|
+
if (!isTransient || attempt >= MAX_TRANSIENT_RETRIES - 1) {
|
|
5328
|
+
throw new Error(`git failed to start: ${code ?? "unknown"} \u2014 ${message}`);
|
|
5329
|
+
}
|
|
5330
|
+
transientBackoff(attempt);
|
|
5331
|
+
continue;
|
|
5332
|
+
}
|
|
5333
|
+
if (result.status === 0) {
|
|
5334
|
+
return result.stdout ?? "";
|
|
5335
|
+
}
|
|
5319
5336
|
throw new Error(result.stderr?.trim() || `git exited with code ${result.status}`);
|
|
5320
5337
|
}
|
|
5321
|
-
|
|
5338
|
+
throw new Error("git command failed after transient retries");
|
|
5322
5339
|
}
|
|
5323
5340
|
function appendRetentionEvent(directory, event) {
|
|
5324
5341
|
try {
|
|
@@ -5335,9 +5352,20 @@ function getCurrentSha(directory) {
|
|
|
5335
5352
|
function isGitRepo2(directory) {
|
|
5336
5353
|
try {
|
|
5337
5354
|
gitExec(["rev-parse", "--git-dir"], directory);
|
|
5338
|
-
return true;
|
|
5339
|
-
} catch {
|
|
5340
|
-
|
|
5355
|
+
return { isRepo: true };
|
|
5356
|
+
} catch (e) {
|
|
5357
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
5358
|
+
const isTransient = /ETIMEDOUT|timed out/i.test(message) && !/not a git repository/i.test(message);
|
|
5359
|
+
if (isTransient) {
|
|
5360
|
+
return {
|
|
5361
|
+
isRepo: false,
|
|
5362
|
+
warning: "git probe failed after retry exhaustion \u2014 treating as not a git repository"
|
|
5363
|
+
};
|
|
5364
|
+
}
|
|
5365
|
+
return {
|
|
5366
|
+
isRepo: false,
|
|
5367
|
+
warning: "git probe failed \u2014 directory may not be a git repository"
|
|
5368
|
+
};
|
|
5341
5369
|
}
|
|
5342
5370
|
}
|
|
5343
5371
|
function handleSave(label, directory) {
|
|
@@ -5480,11 +5508,12 @@ var checkpoint = createSwarmTool({
|
|
|
5480
5508
|
label: exports_external.string().optional().describe("Checkpoint label (required for save, restore, delete)")
|
|
5481
5509
|
},
|
|
5482
5510
|
execute: async (args, directory) => {
|
|
5483
|
-
|
|
5511
|
+
const repoProbe = isGitRepo2(directory);
|
|
5512
|
+
if (!repoProbe.isRepo) {
|
|
5484
5513
|
return JSON.stringify({
|
|
5485
5514
|
action: "unknown",
|
|
5486
5515
|
success: false,
|
|
5487
|
-
error: "not a git repository"
|
|
5516
|
+
error: `${repoProbe.warning ?? "not a git repository"} \u2014 checkpoint tools require a git repository`
|
|
5488
5517
|
}, null, 2);
|
|
5489
5518
|
}
|
|
5490
5519
|
let action;
|
|
@@ -5673,6 +5702,7 @@ async function handleClarifyCommand(_directory, args) {
|
|
|
5673
5702
|
}
|
|
5674
5703
|
|
|
5675
5704
|
// src/commands/close.ts
|
|
5705
|
+
import { spawnSync as spawnSync5 } from "child_process";
|
|
5676
5706
|
import * as fsSync2 from "fs";
|
|
5677
5707
|
import { promises as fs11 } from "fs";
|
|
5678
5708
|
import path24 from "path";
|
|
@@ -6079,7 +6109,8 @@ async function runCuratorPostMortem(directory, options = {}) {
|
|
|
6079
6109
|
} catch {
|
|
6080
6110
|
warnings.push("Failed to load plan data.");
|
|
6081
6111
|
}
|
|
6082
|
-
const
|
|
6112
|
+
const effectivePlanId = planId === "unknown" ? `unknown-${Date.now()}` : planId;
|
|
6113
|
+
const reportFilename = `post-mortem-${effectivePlanId}.md`;
|
|
6083
6114
|
let reportPath;
|
|
6084
6115
|
try {
|
|
6085
6116
|
reportPath = validateSwarmPath(directory, reportFilename);
|
|
@@ -6095,22 +6126,22 @@ async function runCuratorPostMortem(directory, options = {}) {
|
|
|
6095
6126
|
if (!options.force && isReportValid(reportPath)) {
|
|
6096
6127
|
return {
|
|
6097
6128
|
success: true,
|
|
6098
|
-
planId,
|
|
6129
|
+
planId: effectivePlanId,
|
|
6099
6130
|
reportPath,
|
|
6100
6131
|
summary: "Post-mortem report already exists (idempotent skip).",
|
|
6101
6132
|
warnings
|
|
6102
6133
|
};
|
|
6103
6134
|
}
|
|
6104
|
-
const lock = await _internals13.acquirePostMortemLock(directory,
|
|
6135
|
+
const lock = await _internals13.acquirePostMortemLock(directory, effectivePlanId);
|
|
6105
6136
|
if (!lock.acquired) {
|
|
6106
6137
|
return {
|
|
6107
6138
|
success: false,
|
|
6108
|
-
planId,
|
|
6139
|
+
planId: effectivePlanId,
|
|
6109
6140
|
reportPath,
|
|
6110
6141
|
summary: null,
|
|
6111
6142
|
warnings: [
|
|
6112
6143
|
...warnings,
|
|
6113
|
-
`Concurrent post-mortem run in progress for plan ${
|
|
6144
|
+
`Concurrent post-mortem run in progress for plan ${effectivePlanId}; skipped.`
|
|
6114
6145
|
]
|
|
6115
6146
|
};
|
|
6116
6147
|
}
|
|
@@ -6160,7 +6191,7 @@ async function runCuratorPostMortem(directory, options = {}) {
|
|
|
6160
6191
|
if (options.llmDelegate) {
|
|
6161
6192
|
try {
|
|
6162
6193
|
const { CURATOR_POSTMORTEM_PROMPT: CURATOR_POSTMORTEM_PROMPT2 } = await import("./explorer-gz70sm9b.js");
|
|
6163
|
-
const userInput = assembleLLMInput(
|
|
6194
|
+
const userInput = assembleLLMInput(effectivePlanId, planSummary, knowledgeSummary, curatorDigest, proposals, unactionable, retrospectives, driftReports);
|
|
6164
6195
|
const ac = new AbortController;
|
|
6165
6196
|
const timer = setTimeout(() => ac.abort(), 300000);
|
|
6166
6197
|
let llmOutput;
|
|
@@ -6176,17 +6207,17 @@ async function runCuratorPostMortem(directory, options = {}) {
|
|
|
6176
6207
|
} finally {
|
|
6177
6208
|
clearTimeout(timer);
|
|
6178
6209
|
}
|
|
6179
|
-
reportContent = `# Post-Mortem Report: ${
|
|
6210
|
+
reportContent = `# Post-Mortem Report: ${effectivePlanId}
|
|
6180
6211
|
Generated: ${new Date().toISOString()}
|
|
6181
6212
|
|
|
6182
6213
|
${llmOutput}`;
|
|
6183
6214
|
} catch (err) {
|
|
6184
6215
|
const msg = err instanceof Error ? err.message : String(err);
|
|
6185
6216
|
warnings.push(`LLM delegate failed, falling back to data-only report: ${msg}`);
|
|
6186
|
-
reportContent = _internals13.buildDataOnlyReport(
|
|
6217
|
+
reportContent = _internals13.buildDataOnlyReport(effectivePlanId, planSummary, knowledgeSummary, curatorDigest, proposals, unactionable, retrospectives, driftReports);
|
|
6187
6218
|
}
|
|
6188
6219
|
} else {
|
|
6189
|
-
reportContent = _internals13.buildDataOnlyReport(
|
|
6220
|
+
reportContent = _internals13.buildDataOnlyReport(effectivePlanId, planSummary, knowledgeSummary, curatorDigest, proposals, unactionable, retrospectives, driftReports);
|
|
6190
6221
|
}
|
|
6191
6222
|
try {
|
|
6192
6223
|
const { mkdirSync: mkdirSync6 } = await import("fs");
|
|
@@ -6196,7 +6227,7 @@ ${llmOutput}`;
|
|
|
6196
6227
|
const msg = err instanceof Error ? err.message : String(err);
|
|
6197
6228
|
return {
|
|
6198
6229
|
success: false,
|
|
6199
|
-
planId,
|
|
6230
|
+
planId: effectivePlanId,
|
|
6200
6231
|
reportPath: null,
|
|
6201
6232
|
summary: null,
|
|
6202
6233
|
warnings: [...warnings, `Failed to write report: ${msg}`]
|
|
@@ -6206,13 +6237,13 @@ ${llmOutput}`;
|
|
|
6206
6237
|
const neverAppliedCount = knowledgeSummary.filter((e) => e.applied === 0 && e.violated === 0 && e.ignored === 0).length;
|
|
6207
6238
|
const totalViolations = knowledgeSummary.reduce((s, e) => s + e.violated, 0);
|
|
6208
6239
|
const summary = [
|
|
6209
|
-
`Post-mortem for plan "${
|
|
6240
|
+
`Post-mortem for plan "${effectivePlanId}": ${totalEntries} knowledge entries reviewed.`,
|
|
6210
6241
|
`${neverAppliedCount} never-applied entries flagged; ${totalViolations} total violations recorded.`,
|
|
6211
6242
|
`${proposals.length} pending proposals, ${unactionable.length} quarantined entries.`
|
|
6212
6243
|
].join(" ");
|
|
6213
6244
|
return {
|
|
6214
6245
|
success: true,
|
|
6215
|
-
planId,
|
|
6246
|
+
planId: effectivePlanId,
|
|
6216
6247
|
reportPath,
|
|
6217
6248
|
summary,
|
|
6218
6249
|
warnings
|
|
@@ -9900,6 +9931,9 @@ ${userInput}` : userInput;
|
|
|
9900
9931
|
};
|
|
9901
9932
|
}
|
|
9902
9933
|
|
|
9934
|
+
// src/services/skill-improver.ts
|
|
9935
|
+
init_logger();
|
|
9936
|
+
|
|
9903
9937
|
// src/services/trajectory-cluster.ts
|
|
9904
9938
|
import { mkdir as mkdir6, writeFile as writeFile6 } from "fs/promises";
|
|
9905
9939
|
import * as path22 from "path";
|
|
@@ -10328,7 +10362,14 @@ async function gatherInventory(directory) {
|
|
|
10328
10362
|
continue;
|
|
10329
10363
|
}
|
|
10330
10364
|
const fm = parseDraftFrontmatter(content);
|
|
10331
|
-
if (!fm)
|
|
10365
|
+
if (!fm) {
|
|
10366
|
+
staleActiveSkills.push({
|
|
10367
|
+
slug: skill.slug,
|
|
10368
|
+
reasons: ["unparseable_frontmatter"]
|
|
10369
|
+
});
|
|
10370
|
+
continue;
|
|
10371
|
+
}
|
|
10372
|
+
if (fm.skillOrigin === "shim")
|
|
10332
10373
|
continue;
|
|
10333
10374
|
metadataReadable += 1;
|
|
10334
10375
|
const reasons = [];
|
|
@@ -10476,6 +10517,59 @@ function buildLLMProposalFrame(args) {
|
|
|
10476
10517
|
return lines.join(`
|
|
10477
10518
|
`);
|
|
10478
10519
|
}
|
|
10520
|
+
async function reconcileStaleActiveSkills(directory, options = {}) {
|
|
10521
|
+
const result = {
|
|
10522
|
+
regenerated: [],
|
|
10523
|
+
retired: [],
|
|
10524
|
+
skipped: [],
|
|
10525
|
+
checked: 0
|
|
10526
|
+
};
|
|
10527
|
+
let skills;
|
|
10528
|
+
try {
|
|
10529
|
+
skills = await listSkills(directory);
|
|
10530
|
+
} catch {
|
|
10531
|
+
return result;
|
|
10532
|
+
}
|
|
10533
|
+
for (const skill of skills.active) {
|
|
10534
|
+
let content;
|
|
10535
|
+
try {
|
|
10536
|
+
content = await readFile7(skill.path, "utf-8");
|
|
10537
|
+
} catch {
|
|
10538
|
+
continue;
|
|
10539
|
+
}
|
|
10540
|
+
const fm = parseDraftFrontmatter(content);
|
|
10541
|
+
if (fm?.skillOrigin === "shim") {
|
|
10542
|
+
result.skipped.push(skill.slug);
|
|
10543
|
+
continue;
|
|
10544
|
+
}
|
|
10545
|
+
const stale = !fm || fm.sourceKnowledgeIds.length === 0 || !fm.generatedAt;
|
|
10546
|
+
if (!stale)
|
|
10547
|
+
continue;
|
|
10548
|
+
result.checked += 1;
|
|
10549
|
+
if (options.dryRun) {
|
|
10550
|
+
result.retired.push(skill.slug);
|
|
10551
|
+
continue;
|
|
10552
|
+
}
|
|
10553
|
+
try {
|
|
10554
|
+
const regen = await _internals18.regenerateSkill(directory, skill.slug, {
|
|
10555
|
+
evaluate: false
|
|
10556
|
+
});
|
|
10557
|
+
if (regen.regenerated) {
|
|
10558
|
+
result.regenerated.push(skill.slug);
|
|
10559
|
+
} else if (regen.retired) {
|
|
10560
|
+
result.retired.push(skill.slug);
|
|
10561
|
+
} else {
|
|
10562
|
+
const retire = await retireSkill(directory, skill.slug, "stale_no_source_knowledge");
|
|
10563
|
+
if (retire.retired)
|
|
10564
|
+
result.retired.push(skill.slug);
|
|
10565
|
+
}
|
|
10566
|
+
} catch (err) {
|
|
10567
|
+
warn(`[skill-improver] reconcileStaleActiveSkills: failed to reconcile '${skill.slug}': ${err instanceof Error ? err.message : String(err)}`);
|
|
10568
|
+
result.skipped.push(skill.slug);
|
|
10569
|
+
}
|
|
10570
|
+
}
|
|
10571
|
+
return result;
|
|
10572
|
+
}
|
|
10479
10573
|
async function runSkillImprover(req) {
|
|
10480
10574
|
const cfg = req.config;
|
|
10481
10575
|
const now = req.now ?? new Date;
|
|
@@ -10682,6 +10776,7 @@ async function runSkillImprover(req) {
|
|
|
10682
10776
|
motifs: successMotifResult.motifs,
|
|
10683
10777
|
proposalsWritten: successMotifResult.proposalsWritten.length
|
|
10684
10778
|
};
|
|
10779
|
+
const staleSkillReconciliation = await reconcileStaleActiveSkills(req.directory, { dryRun: writeMode !== "draft_skills" });
|
|
10685
10780
|
let autoApply;
|
|
10686
10781
|
if (req.allowAutoApply !== false && delegate && req.sessionId && hasActiveFullAuto(req.sessionId)) {
|
|
10687
10782
|
try {
|
|
@@ -10702,9 +10797,20 @@ async function runSkillImprover(req) {
|
|
|
10702
10797
|
unactionableHardening,
|
|
10703
10798
|
macroMotifs,
|
|
10704
10799
|
successMotifs,
|
|
10800
|
+
staleSkillReconciliation,
|
|
10705
10801
|
autoApply
|
|
10706
10802
|
};
|
|
10707
10803
|
}
|
|
10804
|
+
var _internals18 = {
|
|
10805
|
+
runSkillImprover,
|
|
10806
|
+
buildDeterministicProposal,
|
|
10807
|
+
buildLLMProposalFrame,
|
|
10808
|
+
buildSystemPrompt,
|
|
10809
|
+
buildUserPrompt,
|
|
10810
|
+
gatherInventory,
|
|
10811
|
+
reconcileStaleActiveSkills,
|
|
10812
|
+
regenerateSkill
|
|
10813
|
+
};
|
|
10708
10814
|
|
|
10709
10815
|
// src/tools/write-retro.ts
|
|
10710
10816
|
async function executeWriteRetro(args, directory) {
|
|
@@ -11048,13 +11154,13 @@ var write_retro = createSwarmTool({
|
|
|
11048
11154
|
task_id: args.task_id !== undefined ? String(args.task_id) : undefined,
|
|
11049
11155
|
metadata: args.metadata
|
|
11050
11156
|
};
|
|
11051
|
-
return await
|
|
11157
|
+
return await _internals19.executeWriteRetro(writeRetroArgs, directory);
|
|
11052
11158
|
} catch {
|
|
11053
11159
|
return JSON.stringify({ success: false, phase: rawPhase, message: "Invalid arguments" }, null, 2);
|
|
11054
11160
|
}
|
|
11055
11161
|
}
|
|
11056
11162
|
});
|
|
11057
|
-
var
|
|
11163
|
+
var _internals19 = {
|
|
11058
11164
|
executeWriteRetro,
|
|
11059
11165
|
write_retro
|
|
11060
11166
|
};
|
|
@@ -11097,8 +11203,9 @@ function countSessionKnowledgeEntries(entries, sessionStart, fallbackCount) {
|
|
|
11097
11203
|
return Number.isFinite(createdAtMs) && createdAtMs >= sessionStartMs;
|
|
11098
11204
|
}).length;
|
|
11099
11205
|
}
|
|
11100
|
-
async function
|
|
11206
|
+
async function copyDirRecursiveWithFailures(src, dest) {
|
|
11101
11207
|
let count = 0;
|
|
11208
|
+
const failures = [];
|
|
11102
11209
|
const entries = await fs11.readdir(src);
|
|
11103
11210
|
await fs11.mkdir(dest, { recursive: true });
|
|
11104
11211
|
for (const entry of entries) {
|
|
@@ -11107,17 +11214,32 @@ async function copyDirRecursive(src, dest) {
|
|
|
11107
11214
|
try {
|
|
11108
11215
|
const stat4 = await fs11.stat(srcEntry);
|
|
11109
11216
|
if (stat4.isDirectory()) {
|
|
11110
|
-
const
|
|
11111
|
-
count +=
|
|
11217
|
+
const subResult = await copyDirRecursiveWithFailures(srcEntry, destEntry);
|
|
11218
|
+
count += subResult.copied;
|
|
11219
|
+
failures.push(...subResult.failures);
|
|
11112
11220
|
} else {
|
|
11113
11221
|
try {
|
|
11114
11222
|
await fs11.copyFile(srcEntry, destEntry);
|
|
11115
11223
|
count++;
|
|
11116
|
-
} catch {
|
|
11224
|
+
} catch (err) {
|
|
11225
|
+
const errno = err?.code;
|
|
11226
|
+
if (errno !== "ENOENT") {
|
|
11227
|
+
failures.push(`${srcEntry}: ${err instanceof Error ? err.message : String(err)}`);
|
|
11228
|
+
}
|
|
11229
|
+
}
|
|
11117
11230
|
}
|
|
11118
|
-
} catch {
|
|
11231
|
+
} catch (err) {
|
|
11232
|
+
const errno = err?.code;
|
|
11233
|
+
if (errno !== "ENOENT") {
|
|
11234
|
+
failures.push(`${srcEntry}: ${err instanceof Error ? err.message : String(err)}`);
|
|
11235
|
+
}
|
|
11236
|
+
}
|
|
11119
11237
|
}
|
|
11120
|
-
return count;
|
|
11238
|
+
return { copied: count, failures };
|
|
11239
|
+
}
|
|
11240
|
+
async function copyDirRecursive(src, dest) {
|
|
11241
|
+
const result = await copyDirRecursiveWithFailures(src, dest);
|
|
11242
|
+
return result.copied;
|
|
11121
11243
|
}
|
|
11122
11244
|
var ARCHIVE_ARTIFACTS = [
|
|
11123
11245
|
"plan.json",
|
|
@@ -11309,8 +11431,8 @@ async function runFinalizeStage(ctx) {
|
|
|
11309
11431
|
];
|
|
11310
11432
|
ctx.curationSucceeded = false;
|
|
11311
11433
|
try {
|
|
11312
|
-
ctx.curationResult = await
|
|
11313
|
-
llmDelegate:
|
|
11434
|
+
ctx.curationResult = await _internals20.curateAndStoreSwarm(ctx.allLessons, ctx.projectName, { phase_number: 0 }, ctx.directory, ctx.config, {
|
|
11435
|
+
llmDelegate: _internals20.createCuratorLLMDelegate(ctx.directory, "phase", ctx.options.sessionID),
|
|
11314
11436
|
enrichmentQuota: {
|
|
11315
11437
|
maxCalls: ctx.config.enrichment.max_calls_per_day,
|
|
11316
11438
|
window: ctx.config.enrichment.quota_window
|
|
@@ -11329,7 +11451,7 @@ async function runFinalizeStage(ctx) {
|
|
|
11329
11451
|
if (ctx.config.hive_enabled === false) {} else {
|
|
11330
11452
|
try {
|
|
11331
11453
|
const entries = await readKnowledge(resolveSwarmKnowledgePath(ctx.directory));
|
|
11332
|
-
const result = await
|
|
11454
|
+
const result = await _internals20.checkHivePromotions(entries, ctx.config);
|
|
11333
11455
|
ctx.hivePromoted = result.new_promotions;
|
|
11334
11456
|
} catch (hiveErr) {
|
|
11335
11457
|
const msg = hiveErr instanceof Error ? hiveErr.message : String(hiveErr);
|
|
@@ -11350,7 +11472,7 @@ async function runFinalizeStage(ctx) {
|
|
|
11350
11472
|
ctx.knowledgeSkillHint = ctx.sessionKnowledgeCreated > 0 ? `${ctx.sessionKnowledgeCreated} knowledge entries created this session. Consider running skill_improve or skill_generate to compile mature entries into skills.` : "";
|
|
11351
11473
|
if (ctx.runSkillReview) {
|
|
11352
11474
|
try {
|
|
11353
|
-
const { config: loadedConfig } =
|
|
11475
|
+
const { config: loadedConfig } = _internals20.loadPluginConfigWithMeta(ctx.directory);
|
|
11354
11476
|
const skillImproverConfig = SkillImproverConfigSchema.parse(loadedConfig.skill_improver ?? {});
|
|
11355
11477
|
const skillReviewResult = await runAbortableSkillReview({
|
|
11356
11478
|
directory: ctx.directory,
|
|
@@ -11401,7 +11523,7 @@ async function runFinalizeStage(ctx) {
|
|
|
11401
11523
|
}
|
|
11402
11524
|
if (!ctx.planAlreadyDone || ctx.guaranteeResult.closedPhaseIds.length > 0 || ctx.guaranteeResult.closedTaskIds.length > 0) {
|
|
11403
11525
|
try {
|
|
11404
|
-
await
|
|
11526
|
+
await _internals20.closePlanTerminalState(ctx.directory, ctx.planData, {
|
|
11405
11527
|
closedPhaseIds: ctx.guaranteeResult.closedPhaseIds,
|
|
11406
11528
|
closedTaskIds: ctx.guaranteeResult.closedTaskIds,
|
|
11407
11529
|
originalStatuses: ctx.originalStatuses
|
|
@@ -11418,11 +11540,11 @@ async function runFinalizeStage(ctx) {
|
|
|
11418
11540
|
}
|
|
11419
11541
|
try {
|
|
11420
11542
|
const { CuratorConfigSchema: CCS } = await import("./schema-84146tvk.js");
|
|
11421
|
-
const { config: pmLoadedConfig } =
|
|
11543
|
+
const { config: pmLoadedConfig } = _internals20.loadPluginConfigWithMeta(ctx.directory);
|
|
11422
11544
|
const curatorCfg = CCS.parse(pmLoadedConfig.curator ?? {});
|
|
11423
11545
|
if (curatorCfg.enabled && curatorCfg.postmortem_enabled) {
|
|
11424
|
-
const pmResult = await
|
|
11425
|
-
llmDelegate:
|
|
11546
|
+
const pmResult = await _internals20.runCuratorPostMortem(ctx.directory, {
|
|
11547
|
+
llmDelegate: _internals20.createCuratorLLMDelegate(ctx.directory, "postmortem", ctx.options.sessionID)
|
|
11426
11548
|
});
|
|
11427
11549
|
if (pmResult.success && pmResult.summary) {
|
|
11428
11550
|
ctx.postMortemSummary = pmResult.summary;
|
|
@@ -11436,31 +11558,145 @@ async function runFinalizeStage(ctx) {
|
|
|
11436
11558
|
ctx.warnings.push(`Post-mortem failed: ${msg}`);
|
|
11437
11559
|
}
|
|
11438
11560
|
}
|
|
11561
|
+
async function copySqliteSafe(srcPath, destPath) {
|
|
11562
|
+
if (!fsSync2.existsSync(srcPath)) {
|
|
11563
|
+
return {
|
|
11564
|
+
success: true,
|
|
11565
|
+
skipped: true,
|
|
11566
|
+
reason: "source does not exist (ENOENT)"
|
|
11567
|
+
};
|
|
11568
|
+
}
|
|
11569
|
+
let checkpointVerified = false;
|
|
11570
|
+
try {
|
|
11571
|
+
const result = spawnSync5("sqlite3", [srcPath, "PRAGMA wal_checkpoint(TRUNCATE);"], {
|
|
11572
|
+
cwd: path24.dirname(srcPath),
|
|
11573
|
+
encoding: "utf-8",
|
|
11574
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
11575
|
+
timeout: 1e4,
|
|
11576
|
+
windowsHide: true,
|
|
11577
|
+
maxBuffer: 1024
|
|
11578
|
+
});
|
|
11579
|
+
if (result.error) {
|
|
11580
|
+
const code = result.error.code;
|
|
11581
|
+
if (code === "ENOENT") {
|
|
11582
|
+
try {
|
|
11583
|
+
await fs11.copyFile(srcPath, destPath);
|
|
11584
|
+
return {
|
|
11585
|
+
success: true,
|
|
11586
|
+
reason: "copied without WAL checkpoint (sqlite3 CLI unavailable)"
|
|
11587
|
+
};
|
|
11588
|
+
} catch (copyErr) {
|
|
11589
|
+
return {
|
|
11590
|
+
success: false,
|
|
11591
|
+
reason: `fallback copy failed: ${copyErr instanceof Error ? copyErr.message : String(copyErr)}`
|
|
11592
|
+
};
|
|
11593
|
+
}
|
|
11594
|
+
}
|
|
11595
|
+
return {
|
|
11596
|
+
success: false,
|
|
11597
|
+
reason: `wal_checkpoint failed: ${result.error instanceof Error ? result.error.message : String(result.error)}`
|
|
11598
|
+
};
|
|
11599
|
+
}
|
|
11600
|
+
if (result.status !== 0) {
|
|
11601
|
+
return {
|
|
11602
|
+
success: false,
|
|
11603
|
+
reason: `wal_checkpoint exited with code ${result.status}`
|
|
11604
|
+
};
|
|
11605
|
+
}
|
|
11606
|
+
const output = (result.stdout || "").trim();
|
|
11607
|
+
const lines = output.split(`
|
|
11608
|
+
`).filter((l) => l.trim());
|
|
11609
|
+
if (lines.length >= 1) {
|
|
11610
|
+
const dataLine = lines[0];
|
|
11611
|
+
const columns = dataLine.split("|");
|
|
11612
|
+
const busyFlag = parseInt(columns[0], 10);
|
|
11613
|
+
checkpointVerified = !Number.isNaN(busyFlag) && busyFlag === 0;
|
|
11614
|
+
}
|
|
11615
|
+
} catch (err) {
|
|
11616
|
+
return {
|
|
11617
|
+
success: false,
|
|
11618
|
+
reason: `wal_checkpoint error: ${err instanceof Error ? err.message : String(err)}`
|
|
11619
|
+
};
|
|
11620
|
+
}
|
|
11621
|
+
try {
|
|
11622
|
+
await fs11.copyFile(srcPath, destPath);
|
|
11623
|
+
if (checkpointVerified) {
|
|
11624
|
+
return { success: true };
|
|
11625
|
+
}
|
|
11626
|
+
return {
|
|
11627
|
+
success: true,
|
|
11628
|
+
reason: "WAL checkpoint incomplete (busy) \u2014 archive copy may be stale, original preserved"
|
|
11629
|
+
};
|
|
11630
|
+
} catch (err) {
|
|
11631
|
+
return {
|
|
11632
|
+
success: false,
|
|
11633
|
+
reason: `copy failed: ${err instanceof Error ? err.message : String(err)}`
|
|
11634
|
+
};
|
|
11635
|
+
}
|
|
11636
|
+
}
|
|
11439
11637
|
async function runArchiveStage(ctx) {
|
|
11440
11638
|
ctx.timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
11441
11639
|
ctx.archiveSuffix = Math.random().toString(36).slice(2, 8);
|
|
11442
11640
|
ctx.archiveDir = path24.join(ctx.swarmDir, "archive", `swarm-${ctx.timestamp}-${ctx.archiveSuffix}`);
|
|
11443
11641
|
try {
|
|
11444
11642
|
await fs11.mkdir(ctx.archiveDir, { recursive: true });
|
|
11643
|
+
const WAL_SIDECAR_FILES = new Set(["swarm.db-shm", "swarm.db-wal"]);
|
|
11445
11644
|
for (const artifact of ARCHIVE_ARTIFACTS) {
|
|
11645
|
+
if (WAL_SIDECAR_FILES.has(artifact)) {
|
|
11646
|
+
continue;
|
|
11647
|
+
}
|
|
11446
11648
|
const srcPath = path24.join(ctx.swarmDir, artifact);
|
|
11447
11649
|
const destPath = path24.join(ctx.archiveDir, artifact);
|
|
11448
|
-
|
|
11449
|
-
await
|
|
11450
|
-
|
|
11451
|
-
|
|
11452
|
-
|
|
11650
|
+
if (artifact === "swarm.db") {
|
|
11651
|
+
const result = await copySqliteSafe(srcPath, destPath);
|
|
11652
|
+
if (result.skipped) {} else if (result.success) {
|
|
11653
|
+
ctx.archivedFileCount++;
|
|
11654
|
+
if (result.reason) {
|
|
11655
|
+
ctx.warnings.push(`Archived ${artifact}: ${result.reason}. Original preserved to prevent data loss.`);
|
|
11656
|
+
} else {
|
|
11657
|
+
ctx.archivedActiveStateFiles.add(artifact);
|
|
11658
|
+
}
|
|
11659
|
+
} else {
|
|
11660
|
+
ctx.archiveFailureReasons.set(artifact, result.reason);
|
|
11661
|
+
ctx.warnings.push(`Failed to archive ${artifact}: ${result.reason}. File preserved (not cleaned up).`);
|
|
11453
11662
|
}
|
|
11454
|
-
}
|
|
11663
|
+
} else {
|
|
11664
|
+
try {
|
|
11665
|
+
await fs11.copyFile(srcPath, destPath);
|
|
11666
|
+
ctx.archivedFileCount++;
|
|
11667
|
+
if (ACTIVE_STATE_TO_CLEAN.includes(artifact)) {
|
|
11668
|
+
ctx.archivedActiveStateFiles.add(artifact);
|
|
11669
|
+
}
|
|
11670
|
+
} catch (err) {
|
|
11671
|
+
const errno = err?.code;
|
|
11672
|
+
if (errno === "ENOENT") {} else {
|
|
11673
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
11674
|
+
ctx.archiveFailureReasons.set(artifact, `${errno ?? "unknown"}: ${reason}`);
|
|
11675
|
+
ctx.warnings.push(`Failed to archive ${artifact} [${errno ?? "unknown"}]: ${reason}. File preserved (not cleaned up).`);
|
|
11676
|
+
}
|
|
11677
|
+
}
|
|
11678
|
+
}
|
|
11455
11679
|
}
|
|
11456
11680
|
for (const dirName of ACTIVE_STATE_DIRS_TO_CLEAN) {
|
|
11457
11681
|
const srcDir = path24.join(ctx.swarmDir, dirName);
|
|
11458
11682
|
const destDir = path24.join(ctx.archiveDir, dirName);
|
|
11459
11683
|
try {
|
|
11460
|
-
const
|
|
11461
|
-
ctx.archivedFileCount += copied;
|
|
11462
|
-
|
|
11463
|
-
|
|
11684
|
+
const result = await copyDirRecursiveWithFailures(srcDir, destDir);
|
|
11685
|
+
ctx.archivedFileCount += result.copied;
|
|
11686
|
+
if (result.failures.length === 0) {
|
|
11687
|
+
ctx.archivedActiveStateDirs.add(dirName);
|
|
11688
|
+
} else {
|
|
11689
|
+
ctx.warnings.push(`Directory ${dirName} not fully archived (${result.failures.length} failure(s)). Source preserved.`);
|
|
11690
|
+
for (const failure of result.failures) {
|
|
11691
|
+
ctx.warnings.push(` - ${failure}`);
|
|
11692
|
+
}
|
|
11693
|
+
}
|
|
11694
|
+
} catch (err) {
|
|
11695
|
+
const code = err.code;
|
|
11696
|
+
if (code !== "ENOENT") {
|
|
11697
|
+
ctx.warnings.push(`Failed to archive directory ${dirName} [${code ?? "unknown"}]: ${err.message}. Source preserved.`);
|
|
11698
|
+
}
|
|
11699
|
+
}
|
|
11464
11700
|
}
|
|
11465
11701
|
ctx.archiveResult = `Archived ${ctx.archivedFileCount} artifact(s) to .swarm/archive/swarm-${ctx.timestamp}-${ctx.archiveSuffix}/`;
|
|
11466
11702
|
} catch (archiveError) {
|
|
@@ -11478,7 +11714,7 @@ async function runArchiveEvidenceRetention(ctx) {
|
|
|
11478
11714
|
let maxAgeDays = 30;
|
|
11479
11715
|
let maxBundles = 10;
|
|
11480
11716
|
try {
|
|
11481
|
-
const { config: evidenceLoadedConfig } =
|
|
11717
|
+
const { config: evidenceLoadedConfig } = _internals20.loadPluginConfigWithMeta(ctx.directory);
|
|
11482
11718
|
const evidenceCfg = evidenceLoadedConfig.evidence ?? {};
|
|
11483
11719
|
if (typeof evidenceCfg.max_age_days === "number") {
|
|
11484
11720
|
maxAgeDays = evidenceCfg.max_age_days;
|
|
@@ -11488,7 +11724,7 @@ async function runArchiveEvidenceRetention(ctx) {
|
|
|
11488
11724
|
}
|
|
11489
11725
|
} catch {}
|
|
11490
11726
|
try {
|
|
11491
|
-
await
|
|
11727
|
+
await _internals20.archiveEvidence(ctx.directory, maxAgeDays, maxBundles);
|
|
11492
11728
|
} catch (error2) {
|
|
11493
11729
|
const msg = error2 instanceof Error ? error2.message : String(error2);
|
|
11494
11730
|
ctx.warnings.push(`Evidence retention archive failed: ${msg}`);
|
|
@@ -11501,14 +11737,21 @@ async function runCleanStage(ctx) {
|
|
|
11501
11737
|
if (ctx.archivedActiveStateFiles.size > 0) {
|
|
11502
11738
|
for (const artifact of ACTIVE_STATE_TO_CLEAN) {
|
|
11503
11739
|
if (!ctx.archivedActiveStateFiles.has(artifact)) {
|
|
11504
|
-
ctx.
|
|
11740
|
+
const reason = ctx.archiveFailureReasons?.get(artifact);
|
|
11741
|
+
ctx.warnings.push(reason ? `Preserved ${artifact} because it was not successfully archived: ${reason}.` : `Preserved ${artifact} because it was not successfully archived.`);
|
|
11505
11742
|
continue;
|
|
11506
11743
|
}
|
|
11507
11744
|
const filePath = path24.join(ctx.swarmDir, artifact);
|
|
11508
11745
|
try {
|
|
11509
11746
|
await fs11.unlink(filePath);
|
|
11510
11747
|
cleanedFiles.push(artifact);
|
|
11511
|
-
} catch {
|
|
11748
|
+
} catch (err) {
|
|
11749
|
+
const errno = err?.code;
|
|
11750
|
+
if (errno === "ENOENT") {} else {
|
|
11751
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
11752
|
+
ctx.warnings.push(`Failed to clean active-state file ${artifact} [${errno ?? "unknown"}]: ${reason}`);
|
|
11753
|
+
}
|
|
11754
|
+
}
|
|
11512
11755
|
}
|
|
11513
11756
|
} else {
|
|
11514
11757
|
ctx.warnings.push("Skipped active-state cleanup because no active-state files were archived. Files preserved to prevent data loss.");
|
|
@@ -11530,15 +11773,33 @@ async function runCleanStage(ctx) {
|
|
|
11530
11773
|
try {
|
|
11531
11774
|
await fs11.unlink(path24.join(ctx.swarmDir, backup));
|
|
11532
11775
|
configBackupsRemoved++;
|
|
11533
|
-
} catch {
|
|
11776
|
+
} catch (err) {
|
|
11777
|
+
const errno = err?.code;
|
|
11778
|
+
if (errno === "ENOENT") {} else {
|
|
11779
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
11780
|
+
ctx.warnings.push(`Failed to clean config-backup ${backup} [${errno ?? "unknown"}]: ${reason}`);
|
|
11781
|
+
}
|
|
11782
|
+
}
|
|
11534
11783
|
}
|
|
11535
11784
|
const ledgerSiblings = swarmFiles.filter((f) => (f.startsWith("plan-ledger.archived-") || f.startsWith("plan-ledger.backup-")) && f.endsWith(".jsonl"));
|
|
11536
11785
|
for (const sibling of ledgerSiblings) {
|
|
11537
11786
|
try {
|
|
11538
11787
|
await fs11.unlink(path24.join(ctx.swarmDir, sibling));
|
|
11539
|
-
} catch {
|
|
11788
|
+
} catch (err) {
|
|
11789
|
+
const errno = err?.code;
|
|
11790
|
+
if (errno === "ENOENT") {} else {
|
|
11791
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
11792
|
+
ctx.warnings.push(`Failed to clean ledger sibling ${sibling} [${errno ?? "unknown"}]: ${reason}`);
|
|
11793
|
+
}
|
|
11794
|
+
}
|
|
11540
11795
|
}
|
|
11541
|
-
} catch {
|
|
11796
|
+
} catch (err) {
|
|
11797
|
+
const errno = err?.code;
|
|
11798
|
+
if (errno === "ENOENT") {} else {
|
|
11799
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
11800
|
+
ctx.warnings.push(`Failed to read ${ctx.swarmDir} for stale-file cleanup [${errno ?? "unknown"}]: ${reason}`);
|
|
11801
|
+
}
|
|
11802
|
+
}
|
|
11542
11803
|
let swarmPlanFilesRemoved = 0;
|
|
11543
11804
|
const candidates = [
|
|
11544
11805
|
path24.join(ctx.directory, ".swarm", "SWARM_PLAN.json"),
|
|
@@ -11564,9 +11825,21 @@ async function runCleanStage(ctx) {
|
|
|
11564
11825
|
try {
|
|
11565
11826
|
await fs11.unlink(path24.join(ctx.swarmDir, tmp));
|
|
11566
11827
|
tmpFilesRemoved++;
|
|
11567
|
-
} catch {
|
|
11828
|
+
} catch (err) {
|
|
11829
|
+
const errno = err?.code;
|
|
11830
|
+
if (errno === "ENOENT") {} else {
|
|
11831
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
11832
|
+
ctx.warnings.push(`Failed to clean tmp file ${tmp} [${errno ?? "unknown"}]: ${reason}`);
|
|
11833
|
+
}
|
|
11834
|
+
}
|
|
11568
11835
|
}
|
|
11569
|
-
} catch {
|
|
11836
|
+
} catch (err) {
|
|
11837
|
+
const errno = err?.code;
|
|
11838
|
+
if (errno === "ENOENT") {} else {
|
|
11839
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
11840
|
+
ctx.warnings.push(`Failed to read ${ctx.swarmDir} for tmp-file cleanup [${errno ?? "unknown"}]: ${reason}`);
|
|
11841
|
+
}
|
|
11842
|
+
}
|
|
11570
11843
|
if (tmpFilesRemoved > 0) {
|
|
11571
11844
|
cleanedFiles.push(`${tmpFilesRemoved} .tmp.* file(s)`);
|
|
11572
11845
|
}
|
|
@@ -11583,9 +11856,14 @@ async function runCleanStage(ctx) {
|
|
|
11583
11856
|
""
|
|
11584
11857
|
].join(`
|
|
11585
11858
|
`);
|
|
11859
|
+
const contextTempPath = path24.join(path24.dirname(contextPath), `${path24.basename(contextPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
|
|
11586
11860
|
try {
|
|
11587
|
-
await fs11.writeFile(
|
|
11861
|
+
await fs11.writeFile(contextTempPath, contextContent, "utf-8");
|
|
11862
|
+
fsSync2.renameSync(contextTempPath, contextPath);
|
|
11588
11863
|
} catch (error2) {
|
|
11864
|
+
try {
|
|
11865
|
+
fsSync2.unlinkSync(contextTempPath);
|
|
11866
|
+
} catch {}
|
|
11589
11867
|
const msg = error2 instanceof Error ? error2.message : String(error2);
|
|
11590
11868
|
ctx.warnings.push(`Failed to reset context.md: ${msg}`);
|
|
11591
11869
|
console.warn("[close-command] Failed to write context.md:", error2);
|
|
@@ -11601,9 +11879,9 @@ async function runAlignStage(ctx) {
|
|
|
11601
11879
|
const pruneBranches = ctx.args.includes("--prune-branches");
|
|
11602
11880
|
let gitAlignResult = "";
|
|
11603
11881
|
const prunedBranches = [];
|
|
11604
|
-
const gitStatus =
|
|
11882
|
+
const gitStatus = _internals20.getGitRepositoryStatus(ctx.directory);
|
|
11605
11883
|
if (gitStatus.isRepo) {
|
|
11606
|
-
const aggressiveResult = await
|
|
11884
|
+
const aggressiveResult = await _internals20.resetToMainAfterMerge(ctx.directory, {
|
|
11607
11885
|
pruneBranches
|
|
11608
11886
|
});
|
|
11609
11887
|
if (aggressiveResult.success) {
|
|
@@ -11615,7 +11893,7 @@ async function runAlignStage(ctx) {
|
|
|
11615
11893
|
ctx.warnings.push("Uncommitted changes were discarded during git alignment");
|
|
11616
11894
|
}
|
|
11617
11895
|
} else {
|
|
11618
|
-
const alignResult = await
|
|
11896
|
+
const alignResult = await _internals20.resetToRemoteBranch(ctx.directory, {
|
|
11619
11897
|
pruneBranches
|
|
11620
11898
|
});
|
|
11621
11899
|
gitAlignResult = alignResult.message;
|
|
@@ -11675,20 +11953,38 @@ async function handleCloseCommand(directory, args, options = {}) {
|
|
|
11675
11953
|
let finalizeLock = {
|
|
11676
11954
|
acquired: false
|
|
11677
11955
|
};
|
|
11678
|
-
finalizeLock = await
|
|
11956
|
+
finalizeLock = await _internals20.acquireFinalizeLock(directory);
|
|
11679
11957
|
if (!finalizeLock.acquired) {
|
|
11680
11958
|
return `\u274C Another /swarm finalize is already running for this project. If you are certain no other run is active, wait for the lock to expire or remove the stale lock and retry.`;
|
|
11681
11959
|
}
|
|
11682
|
-
const phases = planData.phases ?? [];
|
|
11683
|
-
const inProgressPhases = phases.filter((p) => p.status === "in_progress");
|
|
11684
|
-
const isForced = args.includes("--force");
|
|
11685
|
-
const runSkillReview = args.includes("--skill-review");
|
|
11686
|
-
let planAlreadyDone = false;
|
|
11687
|
-
if (planExists) {
|
|
11688
|
-
planAlreadyDone = phases.length > 0 && phases.every((p) => p.status === "complete" || p.status === "completed" || p.status === "blocked" || p.status === "closed");
|
|
11689
|
-
}
|
|
11690
11960
|
try {
|
|
11691
|
-
|
|
11961
|
+
if (!planExists) {
|
|
11962
|
+
const archiveDir = path24.join(swarmDir, "archive");
|
|
11963
|
+
try {
|
|
11964
|
+
const archiveEntries = await fs11.readdir(archiveDir);
|
|
11965
|
+
const hasArchiveBundle = archiveEntries.some((entry) => entry.startsWith("swarm-"));
|
|
11966
|
+
if (hasArchiveBundle) {
|
|
11967
|
+
const hasActiveState = [
|
|
11968
|
+
...ACTIVE_STATE_TO_CLEAN,
|
|
11969
|
+
...ACTIVE_STATE_DIRS_TO_CLEAN
|
|
11970
|
+
].some((entry) => fsSync2.existsSync(path24.join(swarmDir, entry)));
|
|
11971
|
+
if (!hasActiveState) {
|
|
11972
|
+
return `\u2705 Already finalized \u2014 nothing to do.
|
|
11973
|
+
|
|
11974
|
+
This project was already finalized in a previous /swarm close run. The plan has been archived and cleaned up. No further action is needed.`;
|
|
11975
|
+
}
|
|
11976
|
+
}
|
|
11977
|
+
} catch {}
|
|
11978
|
+
}
|
|
11979
|
+
const phases = planData.phases ?? [];
|
|
11980
|
+
const inProgressPhases = phases.filter((p) => p.status === "in_progress");
|
|
11981
|
+
const isForced = args.includes("--force");
|
|
11982
|
+
const runSkillReview = args.includes("--skill-review");
|
|
11983
|
+
let planAlreadyDone = false;
|
|
11984
|
+
if (planExists) {
|
|
11985
|
+
planAlreadyDone = phases.length > 0 && phases.every((p) => p.status === "complete" || p.status === "completed" || p.status === "blocked" || p.status === "closed");
|
|
11986
|
+
}
|
|
11987
|
+
const { config: loadedConfig } = _internals20.loadPluginConfigWithMeta(directory);
|
|
11692
11988
|
const config = KnowledgeConfigSchema.parse(loadedConfig.knowledge ?? {});
|
|
11693
11989
|
const ctx = {
|
|
11694
11990
|
directory,
|
|
@@ -11724,6 +12020,7 @@ async function handleCloseCommand(directory, args, options = {}) {
|
|
|
11724
12020
|
archivedFileCount: 0,
|
|
11725
12021
|
archivedActiveStateFiles: new Set,
|
|
11726
12022
|
archivedActiveStateDirs: new Set,
|
|
12023
|
+
archiveFailureReasons: new Map,
|
|
11727
12024
|
timestamp: "",
|
|
11728
12025
|
archiveDir: "",
|
|
11729
12026
|
archiveSuffix: "",
|
|
@@ -11786,14 +12083,19 @@ async function handleCloseCommand(directory, args, options = {}) {
|
|
|
11786
12083
|
...ctx.warnings.length > 0 ? ["## Warnings", ...ctx.warnings.map((w) => `- ${w}`), ""] : []
|
|
11787
12084
|
].join(`
|
|
11788
12085
|
`);
|
|
12086
|
+
const closeSummaryTempPath = path24.join(path24.dirname(closeSummaryPath), `${path24.basename(closeSummaryPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
|
|
11789
12087
|
try {
|
|
11790
|
-
await fs11.writeFile(
|
|
12088
|
+
await fs11.writeFile(closeSummaryTempPath, summaryContent, "utf-8");
|
|
12089
|
+
fsSync2.renameSync(closeSummaryTempPath, closeSummaryPath);
|
|
11791
12090
|
} catch (error2) {
|
|
12091
|
+
try {
|
|
12092
|
+
fsSync2.unlinkSync(closeSummaryTempPath);
|
|
12093
|
+
} catch {}
|
|
11792
12094
|
const msg = error2 instanceof Error ? error2.message : String(error2);
|
|
11793
12095
|
ctx.warnings.push(`Failed to write close-summary.md: ${msg}`);
|
|
11794
12096
|
console.warn("[close-command] Failed to write close-summary.md:", error2);
|
|
11795
12097
|
}
|
|
11796
|
-
|
|
12098
|
+
_internals20.resetSwarmStatePreservingSingletons();
|
|
11797
12099
|
const retroWarnings = ctx.warnings.filter((w) => w.includes("Retrospective write") || w.includes("retrospective write") || w.includes("Session retrospective"));
|
|
11798
12100
|
const otherWarnings = ctx.warnings.filter((w) => !w.includes("Retrospective write") && !w.includes("retrospective write") && !w.includes("Session retrospective"));
|
|
11799
12101
|
let warningMsg = "";
|
|
@@ -11848,7 +12150,7 @@ async function acquireFinalizeLock(directory) {
|
|
|
11848
12150
|
}
|
|
11849
12151
|
return { acquired: false };
|
|
11850
12152
|
}
|
|
11851
|
-
var
|
|
12153
|
+
var _internals20 = {
|
|
11852
12154
|
ACTIVE_STATE_DIRS_TO_CLEAN,
|
|
11853
12155
|
countSessionKnowledgeEntries,
|
|
11854
12156
|
CLOSE_SKILL_REVIEW_TIMEOUT_MS,
|
|
@@ -12129,7 +12431,7 @@ async function handleConfigCommand(directory, _args) {
|
|
|
12129
12431
|
}
|
|
12130
12432
|
|
|
12131
12433
|
// src/services/skill-consolidation.ts
|
|
12132
|
-
import { existsSync as
|
|
12434
|
+
import { existsSync as existsSync14 } from "fs";
|
|
12133
12435
|
import { mkdir as mkdir8, readFile as readFile8, rename as rename4, writeFile as writeFile8 } from "fs/promises";
|
|
12134
12436
|
import * as path26 from "path";
|
|
12135
12437
|
|
|
@@ -12160,7 +12462,7 @@ function consolidationStatePath(directory) {
|
|
|
12160
12462
|
}
|
|
12161
12463
|
async function readState2(directory) {
|
|
12162
12464
|
const filePath = consolidationStatePath(directory);
|
|
12163
|
-
if (!
|
|
12465
|
+
if (!existsSync14(filePath))
|
|
12164
12466
|
return {};
|
|
12165
12467
|
try {
|
|
12166
12468
|
const parsed = JSON.parse(await readFile8(filePath, "utf-8"));
|
|
@@ -12636,9 +12938,9 @@ async function detectDarkMatter(directory, options) {
|
|
|
12636
12938
|
} catch {
|
|
12637
12939
|
return [];
|
|
12638
12940
|
}
|
|
12639
|
-
const commitMap = await
|
|
12640
|
-
const matrix =
|
|
12641
|
-
const staticEdges = await
|
|
12941
|
+
const commitMap = await _internals21.parseGitLog(directory, maxCommitsToAnalyze);
|
|
12942
|
+
const matrix = _internals21.buildCoChangeMatrix(commitMap, maxFilesPerCommit);
|
|
12943
|
+
const staticEdges = await _internals21.getStaticEdges(directory);
|
|
12642
12944
|
const results = [];
|
|
12643
12945
|
for (const entry of matrix.values()) {
|
|
12644
12946
|
const key = `${entry.fileA}::${entry.fileB}`;
|
|
@@ -12754,11 +13056,11 @@ var co_change_analyzer = createSwarmTool({
|
|
|
12754
13056
|
npmiThreshold,
|
|
12755
13057
|
maxCommitsToAnalyze
|
|
12756
13058
|
};
|
|
12757
|
-
const pairs = await
|
|
12758
|
-
return
|
|
13059
|
+
const pairs = await _internals21.detectDarkMatter(directory, options);
|
|
13060
|
+
return _internals21.formatDarkMatterOutput(pairs);
|
|
12759
13061
|
}
|
|
12760
13062
|
});
|
|
12761
|
-
var
|
|
13063
|
+
var _internals21 = {
|
|
12762
13064
|
parseGitLog,
|
|
12763
13065
|
buildCoChangeMatrix,
|
|
12764
13066
|
getStaticEdges,
|
|
@@ -12775,7 +13077,7 @@ var DEFAULT_MAX_COMMITS = 500;
|
|
|
12775
13077
|
var cache = new Map;
|
|
12776
13078
|
async function readGitHead(directory) {
|
|
12777
13079
|
try {
|
|
12778
|
-
const { stdout } = await
|
|
13080
|
+
const { stdout } = await _internals22.execFile("git", ["rev-parse", "HEAD"], {
|
|
12779
13081
|
cwd: directory,
|
|
12780
13082
|
timeout: GIT_HEAD_TIMEOUT_MS
|
|
12781
13083
|
});
|
|
@@ -12801,9 +13103,9 @@ async function getCoChangeData(directory, options) {
|
|
|
12801
13103
|
let entries;
|
|
12802
13104
|
let commitsObserved;
|
|
12803
13105
|
try {
|
|
12804
|
-
const commitMap = await
|
|
13106
|
+
const commitMap = await _internals22.parseGitLog(directory, maxCommits);
|
|
12805
13107
|
commitsObserved = commitMap.size;
|
|
12806
|
-
const matrix =
|
|
13108
|
+
const matrix = _internals22.buildCoChangeMatrix(commitMap);
|
|
12807
13109
|
entries = Array.from(matrix.values());
|
|
12808
13110
|
} catch {
|
|
12809
13111
|
return { pairs: [], commitsObserved: 0 };
|
|
@@ -12827,10 +13129,10 @@ async function getCoChangePairs(directory, options) {
|
|
|
12827
13129
|
const data = await getCoChangeData(directory, options);
|
|
12828
13130
|
return data.pairs;
|
|
12829
13131
|
}
|
|
12830
|
-
var
|
|
13132
|
+
var _internals22 = {
|
|
12831
13133
|
execFile: execFileAsync,
|
|
12832
|
-
parseGitLog:
|
|
12833
|
-
buildCoChangeMatrix:
|
|
13134
|
+
parseGitLog: _internals21.parseGitLog,
|
|
13135
|
+
buildCoChangeMatrix: _internals21.buildCoChangeMatrix
|
|
12834
13136
|
};
|
|
12835
13137
|
|
|
12836
13138
|
// src/turbo/epic/cochange-conflict.ts
|
|
@@ -13112,7 +13414,7 @@ async function handleCouplingCommand(directory, args) {
|
|
|
13112
13414
|
|
|
13113
13415
|
Usage: /swarm coupling [--phase <n>] [--threshold <-1..1>] [--min-co-changes <n>] [--format markdown|json] [--persist]`;
|
|
13114
13416
|
}
|
|
13115
|
-
const plan = await
|
|
13417
|
+
const plan = await _internals23.loadPlanJsonOnly(directory);
|
|
13116
13418
|
if (plan === null) {
|
|
13117
13419
|
return "No plan found at `.swarm/plan.json`. Run `/swarm plan` to create one before measuring coupling.";
|
|
13118
13420
|
}
|
|
@@ -13136,7 +13438,7 @@ Usage: /swarm coupling [--phase <n>] [--threshold <-1..1>] [--min-co-changes <n>
|
|
|
13136
13438
|
const scope = scopeFiles ?? task.files_touched ?? [];
|
|
13137
13439
|
return { id: task.id, scope };
|
|
13138
13440
|
});
|
|
13139
|
-
const cochangePairs = await
|
|
13441
|
+
const cochangePairs = await _internals23.getCoChangePairs(directory);
|
|
13140
13442
|
const report = computeCouplingReport(tasks, cochangePairs, {
|
|
13141
13443
|
npmi: parsed.threshold,
|
|
13142
13444
|
minCoChanges: parsed.minCoChanges
|
|
@@ -13175,7 +13477,7 @@ _Warning: failed to persist report (${persistStatus.error})._`;
|
|
|
13175
13477
|
}
|
|
13176
13478
|
return `${formatCouplingReportMarkdown(report)}${persistTrailer}`;
|
|
13177
13479
|
}
|
|
13178
|
-
var
|
|
13480
|
+
var _internals23 = {
|
|
13179
13481
|
loadPlanJsonOnly,
|
|
13180
13482
|
getCoChangePairs
|
|
13181
13483
|
};
|
|
@@ -13229,7 +13531,7 @@ async function handleDarkMatterCommand(directory, args) {
|
|
|
13229
13531
|
}
|
|
13230
13532
|
let pairs;
|
|
13231
13533
|
try {
|
|
13232
|
-
pairs = await
|
|
13534
|
+
pairs = await _internals21.detectDarkMatter(directory, options);
|
|
13233
13535
|
} catch (err) {
|
|
13234
13536
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
13235
13537
|
return `## Dark Matter Analysis Failed
|
|
@@ -13607,7 +13909,7 @@ ${USAGE5}`;
|
|
|
13607
13909
|
|
|
13608
13910
|
// src/services/diagnose-service.ts
|
|
13609
13911
|
import * as child_process4 from "child_process";
|
|
13610
|
-
import { existsSync as
|
|
13912
|
+
import { existsSync as existsSync17, readdirSync as readdirSync3, readFileSync as readFileSync9, statSync as statSync6 } from "fs";
|
|
13611
13913
|
import path31 from "path";
|
|
13612
13914
|
import { fileURLToPath } from "url";
|
|
13613
13915
|
|
|
@@ -13660,11 +13962,11 @@ init_capability_probe();
|
|
|
13660
13962
|
init_executor();
|
|
13661
13963
|
|
|
13662
13964
|
// src/services/knowledge-diagnostics.ts
|
|
13663
|
-
import { existsSync as
|
|
13965
|
+
import { existsSync as existsSync16 } from "fs";
|
|
13664
13966
|
import { readFile as readFile10 } from "fs/promises";
|
|
13665
13967
|
|
|
13666
13968
|
// src/services/version-check.ts
|
|
13667
|
-
import { existsSync as
|
|
13969
|
+
import { existsSync as existsSync15, mkdirSync as mkdirSync9, readFileSync as readFileSync8, writeFileSync as writeFileSync8 } from "fs";
|
|
13668
13970
|
import { homedir as homedir4 } from "os";
|
|
13669
13971
|
import { join as join25 } from "path";
|
|
13670
13972
|
var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;
|
|
@@ -13679,7 +13981,7 @@ function cacheFile() {
|
|
|
13679
13981
|
function readVersionCache() {
|
|
13680
13982
|
try {
|
|
13681
13983
|
const path31 = cacheFile();
|
|
13682
|
-
if (!
|
|
13984
|
+
if (!existsSync15(path31))
|
|
13683
13985
|
return null;
|
|
13684
13986
|
const raw = readFileSync8(path31, "utf-8");
|
|
13685
13987
|
const parsed = JSON.parse(raw);
|
|
@@ -13720,7 +14022,7 @@ var SEVEN_DAYS_MS2 = 7 * 24 * 60 * 60 * 1000;
|
|
|
13720
14022
|
var UNACTIONABLE_BACKLOG_WARN = 100;
|
|
13721
14023
|
var INSIGHT_BACKLOG_WARN = 50;
|
|
13722
14024
|
async function readRawLines(filePath) {
|
|
13723
|
-
if (!
|
|
14025
|
+
if (!existsSync16(filePath))
|
|
13724
14026
|
return { entries: [], corrupt: 0 };
|
|
13725
14027
|
const content = await readFile10(filePath, "utf-8");
|
|
13726
14028
|
const entries = [];
|
|
@@ -13845,7 +14147,7 @@ async function computeKnowledgeDebug(directory) {
|
|
|
13845
14147
|
};
|
|
13846
14148
|
}
|
|
13847
14149
|
async function safeJsonlCount(filePath) {
|
|
13848
|
-
if (!filePath || !
|
|
14150
|
+
if (!filePath || !existsSync16(filePath))
|
|
13849
14151
|
return 0;
|
|
13850
14152
|
try {
|
|
13851
14153
|
const content = await readFile10(filePath, "utf-8");
|
|
@@ -13917,7 +14219,7 @@ async function checkKnowledgeHealth(directory) {
|
|
|
13917
14219
|
// src/services/diagnose-service.ts
|
|
13918
14220
|
var { version: version2 } = package_default;
|
|
13919
14221
|
var sandboxCapabilityProbe = new SandboxCapabilityProbe;
|
|
13920
|
-
var
|
|
14222
|
+
var _internals24 = {
|
|
13921
14223
|
detectSandboxCapability: () => sandboxCapabilityProbe.detect(),
|
|
13922
14224
|
getSandboxExecutor: getExecutor
|
|
13923
14225
|
};
|
|
@@ -14166,7 +14468,7 @@ async function checkConfigBackups(directory) {
|
|
|
14166
14468
|
}
|
|
14167
14469
|
async function checkGitRepository(directory) {
|
|
14168
14470
|
try {
|
|
14169
|
-
if (!
|
|
14471
|
+
if (!existsSync17(directory) || !statSync6(directory).isDirectory()) {
|
|
14170
14472
|
return {
|
|
14171
14473
|
name: "Git Repository",
|
|
14172
14474
|
status: "\u274C",
|
|
@@ -14231,7 +14533,7 @@ async function checkSpecStaleness(directory, plan) {
|
|
|
14231
14533
|
}
|
|
14232
14534
|
async function checkConfigParseability(directory) {
|
|
14233
14535
|
const configPath = path31.join(directory, ".opencode/opencode-swarm.json");
|
|
14234
|
-
if (!
|
|
14536
|
+
if (!existsSync17(configPath)) {
|
|
14235
14537
|
return {
|
|
14236
14538
|
name: "Config Parseability",
|
|
14237
14539
|
status: "\u2705",
|
|
@@ -14286,11 +14588,11 @@ async function checkGrammarWasmFiles() {
|
|
|
14286
14588
|
const thisDir = path31.dirname(fileURLToPath(import.meta.url));
|
|
14287
14589
|
const grammarDir = resolveGrammarDir(thisDir);
|
|
14288
14590
|
const missing = [];
|
|
14289
|
-
if (!
|
|
14591
|
+
if (!existsSync17(path31.join(grammarDir, "tree-sitter.wasm"))) {
|
|
14290
14592
|
missing.push("tree-sitter.wasm (core runtime)");
|
|
14291
14593
|
}
|
|
14292
14594
|
for (const file of grammarFiles) {
|
|
14293
|
-
if (!
|
|
14595
|
+
if (!existsSync17(path31.join(grammarDir, file))) {
|
|
14294
14596
|
missing.push(file);
|
|
14295
14597
|
}
|
|
14296
14598
|
}
|
|
@@ -14309,7 +14611,7 @@ async function checkGrammarWasmFiles() {
|
|
|
14309
14611
|
}
|
|
14310
14612
|
async function checkCheckpointManifest(directory) {
|
|
14311
14613
|
const manifestPath = path31.join(directory, ".swarm/checkpoints.json");
|
|
14312
|
-
if (!
|
|
14614
|
+
if (!existsSync17(manifestPath)) {
|
|
14313
14615
|
return {
|
|
14314
14616
|
name: "Checkpoint Manifest",
|
|
14315
14617
|
status: "\u2705",
|
|
@@ -14361,7 +14663,7 @@ async function checkCheckpointManifest(directory) {
|
|
|
14361
14663
|
}
|
|
14362
14664
|
async function checkEventStreamIntegrity(directory) {
|
|
14363
14665
|
const eventsPath = path31.join(directory, ".swarm/events.jsonl");
|
|
14364
|
-
if (!
|
|
14666
|
+
if (!existsSync17(eventsPath)) {
|
|
14365
14667
|
return {
|
|
14366
14668
|
name: "Event Stream",
|
|
14367
14669
|
status: "\u2705",
|
|
@@ -14402,7 +14704,7 @@ async function checkEventStreamIntegrity(directory) {
|
|
|
14402
14704
|
}
|
|
14403
14705
|
async function checkSteeringDirectives(directory) {
|
|
14404
14706
|
const eventsPath = path31.join(directory, ".swarm/events.jsonl");
|
|
14405
|
-
if (!
|
|
14707
|
+
if (!existsSync17(eventsPath)) {
|
|
14406
14708
|
return {
|
|
14407
14709
|
name: "Steering Directives",
|
|
14408
14710
|
status: "\u2705",
|
|
@@ -14458,7 +14760,7 @@ async function checkCurator(directory) {
|
|
|
14458
14760
|
};
|
|
14459
14761
|
}
|
|
14460
14762
|
const summaryPath = path31.join(directory, ".swarm/curator-summary.json");
|
|
14461
|
-
if (!
|
|
14763
|
+
if (!existsSync17(summaryPath)) {
|
|
14462
14764
|
return {
|
|
14463
14765
|
name: "Curator",
|
|
14464
14766
|
status: "\u2705",
|
|
@@ -14501,9 +14803,9 @@ async function checkCurator(directory) {
|
|
|
14501
14803
|
}
|
|
14502
14804
|
async function getSandboxStatus() {
|
|
14503
14805
|
try {
|
|
14504
|
-
const capability = await
|
|
14806
|
+
const capability = await _internals24.detectSandboxCapability();
|
|
14505
14807
|
const mechanism = capability.mechanism ?? "none";
|
|
14506
|
-
const executor = await
|
|
14808
|
+
const executor = await _internals24.getSandboxExecutor();
|
|
14507
14809
|
const hasExecutor = executor !== null;
|
|
14508
14810
|
if (hasExecutor) {
|
|
14509
14811
|
return {
|
|
@@ -14660,7 +14962,7 @@ async function getDiagnoseData(directory) {
|
|
|
14660
14962
|
checks.push(await checkKnowledgeHealth(directory));
|
|
14661
14963
|
try {
|
|
14662
14964
|
const evidenceDir = path31.join(directory, ".swarm", "evidence");
|
|
14663
|
-
const snapshotFiles =
|
|
14965
|
+
const snapshotFiles = existsSync17(evidenceDir) ? readdirSync3(evidenceDir).filter((f) => f.startsWith("agent-tools-") && f.endsWith(".json")) : [];
|
|
14664
14966
|
if (snapshotFiles.length > 0) {
|
|
14665
14967
|
const latest = snapshotFiles.sort().pop();
|
|
14666
14968
|
checks.push({
|
|
@@ -14693,7 +14995,7 @@ async function getDiagnoseData(directory) {
|
|
|
14693
14995
|
const cacheRows = [];
|
|
14694
14996
|
for (const cachePath of cachePaths) {
|
|
14695
14997
|
try {
|
|
14696
|
-
if (!
|
|
14998
|
+
if (!existsSync17(cachePath)) {
|
|
14697
14999
|
cacheRows.push(`\u2B1C ${cachePath} \u2014 absent`);
|
|
14698
15000
|
continue;
|
|
14699
15001
|
}
|
|
@@ -15239,7 +15541,7 @@ function readPromotionEvidence(directory) {
|
|
|
15239
15541
|
}
|
|
15240
15542
|
|
|
15241
15543
|
// src/commands/epic.ts
|
|
15242
|
-
var
|
|
15544
|
+
var _internals25 = {
|
|
15243
15545
|
loadPluginConfigWithMeta,
|
|
15244
15546
|
loadPlanJsonOnly,
|
|
15245
15547
|
getCoChangeData,
|
|
@@ -15261,7 +15563,7 @@ async function handleEpicCommand(directory, args, sessionID) {
|
|
|
15261
15563
|
if (!sessionID || sessionID.trim() === "") {
|
|
15262
15564
|
return "Error: No active session context. Epic Mode requires an active session. Use /swarm epic from within an OpenCode session.";
|
|
15263
15565
|
}
|
|
15264
|
-
const session =
|
|
15566
|
+
const session = _internals25.ensureAgentSession(sessionID, undefined, directory);
|
|
15265
15567
|
const arg0 = args[0]?.toLowerCase();
|
|
15266
15568
|
switch (arg0) {
|
|
15267
15569
|
case "status":
|
|
@@ -15288,7 +15590,7 @@ Usage:
|
|
|
15288
15590
|
}
|
|
15289
15591
|
function enableAndAck(directory, sessionID, session) {
|
|
15290
15592
|
try {
|
|
15291
|
-
|
|
15593
|
+
_internals25.enableEpicMode(directory, sessionID);
|
|
15292
15594
|
} catch (err) {
|
|
15293
15595
|
return `Error enabling Epic Mode: ${err instanceof Error ? err.message : String(err)}`;
|
|
15294
15596
|
}
|
|
@@ -15304,7 +15606,7 @@ function enableAndAck(directory, sessionID, session) {
|
|
|
15304
15606
|
}
|
|
15305
15607
|
function disableAndAck(directory, sessionID, session) {
|
|
15306
15608
|
try {
|
|
15307
|
-
|
|
15609
|
+
_internals25.disableEpicMode(directory, sessionID);
|
|
15308
15610
|
} catch (err) {
|
|
15309
15611
|
return `Error disabling Epic Mode: ${err instanceof Error ? err.message : String(err)}`;
|
|
15310
15612
|
}
|
|
@@ -15313,12 +15615,12 @@ function disableAndAck(directory, sessionID, session) {
|
|
|
15313
15615
|
}
|
|
15314
15616
|
function renderStatus(directory, sessionID) {
|
|
15315
15617
|
const lines = ["## Epic Mode \u2014 Status", ""];
|
|
15316
|
-
if (
|
|
15618
|
+
if (_internals25.isStateUnreadable(directory)) {
|
|
15317
15619
|
lines.push("**Epic Mode state is unreadable** (`.swarm/epic-state.json` is corrupt or has an unexpected shape). Status cannot be reported until the file is repaired or removed. The fail-closed marker means `epic_decide_phase` will refuse to compute a verdict in this state.");
|
|
15318
15620
|
return lines.join(`
|
|
15319
15621
|
`);
|
|
15320
15622
|
}
|
|
15321
|
-
const state =
|
|
15623
|
+
const state = _internals25.loadEpicSessionState(directory, sessionID);
|
|
15322
15624
|
if (!state) {
|
|
15323
15625
|
lines.push("Epic Mode has not been toggled for this session.");
|
|
15324
15626
|
return lines.join(`
|
|
@@ -15370,7 +15672,7 @@ function formatGreenfieldDetail(input) {
|
|
|
15370
15672
|
function renderLast(directory) {
|
|
15371
15673
|
let records;
|
|
15372
15674
|
try {
|
|
15373
|
-
records =
|
|
15675
|
+
records = _internals25.readPromotionEvidence(directory);
|
|
15374
15676
|
} catch (err) {
|
|
15375
15677
|
return `Error reading epic-promotions.jsonl: ${err instanceof Error ? err.message : String(err)}`;
|
|
15376
15678
|
}
|
|
@@ -15425,7 +15727,7 @@ function renderLast(directory) {
|
|
|
15425
15727
|
`);
|
|
15426
15728
|
}
|
|
15427
15729
|
function renderCalibration(directory) {
|
|
15428
|
-
if (
|
|
15730
|
+
if (_internals25.isCalibrationStateUnreadable(directory)) {
|
|
15429
15731
|
return [
|
|
15430
15732
|
"## Epic Mode \u2014 Calibration",
|
|
15431
15733
|
"",
|
|
@@ -15437,11 +15739,11 @@ function renderCalibration(directory) {
|
|
|
15437
15739
|
}
|
|
15438
15740
|
let state;
|
|
15439
15741
|
try {
|
|
15440
|
-
state =
|
|
15742
|
+
state = _internals25.loadCalibrationState(directory);
|
|
15441
15743
|
} catch (err) {
|
|
15442
15744
|
return `Error reading calibration state: ${err instanceof Error ? err.message : String(err)}`;
|
|
15443
15745
|
}
|
|
15444
|
-
const { config } =
|
|
15746
|
+
const { config } = _internals25.loadPluginConfigWithMeta(directory);
|
|
15445
15747
|
const staticThreshold = config.turbo?.epic?.mode?.activation_threshold ?? 0.3;
|
|
15446
15748
|
const calibrationCfg = config.turbo?.epic?.calibration;
|
|
15447
15749
|
const loosenWindow = calibrationCfg?.loosen_window ?? 10;
|
|
@@ -15489,7 +15791,7 @@ function renderCalibration(directory) {
|
|
|
15489
15791
|
lines.push("");
|
|
15490
15792
|
let recentDivergent = [];
|
|
15491
15793
|
try {
|
|
15492
|
-
const all =
|
|
15794
|
+
const all = _internals25.readDivergenceHistory(directory, { limit: 50 });
|
|
15493
15795
|
recentDivergent = all.filter((r) => !r.isClean).slice(-5);
|
|
15494
15796
|
} catch {}
|
|
15495
15797
|
lines.push("### Recent divergent tasks (tightened the threshold)");
|
|
@@ -15506,11 +15808,11 @@ function renderCalibration(directory) {
|
|
|
15506
15808
|
`);
|
|
15507
15809
|
}
|
|
15508
15810
|
async function renderDecide(directory) {
|
|
15509
|
-
const plan = await
|
|
15811
|
+
const plan = await _internals25.loadPlanJsonOnly(directory);
|
|
15510
15812
|
if (!plan) {
|
|
15511
15813
|
return "No plan found at `.swarm/plan.json`. Run `/swarm plan` first.";
|
|
15512
15814
|
}
|
|
15513
|
-
const { config } =
|
|
15815
|
+
const { config } = _internals25.loadPluginConfigWithMeta(directory);
|
|
15514
15816
|
const modeCfg = config.turbo?.epic?.mode;
|
|
15515
15817
|
const cochangeCfg = config.turbo?.epic?.cochange;
|
|
15516
15818
|
const activationThreshold = modeCfg?.activation_threshold ?? 0.3;
|
|
@@ -15520,20 +15822,20 @@ async function renderDecide(directory) {
|
|
|
15520
15822
|
const tasks = [];
|
|
15521
15823
|
for (const phase of plan.phases) {
|
|
15522
15824
|
for (const task of phase.tasks) {
|
|
15523
|
-
const scopeFiles =
|
|
15825
|
+
const scopeFiles = _internals25.readTaskScopes(directory, task.id);
|
|
15524
15826
|
const scope = scopeFiles ?? task.files_touched ?? [];
|
|
15525
15827
|
tasks.push({ id: task.id, scope });
|
|
15526
15828
|
}
|
|
15527
15829
|
}
|
|
15528
|
-
const { pairs, commitsObserved } = await
|
|
15830
|
+
const { pairs, commitsObserved } = await _internals25.getCoChangeData(directory);
|
|
15529
15831
|
const isGitProject = (() => {
|
|
15530
15832
|
try {
|
|
15531
|
-
return
|
|
15833
|
+
return _internals25.isGitRepo(directory);
|
|
15532
15834
|
} catch {
|
|
15533
15835
|
return false;
|
|
15534
15836
|
}
|
|
15535
15837
|
})();
|
|
15536
|
-
const verdict =
|
|
15838
|
+
const verdict = _internals25.decideEpicActivation(tasks, pairs, commitsObserved, {
|
|
15537
15839
|
activationThreshold,
|
|
15538
15840
|
minCommitsForSignal,
|
|
15539
15841
|
cochangeNpmiThreshold,
|
|
@@ -15577,7 +15879,7 @@ function formatVerdict(verdict) {
|
|
|
15577
15879
|
}
|
|
15578
15880
|
|
|
15579
15881
|
// src/services/evidence-service.ts
|
|
15580
|
-
var
|
|
15882
|
+
var _internals26 = {
|
|
15581
15883
|
loadEvidence,
|
|
15582
15884
|
listEvidenceTaskIds
|
|
15583
15885
|
};
|
|
@@ -15622,7 +15924,7 @@ function getVerdictEmoji(verdict) {
|
|
|
15622
15924
|
return getVerdictIcon(verdict);
|
|
15623
15925
|
}
|
|
15624
15926
|
async function getTaskEvidenceData(directory, taskId) {
|
|
15625
|
-
const result = await
|
|
15927
|
+
const result = await _internals26.loadEvidence(directory, taskId);
|
|
15626
15928
|
if (result.status !== "found") {
|
|
15627
15929
|
return {
|
|
15628
15930
|
hasEvidence: false,
|
|
@@ -15645,13 +15947,13 @@ async function getTaskEvidenceData(directory, taskId) {
|
|
|
15645
15947
|
};
|
|
15646
15948
|
}
|
|
15647
15949
|
async function getEvidenceListData(directory) {
|
|
15648
|
-
const taskIds = await
|
|
15950
|
+
const taskIds = await _internals26.listEvidenceTaskIds(directory);
|
|
15649
15951
|
if (taskIds.length === 0) {
|
|
15650
15952
|
return { hasEvidence: false, tasks: [] };
|
|
15651
15953
|
}
|
|
15652
15954
|
const tasks = [];
|
|
15653
15955
|
for (const taskId of taskIds) {
|
|
15654
|
-
const result = await
|
|
15956
|
+
const result = await _internals26.loadEvidence(directory, taskId);
|
|
15655
15957
|
if (result.status === "found") {
|
|
15656
15958
|
tasks.push({
|
|
15657
15959
|
taskId,
|
|
@@ -15731,7 +16033,7 @@ async function handleEvidenceCommand(directory, args) {
|
|
|
15731
16033
|
return formatTaskEvidenceMarkdown(evidenceData);
|
|
15732
16034
|
}
|
|
15733
16035
|
async function handleEvidenceSummaryCommand(directory) {
|
|
15734
|
-
const { buildEvidenceSummary } = await import("./evidence-summary-service-
|
|
16036
|
+
const { buildEvidenceSummary } = await import("./evidence-summary-service-5me91eq8.js");
|
|
15735
16037
|
const artifact = await buildEvidenceSummary(directory);
|
|
15736
16038
|
if (!artifact) {
|
|
15737
16039
|
return "No plan found. Run `/swarm plan` to check plan status.";
|
|
@@ -16235,7 +16537,7 @@ function buildStatusReport(directory, sessionID, sessionFlag) {
|
|
|
16235
16537
|
|
|
16236
16538
|
// src/commands/handoff.ts
|
|
16237
16539
|
import crypto4 from "crypto";
|
|
16238
|
-
import { renameSync as
|
|
16540
|
+
import { renameSync as renameSync9, unlinkSync as unlinkSync5 } from "fs";
|
|
16239
16541
|
|
|
16240
16542
|
// src/services/handoff-service.ts
|
|
16241
16543
|
var RTL_OVERRIDE_PATTERN = /[\u202e\u202d\u202c\u200f]/g;
|
|
@@ -16273,7 +16575,7 @@ function extractCurrentPhaseFromPlan2(plan) {
|
|
|
16273
16575
|
if (!plan) {
|
|
16274
16576
|
return { currentPhase: null, currentTask: null, incompleteTasks: [] };
|
|
16275
16577
|
}
|
|
16276
|
-
if (!
|
|
16578
|
+
if (!_internals27.validatePlanPhases(plan)) {
|
|
16277
16579
|
return { currentPhase: null, currentTask: null, incompleteTasks: [] };
|
|
16278
16580
|
}
|
|
16279
16581
|
let currentPhase = null;
|
|
@@ -16415,9 +16717,9 @@ function extractPhaseMetrics(content) {
|
|
|
16415
16717
|
async function getHandoffData(directory) {
|
|
16416
16718
|
const now = new Date().toISOString();
|
|
16417
16719
|
const sessionContent = await readSwarmFileAsync(directory, "session/state.json");
|
|
16418
|
-
const sessionState =
|
|
16720
|
+
const sessionState = _internals27.parseSessionState(sessionContent);
|
|
16419
16721
|
const plan = await loadPlanJsonOnly(directory);
|
|
16420
|
-
const planInfo =
|
|
16722
|
+
const planInfo = _internals27.extractCurrentPhaseFromPlan(plan);
|
|
16421
16723
|
if (!plan) {
|
|
16422
16724
|
const planMdContent = await readSwarmFileAsync(directory, "plan.md");
|
|
16423
16725
|
if (planMdContent) {
|
|
@@ -16436,8 +16738,8 @@ async function getHandoffData(directory) {
|
|
|
16436
16738
|
}
|
|
16437
16739
|
}
|
|
16438
16740
|
const contextContent = await readSwarmFileAsync(directory, "context.md");
|
|
16439
|
-
const recentDecisions =
|
|
16440
|
-
const rawPhaseMetrics =
|
|
16741
|
+
const recentDecisions = _internals27.extractDecisions(contextContent);
|
|
16742
|
+
const rawPhaseMetrics = _internals27.extractPhaseMetrics(contextContent);
|
|
16441
16743
|
const phaseMetrics = sanitizeString(rawPhaseMetrics, 1000);
|
|
16442
16744
|
let delegationState = null;
|
|
16443
16745
|
if (sessionState?.delegationState) {
|
|
@@ -16601,7 +16903,7 @@ ${lines.join(`
|
|
|
16601
16903
|
`)}
|
|
16602
16904
|
\`\`\``;
|
|
16603
16905
|
}
|
|
16604
|
-
var
|
|
16906
|
+
var _internals27 = {
|
|
16605
16907
|
getHandoffData,
|
|
16606
16908
|
formatHandoffMarkdown,
|
|
16607
16909
|
formatContinuationPrompt,
|
|
@@ -16615,7 +16917,7 @@ var _internals26 = {
|
|
|
16615
16917
|
};
|
|
16616
16918
|
|
|
16617
16919
|
// src/session/snapshot-writer.ts
|
|
16618
|
-
import { closeSync as closeSync6, fsyncSync as fsyncSync2, mkdirSync as mkdirSync14, openSync as openSync6, renameSync as
|
|
16920
|
+
import { closeSync as closeSync6, fsyncSync as fsyncSync2, mkdirSync as mkdirSync14, openSync as openSync6, renameSync as renameSync8 } from "fs";
|
|
16619
16921
|
import * as path36 from "path";
|
|
16620
16922
|
var _writeInFlight = Promise.resolve();
|
|
16621
16923
|
function serializeAgentSession(s) {
|
|
@@ -16735,7 +17037,7 @@ async function writeSnapshot(directory, state) {
|
|
|
16735
17037
|
closeSync6(fd);
|
|
16736
17038
|
}
|
|
16737
17039
|
} catch {}
|
|
16738
|
-
|
|
17040
|
+
renameSync8(tempPath, resolvedPath);
|
|
16739
17041
|
} catch (error2) {
|
|
16740
17042
|
log("[snapshot-writer] write failed", {
|
|
16741
17043
|
error: error2 instanceof Error ? error2.message : String(error2)
|
|
@@ -16744,15 +17046,15 @@ async function writeSnapshot(directory, state) {
|
|
|
16744
17046
|
}
|
|
16745
17047
|
function createSnapshotWriterHook(directory) {
|
|
16746
17048
|
return (_input, _output) => {
|
|
16747
|
-
_writeInFlight = _writeInFlight.then(() =>
|
|
17049
|
+
_writeInFlight = _writeInFlight.then(() => _internals28.writeSnapshot(directory, swarmState), () => _internals28.writeSnapshot(directory, swarmState));
|
|
16748
17050
|
return _writeInFlight;
|
|
16749
17051
|
};
|
|
16750
17052
|
}
|
|
16751
17053
|
async function flushPendingSnapshot(directory) {
|
|
16752
|
-
_writeInFlight = _writeInFlight.then(() =>
|
|
17054
|
+
_writeInFlight = _writeInFlight.then(() => _internals28.writeSnapshot(directory, swarmState), () => _internals28.writeSnapshot(directory, swarmState));
|
|
16753
17055
|
await _writeInFlight;
|
|
16754
17056
|
}
|
|
16755
|
-
var
|
|
17057
|
+
var _internals28 = {
|
|
16756
17058
|
writeSnapshot,
|
|
16757
17059
|
createSnapshotWriterHook,
|
|
16758
17060
|
flushPendingSnapshot
|
|
@@ -16767,10 +17069,10 @@ async function handleHandoffCommand(directory, _args) {
|
|
|
16767
17069
|
const tempPath = `${resolvedPath}.tmp.${crypto4.randomUUID()}`;
|
|
16768
17070
|
await bunWrite(tempPath, markdown);
|
|
16769
17071
|
try {
|
|
16770
|
-
|
|
17072
|
+
renameSync9(tempPath, resolvedPath);
|
|
16771
17073
|
} catch (renameErr) {
|
|
16772
17074
|
try {
|
|
16773
|
-
|
|
17075
|
+
unlinkSync5(tempPath);
|
|
16774
17076
|
} catch {}
|
|
16775
17077
|
throw renameErr;
|
|
16776
17078
|
}
|
|
@@ -16779,10 +17081,10 @@ async function handleHandoffCommand(directory, _args) {
|
|
|
16779
17081
|
const promptTempPath = `${promptPath}.tmp.${crypto4.randomUUID()}`;
|
|
16780
17082
|
await bunWrite(promptTempPath, continuationPrompt);
|
|
16781
17083
|
try {
|
|
16782
|
-
|
|
17084
|
+
renameSync9(promptTempPath, promptPath);
|
|
16783
17085
|
} catch (renameErr) {
|
|
16784
17086
|
try {
|
|
16785
|
-
|
|
17087
|
+
unlinkSync5(promptTempPath);
|
|
16786
17088
|
} catch {}
|
|
16787
17089
|
throw renameErr;
|
|
16788
17090
|
}
|
|
@@ -16942,7 +17244,7 @@ async function handleHistoryCommand(directory, _args) {
|
|
|
16942
17244
|
return formatHistoryMarkdown(historyData);
|
|
16943
17245
|
}
|
|
16944
17246
|
// src/commands/_shared/url-security.ts
|
|
16945
|
-
import { spawnSync as
|
|
17247
|
+
import { spawnSync as spawnSync6 } from "child_process";
|
|
16946
17248
|
var MAX_URL_LEN = 2048;
|
|
16947
17249
|
var IPV4_PRIVATE = /^10\./;
|
|
16948
17250
|
var IPV4_LOOPBACK = /^127\./;
|
|
@@ -16952,7 +17254,7 @@ var IPV4_PRIVATE_192 = /^192\.168\./;
|
|
|
16952
17254
|
var IPV4_ZERO_NETWORK = /^0\./;
|
|
16953
17255
|
var IPV6_LINK_LOCAL = /^fe80:/i;
|
|
16954
17256
|
var IPV6_UNIQUE_LOCAL = /^f[cd][0-9a-f]{2}:/i;
|
|
16955
|
-
var
|
|
17257
|
+
var _internals29 = { spawnSync: spawnSync6 };
|
|
16956
17258
|
function sanitizeUrl(raw) {
|
|
16957
17259
|
let urlStr = raw.trim();
|
|
16958
17260
|
urlStr = urlStr.replace(/\[\s*MODE\s*:[^\]]*\]/gi, "");
|
|
@@ -17062,7 +17364,7 @@ function validateAndSanitizeGithubUrl(rawUrl, resource) {
|
|
|
17062
17364
|
}
|
|
17063
17365
|
function detectGitRemote(cwd) {
|
|
17064
17366
|
try {
|
|
17065
|
-
const result =
|
|
17367
|
+
const result = _internals29.spawnSync("git", ["remote", "get-url", "origin"], {
|
|
17066
17368
|
encoding: "utf-8",
|
|
17067
17369
|
stdio: ["ignore", "pipe", "pipe"],
|
|
17068
17370
|
timeout: 5000,
|
|
@@ -17231,7 +17533,7 @@ import { join as join30 } from "path";
|
|
|
17231
17533
|
// src/hooks/knowledge-migrator.ts
|
|
17232
17534
|
init_logger();
|
|
17233
17535
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
17234
|
-
import { existsSync as
|
|
17536
|
+
import { existsSync as existsSync22, readFileSync as readFileSync14 } from "fs";
|
|
17235
17537
|
import { mkdir as mkdir9, readFile as readFile11, writeFile as writeFile9 } from "fs/promises";
|
|
17236
17538
|
import * as os8 from "os";
|
|
17237
17539
|
import * as path37 from "path";
|
|
@@ -17249,7 +17551,7 @@ async function migrateKnowledgeToExternal(_directory, _config) {
|
|
|
17249
17551
|
skippedReason: "no-context-file"
|
|
17250
17552
|
};
|
|
17251
17553
|
}
|
|
17252
|
-
var
|
|
17554
|
+
var _internals30 = {
|
|
17253
17555
|
appendKnowledge,
|
|
17254
17556
|
migrateContextToKnowledge,
|
|
17255
17557
|
migrateKnowledgeToExternal,
|
|
@@ -17267,7 +17569,7 @@ async function migrateContextToKnowledge(directory, config) {
|
|
|
17267
17569
|
const sentinelPath = path37.join(directory, ".swarm", ".knowledge-migrated");
|
|
17268
17570
|
const contextPath = path37.join(directory, ".swarm", "context.md");
|
|
17269
17571
|
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
17270
|
-
if (
|
|
17572
|
+
if (existsSync22(sentinelPath)) {
|
|
17271
17573
|
return {
|
|
17272
17574
|
migrated: false,
|
|
17273
17575
|
entriesMigrated: 0,
|
|
@@ -17276,7 +17578,7 @@ async function migrateContextToKnowledge(directory, config) {
|
|
|
17276
17578
|
skippedReason: "sentinel-exists"
|
|
17277
17579
|
};
|
|
17278
17580
|
}
|
|
17279
|
-
if (!
|
|
17581
|
+
if (!existsSync22(contextPath)) {
|
|
17280
17582
|
return {
|
|
17281
17583
|
migrated: false,
|
|
17282
17584
|
entriesMigrated: 0,
|
|
@@ -17295,9 +17597,9 @@ async function migrateContextToKnowledge(directory, config) {
|
|
|
17295
17597
|
skippedReason: "empty-context"
|
|
17296
17598
|
};
|
|
17297
17599
|
}
|
|
17298
|
-
const rawEntries =
|
|
17600
|
+
const rawEntries = _internals30.parseContextMd(contextContent);
|
|
17299
17601
|
if (rawEntries.length === 0) {
|
|
17300
|
-
await
|
|
17602
|
+
await _internals30.writeSentinel(sentinelPath, 0, 0);
|
|
17301
17603
|
return {
|
|
17302
17604
|
migrated: true,
|
|
17303
17605
|
entriesMigrated: 0,
|
|
@@ -17308,10 +17610,10 @@ async function migrateContextToKnowledge(directory, config) {
|
|
|
17308
17610
|
const existing = await readKnowledge(knowledgePath);
|
|
17309
17611
|
let migrated = 0;
|
|
17310
17612
|
let dropped = 0;
|
|
17311
|
-
const projectName =
|
|
17613
|
+
const projectName = _internals30.inferProjectName(directory);
|
|
17312
17614
|
for (const raw of rawEntries) {
|
|
17313
17615
|
if (config.validation_enabled !== false) {
|
|
17314
|
-
const category = raw.categoryHint ??
|
|
17616
|
+
const category = raw.categoryHint ?? _internals30.inferCategoryFromText(raw.text);
|
|
17315
17617
|
const result = validateLesson(raw.text, existing.map((e) => e.lesson), {
|
|
17316
17618
|
category,
|
|
17317
17619
|
scope: "global",
|
|
@@ -17331,8 +17633,8 @@ async function migrateContextToKnowledge(directory, config) {
|
|
|
17331
17633
|
const entry = {
|
|
17332
17634
|
id: randomUUID4(),
|
|
17333
17635
|
tier: "swarm",
|
|
17334
|
-
lesson:
|
|
17335
|
-
category: raw.categoryHint ??
|
|
17636
|
+
lesson: _internals30.truncateLesson(raw.text),
|
|
17637
|
+
category: raw.categoryHint ?? _internals30.inferCategoryFromText(raw.text),
|
|
17336
17638
|
tags: [...inferredTags, `migration:${raw.sourceSection}`],
|
|
17337
17639
|
scope: "global",
|
|
17338
17640
|
confidence: 0.3,
|
|
@@ -17355,7 +17657,7 @@ async function migrateContextToKnowledge(directory, config) {
|
|
|
17355
17657
|
if (migrated > 0) {
|
|
17356
17658
|
await rewriteKnowledge(knowledgePath, existing);
|
|
17357
17659
|
}
|
|
17358
|
-
await
|
|
17660
|
+
await _internals30.writeSentinel(sentinelPath, migrated, dropped);
|
|
17359
17661
|
log(`[knowledge-migrator] Migrated ${migrated} entries, dropped ${dropped}`);
|
|
17360
17662
|
return {
|
|
17361
17663
|
migrated: true,
|
|
@@ -17365,10 +17667,10 @@ async function migrateContextToKnowledge(directory, config) {
|
|
|
17365
17667
|
};
|
|
17366
17668
|
}
|
|
17367
17669
|
async function migrateHiveKnowledgeLegacy(config) {
|
|
17368
|
-
const legacyHivePath =
|
|
17670
|
+
const legacyHivePath = _internals30.resolveLegacyHiveKnowledgePath();
|
|
17369
17671
|
const canonicalHivePath = resolveHiveKnowledgePath();
|
|
17370
17672
|
const sentinelPath = path37.join(path37.dirname(canonicalHivePath), ".hive-knowledge-migrated");
|
|
17371
|
-
if (
|
|
17673
|
+
if (existsSync22(sentinelPath)) {
|
|
17372
17674
|
return {
|
|
17373
17675
|
migrated: false,
|
|
17374
17676
|
entriesMigrated: 0,
|
|
@@ -17377,7 +17679,7 @@ async function migrateHiveKnowledgeLegacy(config) {
|
|
|
17377
17679
|
skippedReason: "sentinel-exists"
|
|
17378
17680
|
};
|
|
17379
17681
|
}
|
|
17380
|
-
if (!
|
|
17682
|
+
if (!existsSync22(legacyHivePath)) {
|
|
17381
17683
|
return {
|
|
17382
17684
|
migrated: false,
|
|
17383
17685
|
entriesMigrated: 0,
|
|
@@ -17388,7 +17690,7 @@ async function migrateHiveKnowledgeLegacy(config) {
|
|
|
17388
17690
|
}
|
|
17389
17691
|
const legacyEntries = await readKnowledge(legacyHivePath);
|
|
17390
17692
|
if (legacyEntries.length === 0) {
|
|
17391
|
-
await
|
|
17693
|
+
await _internals30.writeSentinel(sentinelPath, 0, 0);
|
|
17392
17694
|
return {
|
|
17393
17695
|
migrated: true,
|
|
17394
17696
|
entriesMigrated: 0,
|
|
@@ -17436,7 +17738,7 @@ async function migrateHiveKnowledgeLegacy(config) {
|
|
|
17436
17738
|
const newHiveEntry = {
|
|
17437
17739
|
id: resolvedId,
|
|
17438
17740
|
tier: "hive",
|
|
17439
|
-
lesson:
|
|
17741
|
+
lesson: _internals30.truncateLesson(lesson),
|
|
17440
17742
|
category,
|
|
17441
17743
|
tags: ["migration:legacy-hive"],
|
|
17442
17744
|
scope: scopeTag,
|
|
@@ -17455,7 +17757,7 @@ async function migrateHiveKnowledgeLegacy(config) {
|
|
|
17455
17757
|
encounter_score: 1
|
|
17456
17758
|
};
|
|
17457
17759
|
try {
|
|
17458
|
-
await
|
|
17760
|
+
await _internals30.appendKnowledge(canonicalHivePath, newHiveEntry);
|
|
17459
17761
|
existingHiveEntries.push(newHiveEntry);
|
|
17460
17762
|
migrated++;
|
|
17461
17763
|
} catch (appendError) {
|
|
@@ -17471,7 +17773,7 @@ async function migrateHiveKnowledgeLegacy(config) {
|
|
|
17471
17773
|
dropped++;
|
|
17472
17774
|
}
|
|
17473
17775
|
}
|
|
17474
|
-
await
|
|
17776
|
+
await _internals30.writeSentinel(sentinelPath, migrated, dropped);
|
|
17475
17777
|
log(`[knowledge-migrator] Migrated ${migrated} legacy hive entries, dropped ${dropped}`);
|
|
17476
17778
|
return {
|
|
17477
17779
|
migrated: true,
|
|
@@ -17482,7 +17784,7 @@ async function migrateHiveKnowledgeLegacy(config) {
|
|
|
17482
17784
|
};
|
|
17483
17785
|
}
|
|
17484
17786
|
function parseContextMd(content) {
|
|
17485
|
-
const sections =
|
|
17787
|
+
const sections = _internals30.splitIntoSections(content);
|
|
17486
17788
|
const entries = [];
|
|
17487
17789
|
const seen = new Set;
|
|
17488
17790
|
const sectionPatterns = [
|
|
@@ -17498,7 +17800,7 @@ function parseContextMd(content) {
|
|
|
17498
17800
|
const match = sectionPatterns.find((sp) => sp.pattern.test(section.heading));
|
|
17499
17801
|
if (!match)
|
|
17500
17802
|
continue;
|
|
17501
|
-
const bullets =
|
|
17803
|
+
const bullets = _internals30.extractBullets(section.body);
|
|
17502
17804
|
for (const bullet of bullets) {
|
|
17503
17805
|
if (bullet.length < 15)
|
|
17504
17806
|
continue;
|
|
@@ -17507,9 +17809,9 @@ function parseContextMd(content) {
|
|
|
17507
17809
|
continue;
|
|
17508
17810
|
seen.add(normalized);
|
|
17509
17811
|
entries.push({
|
|
17510
|
-
text:
|
|
17812
|
+
text: _internals30.truncateLesson(bullet),
|
|
17511
17813
|
sourceSection: match.sourceSection,
|
|
17512
|
-
categoryHint:
|
|
17814
|
+
categoryHint: _internals30.inferCategoryFromText(bullet)
|
|
17513
17815
|
});
|
|
17514
17816
|
}
|
|
17515
17817
|
}
|
|
@@ -17579,7 +17881,7 @@ function truncateLesson2(text) {
|
|
|
17579
17881
|
}
|
|
17580
17882
|
function inferProjectName(directory) {
|
|
17581
17883
|
const packageJsonPath = path37.join(directory, "package.json");
|
|
17582
|
-
if (
|
|
17884
|
+
if (existsSync22(packageJsonPath)) {
|
|
17583
17885
|
try {
|
|
17584
17886
|
const pkg = JSON.parse(readFileSync14(packageJsonPath, "utf-8"));
|
|
17585
17887
|
if (pkg.name && typeof pkg.name === "string") {
|
|
@@ -17856,7 +18158,7 @@ function timeoutMessage(timeoutMs) {
|
|
|
17856
18158
|
async function computeWithTimeout(directory, currentPhase, timeoutMs) {
|
|
17857
18159
|
const controller = new AbortController;
|
|
17858
18160
|
let timeout;
|
|
17859
|
-
const metricsPromise =
|
|
18161
|
+
const metricsPromise = _internals31.computeLearningMetrics(directory, {
|
|
17860
18162
|
currentPhase,
|
|
17861
18163
|
signal: controller.signal
|
|
17862
18164
|
});
|
|
@@ -17913,7 +18215,7 @@ ${JSON.stringify({
|
|
|
17913
18215
|
return `Error computing learning metrics: ${message}. Run /swarm diagnose to check .swarm/ health.`;
|
|
17914
18216
|
}
|
|
17915
18217
|
}
|
|
17916
|
-
var
|
|
18218
|
+
var _internals31 = {
|
|
17917
18219
|
computeLearningMetrics
|
|
17918
18220
|
};
|
|
17919
18221
|
|
|
@@ -18032,7 +18334,7 @@ ${USAGE7}`;
|
|
|
18032
18334
|
}
|
|
18033
18335
|
|
|
18034
18336
|
// src/commands/memory.ts
|
|
18035
|
-
import { existsSync as
|
|
18337
|
+
import { existsSync as existsSync25 } from "fs";
|
|
18036
18338
|
import * as path42 from "path";
|
|
18037
18339
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
18038
18340
|
|
|
@@ -18130,7 +18432,7 @@ import * as path41 from "path";
|
|
|
18130
18432
|
|
|
18131
18433
|
// src/memory/local-jsonl-provider.ts
|
|
18132
18434
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
18133
|
-
import { existsSync as
|
|
18435
|
+
import { existsSync as existsSync23 } from "fs";
|
|
18134
18436
|
import {
|
|
18135
18437
|
appendFile as appendFile3,
|
|
18136
18438
|
mkdir as mkdir10,
|
|
@@ -19297,7 +19599,7 @@ function validateLoadedProposals(values, config) {
|
|
|
19297
19599
|
return { records, invalidCount };
|
|
19298
19600
|
}
|
|
19299
19601
|
async function readJsonl(filePath) {
|
|
19300
|
-
if (!
|
|
19602
|
+
if (!existsSync23(filePath))
|
|
19301
19603
|
return [];
|
|
19302
19604
|
const content = await readFile12(filePath, "utf-8");
|
|
19303
19605
|
const records = [];
|
|
@@ -19374,7 +19676,7 @@ import { createRequire as createRequire2 } from "module";
|
|
|
19374
19676
|
import * as path40 from "path";
|
|
19375
19677
|
|
|
19376
19678
|
// src/memory/jsonl-migration.ts
|
|
19377
|
-
import { existsSync as
|
|
19679
|
+
import { existsSync as existsSync24, renameSync as renameSync10, unlinkSync as unlinkSync6 } from "fs";
|
|
19378
19680
|
import { copyFile as copyFile2, mkdir as mkdir11, readFile as readFile13, stat as stat5, writeFile as writeFile11 } from "fs/promises";
|
|
19379
19681
|
import * as path39 from "path";
|
|
19380
19682
|
var LEGACY_JSONL_MIGRATION_VERSION = 2;
|
|
@@ -19408,10 +19710,10 @@ async function backupLegacyJsonl(rootDirectory, config = {}) {
|
|
|
19408
19710
|
const results = [];
|
|
19409
19711
|
for (const filename of ["memories.jsonl", "proposals.jsonl"]) {
|
|
19410
19712
|
const source = path39.join(storageDir, filename);
|
|
19411
|
-
if (!
|
|
19713
|
+
if (!existsSync24(source))
|
|
19412
19714
|
continue;
|
|
19413
19715
|
const backup = path39.join(backupDir, `${filename}.pre-sqlite-migration`);
|
|
19414
|
-
if (
|
|
19716
|
+
if (existsSync24(backup)) {
|
|
19415
19717
|
results.push({ source, backup, created: false });
|
|
19416
19718
|
continue;
|
|
19417
19719
|
}
|
|
@@ -19425,20 +19727,47 @@ async function writeJsonlExport(rootDirectory, config, memories, proposals) {
|
|
|
19425
19727
|
await mkdir11(exportDir, { recursive: true });
|
|
19426
19728
|
const memoriesPath = path39.join(exportDir, "memories.jsonl");
|
|
19427
19729
|
const proposalsPath = path39.join(exportDir, "proposals.jsonl");
|
|
19428
|
-
|
|
19429
|
-
|
|
19730
|
+
const memoriesTempPath = path39.join(path39.dirname(memoriesPath), `${path39.basename(memoriesPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
|
|
19731
|
+
try {
|
|
19732
|
+
await writeFile11(memoriesTempPath, toJsonl(memories), "utf-8");
|
|
19733
|
+
renameSync10(memoriesTempPath, memoriesPath);
|
|
19734
|
+
} catch (err) {
|
|
19735
|
+
try {
|
|
19736
|
+
unlinkSync6(memoriesTempPath);
|
|
19737
|
+
} catch {}
|
|
19738
|
+
throw err;
|
|
19739
|
+
}
|
|
19740
|
+
const proposalsTempPath = path39.join(path39.dirname(proposalsPath), `${path39.basename(proposalsPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
|
|
19741
|
+
try {
|
|
19742
|
+
await writeFile11(proposalsTempPath, toJsonl(proposals), "utf-8");
|
|
19743
|
+
renameSync10(proposalsTempPath, proposalsPath);
|
|
19744
|
+
} catch (err) {
|
|
19745
|
+
try {
|
|
19746
|
+
unlinkSync6(proposalsTempPath);
|
|
19747
|
+
} catch {}
|
|
19748
|
+
throw err;
|
|
19749
|
+
}
|
|
19430
19750
|
return { directory: exportDir, memoriesPath, proposalsPath };
|
|
19431
19751
|
}
|
|
19432
19752
|
async function writeMigrationReport(rootDirectory, report, config = {}) {
|
|
19433
19753
|
const reportPath = path39.join(resolveMemoryStorageDir(rootDirectory, config), "migration-report.json");
|
|
19434
19754
|
await mkdir11(path39.dirname(reportPath), { recursive: true });
|
|
19435
|
-
|
|
19755
|
+
const reportTempPath = path39.join(path39.dirname(reportPath), `${path39.basename(reportPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
|
|
19756
|
+
try {
|
|
19757
|
+
await writeFile11(reportTempPath, `${JSON.stringify(report, null, 2)}
|
|
19436
19758
|
`, "utf-8");
|
|
19759
|
+
renameSync10(reportTempPath, reportPath);
|
|
19760
|
+
} catch (err) {
|
|
19761
|
+
try {
|
|
19762
|
+
unlinkSync6(reportTempPath);
|
|
19763
|
+
} catch {}
|
|
19764
|
+
throw err;
|
|
19765
|
+
}
|
|
19437
19766
|
return reportPath;
|
|
19438
19767
|
}
|
|
19439
19768
|
async function readMigrationReport(rootDirectory, config = {}) {
|
|
19440
19769
|
const reportPath = path39.join(resolveMemoryStorageDir(rootDirectory, config), "migration-report.json");
|
|
19441
|
-
if (!
|
|
19770
|
+
if (!existsSync24(reportPath))
|
|
19442
19771
|
return null;
|
|
19443
19772
|
try {
|
|
19444
19773
|
return JSON.parse(await readFile13(reportPath, "utf-8"));
|
|
@@ -19452,13 +19781,13 @@ async function getLegacyJsonlFileStatus(rootDirectory, config = {}) {
|
|
|
19452
19781
|
for (const file of ["memories.jsonl", "proposals.jsonl"]) {
|
|
19453
19782
|
const filePath = path39.join(storageDir, file);
|
|
19454
19783
|
let sizeBytes = 0;
|
|
19455
|
-
if (
|
|
19784
|
+
if (existsSync24(filePath)) {
|
|
19456
19785
|
sizeBytes = (await stat5(filePath)).size;
|
|
19457
19786
|
}
|
|
19458
19787
|
statuses.push({
|
|
19459
19788
|
file,
|
|
19460
19789
|
path: filePath,
|
|
19461
|
-
exists:
|
|
19790
|
+
exists: existsSync24(filePath),
|
|
19462
19791
|
sizeBytes
|
|
19463
19792
|
});
|
|
19464
19793
|
}
|
|
@@ -19539,7 +19868,7 @@ async function readProposalJsonl(filePath, config) {
|
|
|
19539
19868
|
return { records, invalidRows, totalRows: rows.totalRows };
|
|
19540
19869
|
}
|
|
19541
19870
|
async function readJsonlRows(filePath) {
|
|
19542
|
-
if (!
|
|
19871
|
+
if (!existsSync24(filePath)) {
|
|
19543
19872
|
return { rows: [], invalidRows: [], totalRows: 0 };
|
|
19544
19873
|
}
|
|
19545
19874
|
const content = await readFile13(filePath, "utf-8");
|
|
@@ -20929,7 +21258,7 @@ async function handleMemoryStatusCommand(directory, _args) {
|
|
|
20929
21258
|
`- Provider: \`${config.provider}\``,
|
|
20930
21259
|
`- Storage: \`${storageDir}\``,
|
|
20931
21260
|
`- SQLite path: \`${sqlitePath}\``,
|
|
20932
|
-
`- SQLite database exists: \`${
|
|
21261
|
+
`- SQLite database exists: \`${existsSync25(sqlitePath)}\``,
|
|
20933
21262
|
`- Automatic destructive cleanup: \`disabled\``,
|
|
20934
21263
|
"",
|
|
20935
21264
|
"### Legacy JSONL"
|
|
@@ -21349,15 +21678,15 @@ function truncate(value, maxLength) {
|
|
|
21349
21678
|
}
|
|
21350
21679
|
|
|
21351
21680
|
// src/services/plan-service.ts
|
|
21352
|
-
var
|
|
21681
|
+
var _internals32 = {
|
|
21353
21682
|
loadPlanJsonOnly,
|
|
21354
21683
|
derivePlanMarkdown,
|
|
21355
21684
|
readSwarmFileAsync
|
|
21356
21685
|
};
|
|
21357
21686
|
async function getPlanData(directory, phaseArg) {
|
|
21358
|
-
const plan = await
|
|
21687
|
+
const plan = await _internals32.loadPlanJsonOnly(directory);
|
|
21359
21688
|
if (plan) {
|
|
21360
|
-
const fullMarkdown =
|
|
21689
|
+
const fullMarkdown = _internals32.derivePlanMarkdown(plan);
|
|
21361
21690
|
if (phaseArg === undefined || phaseArg === null || phaseArg === "") {
|
|
21362
21691
|
return {
|
|
21363
21692
|
hasPlan: true,
|
|
@@ -21400,7 +21729,7 @@ async function getPlanData(directory, phaseArg) {
|
|
|
21400
21729
|
isLegacy: false
|
|
21401
21730
|
};
|
|
21402
21731
|
}
|
|
21403
|
-
const planContent = await
|
|
21732
|
+
const planContent = await _internals32.readSwarmFileAsync(directory, "plan.md");
|
|
21404
21733
|
if (!planContent) {
|
|
21405
21734
|
return {
|
|
21406
21735
|
hasPlan: false,
|
|
@@ -21497,7 +21826,7 @@ async function handlePlanCommand(directory, args) {
|
|
|
21497
21826
|
return formatPlanMarkdown(planData);
|
|
21498
21827
|
}
|
|
21499
21828
|
// src/commands/post-mortem.ts
|
|
21500
|
-
var
|
|
21829
|
+
var _internals33 = {
|
|
21501
21830
|
createCuratorLLMDelegate,
|
|
21502
21831
|
runCuratorPostMortem
|
|
21503
21832
|
};
|
|
@@ -21509,10 +21838,10 @@ async function handlePostMortemCommand(directory, args, options) {
|
|
|
21509
21838
|
};
|
|
21510
21839
|
if (options?.sessionID) {
|
|
21511
21840
|
try {
|
|
21512
|
-
pmOptions.llmDelegate =
|
|
21841
|
+
pmOptions.llmDelegate = _internals33.createCuratorLLMDelegate(directory, "postmortem", options.sessionID);
|
|
21513
21842
|
} catch {}
|
|
21514
21843
|
}
|
|
21515
|
-
const result = await
|
|
21844
|
+
const result = await _internals33.runCuratorPostMortem(directory, pmOptions);
|
|
21516
21845
|
const lines = [];
|
|
21517
21846
|
if (result.success) {
|
|
21518
21847
|
lines.push("## Post-Mortem Report Generated");
|
|
@@ -21667,12 +21996,12 @@ function formatRelativeTime(epochMs) {
|
|
|
21667
21996
|
const diffDays = Math.floor(diffHours / 24);
|
|
21668
21997
|
return `${diffDays} day${diffDays === 1 ? "" : "s"} ago`;
|
|
21669
21998
|
}
|
|
21670
|
-
var
|
|
21999
|
+
var _internals34 = {
|
|
21671
22000
|
formatRelativeTime,
|
|
21672
22001
|
listActive
|
|
21673
22002
|
};
|
|
21674
22003
|
async function handlePrMonitorStatusCommand(directory, _args, sessionID) {
|
|
21675
|
-
const allActive = await
|
|
22004
|
+
const allActive = await _internals34.listActive(directory);
|
|
21676
22005
|
const sessionSubs = allActive.filter((record) => record.sessionID === sessionID);
|
|
21677
22006
|
if (sessionSubs.length === 0) {
|
|
21678
22007
|
return "No active PR subscriptions for this session.";
|
|
@@ -21797,7 +22126,7 @@ async function handlePrSubscribeCommand(directory, args, sessionID) {
|
|
|
21797
22126
|
const repoFullName = `${prInfo.owner}/${prInfo.repo}`;
|
|
21798
22127
|
const prUrl = `https://github.com/${prInfo.owner}/${prInfo.repo}/pull/${prInfo.number}`;
|
|
21799
22128
|
try {
|
|
21800
|
-
const config =
|
|
22129
|
+
const config = _internals35.loadPluginConfig(directory);
|
|
21801
22130
|
const prMonitorConfig = config.pr_monitor;
|
|
21802
22131
|
if (!prMonitorConfig?.enabled) {
|
|
21803
22132
|
return [
|
|
@@ -21807,7 +22136,7 @@ async function handlePrSubscribeCommand(directory, args, sessionID) {
|
|
|
21807
22136
|
].join(`
|
|
21808
22137
|
`);
|
|
21809
22138
|
}
|
|
21810
|
-
await
|
|
22139
|
+
await _internals35.subscribe(directory, {
|
|
21811
22140
|
sessionID,
|
|
21812
22141
|
prNumber: prInfo.number,
|
|
21813
22142
|
repoFullName,
|
|
@@ -21831,7 +22160,7 @@ async function handlePrSubscribeCommand(directory, args, sessionID) {
|
|
|
21831
22160
|
`);
|
|
21832
22161
|
}
|
|
21833
22162
|
}
|
|
21834
|
-
var
|
|
22163
|
+
var _internals35 = {
|
|
21835
22164
|
loadPluginConfig,
|
|
21836
22165
|
subscribe
|
|
21837
22166
|
};
|
|
@@ -21854,9 +22183,9 @@ async function handlePrUnsubscribeCommand(directory, args, sessionID) {
|
|
|
21854
22183
|
`);
|
|
21855
22184
|
}
|
|
21856
22185
|
const refToken = rest[0];
|
|
21857
|
-
const prInfo =
|
|
22186
|
+
const prInfo = _internals36.parsePrRef(refToken, directory);
|
|
21858
22187
|
if (!prInfo) {
|
|
21859
|
-
if (
|
|
22188
|
+
if (_internals36.looksLikePrRef(refToken)) {
|
|
21860
22189
|
return [
|
|
21861
22190
|
`Error: Could not resolve PR reference from "${refToken}".`,
|
|
21862
22191
|
"",
|
|
@@ -21877,8 +22206,8 @@ async function handlePrUnsubscribeCommand(directory, args, sessionID) {
|
|
|
21877
22206
|
const repoFullName = `${prInfo.owner}/${prInfo.repo}`;
|
|
21878
22207
|
const prUrl = `https://github.com/${prInfo.owner}/${prInfo.repo}/pull/${prInfo.number}`;
|
|
21879
22208
|
try {
|
|
21880
|
-
const correlationId =
|
|
21881
|
-
const result = await
|
|
22209
|
+
const correlationId = _internals36.buildCorrelationId(sessionID, repoFullName, prInfo.number);
|
|
22210
|
+
const result = await _internals36.unsubscribe(directory, correlationId);
|
|
21882
22211
|
if (!result) {
|
|
21883
22212
|
return [
|
|
21884
22213
|
`Not subscribed to ${prUrl}`,
|
|
@@ -21905,7 +22234,7 @@ async function handlePrUnsubscribeCommand(directory, args, sessionID) {
|
|
|
21905
22234
|
`);
|
|
21906
22235
|
}
|
|
21907
22236
|
}
|
|
21908
|
-
var
|
|
22237
|
+
var _internals36 = {
|
|
21909
22238
|
unsubscribe,
|
|
21910
22239
|
buildCorrelationId,
|
|
21911
22240
|
parsePrRef,
|
|
@@ -22339,15 +22668,15 @@ var lint = createSwarmTool({
|
|
|
22339
22668
|
}
|
|
22340
22669
|
const { mode } = args;
|
|
22341
22670
|
const cwd = directory;
|
|
22342
|
-
const linter = await
|
|
22671
|
+
const linter = await _internals37.detectAvailableLinter(directory);
|
|
22343
22672
|
if (linter) {
|
|
22344
|
-
const result = await
|
|
22673
|
+
const result = await _internals37.runLint(linter, mode, directory);
|
|
22345
22674
|
return JSON.stringify(result, null, 2);
|
|
22346
22675
|
}
|
|
22347
|
-
const additionalLinter =
|
|
22676
|
+
const additionalLinter = _internals37.detectAdditionalLinter(cwd);
|
|
22348
22677
|
if (additionalLinter) {
|
|
22349
22678
|
warn(`[lint] Using ${additionalLinter} linter for this project`);
|
|
22350
|
-
const result = await
|
|
22679
|
+
const result = await _internals37.runAdditionalLint(additionalLinter, mode, cwd);
|
|
22351
22680
|
return JSON.stringify(result, null, 2);
|
|
22352
22681
|
}
|
|
22353
22682
|
const errorResult = {
|
|
@@ -22361,7 +22690,7 @@ For Rust: rustup component add clippy`
|
|
|
22361
22690
|
return JSON.stringify(errorResult, null, 2);
|
|
22362
22691
|
}
|
|
22363
22692
|
});
|
|
22364
|
-
var
|
|
22693
|
+
var _internals37 = {
|
|
22365
22694
|
detectAvailableLinter,
|
|
22366
22695
|
runLint,
|
|
22367
22696
|
detectAdditionalLinter,
|
|
@@ -23049,7 +23378,7 @@ var secretscan = createSwarmTool({
|
|
|
23049
23378
|
});
|
|
23050
23379
|
async function runSecretscan(directory) {
|
|
23051
23380
|
try {
|
|
23052
|
-
const result = await
|
|
23381
|
+
const result = await _internals38.secretscan.execute({ directory }, {});
|
|
23053
23382
|
const jsonStr = typeof result === "string" ? result : result.output;
|
|
23054
23383
|
return JSON.parse(jsonStr);
|
|
23055
23384
|
} catch (e) {
|
|
@@ -23064,7 +23393,7 @@ async function runSecretscan(directory) {
|
|
|
23064
23393
|
return errorResult;
|
|
23065
23394
|
}
|
|
23066
23395
|
}
|
|
23067
|
-
var
|
|
23396
|
+
var _internals38 = {
|
|
23068
23397
|
secretscan,
|
|
23069
23398
|
runSecretscan
|
|
23070
23399
|
};
|
|
@@ -23337,7 +23666,7 @@ async function buildImpactMapInternal(cwd) {
|
|
|
23337
23666
|
}
|
|
23338
23667
|
return impactMap;
|
|
23339
23668
|
}
|
|
23340
|
-
var
|
|
23669
|
+
var _internals39 = {
|
|
23341
23670
|
validateProjectRoot,
|
|
23342
23671
|
normalizePath: normalizePath2,
|
|
23343
23672
|
isCacheStale,
|
|
@@ -23352,8 +23681,8 @@ var _internals38 = {
|
|
|
23352
23681
|
_clearGoModuleCache
|
|
23353
23682
|
};
|
|
23354
23683
|
async function buildImpactMap(cwd) {
|
|
23355
|
-
const impactMap = await
|
|
23356
|
-
await
|
|
23684
|
+
const impactMap = await _internals39.buildImpactMapInternal(cwd);
|
|
23685
|
+
await _internals39.saveImpactMap(cwd, impactMap);
|
|
23357
23686
|
return impactMap;
|
|
23358
23687
|
}
|
|
23359
23688
|
async function loadImpactMap(cwd, options) {
|
|
@@ -23367,7 +23696,7 @@ async function loadImpactMap(cwd, options) {
|
|
|
23367
23696
|
const hasValidValues = Object.values(map).every((v) => Array.isArray(v) && v.every((item) => typeof item === "string"));
|
|
23368
23697
|
if (hasValidValues) {
|
|
23369
23698
|
const generatedAt = new Date(data.generatedAt).getTime();
|
|
23370
|
-
if (!
|
|
23699
|
+
if (!_internals39.isCacheStale(map, generatedAt)) {
|
|
23371
23700
|
return map;
|
|
23372
23701
|
}
|
|
23373
23702
|
if (options?.skipRebuild) {
|
|
@@ -23387,13 +23716,13 @@ async function loadImpactMap(cwd, options) {
|
|
|
23387
23716
|
if (options?.skipRebuild) {
|
|
23388
23717
|
return {};
|
|
23389
23718
|
}
|
|
23390
|
-
return
|
|
23719
|
+
return _internals39.buildImpactMap(cwd);
|
|
23391
23720
|
}
|
|
23392
23721
|
async function saveImpactMap(cwd, impactMap) {
|
|
23393
23722
|
if (!path45.isAbsolute(cwd)) {
|
|
23394
23723
|
throw new Error(`saveImpactMap requires an absolute project root path, got: "${cwd}"`);
|
|
23395
23724
|
}
|
|
23396
|
-
|
|
23725
|
+
_internals39.validateProjectRoot(cwd);
|
|
23397
23726
|
const cacheDir2 = path45.join(cwd, ".swarm", "cache");
|
|
23398
23727
|
const cachePath = path45.join(cacheDir2, "impact-map.json");
|
|
23399
23728
|
if (!fs20.existsSync(cacheDir2)) {
|
|
@@ -23417,7 +23746,7 @@ async function analyzeImpact(changedFiles, cwd, budget) {
|
|
|
23417
23746
|
};
|
|
23418
23747
|
}
|
|
23419
23748
|
const validFiles = changedFiles.filter((f) => typeof f === "string" && f.length > 0 && !f.includes("\x00"));
|
|
23420
|
-
const impactMap = await
|
|
23749
|
+
const impactMap = await _internals39.loadImpactMap(cwd);
|
|
23421
23750
|
const impactedTestsSet = new Set;
|
|
23422
23751
|
const untestedFiles = [];
|
|
23423
23752
|
let visitedCount = 0;
|
|
@@ -23882,7 +24211,7 @@ function batchAppendTestRuns(records, workingDir) {
|
|
|
23882
24211
|
}
|
|
23883
24212
|
const historyPath = getHistoryPath(workingDir);
|
|
23884
24213
|
const historyDir = path46.dirname(historyPath);
|
|
23885
|
-
|
|
24214
|
+
_internals40.validateProjectRoot(workingDir);
|
|
23886
24215
|
if (!fs21.existsSync(historyDir)) {
|
|
23887
24216
|
fs21.mkdirSync(historyDir, { recursive: true });
|
|
23888
24217
|
}
|
|
@@ -24005,7 +24334,7 @@ function getAllHistory(workingDir) {
|
|
|
24005
24334
|
records.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
|
|
24006
24335
|
return records;
|
|
24007
24336
|
}
|
|
24008
|
-
var
|
|
24337
|
+
var _internals40 = {
|
|
24009
24338
|
validateProjectRoot
|
|
24010
24339
|
};
|
|
24011
24340
|
|
|
@@ -24477,19 +24806,19 @@ function hasCompoundTestExtension(filename) {
|
|
|
24477
24806
|
const lower = filename.toLowerCase();
|
|
24478
24807
|
return COMPOUND_TEST_EXTENSIONS.some((ext) => lower.endsWith(ext));
|
|
24479
24808
|
}
|
|
24480
|
-
function isLanguageSpecificTestFile(
|
|
24481
|
-
const lower =
|
|
24809
|
+
function isLanguageSpecificTestFile(basename9) {
|
|
24810
|
+
const lower = basename9.toLowerCase();
|
|
24482
24811
|
if (lower.endsWith("_test.go"))
|
|
24483
24812
|
return true;
|
|
24484
24813
|
if (lower.endsWith(".py") && (lower.startsWith("test_") || lower.endsWith("_test.py")))
|
|
24485
24814
|
return true;
|
|
24486
24815
|
if (lower.endsWith("_spec.rb"))
|
|
24487
24816
|
return true;
|
|
24488
|
-
if (lower.endsWith(".java") && (/^Test[A-Z]/.test(
|
|
24817
|
+
if (lower.endsWith(".java") && (/^Test[A-Z]/.test(basename9) || basename9.endsWith("Test.java") || basename9.endsWith("Tests.java") || lower.endsWith("it.java")))
|
|
24489
24818
|
return true;
|
|
24490
24819
|
if (lower.endsWith(".cs") && (lower.endsWith("test.cs") || lower.endsWith("tests.cs")))
|
|
24491
24820
|
return true;
|
|
24492
|
-
if (lower.endsWith(".kt") && (/^Test[A-Z]/.test(
|
|
24821
|
+
if (lower.endsWith(".kt") && (/^Test[A-Z]/.test(basename9) || lower.endsWith("test.kt") || lower.endsWith("tests.kt")))
|
|
24493
24822
|
return true;
|
|
24494
24823
|
if (lower.endsWith(".tests.ps1"))
|
|
24495
24824
|
return true;
|
|
@@ -24497,23 +24826,23 @@ function isLanguageSpecificTestFile(basename8) {
|
|
|
24497
24826
|
}
|
|
24498
24827
|
function isConventionTestFilePath(filePath) {
|
|
24499
24828
|
const normalizedPath = filePath.replace(/\\/g, "/");
|
|
24500
|
-
const
|
|
24501
|
-
return hasCompoundTestExtension(
|
|
24829
|
+
const basename9 = path48.basename(filePath);
|
|
24830
|
+
return hasCompoundTestExtension(basename9) || basename9.includes(".spec.") || basename9.includes(".test.") || isLanguageSpecificTestFile(basename9) || isTestDirectoryPath(normalizedPath);
|
|
24502
24831
|
}
|
|
24503
24832
|
function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
|
|
24504
24833
|
const testFiles = [];
|
|
24505
24834
|
for (const file of sourceFiles) {
|
|
24506
24835
|
const absoluteFile = resolveWorkspacePath(file, workingDir);
|
|
24507
24836
|
const relativeFile = path48.relative(workingDir, absoluteFile);
|
|
24508
|
-
const
|
|
24837
|
+
const basename9 = path48.basename(absoluteFile);
|
|
24509
24838
|
const dirname23 = path48.dirname(absoluteFile);
|
|
24510
24839
|
const preferRelativeOutput = !path48.isAbsolute(file);
|
|
24511
24840
|
if (isConventionTestFilePath(relativeFile) || isConventionTestFilePath(file)) {
|
|
24512
24841
|
dedupePush(testFiles, toWorkspaceOutputPath(absoluteFile, workingDir, preferRelativeOutput));
|
|
24513
24842
|
continue;
|
|
24514
24843
|
}
|
|
24515
|
-
const nameWithoutExt =
|
|
24516
|
-
const ext = path48.extname(
|
|
24844
|
+
const nameWithoutExt = basename9.replace(/\.[^.]+$/, "");
|
|
24845
|
+
const ext = path48.extname(basename9);
|
|
24517
24846
|
const genericTestNames = [
|
|
24518
24847
|
`${nameWithoutExt}.spec${ext}`,
|
|
24519
24848
|
`${nameWithoutExt}.test${ext}`
|
|
@@ -24524,7 +24853,7 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
|
|
|
24524
24853
|
...languageSpecificTestNames
|
|
24525
24854
|
].map((candidateName) => path48.join(dirname23, candidateName));
|
|
24526
24855
|
const testDirectoryNames = [
|
|
24527
|
-
|
|
24856
|
+
basename9,
|
|
24528
24857
|
...genericTestNames,
|
|
24529
24858
|
...languageSpecificTestNames
|
|
24530
24859
|
];
|
|
@@ -25918,9 +26247,9 @@ function getVersionFileVersion(dir) {
|
|
|
25918
26247
|
async function runVersionCheck(dir, _timeoutMs) {
|
|
25919
26248
|
const startTime = Date.now();
|
|
25920
26249
|
try {
|
|
25921
|
-
const packageVersion =
|
|
25922
|
-
const changelogVersion =
|
|
25923
|
-
const versionFileVersion =
|
|
26250
|
+
const packageVersion = _internals41.getPackageVersion(dir);
|
|
26251
|
+
const changelogVersion = _internals41.getChangelogVersion(dir);
|
|
26252
|
+
const versionFileVersion = _internals41.getVersionFileVersion(dir);
|
|
25924
26253
|
const versions = [];
|
|
25925
26254
|
if (packageVersion)
|
|
25926
26255
|
versions.push(`package.json: ${packageVersion}`);
|
|
@@ -26284,7 +26613,7 @@ async function runPreflight(dir, phase, config) {
|
|
|
26284
26613
|
const reportId = `preflight-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
26285
26614
|
let validatedDir;
|
|
26286
26615
|
try {
|
|
26287
|
-
validatedDir =
|
|
26616
|
+
validatedDir = _internals41.validateDirectoryPath(dir);
|
|
26288
26617
|
} catch (error2) {
|
|
26289
26618
|
return {
|
|
26290
26619
|
id: reportId,
|
|
@@ -26304,7 +26633,7 @@ async function runPreflight(dir, phase, config) {
|
|
|
26304
26633
|
}
|
|
26305
26634
|
let validatedTimeout;
|
|
26306
26635
|
try {
|
|
26307
|
-
validatedTimeout =
|
|
26636
|
+
validatedTimeout = _internals41.validateTimeout(config?.checkTimeoutMs, DEFAULT_CONFIG.checkTimeoutMs);
|
|
26308
26637
|
} catch (error2) {
|
|
26309
26638
|
return {
|
|
26310
26639
|
id: reportId,
|
|
@@ -26345,12 +26674,12 @@ async function runPreflight(dir, phase, config) {
|
|
|
26345
26674
|
});
|
|
26346
26675
|
const checks = [];
|
|
26347
26676
|
log("[Preflight] Running lint check...");
|
|
26348
|
-
const lintResult = await
|
|
26677
|
+
const lintResult = await _internals41.runLintCheck(validatedDir, cfg.linter, cfg.checkTimeoutMs);
|
|
26349
26678
|
checks.push(lintResult);
|
|
26350
26679
|
log(`[Preflight] Lint check: ${lintResult.status} ${lintResult.message}`);
|
|
26351
26680
|
if (!cfg.skipTests) {
|
|
26352
26681
|
log("[Preflight] Running tests check...");
|
|
26353
|
-
const testsResult = await
|
|
26682
|
+
const testsResult = await _internals41.runTestsCheck(validatedDir, cfg.testScope, cfg.checkTimeoutMs);
|
|
26354
26683
|
checks.push(testsResult);
|
|
26355
26684
|
log(`[Preflight] Tests check: ${testsResult.status} ${testsResult.message}`);
|
|
26356
26685
|
} else {
|
|
@@ -26362,7 +26691,7 @@ async function runPreflight(dir, phase, config) {
|
|
|
26362
26691
|
}
|
|
26363
26692
|
if (!cfg.skipSecrets) {
|
|
26364
26693
|
log("[Preflight] Running secrets check...");
|
|
26365
|
-
const secretsResult = await
|
|
26694
|
+
const secretsResult = await _internals41.runSecretsCheck(validatedDir, cfg.checkTimeoutMs);
|
|
26366
26695
|
checks.push(secretsResult);
|
|
26367
26696
|
log(`[Preflight] Secrets check: ${secretsResult.status} ${secretsResult.message}`);
|
|
26368
26697
|
} else {
|
|
@@ -26374,7 +26703,7 @@ async function runPreflight(dir, phase, config) {
|
|
|
26374
26703
|
}
|
|
26375
26704
|
if (!cfg.skipEvidence) {
|
|
26376
26705
|
log("[Preflight] Running evidence check...");
|
|
26377
|
-
const evidenceResult = await
|
|
26706
|
+
const evidenceResult = await _internals41.runEvidenceCheck(validatedDir);
|
|
26378
26707
|
checks.push(evidenceResult);
|
|
26379
26708
|
log(`[Preflight] Evidence check: ${evidenceResult.status} ${evidenceResult.message}`);
|
|
26380
26709
|
} else {
|
|
@@ -26385,12 +26714,12 @@ async function runPreflight(dir, phase, config) {
|
|
|
26385
26714
|
});
|
|
26386
26715
|
}
|
|
26387
26716
|
log("[Preflight] Running requirement coverage check...");
|
|
26388
|
-
const reqCoverageResult = await
|
|
26717
|
+
const reqCoverageResult = await _internals41.runRequirementCoverageCheck(validatedDir, phase);
|
|
26389
26718
|
checks.push(reqCoverageResult);
|
|
26390
26719
|
log(`[Preflight] Requirement coverage check: ${reqCoverageResult.status} ${reqCoverageResult.message}`);
|
|
26391
26720
|
if (!cfg.skipVersion) {
|
|
26392
26721
|
log("[Preflight] Running version check...");
|
|
26393
|
-
const versionResult = await
|
|
26722
|
+
const versionResult = await _internals41.runVersionCheck(validatedDir, cfg.checkTimeoutMs);
|
|
26394
26723
|
checks.push(versionResult);
|
|
26395
26724
|
log(`[Preflight] Version check: ${versionResult.status} ${versionResult.message}`);
|
|
26396
26725
|
} else {
|
|
@@ -26453,10 +26782,10 @@ function formatPreflightMarkdown(report) {
|
|
|
26453
26782
|
async function handlePreflightCommand(directory, _args) {
|
|
26454
26783
|
const plan = await loadPlan(directory);
|
|
26455
26784
|
const phase = plan?.current_phase ?? 1;
|
|
26456
|
-
const report = await
|
|
26457
|
-
return
|
|
26785
|
+
const report = await _internals41.runPreflight(directory, phase);
|
|
26786
|
+
return _internals41.formatPreflightMarkdown(report);
|
|
26458
26787
|
}
|
|
26459
|
-
var
|
|
26788
|
+
var _internals41 = {
|
|
26460
26789
|
runPreflight,
|
|
26461
26790
|
formatPreflightMarkdown,
|
|
26462
26791
|
handlePreflightCommand,
|
|
@@ -27362,7 +27691,9 @@ async function handleResetCommand(directory, args) {
|
|
|
27362
27691
|
fs25.unlinkSync(rootPath);
|
|
27363
27692
|
results.push(`- \u2705 Deleted ${filename} (root)`);
|
|
27364
27693
|
}
|
|
27365
|
-
} catch {
|
|
27694
|
+
} catch (err) {
|
|
27695
|
+
results.push(`- \u274C Failed to delete ${filename}: ${err instanceof Error ? err.message : String(err)}`);
|
|
27696
|
+
}
|
|
27366
27697
|
}
|
|
27367
27698
|
try {
|
|
27368
27699
|
resetAutomationManager();
|
|
@@ -27857,7 +28188,7 @@ async function recordReplayEntry(artifactPath, sessionID, entry) {
|
|
|
27857
28188
|
}
|
|
27858
28189
|
|
|
27859
28190
|
// src/prm/index.ts
|
|
27860
|
-
var
|
|
28191
|
+
var _internals42 = {
|
|
27861
28192
|
getAgentSession,
|
|
27862
28193
|
readTrajectory,
|
|
27863
28194
|
getInMemoryTrajectory,
|
|
@@ -27880,11 +28211,16 @@ function resetPrmSessionState(session, sessionId) {
|
|
|
27880
28211
|
session.prmTrajectoryStep = 0;
|
|
27881
28212
|
session.replayArtifactPath = null;
|
|
27882
28213
|
if (sessionId) {
|
|
27883
|
-
|
|
28214
|
+
_internals42.clearTrajectoryCache(sessionId);
|
|
27884
28215
|
}
|
|
27885
28216
|
}
|
|
27886
28217
|
|
|
27887
28218
|
// src/commands/reset-session.ts
|
|
28219
|
+
function errorMessage(err) {
|
|
28220
|
+
if (err instanceof Error)
|
|
28221
|
+
return err.message;
|
|
28222
|
+
return String(err);
|
|
28223
|
+
}
|
|
27888
28224
|
async function handleResetSessionCommand(directory, _args) {
|
|
27889
28225
|
const results = [];
|
|
27890
28226
|
try {
|
|
@@ -27898,22 +28234,30 @@ async function handleResetSessionCommand(directory, _args) {
|
|
|
27898
28234
|
} catch {
|
|
27899
28235
|
results.push("\u274C Failed to delete state.json");
|
|
27900
28236
|
}
|
|
27901
|
-
|
|
27902
|
-
|
|
27903
|
-
|
|
27904
|
-
|
|
27905
|
-
|
|
27906
|
-
|
|
27907
|
-
|
|
27908
|
-
const filePath = path52.join(sessionDir, file);
|
|
27909
|
-
if (fs27.lstatSync(filePath).isFile()) {
|
|
27910
|
-
fs27.unlinkSync(filePath);
|
|
27911
|
-
deletedCount++;
|
|
27912
|
-
}
|
|
27913
|
-
}
|
|
27914
|
-
results.push(`\u2705 Cleaned ${deletedCount} additional session file(s)`);
|
|
28237
|
+
const sessionDir = path52.dirname(validateSwarmPath(directory, "session/state.json"));
|
|
28238
|
+
let sessionFiles = [];
|
|
28239
|
+
if (fs27.existsSync(sessionDir)) {
|
|
28240
|
+
try {
|
|
28241
|
+
sessionFiles = fs27.readdirSync(sessionDir);
|
|
28242
|
+
} catch (err) {
|
|
28243
|
+
results.push(`\u274C Failed to read session directory: ${errorMessage(err)}`);
|
|
27915
28244
|
}
|
|
27916
|
-
}
|
|
28245
|
+
}
|
|
28246
|
+
for (const file of sessionFiles) {
|
|
28247
|
+
if (file === "state.json")
|
|
28248
|
+
continue;
|
|
28249
|
+
const filePath = path52.join(sessionDir, file);
|
|
28250
|
+
try {
|
|
28251
|
+
if (!fs27.existsSync(filePath))
|
|
28252
|
+
continue;
|
|
28253
|
+
if (!fs27.lstatSync(filePath).isFile())
|
|
28254
|
+
continue;
|
|
28255
|
+
fs27.unlinkSync(filePath);
|
|
28256
|
+
results.push(`\u2713 Deleted ${file}`);
|
|
28257
|
+
} catch (err) {
|
|
28258
|
+
results.push(`\u274C Failed to delete ${file}: ${errorMessage(err)}`);
|
|
28259
|
+
}
|
|
28260
|
+
}
|
|
27917
28261
|
const sessionCount = swarmState.agentSessions.size;
|
|
27918
28262
|
for (const [sessionId, session] of swarmState.agentSessions) {
|
|
27919
28263
|
resetPrmSessionState(session, sessionId);
|
|
@@ -28075,6 +28419,7 @@ async function handleRollbackCommand(directory, args) {
|
|
|
28075
28419
|
]);
|
|
28076
28420
|
const successes = [];
|
|
28077
28421
|
const failures = [];
|
|
28422
|
+
const warnings = [];
|
|
28078
28423
|
for (const file of checkpointFiles) {
|
|
28079
28424
|
if (EXCLUDE_FILES.has(file) || file.startsWith("plan-ledger.archived-")) {
|
|
28080
28425
|
continue;
|
|
@@ -28100,30 +28445,39 @@ async function handleRollbackCommand(directory, args) {
|
|
|
28100
28445
|
`);
|
|
28101
28446
|
}
|
|
28102
28447
|
const existingLedgerPath = path54.join(swarmDir, "plan-ledger.jsonl");
|
|
28448
|
+
let ledgerDeletionFailed = false;
|
|
28103
28449
|
if (fs28.existsSync(existingLedgerPath)) {
|
|
28104
|
-
|
|
28105
|
-
|
|
28106
|
-
|
|
28107
|
-
|
|
28108
|
-
|
|
28109
|
-
|
|
28110
|
-
const plan = PlanSchema.parse(JSON.parse(planRaw));
|
|
28111
|
-
const planId = derivePlanId(plan);
|
|
28112
|
-
const planHash = computePlanHash(plan);
|
|
28113
|
-
await initLedger(directory, planId, planHash, plan);
|
|
28114
|
-
await appendLedgerEvent(directory, {
|
|
28115
|
-
event_type: "plan_rebuilt",
|
|
28116
|
-
source: "rollback",
|
|
28117
|
-
plan_id: planId
|
|
28118
|
-
});
|
|
28450
|
+
try {
|
|
28451
|
+
fs28.unlinkSync(existingLedgerPath);
|
|
28452
|
+
} catch (err) {
|
|
28453
|
+
ledgerDeletionFailed = true;
|
|
28454
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
28455
|
+
warnings.push(`\u26A0\uFE0F Warning: Could not delete stale ledger (${errMsg}). The ledger may be inconsistent with the restored plan. Run /swarm reset-session to clean up session state.`);
|
|
28119
28456
|
}
|
|
28120
|
-
}
|
|
28121
|
-
|
|
28122
|
-
|
|
28123
|
-
|
|
28124
|
-
|
|
28125
|
-
|
|
28457
|
+
}
|
|
28458
|
+
if (!ledgerDeletionFailed) {
|
|
28459
|
+
try {
|
|
28460
|
+
const planJsonPath = path54.join(swarmDir, "plan.json");
|
|
28461
|
+
if (fs28.existsSync(planJsonPath)) {
|
|
28462
|
+
const planRaw = fs28.readFileSync(planJsonPath, "utf-8");
|
|
28463
|
+
const plan = PlanSchema.parse(JSON.parse(planRaw));
|
|
28464
|
+
const planId = derivePlanId(plan);
|
|
28465
|
+
const planHash = computePlanHash(plan);
|
|
28466
|
+
await initLedger(directory, planId, planHash, plan);
|
|
28467
|
+
await appendLedgerEvent(directory, {
|
|
28468
|
+
event_type: "plan_rebuilt",
|
|
28469
|
+
source: "rollback",
|
|
28470
|
+
plan_id: planId
|
|
28471
|
+
});
|
|
28472
|
+
}
|
|
28473
|
+
} catch (initError) {
|
|
28474
|
+
return [
|
|
28475
|
+
`Rollback restored files but failed to initialize ledger: ${initError instanceof Error ? initError.message : String(initError)}`,
|
|
28476
|
+
"The .swarm/plan.json has been restored but the ledger may be out of sync.",
|
|
28477
|
+
"Run /swarm reset-session to reinitialize the ledger."
|
|
28478
|
+
].join(`
|
|
28126
28479
|
`);
|
|
28480
|
+
}
|
|
28127
28481
|
}
|
|
28128
28482
|
const eventsPath = validateSwarmPath(directory, "events.jsonl");
|
|
28129
28483
|
const rollbackEvent = {
|
|
@@ -28138,6 +28492,14 @@ async function handleRollbackCommand(directory, args) {
|
|
|
28138
28492
|
} catch (error2) {
|
|
28139
28493
|
console.error("Failed to write rollback event:", error2 instanceof Error ? error2.message : String(error2));
|
|
28140
28494
|
}
|
|
28495
|
+
if (warnings.length > 0) {
|
|
28496
|
+
return [
|
|
28497
|
+
...warnings,
|
|
28498
|
+
"",
|
|
28499
|
+
`Rolled back to phase ${targetPhase}: ${checkpoint2.label || "no label"}`
|
|
28500
|
+
].join(`
|
|
28501
|
+
`);
|
|
28502
|
+
}
|
|
28141
28503
|
return `Rolled back to phase ${targetPhase}: ${checkpoint2.label || "no label"}`;
|
|
28142
28504
|
}
|
|
28143
28505
|
|
|
@@ -28307,6 +28669,7 @@ async function handleSddCommand(_directory, _args) {
|
|
|
28307
28669
|
}
|
|
28308
28670
|
|
|
28309
28671
|
// src/commands/simulate.ts
|
|
28672
|
+
import { renameSync as renameSync11, unlinkSync as unlinkSync11 } from "fs";
|
|
28310
28673
|
async function handleSimulateCommand(directory, args) {
|
|
28311
28674
|
const thresholdIndex = args.indexOf("--threshold");
|
|
28312
28675
|
const minCommitsIndex = args.indexOf("--min-commits");
|
|
@@ -28325,7 +28688,7 @@ async function handleSimulateCommand(directory, args) {
|
|
|
28325
28688
|
}
|
|
28326
28689
|
let darkMatterPairs;
|
|
28327
28690
|
try {
|
|
28328
|
-
darkMatterPairs = await
|
|
28691
|
+
darkMatterPairs = await _internals21.detectDarkMatter(directory, options);
|
|
28329
28692
|
} catch (err) {
|
|
28330
28693
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
28331
28694
|
return `## Simulate Report
|
|
@@ -28358,7 +28721,16 @@ Ensure this is a git repository with commit history.`;
|
|
|
28358
28721
|
const path55 = await import("path");
|
|
28359
28722
|
const reportPath = path55.join(directory, ".swarm", "simulate-report.md");
|
|
28360
28723
|
await fs29.mkdir(path55.dirname(reportPath), { recursive: true });
|
|
28361
|
-
|
|
28724
|
+
const reportTempPath = path55.join(path55.dirname(reportPath), `${path55.basename(reportPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
|
|
28725
|
+
try {
|
|
28726
|
+
await fs29.writeFile(reportTempPath, report, "utf-8");
|
|
28727
|
+
renameSync11(reportTempPath, reportPath);
|
|
28728
|
+
} catch (err) {
|
|
28729
|
+
try {
|
|
28730
|
+
unlinkSync11(reportTempPath);
|
|
28731
|
+
} catch {}
|
|
28732
|
+
throw err;
|
|
28733
|
+
}
|
|
28362
28734
|
} catch (err) {
|
|
28363
28735
|
const writeErr = err instanceof Error ? err.message : String(err);
|
|
28364
28736
|
warn(`simulate: failed to write report to ${directory}/.swarm/simulate-report.md`, writeErr);
|
|
@@ -28581,7 +28953,7 @@ var DEFAULT_CONTEXT_BUDGET_CONFIG = {
|
|
|
28581
28953
|
};
|
|
28582
28954
|
|
|
28583
28955
|
// src/services/status-service.ts
|
|
28584
|
-
var
|
|
28956
|
+
var _internals43 = {
|
|
28585
28957
|
loadLeanTurboRunState,
|
|
28586
28958
|
hasActiveLeanTurbo,
|
|
28587
28959
|
hasActiveFullAuto
|
|
@@ -28686,7 +29058,7 @@ async function getStatusData(directory, agents) {
|
|
|
28686
29058
|
}
|
|
28687
29059
|
function enrichWithLeanTurbo(status, directory) {
|
|
28688
29060
|
const turboMode = hasActiveTurboMode();
|
|
28689
|
-
const leanActive =
|
|
29061
|
+
const leanActive = _internals43.hasActiveLeanTurbo();
|
|
28690
29062
|
let turboStrategy = "off";
|
|
28691
29063
|
if (leanActive) {
|
|
28692
29064
|
turboStrategy = "lean";
|
|
@@ -28705,7 +29077,7 @@ function enrichWithLeanTurbo(status, directory) {
|
|
|
28705
29077
|
}
|
|
28706
29078
|
}
|
|
28707
29079
|
if (leanSessionID) {
|
|
28708
|
-
const runState =
|
|
29080
|
+
const runState = _internals43.loadLeanTurboRunState(directory, leanSessionID);
|
|
28709
29081
|
if (runState) {
|
|
28710
29082
|
status.leanTurboPhase = runState.phase;
|
|
28711
29083
|
status.leanMaxParallelCoders = runState.maxParallelCoders;
|
|
@@ -28737,7 +29109,7 @@ function enrichWithLeanTurbo(status, directory) {
|
|
|
28737
29109
|
}
|
|
28738
29110
|
}
|
|
28739
29111
|
}
|
|
28740
|
-
status.fullAutoActive =
|
|
29112
|
+
status.fullAutoActive = _internals43.hasActiveFullAuto();
|
|
28741
29113
|
return status;
|
|
28742
29114
|
}
|
|
28743
29115
|
function formatStatusMarkdown(status) {
|
|
@@ -28891,7 +29263,7 @@ No active swarm plan found. Nothing to sync.`;
|
|
|
28891
29263
|
|
|
28892
29264
|
// src/commands/turbo.ts
|
|
28893
29265
|
init_logger();
|
|
28894
|
-
var
|
|
29266
|
+
var _internals44 = {
|
|
28895
29267
|
loadPluginConfigWithMeta
|
|
28896
29268
|
};
|
|
28897
29269
|
async function handleTurboCommand(directory, args, sessionID) {
|
|
@@ -28951,7 +29323,7 @@ async function handleTurboCommand(directory, args, sessionID) {
|
|
|
28951
29323
|
if (arg0 === "on") {
|
|
28952
29324
|
let strategy = "standard";
|
|
28953
29325
|
try {
|
|
28954
|
-
const { config } =
|
|
29326
|
+
const { config } = _internals44.loadPluginConfigWithMeta(directory);
|
|
28955
29327
|
if (config.turbo?.strategy === "lean") {
|
|
28956
29328
|
strategy = "lean";
|
|
28957
29329
|
}
|
|
@@ -29048,7 +29420,7 @@ function enableLeanTurbo(session, directory, sessionID) {
|
|
|
29048
29420
|
let maxParallelCoders = 4;
|
|
29049
29421
|
let conflictPolicy = "serialize";
|
|
29050
29422
|
try {
|
|
29051
|
-
const { config } =
|
|
29423
|
+
const { config } = _internals44.loadPluginConfigWithMeta(directory);
|
|
29052
29424
|
const leanConfig = config.turbo?.lean;
|
|
29053
29425
|
if (leanConfig) {
|
|
29054
29426
|
maxParallelCoders = leanConfig.max_parallel_coders ?? 4;
|
|
@@ -29204,7 +29576,7 @@ function findSimilarCommands(query) {
|
|
|
29204
29576
|
}
|
|
29205
29577
|
const scored = VALID_COMMANDS.map((cmd) => {
|
|
29206
29578
|
const cmdLower = cmd.toLowerCase();
|
|
29207
|
-
const fullScore =
|
|
29579
|
+
const fullScore = _internals45.levenshteinDistance(q, cmdLower);
|
|
29208
29580
|
let tokenScore = Infinity;
|
|
29209
29581
|
if (cmd.includes(" ") || cmd.includes("-")) {
|
|
29210
29582
|
const qTokens = q.split(/[\s-]+/);
|
|
@@ -29217,7 +29589,7 @@ function findSimilarCommands(query) {
|
|
|
29217
29589
|
for (const ct of cmdTokens) {
|
|
29218
29590
|
if (ct.length === 0)
|
|
29219
29591
|
continue;
|
|
29220
|
-
const dist =
|
|
29592
|
+
const dist = _internals45.levenshteinDistance(qt, ct);
|
|
29221
29593
|
if (dist < minDist)
|
|
29222
29594
|
minDist = dist;
|
|
29223
29595
|
}
|
|
@@ -29227,7 +29599,7 @@ function findSimilarCommands(query) {
|
|
|
29227
29599
|
}
|
|
29228
29600
|
const dashStrippedQ = q.replace(/-/g, "");
|
|
29229
29601
|
const dashStrippedCmd = cmdLower.replace(/-/g, "");
|
|
29230
|
-
const dashScore =
|
|
29602
|
+
const dashScore = _internals45.levenshteinDistance(dashStrippedQ, dashStrippedCmd);
|
|
29231
29603
|
const score = Math.min(fullScore, tokenScore, dashScore);
|
|
29232
29604
|
return { cmd, score };
|
|
29233
29605
|
});
|
|
@@ -29255,16 +29627,16 @@ function buildDetailedHelp(commandName, entry) {
|
|
|
29255
29627
|
async function handleHelpCommand(ctx) {
|
|
29256
29628
|
const targetCommand = ctx.args.join(" ");
|
|
29257
29629
|
if (!targetCommand) {
|
|
29258
|
-
const { buildHelpText } = await import("./index-
|
|
29630
|
+
const { buildHelpText } = await import("./index-r3f47swm.js");
|
|
29259
29631
|
return buildHelpText();
|
|
29260
29632
|
}
|
|
29261
29633
|
const tokens = targetCommand.split(/\s+/);
|
|
29262
|
-
const resolved =
|
|
29634
|
+
const resolved = _internals45.resolveCommand(tokens);
|
|
29263
29635
|
if (resolved) {
|
|
29264
|
-
return
|
|
29636
|
+
return _internals45.buildDetailedHelp(resolved.key, resolved.entry);
|
|
29265
29637
|
}
|
|
29266
|
-
const similar =
|
|
29267
|
-
const { buildHelpText: fullHelp } = await import("./index-
|
|
29638
|
+
const similar = _internals45.findSimilarCommands(targetCommand);
|
|
29639
|
+
const { buildHelpText: fullHelp } = await import("./index-r3f47swm.js");
|
|
29268
29640
|
if (similar.length > 0) {
|
|
29269
29641
|
return `Command '/swarm ${targetCommand}' not found.
|
|
29270
29642
|
|
|
@@ -29328,7 +29700,7 @@ var COMMAND_REGISTRY = {
|
|
|
29328
29700
|
toolNoArgs: true
|
|
29329
29701
|
},
|
|
29330
29702
|
help: {
|
|
29331
|
-
handler: (ctx) =>
|
|
29703
|
+
handler: (ctx) => _internals45.handleHelpCommand(ctx),
|
|
29332
29704
|
description: "Show help for swarm commands",
|
|
29333
29705
|
category: "core",
|
|
29334
29706
|
args: "[command]",
|
|
@@ -29397,7 +29769,7 @@ var COMMAND_REGISTRY = {
|
|
|
29397
29769
|
},
|
|
29398
29770
|
"guardrail explain": {
|
|
29399
29771
|
handler: async (ctx) => {
|
|
29400
|
-
const { handleGuardrailExplain } = await import("./guardrail-explain-
|
|
29772
|
+
const { handleGuardrailExplain } = await import("./guardrail-explain-2q9myk7c.js");
|
|
29401
29773
|
return handleGuardrailExplain(ctx.directory, ctx.args);
|
|
29402
29774
|
},
|
|
29403
29775
|
description: "Dry-run: show what the guardrails would do to a command or write target (executes nothing)",
|
|
@@ -30178,7 +30550,7 @@ function validateToolPolicy() {
|
|
|
30178
30550
|
}
|
|
30179
30551
|
return { valid: warnings.length === 0, warnings };
|
|
30180
30552
|
}
|
|
30181
|
-
var
|
|
30553
|
+
var _internals45 = {
|
|
30182
30554
|
handleHelpCommand,
|
|
30183
30555
|
validateAliases,
|
|
30184
30556
|
validateToolPolicy,
|
|
@@ -30187,7 +30559,7 @@ var _internals44 = {
|
|
|
30187
30559
|
findSimilarCommands,
|
|
30188
30560
|
buildDetailedHelp
|
|
30189
30561
|
};
|
|
30190
|
-
var validation =
|
|
30562
|
+
var validation = _internals45.validateAliases();
|
|
30191
30563
|
if (!validation.valid) {
|
|
30192
30564
|
throw new Error(`COMMAND_REGISTRY alias validation failed:
|
|
30193
30565
|
${validation.errors.join(`
|
|
@@ -30199,7 +30571,7 @@ ${validation.warnings.join(`
|
|
|
30199
30571
|
`)}`);
|
|
30200
30572
|
}
|
|
30201
30573
|
try {
|
|
30202
|
-
const toolPolicyValidation =
|
|
30574
|
+
const toolPolicyValidation = _internals45.validateToolPolicy();
|
|
30203
30575
|
if (toolPolicyValidation.warnings.length > 0) {
|
|
30204
30576
|
console.warn(`COMMAND_REGISTRY toolPolicy warnings:
|
|
30205
30577
|
${toolPolicyValidation.warnings.join(`
|
|
@@ -30263,7 +30635,7 @@ function formatCommandNotFound(tokens) {
|
|
|
30263
30635
|
const attemptedCommand = tokens[0] || "";
|
|
30264
30636
|
const MAX_DISPLAY = 100;
|
|
30265
30637
|
const displayCommand = attemptedCommand.length > MAX_DISPLAY ? `${attemptedCommand.slice(0, MAX_DISPLAY)}...` : attemptedCommand;
|
|
30266
|
-
const similar =
|
|
30638
|
+
const similar = _internals45.findSimilarCommands(attemptedCommand);
|
|
30267
30639
|
const header = `Command \`/swarm ${displayCommand}\` not found.`;
|
|
30268
30640
|
const suggestions = similar.length > 0 ? `Did you mean:
|
|
30269
30641
|
${similar.map((cmd) => ` - /swarm ${cmd}`).join(`
|
|
@@ -30320,4 +30692,4 @@ ${text}`;
|
|
|
30320
30692
|
};
|
|
30321
30693
|
}
|
|
30322
30694
|
|
|
30323
|
-
export { package_default, handleAcknowledgeSpecDriftCommand, handleAgentsCommand, handleAnalyzeCommand, handleArchiveCommand, DC_SAFE_TARGETS, dcNormalizeCommand, dcUnwrapWrappers, dcSplitSegments, dcValidateTargets, dcCheckJunctionCreation, dcExtractWindowsCmdTargets, dcExtractPowerShellTargets, normalizeSwarmCommandInput, canonicalCommandKey, formatCommandNotFound, executeSwarmCommand, SWARM_COMMAND_TOOL_COMMANDS, SWARM_COMMAND_TOOL_ALLOWLIST, HUMAN_ONLY_SWARM_COMMANDS, classifySwarmCommandToolUse, classifySwarmCommandChatFallbackUse, detectPosixWrites, detectWindowsWrites, resolveWriteTargets, handleAutoProceedCommand, handleBenchmarkCommand, handleBrainstormCommand, handleCheckpointCommand, handleClarifyCommand, handleCloseCommand, handleCodebaseReviewCommand, handleConcurrencyCommand, handleConfigCommand, handleConsolidateCommand, handleCouncilCommand, handleCurateCommand, handleDarkMatterCommand, handleDeepDiveCommand, handleDeepResearchCommand, getPluginConfigDir, getPluginCachePaths, getPluginLockFilePaths, handleDiagnoseCommand, handleDoctorCommand, handleEvidenceCommand, handleEvidenceSummaryCommand, handleExportCommand, handleFullAutoCommand, handleHandoffCommand, handleHistoryCommand, handleKnowledgeQuarantineCommand, handleKnowledgeRestoreCommand, handleKnowledgeMigrateCommand, handleKnowledgeListCommand, handleKnowledgeUnactionableCommand, handleKnowledgeRetryHardeningCommand, handleLearningCommand, handleMemoryCommand, handleMemoryStatusCommand, handleMemoryMigrateCommand, handleMemoryImportCommand, handleMemoryExportCommand, handlePlanCommand, handlePreflightCommand, handlePromoteCommand, handleQaGatesCommand, handleResetCommand, handleResetSessionCommand, handleRetrieveCommand, handleRollbackCommand, handleSddStatusCommand, handleSddValidateCommand, handleSddProjectCommand, handleSddCommand, handleSimulateCommand, handleSpecifyCommand, handleStatusCommand, handleSyncPlanCommand, handleTurboCommand, handleWriteRetroCommand, handleHelpCommand, COMMAND_REGISTRY, VALID_COMMANDS,
|
|
30695
|
+
export { package_default, handleAcknowledgeSpecDriftCommand, handleAgentsCommand, handleAnalyzeCommand, handleArchiveCommand, DC_SAFE_TARGETS, dcNormalizeCommand, dcUnwrapWrappers, dcSplitSegments, dcValidateTargets, dcCheckJunctionCreation, dcExtractWindowsCmdTargets, dcExtractPowerShellTargets, normalizeSwarmCommandInput, canonicalCommandKey, formatCommandNotFound, executeSwarmCommand, SWARM_COMMAND_TOOL_COMMANDS, SWARM_COMMAND_TOOL_ALLOWLIST, HUMAN_ONLY_SWARM_COMMANDS, classifySwarmCommandToolUse, classifySwarmCommandChatFallbackUse, detectPosixWrites, detectWindowsWrites, resolveWriteTargets, handleAutoProceedCommand, handleBenchmarkCommand, handleBrainstormCommand, handleCheckpointCommand, handleClarifyCommand, handleCloseCommand, handleCodebaseReviewCommand, handleConcurrencyCommand, handleConfigCommand, handleConsolidateCommand, handleCouncilCommand, handleCurateCommand, handleDarkMatterCommand, handleDeepDiveCommand, handleDeepResearchCommand, getPluginConfigDir, getPluginCachePaths, getPluginLockFilePaths, handleDiagnoseCommand, handleDoctorCommand, handleEvidenceCommand, handleEvidenceSummaryCommand, handleExportCommand, handleFullAutoCommand, handleHandoffCommand, handleHistoryCommand, handleKnowledgeQuarantineCommand, handleKnowledgeRestoreCommand, handleKnowledgeMigrateCommand, handleKnowledgeListCommand, handleKnowledgeUnactionableCommand, handleKnowledgeRetryHardeningCommand, handleLearningCommand, handleMemoryCommand, handleMemoryStatusCommand, handleMemoryMigrateCommand, handleMemoryImportCommand, handleMemoryExportCommand, handlePlanCommand, handlePreflightCommand, handlePromoteCommand, handleQaGatesCommand, handleResetCommand, handleResetSessionCommand, handleRetrieveCommand, handleRollbackCommand, handleSddStatusCommand, handleSddValidateCommand, handleSddProjectCommand, handleSddCommand, handleSimulateCommand, handleSpecifyCommand, handleStatusCommand, handleSyncPlanCommand, handleTurboCommand, handleWriteRetroCommand, handleHelpCommand, COMMAND_REGISTRY, VALID_COMMANDS, _internals45 as _internals, resolveCommand };
|