opencode-swarm 6.21.3 → 6.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +56 -4
- package/dist/agents/critic.d.ts +1 -0
- package/dist/agents/explorer.d.ts +1 -0
- package/dist/background/event-bus.d.ts +1 -1
- package/dist/cli/index.js +18 -6
- package/dist/config/schema.d.ts +21 -0
- package/dist/hooks/curator-drift.d.ts +30 -0
- package/dist/hooks/curator-types.d.ts +99 -0
- package/dist/hooks/curator.d.ts +70 -0
- package/dist/index.js +950 -279
- package/dist/session/snapshot-reader.d.ts +8 -0
- package/dist/session/snapshot-writer.d.ts +1 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -14549,7 +14549,7 @@ async function loadEvidence(directory, taskId) {
|
|
|
14549
14549
|
return { status: "found", bundle: validated };
|
|
14550
14550
|
} catch (error49) {
|
|
14551
14551
|
warn(`Wrapped flat retrospective failed validation for task ${sanitizedTaskId}: ${error49 instanceof Error ? error49.message : String(error49)}`);
|
|
14552
|
-
const errors3 = error49 instanceof ZodError ? error49.issues.map((e) => e.path.join(".")
|
|
14552
|
+
const errors3 = error49 instanceof ZodError ? error49.issues.map((e) => `${e.path.join(".")}: ${e.message}`) : [String(error49)];
|
|
14553
14553
|
return { status: "invalid_schema", errors: errors3 };
|
|
14554
14554
|
}
|
|
14555
14555
|
}
|
|
@@ -14558,7 +14558,7 @@ async function loadEvidence(directory, taskId) {
|
|
|
14558
14558
|
return { status: "found", bundle: validated };
|
|
14559
14559
|
} catch (error49) {
|
|
14560
14560
|
warn(`Evidence bundle validation failed for task ${sanitizedTaskId}: ${error49 instanceof Error ? error49.message : String(error49)}`);
|
|
14561
|
-
const errors3 = error49 instanceof ZodError ? error49.issues.map((e) => e.path.join(".")
|
|
14561
|
+
const errors3 = error49 instanceof ZodError ? error49.issues.map((e) => `${e.path.join(".")}: ${e.message}`) : [String(error49)];
|
|
14562
14562
|
return { status: "invalid_schema", errors: errors3 };
|
|
14563
14563
|
}
|
|
14564
14564
|
}
|
|
@@ -36296,8 +36296,8 @@ var init_tree_sitter = __esm(() => {
|
|
|
36296
36296
|
bytes = Promise.resolve(input);
|
|
36297
36297
|
} else {
|
|
36298
36298
|
if (globalThis.process?.versions.node) {
|
|
36299
|
-
const
|
|
36300
|
-
bytes =
|
|
36299
|
+
const fs27 = await import("fs/promises");
|
|
36300
|
+
bytes = fs27.readFile(input);
|
|
36301
36301
|
} else {
|
|
36302
36302
|
bytes = fetch(input).then((response) => response.arrayBuffer().then((buffer) => {
|
|
36303
36303
|
if (response.ok) {
|
|
@@ -36352,11 +36352,11 @@ ${JSON.stringify(symbolNames, null, 2)}`);
|
|
|
36352
36352
|
throw toThrow;
|
|
36353
36353
|
}, "quit_");
|
|
36354
36354
|
var scriptDirectory = "";
|
|
36355
|
-
function locateFile(
|
|
36355
|
+
function locateFile(path39) {
|
|
36356
36356
|
if (Module["locateFile"]) {
|
|
36357
|
-
return Module["locateFile"](
|
|
36357
|
+
return Module["locateFile"](path39, scriptDirectory);
|
|
36358
36358
|
}
|
|
36359
|
-
return scriptDirectory +
|
|
36359
|
+
return scriptDirectory + path39;
|
|
36360
36360
|
}
|
|
36361
36361
|
__name(locateFile, "locateFile");
|
|
36362
36362
|
var readAsync, readBinary;
|
|
@@ -38104,7 +38104,7 @@ var init_runtime = __esm(() => {
|
|
|
38104
38104
|
});
|
|
38105
38105
|
|
|
38106
38106
|
// src/index.ts
|
|
38107
|
-
import * as
|
|
38107
|
+
import * as path48 from "path";
|
|
38108
38108
|
|
|
38109
38109
|
// src/tools/tool-names.ts
|
|
38110
38110
|
var TOOL_NAMES = [
|
|
@@ -38763,6 +38763,16 @@ var KnowledgeConfigSchema = exports_external.object({
|
|
|
38763
38763
|
min_retrievals_for_utility: exports_external.number().min(1).max(100).default(3),
|
|
38764
38764
|
schema_version: exports_external.number().int().min(1).default(1)
|
|
38765
38765
|
});
|
|
38766
|
+
var CuratorConfigSchema = exports_external.object({
|
|
38767
|
+
enabled: exports_external.boolean().default(false),
|
|
38768
|
+
init_enabled: exports_external.boolean().default(true),
|
|
38769
|
+
phase_enabled: exports_external.boolean().default(true),
|
|
38770
|
+
max_summary_tokens: exports_external.number().min(500).max(8000).default(2000),
|
|
38771
|
+
min_knowledge_confidence: exports_external.number().min(0).max(1).default(0.7),
|
|
38772
|
+
compliance_report: exports_external.boolean().default(true),
|
|
38773
|
+
suppress_warnings: exports_external.boolean().default(true),
|
|
38774
|
+
drift_inject_max_chars: exports_external.number().min(100).max(2000).default(500)
|
|
38775
|
+
});
|
|
38766
38776
|
var PluginConfigSchema = exports_external.object({
|
|
38767
38777
|
agents: exports_external.record(exports_external.string(), AgentOverrideConfigSchema).optional(),
|
|
38768
38778
|
swarms: exports_external.record(exports_external.string(), SwarmConfigSchema).optional(),
|
|
@@ -38790,6 +38800,7 @@ var PluginConfigSchema = exports_external.object({
|
|
|
38790
38800
|
checkpoint: CheckpointConfigSchema.optional(),
|
|
38791
38801
|
automation: AutomationConfigSchema.optional(),
|
|
38792
38802
|
knowledge: KnowledgeConfigSchema.optional(),
|
|
38803
|
+
curator: CuratorConfigSchema.optional(),
|
|
38793
38804
|
tool_output: exports_external.object({
|
|
38794
38805
|
truncation_enabled: exports_external.boolean().default(true),
|
|
38795
38806
|
max_lines: exports_external.number().min(10).max(500).default(150),
|
|
@@ -42540,7 +42551,7 @@ async function readRejectedLessons(directory) {
|
|
|
42540
42551
|
}
|
|
42541
42552
|
async function appendKnowledge(filePath, entry) {
|
|
42542
42553
|
await mkdir(path9.dirname(filePath), { recursive: true });
|
|
42543
|
-
await appendFile(filePath, JSON.stringify(entry)
|
|
42554
|
+
await appendFile(filePath, `${JSON.stringify(entry)}
|
|
42544
42555
|
`, "utf-8");
|
|
42545
42556
|
}
|
|
42546
42557
|
async function rewriteKnowledge(filePath, entries) {
|
|
@@ -43123,7 +43134,7 @@ async function checkPhaseBoundaries(plan) {
|
|
|
43123
43134
|
for (const phase of plan.phases) {
|
|
43124
43135
|
for (const task of phase.tasks) {
|
|
43125
43136
|
const taskPhaseNum = parseInt(task.id.split(".")[0], 10);
|
|
43126
|
-
if (isNaN(taskPhaseNum)) {
|
|
43137
|
+
if (Number.isNaN(taskPhaseNum)) {
|
|
43127
43138
|
mismatches.push(`Task ${task.id} has invalid phase number`);
|
|
43128
43139
|
} else if (taskPhaseNum !== phase.id) {
|
|
43129
43140
|
mismatches.push(`Task ${task.id} found under Phase ${phase.id}`);
|
|
@@ -43935,7 +43946,7 @@ function sanitizeString(str, maxLength) {
|
|
|
43935
43946
|
return "";
|
|
43936
43947
|
const sanitized = String(str).replace(RTL_OVERRIDE_PATTERN, "");
|
|
43937
43948
|
if (sanitized.length > maxLength) {
|
|
43938
|
-
return sanitized.substring(0, maxLength - 3)
|
|
43949
|
+
return `${sanitized.substring(0, maxLength - 3)}...`;
|
|
43939
43950
|
}
|
|
43940
43951
|
return sanitized;
|
|
43941
43952
|
}
|
|
@@ -44106,7 +44117,7 @@ async function getHandoffData(directory) {
|
|
|
44106
44117
|
const phaseMatch = planMdContent.match(/^## Phase (\d+):?\s*(.+)?$/m);
|
|
44107
44118
|
const taskMatch = planMdContent.match(/^- \[ \] (\d+\.\d+)/g);
|
|
44108
44119
|
if (phaseMatch) {
|
|
44109
|
-
planInfo.currentPhase = sanitizeString(`Phase ${phaseMatch[1]}${phaseMatch[2] ?
|
|
44120
|
+
planInfo.currentPhase = sanitizeString(`Phase ${phaseMatch[1]}${phaseMatch[2] ? `: ${phaseMatch[2]}` : ""}`, MAX_TASK_ID_LENGTH);
|
|
44110
44121
|
}
|
|
44111
44122
|
if (taskMatch) {
|
|
44112
44123
|
const rawTasks = taskMatch.map((t) => t.replace("- [ ] ", ""));
|
|
@@ -44273,7 +44284,8 @@ function serializeAgentSession(s) {
|
|
|
44273
44284
|
lastPhaseCompletePhase: s.lastPhaseCompletePhase ?? 0,
|
|
44274
44285
|
phaseAgentsDispatched,
|
|
44275
44286
|
qaSkipCount: s.qaSkipCount ?? 0,
|
|
44276
|
-
qaSkipTaskIds: s.qaSkipTaskIds ?? []
|
|
44287
|
+
qaSkipTaskIds: s.qaSkipTaskIds ?? [],
|
|
44288
|
+
taskWorkflowStates: Object.fromEntries(s.taskWorkflowStates ?? new Map)
|
|
44277
44289
|
};
|
|
44278
44290
|
}
|
|
44279
44291
|
async function writeSnapshot(directory, state) {
|
|
@@ -46135,7 +46147,7 @@ No plan content available. Start by creating a .swarm/plan.md file.
|
|
|
46135
46147
|
if (incompleteTasks.length > 0) {
|
|
46136
46148
|
const truncateTask = (task) => {
|
|
46137
46149
|
const text = task.replace("- [ ] ", "");
|
|
46138
|
-
return text.length > 60 ? text.slice(0, 57)
|
|
46150
|
+
return text.length > 60 ? `${text.slice(0, 57)}...` : text;
|
|
46139
46151
|
};
|
|
46140
46152
|
compactResult.push(`- Current: ${truncateTask(incompleteTasks[0])}`);
|
|
46141
46153
|
const lookahead = incompleteTasks.slice(1, 1 + Math.min(lookaheadCount, 1));
|
|
@@ -47201,7 +47213,7 @@ function shouldMaskToolOutput(msg, index, totalMessages, recentWindowSize, thres
|
|
|
47201
47213
|
const age = totalMessages - 1 - index;
|
|
47202
47214
|
return age > recentWindowSize || text.length > threshold;
|
|
47203
47215
|
}
|
|
47204
|
-
function maskToolOutput(msg,
|
|
47216
|
+
function maskToolOutput(msg, _threshold) {
|
|
47205
47217
|
if (!msg?.parts)
|
|
47206
47218
|
return 0;
|
|
47207
47219
|
let freedTokens = 0;
|
|
@@ -48322,6 +48334,416 @@ function consolidateSystemMessages(messages) {
|
|
|
48322
48334
|
}
|
|
48323
48335
|
// src/hooks/phase-monitor.ts
|
|
48324
48336
|
init_manager2();
|
|
48337
|
+
|
|
48338
|
+
// src/hooks/curator.ts
|
|
48339
|
+
init_event_bus();
|
|
48340
|
+
import * as fs14 from "fs";
|
|
48341
|
+
import * as path26 from "path";
|
|
48342
|
+
init_utils2();
|
|
48343
|
+
async function readCuratorSummary(directory) {
|
|
48344
|
+
const content = await readSwarmFileAsync(directory, "curator-summary.json");
|
|
48345
|
+
if (content === null) {
|
|
48346
|
+
return null;
|
|
48347
|
+
}
|
|
48348
|
+
try {
|
|
48349
|
+
const parsed = JSON.parse(content);
|
|
48350
|
+
if (parsed.schema_version !== 1) {
|
|
48351
|
+
console.warn(`Curator summary has unsupported schema version: ${parsed.schema_version}. Expected 1.`);
|
|
48352
|
+
return null;
|
|
48353
|
+
}
|
|
48354
|
+
return parsed;
|
|
48355
|
+
} catch {
|
|
48356
|
+
console.warn("Failed to parse curator-summary.json: invalid JSON");
|
|
48357
|
+
return null;
|
|
48358
|
+
}
|
|
48359
|
+
}
|
|
48360
|
+
async function writeCuratorSummary(directory, summary) {
|
|
48361
|
+
const resolvedPath = validateSwarmPath(directory, "curator-summary.json");
|
|
48362
|
+
fs14.mkdirSync(path26.dirname(resolvedPath), { recursive: true });
|
|
48363
|
+
await Bun.write(resolvedPath, JSON.stringify(summary, null, 2));
|
|
48364
|
+
}
|
|
48365
|
+
function normalizeAgentName(name2) {
|
|
48366
|
+
return name2.toLowerCase().replace(/^(mega|paid|local|lowtier|modelrelay)_/, "");
|
|
48367
|
+
}
|
|
48368
|
+
function filterPhaseEvents(eventsJsonl, phase, sinceTimestamp) {
|
|
48369
|
+
const lines = eventsJsonl.split(`
|
|
48370
|
+
`);
|
|
48371
|
+
const filtered = [];
|
|
48372
|
+
for (const line of lines) {
|
|
48373
|
+
if (!line.trim())
|
|
48374
|
+
continue;
|
|
48375
|
+
try {
|
|
48376
|
+
const event = JSON.parse(line);
|
|
48377
|
+
if (sinceTimestamp) {
|
|
48378
|
+
if (event.timestamp > sinceTimestamp) {
|
|
48379
|
+
filtered.push(event);
|
|
48380
|
+
}
|
|
48381
|
+
} else {
|
|
48382
|
+
if (event.phase === phase) {
|
|
48383
|
+
filtered.push(event);
|
|
48384
|
+
}
|
|
48385
|
+
}
|
|
48386
|
+
} catch {
|
|
48387
|
+
console.warn("filterPhaseEvents: skipping malformed line");
|
|
48388
|
+
}
|
|
48389
|
+
}
|
|
48390
|
+
return filtered;
|
|
48391
|
+
}
|
|
48392
|
+
function checkPhaseCompliance(phaseEvents, agentsDispatched, requiredAgents, phase) {
|
|
48393
|
+
const observations = [];
|
|
48394
|
+
const timestamp = new Date().toISOString();
|
|
48395
|
+
for (const agent of requiredAgents) {
|
|
48396
|
+
const normalizedAgent = normalizeAgentName(agent);
|
|
48397
|
+
const isDispatched = agentsDispatched.some((a) => normalizeAgentName(a) === normalizedAgent);
|
|
48398
|
+
if (!isDispatched) {
|
|
48399
|
+
observations.push({
|
|
48400
|
+
phase,
|
|
48401
|
+
timestamp,
|
|
48402
|
+
type: "workflow_deviation",
|
|
48403
|
+
severity: "warning",
|
|
48404
|
+
description: `Agent '${agent}' required but not dispatched in phase ${phase}`
|
|
48405
|
+
});
|
|
48406
|
+
}
|
|
48407
|
+
}
|
|
48408
|
+
const coderDelegations = [];
|
|
48409
|
+
const reviewerDelegations = [];
|
|
48410
|
+
for (let i2 = 0;i2 < phaseEvents.length; i2++) {
|
|
48411
|
+
const e = phaseEvents[i2];
|
|
48412
|
+
try {
|
|
48413
|
+
if (e.type === "agent.delegation") {
|
|
48414
|
+
const agent = e.agent;
|
|
48415
|
+
if (agent && typeof agent === "string") {
|
|
48416
|
+
const normalized = normalizeAgentName(agent);
|
|
48417
|
+
if (normalized === "coder") {
|
|
48418
|
+
coderDelegations.push({ event: e, index: i2 });
|
|
48419
|
+
} else if (normalized === "reviewer") {
|
|
48420
|
+
reviewerDelegations.push({ event: e, index: i2 });
|
|
48421
|
+
}
|
|
48422
|
+
}
|
|
48423
|
+
}
|
|
48424
|
+
} catch {}
|
|
48425
|
+
}
|
|
48426
|
+
for (const coderEvent of coderDelegations) {
|
|
48427
|
+
const hasSubsequentReviewer = reviewerDelegations.some((r) => r.index > coderEvent.index);
|
|
48428
|
+
if (!hasSubsequentReviewer) {
|
|
48429
|
+
observations.push({
|
|
48430
|
+
phase,
|
|
48431
|
+
timestamp,
|
|
48432
|
+
type: "missing_reviewer",
|
|
48433
|
+
severity: "warning",
|
|
48434
|
+
description: `Coder delegation in phase ${phase} has no subsequent reviewer delegation`
|
|
48435
|
+
});
|
|
48436
|
+
}
|
|
48437
|
+
}
|
|
48438
|
+
let phaseCompleteIndex = -1;
|
|
48439
|
+
let retroIndex = -1;
|
|
48440
|
+
for (let i2 = 0;i2 < phaseEvents.length; i2++) {
|
|
48441
|
+
const e = phaseEvents[i2];
|
|
48442
|
+
try {
|
|
48443
|
+
const eventType = e.type;
|
|
48444
|
+
const evidenceType = e.evidence_type;
|
|
48445
|
+
if (typeof eventType === "string" && (eventType === "phase_complete" || eventType === "phase.complete")) {
|
|
48446
|
+
phaseCompleteIndex = i2;
|
|
48447
|
+
}
|
|
48448
|
+
if (typeof eventType === "string" && eventType === "retrospective.written" || typeof evidenceType === "string" && evidenceType === "retrospective") {
|
|
48449
|
+
retroIndex = i2;
|
|
48450
|
+
}
|
|
48451
|
+
} catch {}
|
|
48452
|
+
}
|
|
48453
|
+
if (phaseCompleteIndex !== -1 && retroIndex === -1) {
|
|
48454
|
+
observations.push({
|
|
48455
|
+
phase,
|
|
48456
|
+
timestamp,
|
|
48457
|
+
type: "missing_retro",
|
|
48458
|
+
severity: "warning",
|
|
48459
|
+
description: `Phase ${phase} completed without retrospective evidence`
|
|
48460
|
+
});
|
|
48461
|
+
}
|
|
48462
|
+
const domainDetectionEvents = [];
|
|
48463
|
+
const smeDelegations = [];
|
|
48464
|
+
for (let i2 = 0;i2 < phaseEvents.length; i2++) {
|
|
48465
|
+
const e = phaseEvents[i2];
|
|
48466
|
+
try {
|
|
48467
|
+
if (e.type === "domains.detected") {
|
|
48468
|
+
domainDetectionEvents.push({ event: e, index: i2 });
|
|
48469
|
+
}
|
|
48470
|
+
if (e.type === "agent.delegation" && e.agent) {
|
|
48471
|
+
const agent = e.agent;
|
|
48472
|
+
if (agent && typeof agent === "string") {
|
|
48473
|
+
const normalized = normalizeAgentName(agent);
|
|
48474
|
+
if (normalized === "sme") {
|
|
48475
|
+
smeDelegations.push({ event: e, index: i2 });
|
|
48476
|
+
}
|
|
48477
|
+
}
|
|
48478
|
+
}
|
|
48479
|
+
} catch {}
|
|
48480
|
+
}
|
|
48481
|
+
for (const domainEvent of domainDetectionEvents) {
|
|
48482
|
+
const hasSubsequentSme = smeDelegations.some((s) => s.index > domainEvent.index);
|
|
48483
|
+
if (!hasSubsequentSme) {
|
|
48484
|
+
observations.push({
|
|
48485
|
+
phase,
|
|
48486
|
+
timestamp,
|
|
48487
|
+
type: "missing_sme",
|
|
48488
|
+
severity: "info",
|
|
48489
|
+
description: `Domains detected in phase ${phase} but no SME consultation found`
|
|
48490
|
+
});
|
|
48491
|
+
}
|
|
48492
|
+
}
|
|
48493
|
+
return observations;
|
|
48494
|
+
}
|
|
48495
|
+
async function runCuratorInit(directory, config3) {
|
|
48496
|
+
try {
|
|
48497
|
+
const priorSummary = await readCuratorSummary(directory);
|
|
48498
|
+
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
48499
|
+
const allEntries = await readKnowledge(knowledgePath);
|
|
48500
|
+
const highConfidenceEntries = allEntries.filter((e) => typeof e.confidence === "number" && e.confidence >= config3.min_knowledge_confidence);
|
|
48501
|
+
const contextMd = await readSwarmFileAsync(directory, "context.md");
|
|
48502
|
+
const briefingParts = [];
|
|
48503
|
+
if (priorSummary) {
|
|
48504
|
+
briefingParts.push(`## Prior Session Summary (Phase ${priorSummary.last_phase_covered})`);
|
|
48505
|
+
briefingParts.push(priorSummary.digest);
|
|
48506
|
+
if (priorSummary.compliance_observations.length > 0 && !config3.suppress_warnings) {
|
|
48507
|
+
briefingParts.push(`
|
|
48508
|
+
## Compliance Observations`);
|
|
48509
|
+
for (const obs of priorSummary.compliance_observations) {
|
|
48510
|
+
briefingParts.push(`- [${obs.severity.toUpperCase()}] Phase ${obs.phase}: ${obs.description}`);
|
|
48511
|
+
}
|
|
48512
|
+
}
|
|
48513
|
+
if (priorSummary.knowledge_recommendations.length > 0) {
|
|
48514
|
+
briefingParts.push(`
|
|
48515
|
+
## Knowledge Recommendations`);
|
|
48516
|
+
for (const rec of priorSummary.knowledge_recommendations) {
|
|
48517
|
+
briefingParts.push(`- ${rec.action}: ${rec.lesson} (${rec.reason})`);
|
|
48518
|
+
}
|
|
48519
|
+
}
|
|
48520
|
+
} else {
|
|
48521
|
+
briefingParts.push("## First Session \u2014 No Prior Summary");
|
|
48522
|
+
briefingParts.push("This is the first curator run for this project. No prior phase data available.");
|
|
48523
|
+
}
|
|
48524
|
+
if (highConfidenceEntries.length > 0) {
|
|
48525
|
+
briefingParts.push(`
|
|
48526
|
+
## High-Confidence Knowledge`);
|
|
48527
|
+
for (const entry of highConfidenceEntries.slice(0, 10)) {
|
|
48528
|
+
const lesson = typeof entry.lesson === "string" ? entry.lesson : JSON.stringify(entry.lesson);
|
|
48529
|
+
briefingParts.push(`- ${lesson}`);
|
|
48530
|
+
}
|
|
48531
|
+
}
|
|
48532
|
+
if (contextMd) {
|
|
48533
|
+
briefingParts.push(`
|
|
48534
|
+
## Context Summary`);
|
|
48535
|
+
const maxContextChars = config3.max_summary_tokens * 2;
|
|
48536
|
+
briefingParts.push(contextMd.slice(0, maxContextChars));
|
|
48537
|
+
}
|
|
48538
|
+
const contradictions = allEntries.filter((e) => Array.isArray(e.tags) && e.tags.some((t) => t.includes("contradiction"))).map((e) => typeof e.lesson === "string" ? e.lesson : JSON.stringify(e.lesson));
|
|
48539
|
+
const result = {
|
|
48540
|
+
briefing: briefingParts.join(`
|
|
48541
|
+
`),
|
|
48542
|
+
contradictions,
|
|
48543
|
+
knowledge_entries_reviewed: allEntries.length,
|
|
48544
|
+
prior_phases_covered: priorSummary ? priorSummary.last_phase_covered : 0
|
|
48545
|
+
};
|
|
48546
|
+
getGlobalEventBus().publish("curator.init.completed", {
|
|
48547
|
+
prior_phases_covered: result.prior_phases_covered,
|
|
48548
|
+
knowledge_entries_reviewed: result.knowledge_entries_reviewed,
|
|
48549
|
+
contradictions_found: contradictions.length
|
|
48550
|
+
});
|
|
48551
|
+
return result;
|
|
48552
|
+
} catch (err2) {
|
|
48553
|
+
getGlobalEventBus().publish("curator.error", {
|
|
48554
|
+
operation: "init",
|
|
48555
|
+
error: String(err2)
|
|
48556
|
+
});
|
|
48557
|
+
return {
|
|
48558
|
+
briefing: `## Curator Init Failed
|
|
48559
|
+
Could not load prior session context.`,
|
|
48560
|
+
contradictions: [],
|
|
48561
|
+
knowledge_entries_reviewed: 0,
|
|
48562
|
+
prior_phases_covered: 0
|
|
48563
|
+
};
|
|
48564
|
+
}
|
|
48565
|
+
}
|
|
48566
|
+
async function runCuratorPhase(directory, phase, agentsDispatched, _config, _knowledgeConfig) {
|
|
48567
|
+
try {
|
|
48568
|
+
const priorSummary = await readCuratorSummary(directory);
|
|
48569
|
+
const eventsJsonlContent = await readSwarmFileAsync(directory, "events.jsonl");
|
|
48570
|
+
const phaseEvents = eventsJsonlContent ? filterPhaseEvents(eventsJsonlContent, phase) : [];
|
|
48571
|
+
const contextMd = await readSwarmFileAsync(directory, "context.md");
|
|
48572
|
+
const requiredAgents = ["reviewer", "test_engineer"];
|
|
48573
|
+
const complianceObservations = checkPhaseCompliance(phaseEvents, agentsDispatched, requiredAgents, phase);
|
|
48574
|
+
const tasksCompleted = phaseEvents.filter((e) => e.type === "task.completed").length;
|
|
48575
|
+
const keyDecisions = [];
|
|
48576
|
+
if (contextMd) {
|
|
48577
|
+
const decisionSection = contextMd.match(/## Decisions\r?\n([\s\S]*?)(?:\r?\n##|$)/);
|
|
48578
|
+
if (decisionSection) {
|
|
48579
|
+
const lines = decisionSection[1].split(`
|
|
48580
|
+
`);
|
|
48581
|
+
for (const line of lines) {
|
|
48582
|
+
const trimmed = line.trim();
|
|
48583
|
+
if (trimmed.startsWith("- ")) {
|
|
48584
|
+
keyDecisions.push(trimmed.slice(2));
|
|
48585
|
+
}
|
|
48586
|
+
}
|
|
48587
|
+
}
|
|
48588
|
+
}
|
|
48589
|
+
const phaseDigest = {
|
|
48590
|
+
phase,
|
|
48591
|
+
timestamp: new Date().toISOString(),
|
|
48592
|
+
summary: `Phase ${phase} completed. ${tasksCompleted} tasks recorded. ${complianceObservations.length} compliance observations.`,
|
|
48593
|
+
agents_used: [...new Set(agentsDispatched.map(normalizeAgentName))],
|
|
48594
|
+
tasks_completed: tasksCompleted,
|
|
48595
|
+
tasks_total: tasksCompleted,
|
|
48596
|
+
key_decisions: keyDecisions.slice(0, 5),
|
|
48597
|
+
blockers_resolved: []
|
|
48598
|
+
};
|
|
48599
|
+
const knowledgeRecommendations = [];
|
|
48600
|
+
const sessionId = `session-${Date.now()}`;
|
|
48601
|
+
const now = new Date().toISOString();
|
|
48602
|
+
let updatedSummary;
|
|
48603
|
+
if (priorSummary) {
|
|
48604
|
+
updatedSummary = {
|
|
48605
|
+
...priorSummary,
|
|
48606
|
+
last_updated: now,
|
|
48607
|
+
last_phase_covered: Math.max(priorSummary.last_phase_covered, phase),
|
|
48608
|
+
digest: priorSummary.digest + `
|
|
48609
|
+
|
|
48610
|
+
### Phase ${phase}
|
|
48611
|
+
${phaseDigest.summary}`,
|
|
48612
|
+
phase_digests: [...priorSummary.phase_digests, phaseDigest],
|
|
48613
|
+
compliance_observations: [
|
|
48614
|
+
...priorSummary.compliance_observations,
|
|
48615
|
+
...complianceObservations
|
|
48616
|
+
],
|
|
48617
|
+
knowledge_recommendations: knowledgeRecommendations
|
|
48618
|
+
};
|
|
48619
|
+
} else {
|
|
48620
|
+
updatedSummary = {
|
|
48621
|
+
schema_version: 1,
|
|
48622
|
+
session_id: sessionId,
|
|
48623
|
+
last_updated: now,
|
|
48624
|
+
last_phase_covered: phase,
|
|
48625
|
+
digest: `### Phase ${phase}
|
|
48626
|
+
${phaseDigest.summary}`,
|
|
48627
|
+
phase_digests: [phaseDigest],
|
|
48628
|
+
compliance_observations: complianceObservations,
|
|
48629
|
+
knowledge_recommendations: knowledgeRecommendations
|
|
48630
|
+
};
|
|
48631
|
+
}
|
|
48632
|
+
await writeCuratorSummary(directory, updatedSummary);
|
|
48633
|
+
const eventsPath = path26.join(directory, ".swarm", "events.jsonl");
|
|
48634
|
+
for (const obs of complianceObservations) {
|
|
48635
|
+
await appendKnowledge(eventsPath, {
|
|
48636
|
+
type: "curator_compliance",
|
|
48637
|
+
timestamp: obs.timestamp,
|
|
48638
|
+
phase: obs.phase,
|
|
48639
|
+
observation_type: obs.type,
|
|
48640
|
+
severity: obs.severity,
|
|
48641
|
+
description: obs.description
|
|
48642
|
+
});
|
|
48643
|
+
}
|
|
48644
|
+
const result = {
|
|
48645
|
+
phase,
|
|
48646
|
+
digest: phaseDigest,
|
|
48647
|
+
compliance: complianceObservations,
|
|
48648
|
+
knowledge_recommendations: knowledgeRecommendations,
|
|
48649
|
+
summary_updated: true
|
|
48650
|
+
};
|
|
48651
|
+
getGlobalEventBus().publish("curator.phase.completed", {
|
|
48652
|
+
phase,
|
|
48653
|
+
compliance_count: complianceObservations.length,
|
|
48654
|
+
summary_updated: true
|
|
48655
|
+
});
|
|
48656
|
+
return result;
|
|
48657
|
+
} catch (err2) {
|
|
48658
|
+
getGlobalEventBus().publish("curator.error", {
|
|
48659
|
+
operation: "phase",
|
|
48660
|
+
phase,
|
|
48661
|
+
error: String(err2)
|
|
48662
|
+
});
|
|
48663
|
+
return {
|
|
48664
|
+
phase,
|
|
48665
|
+
digest: {
|
|
48666
|
+
phase,
|
|
48667
|
+
timestamp: new Date().toISOString(),
|
|
48668
|
+
summary: `Phase ${phase} curator run failed: ${String(err2)}`,
|
|
48669
|
+
agents_used: [],
|
|
48670
|
+
tasks_completed: 0,
|
|
48671
|
+
tasks_total: 0,
|
|
48672
|
+
key_decisions: [],
|
|
48673
|
+
blockers_resolved: []
|
|
48674
|
+
},
|
|
48675
|
+
compliance: [],
|
|
48676
|
+
knowledge_recommendations: [],
|
|
48677
|
+
summary_updated: false
|
|
48678
|
+
};
|
|
48679
|
+
}
|
|
48680
|
+
}
|
|
48681
|
+
async function applyCuratorKnowledgeUpdates(directory, recommendations, _knowledgeConfig) {
|
|
48682
|
+
let applied = 0;
|
|
48683
|
+
let skipped = 0;
|
|
48684
|
+
if (recommendations.length === 0) {
|
|
48685
|
+
return { applied, skipped };
|
|
48686
|
+
}
|
|
48687
|
+
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
48688
|
+
const entries = await readKnowledge(knowledgePath);
|
|
48689
|
+
let modified = false;
|
|
48690
|
+
const appliedIds = new Set;
|
|
48691
|
+
const updatedEntries = entries.map((entry) => {
|
|
48692
|
+
const rec = recommendations.find((r) => r.entry_id === entry.id);
|
|
48693
|
+
if (!rec)
|
|
48694
|
+
return entry;
|
|
48695
|
+
switch (rec.action) {
|
|
48696
|
+
case "promote":
|
|
48697
|
+
appliedIds.add(entry.id);
|
|
48698
|
+
applied++;
|
|
48699
|
+
modified = true;
|
|
48700
|
+
return {
|
|
48701
|
+
...entry,
|
|
48702
|
+
hive_eligible: true,
|
|
48703
|
+
confidence: Math.min(1, (entry.confidence ?? 0) + 0.1),
|
|
48704
|
+
updated_at: new Date().toISOString()
|
|
48705
|
+
};
|
|
48706
|
+
case "archive":
|
|
48707
|
+
appliedIds.add(entry.id);
|
|
48708
|
+
applied++;
|
|
48709
|
+
modified = true;
|
|
48710
|
+
return {
|
|
48711
|
+
...entry,
|
|
48712
|
+
status: "archived",
|
|
48713
|
+
updated_at: new Date().toISOString()
|
|
48714
|
+
};
|
|
48715
|
+
case "flag_contradiction":
|
|
48716
|
+
appliedIds.add(entry.id);
|
|
48717
|
+
applied++;
|
|
48718
|
+
modified = true;
|
|
48719
|
+
return {
|
|
48720
|
+
...entry,
|
|
48721
|
+
tags: [
|
|
48722
|
+
...entry.tags ?? [],
|
|
48723
|
+
`contradiction:${(rec.reason ?? "").slice(0, 50)}`
|
|
48724
|
+
],
|
|
48725
|
+
updated_at: new Date().toISOString()
|
|
48726
|
+
};
|
|
48727
|
+
default:
|
|
48728
|
+
return entry;
|
|
48729
|
+
}
|
|
48730
|
+
});
|
|
48731
|
+
for (const rec of recommendations) {
|
|
48732
|
+
if (rec.entry_id !== undefined && !appliedIds.has(rec.entry_id)) {
|
|
48733
|
+
const found = entries.some((e) => e.id === rec.entry_id);
|
|
48734
|
+
if (!found) {
|
|
48735
|
+
console.warn(`[curator] applyCuratorKnowledgeUpdates: entry_id '${rec.entry_id}' not found \u2014 skipping`);
|
|
48736
|
+
}
|
|
48737
|
+
skipped++;
|
|
48738
|
+
}
|
|
48739
|
+
}
|
|
48740
|
+
if (modified) {
|
|
48741
|
+
await rewriteKnowledge(knowledgePath, updatedEntries);
|
|
48742
|
+
}
|
|
48743
|
+
return { applied, skipped };
|
|
48744
|
+
}
|
|
48745
|
+
|
|
48746
|
+
// src/hooks/phase-monitor.ts
|
|
48325
48747
|
init_utils2();
|
|
48326
48748
|
function createPhaseMonitorHook(directory, preflightManager) {
|
|
48327
48749
|
let lastKnownPhase = null;
|
|
@@ -48332,6 +48754,12 @@ function createPhaseMonitorHook(directory, preflightManager) {
|
|
|
48332
48754
|
const currentPhase = plan.current_phase ?? 1;
|
|
48333
48755
|
if (lastKnownPhase === null) {
|
|
48334
48756
|
lastKnownPhase = currentPhase;
|
|
48757
|
+
try {
|
|
48758
|
+
const curatorConfig = CuratorConfigSchema.parse({});
|
|
48759
|
+
if (curatorConfig.enabled && curatorConfig.init_enabled) {
|
|
48760
|
+
await runCuratorInit(directory, curatorConfig);
|
|
48761
|
+
}
|
|
48762
|
+
} catch {}
|
|
48335
48763
|
return;
|
|
48336
48764
|
}
|
|
48337
48765
|
if (currentPhase !== lastKnownPhase) {
|
|
@@ -48432,7 +48860,7 @@ ${originalText}`;
|
|
|
48432
48860
|
};
|
|
48433
48861
|
}
|
|
48434
48862
|
// src/hooks/system-enhancer.ts
|
|
48435
|
-
import * as
|
|
48863
|
+
import * as fs16 from "fs";
|
|
48436
48864
|
init_manager();
|
|
48437
48865
|
init_detector();
|
|
48438
48866
|
init_manager2();
|
|
@@ -48440,8 +48868,8 @@ init_manager2();
|
|
|
48440
48868
|
// src/services/decision-drift-analyzer.ts
|
|
48441
48869
|
init_utils2();
|
|
48442
48870
|
init_manager2();
|
|
48443
|
-
import * as
|
|
48444
|
-
import * as
|
|
48871
|
+
import * as fs15 from "fs";
|
|
48872
|
+
import * as path27 from "path";
|
|
48445
48873
|
var DEFAULT_DRIFT_CONFIG = {
|
|
48446
48874
|
staleThresholdPhases: 1,
|
|
48447
48875
|
detectContradictions: true,
|
|
@@ -48595,11 +49023,11 @@ async function analyzeDecisionDrift(directory, config3 = {}) {
|
|
|
48595
49023
|
currentPhase = legacyPhase;
|
|
48596
49024
|
}
|
|
48597
49025
|
}
|
|
48598
|
-
const contextPath =
|
|
49026
|
+
const contextPath = path27.join(directory, ".swarm", "context.md");
|
|
48599
49027
|
let contextContent = "";
|
|
48600
49028
|
try {
|
|
48601
|
-
if (
|
|
48602
|
-
contextContent =
|
|
49029
|
+
if (fs15.existsSync(contextPath)) {
|
|
49030
|
+
contextContent = fs15.readFileSync(contextPath, "utf-8");
|
|
48603
49031
|
}
|
|
48604
49032
|
} catch {
|
|
48605
49033
|
return {
|
|
@@ -49064,7 +49492,7 @@ ${top5.map((d) => `- [${d.category}] ${d.directive}`).join(`
|
|
|
49064
49492
|
continue;
|
|
49065
49493
|
const ts = retro.timestamp ?? b.bundle.created_at;
|
|
49066
49494
|
const ageMs = now - new Date(ts).getTime();
|
|
49067
|
-
if (isNaN(ageMs) || ageMs > cutoffMs)
|
|
49495
|
+
if (Number.isNaN(ageMs) || ageMs > cutoffMs)
|
|
49068
49496
|
continue;
|
|
49069
49497
|
allRetros.push({ entry: retro, timestamp: ts });
|
|
49070
49498
|
}
|
|
@@ -49076,11 +49504,11 @@ ${top5.map((d) => `- [${d.category}] ${d.directive}`).join(`
|
|
|
49076
49504
|
allRetros.sort((a, b) => {
|
|
49077
49505
|
const ta = new Date(a.timestamp).getTime();
|
|
49078
49506
|
const tb = new Date(b.timestamp).getTime();
|
|
49079
|
-
if (isNaN(ta) && isNaN(tb))
|
|
49507
|
+
if (Number.isNaN(ta) && Number.isNaN(tb))
|
|
49080
49508
|
return 0;
|
|
49081
|
-
if (isNaN(ta))
|
|
49509
|
+
if (Number.isNaN(ta))
|
|
49082
49510
|
return 1;
|
|
49083
|
-
if (isNaN(tb))
|
|
49511
|
+
if (Number.isNaN(tb))
|
|
49084
49512
|
return -1;
|
|
49085
49513
|
return tb - ta;
|
|
49086
49514
|
});
|
|
@@ -49125,7 +49553,7 @@ async function buildCoderRetroInjection(directory, currentPhaseNumber) {
|
|
|
49125
49553
|
if (!retroEntry || retroEntry.verdict === "fail")
|
|
49126
49554
|
return null;
|
|
49127
49555
|
const lessons = retroEntry.lessons_learned ?? [];
|
|
49128
|
-
const summaryLine = `[SWARM RETROSPECTIVE] From Phase ${prevPhase}:${retroEntry.summary ?
|
|
49556
|
+
const summaryLine = `[SWARM RETROSPECTIVE] From Phase ${prevPhase}:${retroEntry.summary ? ` ${retroEntry.summary}` : ""}`;
|
|
49129
49557
|
const allLines = [summaryLine, ...lessons];
|
|
49130
49558
|
const text = allLines.join(`
|
|
49131
49559
|
`);
|
|
@@ -49242,11 +49670,11 @@ function createSystemEnhancerHook(config3, directory) {
|
|
|
49242
49670
|
if (handoffContent) {
|
|
49243
49671
|
const handoffPath = validateSwarmPath(directory, "handoff.md");
|
|
49244
49672
|
const consumedPath = validateSwarmPath(directory, "handoff-consumed.md");
|
|
49245
|
-
if (
|
|
49673
|
+
if (fs16.existsSync(consumedPath)) {
|
|
49246
49674
|
warn("Duplicate handoff detected: handoff-consumed.md already exists");
|
|
49247
|
-
|
|
49675
|
+
fs16.unlinkSync(consumedPath);
|
|
49248
49676
|
}
|
|
49249
|
-
|
|
49677
|
+
fs16.renameSync(handoffPath, consumedPath);
|
|
49250
49678
|
const handoffBlock = `## HANDOFF \u2014 Resuming from model switch
|
|
49251
49679
|
The previous model's session ended. Here is your starting context:
|
|
49252
49680
|
|
|
@@ -49522,11 +49950,11 @@ ${budgetWarning}`);
|
|
|
49522
49950
|
if (handoffContent) {
|
|
49523
49951
|
const handoffPath = validateSwarmPath(directory, "handoff.md");
|
|
49524
49952
|
const consumedPath = validateSwarmPath(directory, "handoff-consumed.md");
|
|
49525
|
-
if (
|
|
49953
|
+
if (fs16.existsSync(consumedPath)) {
|
|
49526
49954
|
warn("Duplicate handoff detected: handoff-consumed.md already exists");
|
|
49527
|
-
|
|
49955
|
+
fs16.unlinkSync(consumedPath);
|
|
49528
49956
|
}
|
|
49529
|
-
|
|
49957
|
+
fs16.renameSync(handoffPath, consumedPath);
|
|
49530
49958
|
const handoffBlock = `## HANDOFF \u2014 Resuming from model switch
|
|
49531
49959
|
The previous model's session ended. Here is your starting context:
|
|
49532
49960
|
|
|
@@ -50204,7 +50632,7 @@ function createDarkMatterDetectorHook(directory) {
|
|
|
50204
50632
|
// src/hooks/knowledge-reader.ts
|
|
50205
50633
|
import { existsSync as existsSync18 } from "fs";
|
|
50206
50634
|
import { mkdir as mkdir4, readFile as readFile4, writeFile as writeFile4 } from "fs/promises";
|
|
50207
|
-
import * as
|
|
50635
|
+
import * as path28 from "path";
|
|
50208
50636
|
var JACCARD_THRESHOLD = 0.6;
|
|
50209
50637
|
var HIVE_TIER_BOOST = 0.05;
|
|
50210
50638
|
var SAME_PROJECT_PENALTY = -0.05;
|
|
@@ -50252,7 +50680,7 @@ function inferCategoriesFromPhase(phaseDescription) {
|
|
|
50252
50680
|
return ["process", "tooling"];
|
|
50253
50681
|
}
|
|
50254
50682
|
async function recordLessonsShown(directory, lessonIds, currentPhase) {
|
|
50255
|
-
const shownFile =
|
|
50683
|
+
const shownFile = path28.join(directory, ".swarm", ".knowledge-shown.json");
|
|
50256
50684
|
try {
|
|
50257
50685
|
let shownData = {};
|
|
50258
50686
|
if (existsSync18(shownFile)) {
|
|
@@ -50260,7 +50688,7 @@ async function recordLessonsShown(directory, lessonIds, currentPhase) {
|
|
|
50260
50688
|
shownData = JSON.parse(content);
|
|
50261
50689
|
}
|
|
50262
50690
|
shownData[currentPhase] = lessonIds;
|
|
50263
|
-
await mkdir4(
|
|
50691
|
+
await mkdir4(path28.dirname(shownFile), { recursive: true });
|
|
50264
50692
|
await writeFile4(shownFile, JSON.stringify(shownData, null, 2), "utf-8");
|
|
50265
50693
|
} catch {
|
|
50266
50694
|
console.warn("[swarm] Knowledge: failed to record shown lessons");
|
|
@@ -50355,7 +50783,7 @@ async function readMergedKnowledge(directory, config3, context) {
|
|
|
50355
50783
|
return topN;
|
|
50356
50784
|
}
|
|
50357
50785
|
async function updateRetrievalOutcome(directory, phaseInfo, phaseSucceeded) {
|
|
50358
|
-
const shownFile =
|
|
50786
|
+
const shownFile = path28.join(directory, ".swarm", ".knowledge-shown.json");
|
|
50359
50787
|
try {
|
|
50360
50788
|
if (!existsSync18(shownFile)) {
|
|
50361
50789
|
return;
|
|
@@ -50823,6 +51251,160 @@ Use this data to avoid repeating known failure patterns.`;
|
|
|
50823
51251
|
return prefix + summaryText + suffix;
|
|
50824
51252
|
}
|
|
50825
51253
|
|
|
51254
|
+
// src/hooks/curator-drift.ts
|
|
51255
|
+
init_event_bus();
|
|
51256
|
+
init_utils2();
|
|
51257
|
+
import * as fs17 from "fs";
|
|
51258
|
+
import * as path29 from "path";
|
|
51259
|
+
var DRIFT_REPORT_PREFIX = "drift-report-phase-";
|
|
51260
|
+
async function readPriorDriftReports(directory) {
|
|
51261
|
+
const swarmDir = path29.join(directory, ".swarm");
|
|
51262
|
+
const entries = await fs17.promises.readdir(swarmDir).catch(() => null);
|
|
51263
|
+
if (entries === null)
|
|
51264
|
+
return [];
|
|
51265
|
+
const reportFiles = entries.filter((name2) => name2.startsWith(DRIFT_REPORT_PREFIX) && name2.endsWith(".json")).sort();
|
|
51266
|
+
const reports = [];
|
|
51267
|
+
for (const filename of reportFiles) {
|
|
51268
|
+
const content = await readSwarmFileAsync(directory, filename);
|
|
51269
|
+
if (content === null)
|
|
51270
|
+
continue;
|
|
51271
|
+
try {
|
|
51272
|
+
const report = JSON.parse(content);
|
|
51273
|
+
if (typeof report.phase !== "number" || typeof report.alignment !== "string") {
|
|
51274
|
+
console.warn(`[curator-drift] Skipping corrupt drift report: ${filename}`);
|
|
51275
|
+
continue;
|
|
51276
|
+
}
|
|
51277
|
+
reports.push(report);
|
|
51278
|
+
} catch {
|
|
51279
|
+
console.warn(`[curator-drift] Skipping unreadable drift report: ${filename}`);
|
|
51280
|
+
}
|
|
51281
|
+
}
|
|
51282
|
+
reports.sort((a, b) => a.phase - b.phase);
|
|
51283
|
+
return reports;
|
|
51284
|
+
}
|
|
51285
|
+
async function writeDriftReport(directory, report) {
|
|
51286
|
+
const filename = `${DRIFT_REPORT_PREFIX}${report.phase}.json`;
|
|
51287
|
+
const filePath = validateSwarmPath(directory, filename);
|
|
51288
|
+
const swarmDir = path29.dirname(filePath);
|
|
51289
|
+
await fs17.promises.mkdir(swarmDir, { recursive: true });
|
|
51290
|
+
try {
|
|
51291
|
+
await fs17.promises.writeFile(filePath, JSON.stringify(report, null, 2), "utf-8");
|
|
51292
|
+
} catch (err2) {
|
|
51293
|
+
throw new Error(`[curator-drift] Failed to write drift report to ${filePath}: ${String(err2)}`);
|
|
51294
|
+
}
|
|
51295
|
+
return filePath;
|
|
51296
|
+
}
|
|
51297
|
+
async function runCriticDriftCheck(directory, phase, curatorResult, config3) {
|
|
51298
|
+
try {
|
|
51299
|
+
const planMd = await readSwarmFileAsync(directory, "plan.md");
|
|
51300
|
+
const specMd = await readSwarmFileAsync(directory, "spec.md");
|
|
51301
|
+
const priorReports = await readPriorDriftReports(directory);
|
|
51302
|
+
const complianceCount = curatorResult.compliance.length;
|
|
51303
|
+
const warningCompliance = curatorResult.compliance.filter((obs) => obs.severity === "warning");
|
|
51304
|
+
let alignment = "ALIGNED";
|
|
51305
|
+
let driftScore = 0;
|
|
51306
|
+
if (!planMd) {
|
|
51307
|
+
alignment = "MINOR_DRIFT";
|
|
51308
|
+
driftScore = 0.3;
|
|
51309
|
+
} else if (warningCompliance.length >= 3) {
|
|
51310
|
+
alignment = "MAJOR_DRIFT";
|
|
51311
|
+
driftScore = Math.min(0.9, 0.5 + warningCompliance.length * 0.1);
|
|
51312
|
+
} else if (warningCompliance.length >= 1 || complianceCount >= 3) {
|
|
51313
|
+
alignment = "MINOR_DRIFT";
|
|
51314
|
+
driftScore = Math.min(0.49, 0.2 + complianceCount * 0.05);
|
|
51315
|
+
}
|
|
51316
|
+
const priorSummaries = priorReports.map((r) => r.injection_summary).filter(Boolean);
|
|
51317
|
+
const keyCorrections = warningCompliance.map((obs) => obs.description);
|
|
51318
|
+
const firstDeviation = warningCompliance.length > 0 ? {
|
|
51319
|
+
phase,
|
|
51320
|
+
task: "unknown",
|
|
51321
|
+
description: warningCompliance[0]?.description ?? ""
|
|
51322
|
+
} : null;
|
|
51323
|
+
const payloadLines = [
|
|
51324
|
+
`CURATOR_DIGEST: ${JSON.stringify(curatorResult.digest)}`,
|
|
51325
|
+
`CURATOR_COMPLIANCE: ${JSON.stringify(curatorResult.compliance)}`,
|
|
51326
|
+
`PLAN: ${planMd ?? "none"}`,
|
|
51327
|
+
`SPEC: ${specMd ?? "none"}`,
|
|
51328
|
+
`PRIOR_DRIFT_REPORTS: ${JSON.stringify(priorSummaries)}`
|
|
51329
|
+
];
|
|
51330
|
+
const payload = payloadLines.join(`
|
|
51331
|
+
`);
|
|
51332
|
+
const requirementsChecked = curatorResult.digest.tasks_total;
|
|
51333
|
+
const requirementsSatisfied = curatorResult.digest.tasks_completed;
|
|
51334
|
+
const injectionSummaryRaw = `Phase ${phase}: ${alignment} (${driftScore.toFixed(2)}) \u2014 ${firstDeviation ? firstDeviation.description : "all requirements on track"}.${keyCorrections.length > 0 ? `Correction: ${keyCorrections[0] ?? ""}.` : ""}`;
|
|
51335
|
+
const injectionSummary = injectionSummaryRaw.slice(0, config3.drift_inject_max_chars);
|
|
51336
|
+
const report = {
|
|
51337
|
+
schema_version: 1,
|
|
51338
|
+
phase,
|
|
51339
|
+
timestamp: new Date().toISOString(),
|
|
51340
|
+
alignment,
|
|
51341
|
+
drift_score: driftScore,
|
|
51342
|
+
first_deviation: firstDeviation,
|
|
51343
|
+
compounding_effects: priorReports.filter((r) => r.alignment !== "ALIGNED").map((r) => `Phase ${r.phase}: ${r.alignment}`).slice(0, 5),
|
|
51344
|
+
corrections: keyCorrections.slice(0, 5),
|
|
51345
|
+
requirements_checked: requirementsChecked,
|
|
51346
|
+
requirements_satisfied: requirementsSatisfied,
|
|
51347
|
+
scope_additions: [],
|
|
51348
|
+
injection_summary: injectionSummary
|
|
51349
|
+
};
|
|
51350
|
+
const reportPath = await writeDriftReport(directory, report);
|
|
51351
|
+
getGlobalEventBus().publish("curator.drift.completed", {
|
|
51352
|
+
phase,
|
|
51353
|
+
alignment,
|
|
51354
|
+
drift_score: driftScore,
|
|
51355
|
+
report_path: reportPath
|
|
51356
|
+
});
|
|
51357
|
+
const injectionText = injectionSummary;
|
|
51358
|
+
return {
|
|
51359
|
+
phase,
|
|
51360
|
+
report,
|
|
51361
|
+
report_path: reportPath,
|
|
51362
|
+
injection_text: injectionText
|
|
51363
|
+
};
|
|
51364
|
+
} catch (err2) {
|
|
51365
|
+
getGlobalEventBus().publish("curator.error", {
|
|
51366
|
+
operation: "drift",
|
|
51367
|
+
phase,
|
|
51368
|
+
error: String(err2)
|
|
51369
|
+
});
|
|
51370
|
+
const defaultReport = {
|
|
51371
|
+
schema_version: 1,
|
|
51372
|
+
phase,
|
|
51373
|
+
timestamp: new Date().toISOString(),
|
|
51374
|
+
alignment: "ALIGNED",
|
|
51375
|
+
drift_score: 0,
|
|
51376
|
+
first_deviation: null,
|
|
51377
|
+
compounding_effects: [],
|
|
51378
|
+
corrections: [],
|
|
51379
|
+
requirements_checked: 0,
|
|
51380
|
+
requirements_satisfied: 0,
|
|
51381
|
+
scope_additions: [],
|
|
51382
|
+
injection_summary: `Phase ${phase}: drift analysis unavailable (${String(err2)})`
|
|
51383
|
+
};
|
|
51384
|
+
return {
|
|
51385
|
+
phase,
|
|
51386
|
+
report: defaultReport,
|
|
51387
|
+
report_path: "",
|
|
51388
|
+
injection_text: ""
|
|
51389
|
+
};
|
|
51390
|
+
}
|
|
51391
|
+
}
|
|
51392
|
+
function buildDriftInjectionText(report, maxChars) {
|
|
51393
|
+
if (maxChars <= 0) {
|
|
51394
|
+
return "";
|
|
51395
|
+
}
|
|
51396
|
+
let text;
|
|
51397
|
+
if (report.alignment === "ALIGNED" && report.drift_score < 0.1) {
|
|
51398
|
+
text = `<drift_report>Phase ${report.phase}: ALIGNED, all requirements on track.</drift_report>`;
|
|
51399
|
+
} else {
|
|
51400
|
+
const keyFinding = report.first_deviation?.description ?? "no deviation recorded";
|
|
51401
|
+
const score = report.drift_score ?? 0;
|
|
51402
|
+
const correctionClause = report.corrections?.[0] ? `Correction: ${report.corrections[0]}.` : "";
|
|
51403
|
+
text = `<drift_report>Phase ${report.phase}: ${report.alignment} (${score.toFixed(2)}) \u2014 ${keyFinding}. ${correctionClause}</drift_report>`;
|
|
51404
|
+
}
|
|
51405
|
+
return text.slice(0, maxChars);
|
|
51406
|
+
}
|
|
51407
|
+
|
|
50826
51408
|
// src/hooks/knowledge-injector.ts
|
|
50827
51409
|
init_utils2();
|
|
50828
51410
|
function formatStars(confidence) {
|
|
@@ -50924,9 +51506,9 @@ function createKnowledgeInjectorHook(directory, config3) {
|
|
|
50924
51506
|
].join(`
|
|
50925
51507
|
`);
|
|
50926
51508
|
if (runMemory) {
|
|
50927
|
-
cachedInjectionText = runMemory
|
|
51509
|
+
cachedInjectionText = `${runMemory}
|
|
50928
51510
|
|
|
50929
|
-
|
|
51511
|
+
${knowledgeSection}`;
|
|
50930
51512
|
} else {
|
|
50931
51513
|
cachedInjectionText = knowledgeSection;
|
|
50932
51514
|
}
|
|
@@ -50940,13 +51522,25 @@ function createKnowledgeInjectorHook(directory, config3) {
|
|
|
50940
51522
|
` + rejectedLines.join(`
|
|
50941
51523
|
`);
|
|
50942
51524
|
}
|
|
51525
|
+
try {
|
|
51526
|
+
const driftReports = await readPriorDriftReports(directory);
|
|
51527
|
+
if (driftReports.length > 0 && cachedInjectionText !== null) {
|
|
51528
|
+
const latestReport = driftReports[driftReports.length - 1];
|
|
51529
|
+
const driftText = buildDriftInjectionText(latestReport, 500);
|
|
51530
|
+
if (driftText) {
|
|
51531
|
+
cachedInjectionText = `${driftText}
|
|
51532
|
+
|
|
51533
|
+
${cachedInjectionText}`;
|
|
51534
|
+
}
|
|
51535
|
+
}
|
|
51536
|
+
} catch {}
|
|
50943
51537
|
injectKnowledgeMessage(output, cachedInjectionText);
|
|
50944
51538
|
});
|
|
50945
51539
|
}
|
|
50946
51540
|
|
|
50947
51541
|
// src/hooks/steering-consumed.ts
|
|
50948
51542
|
init_utils2();
|
|
50949
|
-
import * as
|
|
51543
|
+
import * as fs18 from "fs";
|
|
50950
51544
|
function recordSteeringConsumed(directory, directiveId) {
|
|
50951
51545
|
try {
|
|
50952
51546
|
const eventsPath = validateSwarmPath(directory, "events.jsonl");
|
|
@@ -50955,7 +51549,7 @@ function recordSteeringConsumed(directory, directiveId) {
|
|
|
50955
51549
|
directiveId,
|
|
50956
51550
|
timestamp: new Date().toISOString()
|
|
50957
51551
|
};
|
|
50958
|
-
|
|
51552
|
+
fs18.appendFileSync(eventsPath, `${JSON.stringify(event)}
|
|
50959
51553
|
`, "utf-8");
|
|
50960
51554
|
} catch {}
|
|
50961
51555
|
}
|
|
@@ -51000,6 +51594,27 @@ init_config_doctor();
|
|
|
51000
51594
|
|
|
51001
51595
|
// src/session/snapshot-reader.ts
|
|
51002
51596
|
init_utils2();
|
|
51597
|
+
import path30 from "path";
|
|
51598
|
+
var VALID_TASK_WORKFLOW_STATES = [
|
|
51599
|
+
"idle",
|
|
51600
|
+
"coder_delegated",
|
|
51601
|
+
"pre_check_passed",
|
|
51602
|
+
"reviewer_run",
|
|
51603
|
+
"tests_run",
|
|
51604
|
+
"complete"
|
|
51605
|
+
];
|
|
51606
|
+
function deserializeTaskWorkflowStates(raw) {
|
|
51607
|
+
const m = new Map;
|
|
51608
|
+
if (!raw || typeof raw !== "object") {
|
|
51609
|
+
return m;
|
|
51610
|
+
}
|
|
51611
|
+
for (const [taskId, stateVal] of Object.entries(raw)) {
|
|
51612
|
+
if (VALID_TASK_WORKFLOW_STATES.includes(stateVal)) {
|
|
51613
|
+
m.set(taskId, stateVal);
|
|
51614
|
+
}
|
|
51615
|
+
}
|
|
51616
|
+
return m;
|
|
51617
|
+
}
|
|
51003
51618
|
function deserializeAgentSession(s) {
|
|
51004
51619
|
const gateLog = new Map;
|
|
51005
51620
|
if (s.gateLog) {
|
|
@@ -51042,7 +51657,7 @@ function deserializeAgentSession(s) {
|
|
|
51042
51657
|
phaseAgentsDispatched,
|
|
51043
51658
|
qaSkipCount: s.qaSkipCount ?? 0,
|
|
51044
51659
|
qaSkipTaskIds: s.qaSkipTaskIds ?? [],
|
|
51045
|
-
taskWorkflowStates:
|
|
51660
|
+
taskWorkflowStates: deserializeTaskWorkflowStates(s.taskWorkflowStates),
|
|
51046
51661
|
lastGateOutcome: null,
|
|
51047
51662
|
declaredCoderScope: null,
|
|
51048
51663
|
lastScopeViolation: null,
|
|
@@ -51096,11 +51711,53 @@ function rehydrateState(snapshot) {
|
|
|
51096
51711
|
}
|
|
51097
51712
|
}
|
|
51098
51713
|
}
|
|
51714
|
+
async function reconcileTaskStatesFromPlan(directory) {
|
|
51715
|
+
let raw;
|
|
51716
|
+
try {
|
|
51717
|
+
raw = await Bun.file(path30.join(directory, ".swarm/plan.json")).text();
|
|
51718
|
+
} catch {
|
|
51719
|
+
return;
|
|
51720
|
+
}
|
|
51721
|
+
let plan;
|
|
51722
|
+
try {
|
|
51723
|
+
plan = JSON.parse(raw);
|
|
51724
|
+
} catch {
|
|
51725
|
+
return;
|
|
51726
|
+
}
|
|
51727
|
+
if (!plan?.phases || !Array.isArray(plan.phases)) {
|
|
51728
|
+
return;
|
|
51729
|
+
}
|
|
51730
|
+
for (const phase of plan.phases) {
|
|
51731
|
+
if (!phase?.tasks || !Array.isArray(phase.tasks)) {
|
|
51732
|
+
continue;
|
|
51733
|
+
}
|
|
51734
|
+
for (const task of phase.tasks) {
|
|
51735
|
+
if (!task?.id || typeof task.id !== "string") {
|
|
51736
|
+
continue;
|
|
51737
|
+
}
|
|
51738
|
+
const taskId = task.id;
|
|
51739
|
+
const planStatus = task.status;
|
|
51740
|
+
for (const session of swarmState.agentSessions.values()) {
|
|
51741
|
+
const currentState = getTaskState(session, taskId);
|
|
51742
|
+
if (planStatus === "completed" && currentState !== "tests_run" && currentState !== "complete") {
|
|
51743
|
+
try {
|
|
51744
|
+
advanceTaskState(session, taskId, "tests_run");
|
|
51745
|
+
} catch {}
|
|
51746
|
+
} else if (planStatus === "in_progress" && currentState === "idle") {
|
|
51747
|
+
try {
|
|
51748
|
+
advanceTaskState(session, taskId, "coder_delegated");
|
|
51749
|
+
} catch {}
|
|
51750
|
+
}
|
|
51751
|
+
}
|
|
51752
|
+
}
|
|
51753
|
+
}
|
|
51754
|
+
}
|
|
51099
51755
|
async function loadSnapshot(directory) {
|
|
51100
51756
|
try {
|
|
51101
51757
|
const snapshot = await readSnapshot(directory);
|
|
51102
51758
|
if (snapshot !== null) {
|
|
51103
51759
|
rehydrateState(snapshot);
|
|
51760
|
+
await reconcileTaskStatesFromPlan(directory);
|
|
51104
51761
|
}
|
|
51105
51762
|
} catch {}
|
|
51106
51763
|
}
|
|
@@ -51280,8 +51937,8 @@ var build_check = createSwarmTool({
|
|
|
51280
51937
|
init_tool();
|
|
51281
51938
|
init_create_tool();
|
|
51282
51939
|
import { spawnSync } from "child_process";
|
|
51283
|
-
import * as
|
|
51284
|
-
import * as
|
|
51940
|
+
import * as fs19 from "fs";
|
|
51941
|
+
import * as path31 from "path";
|
|
51285
51942
|
var CHECKPOINT_LOG_PATH = ".swarm/checkpoints.json";
|
|
51286
51943
|
var MAX_LABEL_LENGTH = 100;
|
|
51287
51944
|
var GIT_TIMEOUT_MS = 30000;
|
|
@@ -51332,13 +51989,13 @@ function validateLabel(label) {
|
|
|
51332
51989
|
return null;
|
|
51333
51990
|
}
|
|
51334
51991
|
function getCheckpointLogPath(directory) {
|
|
51335
|
-
return
|
|
51992
|
+
return path31.join(directory, CHECKPOINT_LOG_PATH);
|
|
51336
51993
|
}
|
|
51337
51994
|
function readCheckpointLog(directory) {
|
|
51338
51995
|
const logPath = getCheckpointLogPath(directory);
|
|
51339
51996
|
try {
|
|
51340
|
-
if (
|
|
51341
|
-
const content =
|
|
51997
|
+
if (fs19.existsSync(logPath)) {
|
|
51998
|
+
const content = fs19.readFileSync(logPath, "utf-8");
|
|
51342
51999
|
const parsed = JSON.parse(content);
|
|
51343
52000
|
if (!parsed.checkpoints || !Array.isArray(parsed.checkpoints)) {
|
|
51344
52001
|
return { version: 1, checkpoints: [] };
|
|
@@ -51350,13 +52007,13 @@ function readCheckpointLog(directory) {
|
|
|
51350
52007
|
}
|
|
51351
52008
|
function writeCheckpointLog(log2, directory) {
|
|
51352
52009
|
const logPath = getCheckpointLogPath(directory);
|
|
51353
|
-
const dir =
|
|
51354
|
-
if (!
|
|
51355
|
-
|
|
52010
|
+
const dir = path31.dirname(logPath);
|
|
52011
|
+
if (!fs19.existsSync(dir)) {
|
|
52012
|
+
fs19.mkdirSync(dir, { recursive: true });
|
|
51356
52013
|
}
|
|
51357
52014
|
const tempPath = `${logPath}.tmp`;
|
|
51358
|
-
|
|
51359
|
-
|
|
52015
|
+
fs19.writeFileSync(tempPath, JSON.stringify(log2, null, 2), "utf-8");
|
|
52016
|
+
fs19.renameSync(tempPath, logPath);
|
|
51360
52017
|
}
|
|
51361
52018
|
function gitExec(args2) {
|
|
51362
52019
|
const result = spawnSync("git", args2, {
|
|
@@ -51557,8 +52214,8 @@ var checkpoint = createSwarmTool({
|
|
|
51557
52214
|
// src/tools/complexity-hotspots.ts
|
|
51558
52215
|
init_dist();
|
|
51559
52216
|
init_create_tool();
|
|
51560
|
-
import * as
|
|
51561
|
-
import * as
|
|
52217
|
+
import * as fs20 from "fs";
|
|
52218
|
+
import * as path32 from "path";
|
|
51562
52219
|
var MAX_FILE_SIZE_BYTES2 = 256 * 1024;
|
|
51563
52220
|
var DEFAULT_DAYS = 90;
|
|
51564
52221
|
var DEFAULT_TOP_N = 20;
|
|
@@ -51687,11 +52344,11 @@ function estimateComplexity(content) {
|
|
|
51687
52344
|
}
|
|
51688
52345
|
function getComplexityForFile(filePath) {
|
|
51689
52346
|
try {
|
|
51690
|
-
const stat2 =
|
|
52347
|
+
const stat2 = fs20.statSync(filePath);
|
|
51691
52348
|
if (stat2.size > MAX_FILE_SIZE_BYTES2) {
|
|
51692
52349
|
return null;
|
|
51693
52350
|
}
|
|
51694
|
-
const content =
|
|
52351
|
+
const content = fs20.readFileSync(filePath, "utf-8");
|
|
51695
52352
|
return estimateComplexity(content);
|
|
51696
52353
|
} catch {
|
|
51697
52354
|
return null;
|
|
@@ -51702,7 +52359,7 @@ async function analyzeHotspots(days, topN, extensions, directory) {
|
|
|
51702
52359
|
const extSet = new Set(extensions.map((e) => e.startsWith(".") ? e : `.${e}`));
|
|
51703
52360
|
const filteredChurn = new Map;
|
|
51704
52361
|
for (const [file3, count] of churnMap) {
|
|
51705
|
-
const ext =
|
|
52362
|
+
const ext = path32.extname(file3).toLowerCase();
|
|
51706
52363
|
if (extSet.has(ext)) {
|
|
51707
52364
|
filteredChurn.set(file3, count);
|
|
51708
52365
|
}
|
|
@@ -51712,8 +52369,8 @@ async function analyzeHotspots(days, topN, extensions, directory) {
|
|
|
51712
52369
|
let analyzedFiles = 0;
|
|
51713
52370
|
for (const [file3, churnCount] of filteredChurn) {
|
|
51714
52371
|
let fullPath = file3;
|
|
51715
|
-
if (!
|
|
51716
|
-
fullPath =
|
|
52372
|
+
if (!fs20.existsSync(fullPath)) {
|
|
52373
|
+
fullPath = path32.join(cwd, file3);
|
|
51717
52374
|
}
|
|
51718
52375
|
const complexity = getComplexityForFile(fullPath);
|
|
51719
52376
|
if (complexity !== null) {
|
|
@@ -51860,8 +52517,8 @@ var complexity_hotspots = createSwarmTool({
|
|
|
51860
52517
|
});
|
|
51861
52518
|
// src/tools/declare-scope.ts
|
|
51862
52519
|
init_tool();
|
|
51863
|
-
import * as
|
|
51864
|
-
import * as
|
|
52520
|
+
import * as fs21 from "fs";
|
|
52521
|
+
import * as path33 from "path";
|
|
51865
52522
|
init_create_tool();
|
|
51866
52523
|
function validateTaskIdFormat(taskId) {
|
|
51867
52524
|
const taskIdPattern = /^\d+\.\d+(\.\d+)*$/;
|
|
@@ -51940,8 +52597,8 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
51940
52597
|
};
|
|
51941
52598
|
}
|
|
51942
52599
|
}
|
|
51943
|
-
normalizedDir =
|
|
51944
|
-
const pathParts = normalizedDir.split(
|
|
52600
|
+
normalizedDir = path33.normalize(args2.working_directory);
|
|
52601
|
+
const pathParts = normalizedDir.split(path33.sep);
|
|
51945
52602
|
if (pathParts.includes("..")) {
|
|
51946
52603
|
return {
|
|
51947
52604
|
success: false,
|
|
@@ -51951,11 +52608,11 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
51951
52608
|
]
|
|
51952
52609
|
};
|
|
51953
52610
|
}
|
|
51954
|
-
const resolvedDir =
|
|
52611
|
+
const resolvedDir = path33.resolve(normalizedDir);
|
|
51955
52612
|
try {
|
|
51956
|
-
const realPath =
|
|
51957
|
-
const planPath2 =
|
|
51958
|
-
if (!
|
|
52613
|
+
const realPath = fs21.realpathSync(resolvedDir);
|
|
52614
|
+
const planPath2 = path33.join(realPath, ".swarm", "plan.json");
|
|
52615
|
+
if (!fs21.existsSync(planPath2)) {
|
|
51959
52616
|
return {
|
|
51960
52617
|
success: false,
|
|
51961
52618
|
message: `Invalid working_directory: plan not found in "${realPath}"`,
|
|
@@ -51975,8 +52632,8 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
51975
52632
|
}
|
|
51976
52633
|
}
|
|
51977
52634
|
const directory = normalizedDir ?? fallbackDir ?? process.cwd();
|
|
51978
|
-
const planPath =
|
|
51979
|
-
if (!
|
|
52635
|
+
const planPath = path33.resolve(directory, ".swarm", "plan.json");
|
|
52636
|
+
if (!fs21.existsSync(planPath)) {
|
|
51980
52637
|
return {
|
|
51981
52638
|
success: false,
|
|
51982
52639
|
message: "No plan found",
|
|
@@ -51985,7 +52642,7 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
51985
52642
|
}
|
|
51986
52643
|
let planContent;
|
|
51987
52644
|
try {
|
|
51988
|
-
planContent = JSON.parse(
|
|
52645
|
+
planContent = JSON.parse(fs21.readFileSync(planPath, "utf-8"));
|
|
51989
52646
|
} catch {
|
|
51990
52647
|
return {
|
|
51991
52648
|
success: false,
|
|
@@ -52065,20 +52722,20 @@ function validateBase(base) {
|
|
|
52065
52722
|
function validatePaths(paths) {
|
|
52066
52723
|
if (!paths)
|
|
52067
52724
|
return null;
|
|
52068
|
-
for (const
|
|
52069
|
-
if (!
|
|
52725
|
+
for (const path34 of paths) {
|
|
52726
|
+
if (!path34 || path34.length === 0) {
|
|
52070
52727
|
return "empty path not allowed";
|
|
52071
52728
|
}
|
|
52072
|
-
if (
|
|
52729
|
+
if (path34.length > MAX_PATH_LENGTH) {
|
|
52073
52730
|
return `path exceeds maximum length of ${MAX_PATH_LENGTH}`;
|
|
52074
52731
|
}
|
|
52075
|
-
if (SHELL_METACHARACTERS2.test(
|
|
52732
|
+
if (SHELL_METACHARACTERS2.test(path34)) {
|
|
52076
52733
|
return "path contains shell metacharacters";
|
|
52077
52734
|
}
|
|
52078
|
-
if (
|
|
52735
|
+
if (path34.startsWith("-")) {
|
|
52079
52736
|
return 'path cannot start with "-" (option-like arguments not allowed)';
|
|
52080
52737
|
}
|
|
52081
|
-
if (CONTROL_CHAR_PATTERN2.test(
|
|
52738
|
+
if (CONTROL_CHAR_PATTERN2.test(path34)) {
|
|
52082
52739
|
return "path contains control characters";
|
|
52083
52740
|
}
|
|
52084
52741
|
}
|
|
@@ -52158,8 +52815,8 @@ var diff = tool({
|
|
|
52158
52815
|
if (parts2.length >= 3) {
|
|
52159
52816
|
const additions = parseInt(parts2[0], 10) || 0;
|
|
52160
52817
|
const deletions = parseInt(parts2[1], 10) || 0;
|
|
52161
|
-
const
|
|
52162
|
-
files.push({ path:
|
|
52818
|
+
const path34 = parts2[2];
|
|
52819
|
+
files.push({ path: path34, additions, deletions });
|
|
52163
52820
|
}
|
|
52164
52821
|
}
|
|
52165
52822
|
const contractChanges = [];
|
|
@@ -52388,8 +53045,8 @@ Use these as DOMAIN values when delegating to @sme.`;
|
|
|
52388
53045
|
// src/tools/evidence-check.ts
|
|
52389
53046
|
init_dist();
|
|
52390
53047
|
init_create_tool();
|
|
52391
|
-
import * as
|
|
52392
|
-
import * as
|
|
53048
|
+
import * as fs22 from "fs";
|
|
53049
|
+
import * as path34 from "path";
|
|
52393
53050
|
var MAX_FILE_SIZE_BYTES3 = 1024 * 1024;
|
|
52394
53051
|
var MAX_EVIDENCE_FILES = 1000;
|
|
52395
53052
|
var EVIDENCE_DIR = ".swarm/evidence";
|
|
@@ -52412,9 +53069,9 @@ function validateRequiredTypes(input) {
|
|
|
52412
53069
|
return null;
|
|
52413
53070
|
}
|
|
52414
53071
|
function isPathWithinSwarm(filePath, cwd) {
|
|
52415
|
-
const normalizedCwd =
|
|
52416
|
-
const swarmPath =
|
|
52417
|
-
const normalizedPath =
|
|
53072
|
+
const normalizedCwd = path34.resolve(cwd);
|
|
53073
|
+
const swarmPath = path34.join(normalizedCwd, ".swarm");
|
|
53074
|
+
const normalizedPath = path34.resolve(filePath);
|
|
52418
53075
|
return normalizedPath.startsWith(swarmPath);
|
|
52419
53076
|
}
|
|
52420
53077
|
function parseCompletedTasks(planContent) {
|
|
@@ -52430,12 +53087,12 @@ function parseCompletedTasks(planContent) {
|
|
|
52430
53087
|
}
|
|
52431
53088
|
function readEvidenceFiles(evidenceDir, _cwd) {
|
|
52432
53089
|
const evidence = [];
|
|
52433
|
-
if (!
|
|
53090
|
+
if (!fs22.existsSync(evidenceDir) || !fs22.statSync(evidenceDir).isDirectory()) {
|
|
52434
53091
|
return evidence;
|
|
52435
53092
|
}
|
|
52436
53093
|
let files;
|
|
52437
53094
|
try {
|
|
52438
|
-
files =
|
|
53095
|
+
files = fs22.readdirSync(evidenceDir);
|
|
52439
53096
|
} catch {
|
|
52440
53097
|
return evidence;
|
|
52441
53098
|
}
|
|
@@ -52444,14 +53101,14 @@ function readEvidenceFiles(evidenceDir, _cwd) {
|
|
|
52444
53101
|
if (!VALID_EVIDENCE_FILENAME_REGEX.test(filename)) {
|
|
52445
53102
|
continue;
|
|
52446
53103
|
}
|
|
52447
|
-
const filePath =
|
|
53104
|
+
const filePath = path34.join(evidenceDir, filename);
|
|
52448
53105
|
try {
|
|
52449
|
-
const resolvedPath =
|
|
52450
|
-
const evidenceDirResolved =
|
|
53106
|
+
const resolvedPath = path34.resolve(filePath);
|
|
53107
|
+
const evidenceDirResolved = path34.resolve(evidenceDir);
|
|
52451
53108
|
if (!resolvedPath.startsWith(evidenceDirResolved)) {
|
|
52452
53109
|
continue;
|
|
52453
53110
|
}
|
|
52454
|
-
const stat2 =
|
|
53111
|
+
const stat2 = fs22.lstatSync(filePath);
|
|
52455
53112
|
if (!stat2.isFile()) {
|
|
52456
53113
|
continue;
|
|
52457
53114
|
}
|
|
@@ -52460,7 +53117,7 @@ function readEvidenceFiles(evidenceDir, _cwd) {
|
|
|
52460
53117
|
}
|
|
52461
53118
|
let fileStat;
|
|
52462
53119
|
try {
|
|
52463
|
-
fileStat =
|
|
53120
|
+
fileStat = fs22.statSync(filePath);
|
|
52464
53121
|
if (fileStat.size > MAX_FILE_SIZE_BYTES3) {
|
|
52465
53122
|
continue;
|
|
52466
53123
|
}
|
|
@@ -52469,7 +53126,7 @@ function readEvidenceFiles(evidenceDir, _cwd) {
|
|
|
52469
53126
|
}
|
|
52470
53127
|
let content;
|
|
52471
53128
|
try {
|
|
52472
|
-
content =
|
|
53129
|
+
content = fs22.readFileSync(filePath, "utf-8");
|
|
52473
53130
|
} catch {
|
|
52474
53131
|
continue;
|
|
52475
53132
|
}
|
|
@@ -52554,7 +53211,7 @@ var evidence_check = createSwarmTool({
|
|
|
52554
53211
|
return JSON.stringify(errorResult, null, 2);
|
|
52555
53212
|
}
|
|
52556
53213
|
const requiredTypes = requiredTypesValue.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
|
|
52557
|
-
const planPath =
|
|
53214
|
+
const planPath = path34.join(cwd, PLAN_FILE);
|
|
52558
53215
|
if (!isPathWithinSwarm(planPath, cwd)) {
|
|
52559
53216
|
const errorResult = {
|
|
52560
53217
|
error: "plan file path validation failed",
|
|
@@ -52568,7 +53225,7 @@ var evidence_check = createSwarmTool({
|
|
|
52568
53225
|
}
|
|
52569
53226
|
let planContent;
|
|
52570
53227
|
try {
|
|
52571
|
-
planContent =
|
|
53228
|
+
planContent = fs22.readFileSync(planPath, "utf-8");
|
|
52572
53229
|
} catch {
|
|
52573
53230
|
const result2 = {
|
|
52574
53231
|
message: "No completed tasks found in plan.",
|
|
@@ -52586,7 +53243,7 @@ var evidence_check = createSwarmTool({
|
|
|
52586
53243
|
};
|
|
52587
53244
|
return JSON.stringify(result2, null, 2);
|
|
52588
53245
|
}
|
|
52589
|
-
const evidenceDir =
|
|
53246
|
+
const evidenceDir = path34.join(cwd, EVIDENCE_DIR);
|
|
52590
53247
|
const evidence = readEvidenceFiles(evidenceDir, cwd);
|
|
52591
53248
|
const { tasksWithFullEvidence, gaps } = analyzeGaps(completedTasks, evidence, requiredTypes);
|
|
52592
53249
|
const completeness = completedTasks.length > 0 ? Math.round(tasksWithFullEvidence.length / completedTasks.length * 100) / 100 : 1;
|
|
@@ -52603,8 +53260,8 @@ var evidence_check = createSwarmTool({
|
|
|
52603
53260
|
// src/tools/file-extractor.ts
|
|
52604
53261
|
init_tool();
|
|
52605
53262
|
init_create_tool();
|
|
52606
|
-
import * as
|
|
52607
|
-
import * as
|
|
53263
|
+
import * as fs23 from "fs";
|
|
53264
|
+
import * as path35 from "path";
|
|
52608
53265
|
var EXT_MAP = {
|
|
52609
53266
|
python: ".py",
|
|
52610
53267
|
py: ".py",
|
|
@@ -52666,8 +53323,8 @@ var extract_code_blocks = createSwarmTool({
|
|
|
52666
53323
|
execute: async (args2, directory) => {
|
|
52667
53324
|
const { content, output_dir, prefix } = args2;
|
|
52668
53325
|
const targetDir = output_dir || directory;
|
|
52669
|
-
if (!
|
|
52670
|
-
|
|
53326
|
+
if (!fs23.existsSync(targetDir)) {
|
|
53327
|
+
fs23.mkdirSync(targetDir, { recursive: true });
|
|
52671
53328
|
}
|
|
52672
53329
|
if (!content) {
|
|
52673
53330
|
return "Error: content is required";
|
|
@@ -52685,16 +53342,16 @@ var extract_code_blocks = createSwarmTool({
|
|
|
52685
53342
|
if (prefix) {
|
|
52686
53343
|
filename = `${prefix}_${filename}`;
|
|
52687
53344
|
}
|
|
52688
|
-
let filepath =
|
|
52689
|
-
const base =
|
|
52690
|
-
const ext =
|
|
53345
|
+
let filepath = path35.join(targetDir, filename);
|
|
53346
|
+
const base = path35.basename(filepath, path35.extname(filepath));
|
|
53347
|
+
const ext = path35.extname(filepath);
|
|
52691
53348
|
let counter = 1;
|
|
52692
|
-
while (
|
|
52693
|
-
filepath =
|
|
53349
|
+
while (fs23.existsSync(filepath)) {
|
|
53350
|
+
filepath = path35.join(targetDir, `${base}_${counter}${ext}`);
|
|
52694
53351
|
counter++;
|
|
52695
53352
|
}
|
|
52696
53353
|
try {
|
|
52697
|
-
|
|
53354
|
+
fs23.writeFileSync(filepath, code.trim(), "utf-8");
|
|
52698
53355
|
savedFiles.push(filepath);
|
|
52699
53356
|
} catch (error93) {
|
|
52700
53357
|
errors5.push(`Failed to save ${filename}: ${error93 instanceof Error ? error93.message : String(error93)}`);
|
|
@@ -52802,8 +53459,8 @@ var gitingest = tool({
|
|
|
52802
53459
|
});
|
|
52803
53460
|
// src/tools/imports.ts
|
|
52804
53461
|
init_dist();
|
|
52805
|
-
import * as
|
|
52806
|
-
import * as
|
|
53462
|
+
import * as fs24 from "fs";
|
|
53463
|
+
import * as path36 from "path";
|
|
52807
53464
|
var MAX_FILE_PATH_LENGTH2 = 500;
|
|
52808
53465
|
var MAX_SYMBOL_LENGTH = 256;
|
|
52809
53466
|
var MAX_FILE_SIZE_BYTES4 = 1024 * 1024;
|
|
@@ -52857,7 +53514,7 @@ function validateSymbolInput(symbol3) {
|
|
|
52857
53514
|
return null;
|
|
52858
53515
|
}
|
|
52859
53516
|
function isBinaryFile2(filePath, buffer) {
|
|
52860
|
-
const ext =
|
|
53517
|
+
const ext = path36.extname(filePath).toLowerCase();
|
|
52861
53518
|
if (ext === ".json" || ext === ".md" || ext === ".txt") {
|
|
52862
53519
|
return false;
|
|
52863
53520
|
}
|
|
@@ -52881,15 +53538,15 @@ function parseImports(content, targetFile, targetSymbol) {
|
|
|
52881
53538
|
const imports = [];
|
|
52882
53539
|
let _resolvedTarget;
|
|
52883
53540
|
try {
|
|
52884
|
-
_resolvedTarget =
|
|
53541
|
+
_resolvedTarget = path36.resolve(targetFile);
|
|
52885
53542
|
} catch {
|
|
52886
53543
|
_resolvedTarget = targetFile;
|
|
52887
53544
|
}
|
|
52888
|
-
const targetBasename =
|
|
53545
|
+
const targetBasename = path36.basename(targetFile, path36.extname(targetFile));
|
|
52889
53546
|
const targetWithExt = targetFile;
|
|
52890
53547
|
const targetWithoutExt = targetFile.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
|
|
52891
|
-
const normalizedTargetWithExt =
|
|
52892
|
-
const normalizedTargetWithoutExt =
|
|
53548
|
+
const normalizedTargetWithExt = path36.normalize(targetWithExt).replace(/\\/g, "/");
|
|
53549
|
+
const normalizedTargetWithoutExt = path36.normalize(targetWithoutExt).replace(/\\/g, "/");
|
|
52893
53550
|
const importRegex = /import\s+(?:\{[\s\S]*?\}|(?:\*\s+as\s+\w+)|\w+)\s+from\s+['"`]([^'"`]+)['"`]|import\s+['"`]([^'"`]+)['"`]|require\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g;
|
|
52894
53551
|
for (let match = importRegex.exec(content);match !== null; match = importRegex.exec(content)) {
|
|
52895
53552
|
const modulePath = match[1] || match[2] || match[3];
|
|
@@ -52912,9 +53569,9 @@ function parseImports(content, targetFile, targetSymbol) {
|
|
|
52912
53569
|
}
|
|
52913
53570
|
const _normalizedModule = modulePath.replace(/^\.\//, "").replace(/^\.\.\\/, "../");
|
|
52914
53571
|
let isMatch = false;
|
|
52915
|
-
const _targetDir =
|
|
52916
|
-
const targetExt =
|
|
52917
|
-
const targetBasenameNoExt =
|
|
53572
|
+
const _targetDir = path36.dirname(targetFile);
|
|
53573
|
+
const targetExt = path36.extname(targetFile);
|
|
53574
|
+
const targetBasenameNoExt = path36.basename(targetFile, targetExt);
|
|
52918
53575
|
const moduleNormalized = modulePath.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
52919
53576
|
const moduleName = modulePath.split(/[/\\]/).pop() || "";
|
|
52920
53577
|
const moduleNameNoExt = moduleName.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
|
|
@@ -52971,7 +53628,7 @@ var SKIP_DIRECTORIES2 = new Set([
|
|
|
52971
53628
|
function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFiles: 0, fileErrors: [] }) {
|
|
52972
53629
|
let entries;
|
|
52973
53630
|
try {
|
|
52974
|
-
entries =
|
|
53631
|
+
entries = fs24.readdirSync(dir);
|
|
52975
53632
|
} catch (e) {
|
|
52976
53633
|
stats.fileErrors.push({
|
|
52977
53634
|
path: dir,
|
|
@@ -52982,13 +53639,13 @@ function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFil
|
|
|
52982
53639
|
entries.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
|
|
52983
53640
|
for (const entry of entries) {
|
|
52984
53641
|
if (SKIP_DIRECTORIES2.has(entry)) {
|
|
52985
|
-
stats.skippedDirs.push(
|
|
53642
|
+
stats.skippedDirs.push(path36.join(dir, entry));
|
|
52986
53643
|
continue;
|
|
52987
53644
|
}
|
|
52988
|
-
const fullPath =
|
|
53645
|
+
const fullPath = path36.join(dir, entry);
|
|
52989
53646
|
let stat2;
|
|
52990
53647
|
try {
|
|
52991
|
-
stat2 =
|
|
53648
|
+
stat2 = fs24.statSync(fullPath);
|
|
52992
53649
|
} catch (e) {
|
|
52993
53650
|
stats.fileErrors.push({
|
|
52994
53651
|
path: fullPath,
|
|
@@ -52999,7 +53656,7 @@ function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFil
|
|
|
52999
53656
|
if (stat2.isDirectory()) {
|
|
53000
53657
|
findSourceFiles2(fullPath, files, stats);
|
|
53001
53658
|
} else if (stat2.isFile()) {
|
|
53002
|
-
const ext =
|
|
53659
|
+
const ext = path36.extname(fullPath).toLowerCase();
|
|
53003
53660
|
if (SUPPORTED_EXTENSIONS.includes(ext)) {
|
|
53004
53661
|
files.push(fullPath);
|
|
53005
53662
|
}
|
|
@@ -53055,8 +53712,8 @@ var imports = tool({
|
|
|
53055
53712
|
return JSON.stringify(errorResult, null, 2);
|
|
53056
53713
|
}
|
|
53057
53714
|
try {
|
|
53058
|
-
const targetFile =
|
|
53059
|
-
if (!
|
|
53715
|
+
const targetFile = path36.resolve(file3);
|
|
53716
|
+
if (!fs24.existsSync(targetFile)) {
|
|
53060
53717
|
const errorResult = {
|
|
53061
53718
|
error: `target file not found: ${file3}`,
|
|
53062
53719
|
target: file3,
|
|
@@ -53066,7 +53723,7 @@ var imports = tool({
|
|
|
53066
53723
|
};
|
|
53067
53724
|
return JSON.stringify(errorResult, null, 2);
|
|
53068
53725
|
}
|
|
53069
|
-
const targetStat =
|
|
53726
|
+
const targetStat = fs24.statSync(targetFile);
|
|
53070
53727
|
if (!targetStat.isFile()) {
|
|
53071
53728
|
const errorResult = {
|
|
53072
53729
|
error: "target must be a file, not a directory",
|
|
@@ -53077,7 +53734,7 @@ var imports = tool({
|
|
|
53077
53734
|
};
|
|
53078
53735
|
return JSON.stringify(errorResult, null, 2);
|
|
53079
53736
|
}
|
|
53080
|
-
const baseDir =
|
|
53737
|
+
const baseDir = path36.dirname(targetFile);
|
|
53081
53738
|
const scanStats = {
|
|
53082
53739
|
skippedDirs: [],
|
|
53083
53740
|
skippedFiles: 0,
|
|
@@ -53092,12 +53749,12 @@ var imports = tool({
|
|
|
53092
53749
|
if (consumers.length >= MAX_CONSUMERS)
|
|
53093
53750
|
break;
|
|
53094
53751
|
try {
|
|
53095
|
-
const stat2 =
|
|
53752
|
+
const stat2 = fs24.statSync(filePath);
|
|
53096
53753
|
if (stat2.size > MAX_FILE_SIZE_BYTES4) {
|
|
53097
53754
|
skippedFileCount++;
|
|
53098
53755
|
continue;
|
|
53099
53756
|
}
|
|
53100
|
-
const buffer =
|
|
53757
|
+
const buffer = fs24.readFileSync(filePath);
|
|
53101
53758
|
if (isBinaryFile2(filePath, buffer)) {
|
|
53102
53759
|
skippedFileCount++;
|
|
53103
53760
|
continue;
|
|
@@ -53166,8 +53823,8 @@ init_lint();
|
|
|
53166
53823
|
|
|
53167
53824
|
// src/tools/phase-complete.ts
|
|
53168
53825
|
init_dist();
|
|
53169
|
-
import * as
|
|
53170
|
-
import * as
|
|
53826
|
+
import * as fs25 from "fs";
|
|
53827
|
+
import * as path37 from "path";
|
|
53171
53828
|
init_manager();
|
|
53172
53829
|
init_utils2();
|
|
53173
53830
|
init_create_tool();
|
|
@@ -53357,7 +54014,7 @@ async function executePhaseComplete(args2, workingDirectory) {
|
|
|
53357
54014
|
}
|
|
53358
54015
|
if (retroFound && retroEntry?.lessons_learned && retroEntry.lessons_learned.length > 0) {
|
|
53359
54016
|
try {
|
|
53360
|
-
const projectName =
|
|
54017
|
+
const projectName = path37.basename(dir);
|
|
53361
54018
|
const knowledgeConfig = {
|
|
53362
54019
|
enabled: true,
|
|
53363
54020
|
swarm_max_entries: 100,
|
|
@@ -53380,6 +54037,16 @@ async function executePhaseComplete(args2, workingDirectory) {
|
|
|
53380
54037
|
console.warn("[phase_complete] Failed to curate lessons from retrospective:", error93);
|
|
53381
54038
|
}
|
|
53382
54039
|
}
|
|
54040
|
+
try {
|
|
54041
|
+
const curatorConfig = CuratorConfigSchema.parse(config3.curator ?? {});
|
|
54042
|
+
if (curatorConfig.enabled && curatorConfig.phase_enabled) {
|
|
54043
|
+
const curatorResult = await runCuratorPhase(dir, phase, agentsDispatched, curatorConfig, {});
|
|
54044
|
+
await applyCuratorKnowledgeUpdates(dir, curatorResult.knowledge_recommendations, {});
|
|
54045
|
+
await runCriticDriftCheck(dir, phase, curatorResult, curatorConfig);
|
|
54046
|
+
}
|
|
54047
|
+
} catch (curatorError) {
|
|
54048
|
+
console.warn("[phase_complete] Curator pipeline error (non-blocking):", curatorError);
|
|
54049
|
+
}
|
|
53383
54050
|
const effectiveRequired = [...phaseCompleteConfig.required_agents];
|
|
53384
54051
|
if (phaseCompleteConfig.require_docs && !effectiveRequired.includes("docs")) {
|
|
53385
54052
|
effectiveRequired.push("docs");
|
|
@@ -53418,7 +54085,7 @@ async function executePhaseComplete(args2, workingDirectory) {
|
|
|
53418
54085
|
};
|
|
53419
54086
|
try {
|
|
53420
54087
|
const eventsPath = validateSwarmPath(dir, "events.jsonl");
|
|
53421
|
-
|
|
54088
|
+
fs25.appendFileSync(eventsPath, `${JSON.stringify(event)}
|
|
53422
54089
|
`, "utf-8");
|
|
53423
54090
|
} catch (writeError) {
|
|
53424
54091
|
warnings.push(`Warning: failed to write phase complete event: ${writeError instanceof Error ? writeError.message : String(writeError)}`);
|
|
@@ -53476,8 +54143,8 @@ init_dist();
|
|
|
53476
54143
|
init_discovery();
|
|
53477
54144
|
init_utils();
|
|
53478
54145
|
init_create_tool();
|
|
53479
|
-
import * as
|
|
53480
|
-
import * as
|
|
54146
|
+
import * as fs26 from "fs";
|
|
54147
|
+
import * as path38 from "path";
|
|
53481
54148
|
var MAX_OUTPUT_BYTES5 = 52428800;
|
|
53482
54149
|
var AUDIT_TIMEOUT_MS = 120000;
|
|
53483
54150
|
function isValidEcosystem(value) {
|
|
@@ -53495,28 +54162,28 @@ function validateArgs3(args2) {
|
|
|
53495
54162
|
function detectEcosystems(directory) {
|
|
53496
54163
|
const ecosystems = [];
|
|
53497
54164
|
const cwd = directory;
|
|
53498
|
-
if (
|
|
54165
|
+
if (fs26.existsSync(path38.join(cwd, "package.json"))) {
|
|
53499
54166
|
ecosystems.push("npm");
|
|
53500
54167
|
}
|
|
53501
|
-
if (
|
|
54168
|
+
if (fs26.existsSync(path38.join(cwd, "pyproject.toml")) || fs26.existsSync(path38.join(cwd, "requirements.txt"))) {
|
|
53502
54169
|
ecosystems.push("pip");
|
|
53503
54170
|
}
|
|
53504
|
-
if (
|
|
54171
|
+
if (fs26.existsSync(path38.join(cwd, "Cargo.toml"))) {
|
|
53505
54172
|
ecosystems.push("cargo");
|
|
53506
54173
|
}
|
|
53507
|
-
if (
|
|
54174
|
+
if (fs26.existsSync(path38.join(cwd, "go.mod"))) {
|
|
53508
54175
|
ecosystems.push("go");
|
|
53509
54176
|
}
|
|
53510
54177
|
try {
|
|
53511
|
-
const files =
|
|
54178
|
+
const files = fs26.readdirSync(cwd);
|
|
53512
54179
|
if (files.some((f) => f.endsWith(".csproj") || f.endsWith(".sln"))) {
|
|
53513
54180
|
ecosystems.push("dotnet");
|
|
53514
54181
|
}
|
|
53515
54182
|
} catch {}
|
|
53516
|
-
if (
|
|
54183
|
+
if (fs26.existsSync(path38.join(cwd, "Gemfile")) || fs26.existsSync(path38.join(cwd, "Gemfile.lock"))) {
|
|
53517
54184
|
ecosystems.push("ruby");
|
|
53518
54185
|
}
|
|
53519
|
-
if (
|
|
54186
|
+
if (fs26.existsSync(path38.join(cwd, "pubspec.yaml"))) {
|
|
53520
54187
|
ecosystems.push("dart");
|
|
53521
54188
|
}
|
|
53522
54189
|
return ecosystems;
|
|
@@ -54577,8 +55244,8 @@ var SUPPORTED_PARSER_EXTENSIONS = new Set([
|
|
|
54577
55244
|
]);
|
|
54578
55245
|
// src/tools/pre-check-batch.ts
|
|
54579
55246
|
init_dist();
|
|
54580
|
-
import * as
|
|
54581
|
-
import * as
|
|
55247
|
+
import * as fs29 from "fs";
|
|
55248
|
+
import * as path41 from "path";
|
|
54582
55249
|
|
|
54583
55250
|
// node_modules/yocto-queue/index.js
|
|
54584
55251
|
class Node2 {
|
|
@@ -54723,8 +55390,8 @@ function pLimit(concurrency) {
|
|
|
54723
55390
|
},
|
|
54724
55391
|
map: {
|
|
54725
55392
|
async value(iterable, function_) {
|
|
54726
|
-
const
|
|
54727
|
-
return Promise.all(
|
|
55393
|
+
const promises2 = Array.from(iterable, (value, index) => this(function_, value, index));
|
|
55394
|
+
return Promise.all(promises2);
|
|
54728
55395
|
}
|
|
54729
55396
|
}
|
|
54730
55397
|
});
|
|
@@ -54745,8 +55412,8 @@ init_lint();
|
|
|
54745
55412
|
init_manager();
|
|
54746
55413
|
|
|
54747
55414
|
// src/quality/metrics.ts
|
|
54748
|
-
import * as
|
|
54749
|
-
import * as
|
|
55415
|
+
import * as fs27 from "fs";
|
|
55416
|
+
import * as path39 from "path";
|
|
54750
55417
|
var MAX_FILE_SIZE_BYTES5 = 256 * 1024;
|
|
54751
55418
|
var MIN_DUPLICATION_LINES = 10;
|
|
54752
55419
|
function estimateCyclomaticComplexity(content) {
|
|
@@ -54784,11 +55451,11 @@ function estimateCyclomaticComplexity(content) {
|
|
|
54784
55451
|
}
|
|
54785
55452
|
function getComplexityForFile2(filePath) {
|
|
54786
55453
|
try {
|
|
54787
|
-
const stat2 =
|
|
55454
|
+
const stat2 = fs27.statSync(filePath);
|
|
54788
55455
|
if (stat2.size > MAX_FILE_SIZE_BYTES5) {
|
|
54789
55456
|
return null;
|
|
54790
55457
|
}
|
|
54791
|
-
const content =
|
|
55458
|
+
const content = fs27.readFileSync(filePath, "utf-8");
|
|
54792
55459
|
return estimateCyclomaticComplexity(content);
|
|
54793
55460
|
} catch {
|
|
54794
55461
|
return null;
|
|
@@ -54798,8 +55465,8 @@ async function computeComplexityDelta(files, workingDir) {
|
|
|
54798
55465
|
let totalComplexity = 0;
|
|
54799
55466
|
const analyzedFiles = [];
|
|
54800
55467
|
for (const file3 of files) {
|
|
54801
|
-
const fullPath =
|
|
54802
|
-
if (!
|
|
55468
|
+
const fullPath = path39.isAbsolute(file3) ? file3 : path39.join(workingDir, file3);
|
|
55469
|
+
if (!fs27.existsSync(fullPath)) {
|
|
54803
55470
|
continue;
|
|
54804
55471
|
}
|
|
54805
55472
|
const complexity = getComplexityForFile2(fullPath);
|
|
@@ -54920,8 +55587,8 @@ function countGoExports(content) {
|
|
|
54920
55587
|
}
|
|
54921
55588
|
function getExportCountForFile(filePath) {
|
|
54922
55589
|
try {
|
|
54923
|
-
const content =
|
|
54924
|
-
const ext =
|
|
55590
|
+
const content = fs27.readFileSync(filePath, "utf-8");
|
|
55591
|
+
const ext = path39.extname(filePath).toLowerCase();
|
|
54925
55592
|
switch (ext) {
|
|
54926
55593
|
case ".ts":
|
|
54927
55594
|
case ".tsx":
|
|
@@ -54947,8 +55614,8 @@ async function computePublicApiDelta(files, workingDir) {
|
|
|
54947
55614
|
let totalExports = 0;
|
|
54948
55615
|
const analyzedFiles = [];
|
|
54949
55616
|
for (const file3 of files) {
|
|
54950
|
-
const fullPath =
|
|
54951
|
-
if (!
|
|
55617
|
+
const fullPath = path39.isAbsolute(file3) ? file3 : path39.join(workingDir, file3);
|
|
55618
|
+
if (!fs27.existsSync(fullPath)) {
|
|
54952
55619
|
continue;
|
|
54953
55620
|
}
|
|
54954
55621
|
const exports = getExportCountForFile(fullPath);
|
|
@@ -54981,16 +55648,16 @@ async function computeDuplicationRatio(files, workingDir) {
|
|
|
54981
55648
|
let duplicateLines = 0;
|
|
54982
55649
|
const analyzedFiles = [];
|
|
54983
55650
|
for (const file3 of files) {
|
|
54984
|
-
const fullPath =
|
|
54985
|
-
if (!
|
|
55651
|
+
const fullPath = path39.isAbsolute(file3) ? file3 : path39.join(workingDir, file3);
|
|
55652
|
+
if (!fs27.existsSync(fullPath)) {
|
|
54986
55653
|
continue;
|
|
54987
55654
|
}
|
|
54988
55655
|
try {
|
|
54989
|
-
const stat2 =
|
|
55656
|
+
const stat2 = fs27.statSync(fullPath);
|
|
54990
55657
|
if (stat2.size > MAX_FILE_SIZE_BYTES5) {
|
|
54991
55658
|
continue;
|
|
54992
55659
|
}
|
|
54993
|
-
const content =
|
|
55660
|
+
const content = fs27.readFileSync(fullPath, "utf-8");
|
|
54994
55661
|
const lines = content.split(`
|
|
54995
55662
|
`).filter((line) => line.trim().length > 0);
|
|
54996
55663
|
if (lines.length < MIN_DUPLICATION_LINES) {
|
|
@@ -55014,8 +55681,8 @@ function countCodeLines(content) {
|
|
|
55014
55681
|
return lines.length;
|
|
55015
55682
|
}
|
|
55016
55683
|
function isTestFile(filePath) {
|
|
55017
|
-
const basename8 =
|
|
55018
|
-
const _ext =
|
|
55684
|
+
const basename8 = path39.basename(filePath);
|
|
55685
|
+
const _ext = path39.extname(filePath).toLowerCase();
|
|
55019
55686
|
const testPatterns = [
|
|
55020
55687
|
".test.",
|
|
55021
55688
|
".spec.",
|
|
@@ -55096,8 +55763,8 @@ function matchGlobSegment(globSegments, pathSegments) {
|
|
|
55096
55763
|
}
|
|
55097
55764
|
return gIndex === globSegments.length && pIndex === pathSegments.length;
|
|
55098
55765
|
}
|
|
55099
|
-
function matchesGlobSegment(
|
|
55100
|
-
const normalizedPath =
|
|
55766
|
+
function matchesGlobSegment(path40, glob) {
|
|
55767
|
+
const normalizedPath = path40.replace(/\\/g, "/");
|
|
55101
55768
|
const normalizedGlob = glob.replace(/\\/g, "/");
|
|
55102
55769
|
if (normalizedPath.includes("//")) {
|
|
55103
55770
|
return false;
|
|
@@ -55128,8 +55795,8 @@ function simpleGlobToRegex(glob) {
|
|
|
55128
55795
|
function hasGlobstar(glob) {
|
|
55129
55796
|
return glob.includes("**");
|
|
55130
55797
|
}
|
|
55131
|
-
function globMatches(
|
|
55132
|
-
const normalizedPath =
|
|
55798
|
+
function globMatches(path40, glob) {
|
|
55799
|
+
const normalizedPath = path40.replace(/\\/g, "/");
|
|
55133
55800
|
if (!glob || glob === "") {
|
|
55134
55801
|
if (normalizedPath.includes("//")) {
|
|
55135
55802
|
return false;
|
|
@@ -55165,31 +55832,31 @@ function shouldExcludeFile(filePath, excludeGlobs) {
|
|
|
55165
55832
|
async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
|
|
55166
55833
|
let testLines = 0;
|
|
55167
55834
|
let codeLines = 0;
|
|
55168
|
-
const srcDir =
|
|
55169
|
-
if (
|
|
55835
|
+
const srcDir = path39.join(workingDir, "src");
|
|
55836
|
+
if (fs27.existsSync(srcDir)) {
|
|
55170
55837
|
await scanDirectoryForLines(srcDir, enforceGlobs, excludeGlobs, false, (lines) => {
|
|
55171
55838
|
codeLines += lines;
|
|
55172
55839
|
});
|
|
55173
55840
|
}
|
|
55174
55841
|
const possibleSrcDirs = ["lib", "app", "source", "core"];
|
|
55175
55842
|
for (const dir of possibleSrcDirs) {
|
|
55176
|
-
const dirPath =
|
|
55177
|
-
if (
|
|
55843
|
+
const dirPath = path39.join(workingDir, dir);
|
|
55844
|
+
if (fs27.existsSync(dirPath)) {
|
|
55178
55845
|
await scanDirectoryForLines(dirPath, enforceGlobs, excludeGlobs, false, (lines) => {
|
|
55179
55846
|
codeLines += lines;
|
|
55180
55847
|
});
|
|
55181
55848
|
}
|
|
55182
55849
|
}
|
|
55183
|
-
const testsDir =
|
|
55184
|
-
if (
|
|
55850
|
+
const testsDir = path39.join(workingDir, "tests");
|
|
55851
|
+
if (fs27.existsSync(testsDir)) {
|
|
55185
55852
|
await scanDirectoryForLines(testsDir, ["**"], ["node_modules", "dist"], true, (lines) => {
|
|
55186
55853
|
testLines += lines;
|
|
55187
55854
|
});
|
|
55188
55855
|
}
|
|
55189
55856
|
const possibleTestDirs = ["test", "__tests__", "specs"];
|
|
55190
55857
|
for (const dir of possibleTestDirs) {
|
|
55191
|
-
const dirPath =
|
|
55192
|
-
if (
|
|
55858
|
+
const dirPath = path39.join(workingDir, dir);
|
|
55859
|
+
if (fs27.existsSync(dirPath) && dirPath !== testsDir) {
|
|
55193
55860
|
await scanDirectoryForLines(dirPath, ["**"], ["node_modules", "dist"], true, (lines) => {
|
|
55194
55861
|
testLines += lines;
|
|
55195
55862
|
});
|
|
@@ -55201,9 +55868,9 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
|
|
|
55201
55868
|
}
|
|
55202
55869
|
async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTestScan, callback) {
|
|
55203
55870
|
try {
|
|
55204
|
-
const entries =
|
|
55871
|
+
const entries = fs27.readdirSync(dirPath, { withFileTypes: true });
|
|
55205
55872
|
for (const entry of entries) {
|
|
55206
|
-
const fullPath =
|
|
55873
|
+
const fullPath = path39.join(dirPath, entry.name);
|
|
55207
55874
|
if (entry.isDirectory()) {
|
|
55208
55875
|
if (entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === ".git") {
|
|
55209
55876
|
continue;
|
|
@@ -55211,7 +55878,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
|
|
|
55211
55878
|
await scanDirectoryForLines(fullPath, includeGlobs, excludeGlobs, isTestScan, callback);
|
|
55212
55879
|
} else if (entry.isFile()) {
|
|
55213
55880
|
const relativePath = fullPath.replace(`${process.cwd()}/`, "");
|
|
55214
|
-
const ext =
|
|
55881
|
+
const ext = path39.extname(entry.name).toLowerCase();
|
|
55215
55882
|
const validExts = [
|
|
55216
55883
|
".ts",
|
|
55217
55884
|
".tsx",
|
|
@@ -55247,7 +55914,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
|
|
|
55247
55914
|
continue;
|
|
55248
55915
|
}
|
|
55249
55916
|
try {
|
|
55250
|
-
const content =
|
|
55917
|
+
const content = fs27.readFileSync(fullPath, "utf-8");
|
|
55251
55918
|
const lines = countCodeLines(content);
|
|
55252
55919
|
callback(lines);
|
|
55253
55920
|
} catch {}
|
|
@@ -55461,8 +56128,8 @@ async function qualityBudget(input, directory) {
|
|
|
55461
56128
|
init_dist();
|
|
55462
56129
|
init_manager();
|
|
55463
56130
|
init_detector();
|
|
55464
|
-
import * as
|
|
55465
|
-
import * as
|
|
56131
|
+
import * as fs28 from "fs";
|
|
56132
|
+
import * as path40 from "path";
|
|
55466
56133
|
import { extname as extname9 } from "path";
|
|
55467
56134
|
|
|
55468
56135
|
// src/sast/rules/c.ts
|
|
@@ -56329,17 +56996,17 @@ var SEVERITY_ORDER = {
|
|
|
56329
56996
|
};
|
|
56330
56997
|
function shouldSkipFile(filePath) {
|
|
56331
56998
|
try {
|
|
56332
|
-
const stats =
|
|
56999
|
+
const stats = fs28.statSync(filePath);
|
|
56333
57000
|
if (stats.size > MAX_FILE_SIZE_BYTES6) {
|
|
56334
57001
|
return { skip: true, reason: "file too large" };
|
|
56335
57002
|
}
|
|
56336
57003
|
if (stats.size === 0) {
|
|
56337
57004
|
return { skip: true, reason: "empty file" };
|
|
56338
57005
|
}
|
|
56339
|
-
const fd =
|
|
57006
|
+
const fd = fs28.openSync(filePath, "r");
|
|
56340
57007
|
const buffer = Buffer.alloc(8192);
|
|
56341
|
-
const bytesRead =
|
|
56342
|
-
|
|
57008
|
+
const bytesRead = fs28.readSync(fd, buffer, 0, 8192, 0);
|
|
57009
|
+
fs28.closeSync(fd);
|
|
56343
57010
|
if (bytesRead > 0) {
|
|
56344
57011
|
let nullCount = 0;
|
|
56345
57012
|
for (let i2 = 0;i2 < bytesRead; i2++) {
|
|
@@ -56378,7 +57045,7 @@ function countBySeverity(findings) {
|
|
|
56378
57045
|
}
|
|
56379
57046
|
function scanFileWithTierA(filePath, language) {
|
|
56380
57047
|
try {
|
|
56381
|
-
const content =
|
|
57048
|
+
const content = fs28.readFileSync(filePath, "utf-8");
|
|
56382
57049
|
const findings = executeRulesSync(filePath, content, language);
|
|
56383
57050
|
return findings.map((f) => ({
|
|
56384
57051
|
rule_id: f.rule_id,
|
|
@@ -56425,8 +57092,8 @@ async function sastScan(input, directory, config3) {
|
|
|
56425
57092
|
_filesSkipped++;
|
|
56426
57093
|
continue;
|
|
56427
57094
|
}
|
|
56428
|
-
const resolvedPath =
|
|
56429
|
-
if (!
|
|
57095
|
+
const resolvedPath = path40.isAbsolute(filePath) ? filePath : path40.resolve(directory, filePath);
|
|
57096
|
+
if (!fs28.existsSync(resolvedPath)) {
|
|
56430
57097
|
_filesSkipped++;
|
|
56431
57098
|
continue;
|
|
56432
57099
|
}
|
|
@@ -56624,18 +57291,18 @@ function validatePath(inputPath, baseDir, workspaceDir) {
|
|
|
56624
57291
|
let resolved;
|
|
56625
57292
|
const isWinAbs = isWindowsAbsolutePath(inputPath);
|
|
56626
57293
|
if (isWinAbs) {
|
|
56627
|
-
resolved =
|
|
56628
|
-
} else if (
|
|
56629
|
-
resolved =
|
|
57294
|
+
resolved = path41.win32.resolve(inputPath);
|
|
57295
|
+
} else if (path41.isAbsolute(inputPath)) {
|
|
57296
|
+
resolved = path41.resolve(inputPath);
|
|
56630
57297
|
} else {
|
|
56631
|
-
resolved =
|
|
57298
|
+
resolved = path41.resolve(baseDir, inputPath);
|
|
56632
57299
|
}
|
|
56633
|
-
const workspaceResolved =
|
|
57300
|
+
const workspaceResolved = path41.resolve(workspaceDir);
|
|
56634
57301
|
let relative4;
|
|
56635
57302
|
if (isWinAbs) {
|
|
56636
|
-
relative4 =
|
|
57303
|
+
relative4 = path41.win32.relative(workspaceResolved, resolved);
|
|
56637
57304
|
} else {
|
|
56638
|
-
relative4 =
|
|
57305
|
+
relative4 = path41.relative(workspaceResolved, resolved);
|
|
56639
57306
|
}
|
|
56640
57307
|
if (relative4.startsWith("..")) {
|
|
56641
57308
|
return "path traversal detected";
|
|
@@ -56696,13 +57363,13 @@ async function runLintWrapped(files, directory, _config) {
|
|
|
56696
57363
|
}
|
|
56697
57364
|
async function runLintOnFiles(linter, files, workspaceDir) {
|
|
56698
57365
|
const isWindows = process.platform === "win32";
|
|
56699
|
-
const binDir =
|
|
57366
|
+
const binDir = path41.join(workspaceDir, "node_modules", ".bin");
|
|
56700
57367
|
const validatedFiles = [];
|
|
56701
57368
|
for (const file3 of files) {
|
|
56702
57369
|
if (typeof file3 !== "string") {
|
|
56703
57370
|
continue;
|
|
56704
57371
|
}
|
|
56705
|
-
const resolvedPath =
|
|
57372
|
+
const resolvedPath = path41.resolve(file3);
|
|
56706
57373
|
const validationError = validatePath(resolvedPath, workspaceDir, workspaceDir);
|
|
56707
57374
|
if (validationError) {
|
|
56708
57375
|
continue;
|
|
@@ -56720,10 +57387,10 @@ async function runLintOnFiles(linter, files, workspaceDir) {
|
|
|
56720
57387
|
}
|
|
56721
57388
|
let command;
|
|
56722
57389
|
if (linter === "biome") {
|
|
56723
|
-
const biomeBin = isWindows ?
|
|
57390
|
+
const biomeBin = isWindows ? path41.join(binDir, "biome.EXE") : path41.join(binDir, "biome");
|
|
56724
57391
|
command = [biomeBin, "check", ...validatedFiles];
|
|
56725
57392
|
} else {
|
|
56726
|
-
const eslintBin = isWindows ?
|
|
57393
|
+
const eslintBin = isWindows ? path41.join(binDir, "eslint.cmd") : path41.join(binDir, "eslint");
|
|
56727
57394
|
command = [eslintBin, ...validatedFiles];
|
|
56728
57395
|
}
|
|
56729
57396
|
try {
|
|
@@ -56860,7 +57527,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
56860
57527
|
skippedFiles++;
|
|
56861
57528
|
continue;
|
|
56862
57529
|
}
|
|
56863
|
-
const resolvedPath =
|
|
57530
|
+
const resolvedPath = path41.resolve(file3);
|
|
56864
57531
|
const validationError = validatePath(resolvedPath, directory, directory);
|
|
56865
57532
|
if (validationError) {
|
|
56866
57533
|
skippedFiles++;
|
|
@@ -56878,14 +57545,14 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
56878
57545
|
};
|
|
56879
57546
|
}
|
|
56880
57547
|
for (const file3 of validatedFiles) {
|
|
56881
|
-
const ext =
|
|
57548
|
+
const ext = path41.extname(file3).toLowerCase();
|
|
56882
57549
|
if (DEFAULT_EXCLUDE_EXTENSIONS2.has(ext)) {
|
|
56883
57550
|
skippedFiles++;
|
|
56884
57551
|
continue;
|
|
56885
57552
|
}
|
|
56886
57553
|
let stat2;
|
|
56887
57554
|
try {
|
|
56888
|
-
stat2 =
|
|
57555
|
+
stat2 = fs29.statSync(file3);
|
|
56889
57556
|
} catch {
|
|
56890
57557
|
skippedFiles++;
|
|
56891
57558
|
continue;
|
|
@@ -56896,7 +57563,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
56896
57563
|
}
|
|
56897
57564
|
let content;
|
|
56898
57565
|
try {
|
|
56899
|
-
const buffer =
|
|
57566
|
+
const buffer = fs29.readFileSync(file3);
|
|
56900
57567
|
if (buffer.includes(0)) {
|
|
56901
57568
|
skippedFiles++;
|
|
56902
57569
|
continue;
|
|
@@ -57037,7 +57704,7 @@ async function runPreCheckBatch(input, workspaceDir) {
|
|
|
57037
57704
|
warn(`pre_check_batch: Invalid file path: ${file3}`);
|
|
57038
57705
|
continue;
|
|
57039
57706
|
}
|
|
57040
|
-
changedFiles.push(
|
|
57707
|
+
changedFiles.push(path41.resolve(directory, file3));
|
|
57041
57708
|
}
|
|
57042
57709
|
if (changedFiles.length === 0) {
|
|
57043
57710
|
warn("pre_check_batch: No valid files after validation, skipping all tools (fail-closed)");
|
|
@@ -57188,7 +57855,7 @@ var pre_check_batch = createSwarmTool({
|
|
|
57188
57855
|
};
|
|
57189
57856
|
return JSON.stringify(errorResult, null, 2);
|
|
57190
57857
|
}
|
|
57191
|
-
const resolvedDirectory =
|
|
57858
|
+
const resolvedDirectory = path41.resolve(typedArgs.directory);
|
|
57192
57859
|
const workspaceAnchor = resolvedDirectory;
|
|
57193
57860
|
const dirError = validateDirectory3(resolvedDirectory, workspaceAnchor);
|
|
57194
57861
|
if (dirError) {
|
|
@@ -57295,8 +57962,8 @@ ${paginatedContent}`;
|
|
|
57295
57962
|
init_tool();
|
|
57296
57963
|
init_manager2();
|
|
57297
57964
|
init_create_tool();
|
|
57298
|
-
import * as
|
|
57299
|
-
import * as
|
|
57965
|
+
import * as fs30 from "fs";
|
|
57966
|
+
import * as path42 from "path";
|
|
57300
57967
|
function detectPlaceholderContent(args2) {
|
|
57301
57968
|
const issues = [];
|
|
57302
57969
|
const placeholderPattern = /^\[\w[\w\s]*\]$/;
|
|
@@ -57400,19 +58067,19 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
57400
58067
|
try {
|
|
57401
58068
|
await savePlan(dir, plan);
|
|
57402
58069
|
try {
|
|
57403
|
-
const markerPath =
|
|
58070
|
+
const markerPath = path42.join(dir, ".swarm", ".plan-write-marker");
|
|
57404
58071
|
const marker = JSON.stringify({
|
|
57405
58072
|
source: "save_plan",
|
|
57406
58073
|
timestamp: new Date().toISOString(),
|
|
57407
58074
|
phases_count: plan.phases.length,
|
|
57408
58075
|
tasks_count: tasksCount
|
|
57409
58076
|
});
|
|
57410
|
-
await
|
|
58077
|
+
await fs30.promises.writeFile(markerPath, marker, "utf8");
|
|
57411
58078
|
} catch {}
|
|
57412
58079
|
return {
|
|
57413
58080
|
success: true,
|
|
57414
58081
|
message: "Plan saved successfully",
|
|
57415
|
-
plan_path:
|
|
58082
|
+
plan_path: path42.join(dir, ".swarm", "plan.json"),
|
|
57416
58083
|
phases_count: plan.phases.length,
|
|
57417
58084
|
tasks_count: tasksCount
|
|
57418
58085
|
};
|
|
@@ -57450,8 +58117,8 @@ var save_plan = createSwarmTool({
|
|
|
57450
58117
|
// src/tools/sbom-generate.ts
|
|
57451
58118
|
init_dist();
|
|
57452
58119
|
init_manager();
|
|
57453
|
-
import * as
|
|
57454
|
-
import * as
|
|
58120
|
+
import * as fs31 from "fs";
|
|
58121
|
+
import * as path43 from "path";
|
|
57455
58122
|
|
|
57456
58123
|
// src/sbom/detectors/dart.ts
|
|
57457
58124
|
function parsePubspecLock(content) {
|
|
@@ -58297,9 +58964,9 @@ function findManifestFiles(rootDir) {
|
|
|
58297
58964
|
const patterns = [...new Set(allDetectors.flatMap((d) => d.patterns))];
|
|
58298
58965
|
function searchDir(dir) {
|
|
58299
58966
|
try {
|
|
58300
|
-
const entries =
|
|
58967
|
+
const entries = fs31.readdirSync(dir, { withFileTypes: true });
|
|
58301
58968
|
for (const entry of entries) {
|
|
58302
|
-
const fullPath =
|
|
58969
|
+
const fullPath = path43.join(dir, entry.name);
|
|
58303
58970
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "target") {
|
|
58304
58971
|
continue;
|
|
58305
58972
|
}
|
|
@@ -58309,7 +58976,7 @@ function findManifestFiles(rootDir) {
|
|
|
58309
58976
|
for (const pattern of patterns) {
|
|
58310
58977
|
const regex = pattern.replace(/\./g, "\\.").replace(/\*/g, ".*").replace(/\?/g, ".");
|
|
58311
58978
|
if (new RegExp(regex, "i").test(entry.name)) {
|
|
58312
|
-
manifestFiles.push(
|
|
58979
|
+
manifestFiles.push(path43.relative(cwd, fullPath));
|
|
58313
58980
|
break;
|
|
58314
58981
|
}
|
|
58315
58982
|
}
|
|
@@ -58326,14 +58993,14 @@ function findManifestFilesInDirs(directories, workingDir) {
|
|
|
58326
58993
|
const patterns = [...new Set(allDetectors.flatMap((d) => d.patterns))];
|
|
58327
58994
|
for (const dir of directories) {
|
|
58328
58995
|
try {
|
|
58329
|
-
const entries =
|
|
58996
|
+
const entries = fs31.readdirSync(dir, { withFileTypes: true });
|
|
58330
58997
|
for (const entry of entries) {
|
|
58331
|
-
const fullPath =
|
|
58998
|
+
const fullPath = path43.join(dir, entry.name);
|
|
58332
58999
|
if (entry.isFile()) {
|
|
58333
59000
|
for (const pattern of patterns) {
|
|
58334
59001
|
const regex = pattern.replace(/\./g, "\\.").replace(/\*/g, ".*").replace(/\?/g, ".");
|
|
58335
59002
|
if (new RegExp(regex, "i").test(entry.name)) {
|
|
58336
|
-
found.push(
|
|
59003
|
+
found.push(path43.relative(workingDir, fullPath));
|
|
58337
59004
|
break;
|
|
58338
59005
|
}
|
|
58339
59006
|
}
|
|
@@ -58346,11 +59013,11 @@ function findManifestFilesInDirs(directories, workingDir) {
|
|
|
58346
59013
|
function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
|
|
58347
59014
|
const dirs = new Set;
|
|
58348
59015
|
for (const file3 of changedFiles) {
|
|
58349
|
-
let currentDir =
|
|
59016
|
+
let currentDir = path43.dirname(file3);
|
|
58350
59017
|
while (true) {
|
|
58351
|
-
if (currentDir && currentDir !== "." && currentDir !==
|
|
58352
|
-
dirs.add(
|
|
58353
|
-
const parent =
|
|
59018
|
+
if (currentDir && currentDir !== "." && currentDir !== path43.sep) {
|
|
59019
|
+
dirs.add(path43.join(workingDir, currentDir));
|
|
59020
|
+
const parent = path43.dirname(currentDir);
|
|
58354
59021
|
if (parent === currentDir)
|
|
58355
59022
|
break;
|
|
58356
59023
|
currentDir = parent;
|
|
@@ -58364,7 +59031,7 @@ function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
|
|
|
58364
59031
|
}
|
|
58365
59032
|
function ensureOutputDir(outputDir) {
|
|
58366
59033
|
try {
|
|
58367
|
-
|
|
59034
|
+
fs31.mkdirSync(outputDir, { recursive: true });
|
|
58368
59035
|
} catch (error93) {
|
|
58369
59036
|
if (!error93 || error93.code !== "EEXIST") {
|
|
58370
59037
|
throw error93;
|
|
@@ -58456,11 +59123,11 @@ var sbom_generate = createSwarmTool({
|
|
|
58456
59123
|
const processedFiles = [];
|
|
58457
59124
|
for (const manifestFile of manifestFiles) {
|
|
58458
59125
|
try {
|
|
58459
|
-
const fullPath =
|
|
58460
|
-
if (!
|
|
59126
|
+
const fullPath = path43.isAbsolute(manifestFile) ? manifestFile : path43.join(workingDir, manifestFile);
|
|
59127
|
+
if (!fs31.existsSync(fullPath)) {
|
|
58461
59128
|
continue;
|
|
58462
59129
|
}
|
|
58463
|
-
const content =
|
|
59130
|
+
const content = fs31.readFileSync(fullPath, "utf-8");
|
|
58464
59131
|
const components = detectComponents(manifestFile, content);
|
|
58465
59132
|
processedFiles.push(manifestFile);
|
|
58466
59133
|
if (components.length > 0) {
|
|
@@ -58473,8 +59140,8 @@ var sbom_generate = createSwarmTool({
|
|
|
58473
59140
|
const bom = generateCycloneDX(allComponents);
|
|
58474
59141
|
const bomJson = serializeCycloneDX(bom);
|
|
58475
59142
|
const filename = generateSbomFilename();
|
|
58476
|
-
const outputPath =
|
|
58477
|
-
|
|
59143
|
+
const outputPath = path43.join(outputDir, filename);
|
|
59144
|
+
fs31.writeFileSync(outputPath, bomJson, "utf-8");
|
|
58478
59145
|
const verdict = processedFiles.length > 0 ? "pass" : "pass";
|
|
58479
59146
|
try {
|
|
58480
59147
|
const timestamp = new Date().toISOString();
|
|
@@ -58516,8 +59183,8 @@ var sbom_generate = createSwarmTool({
|
|
|
58516
59183
|
// src/tools/schema-drift.ts
|
|
58517
59184
|
init_dist();
|
|
58518
59185
|
init_create_tool();
|
|
58519
|
-
import * as
|
|
58520
|
-
import * as
|
|
59186
|
+
import * as fs32 from "fs";
|
|
59187
|
+
import * as path44 from "path";
|
|
58521
59188
|
var SPEC_CANDIDATES = [
|
|
58522
59189
|
"openapi.json",
|
|
58523
59190
|
"openapi.yaml",
|
|
@@ -58549,28 +59216,28 @@ function normalizePath2(p) {
|
|
|
58549
59216
|
}
|
|
58550
59217
|
function discoverSpecFile(cwd, specFileArg) {
|
|
58551
59218
|
if (specFileArg) {
|
|
58552
|
-
const resolvedPath =
|
|
58553
|
-
const normalizedCwd = cwd.endsWith(
|
|
59219
|
+
const resolvedPath = path44.resolve(cwd, specFileArg);
|
|
59220
|
+
const normalizedCwd = cwd.endsWith(path44.sep) ? cwd : cwd + path44.sep;
|
|
58554
59221
|
if (!resolvedPath.startsWith(normalizedCwd) && resolvedPath !== cwd) {
|
|
58555
59222
|
throw new Error("Invalid spec_file: path traversal detected");
|
|
58556
59223
|
}
|
|
58557
|
-
const ext =
|
|
59224
|
+
const ext = path44.extname(resolvedPath).toLowerCase();
|
|
58558
59225
|
if (!ALLOWED_EXTENSIONS.includes(ext)) {
|
|
58559
59226
|
throw new Error(`Invalid spec_file: must end in .json, .yaml, or .yml, got ${ext}`);
|
|
58560
59227
|
}
|
|
58561
|
-
const stats =
|
|
59228
|
+
const stats = fs32.statSync(resolvedPath);
|
|
58562
59229
|
if (stats.size > MAX_SPEC_SIZE) {
|
|
58563
59230
|
throw new Error(`Invalid spec_file: file exceeds ${MAX_SPEC_SIZE / 1024 / 1024}MB limit`);
|
|
58564
59231
|
}
|
|
58565
|
-
if (!
|
|
59232
|
+
if (!fs32.existsSync(resolvedPath)) {
|
|
58566
59233
|
throw new Error(`Spec file not found: ${resolvedPath}`);
|
|
58567
59234
|
}
|
|
58568
59235
|
return resolvedPath;
|
|
58569
59236
|
}
|
|
58570
59237
|
for (const candidate of SPEC_CANDIDATES) {
|
|
58571
|
-
const candidatePath =
|
|
58572
|
-
if (
|
|
58573
|
-
const stats =
|
|
59238
|
+
const candidatePath = path44.resolve(cwd, candidate);
|
|
59239
|
+
if (fs32.existsSync(candidatePath)) {
|
|
59240
|
+
const stats = fs32.statSync(candidatePath);
|
|
58574
59241
|
if (stats.size <= MAX_SPEC_SIZE) {
|
|
58575
59242
|
return candidatePath;
|
|
58576
59243
|
}
|
|
@@ -58579,8 +59246,8 @@ function discoverSpecFile(cwd, specFileArg) {
|
|
|
58579
59246
|
return null;
|
|
58580
59247
|
}
|
|
58581
59248
|
function parseSpec(specFile) {
|
|
58582
|
-
const content =
|
|
58583
|
-
const ext =
|
|
59249
|
+
const content = fs32.readFileSync(specFile, "utf-8");
|
|
59250
|
+
const ext = path44.extname(specFile).toLowerCase();
|
|
58584
59251
|
if (ext === ".json") {
|
|
58585
59252
|
return parseJsonSpec(content);
|
|
58586
59253
|
}
|
|
@@ -58646,12 +59313,12 @@ function extractRoutes(cwd) {
|
|
|
58646
59313
|
function walkDir(dir) {
|
|
58647
59314
|
let entries;
|
|
58648
59315
|
try {
|
|
58649
|
-
entries =
|
|
59316
|
+
entries = fs32.readdirSync(dir, { withFileTypes: true });
|
|
58650
59317
|
} catch {
|
|
58651
59318
|
return;
|
|
58652
59319
|
}
|
|
58653
59320
|
for (const entry of entries) {
|
|
58654
|
-
const fullPath =
|
|
59321
|
+
const fullPath = path44.join(dir, entry.name);
|
|
58655
59322
|
if (entry.isSymbolicLink()) {
|
|
58656
59323
|
continue;
|
|
58657
59324
|
}
|
|
@@ -58661,7 +59328,7 @@ function extractRoutes(cwd) {
|
|
|
58661
59328
|
}
|
|
58662
59329
|
walkDir(fullPath);
|
|
58663
59330
|
} else if (entry.isFile()) {
|
|
58664
|
-
const ext =
|
|
59331
|
+
const ext = path44.extname(entry.name).toLowerCase();
|
|
58665
59332
|
const baseName = entry.name.toLowerCase();
|
|
58666
59333
|
if (![".ts", ".js", ".mjs"].includes(ext)) {
|
|
58667
59334
|
continue;
|
|
@@ -58679,7 +59346,7 @@ function extractRoutes(cwd) {
|
|
|
58679
59346
|
}
|
|
58680
59347
|
function extractRoutesFromFile(filePath) {
|
|
58681
59348
|
const routes = [];
|
|
58682
|
-
const content =
|
|
59349
|
+
const content = fs32.readFileSync(filePath, "utf-8");
|
|
58683
59350
|
const lines = content.split(/\r?\n/);
|
|
58684
59351
|
const expressRegex = /(?:app|router|server|express)\.(get|post|put|patch|delete|options|head)\s*\(\s*['"`]([^'"`]+)['"`]/g;
|
|
58685
59352
|
const flaskRegex = /@(?:app|blueprint|bp)\.route\s*\(\s*['"]([^'"]+)['"]/g;
|
|
@@ -58830,8 +59497,8 @@ init_secretscan();
|
|
|
58830
59497
|
// src/tools/symbols.ts
|
|
58831
59498
|
init_tool();
|
|
58832
59499
|
init_create_tool();
|
|
58833
|
-
import * as
|
|
58834
|
-
import * as
|
|
59500
|
+
import * as fs33 from "fs";
|
|
59501
|
+
import * as path45 from "path";
|
|
58835
59502
|
var MAX_FILE_SIZE_BYTES7 = 1024 * 1024;
|
|
58836
59503
|
var WINDOWS_RESERVED_NAMES = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
|
|
58837
59504
|
function containsControlCharacters(str) {
|
|
@@ -58860,11 +59527,11 @@ function containsWindowsAttacks(str) {
|
|
|
58860
59527
|
}
|
|
58861
59528
|
function isPathInWorkspace(filePath, workspace) {
|
|
58862
59529
|
try {
|
|
58863
|
-
const resolvedPath =
|
|
58864
|
-
const realWorkspace =
|
|
58865
|
-
const realResolvedPath =
|
|
58866
|
-
const relativePath =
|
|
58867
|
-
if (relativePath.startsWith("..") ||
|
|
59530
|
+
const resolvedPath = path45.resolve(workspace, filePath);
|
|
59531
|
+
const realWorkspace = fs33.realpathSync(workspace);
|
|
59532
|
+
const realResolvedPath = fs33.realpathSync(resolvedPath);
|
|
59533
|
+
const relativePath = path45.relative(realWorkspace, realResolvedPath);
|
|
59534
|
+
if (relativePath.startsWith("..") || path45.isAbsolute(relativePath)) {
|
|
58868
59535
|
return false;
|
|
58869
59536
|
}
|
|
58870
59537
|
return true;
|
|
@@ -58876,17 +59543,17 @@ function validatePathForRead(filePath, workspace) {
|
|
|
58876
59543
|
return isPathInWorkspace(filePath, workspace);
|
|
58877
59544
|
}
|
|
58878
59545
|
function extractTSSymbols(filePath, cwd) {
|
|
58879
|
-
const fullPath =
|
|
59546
|
+
const fullPath = path45.join(cwd, filePath);
|
|
58880
59547
|
if (!validatePathForRead(fullPath, cwd)) {
|
|
58881
59548
|
return [];
|
|
58882
59549
|
}
|
|
58883
59550
|
let content;
|
|
58884
59551
|
try {
|
|
58885
|
-
const stats =
|
|
59552
|
+
const stats = fs33.statSync(fullPath);
|
|
58886
59553
|
if (stats.size > MAX_FILE_SIZE_BYTES7) {
|
|
58887
59554
|
throw new Error(`File too large: ${stats.size} bytes (max: ${MAX_FILE_SIZE_BYTES7})`);
|
|
58888
59555
|
}
|
|
58889
|
-
content =
|
|
59556
|
+
content = fs33.readFileSync(fullPath, "utf-8");
|
|
58890
59557
|
} catch {
|
|
58891
59558
|
return [];
|
|
58892
59559
|
}
|
|
@@ -59028,17 +59695,17 @@ function extractTSSymbols(filePath, cwd) {
|
|
|
59028
59695
|
});
|
|
59029
59696
|
}
|
|
59030
59697
|
function extractPythonSymbols(filePath, cwd) {
|
|
59031
|
-
const fullPath =
|
|
59698
|
+
const fullPath = path45.join(cwd, filePath);
|
|
59032
59699
|
if (!validatePathForRead(fullPath, cwd)) {
|
|
59033
59700
|
return [];
|
|
59034
59701
|
}
|
|
59035
59702
|
let content;
|
|
59036
59703
|
try {
|
|
59037
|
-
const stats =
|
|
59704
|
+
const stats = fs33.statSync(fullPath);
|
|
59038
59705
|
if (stats.size > MAX_FILE_SIZE_BYTES7) {
|
|
59039
59706
|
throw new Error(`File too large: ${stats.size} bytes (max: ${MAX_FILE_SIZE_BYTES7})`);
|
|
59040
59707
|
}
|
|
59041
|
-
content =
|
|
59708
|
+
content = fs33.readFileSync(fullPath, "utf-8");
|
|
59042
59709
|
} catch {
|
|
59043
59710
|
return [];
|
|
59044
59711
|
}
|
|
@@ -59111,7 +59778,7 @@ var symbols = createSwarmTool({
|
|
|
59111
59778
|
}, null, 2);
|
|
59112
59779
|
}
|
|
59113
59780
|
const cwd = directory;
|
|
59114
|
-
const ext =
|
|
59781
|
+
const ext = path45.extname(file3);
|
|
59115
59782
|
if (containsControlCharacters(file3)) {
|
|
59116
59783
|
return JSON.stringify({
|
|
59117
59784
|
file: file3,
|
|
@@ -59181,8 +59848,8 @@ init_test_runner();
|
|
|
59181
59848
|
// src/tools/todo-extract.ts
|
|
59182
59849
|
init_dist();
|
|
59183
59850
|
init_create_tool();
|
|
59184
|
-
import * as
|
|
59185
|
-
import * as
|
|
59851
|
+
import * as fs34 from "fs";
|
|
59852
|
+
import * as path46 from "path";
|
|
59186
59853
|
var MAX_TEXT_LENGTH = 200;
|
|
59187
59854
|
var MAX_FILE_SIZE_BYTES8 = 1024 * 1024;
|
|
59188
59855
|
var SUPPORTED_EXTENSIONS2 = new Set([
|
|
@@ -59253,9 +59920,9 @@ function validatePathsInput(paths, cwd) {
|
|
|
59253
59920
|
return { error: "paths contains path traversal", resolvedPath: null };
|
|
59254
59921
|
}
|
|
59255
59922
|
try {
|
|
59256
|
-
const resolvedPath =
|
|
59257
|
-
const normalizedCwd =
|
|
59258
|
-
const normalizedResolved =
|
|
59923
|
+
const resolvedPath = path46.resolve(paths);
|
|
59924
|
+
const normalizedCwd = path46.resolve(cwd);
|
|
59925
|
+
const normalizedResolved = path46.resolve(resolvedPath);
|
|
59259
59926
|
if (!normalizedResolved.startsWith(normalizedCwd)) {
|
|
59260
59927
|
return {
|
|
59261
59928
|
error: "paths must be within the current working directory",
|
|
@@ -59271,13 +59938,13 @@ function validatePathsInput(paths, cwd) {
|
|
|
59271
59938
|
}
|
|
59272
59939
|
}
|
|
59273
59940
|
function isSupportedExtension(filePath) {
|
|
59274
|
-
const ext =
|
|
59941
|
+
const ext = path46.extname(filePath).toLowerCase();
|
|
59275
59942
|
return SUPPORTED_EXTENSIONS2.has(ext);
|
|
59276
59943
|
}
|
|
59277
59944
|
function findSourceFiles3(dir, files = []) {
|
|
59278
59945
|
let entries;
|
|
59279
59946
|
try {
|
|
59280
|
-
entries =
|
|
59947
|
+
entries = fs34.readdirSync(dir);
|
|
59281
59948
|
} catch {
|
|
59282
59949
|
return files;
|
|
59283
59950
|
}
|
|
@@ -59286,10 +59953,10 @@ function findSourceFiles3(dir, files = []) {
|
|
|
59286
59953
|
if (SKIP_DIRECTORIES3.has(entry)) {
|
|
59287
59954
|
continue;
|
|
59288
59955
|
}
|
|
59289
|
-
const fullPath =
|
|
59956
|
+
const fullPath = path46.join(dir, entry);
|
|
59290
59957
|
let stat2;
|
|
59291
59958
|
try {
|
|
59292
|
-
stat2 =
|
|
59959
|
+
stat2 = fs34.statSync(fullPath);
|
|
59293
59960
|
} catch {
|
|
59294
59961
|
continue;
|
|
59295
59962
|
}
|
|
@@ -59382,7 +60049,7 @@ var todo_extract = createSwarmTool({
|
|
|
59382
60049
|
return JSON.stringify(errorResult, null, 2);
|
|
59383
60050
|
}
|
|
59384
60051
|
const scanPath = resolvedPath;
|
|
59385
|
-
if (!
|
|
60052
|
+
if (!fs34.existsSync(scanPath)) {
|
|
59386
60053
|
const errorResult = {
|
|
59387
60054
|
error: `path not found: ${pathsInput}`,
|
|
59388
60055
|
total: 0,
|
|
@@ -59392,13 +60059,13 @@ var todo_extract = createSwarmTool({
|
|
|
59392
60059
|
return JSON.stringify(errorResult, null, 2);
|
|
59393
60060
|
}
|
|
59394
60061
|
const filesToScan = [];
|
|
59395
|
-
const stat2 =
|
|
60062
|
+
const stat2 = fs34.statSync(scanPath);
|
|
59396
60063
|
if (stat2.isFile()) {
|
|
59397
60064
|
if (isSupportedExtension(scanPath)) {
|
|
59398
60065
|
filesToScan.push(scanPath);
|
|
59399
60066
|
} else {
|
|
59400
60067
|
const errorResult = {
|
|
59401
|
-
error: `unsupported file extension: ${
|
|
60068
|
+
error: `unsupported file extension: ${path46.extname(scanPath)}`,
|
|
59402
60069
|
total: 0,
|
|
59403
60070
|
byPriority: { high: 0, medium: 0, low: 0 },
|
|
59404
60071
|
entries: []
|
|
@@ -59411,11 +60078,11 @@ var todo_extract = createSwarmTool({
|
|
|
59411
60078
|
const allEntries = [];
|
|
59412
60079
|
for (const filePath of filesToScan) {
|
|
59413
60080
|
try {
|
|
59414
|
-
const fileStat =
|
|
60081
|
+
const fileStat = fs34.statSync(filePath);
|
|
59415
60082
|
if (fileStat.size > MAX_FILE_SIZE_BYTES8) {
|
|
59416
60083
|
continue;
|
|
59417
60084
|
}
|
|
59418
|
-
const content =
|
|
60085
|
+
const content = fs34.readFileSync(filePath, "utf-8");
|
|
59419
60086
|
const entries = parseTodoComments(content, filePath, tagsSet);
|
|
59420
60087
|
allEntries.push(...entries);
|
|
59421
60088
|
} catch {}
|
|
@@ -59443,8 +60110,8 @@ var todo_extract = createSwarmTool({
|
|
|
59443
60110
|
// src/tools/update-task-status.ts
|
|
59444
60111
|
init_tool();
|
|
59445
60112
|
init_manager2();
|
|
59446
|
-
import * as
|
|
59447
|
-
import * as
|
|
60113
|
+
import * as fs35 from "fs";
|
|
60114
|
+
import * as path47 from "path";
|
|
59448
60115
|
init_create_tool();
|
|
59449
60116
|
var VALID_STATUSES = [
|
|
59450
60117
|
"pending",
|
|
@@ -59481,6 +60148,10 @@ function checkReviewerGate(taskId) {
|
|
|
59481
60148
|
const state = getTaskState(session, taskId);
|
|
59482
60149
|
stateEntries.push(`${sessionId}: ${state}`);
|
|
59483
60150
|
}
|
|
60151
|
+
const allIdle = stateEntries.length > 0 && stateEntries.every((e) => e.endsWith(": idle"));
|
|
60152
|
+
if (allIdle) {
|
|
60153
|
+
console.warn(`[update-task-status] Issue #81 regression detected for task ${taskId}: all ${stateEntries.length} session(s) show idle state. taskWorkflowStates may not be persisting across sessions.`);
|
|
60154
|
+
}
|
|
59484
60155
|
const currentStateStr = stateEntries.length > 0 ? stateEntries.join(", ") : "no active sessions";
|
|
59485
60156
|
return {
|
|
59486
60157
|
blocked: true,
|
|
@@ -59544,8 +60215,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
|
|
|
59544
60215
|
};
|
|
59545
60216
|
}
|
|
59546
60217
|
}
|
|
59547
|
-
normalizedDir =
|
|
59548
|
-
const pathParts = normalizedDir.split(
|
|
60218
|
+
normalizedDir = path47.normalize(args2.working_directory);
|
|
60219
|
+
const pathParts = normalizedDir.split(path47.sep);
|
|
59549
60220
|
if (pathParts.includes("..")) {
|
|
59550
60221
|
return {
|
|
59551
60222
|
success: false,
|
|
@@ -59555,11 +60226,11 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
|
|
|
59555
60226
|
]
|
|
59556
60227
|
};
|
|
59557
60228
|
}
|
|
59558
|
-
const resolvedDir =
|
|
60229
|
+
const resolvedDir = path47.resolve(normalizedDir);
|
|
59559
60230
|
try {
|
|
59560
|
-
const realPath =
|
|
59561
|
-
const planPath =
|
|
59562
|
-
if (!
|
|
60231
|
+
const realPath = fs35.realpathSync(resolvedDir);
|
|
60232
|
+
const planPath = path47.join(realPath, ".swarm", "plan.json");
|
|
60233
|
+
if (!fs35.existsSync(planPath)) {
|
|
59563
60234
|
return {
|
|
59564
60235
|
success: false,
|
|
59565
60236
|
message: `Invalid working_directory: plan not found in "${realPath}"`,
|
|
@@ -59629,10 +60300,10 @@ function truncateToolOutput(output, maxLines, toolName) {
|
|
|
59629
60300
|
footerLines.push(`Tool: ${toolName}`);
|
|
59630
60301
|
}
|
|
59631
60302
|
footerLines.push("Use /swarm retrieve <id> to get the full content");
|
|
59632
|
-
return truncated.join(`
|
|
59633
|
-
`)
|
|
59634
|
-
|
|
59635
|
-
`)
|
|
60303
|
+
return `${truncated.join(`
|
|
60304
|
+
`)}
|
|
60305
|
+
${footerLines.join(`
|
|
60306
|
+
`)}`;
|
|
59636
60307
|
}
|
|
59637
60308
|
|
|
59638
60309
|
// src/index.ts
|
|
@@ -59690,7 +60361,7 @@ var OpenCodeSwarm = async (ctx) => {
|
|
|
59690
60361
|
const { PreflightTriggerManager: PTM } = await Promise.resolve().then(() => (init_trigger(), exports_trigger));
|
|
59691
60362
|
preflightTriggerManager = new PTM(automationConfig);
|
|
59692
60363
|
const { AutomationStatusArtifact: ASA } = await Promise.resolve().then(() => (init_status_artifact(), exports_status_artifact));
|
|
59693
|
-
const swarmDir =
|
|
60364
|
+
const swarmDir = path48.resolve(ctx.directory, ".swarm");
|
|
59694
60365
|
statusArtifact = new ASA(swarmDir);
|
|
59695
60366
|
statusArtifact.updateConfig(automationConfig.mode, automationConfig.capabilities);
|
|
59696
60367
|
if (automationConfig.capabilities?.evidence_auto_summaries === true) {
|