opencode-swarm 6.33.1 → 6.33.2
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 +59 -7
- package/dist/cli/index.js +73 -10
- package/dist/config/evidence-schema.d.ts +79 -0
- package/dist/config/schema.d.ts +6 -0
- package/dist/evidence/manager.d.ts +8 -4
- package/dist/hooks/delegation-gate.getEvidenceTaskId.test.d.ts +20 -0
- package/dist/index.js +811 -258
- package/dist/model-fallback.adversarial.test.d.ts +22 -0
- package/dist/model-fallback.test.d.ts +12 -0
- package/dist/session/snapshot-writer.d.ts +8 -0
- package/dist/state.d.ts +8 -0
- package/dist/tools/doc-scan.d.ts +38 -0
- package/dist/tools/index.d.ts +1 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -14146,7 +14146,7 @@ var init_zod = __esm(() => {
|
|
|
14146
14146
|
});
|
|
14147
14147
|
|
|
14148
14148
|
// src/config/evidence-schema.ts
|
|
14149
|
-
var EVIDENCE_MAX_JSON_BYTES, EVIDENCE_MAX_PATCH_BYTES, EVIDENCE_MAX_TASK_BYTES, EvidenceTypeSchema, EvidenceVerdictSchema, BaseEvidenceSchema, ReviewEvidenceSchema, TestEvidenceSchema, DiffEvidenceSchema, ApprovalEvidenceSchema, NoteEvidenceSchema, RetrospectiveEvidenceSchema, SyntaxEvidenceSchema, PlaceholderEvidenceSchema, SastEvidenceSchema, SbomEvidenceSchema, BuildEvidenceSchema, QualityBudgetEvidenceSchema, EvidenceSchema, EvidenceBundleSchema;
|
|
14149
|
+
var EVIDENCE_MAX_JSON_BYTES, EVIDENCE_MAX_PATCH_BYTES, EVIDENCE_MAX_TASK_BYTES, EvidenceTypeSchema, EvidenceVerdictSchema, BaseEvidenceSchema, ReviewEvidenceSchema, TestEvidenceSchema, DiffEvidenceSchema, ApprovalEvidenceSchema, NoteEvidenceSchema, RetrospectiveEvidenceSchema, SyntaxEvidenceSchema, PlaceholderEvidenceSchema, SastEvidenceSchema, SbomEvidenceSchema, BuildEvidenceSchema, QualityBudgetEvidenceSchema, SecretscanEvidenceSchema, EvidenceSchema, EvidenceBundleSchema;
|
|
14150
14150
|
var init_evidence_schema = __esm(() => {
|
|
14151
14151
|
init_zod();
|
|
14152
14152
|
EVIDENCE_MAX_JSON_BYTES = 500 * 1024;
|
|
@@ -14164,7 +14164,8 @@ var init_evidence_schema = __esm(() => {
|
|
|
14164
14164
|
"sast",
|
|
14165
14165
|
"sbom",
|
|
14166
14166
|
"build",
|
|
14167
|
-
"quality_budget"
|
|
14167
|
+
"quality_budget",
|
|
14168
|
+
"secretscan"
|
|
14168
14169
|
]);
|
|
14169
14170
|
EvidenceVerdictSchema = exports_external.enum([
|
|
14170
14171
|
"pass",
|
|
@@ -14245,7 +14246,14 @@ var init_evidence_schema = __esm(() => {
|
|
|
14245
14246
|
approach: exports_external.string().min(1),
|
|
14246
14247
|
result: exports_external.enum(["success", "failure", "partial"]),
|
|
14247
14248
|
abandoned_reason: exports_external.string().optional()
|
|
14248
|
-
})).max(10).default([])
|
|
14249
|
+
})).max(10).default([]),
|
|
14250
|
+
error_taxonomy: exports_external.array(exports_external.enum([
|
|
14251
|
+
"planning_error",
|
|
14252
|
+
"interface_mismatch",
|
|
14253
|
+
"logic_error",
|
|
14254
|
+
"scope_creep",
|
|
14255
|
+
"gate_evasion"
|
|
14256
|
+
])).default([])
|
|
14249
14257
|
});
|
|
14250
14258
|
SyntaxEvidenceSchema = BaseEvidenceSchema.extend({
|
|
14251
14259
|
type: exports_external.literal("syntax"),
|
|
@@ -14356,6 +14364,13 @@ var init_evidence_schema = __esm(() => {
|
|
|
14356
14364
|
})).default([]),
|
|
14357
14365
|
files_analyzed: exports_external.array(exports_external.string())
|
|
14358
14366
|
});
|
|
14367
|
+
SecretscanEvidenceSchema = BaseEvidenceSchema.extend({
|
|
14368
|
+
type: exports_external.literal("secretscan"),
|
|
14369
|
+
findings_count: exports_external.number().int().min(0).default(0),
|
|
14370
|
+
scan_directory: exports_external.string().optional(),
|
|
14371
|
+
files_scanned: exports_external.number().int().min(0).default(0),
|
|
14372
|
+
skipped_files: exports_external.number().int().min(0).default(0)
|
|
14373
|
+
});
|
|
14359
14374
|
EvidenceSchema = exports_external.discriminatedUnion("type", [
|
|
14360
14375
|
ReviewEvidenceSchema,
|
|
14361
14376
|
TestEvidenceSchema,
|
|
@@ -14368,7 +14383,8 @@ var init_evidence_schema = __esm(() => {
|
|
|
14368
14383
|
SastEvidenceSchema,
|
|
14369
14384
|
SbomEvidenceSchema,
|
|
14370
14385
|
BuildEvidenceSchema,
|
|
14371
|
-
QualityBudgetEvidenceSchema
|
|
14386
|
+
QualityBudgetEvidenceSchema,
|
|
14387
|
+
SecretscanEvidenceSchema
|
|
14372
14388
|
]);
|
|
14373
14389
|
EvidenceBundleSchema = exports_external.object({
|
|
14374
14390
|
schema_version: exports_external.literal("1.0.0"),
|
|
@@ -14458,7 +14474,8 @@ var init_schema = __esm(() => {
|
|
|
14458
14474
|
AgentOverrideConfigSchema = exports_external.object({
|
|
14459
14475
|
model: exports_external.string().optional(),
|
|
14460
14476
|
temperature: exports_external.number().min(0).max(2).optional(),
|
|
14461
|
-
disabled: exports_external.boolean().optional()
|
|
14477
|
+
disabled: exports_external.boolean().optional(),
|
|
14478
|
+
fallback_models: exports_external.array(exports_external.string()).max(3).optional()
|
|
14462
14479
|
});
|
|
14463
14480
|
SwarmConfigSchema = exports_external.object({
|
|
14464
14481
|
name: exports_external.string().optional(),
|
|
@@ -14799,6 +14816,7 @@ var init_schema = __esm(() => {
|
|
|
14799
14816
|
warning_threshold: exports_external.number().min(0.1).max(0.9).default(0.75),
|
|
14800
14817
|
idle_timeout_minutes: exports_external.number().min(5).max(240).default(60),
|
|
14801
14818
|
no_op_warning_threshold: exports_external.number().min(1).max(100).default(15),
|
|
14819
|
+
max_coder_revisions: exports_external.number().int().min(1).max(20).default(5),
|
|
14802
14820
|
qa_gates: exports_external.object({
|
|
14803
14821
|
required_tools: exports_external.array(exports_external.string().min(1)).default([
|
|
14804
14822
|
"diff",
|
|
@@ -15400,6 +15418,9 @@ import * as path4 from "path";
|
|
|
15400
15418
|
function isValidEvidenceType(type) {
|
|
15401
15419
|
return VALID_EVIDENCE_TYPES.includes(type);
|
|
15402
15420
|
}
|
|
15421
|
+
function isSecretscanEvidence(evidence) {
|
|
15422
|
+
return evidence.type === "secretscan";
|
|
15423
|
+
}
|
|
15403
15424
|
function sanitizeTaskId(taskId) {
|
|
15404
15425
|
if (!taskId || taskId.length === 0) {
|
|
15405
15426
|
throw new Error("Invalid task ID: empty string");
|
|
@@ -15652,11 +15673,12 @@ var init_manager = __esm(() => {
|
|
|
15652
15673
|
"sast",
|
|
15653
15674
|
"sbom",
|
|
15654
15675
|
"build",
|
|
15655
|
-
"quality_budget"
|
|
15676
|
+
"quality_budget",
|
|
15677
|
+
"secretscan"
|
|
15656
15678
|
];
|
|
15657
15679
|
TASK_ID_REGEX = /^\d+\.\d+(\.\d+)*$/;
|
|
15658
15680
|
RETRO_TASK_ID_REGEX = /^retro-\d+$/;
|
|
15659
|
-
INTERNAL_TOOL_ID_REGEX = /^(?:sast_scan|quality_budget|syntax_check|placeholder_scan|sbom_generate|build)$/;
|
|
15681
|
+
INTERNAL_TOOL_ID_REGEX = /^(?:sast_scan|quality_budget|syntax_check|placeholder_scan|sbom_generate|build|secretscan)$/;
|
|
15660
15682
|
LEGACY_TASK_COMPLEXITY_MAP = {
|
|
15661
15683
|
low: "simple",
|
|
15662
15684
|
medium: "moderate",
|
|
@@ -36250,7 +36272,7 @@ __export(exports_gate_evidence, {
|
|
|
36250
36272
|
deriveRequiredGates: () => deriveRequiredGates,
|
|
36251
36273
|
DEFAULT_REQUIRED_GATES: () => DEFAULT_REQUIRED_GATES
|
|
36252
36274
|
});
|
|
36253
|
-
import { mkdirSync as mkdirSync9, readFileSync as readFileSync14, renameSync as
|
|
36275
|
+
import { mkdirSync as mkdirSync9, readFileSync as readFileSync14, renameSync as renameSync9, unlinkSync as unlinkSync5 } from "fs";
|
|
36254
36276
|
import * as path30 from "path";
|
|
36255
36277
|
function isValidTaskId2(taskId) {
|
|
36256
36278
|
if (!taskId)
|
|
@@ -36315,7 +36337,7 @@ async function atomicWrite(targetPath, content) {
|
|
|
36315
36337
|
const tempPath = `${targetPath}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`;
|
|
36316
36338
|
try {
|
|
36317
36339
|
await Bun.write(tempPath, content);
|
|
36318
|
-
|
|
36340
|
+
renameSync9(tempPath, targetPath);
|
|
36319
36341
|
} finally {
|
|
36320
36342
|
try {
|
|
36321
36343
|
unlinkSync5(tempPath);
|
|
@@ -37910,11 +37932,11 @@ ${JSON.stringify(symbolNames, null, 2)}`);
|
|
|
37910
37932
|
throw toThrow;
|
|
37911
37933
|
}, "quit_");
|
|
37912
37934
|
var scriptDirectory = "";
|
|
37913
|
-
function locateFile(
|
|
37935
|
+
function locateFile(path48) {
|
|
37914
37936
|
if (Module["locateFile"]) {
|
|
37915
|
-
return Module["locateFile"](
|
|
37937
|
+
return Module["locateFile"](path48, scriptDirectory);
|
|
37916
37938
|
}
|
|
37917
|
-
return scriptDirectory +
|
|
37939
|
+
return scriptDirectory + path48;
|
|
37918
37940
|
}
|
|
37919
37941
|
__name(locateFile, "locateFile");
|
|
37920
37942
|
var readAsync, readBinary;
|
|
@@ -39662,7 +39684,7 @@ var init_runtime = __esm(() => {
|
|
|
39662
39684
|
});
|
|
39663
39685
|
|
|
39664
39686
|
// src/index.ts
|
|
39665
|
-
import * as
|
|
39687
|
+
import * as path58 from "path";
|
|
39666
39688
|
|
|
39667
39689
|
// src/agents/index.ts
|
|
39668
39690
|
init_config();
|
|
@@ -39729,6 +39751,10 @@ function startAgentSession(sessionId, agentName, staleDurationMs = 7200000, dire
|
|
|
39729
39751
|
scopeViolationDetected: false,
|
|
39730
39752
|
modifiedFilesThisCoderTask: [],
|
|
39731
39753
|
turboMode: false,
|
|
39754
|
+
model_fallback_index: 0,
|
|
39755
|
+
modelFallbackExhausted: false,
|
|
39756
|
+
coderRevisions: 0,
|
|
39757
|
+
revisionLimitHit: false,
|
|
39732
39758
|
loopDetectionWindow: [],
|
|
39733
39759
|
pendingAdvisoryMessages: []
|
|
39734
39760
|
};
|
|
@@ -39837,6 +39863,12 @@ function ensureAgentSession(sessionId, agentName, directory) {
|
|
|
39837
39863
|
if (session.turboMode === undefined) {
|
|
39838
39864
|
session.turboMode = false;
|
|
39839
39865
|
}
|
|
39866
|
+
if (session.model_fallback_index === undefined) {
|
|
39867
|
+
session.model_fallback_index = 0;
|
|
39868
|
+
}
|
|
39869
|
+
if (session.modelFallbackExhausted === undefined) {
|
|
39870
|
+
session.modelFallbackExhausted = false;
|
|
39871
|
+
}
|
|
39840
39872
|
if (session.loopDetectionWindow === undefined) {
|
|
39841
39873
|
session.loopDetectionWindow = [];
|
|
39842
39874
|
}
|
|
@@ -44112,14 +44144,18 @@ async function readCuratorSummary(directory) {
|
|
|
44112
44144
|
}
|
|
44113
44145
|
return parsed;
|
|
44114
44146
|
} catch {
|
|
44115
|
-
|
|
44147
|
+
if (process.env.DEBUG_SWARM) {
|
|
44148
|
+
console.warn("Failed to parse curator-summary.json: invalid JSON");
|
|
44149
|
+
}
|
|
44116
44150
|
return null;
|
|
44117
44151
|
}
|
|
44118
44152
|
}
|
|
44119
44153
|
async function writeCuratorSummary(directory, summary) {
|
|
44120
44154
|
const resolvedPath = validateSwarmPath(directory, "curator-summary.json");
|
|
44121
44155
|
fs7.mkdirSync(path12.dirname(resolvedPath), { recursive: true });
|
|
44122
|
-
|
|
44156
|
+
const tempPath = `${resolvedPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
|
|
44157
|
+
await Bun.write(tempPath, JSON.stringify(summary, null, 2));
|
|
44158
|
+
fs7.renameSync(tempPath, resolvedPath);
|
|
44123
44159
|
}
|
|
44124
44160
|
function normalizeAgentName(name2) {
|
|
44125
44161
|
return name2.toLowerCase().replace(/^(mega|paid|local|lowtier|modelrelay)_/, "");
|
|
@@ -44143,7 +44179,9 @@ function filterPhaseEvents(eventsJsonl, phase, sinceTimestamp) {
|
|
|
44143
44179
|
}
|
|
44144
44180
|
}
|
|
44145
44181
|
} catch {
|
|
44146
|
-
|
|
44182
|
+
if (process.env.DEBUG_SWARM) {
|
|
44183
|
+
console.warn("filterPhaseEvents: skipping malformed line");
|
|
44184
|
+
}
|
|
44147
44185
|
}
|
|
44148
44186
|
}
|
|
44149
44187
|
return filtered;
|
|
@@ -46473,7 +46511,7 @@ async function handleExportCommand(directory, _args) {
|
|
|
46473
46511
|
// src/commands/handoff.ts
|
|
46474
46512
|
init_utils2();
|
|
46475
46513
|
import crypto3 from "crypto";
|
|
46476
|
-
import { renameSync as
|
|
46514
|
+
import { renameSync as renameSync6 } from "fs";
|
|
46477
46515
|
|
|
46478
46516
|
// src/services/handoff-service.ts
|
|
46479
46517
|
init_utils2();
|
|
@@ -46774,7 +46812,7 @@ function formatHandoffMarkdown(data) {
|
|
|
46774
46812
|
|
|
46775
46813
|
// src/session/snapshot-writer.ts
|
|
46776
46814
|
init_utils2();
|
|
46777
|
-
import { mkdirSync as mkdirSync7, renameSync as
|
|
46815
|
+
import { mkdirSync as mkdirSync7, renameSync as renameSync5 } from "fs";
|
|
46778
46816
|
import * as path19 from "path";
|
|
46779
46817
|
var pendingWrite = null;
|
|
46780
46818
|
var lastWritePromise = Promise.resolve();
|
|
@@ -46839,7 +46877,11 @@ function serializeAgentSession(s) {
|
|
|
46839
46877
|
taskWorkflowStates: Object.fromEntries(s.taskWorkflowStates ?? new Map),
|
|
46840
46878
|
...s.scopeViolationDetected !== undefined && {
|
|
46841
46879
|
scopeViolationDetected: s.scopeViolationDetected
|
|
46842
|
-
}
|
|
46880
|
+
},
|
|
46881
|
+
model_fallback_index: s.model_fallback_index ?? 0,
|
|
46882
|
+
modelFallbackExhausted: s.modelFallbackExhausted ?? false,
|
|
46883
|
+
coderRevisions: s.coderRevisions ?? 0,
|
|
46884
|
+
revisionLimitHit: s.revisionLimitHit ?? false
|
|
46843
46885
|
};
|
|
46844
46886
|
}
|
|
46845
46887
|
async function writeSnapshot(directory, state) {
|
|
@@ -46861,9 +46903,11 @@ async function writeSnapshot(directory, state) {
|
|
|
46861
46903
|
mkdirSync7(dir, { recursive: true });
|
|
46862
46904
|
const tempPath = `${resolvedPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
|
|
46863
46905
|
await Bun.write(tempPath, content);
|
|
46864
|
-
|
|
46906
|
+
renameSync5(tempPath, resolvedPath);
|
|
46865
46907
|
} catch (error93) {
|
|
46866
|
-
|
|
46908
|
+
if (process.env.DEBUG_SWARM) {
|
|
46909
|
+
console.warn("[snapshot-writer] write failed:", error93 instanceof Error ? error93.message : String(error93));
|
|
46910
|
+
}
|
|
46867
46911
|
}
|
|
46868
46912
|
}
|
|
46869
46913
|
function createSnapshotWriterHook(directory) {
|
|
@@ -46893,7 +46937,7 @@ async function handleHandoffCommand(directory, _args) {
|
|
|
46893
46937
|
const resolvedPath = validateSwarmPath(directory, "handoff.md");
|
|
46894
46938
|
const tempPath = `${resolvedPath}.tmp.${crypto3.randomUUID()}`;
|
|
46895
46939
|
await Bun.write(tempPath, markdown);
|
|
46896
|
-
|
|
46940
|
+
renameSync6(tempPath, resolvedPath);
|
|
46897
46941
|
await writeSnapshot(directory, swarmState);
|
|
46898
46942
|
await flushPendingSnapshot(directory);
|
|
46899
46943
|
return `## Handoff Brief Written
|
|
@@ -47639,7 +47683,7 @@ async function handleResetSessionCommand(directory, _args) {
|
|
|
47639
47683
|
// src/summaries/manager.ts
|
|
47640
47684
|
init_utils2();
|
|
47641
47685
|
init_utils();
|
|
47642
|
-
import { mkdirSync as mkdirSync8, readdirSync as readdirSync7, renameSync as
|
|
47686
|
+
import { mkdirSync as mkdirSync8, readdirSync as readdirSync7, renameSync as renameSync7, rmSync as rmSync3, statSync as statSync7 } from "fs";
|
|
47643
47687
|
import * as path26 from "path";
|
|
47644
47688
|
var SUMMARY_ID_REGEX = /^S\d+$/;
|
|
47645
47689
|
function sanitizeSummaryId(id) {
|
|
@@ -47683,7 +47727,7 @@ async function storeSummary(directory, id, fullOutput, summaryText, maxStoredByt
|
|
|
47683
47727
|
const tempPath = path26.join(summaryDir, `${sanitizedId}.json.tmp.${Date.now()}.${process.pid}`);
|
|
47684
47728
|
try {
|
|
47685
47729
|
await Bun.write(tempPath, entryJson);
|
|
47686
|
-
|
|
47730
|
+
renameSync7(tempPath, summaryPath);
|
|
47687
47731
|
} catch (error93) {
|
|
47688
47732
|
try {
|
|
47689
47733
|
rmSync3(tempPath, { force: true });
|
|
@@ -48863,8 +48907,46 @@ async function executeWriteRetro(args2, directory) {
|
|
|
48863
48907
|
top_rejection_reasons: args2.top_rejection_reasons ?? [],
|
|
48864
48908
|
lessons_learned: (args2.lessons_learned ?? []).slice(0, 5),
|
|
48865
48909
|
user_directives: [],
|
|
48866
|
-
approaches_tried: []
|
|
48910
|
+
approaches_tried: [],
|
|
48911
|
+
error_taxonomy: []
|
|
48867
48912
|
};
|
|
48913
|
+
const taxonomy = [];
|
|
48914
|
+
try {
|
|
48915
|
+
for (const taskSuffix of ["1", "2", "3", "4", "5"]) {
|
|
48916
|
+
const phaseTaskId = `${phase}.${taskSuffix}`;
|
|
48917
|
+
const result = await loadEvidence(directory, phaseTaskId);
|
|
48918
|
+
if (result.status !== "found")
|
|
48919
|
+
continue;
|
|
48920
|
+
const bundle = result.bundle;
|
|
48921
|
+
for (const entry of bundle.entries) {
|
|
48922
|
+
const e = entry;
|
|
48923
|
+
if (e.type === "review" && e.verdict === "fail") {
|
|
48924
|
+
const reasonParts = [];
|
|
48925
|
+
if (typeof e.summary === "string")
|
|
48926
|
+
reasonParts.push(e.summary);
|
|
48927
|
+
if (Array.isArray(e.issues)) {
|
|
48928
|
+
for (const iss of e.issues) {
|
|
48929
|
+
if (typeof iss.message === "string")
|
|
48930
|
+
reasonParts.push(iss.message);
|
|
48931
|
+
}
|
|
48932
|
+
}
|
|
48933
|
+
const reason = reasonParts.join(" ");
|
|
48934
|
+
if (/signature|type|contract|interface/i.test(reason)) {
|
|
48935
|
+
taxonomy.push("interface_mismatch");
|
|
48936
|
+
} else {
|
|
48937
|
+
taxonomy.push("logic_error");
|
|
48938
|
+
}
|
|
48939
|
+
} else if (e.type === "test" && e.verdict === "fail") {
|
|
48940
|
+
taxonomy.push("logic_error");
|
|
48941
|
+
} else if (e.agent === "scope_guard" && e.verdict === "fail") {
|
|
48942
|
+
taxonomy.push("scope_creep");
|
|
48943
|
+
} else if (e.agent === "loop_detector" && e.verdict === "fail") {
|
|
48944
|
+
taxonomy.push("gate_evasion");
|
|
48945
|
+
}
|
|
48946
|
+
}
|
|
48947
|
+
}
|
|
48948
|
+
} catch {}
|
|
48949
|
+
retroEntry.error_taxonomy = [...new Set(taxonomy)];
|
|
48868
48950
|
try {
|
|
48869
48951
|
await saveEvidence(directory, taskId, retroEntry);
|
|
48870
48952
|
return JSON.stringify({
|
|
@@ -49187,7 +49269,7 @@ init_constants();
|
|
|
49187
49269
|
init_schema();
|
|
49188
49270
|
|
|
49189
49271
|
// src/hooks/agent-activity.ts
|
|
49190
|
-
import { renameSync as
|
|
49272
|
+
import { renameSync as renameSync8, unlinkSync as unlinkSync4 } from "fs";
|
|
49191
49273
|
init_utils();
|
|
49192
49274
|
init_utils2();
|
|
49193
49275
|
function createAgentActivityHooks(config3, directory) {
|
|
@@ -49261,7 +49343,7 @@ async function doFlush(directory) {
|
|
|
49261
49343
|
const tempPath = `${path29}.tmp`;
|
|
49262
49344
|
try {
|
|
49263
49345
|
await Bun.write(tempPath, updated);
|
|
49264
|
-
|
|
49346
|
+
renameSync8(tempPath, path29);
|
|
49265
49347
|
} catch (writeError) {
|
|
49266
49348
|
try {
|
|
49267
49349
|
unlinkSync4(tempPath);
|
|
@@ -49895,6 +49977,7 @@ function detectLoop(sessionId, toolName, args2) {
|
|
|
49895
49977
|
|
|
49896
49978
|
// src/hooks/guardrails.ts
|
|
49897
49979
|
var storedInputArgs = new Map;
|
|
49980
|
+
var TRANSIENT_MODEL_ERROR_PATTERN = /rate.?limit|429|503|timeout|overloaded|model.?not.?found|temporarily unavailable|server error/i;
|
|
49898
49981
|
function getStoredInputArgs(callID) {
|
|
49899
49982
|
return storedInputArgs.get(callID);
|
|
49900
49983
|
}
|
|
@@ -50072,6 +50155,9 @@ function createGuardrailsHooks(directory, directoryOrConfig, config3) {
|
|
|
50072
50155
|
const coderSession = swarmState.agentSessions.get(input.sessionID);
|
|
50073
50156
|
if (coderSession) {
|
|
50074
50157
|
coderSession.modifiedFilesThisCoderTask = [];
|
|
50158
|
+
if (!coderSession.revisionLimitHit) {
|
|
50159
|
+
coderSession.coderRevisions = 0;
|
|
50160
|
+
}
|
|
50075
50161
|
}
|
|
50076
50162
|
}
|
|
50077
50163
|
}
|
|
@@ -50080,7 +50166,7 @@ function createGuardrailsHooks(directory, directoryOrConfig, config3) {
|
|
|
50080
50166
|
const loopResult = detectLoop(input.sessionID, input.tool, loopArgs);
|
|
50081
50167
|
if (loopResult.count >= 5) {
|
|
50082
50168
|
throw new Error(`CIRCUIT BREAKER: Delegation loop detected (${loopResult.count} identical patterns). Session paused. Ask the user for guidance.`);
|
|
50083
|
-
} else if (loopResult.count
|
|
50169
|
+
} else if (loopResult.count >= 3 && loopResult.count < 5) {
|
|
50084
50170
|
const agentName2 = typeof loopArgs?.subagent_type === "string" ? loopArgs.subagent_type : "agent";
|
|
50085
50171
|
const loopSession = swarmState.agentSessions.get(input.sessionID);
|
|
50086
50172
|
if (loopSession) {
|
|
@@ -50411,6 +50497,16 @@ function createGuardrailsHooks(directory, directoryOrConfig, config3) {
|
|
|
50411
50497
|
}
|
|
50412
50498
|
if (delegation.isDelegation && delegation.targetAgent === "coder" && session.lastCoderDelegationTaskId) {
|
|
50413
50499
|
session.currentTaskId = session.lastCoderDelegationTaskId;
|
|
50500
|
+
if (!session.revisionLimitHit) {
|
|
50501
|
+
session.coderRevisions++;
|
|
50502
|
+
const maxRevisions = cfg.max_coder_revisions ?? 5;
|
|
50503
|
+
if (session.coderRevisions >= maxRevisions) {
|
|
50504
|
+
session.revisionLimitHit = true;
|
|
50505
|
+
session.pendingAdvisoryMessages ??= [];
|
|
50506
|
+
session.pendingAdvisoryMessages.push(`CODER REVISION LIMIT: Agent has been revised ${session.coderRevisions} times ` + `(max: ${maxRevisions}) for task ${session.currentTaskId ?? "unknown"}. ` + `Escalate to user or consider a fundamentally different approach.`);
|
|
50507
|
+
swarmState.pendingEvents++;
|
|
50508
|
+
}
|
|
50509
|
+
}
|
|
50414
50510
|
session.partialGateWarningsIssuedForTask?.delete(session.currentTaskId);
|
|
50415
50511
|
if (session.declaredCoderScope !== null) {
|
|
50416
50512
|
const undeclaredFiles = session.modifiedFilesThisCoderTask.map((f) => f.replace(/[\r\n\t]/g, "_")).filter((f) => !isInDeclaredScope(f, session.declaredCoderScope));
|
|
@@ -50442,9 +50538,26 @@ function createGuardrailsHooks(directory, directoryOrConfig, config3) {
|
|
|
50442
50538
|
const hasError = output.output === null || output.output === undefined;
|
|
50443
50539
|
if (hasError) {
|
|
50444
50540
|
window2.consecutiveErrors++;
|
|
50541
|
+
if (session) {
|
|
50542
|
+
const outputStr = typeof output.output === "string" ? output.output : "";
|
|
50543
|
+
const errorContent = output.error ?? outputStr;
|
|
50544
|
+
if (typeof errorContent === "string" && TRANSIENT_MODEL_ERROR_PATTERN.test(errorContent) && !session.modelFallbackExhausted) {
|
|
50545
|
+
session.model_fallback_index++;
|
|
50546
|
+
session.modelFallbackExhausted = true;
|
|
50547
|
+
session.pendingAdvisoryMessages ??= [];
|
|
50548
|
+
session.pendingAdvisoryMessages.push(`MODEL FALLBACK: Transient model error detected (attempt ${session.model_fallback_index}). ` + `The agent model may be rate-limited, overloaded, or temporarily unavailable. ` + `Consider retrying with a fallback model or waiting before retrying.`);
|
|
50549
|
+
swarmState.pendingEvents++;
|
|
50550
|
+
}
|
|
50551
|
+
}
|
|
50445
50552
|
} else {
|
|
50446
50553
|
window2.consecutiveErrors = 0;
|
|
50447
50554
|
window2.lastSuccessTimeMs = Date.now();
|
|
50555
|
+
if (session) {
|
|
50556
|
+
if (session.model_fallback_index > 0) {
|
|
50557
|
+
session.model_fallback_index = 0;
|
|
50558
|
+
session.modelFallbackExhausted = false;
|
|
50559
|
+
}
|
|
50560
|
+
}
|
|
50448
50561
|
}
|
|
50449
50562
|
},
|
|
50450
50563
|
messagesTransform: async (_input, output) => {
|
|
@@ -50740,7 +50853,7 @@ function extractPlanTaskId(text) {
|
|
|
50740
50853
|
function getSeedTaskId(session) {
|
|
50741
50854
|
return session.currentTaskId ?? session.lastCoderDelegationTaskId;
|
|
50742
50855
|
}
|
|
50743
|
-
function getEvidenceTaskId(session, directory) {
|
|
50856
|
+
async function getEvidenceTaskId(session, directory) {
|
|
50744
50857
|
const primary = session.currentTaskId ?? session.lastCoderDelegationTaskId;
|
|
50745
50858
|
if (primary)
|
|
50746
50859
|
return primary;
|
|
@@ -50757,7 +50870,7 @@ function getEvidenceTaskId(session, directory) {
|
|
|
50757
50870
|
if (!resolvedPlanPath.startsWith(resolvedDirectory + path31.sep) && resolvedPlanPath !== resolvedDirectory) {
|
|
50758
50871
|
return null;
|
|
50759
50872
|
}
|
|
50760
|
-
const planContent = fs19.
|
|
50873
|
+
const planContent = await fs19.promises.readFile(resolvedPlanPath, "utf-8");
|
|
50761
50874
|
const plan = JSON.parse(planContent);
|
|
50762
50875
|
if (!plan || !Array.isArray(plan.phases)) {
|
|
50763
50876
|
return null;
|
|
@@ -50877,7 +50990,7 @@ function createDelegationGateHook(config3, directory) {
|
|
|
50877
50990
|
}
|
|
50878
50991
|
if (typeof subagentType === "string") {
|
|
50879
50992
|
const rawTaskId = directArgs?.task_id;
|
|
50880
|
-
const evidenceTaskId = typeof rawTaskId === "string" && rawTaskId.length <= 20 && /^\d+\.\d+$/.test(rawTaskId.trim()) ? rawTaskId.trim() : getEvidenceTaskId(session, directory);
|
|
50993
|
+
const evidenceTaskId = typeof rawTaskId === "string" && rawTaskId.length <= 20 && /^\d+\.\d+$/.test(rawTaskId.trim()) ? rawTaskId.trim() : await getEvidenceTaskId(session, directory);
|
|
50881
50994
|
if (evidenceTaskId) {
|
|
50882
50995
|
try {
|
|
50883
50996
|
const turbo = hasActiveTurboMode();
|
|
@@ -50997,7 +51110,7 @@ function createDelegationGateHook(config3, directory) {
|
|
|
50997
51110
|
}
|
|
50998
51111
|
{
|
|
50999
51112
|
const rawTaskId = directArgs?.task_id;
|
|
51000
|
-
const evidenceTaskId = typeof rawTaskId === "string" && rawTaskId.length <= 20 && /^\d+\.\d+$/.test(rawTaskId.trim()) ? rawTaskId.trim() : getEvidenceTaskId(session, directory);
|
|
51113
|
+
const evidenceTaskId = typeof rawTaskId === "string" && rawTaskId.length <= 20 && /^\d+\.\d+$/.test(rawTaskId.trim()) ? rawTaskId.trim() : await getEvidenceTaskId(session, directory);
|
|
51001
51114
|
if (evidenceTaskId) {
|
|
51002
51115
|
try {
|
|
51003
51116
|
const turbo = hasActiveTurboMode();
|
|
@@ -51094,7 +51207,7 @@ ${trimComment}${after}`;
|
|
|
51094
51207
|
const currentTaskId = planTaskId ?? taskIdFromLine;
|
|
51095
51208
|
const coderDelegationPattern = /(?:^|\n)\s*(?:\w+_)?coder\s*\n\s*TASK:/i;
|
|
51096
51209
|
const isCoderDelegation = coderDelegationPattern.test(text);
|
|
51097
|
-
const priorCoderTaskId = sessionID ?
|
|
51210
|
+
const priorCoderTaskId = sessionID ? swarmState.agentSessions.get(sessionID)?.lastCoderDelegationTaskId ?? null : null;
|
|
51098
51211
|
if (sessionID && isCoderDelegation && currentTaskId) {
|
|
51099
51212
|
const session = ensureAgentSession(sessionID);
|
|
51100
51213
|
session.lastCoderDelegationTaskId = currentTaskId;
|
|
@@ -54872,7 +54985,11 @@ function deserializeAgentSession(s) {
|
|
|
54872
54985
|
lastScopeViolation: null,
|
|
54873
54986
|
scopeViolationDetected: s.scopeViolationDetected,
|
|
54874
54987
|
modifiedFilesThisCoderTask: [],
|
|
54875
|
-
pendingAdvisoryMessages: s.pendingAdvisoryMessages ?? []
|
|
54988
|
+
pendingAdvisoryMessages: s.pendingAdvisoryMessages ?? [],
|
|
54989
|
+
model_fallback_index: s.model_fallback_index ?? 0,
|
|
54990
|
+
modelFallbackExhausted: s.modelFallbackExhausted ?? false,
|
|
54991
|
+
coderRevisions: s.coderRevisions ?? 0,
|
|
54992
|
+
revisionLimitHit: s.revisionLimitHit ?? false
|
|
54876
54993
|
};
|
|
54877
54994
|
}
|
|
54878
54995
|
async function readSnapshot(directory) {
|
|
@@ -55115,6 +55232,7 @@ var build_check = createSwarmTool({
|
|
|
55115
55232
|
});
|
|
55116
55233
|
// src/tools/check-gate-status.ts
|
|
55117
55234
|
init_dist();
|
|
55235
|
+
init_manager();
|
|
55118
55236
|
init_create_tool();
|
|
55119
55237
|
import * as fs27 from "fs";
|
|
55120
55238
|
import * as path39 from "path";
|
|
@@ -55238,13 +55356,37 @@ var check_gate_status = createSwarmTool({
|
|
|
55238
55356
|
missingGates.push(requiredGate);
|
|
55239
55357
|
}
|
|
55240
55358
|
}
|
|
55241
|
-
|
|
55359
|
+
let status = missingGates.length === 0 ? "all_passed" : "incomplete";
|
|
55242
55360
|
let message;
|
|
55243
55361
|
if (status === "all_passed") {
|
|
55244
55362
|
message = `All required gates have passed for task "${taskIdInput}".`;
|
|
55245
55363
|
} else {
|
|
55246
55364
|
message = `Task "${taskIdInput}" is incomplete. Missing gates: ${missingGates.join(", ")}.`;
|
|
55247
55365
|
}
|
|
55366
|
+
let secretscanVerdict = "not_run";
|
|
55367
|
+
try {
|
|
55368
|
+
const evidenceResult = await loadEvidence(directory, taskIdInput);
|
|
55369
|
+
if (evidenceResult.status === "found") {
|
|
55370
|
+
const secretscanEntries = evidenceResult.bundle.entries.filter((entry) => entry.type === "secretscan");
|
|
55371
|
+
if (secretscanEntries.length > 0) {
|
|
55372
|
+
const lastSecretscan = secretscanEntries[secretscanEntries.length - 1];
|
|
55373
|
+
if (isSecretscanEvidence(lastSecretscan)) {
|
|
55374
|
+
if (lastSecretscan.verdict === "fail" || lastSecretscan.verdict === "rejected") {
|
|
55375
|
+
secretscanVerdict = "fail";
|
|
55376
|
+
missingGates.push("secretscan (BLOCKED \u2014 secrets detected)");
|
|
55377
|
+
if (status === "all_passed") {
|
|
55378
|
+
status = "incomplete";
|
|
55379
|
+
}
|
|
55380
|
+
message = `BLOCKED: Secretscan found secrets in prior scan. ${message}`;
|
|
55381
|
+
} else if (lastSecretscan.verdict === "pass" || lastSecretscan.verdict === "approved" || lastSecretscan.verdict === "info") {
|
|
55382
|
+
secretscanVerdict = "pass";
|
|
55383
|
+
}
|
|
55384
|
+
}
|
|
55385
|
+
} else {
|
|
55386
|
+
message += " Advisory: No secretscan evidence found for this task. Consider running secretscan.";
|
|
55387
|
+
}
|
|
55388
|
+
}
|
|
55389
|
+
} catch {}
|
|
55248
55390
|
const todoScan = evidenceData.todo_scan;
|
|
55249
55391
|
const result = {
|
|
55250
55392
|
taskId: taskIdInput,
|
|
@@ -55254,7 +55396,8 @@ var check_gate_status = createSwarmTool({
|
|
|
55254
55396
|
missing_gates: missingGates,
|
|
55255
55397
|
gates: gatesMap,
|
|
55256
55398
|
message,
|
|
55257
|
-
todo_scan: todoScan ?? null
|
|
55399
|
+
todo_scan: todoScan ?? null,
|
|
55400
|
+
secretscan_verdict: secretscanVerdict
|
|
55258
55401
|
};
|
|
55259
55402
|
return JSON.stringify(result, null, 2);
|
|
55260
55403
|
}
|
|
@@ -55980,6 +56123,391 @@ var diff = createSwarmTool({
|
|
|
55980
56123
|
}
|
|
55981
56124
|
}
|
|
55982
56125
|
});
|
|
56126
|
+
// src/tools/doc-scan.ts
|
|
56127
|
+
init_dist();
|
|
56128
|
+
init_schema();
|
|
56129
|
+
import * as crypto4 from "crypto";
|
|
56130
|
+
import * as fs30 from "fs";
|
|
56131
|
+
import { mkdir as mkdir5, readFile as readFile6, writeFile as writeFile5 } from "fs/promises";
|
|
56132
|
+
import * as path42 from "path";
|
|
56133
|
+
init_create_tool();
|
|
56134
|
+
var SKIP_DIRECTORIES2 = new Set([
|
|
56135
|
+
"node_modules",
|
|
56136
|
+
".git",
|
|
56137
|
+
".swarm",
|
|
56138
|
+
"dist",
|
|
56139
|
+
"build",
|
|
56140
|
+
".next",
|
|
56141
|
+
"vendor"
|
|
56142
|
+
]);
|
|
56143
|
+
var SKIP_PATTERNS = [/\.test\./, /\.spec\./, /\.d\.ts$/];
|
|
56144
|
+
var MAX_SUMMARY_LENGTH = 200;
|
|
56145
|
+
var MAX_INDEXED_FILES = 100;
|
|
56146
|
+
var READ_LINES_LIMIT = 30;
|
|
56147
|
+
var MIN_LESSON_LENGTH = 15;
|
|
56148
|
+
var MAX_CONSTRAINTS_PER_DOC = 5;
|
|
56149
|
+
var MAX_CONSTRAINT_LENGTH = 200;
|
|
56150
|
+
var RELEVANCE_THRESHOLD = 0.1;
|
|
56151
|
+
var DEDUP_THRESHOLD = 0.6;
|
|
56152
|
+
function normalizeSeparators(filePath) {
|
|
56153
|
+
return filePath.replace(/\\/g, "/");
|
|
56154
|
+
}
|
|
56155
|
+
function matchesDocPattern(filePath, patterns) {
|
|
56156
|
+
const normalizedPath = normalizeSeparators(filePath);
|
|
56157
|
+
const basename5 = path42.basename(filePath);
|
|
56158
|
+
for (const pattern of patterns) {
|
|
56159
|
+
if (!pattern.includes("/") && !pattern.includes("\\")) {
|
|
56160
|
+
if (basename5 === pattern) {
|
|
56161
|
+
return true;
|
|
56162
|
+
}
|
|
56163
|
+
continue;
|
|
56164
|
+
}
|
|
56165
|
+
if (pattern.startsWith("**/")) {
|
|
56166
|
+
const filenamePattern = pattern.slice(3);
|
|
56167
|
+
if (basename5 === filenamePattern) {
|
|
56168
|
+
return true;
|
|
56169
|
+
}
|
|
56170
|
+
continue;
|
|
56171
|
+
}
|
|
56172
|
+
const patternNormalized = normalizeSeparators(pattern);
|
|
56173
|
+
const dirPrefix = patternNormalized.replace(/\/\*\*.*$/, "").replace(/\/\*.*$/, "");
|
|
56174
|
+
if (normalizedPath.startsWith(dirPrefix + "/") || normalizedPath === dirPrefix) {
|
|
56175
|
+
return true;
|
|
56176
|
+
}
|
|
56177
|
+
}
|
|
56178
|
+
return false;
|
|
56179
|
+
}
|
|
56180
|
+
function extractTitleAndSummary(content, filename) {
|
|
56181
|
+
const lines = content.split(`
|
|
56182
|
+
`);
|
|
56183
|
+
let title = filename;
|
|
56184
|
+
let summary = "";
|
|
56185
|
+
let foundTitle = false;
|
|
56186
|
+
const potentialSummaryLines = [];
|
|
56187
|
+
for (let i2 = 0;i2 < lines.length && i2 < READ_LINES_LIMIT; i2++) {
|
|
56188
|
+
const line = lines[i2].trim();
|
|
56189
|
+
if (!foundTitle && line.startsWith("# ")) {
|
|
56190
|
+
title = line.slice(2).trim();
|
|
56191
|
+
foundTitle = true;
|
|
56192
|
+
continue;
|
|
56193
|
+
}
|
|
56194
|
+
if (line && !line.startsWith("#")) {
|
|
56195
|
+
potentialSummaryLines.push(line);
|
|
56196
|
+
}
|
|
56197
|
+
}
|
|
56198
|
+
for (const line of potentialSummaryLines) {
|
|
56199
|
+
summary += (summary ? " " : "") + line;
|
|
56200
|
+
if (summary.length >= MAX_SUMMARY_LENGTH) {
|
|
56201
|
+
break;
|
|
56202
|
+
}
|
|
56203
|
+
}
|
|
56204
|
+
if (summary.length > MAX_SUMMARY_LENGTH) {
|
|
56205
|
+
summary = summary.slice(0, MAX_SUMMARY_LENGTH - 3) + "...";
|
|
56206
|
+
}
|
|
56207
|
+
return { title, summary };
|
|
56208
|
+
}
|
|
56209
|
+
function stripMarkdown(text) {
|
|
56210
|
+
return text.replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/\*\*([^*]+)\*\*/g, "$1").replace(/`([^`]+)`/g, "$1").replace(/^\s*[-*\u2022]\s+/gm, "").replace(/^\s*\d+\.\s+/gm, "").trim();
|
|
56211
|
+
}
|
|
56212
|
+
async function scanDocIndex(directory) {
|
|
56213
|
+
const manifestPath = path42.join(directory, ".swarm", "doc-manifest.json");
|
|
56214
|
+
const defaultPatterns = DocsConfigSchema.parse({}).doc_patterns;
|
|
56215
|
+
const extraPatterns = [
|
|
56216
|
+
"ARCHITECTURE.md",
|
|
56217
|
+
"CLAUDE.md",
|
|
56218
|
+
"AGENTS.md",
|
|
56219
|
+
".github/*.md",
|
|
56220
|
+
"doc/**/*.md"
|
|
56221
|
+
];
|
|
56222
|
+
const allPatterns = [...defaultPatterns, ...extraPatterns];
|
|
56223
|
+
try {
|
|
56224
|
+
const manifestContent = await readFile6(manifestPath, "utf-8");
|
|
56225
|
+
const existingManifest = JSON.parse(manifestContent);
|
|
56226
|
+
if (existingManifest.schema_version === 1 && existingManifest.files) {
|
|
56227
|
+
let cacheValid = true;
|
|
56228
|
+
for (const file3 of existingManifest.files) {
|
|
56229
|
+
try {
|
|
56230
|
+
const fullPath = path42.join(directory, file3.path);
|
|
56231
|
+
const stat2 = fs30.statSync(fullPath);
|
|
56232
|
+
if (stat2.mtimeMs > new Date(existingManifest.scanned_at).getTime()) {
|
|
56233
|
+
cacheValid = false;
|
|
56234
|
+
break;
|
|
56235
|
+
}
|
|
56236
|
+
} catch {
|
|
56237
|
+
cacheValid = false;
|
|
56238
|
+
break;
|
|
56239
|
+
}
|
|
56240
|
+
}
|
|
56241
|
+
if (cacheValid) {
|
|
56242
|
+
return { manifest: existingManifest, cached: true };
|
|
56243
|
+
}
|
|
56244
|
+
}
|
|
56245
|
+
} catch {}
|
|
56246
|
+
const discoveredFiles = [];
|
|
56247
|
+
let rawEntries;
|
|
56248
|
+
try {
|
|
56249
|
+
rawEntries = fs30.readdirSync(directory, { recursive: true });
|
|
56250
|
+
} catch {
|
|
56251
|
+
const manifest2 = {
|
|
56252
|
+
schema_version: 1,
|
|
56253
|
+
scanned_at: new Date().toISOString(),
|
|
56254
|
+
files: []
|
|
56255
|
+
};
|
|
56256
|
+
return { manifest: manifest2, cached: false };
|
|
56257
|
+
}
|
|
56258
|
+
const entries = rawEntries.filter((e) => typeof e === "string");
|
|
56259
|
+
for (const entry of entries) {
|
|
56260
|
+
const fullPath = path42.join(directory, entry);
|
|
56261
|
+
let stat2;
|
|
56262
|
+
try {
|
|
56263
|
+
stat2 = fs30.statSync(fullPath);
|
|
56264
|
+
} catch {
|
|
56265
|
+
continue;
|
|
56266
|
+
}
|
|
56267
|
+
if (!stat2.isFile())
|
|
56268
|
+
continue;
|
|
56269
|
+
const pathParts = normalizeSeparators(entry).split("/");
|
|
56270
|
+
let skipThisFile = false;
|
|
56271
|
+
for (const part of pathParts) {
|
|
56272
|
+
if (SKIP_DIRECTORIES2.has(part)) {
|
|
56273
|
+
skipThisFile = true;
|
|
56274
|
+
break;
|
|
56275
|
+
}
|
|
56276
|
+
}
|
|
56277
|
+
if (skipThisFile)
|
|
56278
|
+
continue;
|
|
56279
|
+
for (const pattern of SKIP_PATTERNS) {
|
|
56280
|
+
if (pattern.test(entry)) {
|
|
56281
|
+
skipThisFile = true;
|
|
56282
|
+
break;
|
|
56283
|
+
}
|
|
56284
|
+
}
|
|
56285
|
+
if (skipThisFile)
|
|
56286
|
+
continue;
|
|
56287
|
+
if (!matchesDocPattern(entry, allPatterns)) {
|
|
56288
|
+
continue;
|
|
56289
|
+
}
|
|
56290
|
+
let content;
|
|
56291
|
+
try {
|
|
56292
|
+
content = fs30.readFileSync(fullPath, "utf-8");
|
|
56293
|
+
} catch {
|
|
56294
|
+
continue;
|
|
56295
|
+
}
|
|
56296
|
+
const { title, summary } = extractTitleAndSummary(content, path42.basename(entry));
|
|
56297
|
+
const lineCount = content.split(`
|
|
56298
|
+
`).length;
|
|
56299
|
+
discoveredFiles.push({
|
|
56300
|
+
path: entry,
|
|
56301
|
+
title,
|
|
56302
|
+
summary,
|
|
56303
|
+
lines: lineCount,
|
|
56304
|
+
mtime: stat2.mtimeMs
|
|
56305
|
+
});
|
|
56306
|
+
}
|
|
56307
|
+
discoveredFiles.sort((a, b) => a.path.toLowerCase().localeCompare(b.path.toLowerCase()));
|
|
56308
|
+
let truncated = false;
|
|
56309
|
+
if (discoveredFiles.length > MAX_INDEXED_FILES) {
|
|
56310
|
+
discoveredFiles.splice(MAX_INDEXED_FILES);
|
|
56311
|
+
truncated = true;
|
|
56312
|
+
}
|
|
56313
|
+
if (truncated && discoveredFiles.length > 0) {
|
|
56314
|
+
discoveredFiles[0].summary = `[Warning: ${MAX_INDEXED_FILES}+ docs found, listing first ${MAX_INDEXED_FILES}] ` + discoveredFiles[0].summary;
|
|
56315
|
+
}
|
|
56316
|
+
const manifest = {
|
|
56317
|
+
schema_version: 1,
|
|
56318
|
+
scanned_at: new Date().toISOString(),
|
|
56319
|
+
files: discoveredFiles
|
|
56320
|
+
};
|
|
56321
|
+
try {
|
|
56322
|
+
await mkdir5(path42.dirname(manifestPath), { recursive: true });
|
|
56323
|
+
await writeFile5(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
|
|
56324
|
+
} catch {}
|
|
56325
|
+
return { manifest, cached: false };
|
|
56326
|
+
}
|
|
56327
|
+
var CONSTRAINT_PATTERNS = [
|
|
56328
|
+
/\bMUST\b/,
|
|
56329
|
+
/\bMUST NOT\b/,
|
|
56330
|
+
/\bSHOULD\b/,
|
|
56331
|
+
/\bSHOULD NOT\b/,
|
|
56332
|
+
/\bDO NOT\b/,
|
|
56333
|
+
/\bALWAYS\b/,
|
|
56334
|
+
/\bNEVER\b/,
|
|
56335
|
+
/\bREQUIRED\b/
|
|
56336
|
+
];
|
|
56337
|
+
var ACTION_WORDS = /\b(must|should|don't|avoid|ensure|use|follow)\b/i;
|
|
56338
|
+
function isConstraintLine(line) {
|
|
56339
|
+
const upperLine = line.toUpperCase();
|
|
56340
|
+
for (const pattern of CONSTRAINT_PATTERNS) {
|
|
56341
|
+
if (pattern.test(upperLine)) {
|
|
56342
|
+
return true;
|
|
56343
|
+
}
|
|
56344
|
+
}
|
|
56345
|
+
if (/^\s*[-*\u2022]/.test(line) && ACTION_WORDS.test(line)) {
|
|
56346
|
+
return true;
|
|
56347
|
+
}
|
|
56348
|
+
return false;
|
|
56349
|
+
}
|
|
56350
|
+
function extractConstraintsFromContent(content) {
|
|
56351
|
+
const lines = content.split(`
|
|
56352
|
+
`);
|
|
56353
|
+
const constraints = [];
|
|
56354
|
+
for (const line of lines) {
|
|
56355
|
+
if (constraints.length >= MAX_CONSTRAINTS_PER_DOC) {
|
|
56356
|
+
break;
|
|
56357
|
+
}
|
|
56358
|
+
const trimmed = line.trim();
|
|
56359
|
+
if (!trimmed)
|
|
56360
|
+
continue;
|
|
56361
|
+
if (isConstraintLine(trimmed)) {
|
|
56362
|
+
const cleaned = stripMarkdown(trimmed);
|
|
56363
|
+
const len = cleaned.length;
|
|
56364
|
+
if (len >= MIN_LESSON_LENGTH && len <= MAX_CONSTRAINT_LENGTH) {
|
|
56365
|
+
constraints.push(cleaned);
|
|
56366
|
+
}
|
|
56367
|
+
}
|
|
56368
|
+
}
|
|
56369
|
+
return constraints;
|
|
56370
|
+
}
|
|
56371
|
+
async function extractDocConstraints(directory, taskFiles, taskDescription) {
|
|
56372
|
+
const manifestPath = path42.join(directory, ".swarm", "doc-manifest.json");
|
|
56373
|
+
let manifest;
|
|
56374
|
+
try {
|
|
56375
|
+
const content = await readFile6(manifestPath, "utf-8");
|
|
56376
|
+
manifest = JSON.parse(content);
|
|
56377
|
+
} catch {
|
|
56378
|
+
const result = await scanDocIndex(directory);
|
|
56379
|
+
manifest = result.manifest;
|
|
56380
|
+
}
|
|
56381
|
+
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
56382
|
+
const existingEntries = await readKnowledge(knowledgePath);
|
|
56383
|
+
const taskContext = [...taskFiles, taskDescription].join(" ");
|
|
56384
|
+
const taskBigrams = wordBigrams(normalize2(taskContext));
|
|
56385
|
+
let extractedCount = 0;
|
|
56386
|
+
let skippedCount = 0;
|
|
56387
|
+
const details = [];
|
|
56388
|
+
for (const docFile of manifest.files) {
|
|
56389
|
+
const docContext = `${docFile.path} ${docFile.title} ${docFile.summary}`;
|
|
56390
|
+
const docBigrams = wordBigrams(normalize2(docContext));
|
|
56391
|
+
const score = jaccardBigram(taskBigrams, docBigrams);
|
|
56392
|
+
if (score <= RELEVANCE_THRESHOLD) {
|
|
56393
|
+
skippedCount++;
|
|
56394
|
+
continue;
|
|
56395
|
+
}
|
|
56396
|
+
let fullContent;
|
|
56397
|
+
try {
|
|
56398
|
+
fullContent = await readFile6(path42.join(directory, docFile.path), "utf-8");
|
|
56399
|
+
} catch {
|
|
56400
|
+
skippedCount++;
|
|
56401
|
+
continue;
|
|
56402
|
+
}
|
|
56403
|
+
const constraints = extractConstraintsFromContent(fullContent);
|
|
56404
|
+
if (constraints.length === 0) {
|
|
56405
|
+
skippedCount++;
|
|
56406
|
+
continue;
|
|
56407
|
+
}
|
|
56408
|
+
const docDetails = {
|
|
56409
|
+
path: docFile.path,
|
|
56410
|
+
score,
|
|
56411
|
+
constraints: []
|
|
56412
|
+
};
|
|
56413
|
+
for (const constraint of constraints) {
|
|
56414
|
+
const duplicate = findNearDuplicate(constraint, existingEntries, DEDUP_THRESHOLD);
|
|
56415
|
+
if (!duplicate) {
|
|
56416
|
+
const entry = {
|
|
56417
|
+
id: crypto4.randomUUID(),
|
|
56418
|
+
tier: "swarm",
|
|
56419
|
+
lesson: constraint,
|
|
56420
|
+
category: "architecture",
|
|
56421
|
+
tags: ["doc-scan", path42.basename(docFile.path)],
|
|
56422
|
+
scope: "global",
|
|
56423
|
+
confidence: 0.5,
|
|
56424
|
+
status: "candidate",
|
|
56425
|
+
confirmed_by: [],
|
|
56426
|
+
project_name: "",
|
|
56427
|
+
retrieval_outcomes: {
|
|
56428
|
+
applied_count: 0,
|
|
56429
|
+
succeeded_after_count: 0,
|
|
56430
|
+
failed_after_count: 0
|
|
56431
|
+
},
|
|
56432
|
+
schema_version: 1,
|
|
56433
|
+
created_at: new Date().toISOString(),
|
|
56434
|
+
updated_at: new Date().toISOString(),
|
|
56435
|
+
auto_generated: true,
|
|
56436
|
+
hive_eligible: false
|
|
56437
|
+
};
|
|
56438
|
+
await appendKnowledge(knowledgePath, entry);
|
|
56439
|
+
existingEntries.push(entry);
|
|
56440
|
+
extractedCount++;
|
|
56441
|
+
docDetails.constraints.push(constraint);
|
|
56442
|
+
}
|
|
56443
|
+
}
|
|
56444
|
+
if (docDetails.constraints.length > 0) {
|
|
56445
|
+
details.push(docDetails);
|
|
56446
|
+
} else {
|
|
56447
|
+
skippedCount++;
|
|
56448
|
+
}
|
|
56449
|
+
}
|
|
56450
|
+
return { extracted: extractedCount, skipped: skippedCount, details };
|
|
56451
|
+
}
|
|
56452
|
+
var doc_scan = createSwarmTool({
|
|
56453
|
+
description: "Scan project documentation files and build an index manifest. Caches results in .swarm/doc-manifest.json for fast subsequent scans.",
|
|
56454
|
+
args: {
|
|
56455
|
+
force: tool.schema.boolean().optional().describe("Force re-scan even if cache is valid")
|
|
56456
|
+
},
|
|
56457
|
+
execute: async (args2, directory) => {
|
|
56458
|
+
let force = false;
|
|
56459
|
+
try {
|
|
56460
|
+
if (args2 && typeof args2 === "object") {
|
|
56461
|
+
const obj = args2;
|
|
56462
|
+
if (obj.force === true)
|
|
56463
|
+
force = true;
|
|
56464
|
+
}
|
|
56465
|
+
} catch {}
|
|
56466
|
+
if (force) {
|
|
56467
|
+
const manifestPath = path42.join(directory, ".swarm", "doc-manifest.json");
|
|
56468
|
+
try {
|
|
56469
|
+
fs30.unlinkSync(manifestPath);
|
|
56470
|
+
} catch {}
|
|
56471
|
+
}
|
|
56472
|
+
const { manifest, cached: cached3 } = await scanDocIndex(directory);
|
|
56473
|
+
return JSON.stringify({
|
|
56474
|
+
success: true,
|
|
56475
|
+
files_count: manifest.files.length,
|
|
56476
|
+
cached: cached3,
|
|
56477
|
+
manifest
|
|
56478
|
+
}, null, 2);
|
|
56479
|
+
}
|
|
56480
|
+
});
|
|
56481
|
+
var doc_extract = createSwarmTool({
|
|
56482
|
+
description: "Extract actionable constraints from project documentation relevant to the current task. Scans docs via doc-manifest, scores relevance via Jaccard bigram similarity, and stores non-duplicate constraints in .swarm/knowledge.jsonl.",
|
|
56483
|
+
args: {
|
|
56484
|
+
task_files: tool.schema.array(tool.schema.string()).describe("List of file paths involved in the current task"),
|
|
56485
|
+
task_description: tool.schema.string().describe("Description of the current task")
|
|
56486
|
+
},
|
|
56487
|
+
execute: async (args2, directory) => {
|
|
56488
|
+
let taskFiles = [];
|
|
56489
|
+
let taskDescription = "";
|
|
56490
|
+
try {
|
|
56491
|
+
if (args2 && typeof args2 === "object") {
|
|
56492
|
+
const obj = args2;
|
|
56493
|
+
if (Array.isArray(obj.task_files)) {
|
|
56494
|
+
taskFiles = obj.task_files.filter((f) => typeof f === "string");
|
|
56495
|
+
}
|
|
56496
|
+
if (typeof obj.task_description === "string") {
|
|
56497
|
+
taskDescription = obj.task_description;
|
|
56498
|
+
}
|
|
56499
|
+
}
|
|
56500
|
+
} catch {}
|
|
56501
|
+
if (taskFiles.length === 0 && !taskDescription) {
|
|
56502
|
+
return JSON.stringify({
|
|
56503
|
+
success: false,
|
|
56504
|
+
error: "task_files or task_description is required"
|
|
56505
|
+
});
|
|
56506
|
+
}
|
|
56507
|
+
const result = await extractDocConstraints(directory, taskFiles, taskDescription);
|
|
56508
|
+
return JSON.stringify({ success: true, ...result }, null, 2);
|
|
56509
|
+
}
|
|
56510
|
+
});
|
|
55983
56511
|
// src/tools/domain-detector.ts
|
|
55984
56512
|
init_tool();
|
|
55985
56513
|
var DOMAIN_PATTERNS = {
|
|
@@ -56163,8 +56691,8 @@ Use these as DOMAIN values when delegating to @sme.`;
|
|
|
56163
56691
|
// src/tools/evidence-check.ts
|
|
56164
56692
|
init_dist();
|
|
56165
56693
|
init_create_tool();
|
|
56166
|
-
import * as
|
|
56167
|
-
import * as
|
|
56694
|
+
import * as fs31 from "fs";
|
|
56695
|
+
import * as path43 from "path";
|
|
56168
56696
|
var MAX_FILE_SIZE_BYTES3 = 1024 * 1024;
|
|
56169
56697
|
var MAX_EVIDENCE_FILES = 1000;
|
|
56170
56698
|
var EVIDENCE_DIR2 = ".swarm/evidence";
|
|
@@ -56194,9 +56722,9 @@ function validateRequiredTypes(input) {
|
|
|
56194
56722
|
return null;
|
|
56195
56723
|
}
|
|
56196
56724
|
function isPathWithinSwarm2(filePath, cwd) {
|
|
56197
|
-
const normalizedCwd =
|
|
56198
|
-
const swarmPath =
|
|
56199
|
-
const normalizedPath =
|
|
56725
|
+
const normalizedCwd = path43.resolve(cwd);
|
|
56726
|
+
const swarmPath = path43.join(normalizedCwd, ".swarm");
|
|
56727
|
+
const normalizedPath = path43.resolve(filePath);
|
|
56200
56728
|
return normalizedPath.startsWith(swarmPath);
|
|
56201
56729
|
}
|
|
56202
56730
|
function parseCompletedTasks(planContent) {
|
|
@@ -56212,12 +56740,12 @@ function parseCompletedTasks(planContent) {
|
|
|
56212
56740
|
}
|
|
56213
56741
|
function readEvidenceFiles(evidenceDir, _cwd) {
|
|
56214
56742
|
const evidence = [];
|
|
56215
|
-
if (!
|
|
56743
|
+
if (!fs31.existsSync(evidenceDir) || !fs31.statSync(evidenceDir).isDirectory()) {
|
|
56216
56744
|
return evidence;
|
|
56217
56745
|
}
|
|
56218
56746
|
let files;
|
|
56219
56747
|
try {
|
|
56220
|
-
files =
|
|
56748
|
+
files = fs31.readdirSync(evidenceDir);
|
|
56221
56749
|
} catch {
|
|
56222
56750
|
return evidence;
|
|
56223
56751
|
}
|
|
@@ -56226,14 +56754,14 @@ function readEvidenceFiles(evidenceDir, _cwd) {
|
|
|
56226
56754
|
if (!VALID_EVIDENCE_FILENAME_REGEX.test(filename)) {
|
|
56227
56755
|
continue;
|
|
56228
56756
|
}
|
|
56229
|
-
const filePath =
|
|
56757
|
+
const filePath = path43.join(evidenceDir, filename);
|
|
56230
56758
|
try {
|
|
56231
|
-
const resolvedPath =
|
|
56232
|
-
const evidenceDirResolved =
|
|
56759
|
+
const resolvedPath = path43.resolve(filePath);
|
|
56760
|
+
const evidenceDirResolved = path43.resolve(evidenceDir);
|
|
56233
56761
|
if (!resolvedPath.startsWith(evidenceDirResolved)) {
|
|
56234
56762
|
continue;
|
|
56235
56763
|
}
|
|
56236
|
-
const stat2 =
|
|
56764
|
+
const stat2 = fs31.lstatSync(filePath);
|
|
56237
56765
|
if (!stat2.isFile()) {
|
|
56238
56766
|
continue;
|
|
56239
56767
|
}
|
|
@@ -56242,7 +56770,7 @@ function readEvidenceFiles(evidenceDir, _cwd) {
|
|
|
56242
56770
|
}
|
|
56243
56771
|
let fileStat;
|
|
56244
56772
|
try {
|
|
56245
|
-
fileStat =
|
|
56773
|
+
fileStat = fs31.statSync(filePath);
|
|
56246
56774
|
if (fileStat.size > MAX_FILE_SIZE_BYTES3) {
|
|
56247
56775
|
continue;
|
|
56248
56776
|
}
|
|
@@ -56251,7 +56779,7 @@ function readEvidenceFiles(evidenceDir, _cwd) {
|
|
|
56251
56779
|
}
|
|
56252
56780
|
let content;
|
|
56253
56781
|
try {
|
|
56254
|
-
content =
|
|
56782
|
+
content = fs31.readFileSync(filePath, "utf-8");
|
|
56255
56783
|
} catch {
|
|
56256
56784
|
continue;
|
|
56257
56785
|
}
|
|
@@ -56347,7 +56875,7 @@ var evidence_check = createSwarmTool({
|
|
|
56347
56875
|
return JSON.stringify(errorResult, null, 2);
|
|
56348
56876
|
}
|
|
56349
56877
|
const requiredTypes = requiredTypesValue.split(",").map((t) => t.trim()).filter((t) => t.length > 0).map(normalizeEvidenceType);
|
|
56350
|
-
const planPath =
|
|
56878
|
+
const planPath = path43.join(cwd, PLAN_FILE);
|
|
56351
56879
|
if (!isPathWithinSwarm2(planPath, cwd)) {
|
|
56352
56880
|
const errorResult = {
|
|
56353
56881
|
error: "plan file path validation failed",
|
|
@@ -56361,7 +56889,7 @@ var evidence_check = createSwarmTool({
|
|
|
56361
56889
|
}
|
|
56362
56890
|
let planContent;
|
|
56363
56891
|
try {
|
|
56364
|
-
planContent =
|
|
56892
|
+
planContent = fs31.readFileSync(planPath, "utf-8");
|
|
56365
56893
|
} catch {
|
|
56366
56894
|
const result2 = {
|
|
56367
56895
|
message: "No completed tasks found in plan.",
|
|
@@ -56379,7 +56907,7 @@ var evidence_check = createSwarmTool({
|
|
|
56379
56907
|
};
|
|
56380
56908
|
return JSON.stringify(result2, null, 2);
|
|
56381
56909
|
}
|
|
56382
|
-
const evidenceDir =
|
|
56910
|
+
const evidenceDir = path43.join(cwd, EVIDENCE_DIR2);
|
|
56383
56911
|
const evidence = readEvidenceFiles(evidenceDir, cwd);
|
|
56384
56912
|
const { tasksWithFullEvidence, gaps } = analyzeGaps(completedTasks, evidence, requiredTypes);
|
|
56385
56913
|
const completeness = completedTasks.length > 0 ? Math.round(tasksWithFullEvidence.length / completedTasks.length * 100) / 100 : 1;
|
|
@@ -56396,8 +56924,8 @@ var evidence_check = createSwarmTool({
|
|
|
56396
56924
|
// src/tools/file-extractor.ts
|
|
56397
56925
|
init_tool();
|
|
56398
56926
|
init_create_tool();
|
|
56399
|
-
import * as
|
|
56400
|
-
import * as
|
|
56927
|
+
import * as fs32 from "fs";
|
|
56928
|
+
import * as path44 from "path";
|
|
56401
56929
|
var EXT_MAP = {
|
|
56402
56930
|
python: ".py",
|
|
56403
56931
|
py: ".py",
|
|
@@ -56459,8 +56987,8 @@ var extract_code_blocks = createSwarmTool({
|
|
|
56459
56987
|
execute: async (args2, directory) => {
|
|
56460
56988
|
const { content, output_dir, prefix } = args2;
|
|
56461
56989
|
const targetDir = output_dir || directory;
|
|
56462
|
-
if (!
|
|
56463
|
-
|
|
56990
|
+
if (!fs32.existsSync(targetDir)) {
|
|
56991
|
+
fs32.mkdirSync(targetDir, { recursive: true });
|
|
56464
56992
|
}
|
|
56465
56993
|
if (!content) {
|
|
56466
56994
|
return "Error: content is required";
|
|
@@ -56478,16 +57006,16 @@ var extract_code_blocks = createSwarmTool({
|
|
|
56478
57006
|
if (prefix) {
|
|
56479
57007
|
filename = `${prefix}_${filename}`;
|
|
56480
57008
|
}
|
|
56481
|
-
let filepath =
|
|
56482
|
-
const base =
|
|
56483
|
-
const ext =
|
|
57009
|
+
let filepath = path44.join(targetDir, filename);
|
|
57010
|
+
const base = path44.basename(filepath, path44.extname(filepath));
|
|
57011
|
+
const ext = path44.extname(filepath);
|
|
56484
57012
|
let counter = 1;
|
|
56485
|
-
while (
|
|
56486
|
-
filepath =
|
|
57013
|
+
while (fs32.existsSync(filepath)) {
|
|
57014
|
+
filepath = path44.join(targetDir, `${base}_${counter}${ext}`);
|
|
56487
57015
|
counter++;
|
|
56488
57016
|
}
|
|
56489
57017
|
try {
|
|
56490
|
-
|
|
57018
|
+
fs32.writeFileSync(filepath, code.trim(), "utf-8");
|
|
56491
57019
|
savedFiles.push(filepath);
|
|
56492
57020
|
} catch (error93) {
|
|
56493
57021
|
errors5.push(`Failed to save ${filename}: ${error93 instanceof Error ? error93.message : String(error93)}`);
|
|
@@ -56603,8 +57131,8 @@ var gitingest = createSwarmTool({
|
|
|
56603
57131
|
// src/tools/imports.ts
|
|
56604
57132
|
init_dist();
|
|
56605
57133
|
init_create_tool();
|
|
56606
|
-
import * as
|
|
56607
|
-
import * as
|
|
57134
|
+
import * as fs33 from "fs";
|
|
57135
|
+
import * as path45 from "path";
|
|
56608
57136
|
var MAX_FILE_PATH_LENGTH2 = 500;
|
|
56609
57137
|
var MAX_SYMBOL_LENGTH = 256;
|
|
56610
57138
|
var MAX_FILE_SIZE_BYTES4 = 1024 * 1024;
|
|
@@ -56658,7 +57186,7 @@ function validateSymbolInput(symbol3) {
|
|
|
56658
57186
|
return null;
|
|
56659
57187
|
}
|
|
56660
57188
|
function isBinaryFile2(filePath, buffer) {
|
|
56661
|
-
const ext =
|
|
57189
|
+
const ext = path45.extname(filePath).toLowerCase();
|
|
56662
57190
|
if (ext === ".json" || ext === ".md" || ext === ".txt") {
|
|
56663
57191
|
return false;
|
|
56664
57192
|
}
|
|
@@ -56682,15 +57210,15 @@ function parseImports(content, targetFile, targetSymbol) {
|
|
|
56682
57210
|
const imports = [];
|
|
56683
57211
|
let _resolvedTarget;
|
|
56684
57212
|
try {
|
|
56685
|
-
_resolvedTarget =
|
|
57213
|
+
_resolvedTarget = path45.resolve(targetFile);
|
|
56686
57214
|
} catch {
|
|
56687
57215
|
_resolvedTarget = targetFile;
|
|
56688
57216
|
}
|
|
56689
|
-
const targetBasename =
|
|
57217
|
+
const targetBasename = path45.basename(targetFile, path45.extname(targetFile));
|
|
56690
57218
|
const targetWithExt = targetFile;
|
|
56691
57219
|
const targetWithoutExt = targetFile.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
|
|
56692
|
-
const normalizedTargetWithExt =
|
|
56693
|
-
const normalizedTargetWithoutExt =
|
|
57220
|
+
const normalizedTargetWithExt = path45.normalize(targetWithExt).replace(/\\/g, "/");
|
|
57221
|
+
const normalizedTargetWithoutExt = path45.normalize(targetWithoutExt).replace(/\\/g, "/");
|
|
56694
57222
|
const importRegex = /import\s+(?:\{[\s\S]*?\}|(?:\*\s+as\s+\w+)|\w+)\s+from\s+['"`]([^'"`]+)['"`]|import\s+['"`]([^'"`]+)['"`]|require\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g;
|
|
56695
57223
|
for (let match = importRegex.exec(content);match !== null; match = importRegex.exec(content)) {
|
|
56696
57224
|
const modulePath = match[1] || match[2] || match[3];
|
|
@@ -56713,9 +57241,9 @@ function parseImports(content, targetFile, targetSymbol) {
|
|
|
56713
57241
|
}
|
|
56714
57242
|
const _normalizedModule = modulePath.replace(/^\.\//, "").replace(/^\.\.\\/, "../");
|
|
56715
57243
|
let isMatch = false;
|
|
56716
|
-
const _targetDir =
|
|
56717
|
-
const targetExt =
|
|
56718
|
-
const targetBasenameNoExt =
|
|
57244
|
+
const _targetDir = path45.dirname(targetFile);
|
|
57245
|
+
const targetExt = path45.extname(targetFile);
|
|
57246
|
+
const targetBasenameNoExt = path45.basename(targetFile, targetExt);
|
|
56719
57247
|
const moduleNormalized = modulePath.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
56720
57248
|
const moduleName = modulePath.split(/[/\\]/).pop() || "";
|
|
56721
57249
|
const moduleNameNoExt = moduleName.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
|
|
@@ -56755,7 +57283,7 @@ function parseImports(content, targetFile, targetSymbol) {
|
|
|
56755
57283
|
}
|
|
56756
57284
|
return imports;
|
|
56757
57285
|
}
|
|
56758
|
-
var
|
|
57286
|
+
var SKIP_DIRECTORIES3 = new Set([
|
|
56759
57287
|
"node_modules",
|
|
56760
57288
|
".git",
|
|
56761
57289
|
"dist",
|
|
@@ -56772,7 +57300,7 @@ var SKIP_DIRECTORIES2 = new Set([
|
|
|
56772
57300
|
function findSourceFiles(dir, files = [], stats = { skippedDirs: [], skippedFiles: 0, fileErrors: [] }) {
|
|
56773
57301
|
let entries;
|
|
56774
57302
|
try {
|
|
56775
|
-
entries =
|
|
57303
|
+
entries = fs33.readdirSync(dir);
|
|
56776
57304
|
} catch (e) {
|
|
56777
57305
|
stats.fileErrors.push({
|
|
56778
57306
|
path: dir,
|
|
@@ -56782,14 +57310,14 @@ function findSourceFiles(dir, files = [], stats = { skippedDirs: [], skippedFile
|
|
|
56782
57310
|
}
|
|
56783
57311
|
entries.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
|
|
56784
57312
|
for (const entry of entries) {
|
|
56785
|
-
if (
|
|
56786
|
-
stats.skippedDirs.push(
|
|
57313
|
+
if (SKIP_DIRECTORIES3.has(entry)) {
|
|
57314
|
+
stats.skippedDirs.push(path45.join(dir, entry));
|
|
56787
57315
|
continue;
|
|
56788
57316
|
}
|
|
56789
|
-
const fullPath =
|
|
57317
|
+
const fullPath = path45.join(dir, entry);
|
|
56790
57318
|
let stat2;
|
|
56791
57319
|
try {
|
|
56792
|
-
stat2 =
|
|
57320
|
+
stat2 = fs33.statSync(fullPath);
|
|
56793
57321
|
} catch (e) {
|
|
56794
57322
|
stats.fileErrors.push({
|
|
56795
57323
|
path: fullPath,
|
|
@@ -56800,7 +57328,7 @@ function findSourceFiles(dir, files = [], stats = { skippedDirs: [], skippedFile
|
|
|
56800
57328
|
if (stat2.isDirectory()) {
|
|
56801
57329
|
findSourceFiles(fullPath, files, stats);
|
|
56802
57330
|
} else if (stat2.isFile()) {
|
|
56803
|
-
const ext =
|
|
57331
|
+
const ext = path45.extname(fullPath).toLowerCase();
|
|
56804
57332
|
if (SUPPORTED_EXTENSIONS.includes(ext)) {
|
|
56805
57333
|
files.push(fullPath);
|
|
56806
57334
|
}
|
|
@@ -56857,8 +57385,8 @@ var imports = createSwarmTool({
|
|
|
56857
57385
|
return JSON.stringify(errorResult, null, 2);
|
|
56858
57386
|
}
|
|
56859
57387
|
try {
|
|
56860
|
-
const targetFile =
|
|
56861
|
-
if (!
|
|
57388
|
+
const targetFile = path45.resolve(file3);
|
|
57389
|
+
if (!fs33.existsSync(targetFile)) {
|
|
56862
57390
|
const errorResult = {
|
|
56863
57391
|
error: `target file not found: ${file3}`,
|
|
56864
57392
|
target: file3,
|
|
@@ -56868,7 +57396,7 @@ var imports = createSwarmTool({
|
|
|
56868
57396
|
};
|
|
56869
57397
|
return JSON.stringify(errorResult, null, 2);
|
|
56870
57398
|
}
|
|
56871
|
-
const targetStat =
|
|
57399
|
+
const targetStat = fs33.statSync(targetFile);
|
|
56872
57400
|
if (!targetStat.isFile()) {
|
|
56873
57401
|
const errorResult = {
|
|
56874
57402
|
error: "target must be a file, not a directory",
|
|
@@ -56879,7 +57407,7 @@ var imports = createSwarmTool({
|
|
|
56879
57407
|
};
|
|
56880
57408
|
return JSON.stringify(errorResult, null, 2);
|
|
56881
57409
|
}
|
|
56882
|
-
const baseDir =
|
|
57410
|
+
const baseDir = path45.dirname(targetFile);
|
|
56883
57411
|
const scanStats = {
|
|
56884
57412
|
skippedDirs: [],
|
|
56885
57413
|
skippedFiles: 0,
|
|
@@ -56894,12 +57422,12 @@ var imports = createSwarmTool({
|
|
|
56894
57422
|
if (consumers.length >= MAX_CONSUMERS)
|
|
56895
57423
|
break;
|
|
56896
57424
|
try {
|
|
56897
|
-
const stat2 =
|
|
57425
|
+
const stat2 = fs33.statSync(filePath);
|
|
56898
57426
|
if (stat2.size > MAX_FILE_SIZE_BYTES4) {
|
|
56899
57427
|
skippedFileCount++;
|
|
56900
57428
|
continue;
|
|
56901
57429
|
}
|
|
56902
|
-
const buffer =
|
|
57430
|
+
const buffer = fs33.readFileSync(filePath);
|
|
56903
57431
|
if (isBinaryFile2(filePath, buffer)) {
|
|
56904
57432
|
skippedFileCount++;
|
|
56905
57433
|
continue;
|
|
@@ -57448,8 +57976,8 @@ init_dist();
|
|
|
57448
57976
|
init_config();
|
|
57449
57977
|
init_schema();
|
|
57450
57978
|
init_manager();
|
|
57451
|
-
import * as
|
|
57452
|
-
import * as
|
|
57979
|
+
import * as fs34 from "fs";
|
|
57980
|
+
import * as path46 from "path";
|
|
57453
57981
|
init_utils2();
|
|
57454
57982
|
init_create_tool();
|
|
57455
57983
|
function safeWarn(message, error93) {
|
|
@@ -57668,7 +58196,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
57668
58196
|
};
|
|
57669
58197
|
if (retroFound && retroEntry?.lessons_learned && retroEntry.lessons_learned.length > 0) {
|
|
57670
58198
|
try {
|
|
57671
|
-
const projectName =
|
|
58199
|
+
const projectName = path46.basename(dir);
|
|
57672
58200
|
await curateAndStoreSwarm(retroEntry.lessons_learned, projectName, { phase_number: phase }, dir, knowledgeConfig);
|
|
57673
58201
|
} catch (error93) {
|
|
57674
58202
|
safeWarn("[phase_complete] Failed to curate lessons from retrospective:", error93);
|
|
@@ -57708,7 +58236,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
57708
58236
|
if (agentsMissing.length > 0) {
|
|
57709
58237
|
try {
|
|
57710
58238
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
57711
|
-
const planRaw =
|
|
58239
|
+
const planRaw = fs34.readFileSync(planPath, "utf-8");
|
|
57712
58240
|
const plan = JSON.parse(planRaw);
|
|
57713
58241
|
const targetPhase = plan.phases.find((p) => p.id === phase);
|
|
57714
58242
|
if (targetPhase && targetPhase.tasks.length > 0 && targetPhase.tasks.every((t) => t.status === "completed")) {
|
|
@@ -57739,7 +58267,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
57739
58267
|
if (phaseCompleteConfig.regression_sweep?.enforce) {
|
|
57740
58268
|
try {
|
|
57741
58269
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
57742
|
-
const planRaw =
|
|
58270
|
+
const planRaw = fs34.readFileSync(planPath, "utf-8");
|
|
57743
58271
|
const plan = JSON.parse(planRaw);
|
|
57744
58272
|
const targetPhase = plan.phases.find((p) => p.id === phase);
|
|
57745
58273
|
if (targetPhase) {
|
|
@@ -57777,7 +58305,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
57777
58305
|
};
|
|
57778
58306
|
try {
|
|
57779
58307
|
const eventsPath = validateSwarmPath(dir, "events.jsonl");
|
|
57780
|
-
|
|
58308
|
+
fs34.appendFileSync(eventsPath, `${JSON.stringify(event)}
|
|
57781
58309
|
`, "utf-8");
|
|
57782
58310
|
} catch (writeError) {
|
|
57783
58311
|
warnings.push(`Warning: failed to write phase complete event: ${writeError instanceof Error ? writeError.message : String(writeError)}`);
|
|
@@ -57796,12 +58324,12 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
57796
58324
|
}
|
|
57797
58325
|
try {
|
|
57798
58326
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
57799
|
-
const planJson =
|
|
58327
|
+
const planJson = fs34.readFileSync(planPath, "utf-8");
|
|
57800
58328
|
const plan = JSON.parse(planJson);
|
|
57801
58329
|
const phaseObj = plan.phases.find((p) => p.id === phase);
|
|
57802
58330
|
if (phaseObj) {
|
|
57803
58331
|
phaseObj.status = "completed";
|
|
57804
|
-
|
|
58332
|
+
fs34.writeFileSync(planPath, `${JSON.stringify(plan, null, 2)}
|
|
57805
58333
|
`, "utf-8");
|
|
57806
58334
|
}
|
|
57807
58335
|
} catch (error93) {
|
|
@@ -57855,8 +58383,8 @@ init_dist();
|
|
|
57855
58383
|
init_discovery();
|
|
57856
58384
|
init_utils();
|
|
57857
58385
|
init_create_tool();
|
|
57858
|
-
import * as
|
|
57859
|
-
import * as
|
|
58386
|
+
import * as fs35 from "fs";
|
|
58387
|
+
import * as path47 from "path";
|
|
57860
58388
|
var MAX_OUTPUT_BYTES5 = 52428800;
|
|
57861
58389
|
var AUDIT_TIMEOUT_MS = 120000;
|
|
57862
58390
|
function isValidEcosystem(value) {
|
|
@@ -57874,28 +58402,28 @@ function validateArgs3(args2) {
|
|
|
57874
58402
|
function detectEcosystems(directory) {
|
|
57875
58403
|
const ecosystems = [];
|
|
57876
58404
|
const cwd = directory;
|
|
57877
|
-
if (
|
|
58405
|
+
if (fs35.existsSync(path47.join(cwd, "package.json"))) {
|
|
57878
58406
|
ecosystems.push("npm");
|
|
57879
58407
|
}
|
|
57880
|
-
if (
|
|
58408
|
+
if (fs35.existsSync(path47.join(cwd, "pyproject.toml")) || fs35.existsSync(path47.join(cwd, "requirements.txt"))) {
|
|
57881
58409
|
ecosystems.push("pip");
|
|
57882
58410
|
}
|
|
57883
|
-
if (
|
|
58411
|
+
if (fs35.existsSync(path47.join(cwd, "Cargo.toml"))) {
|
|
57884
58412
|
ecosystems.push("cargo");
|
|
57885
58413
|
}
|
|
57886
|
-
if (
|
|
58414
|
+
if (fs35.existsSync(path47.join(cwd, "go.mod"))) {
|
|
57887
58415
|
ecosystems.push("go");
|
|
57888
58416
|
}
|
|
57889
58417
|
try {
|
|
57890
|
-
const files =
|
|
58418
|
+
const files = fs35.readdirSync(cwd);
|
|
57891
58419
|
if (files.some((f) => f.endsWith(".csproj") || f.endsWith(".sln"))) {
|
|
57892
58420
|
ecosystems.push("dotnet");
|
|
57893
58421
|
}
|
|
57894
58422
|
} catch {}
|
|
57895
|
-
if (
|
|
58423
|
+
if (fs35.existsSync(path47.join(cwd, "Gemfile")) || fs35.existsSync(path47.join(cwd, "Gemfile.lock"))) {
|
|
57896
58424
|
ecosystems.push("ruby");
|
|
57897
58425
|
}
|
|
57898
|
-
if (
|
|
58426
|
+
if (fs35.existsSync(path47.join(cwd, "pubspec.yaml"))) {
|
|
57899
58427
|
ecosystems.push("dart");
|
|
57900
58428
|
}
|
|
57901
58429
|
return ecosystems;
|
|
@@ -58957,8 +59485,8 @@ var SUPPORTED_PARSER_EXTENSIONS = new Set([
|
|
|
58957
59485
|
]);
|
|
58958
59486
|
// src/tools/pre-check-batch.ts
|
|
58959
59487
|
init_dist();
|
|
58960
|
-
import * as
|
|
58961
|
-
import * as
|
|
59488
|
+
import * as fs38 from "fs";
|
|
59489
|
+
import * as path50 from "path";
|
|
58962
59490
|
|
|
58963
59491
|
// node_modules/yocto-queue/index.js
|
|
58964
59492
|
class Node2 {
|
|
@@ -59103,8 +59631,8 @@ function pLimit(concurrency) {
|
|
|
59103
59631
|
},
|
|
59104
59632
|
map: {
|
|
59105
59633
|
async value(iterable, function_) {
|
|
59106
|
-
const
|
|
59107
|
-
return Promise.all(
|
|
59634
|
+
const promises4 = Array.from(iterable, (value, index) => this(function_, value, index));
|
|
59635
|
+
return Promise.all(promises4);
|
|
59108
59636
|
}
|
|
59109
59637
|
}
|
|
59110
59638
|
});
|
|
@@ -59117,6 +59645,7 @@ function validateConcurrency(concurrency) {
|
|
|
59117
59645
|
}
|
|
59118
59646
|
|
|
59119
59647
|
// src/tools/pre-check-batch.ts
|
|
59648
|
+
init_manager();
|
|
59120
59649
|
init_utils();
|
|
59121
59650
|
init_create_tool();
|
|
59122
59651
|
init_lint();
|
|
@@ -59125,8 +59654,8 @@ init_lint();
|
|
|
59125
59654
|
init_manager();
|
|
59126
59655
|
|
|
59127
59656
|
// src/quality/metrics.ts
|
|
59128
|
-
import * as
|
|
59129
|
-
import * as
|
|
59657
|
+
import * as fs36 from "fs";
|
|
59658
|
+
import * as path48 from "path";
|
|
59130
59659
|
var MAX_FILE_SIZE_BYTES5 = 256 * 1024;
|
|
59131
59660
|
var MIN_DUPLICATION_LINES = 10;
|
|
59132
59661
|
function estimateCyclomaticComplexity(content) {
|
|
@@ -59164,11 +59693,11 @@ function estimateCyclomaticComplexity(content) {
|
|
|
59164
59693
|
}
|
|
59165
59694
|
function getComplexityForFile2(filePath) {
|
|
59166
59695
|
try {
|
|
59167
|
-
const stat2 =
|
|
59696
|
+
const stat2 = fs36.statSync(filePath);
|
|
59168
59697
|
if (stat2.size > MAX_FILE_SIZE_BYTES5) {
|
|
59169
59698
|
return null;
|
|
59170
59699
|
}
|
|
59171
|
-
const content =
|
|
59700
|
+
const content = fs36.readFileSync(filePath, "utf-8");
|
|
59172
59701
|
return estimateCyclomaticComplexity(content);
|
|
59173
59702
|
} catch {
|
|
59174
59703
|
return null;
|
|
@@ -59178,8 +59707,8 @@ async function computeComplexityDelta(files, workingDir) {
|
|
|
59178
59707
|
let totalComplexity = 0;
|
|
59179
59708
|
const analyzedFiles = [];
|
|
59180
59709
|
for (const file3 of files) {
|
|
59181
|
-
const fullPath =
|
|
59182
|
-
if (!
|
|
59710
|
+
const fullPath = path48.isAbsolute(file3) ? file3 : path48.join(workingDir, file3);
|
|
59711
|
+
if (!fs36.existsSync(fullPath)) {
|
|
59183
59712
|
continue;
|
|
59184
59713
|
}
|
|
59185
59714
|
const complexity = getComplexityForFile2(fullPath);
|
|
@@ -59300,8 +59829,8 @@ function countGoExports(content) {
|
|
|
59300
59829
|
}
|
|
59301
59830
|
function getExportCountForFile(filePath) {
|
|
59302
59831
|
try {
|
|
59303
|
-
const content =
|
|
59304
|
-
const ext =
|
|
59832
|
+
const content = fs36.readFileSync(filePath, "utf-8");
|
|
59833
|
+
const ext = path48.extname(filePath).toLowerCase();
|
|
59305
59834
|
switch (ext) {
|
|
59306
59835
|
case ".ts":
|
|
59307
59836
|
case ".tsx":
|
|
@@ -59327,8 +59856,8 @@ async function computePublicApiDelta(files, workingDir) {
|
|
|
59327
59856
|
let totalExports = 0;
|
|
59328
59857
|
const analyzedFiles = [];
|
|
59329
59858
|
for (const file3 of files) {
|
|
59330
|
-
const fullPath =
|
|
59331
|
-
if (!
|
|
59859
|
+
const fullPath = path48.isAbsolute(file3) ? file3 : path48.join(workingDir, file3);
|
|
59860
|
+
if (!fs36.existsSync(fullPath)) {
|
|
59332
59861
|
continue;
|
|
59333
59862
|
}
|
|
59334
59863
|
const exports = getExportCountForFile(fullPath);
|
|
@@ -59361,16 +59890,16 @@ async function computeDuplicationRatio(files, workingDir) {
|
|
|
59361
59890
|
let duplicateLines = 0;
|
|
59362
59891
|
const analyzedFiles = [];
|
|
59363
59892
|
for (const file3 of files) {
|
|
59364
|
-
const fullPath =
|
|
59365
|
-
if (!
|
|
59893
|
+
const fullPath = path48.isAbsolute(file3) ? file3 : path48.join(workingDir, file3);
|
|
59894
|
+
if (!fs36.existsSync(fullPath)) {
|
|
59366
59895
|
continue;
|
|
59367
59896
|
}
|
|
59368
59897
|
try {
|
|
59369
|
-
const stat2 =
|
|
59898
|
+
const stat2 = fs36.statSync(fullPath);
|
|
59370
59899
|
if (stat2.size > MAX_FILE_SIZE_BYTES5) {
|
|
59371
59900
|
continue;
|
|
59372
59901
|
}
|
|
59373
|
-
const content =
|
|
59902
|
+
const content = fs36.readFileSync(fullPath, "utf-8");
|
|
59374
59903
|
const lines = content.split(`
|
|
59375
59904
|
`).filter((line) => line.trim().length > 0);
|
|
59376
59905
|
if (lines.length < MIN_DUPLICATION_LINES) {
|
|
@@ -59394,8 +59923,8 @@ function countCodeLines(content) {
|
|
|
59394
59923
|
return lines.length;
|
|
59395
59924
|
}
|
|
59396
59925
|
function isTestFile(filePath) {
|
|
59397
|
-
const
|
|
59398
|
-
const _ext =
|
|
59926
|
+
const basename9 = path48.basename(filePath);
|
|
59927
|
+
const _ext = path48.extname(filePath).toLowerCase();
|
|
59399
59928
|
const testPatterns = [
|
|
59400
59929
|
".test.",
|
|
59401
59930
|
".spec.",
|
|
@@ -59410,7 +59939,7 @@ function isTestFile(filePath) {
|
|
|
59410
59939
|
".spec.jsx"
|
|
59411
59940
|
];
|
|
59412
59941
|
for (const pattern of testPatterns) {
|
|
59413
|
-
if (
|
|
59942
|
+
if (basename9.includes(pattern)) {
|
|
59414
59943
|
return true;
|
|
59415
59944
|
}
|
|
59416
59945
|
}
|
|
@@ -59476,8 +60005,8 @@ function matchGlobSegment(globSegments, pathSegments) {
|
|
|
59476
60005
|
}
|
|
59477
60006
|
return gIndex === globSegments.length && pIndex === pathSegments.length;
|
|
59478
60007
|
}
|
|
59479
|
-
function matchesGlobSegment(
|
|
59480
|
-
const normalizedPath =
|
|
60008
|
+
function matchesGlobSegment(path49, glob) {
|
|
60009
|
+
const normalizedPath = path49.replace(/\\/g, "/");
|
|
59481
60010
|
const normalizedGlob = glob.replace(/\\/g, "/");
|
|
59482
60011
|
if (normalizedPath.includes("//")) {
|
|
59483
60012
|
return false;
|
|
@@ -59508,8 +60037,8 @@ function simpleGlobToRegex2(glob) {
|
|
|
59508
60037
|
function hasGlobstar(glob) {
|
|
59509
60038
|
return glob.includes("**");
|
|
59510
60039
|
}
|
|
59511
|
-
function globMatches(
|
|
59512
|
-
const normalizedPath =
|
|
60040
|
+
function globMatches(path49, glob) {
|
|
60041
|
+
const normalizedPath = path49.replace(/\\/g, "/");
|
|
59513
60042
|
if (!glob || glob === "") {
|
|
59514
60043
|
if (normalizedPath.includes("//")) {
|
|
59515
60044
|
return false;
|
|
@@ -59545,31 +60074,31 @@ function shouldExcludeFile(filePath, excludeGlobs) {
|
|
|
59545
60074
|
async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
|
|
59546
60075
|
let testLines = 0;
|
|
59547
60076
|
let codeLines = 0;
|
|
59548
|
-
const srcDir =
|
|
59549
|
-
if (
|
|
60077
|
+
const srcDir = path48.join(workingDir, "src");
|
|
60078
|
+
if (fs36.existsSync(srcDir)) {
|
|
59550
60079
|
await scanDirectoryForLines(srcDir, enforceGlobs, excludeGlobs, false, (lines) => {
|
|
59551
60080
|
codeLines += lines;
|
|
59552
60081
|
});
|
|
59553
60082
|
}
|
|
59554
60083
|
const possibleSrcDirs = ["lib", "app", "source", "core"];
|
|
59555
60084
|
for (const dir of possibleSrcDirs) {
|
|
59556
|
-
const dirPath =
|
|
59557
|
-
if (
|
|
60085
|
+
const dirPath = path48.join(workingDir, dir);
|
|
60086
|
+
if (fs36.existsSync(dirPath)) {
|
|
59558
60087
|
await scanDirectoryForLines(dirPath, enforceGlobs, excludeGlobs, false, (lines) => {
|
|
59559
60088
|
codeLines += lines;
|
|
59560
60089
|
});
|
|
59561
60090
|
}
|
|
59562
60091
|
}
|
|
59563
|
-
const testsDir =
|
|
59564
|
-
if (
|
|
60092
|
+
const testsDir = path48.join(workingDir, "tests");
|
|
60093
|
+
if (fs36.existsSync(testsDir)) {
|
|
59565
60094
|
await scanDirectoryForLines(testsDir, ["**"], ["node_modules", "dist"], true, (lines) => {
|
|
59566
60095
|
testLines += lines;
|
|
59567
60096
|
});
|
|
59568
60097
|
}
|
|
59569
60098
|
const possibleTestDirs = ["test", "__tests__", "specs"];
|
|
59570
60099
|
for (const dir of possibleTestDirs) {
|
|
59571
|
-
const dirPath =
|
|
59572
|
-
if (
|
|
60100
|
+
const dirPath = path48.join(workingDir, dir);
|
|
60101
|
+
if (fs36.existsSync(dirPath) && dirPath !== testsDir) {
|
|
59573
60102
|
await scanDirectoryForLines(dirPath, ["**"], ["node_modules", "dist"], true, (lines) => {
|
|
59574
60103
|
testLines += lines;
|
|
59575
60104
|
});
|
|
@@ -59581,9 +60110,9 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
|
|
|
59581
60110
|
}
|
|
59582
60111
|
async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTestScan, callback) {
|
|
59583
60112
|
try {
|
|
59584
|
-
const entries =
|
|
60113
|
+
const entries = fs36.readdirSync(dirPath, { withFileTypes: true });
|
|
59585
60114
|
for (const entry of entries) {
|
|
59586
|
-
const fullPath =
|
|
60115
|
+
const fullPath = path48.join(dirPath, entry.name);
|
|
59587
60116
|
if (entry.isDirectory()) {
|
|
59588
60117
|
if (entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === ".git") {
|
|
59589
60118
|
continue;
|
|
@@ -59591,7 +60120,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
|
|
|
59591
60120
|
await scanDirectoryForLines(fullPath, includeGlobs, excludeGlobs, isTestScan, callback);
|
|
59592
60121
|
} else if (entry.isFile()) {
|
|
59593
60122
|
const relativePath = fullPath.replace(`${dirPath}/`, "");
|
|
59594
|
-
const ext =
|
|
60123
|
+
const ext = path48.extname(entry.name).toLowerCase();
|
|
59595
60124
|
const validExts = [
|
|
59596
60125
|
".ts",
|
|
59597
60126
|
".tsx",
|
|
@@ -59627,7 +60156,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
|
|
|
59627
60156
|
continue;
|
|
59628
60157
|
}
|
|
59629
60158
|
try {
|
|
59630
|
-
const content =
|
|
60159
|
+
const content = fs36.readFileSync(fullPath, "utf-8");
|
|
59631
60160
|
const lines = countCodeLines(content);
|
|
59632
60161
|
callback(lines);
|
|
59633
60162
|
} catch {}
|
|
@@ -59841,8 +60370,8 @@ async function qualityBudget(input, directory) {
|
|
|
59841
60370
|
init_dist();
|
|
59842
60371
|
init_manager();
|
|
59843
60372
|
init_detector();
|
|
59844
|
-
import * as
|
|
59845
|
-
import * as
|
|
60373
|
+
import * as fs37 from "fs";
|
|
60374
|
+
import * as path49 from "path";
|
|
59846
60375
|
import { extname as extname9 } from "path";
|
|
59847
60376
|
|
|
59848
60377
|
// src/sast/rules/c.ts
|
|
@@ -60709,17 +61238,17 @@ var SEVERITY_ORDER = {
|
|
|
60709
61238
|
};
|
|
60710
61239
|
function shouldSkipFile(filePath) {
|
|
60711
61240
|
try {
|
|
60712
|
-
const stats =
|
|
61241
|
+
const stats = fs37.statSync(filePath);
|
|
60713
61242
|
if (stats.size > MAX_FILE_SIZE_BYTES6) {
|
|
60714
61243
|
return { skip: true, reason: "file too large" };
|
|
60715
61244
|
}
|
|
60716
61245
|
if (stats.size === 0) {
|
|
60717
61246
|
return { skip: true, reason: "empty file" };
|
|
60718
61247
|
}
|
|
60719
|
-
const fd =
|
|
61248
|
+
const fd = fs37.openSync(filePath, "r");
|
|
60720
61249
|
const buffer = Buffer.alloc(8192);
|
|
60721
|
-
const bytesRead =
|
|
60722
|
-
|
|
61250
|
+
const bytesRead = fs37.readSync(fd, buffer, 0, 8192, 0);
|
|
61251
|
+
fs37.closeSync(fd);
|
|
60723
61252
|
if (bytesRead > 0) {
|
|
60724
61253
|
let nullCount = 0;
|
|
60725
61254
|
for (let i2 = 0;i2 < bytesRead; i2++) {
|
|
@@ -60758,7 +61287,7 @@ function countBySeverity(findings) {
|
|
|
60758
61287
|
}
|
|
60759
61288
|
function scanFileWithTierA(filePath, language) {
|
|
60760
61289
|
try {
|
|
60761
|
-
const content =
|
|
61290
|
+
const content = fs37.readFileSync(filePath, "utf-8");
|
|
60762
61291
|
const findings = executeRulesSync(filePath, content, language);
|
|
60763
61292
|
return findings.map((f) => ({
|
|
60764
61293
|
rule_id: f.rule_id,
|
|
@@ -60805,8 +61334,8 @@ async function sastScan(input, directory, config3) {
|
|
|
60805
61334
|
_filesSkipped++;
|
|
60806
61335
|
continue;
|
|
60807
61336
|
}
|
|
60808
|
-
const resolvedPath =
|
|
60809
|
-
if (!
|
|
61337
|
+
const resolvedPath = path49.isAbsolute(filePath) ? filePath : path49.resolve(directory, filePath);
|
|
61338
|
+
if (!fs37.existsSync(resolvedPath)) {
|
|
60810
61339
|
_filesSkipped++;
|
|
60811
61340
|
continue;
|
|
60812
61341
|
}
|
|
@@ -61004,18 +61533,18 @@ function validatePath(inputPath, baseDir, workspaceDir) {
|
|
|
61004
61533
|
let resolved;
|
|
61005
61534
|
const isWinAbs = isWindowsAbsolutePath(inputPath);
|
|
61006
61535
|
if (isWinAbs) {
|
|
61007
|
-
resolved =
|
|
61008
|
-
} else if (
|
|
61009
|
-
resolved =
|
|
61536
|
+
resolved = path50.win32.resolve(inputPath);
|
|
61537
|
+
} else if (path50.isAbsolute(inputPath)) {
|
|
61538
|
+
resolved = path50.resolve(inputPath);
|
|
61010
61539
|
} else {
|
|
61011
|
-
resolved =
|
|
61540
|
+
resolved = path50.resolve(baseDir, inputPath);
|
|
61012
61541
|
}
|
|
61013
|
-
const workspaceResolved =
|
|
61542
|
+
const workspaceResolved = path50.resolve(workspaceDir);
|
|
61014
61543
|
let relative6;
|
|
61015
61544
|
if (isWinAbs) {
|
|
61016
|
-
relative6 =
|
|
61545
|
+
relative6 = path50.win32.relative(workspaceResolved, resolved);
|
|
61017
61546
|
} else {
|
|
61018
|
-
relative6 =
|
|
61547
|
+
relative6 = path50.relative(workspaceResolved, resolved);
|
|
61019
61548
|
}
|
|
61020
61549
|
if (relative6.startsWith("..")) {
|
|
61021
61550
|
return "path traversal detected";
|
|
@@ -61076,13 +61605,13 @@ async function runLintWrapped(files, directory, _config) {
|
|
|
61076
61605
|
}
|
|
61077
61606
|
async function runLintOnFiles(linter, files, workspaceDir) {
|
|
61078
61607
|
const isWindows = process.platform === "win32";
|
|
61079
|
-
const binDir =
|
|
61608
|
+
const binDir = path50.join(workspaceDir, "node_modules", ".bin");
|
|
61080
61609
|
const validatedFiles = [];
|
|
61081
61610
|
for (const file3 of files) {
|
|
61082
61611
|
if (typeof file3 !== "string") {
|
|
61083
61612
|
continue;
|
|
61084
61613
|
}
|
|
61085
|
-
const resolvedPath =
|
|
61614
|
+
const resolvedPath = path50.resolve(file3);
|
|
61086
61615
|
const validationError = validatePath(resolvedPath, workspaceDir, workspaceDir);
|
|
61087
61616
|
if (validationError) {
|
|
61088
61617
|
continue;
|
|
@@ -61100,10 +61629,10 @@ async function runLintOnFiles(linter, files, workspaceDir) {
|
|
|
61100
61629
|
}
|
|
61101
61630
|
let command;
|
|
61102
61631
|
if (linter === "biome") {
|
|
61103
|
-
const biomeBin = isWindows ?
|
|
61632
|
+
const biomeBin = isWindows ? path50.join(binDir, "biome.EXE") : path50.join(binDir, "biome");
|
|
61104
61633
|
command = [biomeBin, "check", ...validatedFiles];
|
|
61105
61634
|
} else {
|
|
61106
|
-
const eslintBin = isWindows ?
|
|
61635
|
+
const eslintBin = isWindows ? path50.join(binDir, "eslint.cmd") : path50.join(binDir, "eslint");
|
|
61107
61636
|
command = [eslintBin, ...validatedFiles];
|
|
61108
61637
|
}
|
|
61109
61638
|
try {
|
|
@@ -61240,7 +61769,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
61240
61769
|
skippedFiles++;
|
|
61241
61770
|
continue;
|
|
61242
61771
|
}
|
|
61243
|
-
const resolvedPath =
|
|
61772
|
+
const resolvedPath = path50.resolve(file3);
|
|
61244
61773
|
const validationError = validatePath(resolvedPath, directory, directory);
|
|
61245
61774
|
if (validationError) {
|
|
61246
61775
|
skippedFiles++;
|
|
@@ -61258,14 +61787,14 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
61258
61787
|
};
|
|
61259
61788
|
}
|
|
61260
61789
|
for (const file3 of validatedFiles) {
|
|
61261
|
-
const ext =
|
|
61790
|
+
const ext = path50.extname(file3).toLowerCase();
|
|
61262
61791
|
if (DEFAULT_EXCLUDE_EXTENSIONS2.has(ext)) {
|
|
61263
61792
|
skippedFiles++;
|
|
61264
61793
|
continue;
|
|
61265
61794
|
}
|
|
61266
61795
|
let stat2;
|
|
61267
61796
|
try {
|
|
61268
|
-
stat2 =
|
|
61797
|
+
stat2 = fs38.statSync(file3);
|
|
61269
61798
|
} catch {
|
|
61270
61799
|
skippedFiles++;
|
|
61271
61800
|
continue;
|
|
@@ -61276,7 +61805,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
61276
61805
|
}
|
|
61277
61806
|
let content;
|
|
61278
61807
|
try {
|
|
61279
|
-
const buffer =
|
|
61808
|
+
const buffer = fs38.readFileSync(file3);
|
|
61280
61809
|
if (buffer.includes(0)) {
|
|
61281
61810
|
skippedFiles++;
|
|
61282
61811
|
continue;
|
|
@@ -61417,7 +61946,7 @@ async function runPreCheckBatch(input, workspaceDir, contextDir) {
|
|
|
61417
61946
|
warn(`pre_check_batch: Invalid file path: ${file3}`);
|
|
61418
61947
|
continue;
|
|
61419
61948
|
}
|
|
61420
|
-
changedFiles.push(
|
|
61949
|
+
changedFiles.push(path50.resolve(directory, file3));
|
|
61421
61950
|
}
|
|
61422
61951
|
if (changedFiles.length === 0) {
|
|
61423
61952
|
warn("pre_check_batch: No valid files after validation, skipping all tools (fail-closed)");
|
|
@@ -61464,6 +61993,26 @@ async function runPreCheckBatch(input, workspaceDir, contextDir) {
|
|
|
61464
61993
|
gatesPassed = false;
|
|
61465
61994
|
warn(`pre_check_batch: Secretscan error - GATE FAILED: ${secretscanResult.error}`);
|
|
61466
61995
|
}
|
|
61996
|
+
if (secretscanResult.ran && secretscanResult.result) {
|
|
61997
|
+
try {
|
|
61998
|
+
const scanResult = secretscanResult.result;
|
|
61999
|
+
const secretscanEvidence = {
|
|
62000
|
+
task_id: "secretscan",
|
|
62001
|
+
type: "secretscan",
|
|
62002
|
+
timestamp: new Date().toISOString(),
|
|
62003
|
+
agent: "pre_check_batch",
|
|
62004
|
+
verdict: scanResult.count > 0 ? "fail" : "pass",
|
|
62005
|
+
summary: `Secretscan: ${scanResult.count} finding(s), ${scanResult.files_scanned ?? 0} files scanned, ${scanResult.skipped_files ?? 0} skipped`,
|
|
62006
|
+
findings_count: scanResult.count,
|
|
62007
|
+
scan_directory: scanResult.scan_dir,
|
|
62008
|
+
files_scanned: scanResult.files_scanned,
|
|
62009
|
+
skipped_files: scanResult.skipped_files
|
|
62010
|
+
};
|
|
62011
|
+
await saveEvidence(directory, "secretscan", secretscanEvidence);
|
|
62012
|
+
} catch (e) {
|
|
62013
|
+
warn(`Failed to persist secretscan evidence: ${e instanceof Error ? e.message : String(e)}`);
|
|
62014
|
+
}
|
|
62015
|
+
}
|
|
61467
62016
|
if (sastScanResult.ran && sastScanResult.result) {
|
|
61468
62017
|
if (sastScanResult.result.verdict === "fail") {
|
|
61469
62018
|
gatesPassed = false;
|
|
@@ -61568,7 +62117,7 @@ var pre_check_batch = createSwarmTool({
|
|
|
61568
62117
|
};
|
|
61569
62118
|
return JSON.stringify(errorResult, null, 2);
|
|
61570
62119
|
}
|
|
61571
|
-
const resolvedDirectory =
|
|
62120
|
+
const resolvedDirectory = path50.resolve(typedArgs.directory);
|
|
61572
62121
|
const workspaceAnchor = resolvedDirectory;
|
|
61573
62122
|
const dirError = validateDirectory3(resolvedDirectory, workspaceAnchor);
|
|
61574
62123
|
if (dirError) {
|
|
@@ -61676,8 +62225,8 @@ ${paginatedContent}`;
|
|
|
61676
62225
|
init_tool();
|
|
61677
62226
|
init_manager2();
|
|
61678
62227
|
init_create_tool();
|
|
61679
|
-
import * as
|
|
61680
|
-
import * as
|
|
62228
|
+
import * as fs39 from "fs";
|
|
62229
|
+
import * as path51 from "path";
|
|
61681
62230
|
function detectPlaceholderContent(args2) {
|
|
61682
62231
|
const issues = [];
|
|
61683
62232
|
const placeholderPattern = /^\[\w[\w\s]*\]$/;
|
|
@@ -61781,19 +62330,19 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
61781
62330
|
try {
|
|
61782
62331
|
await savePlan(dir, plan);
|
|
61783
62332
|
try {
|
|
61784
|
-
const markerPath =
|
|
62333
|
+
const markerPath = path51.join(dir, ".swarm", ".plan-write-marker");
|
|
61785
62334
|
const marker = JSON.stringify({
|
|
61786
62335
|
source: "save_plan",
|
|
61787
62336
|
timestamp: new Date().toISOString(),
|
|
61788
62337
|
phases_count: plan.phases.length,
|
|
61789
62338
|
tasks_count: tasksCount
|
|
61790
62339
|
});
|
|
61791
|
-
await
|
|
62340
|
+
await fs39.promises.writeFile(markerPath, marker, "utf8");
|
|
61792
62341
|
} catch {}
|
|
61793
62342
|
return {
|
|
61794
62343
|
success: true,
|
|
61795
62344
|
message: "Plan saved successfully",
|
|
61796
|
-
plan_path:
|
|
62345
|
+
plan_path: path51.join(dir, ".swarm", "plan.json"),
|
|
61797
62346
|
phases_count: plan.phases.length,
|
|
61798
62347
|
tasks_count: tasksCount
|
|
61799
62348
|
};
|
|
@@ -61831,8 +62380,8 @@ var save_plan = createSwarmTool({
|
|
|
61831
62380
|
// src/tools/sbom-generate.ts
|
|
61832
62381
|
init_dist();
|
|
61833
62382
|
init_manager();
|
|
61834
|
-
import * as
|
|
61835
|
-
import * as
|
|
62383
|
+
import * as fs40 from "fs";
|
|
62384
|
+
import * as path52 from "path";
|
|
61836
62385
|
|
|
61837
62386
|
// src/sbom/detectors/index.ts
|
|
61838
62387
|
init_utils();
|
|
@@ -62678,9 +63227,9 @@ function findManifestFiles(rootDir) {
|
|
|
62678
63227
|
const patterns = [...new Set(allDetectors.flatMap((d) => d.patterns))];
|
|
62679
63228
|
function searchDir(dir) {
|
|
62680
63229
|
try {
|
|
62681
|
-
const entries =
|
|
63230
|
+
const entries = fs40.readdirSync(dir, { withFileTypes: true });
|
|
62682
63231
|
for (const entry of entries) {
|
|
62683
|
-
const fullPath =
|
|
63232
|
+
const fullPath = path52.join(dir, entry.name);
|
|
62684
63233
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "target") {
|
|
62685
63234
|
continue;
|
|
62686
63235
|
}
|
|
@@ -62689,7 +63238,7 @@ function findManifestFiles(rootDir) {
|
|
|
62689
63238
|
} else if (entry.isFile()) {
|
|
62690
63239
|
for (const pattern of patterns) {
|
|
62691
63240
|
if (simpleGlobToRegex(pattern).test(entry.name)) {
|
|
62692
|
-
manifestFiles.push(
|
|
63241
|
+
manifestFiles.push(path52.relative(rootDir, fullPath));
|
|
62693
63242
|
break;
|
|
62694
63243
|
}
|
|
62695
63244
|
}
|
|
@@ -62705,13 +63254,13 @@ function findManifestFilesInDirs(directories, workingDir) {
|
|
|
62705
63254
|
const patterns = [...new Set(allDetectors.flatMap((d) => d.patterns))];
|
|
62706
63255
|
for (const dir of directories) {
|
|
62707
63256
|
try {
|
|
62708
|
-
const entries =
|
|
63257
|
+
const entries = fs40.readdirSync(dir, { withFileTypes: true });
|
|
62709
63258
|
for (const entry of entries) {
|
|
62710
|
-
const fullPath =
|
|
63259
|
+
const fullPath = path52.join(dir, entry.name);
|
|
62711
63260
|
if (entry.isFile()) {
|
|
62712
63261
|
for (const pattern of patterns) {
|
|
62713
63262
|
if (simpleGlobToRegex(pattern).test(entry.name)) {
|
|
62714
|
-
found.push(
|
|
63263
|
+
found.push(path52.relative(workingDir, fullPath));
|
|
62715
63264
|
break;
|
|
62716
63265
|
}
|
|
62717
63266
|
}
|
|
@@ -62724,11 +63273,11 @@ function findManifestFilesInDirs(directories, workingDir) {
|
|
|
62724
63273
|
function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
|
|
62725
63274
|
const dirs = new Set;
|
|
62726
63275
|
for (const file3 of changedFiles) {
|
|
62727
|
-
let currentDir =
|
|
63276
|
+
let currentDir = path52.dirname(file3);
|
|
62728
63277
|
while (true) {
|
|
62729
|
-
if (currentDir && currentDir !== "." && currentDir !==
|
|
62730
|
-
dirs.add(
|
|
62731
|
-
const parent =
|
|
63278
|
+
if (currentDir && currentDir !== "." && currentDir !== path52.sep) {
|
|
63279
|
+
dirs.add(path52.join(workingDir, currentDir));
|
|
63280
|
+
const parent = path52.dirname(currentDir);
|
|
62732
63281
|
if (parent === currentDir)
|
|
62733
63282
|
break;
|
|
62734
63283
|
currentDir = parent;
|
|
@@ -62742,7 +63291,7 @@ function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
|
|
|
62742
63291
|
}
|
|
62743
63292
|
function ensureOutputDir(outputDir) {
|
|
62744
63293
|
try {
|
|
62745
|
-
|
|
63294
|
+
fs40.mkdirSync(outputDir, { recursive: true });
|
|
62746
63295
|
} catch (error93) {
|
|
62747
63296
|
if (!error93 || error93.code !== "EEXIST") {
|
|
62748
63297
|
throw error93;
|
|
@@ -62812,7 +63361,7 @@ var sbom_generate = createSwarmTool({
|
|
|
62812
63361
|
const changedFiles = obj.changed_files;
|
|
62813
63362
|
const relativeOutputDir = obj.output_dir || DEFAULT_OUTPUT_DIR;
|
|
62814
63363
|
const workingDir = directory;
|
|
62815
|
-
const outputDir =
|
|
63364
|
+
const outputDir = path52.isAbsolute(relativeOutputDir) ? relativeOutputDir : path52.join(workingDir, relativeOutputDir);
|
|
62816
63365
|
let manifestFiles = [];
|
|
62817
63366
|
if (scope === "all") {
|
|
62818
63367
|
manifestFiles = findManifestFiles(workingDir);
|
|
@@ -62835,11 +63384,11 @@ var sbom_generate = createSwarmTool({
|
|
|
62835
63384
|
const processedFiles = [];
|
|
62836
63385
|
for (const manifestFile of manifestFiles) {
|
|
62837
63386
|
try {
|
|
62838
|
-
const fullPath =
|
|
62839
|
-
if (!
|
|
63387
|
+
const fullPath = path52.isAbsolute(manifestFile) ? manifestFile : path52.join(workingDir, manifestFile);
|
|
63388
|
+
if (!fs40.existsSync(fullPath)) {
|
|
62840
63389
|
continue;
|
|
62841
63390
|
}
|
|
62842
|
-
const content =
|
|
63391
|
+
const content = fs40.readFileSync(fullPath, "utf-8");
|
|
62843
63392
|
const components = detectComponents(manifestFile, content);
|
|
62844
63393
|
processedFiles.push(manifestFile);
|
|
62845
63394
|
if (components.length > 0) {
|
|
@@ -62852,8 +63401,8 @@ var sbom_generate = createSwarmTool({
|
|
|
62852
63401
|
const bom = generateCycloneDX(allComponents);
|
|
62853
63402
|
const bomJson = serializeCycloneDX(bom);
|
|
62854
63403
|
const filename = generateSbomFilename();
|
|
62855
|
-
const outputPath =
|
|
62856
|
-
|
|
63404
|
+
const outputPath = path52.join(outputDir, filename);
|
|
63405
|
+
fs40.writeFileSync(outputPath, bomJson, "utf-8");
|
|
62857
63406
|
const verdict = processedFiles.length > 0 ? "pass" : "pass";
|
|
62858
63407
|
try {
|
|
62859
63408
|
const timestamp = new Date().toISOString();
|
|
@@ -62895,8 +63444,8 @@ var sbom_generate = createSwarmTool({
|
|
|
62895
63444
|
// src/tools/schema-drift.ts
|
|
62896
63445
|
init_dist();
|
|
62897
63446
|
init_create_tool();
|
|
62898
|
-
import * as
|
|
62899
|
-
import * as
|
|
63447
|
+
import * as fs41 from "fs";
|
|
63448
|
+
import * as path53 from "path";
|
|
62900
63449
|
var SPEC_CANDIDATES = [
|
|
62901
63450
|
"openapi.json",
|
|
62902
63451
|
"openapi.yaml",
|
|
@@ -62928,28 +63477,28 @@ function normalizePath2(p) {
|
|
|
62928
63477
|
}
|
|
62929
63478
|
function discoverSpecFile(cwd, specFileArg) {
|
|
62930
63479
|
if (specFileArg) {
|
|
62931
|
-
const resolvedPath =
|
|
62932
|
-
const normalizedCwd = cwd.endsWith(
|
|
63480
|
+
const resolvedPath = path53.resolve(cwd, specFileArg);
|
|
63481
|
+
const normalizedCwd = cwd.endsWith(path53.sep) ? cwd : cwd + path53.sep;
|
|
62933
63482
|
if (!resolvedPath.startsWith(normalizedCwd) && resolvedPath !== cwd) {
|
|
62934
63483
|
throw new Error("Invalid spec_file: path traversal detected");
|
|
62935
63484
|
}
|
|
62936
|
-
const ext =
|
|
63485
|
+
const ext = path53.extname(resolvedPath).toLowerCase();
|
|
62937
63486
|
if (!ALLOWED_EXTENSIONS.includes(ext)) {
|
|
62938
63487
|
throw new Error(`Invalid spec_file: must end in .json, .yaml, or .yml, got ${ext}`);
|
|
62939
63488
|
}
|
|
62940
|
-
const stats =
|
|
63489
|
+
const stats = fs41.statSync(resolvedPath);
|
|
62941
63490
|
if (stats.size > MAX_SPEC_SIZE) {
|
|
62942
63491
|
throw new Error(`Invalid spec_file: file exceeds ${MAX_SPEC_SIZE / 1024 / 1024}MB limit`);
|
|
62943
63492
|
}
|
|
62944
|
-
if (!
|
|
63493
|
+
if (!fs41.existsSync(resolvedPath)) {
|
|
62945
63494
|
throw new Error(`Spec file not found: ${resolvedPath}`);
|
|
62946
63495
|
}
|
|
62947
63496
|
return resolvedPath;
|
|
62948
63497
|
}
|
|
62949
63498
|
for (const candidate of SPEC_CANDIDATES) {
|
|
62950
|
-
const candidatePath =
|
|
62951
|
-
if (
|
|
62952
|
-
const stats =
|
|
63499
|
+
const candidatePath = path53.resolve(cwd, candidate);
|
|
63500
|
+
if (fs41.existsSync(candidatePath)) {
|
|
63501
|
+
const stats = fs41.statSync(candidatePath);
|
|
62953
63502
|
if (stats.size <= MAX_SPEC_SIZE) {
|
|
62954
63503
|
return candidatePath;
|
|
62955
63504
|
}
|
|
@@ -62958,8 +63507,8 @@ function discoverSpecFile(cwd, specFileArg) {
|
|
|
62958
63507
|
return null;
|
|
62959
63508
|
}
|
|
62960
63509
|
function parseSpec(specFile) {
|
|
62961
|
-
const content =
|
|
62962
|
-
const ext =
|
|
63510
|
+
const content = fs41.readFileSync(specFile, "utf-8");
|
|
63511
|
+
const ext = path53.extname(specFile).toLowerCase();
|
|
62963
63512
|
if (ext === ".json") {
|
|
62964
63513
|
return parseJsonSpec(content);
|
|
62965
63514
|
}
|
|
@@ -63030,12 +63579,12 @@ function extractRoutes(cwd) {
|
|
|
63030
63579
|
function walkDir(dir) {
|
|
63031
63580
|
let entries;
|
|
63032
63581
|
try {
|
|
63033
|
-
entries =
|
|
63582
|
+
entries = fs41.readdirSync(dir, { withFileTypes: true });
|
|
63034
63583
|
} catch {
|
|
63035
63584
|
return;
|
|
63036
63585
|
}
|
|
63037
63586
|
for (const entry of entries) {
|
|
63038
|
-
const fullPath =
|
|
63587
|
+
const fullPath = path53.join(dir, entry.name);
|
|
63039
63588
|
if (entry.isSymbolicLink()) {
|
|
63040
63589
|
continue;
|
|
63041
63590
|
}
|
|
@@ -63045,7 +63594,7 @@ function extractRoutes(cwd) {
|
|
|
63045
63594
|
}
|
|
63046
63595
|
walkDir(fullPath);
|
|
63047
63596
|
} else if (entry.isFile()) {
|
|
63048
|
-
const ext =
|
|
63597
|
+
const ext = path53.extname(entry.name).toLowerCase();
|
|
63049
63598
|
const baseName = entry.name.toLowerCase();
|
|
63050
63599
|
if (![".ts", ".js", ".mjs"].includes(ext)) {
|
|
63051
63600
|
continue;
|
|
@@ -63063,7 +63612,7 @@ function extractRoutes(cwd) {
|
|
|
63063
63612
|
}
|
|
63064
63613
|
function extractRoutesFromFile(filePath) {
|
|
63065
63614
|
const routes = [];
|
|
63066
|
-
const content =
|
|
63615
|
+
const content = fs41.readFileSync(filePath, "utf-8");
|
|
63067
63616
|
const lines = content.split(/\r?\n/);
|
|
63068
63617
|
const expressRegex = /(?:app|router|server|express)\.(get|post|put|patch|delete|options|head)\s*\(\s*['"`]([^'"`]+)['"`]/g;
|
|
63069
63618
|
const flaskRegex = /@(?:app|blueprint|bp)\.route\s*\(\s*['"]([^'"]+)['"]/g;
|
|
@@ -63214,8 +63763,8 @@ init_secretscan();
|
|
|
63214
63763
|
// src/tools/symbols.ts
|
|
63215
63764
|
init_tool();
|
|
63216
63765
|
init_create_tool();
|
|
63217
|
-
import * as
|
|
63218
|
-
import * as
|
|
63766
|
+
import * as fs42 from "fs";
|
|
63767
|
+
import * as path54 from "path";
|
|
63219
63768
|
var MAX_FILE_SIZE_BYTES7 = 1024 * 1024;
|
|
63220
63769
|
var WINDOWS_RESERVED_NAMES = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
|
|
63221
63770
|
function containsControlCharacters(str) {
|
|
@@ -63244,11 +63793,11 @@ function containsWindowsAttacks(str) {
|
|
|
63244
63793
|
}
|
|
63245
63794
|
function isPathInWorkspace(filePath, workspace) {
|
|
63246
63795
|
try {
|
|
63247
|
-
const resolvedPath =
|
|
63248
|
-
const realWorkspace =
|
|
63249
|
-
const realResolvedPath =
|
|
63250
|
-
const relativePath =
|
|
63251
|
-
if (relativePath.startsWith("..") ||
|
|
63796
|
+
const resolvedPath = path54.resolve(workspace, filePath);
|
|
63797
|
+
const realWorkspace = fs42.realpathSync(workspace);
|
|
63798
|
+
const realResolvedPath = fs42.realpathSync(resolvedPath);
|
|
63799
|
+
const relativePath = path54.relative(realWorkspace, realResolvedPath);
|
|
63800
|
+
if (relativePath.startsWith("..") || path54.isAbsolute(relativePath)) {
|
|
63252
63801
|
return false;
|
|
63253
63802
|
}
|
|
63254
63803
|
return true;
|
|
@@ -63260,17 +63809,17 @@ function validatePathForRead(filePath, workspace) {
|
|
|
63260
63809
|
return isPathInWorkspace(filePath, workspace);
|
|
63261
63810
|
}
|
|
63262
63811
|
function extractTSSymbols(filePath, cwd) {
|
|
63263
|
-
const fullPath =
|
|
63812
|
+
const fullPath = path54.join(cwd, filePath);
|
|
63264
63813
|
if (!validatePathForRead(fullPath, cwd)) {
|
|
63265
63814
|
return [];
|
|
63266
63815
|
}
|
|
63267
63816
|
let content;
|
|
63268
63817
|
try {
|
|
63269
|
-
const stats =
|
|
63818
|
+
const stats = fs42.statSync(fullPath);
|
|
63270
63819
|
if (stats.size > MAX_FILE_SIZE_BYTES7) {
|
|
63271
63820
|
throw new Error(`File too large: ${stats.size} bytes (max: ${MAX_FILE_SIZE_BYTES7})`);
|
|
63272
63821
|
}
|
|
63273
|
-
content =
|
|
63822
|
+
content = fs42.readFileSync(fullPath, "utf-8");
|
|
63274
63823
|
} catch {
|
|
63275
63824
|
return [];
|
|
63276
63825
|
}
|
|
@@ -63412,17 +63961,17 @@ function extractTSSymbols(filePath, cwd) {
|
|
|
63412
63961
|
});
|
|
63413
63962
|
}
|
|
63414
63963
|
function extractPythonSymbols(filePath, cwd) {
|
|
63415
|
-
const fullPath =
|
|
63964
|
+
const fullPath = path54.join(cwd, filePath);
|
|
63416
63965
|
if (!validatePathForRead(fullPath, cwd)) {
|
|
63417
63966
|
return [];
|
|
63418
63967
|
}
|
|
63419
63968
|
let content;
|
|
63420
63969
|
try {
|
|
63421
|
-
const stats =
|
|
63970
|
+
const stats = fs42.statSync(fullPath);
|
|
63422
63971
|
if (stats.size > MAX_FILE_SIZE_BYTES7) {
|
|
63423
63972
|
throw new Error(`File too large: ${stats.size} bytes (max: ${MAX_FILE_SIZE_BYTES7})`);
|
|
63424
63973
|
}
|
|
63425
|
-
content =
|
|
63974
|
+
content = fs42.readFileSync(fullPath, "utf-8");
|
|
63426
63975
|
} catch {
|
|
63427
63976
|
return [];
|
|
63428
63977
|
}
|
|
@@ -63495,7 +64044,7 @@ var symbols = createSwarmTool({
|
|
|
63495
64044
|
}, null, 2);
|
|
63496
64045
|
}
|
|
63497
64046
|
const cwd = directory;
|
|
63498
|
-
const ext =
|
|
64047
|
+
const ext = path54.extname(file3);
|
|
63499
64048
|
if (containsControlCharacters(file3)) {
|
|
63500
64049
|
return JSON.stringify({
|
|
63501
64050
|
file: file3,
|
|
@@ -63566,8 +64115,8 @@ init_test_runner();
|
|
|
63566
64115
|
init_dist();
|
|
63567
64116
|
init_utils();
|
|
63568
64117
|
init_create_tool();
|
|
63569
|
-
import * as
|
|
63570
|
-
import * as
|
|
64118
|
+
import * as fs43 from "fs";
|
|
64119
|
+
import * as path55 from "path";
|
|
63571
64120
|
var MAX_TEXT_LENGTH = 200;
|
|
63572
64121
|
var MAX_FILE_SIZE_BYTES8 = 1024 * 1024;
|
|
63573
64122
|
var SUPPORTED_EXTENSIONS2 = new Set([
|
|
@@ -63589,7 +64138,7 @@ var SUPPORTED_EXTENSIONS2 = new Set([
|
|
|
63589
64138
|
".swift",
|
|
63590
64139
|
".kt"
|
|
63591
64140
|
]);
|
|
63592
|
-
var
|
|
64141
|
+
var SKIP_DIRECTORIES4 = new Set([
|
|
63593
64142
|
"node_modules",
|
|
63594
64143
|
"dist",
|
|
63595
64144
|
"build",
|
|
@@ -63638,9 +64187,9 @@ function validatePathsInput(paths, cwd) {
|
|
|
63638
64187
|
return { error: "paths contains path traversal", resolvedPath: null };
|
|
63639
64188
|
}
|
|
63640
64189
|
try {
|
|
63641
|
-
const resolvedPath =
|
|
63642
|
-
const normalizedCwd =
|
|
63643
|
-
const normalizedResolved =
|
|
64190
|
+
const resolvedPath = path55.resolve(paths);
|
|
64191
|
+
const normalizedCwd = path55.resolve(cwd);
|
|
64192
|
+
const normalizedResolved = path55.resolve(resolvedPath);
|
|
63644
64193
|
if (!normalizedResolved.startsWith(normalizedCwd)) {
|
|
63645
64194
|
return {
|
|
63646
64195
|
error: "paths must be within the current working directory",
|
|
@@ -63656,25 +64205,25 @@ function validatePathsInput(paths, cwd) {
|
|
|
63656
64205
|
}
|
|
63657
64206
|
}
|
|
63658
64207
|
function isSupportedExtension(filePath) {
|
|
63659
|
-
const ext =
|
|
64208
|
+
const ext = path55.extname(filePath).toLowerCase();
|
|
63660
64209
|
return SUPPORTED_EXTENSIONS2.has(ext);
|
|
63661
64210
|
}
|
|
63662
64211
|
function findSourceFiles2(dir, files = []) {
|
|
63663
64212
|
let entries;
|
|
63664
64213
|
try {
|
|
63665
|
-
entries =
|
|
64214
|
+
entries = fs43.readdirSync(dir);
|
|
63666
64215
|
} catch {
|
|
63667
64216
|
return files;
|
|
63668
64217
|
}
|
|
63669
64218
|
entries.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
|
|
63670
64219
|
for (const entry of entries) {
|
|
63671
|
-
if (
|
|
64220
|
+
if (SKIP_DIRECTORIES4.has(entry)) {
|
|
63672
64221
|
continue;
|
|
63673
64222
|
}
|
|
63674
|
-
const fullPath =
|
|
64223
|
+
const fullPath = path55.join(dir, entry);
|
|
63675
64224
|
let stat2;
|
|
63676
64225
|
try {
|
|
63677
|
-
stat2 =
|
|
64226
|
+
stat2 = fs43.statSync(fullPath);
|
|
63678
64227
|
} catch {
|
|
63679
64228
|
continue;
|
|
63680
64229
|
}
|
|
@@ -63767,7 +64316,7 @@ var todo_extract = createSwarmTool({
|
|
|
63767
64316
|
return JSON.stringify(errorResult, null, 2);
|
|
63768
64317
|
}
|
|
63769
64318
|
const scanPath = resolvedPath;
|
|
63770
|
-
if (!
|
|
64319
|
+
if (!fs43.existsSync(scanPath)) {
|
|
63771
64320
|
const errorResult = {
|
|
63772
64321
|
error: `path not found: ${pathsInput}`,
|
|
63773
64322
|
total: 0,
|
|
@@ -63777,13 +64326,13 @@ var todo_extract = createSwarmTool({
|
|
|
63777
64326
|
return JSON.stringify(errorResult, null, 2);
|
|
63778
64327
|
}
|
|
63779
64328
|
const filesToScan = [];
|
|
63780
|
-
const stat2 =
|
|
64329
|
+
const stat2 = fs43.statSync(scanPath);
|
|
63781
64330
|
if (stat2.isFile()) {
|
|
63782
64331
|
if (isSupportedExtension(scanPath)) {
|
|
63783
64332
|
filesToScan.push(scanPath);
|
|
63784
64333
|
} else {
|
|
63785
64334
|
const errorResult = {
|
|
63786
|
-
error: `unsupported file extension: ${
|
|
64335
|
+
error: `unsupported file extension: ${path55.extname(scanPath)}`,
|
|
63787
64336
|
total: 0,
|
|
63788
64337
|
byPriority: { high: 0, medium: 0, low: 0 },
|
|
63789
64338
|
entries: []
|
|
@@ -63796,11 +64345,11 @@ var todo_extract = createSwarmTool({
|
|
|
63796
64345
|
const allEntries = [];
|
|
63797
64346
|
for (const filePath of filesToScan) {
|
|
63798
64347
|
try {
|
|
63799
|
-
const fileStat =
|
|
64348
|
+
const fileStat = fs43.statSync(filePath);
|
|
63800
64349
|
if (fileStat.size > MAX_FILE_SIZE_BYTES8) {
|
|
63801
64350
|
continue;
|
|
63802
64351
|
}
|
|
63803
|
-
const content =
|
|
64352
|
+
const content = fs43.readFileSync(filePath, "utf-8");
|
|
63804
64353
|
const entries = parseTodoComments(content, filePath, tagsSet);
|
|
63805
64354
|
allEntries.push(...entries);
|
|
63806
64355
|
} catch {}
|
|
@@ -63828,18 +64377,18 @@ var todo_extract = createSwarmTool({
|
|
|
63828
64377
|
// src/tools/update-task-status.ts
|
|
63829
64378
|
init_tool();
|
|
63830
64379
|
init_schema();
|
|
63831
|
-
import * as
|
|
63832
|
-
import * as
|
|
64380
|
+
import * as fs45 from "fs";
|
|
64381
|
+
import * as path57 from "path";
|
|
63833
64382
|
|
|
63834
64383
|
// src/hooks/diff-scope.ts
|
|
63835
|
-
import * as
|
|
63836
|
-
import * as
|
|
64384
|
+
import * as fs44 from "fs";
|
|
64385
|
+
import * as path56 from "path";
|
|
63837
64386
|
function getDeclaredScope(taskId, directory) {
|
|
63838
64387
|
try {
|
|
63839
|
-
const planPath =
|
|
63840
|
-
if (!
|
|
64388
|
+
const planPath = path56.join(directory, ".swarm", "plan.json");
|
|
64389
|
+
if (!fs44.existsSync(planPath))
|
|
63841
64390
|
return null;
|
|
63842
|
-
const raw =
|
|
64391
|
+
const raw = fs44.readFileSync(planPath, "utf-8");
|
|
63843
64392
|
const plan = JSON.parse(raw);
|
|
63844
64393
|
for (const phase of plan.phases ?? []) {
|
|
63845
64394
|
for (const task of phase.tasks ?? []) {
|
|
@@ -63951,7 +64500,7 @@ var TIER_3_PATTERNS = [
|
|
|
63951
64500
|
];
|
|
63952
64501
|
function matchesTier3Pattern(files) {
|
|
63953
64502
|
for (const file3 of files) {
|
|
63954
|
-
const fileName =
|
|
64503
|
+
const fileName = path57.basename(file3);
|
|
63955
64504
|
for (const pattern of TIER_3_PATTERNS) {
|
|
63956
64505
|
if (pattern.test(fileName)) {
|
|
63957
64506
|
return true;
|
|
@@ -63973,8 +64522,8 @@ function checkReviewerGate(taskId, workingDirectory) {
|
|
|
63973
64522
|
if (hasActiveTurboMode2()) {
|
|
63974
64523
|
const resolvedDir2 = workingDirectory;
|
|
63975
64524
|
try {
|
|
63976
|
-
const planPath =
|
|
63977
|
-
const planRaw =
|
|
64525
|
+
const planPath = path57.join(resolvedDir2, ".swarm", "plan.json");
|
|
64526
|
+
const planRaw = fs45.readFileSync(planPath, "utf-8");
|
|
63978
64527
|
const plan = JSON.parse(planRaw);
|
|
63979
64528
|
for (const planPhase of plan.phases ?? []) {
|
|
63980
64529
|
for (const task of planPhase.tasks ?? []) {
|
|
@@ -63993,8 +64542,8 @@ function checkReviewerGate(taskId, workingDirectory) {
|
|
|
63993
64542
|
}
|
|
63994
64543
|
const resolvedDir = workingDirectory;
|
|
63995
64544
|
try {
|
|
63996
|
-
const evidencePath =
|
|
63997
|
-
const raw =
|
|
64545
|
+
const evidencePath = path57.join(resolvedDir, ".swarm", "evidence", `${taskId}.json`);
|
|
64546
|
+
const raw = fs45.readFileSync(evidencePath, "utf-8");
|
|
63998
64547
|
const evidence = JSON.parse(raw);
|
|
63999
64548
|
if (evidence?.required_gates && Array.isArray(evidence.required_gates) && evidence?.gates) {
|
|
64000
64549
|
const allGatesMet = evidence.required_gates.every((gate) => evidence.gates[gate] != null);
|
|
@@ -64034,8 +64583,8 @@ function checkReviewerGate(taskId, workingDirectory) {
|
|
|
64034
64583
|
}
|
|
64035
64584
|
try {
|
|
64036
64585
|
const resolvedDir2 = workingDirectory;
|
|
64037
|
-
const planPath =
|
|
64038
|
-
const planRaw =
|
|
64586
|
+
const planPath = path57.join(resolvedDir2, ".swarm", "plan.json");
|
|
64587
|
+
const planRaw = fs45.readFileSync(planPath, "utf-8");
|
|
64039
64588
|
const plan = JSON.parse(planRaw);
|
|
64040
64589
|
for (const planPhase of plan.phases ?? []) {
|
|
64041
64590
|
for (const task of planPhase.tasks ?? []) {
|
|
@@ -64216,8 +64765,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
|
|
|
64216
64765
|
};
|
|
64217
64766
|
}
|
|
64218
64767
|
}
|
|
64219
|
-
normalizedDir =
|
|
64220
|
-
const pathParts = normalizedDir.split(
|
|
64768
|
+
normalizedDir = path57.normalize(args2.working_directory);
|
|
64769
|
+
const pathParts = normalizedDir.split(path57.sep);
|
|
64221
64770
|
if (pathParts.includes("..")) {
|
|
64222
64771
|
return {
|
|
64223
64772
|
success: false,
|
|
@@ -64227,11 +64776,11 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
|
|
|
64227
64776
|
]
|
|
64228
64777
|
};
|
|
64229
64778
|
}
|
|
64230
|
-
const resolvedDir =
|
|
64779
|
+
const resolvedDir = path57.resolve(normalizedDir);
|
|
64231
64780
|
try {
|
|
64232
|
-
const realPath =
|
|
64233
|
-
const planPath =
|
|
64234
|
-
if (!
|
|
64781
|
+
const realPath = fs45.realpathSync(resolvedDir);
|
|
64782
|
+
const planPath = path57.join(realPath, ".swarm", "plan.json");
|
|
64783
|
+
if (!fs45.existsSync(planPath)) {
|
|
64235
64784
|
return {
|
|
64236
64785
|
success: false,
|
|
64237
64786
|
message: `Invalid working_directory: plan not found in "${realPath}"`,
|
|
@@ -64453,7 +65002,7 @@ var OpenCodeSwarm = async (ctx) => {
|
|
|
64453
65002
|
const { PreflightTriggerManager: PTM } = await Promise.resolve().then(() => (init_trigger(), exports_trigger));
|
|
64454
65003
|
preflightTriggerManager = new PTM(automationConfig);
|
|
64455
65004
|
const { AutomationStatusArtifact: ASA } = await Promise.resolve().then(() => (init_status_artifact(), exports_status_artifact));
|
|
64456
|
-
const swarmDir =
|
|
65005
|
+
const swarmDir = path58.resolve(ctx.directory, ".swarm");
|
|
64457
65006
|
statusArtifact = new ASA(swarmDir);
|
|
64458
65007
|
statusArtifact.updateConfig(automationConfig.mode, automationConfig.capabilities);
|
|
64459
65008
|
if (automationConfig.capabilities?.evidence_auto_summaries === true) {
|
|
@@ -64745,7 +65294,9 @@ var OpenCodeSwarm = async (ctx) => {
|
|
|
64745
65294
|
await safeHook(activityHooks.toolBefore)(input, output);
|
|
64746
65295
|
},
|
|
64747
65296
|
"tool.execute.after": async (input, output) => {
|
|
64748
|
-
|
|
65297
|
+
if (process.env.DEBUG_SWARM) {
|
|
65298
|
+
console.debug("[hook-chain] toolAfter start sessionID=%s agent=%s tool=%s", input.sessionID, input.agent, input.tool?.name);
|
|
65299
|
+
}
|
|
64749
65300
|
await activityHooks.toolAfter(input, output);
|
|
64750
65301
|
await guardrailsHooks.toolAfter(input, output);
|
|
64751
65302
|
await safeHook(delegationLedgerHook.toolAfter)(input, output);
|
|
@@ -64805,7 +65356,9 @@ var OpenCodeSwarm = async (ctx) => {
|
|
|
64805
65356
|
deleteStoredInputArgs(input.callID);
|
|
64806
65357
|
},
|
|
64807
65358
|
"chat.message": safeHook(async (input, output) => {
|
|
64808
|
-
|
|
65359
|
+
if (process.env.DEBUG_SWARM) {
|
|
65360
|
+
console.debug("[session] chat.message sessionID=%s agent=%s", input.sessionID, input.agent);
|
|
65361
|
+
}
|
|
64809
65362
|
await delegationHandler(input, output);
|
|
64810
65363
|
}),
|
|
64811
65364
|
automation: automationManager
|