opencode-swarm 6.33.1 → 6.33.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +59 -7
- package/dist/cli/index.js +74 -11
- 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 +819 -260
- 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 +9 -1
- 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,12 +39863,24 @@ 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
|
}
|
|
39843
39875
|
if (session.pendingAdvisoryMessages === undefined) {
|
|
39844
39876
|
session.pendingAdvisoryMessages = [];
|
|
39845
39877
|
}
|
|
39878
|
+
if (session.coderRevisions === undefined) {
|
|
39879
|
+
session.coderRevisions = 0;
|
|
39880
|
+
}
|
|
39881
|
+
if (session.revisionLimitHit === undefined) {
|
|
39882
|
+
session.revisionLimitHit = false;
|
|
39883
|
+
}
|
|
39846
39884
|
session.lastToolCallTime = now;
|
|
39847
39885
|
return session;
|
|
39848
39886
|
}
|
|
@@ -44112,14 +44150,18 @@ async function readCuratorSummary(directory) {
|
|
|
44112
44150
|
}
|
|
44113
44151
|
return parsed;
|
|
44114
44152
|
} catch {
|
|
44115
|
-
|
|
44153
|
+
if (process.env.DEBUG_SWARM) {
|
|
44154
|
+
console.warn("Failed to parse curator-summary.json: invalid JSON");
|
|
44155
|
+
}
|
|
44116
44156
|
return null;
|
|
44117
44157
|
}
|
|
44118
44158
|
}
|
|
44119
44159
|
async function writeCuratorSummary(directory, summary) {
|
|
44120
44160
|
const resolvedPath = validateSwarmPath(directory, "curator-summary.json");
|
|
44121
44161
|
fs7.mkdirSync(path12.dirname(resolvedPath), { recursive: true });
|
|
44122
|
-
|
|
44162
|
+
const tempPath = `${resolvedPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
|
|
44163
|
+
await Bun.write(tempPath, JSON.stringify(summary, null, 2));
|
|
44164
|
+
fs7.renameSync(tempPath, resolvedPath);
|
|
44123
44165
|
}
|
|
44124
44166
|
function normalizeAgentName(name2) {
|
|
44125
44167
|
return name2.toLowerCase().replace(/^(mega|paid|local|lowtier|modelrelay)_/, "");
|
|
@@ -44143,7 +44185,9 @@ function filterPhaseEvents(eventsJsonl, phase, sinceTimestamp) {
|
|
|
44143
44185
|
}
|
|
44144
44186
|
}
|
|
44145
44187
|
} catch {
|
|
44146
|
-
|
|
44188
|
+
if (process.env.DEBUG_SWARM) {
|
|
44189
|
+
console.warn("filterPhaseEvents: skipping malformed line");
|
|
44190
|
+
}
|
|
44147
44191
|
}
|
|
44148
44192
|
}
|
|
44149
44193
|
return filtered;
|
|
@@ -46473,7 +46517,7 @@ async function handleExportCommand(directory, _args) {
|
|
|
46473
46517
|
// src/commands/handoff.ts
|
|
46474
46518
|
init_utils2();
|
|
46475
46519
|
import crypto3 from "crypto";
|
|
46476
|
-
import { renameSync as
|
|
46520
|
+
import { renameSync as renameSync6 } from "fs";
|
|
46477
46521
|
|
|
46478
46522
|
// src/services/handoff-service.ts
|
|
46479
46523
|
init_utils2();
|
|
@@ -46774,7 +46818,7 @@ function formatHandoffMarkdown(data) {
|
|
|
46774
46818
|
|
|
46775
46819
|
// src/session/snapshot-writer.ts
|
|
46776
46820
|
init_utils2();
|
|
46777
|
-
import { mkdirSync as mkdirSync7, renameSync as
|
|
46821
|
+
import { mkdirSync as mkdirSync7, renameSync as renameSync5 } from "fs";
|
|
46778
46822
|
import * as path19 from "path";
|
|
46779
46823
|
var pendingWrite = null;
|
|
46780
46824
|
var lastWritePromise = Promise.resolve();
|
|
@@ -46839,13 +46883,17 @@ function serializeAgentSession(s) {
|
|
|
46839
46883
|
taskWorkflowStates: Object.fromEntries(s.taskWorkflowStates ?? new Map),
|
|
46840
46884
|
...s.scopeViolationDetected !== undefined && {
|
|
46841
46885
|
scopeViolationDetected: s.scopeViolationDetected
|
|
46842
|
-
}
|
|
46886
|
+
},
|
|
46887
|
+
model_fallback_index: s.model_fallback_index ?? 0,
|
|
46888
|
+
modelFallbackExhausted: s.modelFallbackExhausted ?? false,
|
|
46889
|
+
coderRevisions: s.coderRevisions ?? 0,
|
|
46890
|
+
revisionLimitHit: s.revisionLimitHit ?? false
|
|
46843
46891
|
};
|
|
46844
46892
|
}
|
|
46845
46893
|
async function writeSnapshot(directory, state) {
|
|
46846
46894
|
try {
|
|
46847
46895
|
const snapshot = {
|
|
46848
|
-
version:
|
|
46896
|
+
version: 2,
|
|
46849
46897
|
writtenAt: Date.now(),
|
|
46850
46898
|
toolAggregates: Object.fromEntries(state.toolAggregates),
|
|
46851
46899
|
activeAgent: Object.fromEntries(state.activeAgent),
|
|
@@ -46861,9 +46909,11 @@ async function writeSnapshot(directory, state) {
|
|
|
46861
46909
|
mkdirSync7(dir, { recursive: true });
|
|
46862
46910
|
const tempPath = `${resolvedPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
|
|
46863
46911
|
await Bun.write(tempPath, content);
|
|
46864
|
-
|
|
46912
|
+
renameSync5(tempPath, resolvedPath);
|
|
46865
46913
|
} catch (error93) {
|
|
46866
|
-
|
|
46914
|
+
if (process.env.DEBUG_SWARM) {
|
|
46915
|
+
console.warn("[snapshot-writer] write failed:", error93 instanceof Error ? error93.message : String(error93));
|
|
46916
|
+
}
|
|
46867
46917
|
}
|
|
46868
46918
|
}
|
|
46869
46919
|
function createSnapshotWriterHook(directory) {
|
|
@@ -46893,7 +46943,7 @@ async function handleHandoffCommand(directory, _args) {
|
|
|
46893
46943
|
const resolvedPath = validateSwarmPath(directory, "handoff.md");
|
|
46894
46944
|
const tempPath = `${resolvedPath}.tmp.${crypto3.randomUUID()}`;
|
|
46895
46945
|
await Bun.write(tempPath, markdown);
|
|
46896
|
-
|
|
46946
|
+
renameSync6(tempPath, resolvedPath);
|
|
46897
46947
|
await writeSnapshot(directory, swarmState);
|
|
46898
46948
|
await flushPendingSnapshot(directory);
|
|
46899
46949
|
return `## Handoff Brief Written
|
|
@@ -47639,7 +47689,7 @@ async function handleResetSessionCommand(directory, _args) {
|
|
|
47639
47689
|
// src/summaries/manager.ts
|
|
47640
47690
|
init_utils2();
|
|
47641
47691
|
init_utils();
|
|
47642
|
-
import { mkdirSync as mkdirSync8, readdirSync as readdirSync7, renameSync as
|
|
47692
|
+
import { mkdirSync as mkdirSync8, readdirSync as readdirSync7, renameSync as renameSync7, rmSync as rmSync3, statSync as statSync7 } from "fs";
|
|
47643
47693
|
import * as path26 from "path";
|
|
47644
47694
|
var SUMMARY_ID_REGEX = /^S\d+$/;
|
|
47645
47695
|
function sanitizeSummaryId(id) {
|
|
@@ -47683,7 +47733,7 @@ async function storeSummary(directory, id, fullOutput, summaryText, maxStoredByt
|
|
|
47683
47733
|
const tempPath = path26.join(summaryDir, `${sanitizedId}.json.tmp.${Date.now()}.${process.pid}`);
|
|
47684
47734
|
try {
|
|
47685
47735
|
await Bun.write(tempPath, entryJson);
|
|
47686
|
-
|
|
47736
|
+
renameSync7(tempPath, summaryPath);
|
|
47687
47737
|
} catch (error93) {
|
|
47688
47738
|
try {
|
|
47689
47739
|
rmSync3(tempPath, { force: true });
|
|
@@ -48863,8 +48913,46 @@ async function executeWriteRetro(args2, directory) {
|
|
|
48863
48913
|
top_rejection_reasons: args2.top_rejection_reasons ?? [],
|
|
48864
48914
|
lessons_learned: (args2.lessons_learned ?? []).slice(0, 5),
|
|
48865
48915
|
user_directives: [],
|
|
48866
|
-
approaches_tried: []
|
|
48916
|
+
approaches_tried: [],
|
|
48917
|
+
error_taxonomy: []
|
|
48867
48918
|
};
|
|
48919
|
+
const taxonomy = [];
|
|
48920
|
+
try {
|
|
48921
|
+
for (const taskSuffix of ["1", "2", "3", "4", "5"]) {
|
|
48922
|
+
const phaseTaskId = `${phase}.${taskSuffix}`;
|
|
48923
|
+
const result = await loadEvidence(directory, phaseTaskId);
|
|
48924
|
+
if (result.status !== "found")
|
|
48925
|
+
continue;
|
|
48926
|
+
const bundle = result.bundle;
|
|
48927
|
+
for (const entry of bundle.entries) {
|
|
48928
|
+
const e = entry;
|
|
48929
|
+
if (e.type === "review" && e.verdict === "fail") {
|
|
48930
|
+
const reasonParts = [];
|
|
48931
|
+
if (typeof e.summary === "string")
|
|
48932
|
+
reasonParts.push(e.summary);
|
|
48933
|
+
if (Array.isArray(e.issues)) {
|
|
48934
|
+
for (const iss of e.issues) {
|
|
48935
|
+
if (typeof iss.message === "string")
|
|
48936
|
+
reasonParts.push(iss.message);
|
|
48937
|
+
}
|
|
48938
|
+
}
|
|
48939
|
+
const reason = reasonParts.join(" ");
|
|
48940
|
+
if (/signature|type|contract|interface/i.test(reason)) {
|
|
48941
|
+
taxonomy.push("interface_mismatch");
|
|
48942
|
+
} else {
|
|
48943
|
+
taxonomy.push("logic_error");
|
|
48944
|
+
}
|
|
48945
|
+
} else if (e.type === "test" && e.verdict === "fail") {
|
|
48946
|
+
taxonomy.push("logic_error");
|
|
48947
|
+
} else if (e.agent === "scope_guard" && e.verdict === "fail") {
|
|
48948
|
+
taxonomy.push("scope_creep");
|
|
48949
|
+
} else if (e.agent === "loop_detector" && e.verdict === "fail") {
|
|
48950
|
+
taxonomy.push("gate_evasion");
|
|
48951
|
+
}
|
|
48952
|
+
}
|
|
48953
|
+
}
|
|
48954
|
+
} catch {}
|
|
48955
|
+
retroEntry.error_taxonomy = [...new Set(taxonomy)];
|
|
48868
48956
|
try {
|
|
48869
48957
|
await saveEvidence(directory, taskId, retroEntry);
|
|
48870
48958
|
return JSON.stringify({
|
|
@@ -49187,7 +49275,7 @@ init_constants();
|
|
|
49187
49275
|
init_schema();
|
|
49188
49276
|
|
|
49189
49277
|
// src/hooks/agent-activity.ts
|
|
49190
|
-
import { renameSync as
|
|
49278
|
+
import { renameSync as renameSync8, unlinkSync as unlinkSync4 } from "fs";
|
|
49191
49279
|
init_utils();
|
|
49192
49280
|
init_utils2();
|
|
49193
49281
|
function createAgentActivityHooks(config3, directory) {
|
|
@@ -49261,7 +49349,7 @@ async function doFlush(directory) {
|
|
|
49261
49349
|
const tempPath = `${path29}.tmp`;
|
|
49262
49350
|
try {
|
|
49263
49351
|
await Bun.write(tempPath, updated);
|
|
49264
|
-
|
|
49352
|
+
renameSync8(tempPath, path29);
|
|
49265
49353
|
} catch (writeError) {
|
|
49266
49354
|
try {
|
|
49267
49355
|
unlinkSync4(tempPath);
|
|
@@ -49895,6 +49983,7 @@ function detectLoop(sessionId, toolName, args2) {
|
|
|
49895
49983
|
|
|
49896
49984
|
// src/hooks/guardrails.ts
|
|
49897
49985
|
var storedInputArgs = new Map;
|
|
49986
|
+
var TRANSIENT_MODEL_ERROR_PATTERN = /rate.?limit|429|503|timeout|overloaded|model.?not.?found|temporarily unavailable|server error/i;
|
|
49898
49987
|
function getStoredInputArgs(callID) {
|
|
49899
49988
|
return storedInputArgs.get(callID);
|
|
49900
49989
|
}
|
|
@@ -50072,6 +50161,9 @@ function createGuardrailsHooks(directory, directoryOrConfig, config3) {
|
|
|
50072
50161
|
const coderSession = swarmState.agentSessions.get(input.sessionID);
|
|
50073
50162
|
if (coderSession) {
|
|
50074
50163
|
coderSession.modifiedFilesThisCoderTask = [];
|
|
50164
|
+
if (!coderSession.revisionLimitHit) {
|
|
50165
|
+
coderSession.coderRevisions = 0;
|
|
50166
|
+
}
|
|
50075
50167
|
}
|
|
50076
50168
|
}
|
|
50077
50169
|
}
|
|
@@ -50080,7 +50172,7 @@ function createGuardrailsHooks(directory, directoryOrConfig, config3) {
|
|
|
50080
50172
|
const loopResult = detectLoop(input.sessionID, input.tool, loopArgs);
|
|
50081
50173
|
if (loopResult.count >= 5) {
|
|
50082
50174
|
throw new Error(`CIRCUIT BREAKER: Delegation loop detected (${loopResult.count} identical patterns). Session paused. Ask the user for guidance.`);
|
|
50083
|
-
} else if (loopResult.count
|
|
50175
|
+
} else if (loopResult.count >= 3 && loopResult.count < 5) {
|
|
50084
50176
|
const agentName2 = typeof loopArgs?.subagent_type === "string" ? loopArgs.subagent_type : "agent";
|
|
50085
50177
|
const loopSession = swarmState.agentSessions.get(input.sessionID);
|
|
50086
50178
|
if (loopSession) {
|
|
@@ -50411,6 +50503,16 @@ function createGuardrailsHooks(directory, directoryOrConfig, config3) {
|
|
|
50411
50503
|
}
|
|
50412
50504
|
if (delegation.isDelegation && delegation.targetAgent === "coder" && session.lastCoderDelegationTaskId) {
|
|
50413
50505
|
session.currentTaskId = session.lastCoderDelegationTaskId;
|
|
50506
|
+
if (!session.revisionLimitHit) {
|
|
50507
|
+
session.coderRevisions++;
|
|
50508
|
+
const maxRevisions = cfg.max_coder_revisions ?? 5;
|
|
50509
|
+
if (session.coderRevisions >= maxRevisions) {
|
|
50510
|
+
session.revisionLimitHit = true;
|
|
50511
|
+
session.pendingAdvisoryMessages ??= [];
|
|
50512
|
+
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.`);
|
|
50513
|
+
swarmState.pendingEvents++;
|
|
50514
|
+
}
|
|
50515
|
+
}
|
|
50414
50516
|
session.partialGateWarningsIssuedForTask?.delete(session.currentTaskId);
|
|
50415
50517
|
if (session.declaredCoderScope !== null) {
|
|
50416
50518
|
const undeclaredFiles = session.modifiedFilesThisCoderTask.map((f) => f.replace(/[\r\n\t]/g, "_")).filter((f) => !isInDeclaredScope(f, session.declaredCoderScope));
|
|
@@ -50442,9 +50544,26 @@ function createGuardrailsHooks(directory, directoryOrConfig, config3) {
|
|
|
50442
50544
|
const hasError = output.output === null || output.output === undefined;
|
|
50443
50545
|
if (hasError) {
|
|
50444
50546
|
window2.consecutiveErrors++;
|
|
50547
|
+
if (session) {
|
|
50548
|
+
const outputStr = typeof output.output === "string" ? output.output : "";
|
|
50549
|
+
const errorContent = output.error ?? outputStr;
|
|
50550
|
+
if (typeof errorContent === "string" && TRANSIENT_MODEL_ERROR_PATTERN.test(errorContent) && !session.modelFallbackExhausted) {
|
|
50551
|
+
session.model_fallback_index++;
|
|
50552
|
+
session.modelFallbackExhausted = true;
|
|
50553
|
+
session.pendingAdvisoryMessages ??= [];
|
|
50554
|
+
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.`);
|
|
50555
|
+
swarmState.pendingEvents++;
|
|
50556
|
+
}
|
|
50557
|
+
}
|
|
50445
50558
|
} else {
|
|
50446
50559
|
window2.consecutiveErrors = 0;
|
|
50447
50560
|
window2.lastSuccessTimeMs = Date.now();
|
|
50561
|
+
if (session) {
|
|
50562
|
+
if (session.model_fallback_index > 0) {
|
|
50563
|
+
session.model_fallback_index = 0;
|
|
50564
|
+
session.modelFallbackExhausted = false;
|
|
50565
|
+
}
|
|
50566
|
+
}
|
|
50448
50567
|
}
|
|
50449
50568
|
},
|
|
50450
50569
|
messagesTransform: async (_input, output) => {
|
|
@@ -50740,7 +50859,7 @@ function extractPlanTaskId(text) {
|
|
|
50740
50859
|
function getSeedTaskId(session) {
|
|
50741
50860
|
return session.currentTaskId ?? session.lastCoderDelegationTaskId;
|
|
50742
50861
|
}
|
|
50743
|
-
function getEvidenceTaskId(session, directory) {
|
|
50862
|
+
async function getEvidenceTaskId(session, directory) {
|
|
50744
50863
|
const primary = session.currentTaskId ?? session.lastCoderDelegationTaskId;
|
|
50745
50864
|
if (primary)
|
|
50746
50865
|
return primary;
|
|
@@ -50757,7 +50876,7 @@ function getEvidenceTaskId(session, directory) {
|
|
|
50757
50876
|
if (!resolvedPlanPath.startsWith(resolvedDirectory + path31.sep) && resolvedPlanPath !== resolvedDirectory) {
|
|
50758
50877
|
return null;
|
|
50759
50878
|
}
|
|
50760
|
-
const planContent = fs19.
|
|
50879
|
+
const planContent = await fs19.promises.readFile(resolvedPlanPath, "utf-8");
|
|
50761
50880
|
const plan = JSON.parse(planContent);
|
|
50762
50881
|
if (!plan || !Array.isArray(plan.phases)) {
|
|
50763
50882
|
return null;
|
|
@@ -50877,7 +50996,7 @@ function createDelegationGateHook(config3, directory) {
|
|
|
50877
50996
|
}
|
|
50878
50997
|
if (typeof subagentType === "string") {
|
|
50879
50998
|
const rawTaskId = directArgs?.task_id;
|
|
50880
|
-
const evidenceTaskId = typeof rawTaskId === "string" && rawTaskId.length <= 20 && /^\d+\.\d+$/.test(rawTaskId.trim()) ? rawTaskId.trim() : getEvidenceTaskId(session, directory);
|
|
50999
|
+
const evidenceTaskId = typeof rawTaskId === "string" && rawTaskId.length <= 20 && /^\d+\.\d+$/.test(rawTaskId.trim()) ? rawTaskId.trim() : await getEvidenceTaskId(session, directory);
|
|
50881
51000
|
if (evidenceTaskId) {
|
|
50882
51001
|
try {
|
|
50883
51002
|
const turbo = hasActiveTurboMode();
|
|
@@ -50997,7 +51116,7 @@ function createDelegationGateHook(config3, directory) {
|
|
|
50997
51116
|
}
|
|
50998
51117
|
{
|
|
50999
51118
|
const rawTaskId = directArgs?.task_id;
|
|
51000
|
-
const evidenceTaskId = typeof rawTaskId === "string" && rawTaskId.length <= 20 && /^\d+\.\d+$/.test(rawTaskId.trim()) ? rawTaskId.trim() : getEvidenceTaskId(session, directory);
|
|
51119
|
+
const evidenceTaskId = typeof rawTaskId === "string" && rawTaskId.length <= 20 && /^\d+\.\d+$/.test(rawTaskId.trim()) ? rawTaskId.trim() : await getEvidenceTaskId(session, directory);
|
|
51001
51120
|
if (evidenceTaskId) {
|
|
51002
51121
|
try {
|
|
51003
51122
|
const turbo = hasActiveTurboMode();
|
|
@@ -51094,7 +51213,7 @@ ${trimComment}${after}`;
|
|
|
51094
51213
|
const currentTaskId = planTaskId ?? taskIdFromLine;
|
|
51095
51214
|
const coderDelegationPattern = /(?:^|\n)\s*(?:\w+_)?coder\s*\n\s*TASK:/i;
|
|
51096
51215
|
const isCoderDelegation = coderDelegationPattern.test(text);
|
|
51097
|
-
const priorCoderTaskId = sessionID ?
|
|
51216
|
+
const priorCoderTaskId = sessionID ? swarmState.agentSessions.get(sessionID)?.lastCoderDelegationTaskId ?? null : null;
|
|
51098
51217
|
if (sessionID && isCoderDelegation && currentTaskId) {
|
|
51099
51218
|
const session = ensureAgentSession(sessionID);
|
|
51100
51219
|
session.lastCoderDelegationTaskId = currentTaskId;
|
|
@@ -54872,7 +54991,11 @@ function deserializeAgentSession(s) {
|
|
|
54872
54991
|
lastScopeViolation: null,
|
|
54873
54992
|
scopeViolationDetected: s.scopeViolationDetected,
|
|
54874
54993
|
modifiedFilesThisCoderTask: [],
|
|
54875
|
-
pendingAdvisoryMessages: s.pendingAdvisoryMessages ?? []
|
|
54994
|
+
pendingAdvisoryMessages: s.pendingAdvisoryMessages ?? [],
|
|
54995
|
+
model_fallback_index: s.model_fallback_index ?? 0,
|
|
54996
|
+
modelFallbackExhausted: s.modelFallbackExhausted ?? false,
|
|
54997
|
+
coderRevisions: s.coderRevisions ?? 0,
|
|
54998
|
+
revisionLimitHit: s.revisionLimitHit ?? false
|
|
54876
54999
|
};
|
|
54877
55000
|
}
|
|
54878
55001
|
async function readSnapshot(directory) {
|
|
@@ -54888,7 +55011,7 @@ async function readSnapshot(directory) {
|
|
|
54888
55011
|
return;
|
|
54889
55012
|
return value;
|
|
54890
55013
|
});
|
|
54891
|
-
if (parsed.version !== 1) {
|
|
55014
|
+
if (parsed.version !== 1 && parsed.version !== 2) {
|
|
54892
55015
|
return null;
|
|
54893
55016
|
}
|
|
54894
55017
|
return parsed;
|
|
@@ -55115,6 +55238,7 @@ var build_check = createSwarmTool({
|
|
|
55115
55238
|
});
|
|
55116
55239
|
// src/tools/check-gate-status.ts
|
|
55117
55240
|
init_dist();
|
|
55241
|
+
init_manager();
|
|
55118
55242
|
init_create_tool();
|
|
55119
55243
|
import * as fs27 from "fs";
|
|
55120
55244
|
import * as path39 from "path";
|
|
@@ -55238,13 +55362,37 @@ var check_gate_status = createSwarmTool({
|
|
|
55238
55362
|
missingGates.push(requiredGate);
|
|
55239
55363
|
}
|
|
55240
55364
|
}
|
|
55241
|
-
|
|
55365
|
+
let status = missingGates.length === 0 ? "all_passed" : "incomplete";
|
|
55242
55366
|
let message;
|
|
55243
55367
|
if (status === "all_passed") {
|
|
55244
55368
|
message = `All required gates have passed for task "${taskIdInput}".`;
|
|
55245
55369
|
} else {
|
|
55246
55370
|
message = `Task "${taskIdInput}" is incomplete. Missing gates: ${missingGates.join(", ")}.`;
|
|
55247
55371
|
}
|
|
55372
|
+
let secretscanVerdict = "not_run";
|
|
55373
|
+
try {
|
|
55374
|
+
const evidenceResult = await loadEvidence(directory, taskIdInput);
|
|
55375
|
+
if (evidenceResult.status === "found") {
|
|
55376
|
+
const secretscanEntries = evidenceResult.bundle.entries.filter((entry) => entry.type === "secretscan");
|
|
55377
|
+
if (secretscanEntries.length > 0) {
|
|
55378
|
+
const lastSecretscan = secretscanEntries[secretscanEntries.length - 1];
|
|
55379
|
+
if (isSecretscanEvidence(lastSecretscan)) {
|
|
55380
|
+
if (lastSecretscan.verdict === "fail" || lastSecretscan.verdict === "rejected") {
|
|
55381
|
+
secretscanVerdict = "fail";
|
|
55382
|
+
missingGates.push("secretscan (BLOCKED \u2014 secrets detected)");
|
|
55383
|
+
if (status === "all_passed") {
|
|
55384
|
+
status = "incomplete";
|
|
55385
|
+
}
|
|
55386
|
+
message = `BLOCKED: Secretscan found secrets in prior scan. ${message}`;
|
|
55387
|
+
} else if (lastSecretscan.verdict === "pass" || lastSecretscan.verdict === "approved" || lastSecretscan.verdict === "info") {
|
|
55388
|
+
secretscanVerdict = "pass";
|
|
55389
|
+
}
|
|
55390
|
+
}
|
|
55391
|
+
} else {
|
|
55392
|
+
message += " Advisory: No secretscan evidence found for this task. Consider running secretscan.";
|
|
55393
|
+
}
|
|
55394
|
+
}
|
|
55395
|
+
} catch {}
|
|
55248
55396
|
const todoScan = evidenceData.todo_scan;
|
|
55249
55397
|
const result = {
|
|
55250
55398
|
taskId: taskIdInput,
|
|
@@ -55254,7 +55402,8 @@ var check_gate_status = createSwarmTool({
|
|
|
55254
55402
|
missing_gates: missingGates,
|
|
55255
55403
|
gates: gatesMap,
|
|
55256
55404
|
message,
|
|
55257
|
-
todo_scan: todoScan ?? null
|
|
55405
|
+
todo_scan: todoScan ?? null,
|
|
55406
|
+
secretscan_verdict: secretscanVerdict
|
|
55258
55407
|
};
|
|
55259
55408
|
return JSON.stringify(result, null, 2);
|
|
55260
55409
|
}
|
|
@@ -55980,6 +56129,391 @@ var diff = createSwarmTool({
|
|
|
55980
56129
|
}
|
|
55981
56130
|
}
|
|
55982
56131
|
});
|
|
56132
|
+
// src/tools/doc-scan.ts
|
|
56133
|
+
init_dist();
|
|
56134
|
+
init_schema();
|
|
56135
|
+
import * as crypto4 from "crypto";
|
|
56136
|
+
import * as fs30 from "fs";
|
|
56137
|
+
import { mkdir as mkdir5, readFile as readFile6, writeFile as writeFile5 } from "fs/promises";
|
|
56138
|
+
import * as path42 from "path";
|
|
56139
|
+
init_create_tool();
|
|
56140
|
+
var SKIP_DIRECTORIES2 = new Set([
|
|
56141
|
+
"node_modules",
|
|
56142
|
+
".git",
|
|
56143
|
+
".swarm",
|
|
56144
|
+
"dist",
|
|
56145
|
+
"build",
|
|
56146
|
+
".next",
|
|
56147
|
+
"vendor"
|
|
56148
|
+
]);
|
|
56149
|
+
var SKIP_PATTERNS = [/\.test\./, /\.spec\./, /\.d\.ts$/];
|
|
56150
|
+
var MAX_SUMMARY_LENGTH = 200;
|
|
56151
|
+
var MAX_INDEXED_FILES = 100;
|
|
56152
|
+
var READ_LINES_LIMIT = 30;
|
|
56153
|
+
var MIN_LESSON_LENGTH = 15;
|
|
56154
|
+
var MAX_CONSTRAINTS_PER_DOC = 5;
|
|
56155
|
+
var MAX_CONSTRAINT_LENGTH = 200;
|
|
56156
|
+
var RELEVANCE_THRESHOLD = 0.1;
|
|
56157
|
+
var DEDUP_THRESHOLD = 0.6;
|
|
56158
|
+
function normalizeSeparators(filePath) {
|
|
56159
|
+
return filePath.replace(/\\/g, "/");
|
|
56160
|
+
}
|
|
56161
|
+
function matchesDocPattern(filePath, patterns) {
|
|
56162
|
+
const normalizedPath = normalizeSeparators(filePath);
|
|
56163
|
+
const basename5 = path42.basename(filePath);
|
|
56164
|
+
for (const pattern of patterns) {
|
|
56165
|
+
if (!pattern.includes("/") && !pattern.includes("\\")) {
|
|
56166
|
+
if (basename5 === pattern) {
|
|
56167
|
+
return true;
|
|
56168
|
+
}
|
|
56169
|
+
continue;
|
|
56170
|
+
}
|
|
56171
|
+
if (pattern.startsWith("**/")) {
|
|
56172
|
+
const filenamePattern = pattern.slice(3);
|
|
56173
|
+
if (basename5 === filenamePattern) {
|
|
56174
|
+
return true;
|
|
56175
|
+
}
|
|
56176
|
+
continue;
|
|
56177
|
+
}
|
|
56178
|
+
const patternNormalized = normalizeSeparators(pattern);
|
|
56179
|
+
const dirPrefix = patternNormalized.replace(/\/\*\*.*$/, "").replace(/\/\*.*$/, "");
|
|
56180
|
+
if (normalizedPath.startsWith(dirPrefix + "/") || normalizedPath === dirPrefix) {
|
|
56181
|
+
return true;
|
|
56182
|
+
}
|
|
56183
|
+
}
|
|
56184
|
+
return false;
|
|
56185
|
+
}
|
|
56186
|
+
function extractTitleAndSummary(content, filename) {
|
|
56187
|
+
const lines = content.split(`
|
|
56188
|
+
`);
|
|
56189
|
+
let title = filename;
|
|
56190
|
+
let summary = "";
|
|
56191
|
+
let foundTitle = false;
|
|
56192
|
+
const potentialSummaryLines = [];
|
|
56193
|
+
for (let i2 = 0;i2 < lines.length && i2 < READ_LINES_LIMIT; i2++) {
|
|
56194
|
+
const line = lines[i2].trim();
|
|
56195
|
+
if (!foundTitle && line.startsWith("# ")) {
|
|
56196
|
+
title = line.slice(2).trim();
|
|
56197
|
+
foundTitle = true;
|
|
56198
|
+
continue;
|
|
56199
|
+
}
|
|
56200
|
+
if (line && !line.startsWith("#")) {
|
|
56201
|
+
potentialSummaryLines.push(line);
|
|
56202
|
+
}
|
|
56203
|
+
}
|
|
56204
|
+
for (const line of potentialSummaryLines) {
|
|
56205
|
+
summary += (summary ? " " : "") + line;
|
|
56206
|
+
if (summary.length >= MAX_SUMMARY_LENGTH) {
|
|
56207
|
+
break;
|
|
56208
|
+
}
|
|
56209
|
+
}
|
|
56210
|
+
if (summary.length > MAX_SUMMARY_LENGTH) {
|
|
56211
|
+
summary = summary.slice(0, MAX_SUMMARY_LENGTH - 3) + "...";
|
|
56212
|
+
}
|
|
56213
|
+
return { title, summary };
|
|
56214
|
+
}
|
|
56215
|
+
function stripMarkdown(text) {
|
|
56216
|
+
return text.replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/\*\*([^*]+)\*\*/g, "$1").replace(/`([^`]+)`/g, "$1").replace(/^\s*[-*\u2022]\s+/gm, "").replace(/^\s*\d+\.\s+/gm, "").trim();
|
|
56217
|
+
}
|
|
56218
|
+
async function scanDocIndex(directory) {
|
|
56219
|
+
const manifestPath = path42.join(directory, ".swarm", "doc-manifest.json");
|
|
56220
|
+
const defaultPatterns = DocsConfigSchema.parse({}).doc_patterns;
|
|
56221
|
+
const extraPatterns = [
|
|
56222
|
+
"ARCHITECTURE.md",
|
|
56223
|
+
"CLAUDE.md",
|
|
56224
|
+
"AGENTS.md",
|
|
56225
|
+
".github/*.md",
|
|
56226
|
+
"doc/**/*.md"
|
|
56227
|
+
];
|
|
56228
|
+
const allPatterns = [...defaultPatterns, ...extraPatterns];
|
|
56229
|
+
try {
|
|
56230
|
+
const manifestContent = await readFile6(manifestPath, "utf-8");
|
|
56231
|
+
const existingManifest = JSON.parse(manifestContent);
|
|
56232
|
+
if (existingManifest.schema_version === 1 && existingManifest.files) {
|
|
56233
|
+
let cacheValid = true;
|
|
56234
|
+
for (const file3 of existingManifest.files) {
|
|
56235
|
+
try {
|
|
56236
|
+
const fullPath = path42.join(directory, file3.path);
|
|
56237
|
+
const stat2 = fs30.statSync(fullPath);
|
|
56238
|
+
if (stat2.mtimeMs > new Date(existingManifest.scanned_at).getTime()) {
|
|
56239
|
+
cacheValid = false;
|
|
56240
|
+
break;
|
|
56241
|
+
}
|
|
56242
|
+
} catch {
|
|
56243
|
+
cacheValid = false;
|
|
56244
|
+
break;
|
|
56245
|
+
}
|
|
56246
|
+
}
|
|
56247
|
+
if (cacheValid) {
|
|
56248
|
+
return { manifest: existingManifest, cached: true };
|
|
56249
|
+
}
|
|
56250
|
+
}
|
|
56251
|
+
} catch {}
|
|
56252
|
+
const discoveredFiles = [];
|
|
56253
|
+
let rawEntries;
|
|
56254
|
+
try {
|
|
56255
|
+
rawEntries = fs30.readdirSync(directory, { recursive: true });
|
|
56256
|
+
} catch {
|
|
56257
|
+
const manifest2 = {
|
|
56258
|
+
schema_version: 1,
|
|
56259
|
+
scanned_at: new Date().toISOString(),
|
|
56260
|
+
files: []
|
|
56261
|
+
};
|
|
56262
|
+
return { manifest: manifest2, cached: false };
|
|
56263
|
+
}
|
|
56264
|
+
const entries = rawEntries.filter((e) => typeof e === "string");
|
|
56265
|
+
for (const entry of entries) {
|
|
56266
|
+
const fullPath = path42.join(directory, entry);
|
|
56267
|
+
let stat2;
|
|
56268
|
+
try {
|
|
56269
|
+
stat2 = fs30.statSync(fullPath);
|
|
56270
|
+
} catch {
|
|
56271
|
+
continue;
|
|
56272
|
+
}
|
|
56273
|
+
if (!stat2.isFile())
|
|
56274
|
+
continue;
|
|
56275
|
+
const pathParts = normalizeSeparators(entry).split("/");
|
|
56276
|
+
let skipThisFile = false;
|
|
56277
|
+
for (const part of pathParts) {
|
|
56278
|
+
if (SKIP_DIRECTORIES2.has(part)) {
|
|
56279
|
+
skipThisFile = true;
|
|
56280
|
+
break;
|
|
56281
|
+
}
|
|
56282
|
+
}
|
|
56283
|
+
if (skipThisFile)
|
|
56284
|
+
continue;
|
|
56285
|
+
for (const pattern of SKIP_PATTERNS) {
|
|
56286
|
+
if (pattern.test(entry)) {
|
|
56287
|
+
skipThisFile = true;
|
|
56288
|
+
break;
|
|
56289
|
+
}
|
|
56290
|
+
}
|
|
56291
|
+
if (skipThisFile)
|
|
56292
|
+
continue;
|
|
56293
|
+
if (!matchesDocPattern(entry, allPatterns)) {
|
|
56294
|
+
continue;
|
|
56295
|
+
}
|
|
56296
|
+
let content;
|
|
56297
|
+
try {
|
|
56298
|
+
content = fs30.readFileSync(fullPath, "utf-8");
|
|
56299
|
+
} catch {
|
|
56300
|
+
continue;
|
|
56301
|
+
}
|
|
56302
|
+
const { title, summary } = extractTitleAndSummary(content, path42.basename(entry));
|
|
56303
|
+
const lineCount = content.split(`
|
|
56304
|
+
`).length;
|
|
56305
|
+
discoveredFiles.push({
|
|
56306
|
+
path: entry,
|
|
56307
|
+
title,
|
|
56308
|
+
summary,
|
|
56309
|
+
lines: lineCount,
|
|
56310
|
+
mtime: stat2.mtimeMs
|
|
56311
|
+
});
|
|
56312
|
+
}
|
|
56313
|
+
discoveredFiles.sort((a, b) => a.path.toLowerCase().localeCompare(b.path.toLowerCase()));
|
|
56314
|
+
let truncated = false;
|
|
56315
|
+
if (discoveredFiles.length > MAX_INDEXED_FILES) {
|
|
56316
|
+
discoveredFiles.splice(MAX_INDEXED_FILES);
|
|
56317
|
+
truncated = true;
|
|
56318
|
+
}
|
|
56319
|
+
if (truncated && discoveredFiles.length > 0) {
|
|
56320
|
+
discoveredFiles[0].summary = `[Warning: ${MAX_INDEXED_FILES}+ docs found, listing first ${MAX_INDEXED_FILES}] ` + discoveredFiles[0].summary;
|
|
56321
|
+
}
|
|
56322
|
+
const manifest = {
|
|
56323
|
+
schema_version: 1,
|
|
56324
|
+
scanned_at: new Date().toISOString(),
|
|
56325
|
+
files: discoveredFiles
|
|
56326
|
+
};
|
|
56327
|
+
try {
|
|
56328
|
+
await mkdir5(path42.dirname(manifestPath), { recursive: true });
|
|
56329
|
+
await writeFile5(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
|
|
56330
|
+
} catch {}
|
|
56331
|
+
return { manifest, cached: false };
|
|
56332
|
+
}
|
|
56333
|
+
var CONSTRAINT_PATTERNS = [
|
|
56334
|
+
/\bMUST\b/,
|
|
56335
|
+
/\bMUST NOT\b/,
|
|
56336
|
+
/\bSHOULD\b/,
|
|
56337
|
+
/\bSHOULD NOT\b/,
|
|
56338
|
+
/\bDO NOT\b/,
|
|
56339
|
+
/\bALWAYS\b/,
|
|
56340
|
+
/\bNEVER\b/,
|
|
56341
|
+
/\bREQUIRED\b/
|
|
56342
|
+
];
|
|
56343
|
+
var ACTION_WORDS = /\b(must|should|don't|avoid|ensure|use|follow)\b/i;
|
|
56344
|
+
function isConstraintLine(line) {
|
|
56345
|
+
const upperLine = line.toUpperCase();
|
|
56346
|
+
for (const pattern of CONSTRAINT_PATTERNS) {
|
|
56347
|
+
if (pattern.test(upperLine)) {
|
|
56348
|
+
return true;
|
|
56349
|
+
}
|
|
56350
|
+
}
|
|
56351
|
+
if (/^\s*[-*\u2022]/.test(line) && ACTION_WORDS.test(line)) {
|
|
56352
|
+
return true;
|
|
56353
|
+
}
|
|
56354
|
+
return false;
|
|
56355
|
+
}
|
|
56356
|
+
function extractConstraintsFromContent(content) {
|
|
56357
|
+
const lines = content.split(`
|
|
56358
|
+
`);
|
|
56359
|
+
const constraints = [];
|
|
56360
|
+
for (const line of lines) {
|
|
56361
|
+
if (constraints.length >= MAX_CONSTRAINTS_PER_DOC) {
|
|
56362
|
+
break;
|
|
56363
|
+
}
|
|
56364
|
+
const trimmed = line.trim();
|
|
56365
|
+
if (!trimmed)
|
|
56366
|
+
continue;
|
|
56367
|
+
if (isConstraintLine(trimmed)) {
|
|
56368
|
+
const cleaned = stripMarkdown(trimmed);
|
|
56369
|
+
const len = cleaned.length;
|
|
56370
|
+
if (len >= MIN_LESSON_LENGTH && len <= MAX_CONSTRAINT_LENGTH) {
|
|
56371
|
+
constraints.push(cleaned);
|
|
56372
|
+
}
|
|
56373
|
+
}
|
|
56374
|
+
}
|
|
56375
|
+
return constraints;
|
|
56376
|
+
}
|
|
56377
|
+
async function extractDocConstraints(directory, taskFiles, taskDescription) {
|
|
56378
|
+
const manifestPath = path42.join(directory, ".swarm", "doc-manifest.json");
|
|
56379
|
+
let manifest;
|
|
56380
|
+
try {
|
|
56381
|
+
const content = await readFile6(manifestPath, "utf-8");
|
|
56382
|
+
manifest = JSON.parse(content);
|
|
56383
|
+
} catch {
|
|
56384
|
+
const result = await scanDocIndex(directory);
|
|
56385
|
+
manifest = result.manifest;
|
|
56386
|
+
}
|
|
56387
|
+
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
56388
|
+
const existingEntries = await readKnowledge(knowledgePath);
|
|
56389
|
+
const taskContext = [...taskFiles, taskDescription].join(" ");
|
|
56390
|
+
const taskBigrams = wordBigrams(normalize2(taskContext));
|
|
56391
|
+
let extractedCount = 0;
|
|
56392
|
+
let skippedCount = 0;
|
|
56393
|
+
const details = [];
|
|
56394
|
+
for (const docFile of manifest.files) {
|
|
56395
|
+
const docContext = `${docFile.path} ${docFile.title} ${docFile.summary}`;
|
|
56396
|
+
const docBigrams = wordBigrams(normalize2(docContext));
|
|
56397
|
+
const score = jaccardBigram(taskBigrams, docBigrams);
|
|
56398
|
+
if (score <= RELEVANCE_THRESHOLD) {
|
|
56399
|
+
skippedCount++;
|
|
56400
|
+
continue;
|
|
56401
|
+
}
|
|
56402
|
+
let fullContent;
|
|
56403
|
+
try {
|
|
56404
|
+
fullContent = await readFile6(path42.join(directory, docFile.path), "utf-8");
|
|
56405
|
+
} catch {
|
|
56406
|
+
skippedCount++;
|
|
56407
|
+
continue;
|
|
56408
|
+
}
|
|
56409
|
+
const constraints = extractConstraintsFromContent(fullContent);
|
|
56410
|
+
if (constraints.length === 0) {
|
|
56411
|
+
skippedCount++;
|
|
56412
|
+
continue;
|
|
56413
|
+
}
|
|
56414
|
+
const docDetails = {
|
|
56415
|
+
path: docFile.path,
|
|
56416
|
+
score,
|
|
56417
|
+
constraints: []
|
|
56418
|
+
};
|
|
56419
|
+
for (const constraint of constraints) {
|
|
56420
|
+
const duplicate = findNearDuplicate(constraint, existingEntries, DEDUP_THRESHOLD);
|
|
56421
|
+
if (!duplicate) {
|
|
56422
|
+
const entry = {
|
|
56423
|
+
id: crypto4.randomUUID(),
|
|
56424
|
+
tier: "swarm",
|
|
56425
|
+
lesson: constraint,
|
|
56426
|
+
category: "architecture",
|
|
56427
|
+
tags: ["doc-scan", path42.basename(docFile.path)],
|
|
56428
|
+
scope: "global",
|
|
56429
|
+
confidence: 0.5,
|
|
56430
|
+
status: "candidate",
|
|
56431
|
+
confirmed_by: [],
|
|
56432
|
+
project_name: "",
|
|
56433
|
+
retrieval_outcomes: {
|
|
56434
|
+
applied_count: 0,
|
|
56435
|
+
succeeded_after_count: 0,
|
|
56436
|
+
failed_after_count: 0
|
|
56437
|
+
},
|
|
56438
|
+
schema_version: 1,
|
|
56439
|
+
created_at: new Date().toISOString(),
|
|
56440
|
+
updated_at: new Date().toISOString(),
|
|
56441
|
+
auto_generated: true,
|
|
56442
|
+
hive_eligible: false
|
|
56443
|
+
};
|
|
56444
|
+
await appendKnowledge(knowledgePath, entry);
|
|
56445
|
+
existingEntries.push(entry);
|
|
56446
|
+
extractedCount++;
|
|
56447
|
+
docDetails.constraints.push(constraint);
|
|
56448
|
+
}
|
|
56449
|
+
}
|
|
56450
|
+
if (docDetails.constraints.length > 0) {
|
|
56451
|
+
details.push(docDetails);
|
|
56452
|
+
} else {
|
|
56453
|
+
skippedCount++;
|
|
56454
|
+
}
|
|
56455
|
+
}
|
|
56456
|
+
return { extracted: extractedCount, skipped: skippedCount, details };
|
|
56457
|
+
}
|
|
56458
|
+
var doc_scan = createSwarmTool({
|
|
56459
|
+
description: "Scan project documentation files and build an index manifest. Caches results in .swarm/doc-manifest.json for fast subsequent scans.",
|
|
56460
|
+
args: {
|
|
56461
|
+
force: tool.schema.boolean().optional().describe("Force re-scan even if cache is valid")
|
|
56462
|
+
},
|
|
56463
|
+
execute: async (args2, directory) => {
|
|
56464
|
+
let force = false;
|
|
56465
|
+
try {
|
|
56466
|
+
if (args2 && typeof args2 === "object") {
|
|
56467
|
+
const obj = args2;
|
|
56468
|
+
if (obj.force === true)
|
|
56469
|
+
force = true;
|
|
56470
|
+
}
|
|
56471
|
+
} catch {}
|
|
56472
|
+
if (force) {
|
|
56473
|
+
const manifestPath = path42.join(directory, ".swarm", "doc-manifest.json");
|
|
56474
|
+
try {
|
|
56475
|
+
fs30.unlinkSync(manifestPath);
|
|
56476
|
+
} catch {}
|
|
56477
|
+
}
|
|
56478
|
+
const { manifest, cached: cached3 } = await scanDocIndex(directory);
|
|
56479
|
+
return JSON.stringify({
|
|
56480
|
+
success: true,
|
|
56481
|
+
files_count: manifest.files.length,
|
|
56482
|
+
cached: cached3,
|
|
56483
|
+
manifest
|
|
56484
|
+
}, null, 2);
|
|
56485
|
+
}
|
|
56486
|
+
});
|
|
56487
|
+
var doc_extract = createSwarmTool({
|
|
56488
|
+
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.",
|
|
56489
|
+
args: {
|
|
56490
|
+
task_files: tool.schema.array(tool.schema.string()).describe("List of file paths involved in the current task"),
|
|
56491
|
+
task_description: tool.schema.string().describe("Description of the current task")
|
|
56492
|
+
},
|
|
56493
|
+
execute: async (args2, directory) => {
|
|
56494
|
+
let taskFiles = [];
|
|
56495
|
+
let taskDescription = "";
|
|
56496
|
+
try {
|
|
56497
|
+
if (args2 && typeof args2 === "object") {
|
|
56498
|
+
const obj = args2;
|
|
56499
|
+
if (Array.isArray(obj.task_files)) {
|
|
56500
|
+
taskFiles = obj.task_files.filter((f) => typeof f === "string");
|
|
56501
|
+
}
|
|
56502
|
+
if (typeof obj.task_description === "string") {
|
|
56503
|
+
taskDescription = obj.task_description;
|
|
56504
|
+
}
|
|
56505
|
+
}
|
|
56506
|
+
} catch {}
|
|
56507
|
+
if (taskFiles.length === 0 && !taskDescription) {
|
|
56508
|
+
return JSON.stringify({
|
|
56509
|
+
success: false,
|
|
56510
|
+
error: "task_files or task_description is required"
|
|
56511
|
+
});
|
|
56512
|
+
}
|
|
56513
|
+
const result = await extractDocConstraints(directory, taskFiles, taskDescription);
|
|
56514
|
+
return JSON.stringify({ success: true, ...result }, null, 2);
|
|
56515
|
+
}
|
|
56516
|
+
});
|
|
55983
56517
|
// src/tools/domain-detector.ts
|
|
55984
56518
|
init_tool();
|
|
55985
56519
|
var DOMAIN_PATTERNS = {
|
|
@@ -56163,8 +56697,8 @@ Use these as DOMAIN values when delegating to @sme.`;
|
|
|
56163
56697
|
// src/tools/evidence-check.ts
|
|
56164
56698
|
init_dist();
|
|
56165
56699
|
init_create_tool();
|
|
56166
|
-
import * as
|
|
56167
|
-
import * as
|
|
56700
|
+
import * as fs31 from "fs";
|
|
56701
|
+
import * as path43 from "path";
|
|
56168
56702
|
var MAX_FILE_SIZE_BYTES3 = 1024 * 1024;
|
|
56169
56703
|
var MAX_EVIDENCE_FILES = 1000;
|
|
56170
56704
|
var EVIDENCE_DIR2 = ".swarm/evidence";
|
|
@@ -56194,9 +56728,9 @@ function validateRequiredTypes(input) {
|
|
|
56194
56728
|
return null;
|
|
56195
56729
|
}
|
|
56196
56730
|
function isPathWithinSwarm2(filePath, cwd) {
|
|
56197
|
-
const normalizedCwd =
|
|
56198
|
-
const swarmPath =
|
|
56199
|
-
const normalizedPath =
|
|
56731
|
+
const normalizedCwd = path43.resolve(cwd);
|
|
56732
|
+
const swarmPath = path43.join(normalizedCwd, ".swarm");
|
|
56733
|
+
const normalizedPath = path43.resolve(filePath);
|
|
56200
56734
|
return normalizedPath.startsWith(swarmPath);
|
|
56201
56735
|
}
|
|
56202
56736
|
function parseCompletedTasks(planContent) {
|
|
@@ -56212,12 +56746,12 @@ function parseCompletedTasks(planContent) {
|
|
|
56212
56746
|
}
|
|
56213
56747
|
function readEvidenceFiles(evidenceDir, _cwd) {
|
|
56214
56748
|
const evidence = [];
|
|
56215
|
-
if (!
|
|
56749
|
+
if (!fs31.existsSync(evidenceDir) || !fs31.statSync(evidenceDir).isDirectory()) {
|
|
56216
56750
|
return evidence;
|
|
56217
56751
|
}
|
|
56218
56752
|
let files;
|
|
56219
56753
|
try {
|
|
56220
|
-
files =
|
|
56754
|
+
files = fs31.readdirSync(evidenceDir);
|
|
56221
56755
|
} catch {
|
|
56222
56756
|
return evidence;
|
|
56223
56757
|
}
|
|
@@ -56226,14 +56760,14 @@ function readEvidenceFiles(evidenceDir, _cwd) {
|
|
|
56226
56760
|
if (!VALID_EVIDENCE_FILENAME_REGEX.test(filename)) {
|
|
56227
56761
|
continue;
|
|
56228
56762
|
}
|
|
56229
|
-
const filePath =
|
|
56763
|
+
const filePath = path43.join(evidenceDir, filename);
|
|
56230
56764
|
try {
|
|
56231
|
-
const resolvedPath =
|
|
56232
|
-
const evidenceDirResolved =
|
|
56765
|
+
const resolvedPath = path43.resolve(filePath);
|
|
56766
|
+
const evidenceDirResolved = path43.resolve(evidenceDir);
|
|
56233
56767
|
if (!resolvedPath.startsWith(evidenceDirResolved)) {
|
|
56234
56768
|
continue;
|
|
56235
56769
|
}
|
|
56236
|
-
const stat2 =
|
|
56770
|
+
const stat2 = fs31.lstatSync(filePath);
|
|
56237
56771
|
if (!stat2.isFile()) {
|
|
56238
56772
|
continue;
|
|
56239
56773
|
}
|
|
@@ -56242,7 +56776,7 @@ function readEvidenceFiles(evidenceDir, _cwd) {
|
|
|
56242
56776
|
}
|
|
56243
56777
|
let fileStat;
|
|
56244
56778
|
try {
|
|
56245
|
-
fileStat =
|
|
56779
|
+
fileStat = fs31.statSync(filePath);
|
|
56246
56780
|
if (fileStat.size > MAX_FILE_SIZE_BYTES3) {
|
|
56247
56781
|
continue;
|
|
56248
56782
|
}
|
|
@@ -56251,7 +56785,7 @@ function readEvidenceFiles(evidenceDir, _cwd) {
|
|
|
56251
56785
|
}
|
|
56252
56786
|
let content;
|
|
56253
56787
|
try {
|
|
56254
|
-
content =
|
|
56788
|
+
content = fs31.readFileSync(filePath, "utf-8");
|
|
56255
56789
|
} catch {
|
|
56256
56790
|
continue;
|
|
56257
56791
|
}
|
|
@@ -56347,7 +56881,7 @@ var evidence_check = createSwarmTool({
|
|
|
56347
56881
|
return JSON.stringify(errorResult, null, 2);
|
|
56348
56882
|
}
|
|
56349
56883
|
const requiredTypes = requiredTypesValue.split(",").map((t) => t.trim()).filter((t) => t.length > 0).map(normalizeEvidenceType);
|
|
56350
|
-
const planPath =
|
|
56884
|
+
const planPath = path43.join(cwd, PLAN_FILE);
|
|
56351
56885
|
if (!isPathWithinSwarm2(planPath, cwd)) {
|
|
56352
56886
|
const errorResult = {
|
|
56353
56887
|
error: "plan file path validation failed",
|
|
@@ -56361,7 +56895,7 @@ var evidence_check = createSwarmTool({
|
|
|
56361
56895
|
}
|
|
56362
56896
|
let planContent;
|
|
56363
56897
|
try {
|
|
56364
|
-
planContent =
|
|
56898
|
+
planContent = fs31.readFileSync(planPath, "utf-8");
|
|
56365
56899
|
} catch {
|
|
56366
56900
|
const result2 = {
|
|
56367
56901
|
message: "No completed tasks found in plan.",
|
|
@@ -56379,7 +56913,7 @@ var evidence_check = createSwarmTool({
|
|
|
56379
56913
|
};
|
|
56380
56914
|
return JSON.stringify(result2, null, 2);
|
|
56381
56915
|
}
|
|
56382
|
-
const evidenceDir =
|
|
56916
|
+
const evidenceDir = path43.join(cwd, EVIDENCE_DIR2);
|
|
56383
56917
|
const evidence = readEvidenceFiles(evidenceDir, cwd);
|
|
56384
56918
|
const { tasksWithFullEvidence, gaps } = analyzeGaps(completedTasks, evidence, requiredTypes);
|
|
56385
56919
|
const completeness = completedTasks.length > 0 ? Math.round(tasksWithFullEvidence.length / completedTasks.length * 100) / 100 : 1;
|
|
@@ -56396,8 +56930,8 @@ var evidence_check = createSwarmTool({
|
|
|
56396
56930
|
// src/tools/file-extractor.ts
|
|
56397
56931
|
init_tool();
|
|
56398
56932
|
init_create_tool();
|
|
56399
|
-
import * as
|
|
56400
|
-
import * as
|
|
56933
|
+
import * as fs32 from "fs";
|
|
56934
|
+
import * as path44 from "path";
|
|
56401
56935
|
var EXT_MAP = {
|
|
56402
56936
|
python: ".py",
|
|
56403
56937
|
py: ".py",
|
|
@@ -56459,8 +56993,8 @@ var extract_code_blocks = createSwarmTool({
|
|
|
56459
56993
|
execute: async (args2, directory) => {
|
|
56460
56994
|
const { content, output_dir, prefix } = args2;
|
|
56461
56995
|
const targetDir = output_dir || directory;
|
|
56462
|
-
if (!
|
|
56463
|
-
|
|
56996
|
+
if (!fs32.existsSync(targetDir)) {
|
|
56997
|
+
fs32.mkdirSync(targetDir, { recursive: true });
|
|
56464
56998
|
}
|
|
56465
56999
|
if (!content) {
|
|
56466
57000
|
return "Error: content is required";
|
|
@@ -56478,16 +57012,16 @@ var extract_code_blocks = createSwarmTool({
|
|
|
56478
57012
|
if (prefix) {
|
|
56479
57013
|
filename = `${prefix}_${filename}`;
|
|
56480
57014
|
}
|
|
56481
|
-
let filepath =
|
|
56482
|
-
const base =
|
|
56483
|
-
const ext =
|
|
57015
|
+
let filepath = path44.join(targetDir, filename);
|
|
57016
|
+
const base = path44.basename(filepath, path44.extname(filepath));
|
|
57017
|
+
const ext = path44.extname(filepath);
|
|
56484
57018
|
let counter = 1;
|
|
56485
|
-
while (
|
|
56486
|
-
filepath =
|
|
57019
|
+
while (fs32.existsSync(filepath)) {
|
|
57020
|
+
filepath = path44.join(targetDir, `${base}_${counter}${ext}`);
|
|
56487
57021
|
counter++;
|
|
56488
57022
|
}
|
|
56489
57023
|
try {
|
|
56490
|
-
|
|
57024
|
+
fs32.writeFileSync(filepath, code.trim(), "utf-8");
|
|
56491
57025
|
savedFiles.push(filepath);
|
|
56492
57026
|
} catch (error93) {
|
|
56493
57027
|
errors5.push(`Failed to save ${filename}: ${error93 instanceof Error ? error93.message : String(error93)}`);
|
|
@@ -56603,8 +57137,8 @@ var gitingest = createSwarmTool({
|
|
|
56603
57137
|
// src/tools/imports.ts
|
|
56604
57138
|
init_dist();
|
|
56605
57139
|
init_create_tool();
|
|
56606
|
-
import * as
|
|
56607
|
-
import * as
|
|
57140
|
+
import * as fs33 from "fs";
|
|
57141
|
+
import * as path45 from "path";
|
|
56608
57142
|
var MAX_FILE_PATH_LENGTH2 = 500;
|
|
56609
57143
|
var MAX_SYMBOL_LENGTH = 256;
|
|
56610
57144
|
var MAX_FILE_SIZE_BYTES4 = 1024 * 1024;
|
|
@@ -56658,7 +57192,7 @@ function validateSymbolInput(symbol3) {
|
|
|
56658
57192
|
return null;
|
|
56659
57193
|
}
|
|
56660
57194
|
function isBinaryFile2(filePath, buffer) {
|
|
56661
|
-
const ext =
|
|
57195
|
+
const ext = path45.extname(filePath).toLowerCase();
|
|
56662
57196
|
if (ext === ".json" || ext === ".md" || ext === ".txt") {
|
|
56663
57197
|
return false;
|
|
56664
57198
|
}
|
|
@@ -56682,15 +57216,15 @@ function parseImports(content, targetFile, targetSymbol) {
|
|
|
56682
57216
|
const imports = [];
|
|
56683
57217
|
let _resolvedTarget;
|
|
56684
57218
|
try {
|
|
56685
|
-
_resolvedTarget =
|
|
57219
|
+
_resolvedTarget = path45.resolve(targetFile);
|
|
56686
57220
|
} catch {
|
|
56687
57221
|
_resolvedTarget = targetFile;
|
|
56688
57222
|
}
|
|
56689
|
-
const targetBasename =
|
|
57223
|
+
const targetBasename = path45.basename(targetFile, path45.extname(targetFile));
|
|
56690
57224
|
const targetWithExt = targetFile;
|
|
56691
57225
|
const targetWithoutExt = targetFile.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
|
|
56692
|
-
const normalizedTargetWithExt =
|
|
56693
|
-
const normalizedTargetWithoutExt =
|
|
57226
|
+
const normalizedTargetWithExt = path45.normalize(targetWithExt).replace(/\\/g, "/");
|
|
57227
|
+
const normalizedTargetWithoutExt = path45.normalize(targetWithoutExt).replace(/\\/g, "/");
|
|
56694
57228
|
const importRegex = /import\s+(?:\{[\s\S]*?\}|(?:\*\s+as\s+\w+)|\w+)\s+from\s+['"`]([^'"`]+)['"`]|import\s+['"`]([^'"`]+)['"`]|require\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g;
|
|
56695
57229
|
for (let match = importRegex.exec(content);match !== null; match = importRegex.exec(content)) {
|
|
56696
57230
|
const modulePath = match[1] || match[2] || match[3];
|
|
@@ -56713,9 +57247,9 @@ function parseImports(content, targetFile, targetSymbol) {
|
|
|
56713
57247
|
}
|
|
56714
57248
|
const _normalizedModule = modulePath.replace(/^\.\//, "").replace(/^\.\.\\/, "../");
|
|
56715
57249
|
let isMatch = false;
|
|
56716
|
-
const _targetDir =
|
|
56717
|
-
const targetExt =
|
|
56718
|
-
const targetBasenameNoExt =
|
|
57250
|
+
const _targetDir = path45.dirname(targetFile);
|
|
57251
|
+
const targetExt = path45.extname(targetFile);
|
|
57252
|
+
const targetBasenameNoExt = path45.basename(targetFile, targetExt);
|
|
56719
57253
|
const moduleNormalized = modulePath.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
56720
57254
|
const moduleName = modulePath.split(/[/\\]/).pop() || "";
|
|
56721
57255
|
const moduleNameNoExt = moduleName.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
|
|
@@ -56755,7 +57289,7 @@ function parseImports(content, targetFile, targetSymbol) {
|
|
|
56755
57289
|
}
|
|
56756
57290
|
return imports;
|
|
56757
57291
|
}
|
|
56758
|
-
var
|
|
57292
|
+
var SKIP_DIRECTORIES3 = new Set([
|
|
56759
57293
|
"node_modules",
|
|
56760
57294
|
".git",
|
|
56761
57295
|
"dist",
|
|
@@ -56772,7 +57306,7 @@ var SKIP_DIRECTORIES2 = new Set([
|
|
|
56772
57306
|
function findSourceFiles(dir, files = [], stats = { skippedDirs: [], skippedFiles: 0, fileErrors: [] }) {
|
|
56773
57307
|
let entries;
|
|
56774
57308
|
try {
|
|
56775
|
-
entries =
|
|
57309
|
+
entries = fs33.readdirSync(dir);
|
|
56776
57310
|
} catch (e) {
|
|
56777
57311
|
stats.fileErrors.push({
|
|
56778
57312
|
path: dir,
|
|
@@ -56782,14 +57316,14 @@ function findSourceFiles(dir, files = [], stats = { skippedDirs: [], skippedFile
|
|
|
56782
57316
|
}
|
|
56783
57317
|
entries.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
|
|
56784
57318
|
for (const entry of entries) {
|
|
56785
|
-
if (
|
|
56786
|
-
stats.skippedDirs.push(
|
|
57319
|
+
if (SKIP_DIRECTORIES3.has(entry)) {
|
|
57320
|
+
stats.skippedDirs.push(path45.join(dir, entry));
|
|
56787
57321
|
continue;
|
|
56788
57322
|
}
|
|
56789
|
-
const fullPath =
|
|
57323
|
+
const fullPath = path45.join(dir, entry);
|
|
56790
57324
|
let stat2;
|
|
56791
57325
|
try {
|
|
56792
|
-
stat2 =
|
|
57326
|
+
stat2 = fs33.statSync(fullPath);
|
|
56793
57327
|
} catch (e) {
|
|
56794
57328
|
stats.fileErrors.push({
|
|
56795
57329
|
path: fullPath,
|
|
@@ -56800,7 +57334,7 @@ function findSourceFiles(dir, files = [], stats = { skippedDirs: [], skippedFile
|
|
|
56800
57334
|
if (stat2.isDirectory()) {
|
|
56801
57335
|
findSourceFiles(fullPath, files, stats);
|
|
56802
57336
|
} else if (stat2.isFile()) {
|
|
56803
|
-
const ext =
|
|
57337
|
+
const ext = path45.extname(fullPath).toLowerCase();
|
|
56804
57338
|
if (SUPPORTED_EXTENSIONS.includes(ext)) {
|
|
56805
57339
|
files.push(fullPath);
|
|
56806
57340
|
}
|
|
@@ -56857,8 +57391,8 @@ var imports = createSwarmTool({
|
|
|
56857
57391
|
return JSON.stringify(errorResult, null, 2);
|
|
56858
57392
|
}
|
|
56859
57393
|
try {
|
|
56860
|
-
const targetFile =
|
|
56861
|
-
if (!
|
|
57394
|
+
const targetFile = path45.resolve(file3);
|
|
57395
|
+
if (!fs33.existsSync(targetFile)) {
|
|
56862
57396
|
const errorResult = {
|
|
56863
57397
|
error: `target file not found: ${file3}`,
|
|
56864
57398
|
target: file3,
|
|
@@ -56868,7 +57402,7 @@ var imports = createSwarmTool({
|
|
|
56868
57402
|
};
|
|
56869
57403
|
return JSON.stringify(errorResult, null, 2);
|
|
56870
57404
|
}
|
|
56871
|
-
const targetStat =
|
|
57405
|
+
const targetStat = fs33.statSync(targetFile);
|
|
56872
57406
|
if (!targetStat.isFile()) {
|
|
56873
57407
|
const errorResult = {
|
|
56874
57408
|
error: "target must be a file, not a directory",
|
|
@@ -56879,7 +57413,7 @@ var imports = createSwarmTool({
|
|
|
56879
57413
|
};
|
|
56880
57414
|
return JSON.stringify(errorResult, null, 2);
|
|
56881
57415
|
}
|
|
56882
|
-
const baseDir =
|
|
57416
|
+
const baseDir = path45.dirname(targetFile);
|
|
56883
57417
|
const scanStats = {
|
|
56884
57418
|
skippedDirs: [],
|
|
56885
57419
|
skippedFiles: 0,
|
|
@@ -56894,12 +57428,12 @@ var imports = createSwarmTool({
|
|
|
56894
57428
|
if (consumers.length >= MAX_CONSUMERS)
|
|
56895
57429
|
break;
|
|
56896
57430
|
try {
|
|
56897
|
-
const stat2 =
|
|
57431
|
+
const stat2 = fs33.statSync(filePath);
|
|
56898
57432
|
if (stat2.size > MAX_FILE_SIZE_BYTES4) {
|
|
56899
57433
|
skippedFileCount++;
|
|
56900
57434
|
continue;
|
|
56901
57435
|
}
|
|
56902
|
-
const buffer =
|
|
57436
|
+
const buffer = fs33.readFileSync(filePath);
|
|
56903
57437
|
if (isBinaryFile2(filePath, buffer)) {
|
|
56904
57438
|
skippedFileCount++;
|
|
56905
57439
|
continue;
|
|
@@ -57448,8 +57982,8 @@ init_dist();
|
|
|
57448
57982
|
init_config();
|
|
57449
57983
|
init_schema();
|
|
57450
57984
|
init_manager();
|
|
57451
|
-
import * as
|
|
57452
|
-
import * as
|
|
57985
|
+
import * as fs34 from "fs";
|
|
57986
|
+
import * as path46 from "path";
|
|
57453
57987
|
init_utils2();
|
|
57454
57988
|
init_create_tool();
|
|
57455
57989
|
function safeWarn(message, error93) {
|
|
@@ -57668,7 +58202,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
57668
58202
|
};
|
|
57669
58203
|
if (retroFound && retroEntry?.lessons_learned && retroEntry.lessons_learned.length > 0) {
|
|
57670
58204
|
try {
|
|
57671
|
-
const projectName =
|
|
58205
|
+
const projectName = path46.basename(dir);
|
|
57672
58206
|
await curateAndStoreSwarm(retroEntry.lessons_learned, projectName, { phase_number: phase }, dir, knowledgeConfig);
|
|
57673
58207
|
} catch (error93) {
|
|
57674
58208
|
safeWarn("[phase_complete] Failed to curate lessons from retrospective:", error93);
|
|
@@ -57708,7 +58242,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
57708
58242
|
if (agentsMissing.length > 0) {
|
|
57709
58243
|
try {
|
|
57710
58244
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
57711
|
-
const planRaw =
|
|
58245
|
+
const planRaw = fs34.readFileSync(planPath, "utf-8");
|
|
57712
58246
|
const plan = JSON.parse(planRaw);
|
|
57713
58247
|
const targetPhase = plan.phases.find((p) => p.id === phase);
|
|
57714
58248
|
if (targetPhase && targetPhase.tasks.length > 0 && targetPhase.tasks.every((t) => t.status === "completed")) {
|
|
@@ -57739,7 +58273,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
57739
58273
|
if (phaseCompleteConfig.regression_sweep?.enforce) {
|
|
57740
58274
|
try {
|
|
57741
58275
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
57742
|
-
const planRaw =
|
|
58276
|
+
const planRaw = fs34.readFileSync(planPath, "utf-8");
|
|
57743
58277
|
const plan = JSON.parse(planRaw);
|
|
57744
58278
|
const targetPhase = plan.phases.find((p) => p.id === phase);
|
|
57745
58279
|
if (targetPhase) {
|
|
@@ -57777,7 +58311,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
57777
58311
|
};
|
|
57778
58312
|
try {
|
|
57779
58313
|
const eventsPath = validateSwarmPath(dir, "events.jsonl");
|
|
57780
|
-
|
|
58314
|
+
fs34.appendFileSync(eventsPath, `${JSON.stringify(event)}
|
|
57781
58315
|
`, "utf-8");
|
|
57782
58316
|
} catch (writeError) {
|
|
57783
58317
|
warnings.push(`Warning: failed to write phase complete event: ${writeError instanceof Error ? writeError.message : String(writeError)}`);
|
|
@@ -57796,12 +58330,12 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
57796
58330
|
}
|
|
57797
58331
|
try {
|
|
57798
58332
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
57799
|
-
const planJson =
|
|
58333
|
+
const planJson = fs34.readFileSync(planPath, "utf-8");
|
|
57800
58334
|
const plan = JSON.parse(planJson);
|
|
57801
58335
|
const phaseObj = plan.phases.find((p) => p.id === phase);
|
|
57802
58336
|
if (phaseObj) {
|
|
57803
58337
|
phaseObj.status = "completed";
|
|
57804
|
-
|
|
58338
|
+
fs34.writeFileSync(planPath, `${JSON.stringify(plan, null, 2)}
|
|
57805
58339
|
`, "utf-8");
|
|
57806
58340
|
}
|
|
57807
58341
|
} catch (error93) {
|
|
@@ -57855,8 +58389,8 @@ init_dist();
|
|
|
57855
58389
|
init_discovery();
|
|
57856
58390
|
init_utils();
|
|
57857
58391
|
init_create_tool();
|
|
57858
|
-
import * as
|
|
57859
|
-
import * as
|
|
58392
|
+
import * as fs35 from "fs";
|
|
58393
|
+
import * as path47 from "path";
|
|
57860
58394
|
var MAX_OUTPUT_BYTES5 = 52428800;
|
|
57861
58395
|
var AUDIT_TIMEOUT_MS = 120000;
|
|
57862
58396
|
function isValidEcosystem(value) {
|
|
@@ -57874,28 +58408,28 @@ function validateArgs3(args2) {
|
|
|
57874
58408
|
function detectEcosystems(directory) {
|
|
57875
58409
|
const ecosystems = [];
|
|
57876
58410
|
const cwd = directory;
|
|
57877
|
-
if (
|
|
58411
|
+
if (fs35.existsSync(path47.join(cwd, "package.json"))) {
|
|
57878
58412
|
ecosystems.push("npm");
|
|
57879
58413
|
}
|
|
57880
|
-
if (
|
|
58414
|
+
if (fs35.existsSync(path47.join(cwd, "pyproject.toml")) || fs35.existsSync(path47.join(cwd, "requirements.txt"))) {
|
|
57881
58415
|
ecosystems.push("pip");
|
|
57882
58416
|
}
|
|
57883
|
-
if (
|
|
58417
|
+
if (fs35.existsSync(path47.join(cwd, "Cargo.toml"))) {
|
|
57884
58418
|
ecosystems.push("cargo");
|
|
57885
58419
|
}
|
|
57886
|
-
if (
|
|
58420
|
+
if (fs35.existsSync(path47.join(cwd, "go.mod"))) {
|
|
57887
58421
|
ecosystems.push("go");
|
|
57888
58422
|
}
|
|
57889
58423
|
try {
|
|
57890
|
-
const files =
|
|
58424
|
+
const files = fs35.readdirSync(cwd);
|
|
57891
58425
|
if (files.some((f) => f.endsWith(".csproj") || f.endsWith(".sln"))) {
|
|
57892
58426
|
ecosystems.push("dotnet");
|
|
57893
58427
|
}
|
|
57894
58428
|
} catch {}
|
|
57895
|
-
if (
|
|
58429
|
+
if (fs35.existsSync(path47.join(cwd, "Gemfile")) || fs35.existsSync(path47.join(cwd, "Gemfile.lock"))) {
|
|
57896
58430
|
ecosystems.push("ruby");
|
|
57897
58431
|
}
|
|
57898
|
-
if (
|
|
58432
|
+
if (fs35.existsSync(path47.join(cwd, "pubspec.yaml"))) {
|
|
57899
58433
|
ecosystems.push("dart");
|
|
57900
58434
|
}
|
|
57901
58435
|
return ecosystems;
|
|
@@ -58957,8 +59491,8 @@ var SUPPORTED_PARSER_EXTENSIONS = new Set([
|
|
|
58957
59491
|
]);
|
|
58958
59492
|
// src/tools/pre-check-batch.ts
|
|
58959
59493
|
init_dist();
|
|
58960
|
-
import * as
|
|
58961
|
-
import * as
|
|
59494
|
+
import * as fs38 from "fs";
|
|
59495
|
+
import * as path50 from "path";
|
|
58962
59496
|
|
|
58963
59497
|
// node_modules/yocto-queue/index.js
|
|
58964
59498
|
class Node2 {
|
|
@@ -59103,8 +59637,8 @@ function pLimit(concurrency) {
|
|
|
59103
59637
|
},
|
|
59104
59638
|
map: {
|
|
59105
59639
|
async value(iterable, function_) {
|
|
59106
|
-
const
|
|
59107
|
-
return Promise.all(
|
|
59640
|
+
const promises4 = Array.from(iterable, (value, index) => this(function_, value, index));
|
|
59641
|
+
return Promise.all(promises4);
|
|
59108
59642
|
}
|
|
59109
59643
|
}
|
|
59110
59644
|
});
|
|
@@ -59117,6 +59651,7 @@ function validateConcurrency(concurrency) {
|
|
|
59117
59651
|
}
|
|
59118
59652
|
|
|
59119
59653
|
// src/tools/pre-check-batch.ts
|
|
59654
|
+
init_manager();
|
|
59120
59655
|
init_utils();
|
|
59121
59656
|
init_create_tool();
|
|
59122
59657
|
init_lint();
|
|
@@ -59125,8 +59660,8 @@ init_lint();
|
|
|
59125
59660
|
init_manager();
|
|
59126
59661
|
|
|
59127
59662
|
// src/quality/metrics.ts
|
|
59128
|
-
import * as
|
|
59129
|
-
import * as
|
|
59663
|
+
import * as fs36 from "fs";
|
|
59664
|
+
import * as path48 from "path";
|
|
59130
59665
|
var MAX_FILE_SIZE_BYTES5 = 256 * 1024;
|
|
59131
59666
|
var MIN_DUPLICATION_LINES = 10;
|
|
59132
59667
|
function estimateCyclomaticComplexity(content) {
|
|
@@ -59164,11 +59699,11 @@ function estimateCyclomaticComplexity(content) {
|
|
|
59164
59699
|
}
|
|
59165
59700
|
function getComplexityForFile2(filePath) {
|
|
59166
59701
|
try {
|
|
59167
|
-
const stat2 =
|
|
59702
|
+
const stat2 = fs36.statSync(filePath);
|
|
59168
59703
|
if (stat2.size > MAX_FILE_SIZE_BYTES5) {
|
|
59169
59704
|
return null;
|
|
59170
59705
|
}
|
|
59171
|
-
const content =
|
|
59706
|
+
const content = fs36.readFileSync(filePath, "utf-8");
|
|
59172
59707
|
return estimateCyclomaticComplexity(content);
|
|
59173
59708
|
} catch {
|
|
59174
59709
|
return null;
|
|
@@ -59178,8 +59713,8 @@ async function computeComplexityDelta(files, workingDir) {
|
|
|
59178
59713
|
let totalComplexity = 0;
|
|
59179
59714
|
const analyzedFiles = [];
|
|
59180
59715
|
for (const file3 of files) {
|
|
59181
|
-
const fullPath =
|
|
59182
|
-
if (!
|
|
59716
|
+
const fullPath = path48.isAbsolute(file3) ? file3 : path48.join(workingDir, file3);
|
|
59717
|
+
if (!fs36.existsSync(fullPath)) {
|
|
59183
59718
|
continue;
|
|
59184
59719
|
}
|
|
59185
59720
|
const complexity = getComplexityForFile2(fullPath);
|
|
@@ -59300,8 +59835,8 @@ function countGoExports(content) {
|
|
|
59300
59835
|
}
|
|
59301
59836
|
function getExportCountForFile(filePath) {
|
|
59302
59837
|
try {
|
|
59303
|
-
const content =
|
|
59304
|
-
const ext =
|
|
59838
|
+
const content = fs36.readFileSync(filePath, "utf-8");
|
|
59839
|
+
const ext = path48.extname(filePath).toLowerCase();
|
|
59305
59840
|
switch (ext) {
|
|
59306
59841
|
case ".ts":
|
|
59307
59842
|
case ".tsx":
|
|
@@ -59327,8 +59862,8 @@ async function computePublicApiDelta(files, workingDir) {
|
|
|
59327
59862
|
let totalExports = 0;
|
|
59328
59863
|
const analyzedFiles = [];
|
|
59329
59864
|
for (const file3 of files) {
|
|
59330
|
-
const fullPath =
|
|
59331
|
-
if (!
|
|
59865
|
+
const fullPath = path48.isAbsolute(file3) ? file3 : path48.join(workingDir, file3);
|
|
59866
|
+
if (!fs36.existsSync(fullPath)) {
|
|
59332
59867
|
continue;
|
|
59333
59868
|
}
|
|
59334
59869
|
const exports = getExportCountForFile(fullPath);
|
|
@@ -59361,16 +59896,16 @@ async function computeDuplicationRatio(files, workingDir) {
|
|
|
59361
59896
|
let duplicateLines = 0;
|
|
59362
59897
|
const analyzedFiles = [];
|
|
59363
59898
|
for (const file3 of files) {
|
|
59364
|
-
const fullPath =
|
|
59365
|
-
if (!
|
|
59899
|
+
const fullPath = path48.isAbsolute(file3) ? file3 : path48.join(workingDir, file3);
|
|
59900
|
+
if (!fs36.existsSync(fullPath)) {
|
|
59366
59901
|
continue;
|
|
59367
59902
|
}
|
|
59368
59903
|
try {
|
|
59369
|
-
const stat2 =
|
|
59904
|
+
const stat2 = fs36.statSync(fullPath);
|
|
59370
59905
|
if (stat2.size > MAX_FILE_SIZE_BYTES5) {
|
|
59371
59906
|
continue;
|
|
59372
59907
|
}
|
|
59373
|
-
const content =
|
|
59908
|
+
const content = fs36.readFileSync(fullPath, "utf-8");
|
|
59374
59909
|
const lines = content.split(`
|
|
59375
59910
|
`).filter((line) => line.trim().length > 0);
|
|
59376
59911
|
if (lines.length < MIN_DUPLICATION_LINES) {
|
|
@@ -59394,8 +59929,8 @@ function countCodeLines(content) {
|
|
|
59394
59929
|
return lines.length;
|
|
59395
59930
|
}
|
|
59396
59931
|
function isTestFile(filePath) {
|
|
59397
|
-
const
|
|
59398
|
-
const _ext =
|
|
59932
|
+
const basename9 = path48.basename(filePath);
|
|
59933
|
+
const _ext = path48.extname(filePath).toLowerCase();
|
|
59399
59934
|
const testPatterns = [
|
|
59400
59935
|
".test.",
|
|
59401
59936
|
".spec.",
|
|
@@ -59410,7 +59945,7 @@ function isTestFile(filePath) {
|
|
|
59410
59945
|
".spec.jsx"
|
|
59411
59946
|
];
|
|
59412
59947
|
for (const pattern of testPatterns) {
|
|
59413
|
-
if (
|
|
59948
|
+
if (basename9.includes(pattern)) {
|
|
59414
59949
|
return true;
|
|
59415
59950
|
}
|
|
59416
59951
|
}
|
|
@@ -59476,8 +60011,8 @@ function matchGlobSegment(globSegments, pathSegments) {
|
|
|
59476
60011
|
}
|
|
59477
60012
|
return gIndex === globSegments.length && pIndex === pathSegments.length;
|
|
59478
60013
|
}
|
|
59479
|
-
function matchesGlobSegment(
|
|
59480
|
-
const normalizedPath =
|
|
60014
|
+
function matchesGlobSegment(path49, glob) {
|
|
60015
|
+
const normalizedPath = path49.replace(/\\/g, "/");
|
|
59481
60016
|
const normalizedGlob = glob.replace(/\\/g, "/");
|
|
59482
60017
|
if (normalizedPath.includes("//")) {
|
|
59483
60018
|
return false;
|
|
@@ -59508,8 +60043,8 @@ function simpleGlobToRegex2(glob) {
|
|
|
59508
60043
|
function hasGlobstar(glob) {
|
|
59509
60044
|
return glob.includes("**");
|
|
59510
60045
|
}
|
|
59511
|
-
function globMatches(
|
|
59512
|
-
const normalizedPath =
|
|
60046
|
+
function globMatches(path49, glob) {
|
|
60047
|
+
const normalizedPath = path49.replace(/\\/g, "/");
|
|
59513
60048
|
if (!glob || glob === "") {
|
|
59514
60049
|
if (normalizedPath.includes("//")) {
|
|
59515
60050
|
return false;
|
|
@@ -59545,31 +60080,31 @@ function shouldExcludeFile(filePath, excludeGlobs) {
|
|
|
59545
60080
|
async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
|
|
59546
60081
|
let testLines = 0;
|
|
59547
60082
|
let codeLines = 0;
|
|
59548
|
-
const srcDir =
|
|
59549
|
-
if (
|
|
60083
|
+
const srcDir = path48.join(workingDir, "src");
|
|
60084
|
+
if (fs36.existsSync(srcDir)) {
|
|
59550
60085
|
await scanDirectoryForLines(srcDir, enforceGlobs, excludeGlobs, false, (lines) => {
|
|
59551
60086
|
codeLines += lines;
|
|
59552
60087
|
});
|
|
59553
60088
|
}
|
|
59554
60089
|
const possibleSrcDirs = ["lib", "app", "source", "core"];
|
|
59555
60090
|
for (const dir of possibleSrcDirs) {
|
|
59556
|
-
const dirPath =
|
|
59557
|
-
if (
|
|
60091
|
+
const dirPath = path48.join(workingDir, dir);
|
|
60092
|
+
if (fs36.existsSync(dirPath)) {
|
|
59558
60093
|
await scanDirectoryForLines(dirPath, enforceGlobs, excludeGlobs, false, (lines) => {
|
|
59559
60094
|
codeLines += lines;
|
|
59560
60095
|
});
|
|
59561
60096
|
}
|
|
59562
60097
|
}
|
|
59563
|
-
const testsDir =
|
|
59564
|
-
if (
|
|
60098
|
+
const testsDir = path48.join(workingDir, "tests");
|
|
60099
|
+
if (fs36.existsSync(testsDir)) {
|
|
59565
60100
|
await scanDirectoryForLines(testsDir, ["**"], ["node_modules", "dist"], true, (lines) => {
|
|
59566
60101
|
testLines += lines;
|
|
59567
60102
|
});
|
|
59568
60103
|
}
|
|
59569
60104
|
const possibleTestDirs = ["test", "__tests__", "specs"];
|
|
59570
60105
|
for (const dir of possibleTestDirs) {
|
|
59571
|
-
const dirPath =
|
|
59572
|
-
if (
|
|
60106
|
+
const dirPath = path48.join(workingDir, dir);
|
|
60107
|
+
if (fs36.existsSync(dirPath) && dirPath !== testsDir) {
|
|
59573
60108
|
await scanDirectoryForLines(dirPath, ["**"], ["node_modules", "dist"], true, (lines) => {
|
|
59574
60109
|
testLines += lines;
|
|
59575
60110
|
});
|
|
@@ -59581,9 +60116,9 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
|
|
|
59581
60116
|
}
|
|
59582
60117
|
async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTestScan, callback) {
|
|
59583
60118
|
try {
|
|
59584
|
-
const entries =
|
|
60119
|
+
const entries = fs36.readdirSync(dirPath, { withFileTypes: true });
|
|
59585
60120
|
for (const entry of entries) {
|
|
59586
|
-
const fullPath =
|
|
60121
|
+
const fullPath = path48.join(dirPath, entry.name);
|
|
59587
60122
|
if (entry.isDirectory()) {
|
|
59588
60123
|
if (entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === ".git") {
|
|
59589
60124
|
continue;
|
|
@@ -59591,7 +60126,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
|
|
|
59591
60126
|
await scanDirectoryForLines(fullPath, includeGlobs, excludeGlobs, isTestScan, callback);
|
|
59592
60127
|
} else if (entry.isFile()) {
|
|
59593
60128
|
const relativePath = fullPath.replace(`${dirPath}/`, "");
|
|
59594
|
-
const ext =
|
|
60129
|
+
const ext = path48.extname(entry.name).toLowerCase();
|
|
59595
60130
|
const validExts = [
|
|
59596
60131
|
".ts",
|
|
59597
60132
|
".tsx",
|
|
@@ -59627,7 +60162,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
|
|
|
59627
60162
|
continue;
|
|
59628
60163
|
}
|
|
59629
60164
|
try {
|
|
59630
|
-
const content =
|
|
60165
|
+
const content = fs36.readFileSync(fullPath, "utf-8");
|
|
59631
60166
|
const lines = countCodeLines(content);
|
|
59632
60167
|
callback(lines);
|
|
59633
60168
|
} catch {}
|
|
@@ -59841,8 +60376,8 @@ async function qualityBudget(input, directory) {
|
|
|
59841
60376
|
init_dist();
|
|
59842
60377
|
init_manager();
|
|
59843
60378
|
init_detector();
|
|
59844
|
-
import * as
|
|
59845
|
-
import * as
|
|
60379
|
+
import * as fs37 from "fs";
|
|
60380
|
+
import * as path49 from "path";
|
|
59846
60381
|
import { extname as extname9 } from "path";
|
|
59847
60382
|
|
|
59848
60383
|
// src/sast/rules/c.ts
|
|
@@ -60709,17 +61244,17 @@ var SEVERITY_ORDER = {
|
|
|
60709
61244
|
};
|
|
60710
61245
|
function shouldSkipFile(filePath) {
|
|
60711
61246
|
try {
|
|
60712
|
-
const stats =
|
|
61247
|
+
const stats = fs37.statSync(filePath);
|
|
60713
61248
|
if (stats.size > MAX_FILE_SIZE_BYTES6) {
|
|
60714
61249
|
return { skip: true, reason: "file too large" };
|
|
60715
61250
|
}
|
|
60716
61251
|
if (stats.size === 0) {
|
|
60717
61252
|
return { skip: true, reason: "empty file" };
|
|
60718
61253
|
}
|
|
60719
|
-
const fd =
|
|
61254
|
+
const fd = fs37.openSync(filePath, "r");
|
|
60720
61255
|
const buffer = Buffer.alloc(8192);
|
|
60721
|
-
const bytesRead =
|
|
60722
|
-
|
|
61256
|
+
const bytesRead = fs37.readSync(fd, buffer, 0, 8192, 0);
|
|
61257
|
+
fs37.closeSync(fd);
|
|
60723
61258
|
if (bytesRead > 0) {
|
|
60724
61259
|
let nullCount = 0;
|
|
60725
61260
|
for (let i2 = 0;i2 < bytesRead; i2++) {
|
|
@@ -60758,7 +61293,7 @@ function countBySeverity(findings) {
|
|
|
60758
61293
|
}
|
|
60759
61294
|
function scanFileWithTierA(filePath, language) {
|
|
60760
61295
|
try {
|
|
60761
|
-
const content =
|
|
61296
|
+
const content = fs37.readFileSync(filePath, "utf-8");
|
|
60762
61297
|
const findings = executeRulesSync(filePath, content, language);
|
|
60763
61298
|
return findings.map((f) => ({
|
|
60764
61299
|
rule_id: f.rule_id,
|
|
@@ -60805,8 +61340,8 @@ async function sastScan(input, directory, config3) {
|
|
|
60805
61340
|
_filesSkipped++;
|
|
60806
61341
|
continue;
|
|
60807
61342
|
}
|
|
60808
|
-
const resolvedPath =
|
|
60809
|
-
if (!
|
|
61343
|
+
const resolvedPath = path49.isAbsolute(filePath) ? filePath : path49.resolve(directory, filePath);
|
|
61344
|
+
if (!fs37.existsSync(resolvedPath)) {
|
|
60810
61345
|
_filesSkipped++;
|
|
60811
61346
|
continue;
|
|
60812
61347
|
}
|
|
@@ -61004,18 +61539,18 @@ function validatePath(inputPath, baseDir, workspaceDir) {
|
|
|
61004
61539
|
let resolved;
|
|
61005
61540
|
const isWinAbs = isWindowsAbsolutePath(inputPath);
|
|
61006
61541
|
if (isWinAbs) {
|
|
61007
|
-
resolved =
|
|
61008
|
-
} else if (
|
|
61009
|
-
resolved =
|
|
61542
|
+
resolved = path50.win32.resolve(inputPath);
|
|
61543
|
+
} else if (path50.isAbsolute(inputPath)) {
|
|
61544
|
+
resolved = path50.resolve(inputPath);
|
|
61010
61545
|
} else {
|
|
61011
|
-
resolved =
|
|
61546
|
+
resolved = path50.resolve(baseDir, inputPath);
|
|
61012
61547
|
}
|
|
61013
|
-
const workspaceResolved =
|
|
61548
|
+
const workspaceResolved = path50.resolve(workspaceDir);
|
|
61014
61549
|
let relative6;
|
|
61015
61550
|
if (isWinAbs) {
|
|
61016
|
-
relative6 =
|
|
61551
|
+
relative6 = path50.win32.relative(workspaceResolved, resolved);
|
|
61017
61552
|
} else {
|
|
61018
|
-
relative6 =
|
|
61553
|
+
relative6 = path50.relative(workspaceResolved, resolved);
|
|
61019
61554
|
}
|
|
61020
61555
|
if (relative6.startsWith("..")) {
|
|
61021
61556
|
return "path traversal detected";
|
|
@@ -61076,13 +61611,13 @@ async function runLintWrapped(files, directory, _config) {
|
|
|
61076
61611
|
}
|
|
61077
61612
|
async function runLintOnFiles(linter, files, workspaceDir) {
|
|
61078
61613
|
const isWindows = process.platform === "win32";
|
|
61079
|
-
const binDir =
|
|
61614
|
+
const binDir = path50.join(workspaceDir, "node_modules", ".bin");
|
|
61080
61615
|
const validatedFiles = [];
|
|
61081
61616
|
for (const file3 of files) {
|
|
61082
61617
|
if (typeof file3 !== "string") {
|
|
61083
61618
|
continue;
|
|
61084
61619
|
}
|
|
61085
|
-
const resolvedPath =
|
|
61620
|
+
const resolvedPath = path50.resolve(file3);
|
|
61086
61621
|
const validationError = validatePath(resolvedPath, workspaceDir, workspaceDir);
|
|
61087
61622
|
if (validationError) {
|
|
61088
61623
|
continue;
|
|
@@ -61100,10 +61635,10 @@ async function runLintOnFiles(linter, files, workspaceDir) {
|
|
|
61100
61635
|
}
|
|
61101
61636
|
let command;
|
|
61102
61637
|
if (linter === "biome") {
|
|
61103
|
-
const biomeBin = isWindows ?
|
|
61638
|
+
const biomeBin = isWindows ? path50.join(binDir, "biome.EXE") : path50.join(binDir, "biome");
|
|
61104
61639
|
command = [biomeBin, "check", ...validatedFiles];
|
|
61105
61640
|
} else {
|
|
61106
|
-
const eslintBin = isWindows ?
|
|
61641
|
+
const eslintBin = isWindows ? path50.join(binDir, "eslint.cmd") : path50.join(binDir, "eslint");
|
|
61107
61642
|
command = [eslintBin, ...validatedFiles];
|
|
61108
61643
|
}
|
|
61109
61644
|
try {
|
|
@@ -61240,7 +61775,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
61240
61775
|
skippedFiles++;
|
|
61241
61776
|
continue;
|
|
61242
61777
|
}
|
|
61243
|
-
const resolvedPath =
|
|
61778
|
+
const resolvedPath = path50.resolve(file3);
|
|
61244
61779
|
const validationError = validatePath(resolvedPath, directory, directory);
|
|
61245
61780
|
if (validationError) {
|
|
61246
61781
|
skippedFiles++;
|
|
@@ -61258,14 +61793,14 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
61258
61793
|
};
|
|
61259
61794
|
}
|
|
61260
61795
|
for (const file3 of validatedFiles) {
|
|
61261
|
-
const ext =
|
|
61796
|
+
const ext = path50.extname(file3).toLowerCase();
|
|
61262
61797
|
if (DEFAULT_EXCLUDE_EXTENSIONS2.has(ext)) {
|
|
61263
61798
|
skippedFiles++;
|
|
61264
61799
|
continue;
|
|
61265
61800
|
}
|
|
61266
61801
|
let stat2;
|
|
61267
61802
|
try {
|
|
61268
|
-
stat2 =
|
|
61803
|
+
stat2 = fs38.statSync(file3);
|
|
61269
61804
|
} catch {
|
|
61270
61805
|
skippedFiles++;
|
|
61271
61806
|
continue;
|
|
@@ -61276,7 +61811,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
61276
61811
|
}
|
|
61277
61812
|
let content;
|
|
61278
61813
|
try {
|
|
61279
|
-
const buffer =
|
|
61814
|
+
const buffer = fs38.readFileSync(file3);
|
|
61280
61815
|
if (buffer.includes(0)) {
|
|
61281
61816
|
skippedFiles++;
|
|
61282
61817
|
continue;
|
|
@@ -61417,7 +61952,7 @@ async function runPreCheckBatch(input, workspaceDir, contextDir) {
|
|
|
61417
61952
|
warn(`pre_check_batch: Invalid file path: ${file3}`);
|
|
61418
61953
|
continue;
|
|
61419
61954
|
}
|
|
61420
|
-
changedFiles.push(
|
|
61955
|
+
changedFiles.push(path50.resolve(directory, file3));
|
|
61421
61956
|
}
|
|
61422
61957
|
if (changedFiles.length === 0) {
|
|
61423
61958
|
warn("pre_check_batch: No valid files after validation, skipping all tools (fail-closed)");
|
|
@@ -61464,6 +61999,26 @@ async function runPreCheckBatch(input, workspaceDir, contextDir) {
|
|
|
61464
61999
|
gatesPassed = false;
|
|
61465
62000
|
warn(`pre_check_batch: Secretscan error - GATE FAILED: ${secretscanResult.error}`);
|
|
61466
62001
|
}
|
|
62002
|
+
if (secretscanResult.ran && secretscanResult.result) {
|
|
62003
|
+
try {
|
|
62004
|
+
const scanResult = secretscanResult.result;
|
|
62005
|
+
const secretscanEvidence = {
|
|
62006
|
+
task_id: "secretscan",
|
|
62007
|
+
type: "secretscan",
|
|
62008
|
+
timestamp: new Date().toISOString(),
|
|
62009
|
+
agent: "pre_check_batch",
|
|
62010
|
+
verdict: scanResult.count > 0 ? "fail" : "pass",
|
|
62011
|
+
summary: `Secretscan: ${scanResult.count} finding(s), ${scanResult.files_scanned ?? 0} files scanned, ${scanResult.skipped_files ?? 0} skipped`,
|
|
62012
|
+
findings_count: scanResult.count,
|
|
62013
|
+
scan_directory: scanResult.scan_dir,
|
|
62014
|
+
files_scanned: scanResult.files_scanned,
|
|
62015
|
+
skipped_files: scanResult.skipped_files
|
|
62016
|
+
};
|
|
62017
|
+
await saveEvidence(directory, "secretscan", secretscanEvidence);
|
|
62018
|
+
} catch (e) {
|
|
62019
|
+
warn(`Failed to persist secretscan evidence: ${e instanceof Error ? e.message : String(e)}`);
|
|
62020
|
+
}
|
|
62021
|
+
}
|
|
61467
62022
|
if (sastScanResult.ran && sastScanResult.result) {
|
|
61468
62023
|
if (sastScanResult.result.verdict === "fail") {
|
|
61469
62024
|
gatesPassed = false;
|
|
@@ -61568,7 +62123,7 @@ var pre_check_batch = createSwarmTool({
|
|
|
61568
62123
|
};
|
|
61569
62124
|
return JSON.stringify(errorResult, null, 2);
|
|
61570
62125
|
}
|
|
61571
|
-
const resolvedDirectory =
|
|
62126
|
+
const resolvedDirectory = path50.resolve(typedArgs.directory);
|
|
61572
62127
|
const workspaceAnchor = resolvedDirectory;
|
|
61573
62128
|
const dirError = validateDirectory3(resolvedDirectory, workspaceAnchor);
|
|
61574
62129
|
if (dirError) {
|
|
@@ -61676,8 +62231,8 @@ ${paginatedContent}`;
|
|
|
61676
62231
|
init_tool();
|
|
61677
62232
|
init_manager2();
|
|
61678
62233
|
init_create_tool();
|
|
61679
|
-
import * as
|
|
61680
|
-
import * as
|
|
62234
|
+
import * as fs39 from "fs";
|
|
62235
|
+
import * as path51 from "path";
|
|
61681
62236
|
function detectPlaceholderContent(args2) {
|
|
61682
62237
|
const issues = [];
|
|
61683
62238
|
const placeholderPattern = /^\[\w[\w\s]*\]$/;
|
|
@@ -61781,19 +62336,19 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
61781
62336
|
try {
|
|
61782
62337
|
await savePlan(dir, plan);
|
|
61783
62338
|
try {
|
|
61784
|
-
const markerPath =
|
|
62339
|
+
const markerPath = path51.join(dir, ".swarm", ".plan-write-marker");
|
|
61785
62340
|
const marker = JSON.stringify({
|
|
61786
62341
|
source: "save_plan",
|
|
61787
62342
|
timestamp: new Date().toISOString(),
|
|
61788
62343
|
phases_count: plan.phases.length,
|
|
61789
62344
|
tasks_count: tasksCount
|
|
61790
62345
|
});
|
|
61791
|
-
await
|
|
62346
|
+
await fs39.promises.writeFile(markerPath, marker, "utf8");
|
|
61792
62347
|
} catch {}
|
|
61793
62348
|
return {
|
|
61794
62349
|
success: true,
|
|
61795
62350
|
message: "Plan saved successfully",
|
|
61796
|
-
plan_path:
|
|
62351
|
+
plan_path: path51.join(dir, ".swarm", "plan.json"),
|
|
61797
62352
|
phases_count: plan.phases.length,
|
|
61798
62353
|
tasks_count: tasksCount
|
|
61799
62354
|
};
|
|
@@ -61831,8 +62386,8 @@ var save_plan = createSwarmTool({
|
|
|
61831
62386
|
// src/tools/sbom-generate.ts
|
|
61832
62387
|
init_dist();
|
|
61833
62388
|
init_manager();
|
|
61834
|
-
import * as
|
|
61835
|
-
import * as
|
|
62389
|
+
import * as fs40 from "fs";
|
|
62390
|
+
import * as path52 from "path";
|
|
61836
62391
|
|
|
61837
62392
|
// src/sbom/detectors/index.ts
|
|
61838
62393
|
init_utils();
|
|
@@ -62678,9 +63233,9 @@ function findManifestFiles(rootDir) {
|
|
|
62678
63233
|
const patterns = [...new Set(allDetectors.flatMap((d) => d.patterns))];
|
|
62679
63234
|
function searchDir(dir) {
|
|
62680
63235
|
try {
|
|
62681
|
-
const entries =
|
|
63236
|
+
const entries = fs40.readdirSync(dir, { withFileTypes: true });
|
|
62682
63237
|
for (const entry of entries) {
|
|
62683
|
-
const fullPath =
|
|
63238
|
+
const fullPath = path52.join(dir, entry.name);
|
|
62684
63239
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "target") {
|
|
62685
63240
|
continue;
|
|
62686
63241
|
}
|
|
@@ -62689,7 +63244,7 @@ function findManifestFiles(rootDir) {
|
|
|
62689
63244
|
} else if (entry.isFile()) {
|
|
62690
63245
|
for (const pattern of patterns) {
|
|
62691
63246
|
if (simpleGlobToRegex(pattern).test(entry.name)) {
|
|
62692
|
-
manifestFiles.push(
|
|
63247
|
+
manifestFiles.push(path52.relative(rootDir, fullPath));
|
|
62693
63248
|
break;
|
|
62694
63249
|
}
|
|
62695
63250
|
}
|
|
@@ -62705,13 +63260,13 @@ function findManifestFilesInDirs(directories, workingDir) {
|
|
|
62705
63260
|
const patterns = [...new Set(allDetectors.flatMap((d) => d.patterns))];
|
|
62706
63261
|
for (const dir of directories) {
|
|
62707
63262
|
try {
|
|
62708
|
-
const entries =
|
|
63263
|
+
const entries = fs40.readdirSync(dir, { withFileTypes: true });
|
|
62709
63264
|
for (const entry of entries) {
|
|
62710
|
-
const fullPath =
|
|
63265
|
+
const fullPath = path52.join(dir, entry.name);
|
|
62711
63266
|
if (entry.isFile()) {
|
|
62712
63267
|
for (const pattern of patterns) {
|
|
62713
63268
|
if (simpleGlobToRegex(pattern).test(entry.name)) {
|
|
62714
|
-
found.push(
|
|
63269
|
+
found.push(path52.relative(workingDir, fullPath));
|
|
62715
63270
|
break;
|
|
62716
63271
|
}
|
|
62717
63272
|
}
|
|
@@ -62724,11 +63279,11 @@ function findManifestFilesInDirs(directories, workingDir) {
|
|
|
62724
63279
|
function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
|
|
62725
63280
|
const dirs = new Set;
|
|
62726
63281
|
for (const file3 of changedFiles) {
|
|
62727
|
-
let currentDir =
|
|
63282
|
+
let currentDir = path52.dirname(file3);
|
|
62728
63283
|
while (true) {
|
|
62729
|
-
if (currentDir && currentDir !== "." && currentDir !==
|
|
62730
|
-
dirs.add(
|
|
62731
|
-
const parent =
|
|
63284
|
+
if (currentDir && currentDir !== "." && currentDir !== path52.sep) {
|
|
63285
|
+
dirs.add(path52.join(workingDir, currentDir));
|
|
63286
|
+
const parent = path52.dirname(currentDir);
|
|
62732
63287
|
if (parent === currentDir)
|
|
62733
63288
|
break;
|
|
62734
63289
|
currentDir = parent;
|
|
@@ -62742,7 +63297,7 @@ function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
|
|
|
62742
63297
|
}
|
|
62743
63298
|
function ensureOutputDir(outputDir) {
|
|
62744
63299
|
try {
|
|
62745
|
-
|
|
63300
|
+
fs40.mkdirSync(outputDir, { recursive: true });
|
|
62746
63301
|
} catch (error93) {
|
|
62747
63302
|
if (!error93 || error93.code !== "EEXIST") {
|
|
62748
63303
|
throw error93;
|
|
@@ -62812,7 +63367,7 @@ var sbom_generate = createSwarmTool({
|
|
|
62812
63367
|
const changedFiles = obj.changed_files;
|
|
62813
63368
|
const relativeOutputDir = obj.output_dir || DEFAULT_OUTPUT_DIR;
|
|
62814
63369
|
const workingDir = directory;
|
|
62815
|
-
const outputDir =
|
|
63370
|
+
const outputDir = path52.isAbsolute(relativeOutputDir) ? relativeOutputDir : path52.join(workingDir, relativeOutputDir);
|
|
62816
63371
|
let manifestFiles = [];
|
|
62817
63372
|
if (scope === "all") {
|
|
62818
63373
|
manifestFiles = findManifestFiles(workingDir);
|
|
@@ -62835,11 +63390,11 @@ var sbom_generate = createSwarmTool({
|
|
|
62835
63390
|
const processedFiles = [];
|
|
62836
63391
|
for (const manifestFile of manifestFiles) {
|
|
62837
63392
|
try {
|
|
62838
|
-
const fullPath =
|
|
62839
|
-
if (!
|
|
63393
|
+
const fullPath = path52.isAbsolute(manifestFile) ? manifestFile : path52.join(workingDir, manifestFile);
|
|
63394
|
+
if (!fs40.existsSync(fullPath)) {
|
|
62840
63395
|
continue;
|
|
62841
63396
|
}
|
|
62842
|
-
const content =
|
|
63397
|
+
const content = fs40.readFileSync(fullPath, "utf-8");
|
|
62843
63398
|
const components = detectComponents(manifestFile, content);
|
|
62844
63399
|
processedFiles.push(manifestFile);
|
|
62845
63400
|
if (components.length > 0) {
|
|
@@ -62852,8 +63407,8 @@ var sbom_generate = createSwarmTool({
|
|
|
62852
63407
|
const bom = generateCycloneDX(allComponents);
|
|
62853
63408
|
const bomJson = serializeCycloneDX(bom);
|
|
62854
63409
|
const filename = generateSbomFilename();
|
|
62855
|
-
const outputPath =
|
|
62856
|
-
|
|
63410
|
+
const outputPath = path52.join(outputDir, filename);
|
|
63411
|
+
fs40.writeFileSync(outputPath, bomJson, "utf-8");
|
|
62857
63412
|
const verdict = processedFiles.length > 0 ? "pass" : "pass";
|
|
62858
63413
|
try {
|
|
62859
63414
|
const timestamp = new Date().toISOString();
|
|
@@ -62895,8 +63450,8 @@ var sbom_generate = createSwarmTool({
|
|
|
62895
63450
|
// src/tools/schema-drift.ts
|
|
62896
63451
|
init_dist();
|
|
62897
63452
|
init_create_tool();
|
|
62898
|
-
import * as
|
|
62899
|
-
import * as
|
|
63453
|
+
import * as fs41 from "fs";
|
|
63454
|
+
import * as path53 from "path";
|
|
62900
63455
|
var SPEC_CANDIDATES = [
|
|
62901
63456
|
"openapi.json",
|
|
62902
63457
|
"openapi.yaml",
|
|
@@ -62928,28 +63483,28 @@ function normalizePath2(p) {
|
|
|
62928
63483
|
}
|
|
62929
63484
|
function discoverSpecFile(cwd, specFileArg) {
|
|
62930
63485
|
if (specFileArg) {
|
|
62931
|
-
const resolvedPath =
|
|
62932
|
-
const normalizedCwd = cwd.endsWith(
|
|
63486
|
+
const resolvedPath = path53.resolve(cwd, specFileArg);
|
|
63487
|
+
const normalizedCwd = cwd.endsWith(path53.sep) ? cwd : cwd + path53.sep;
|
|
62933
63488
|
if (!resolvedPath.startsWith(normalizedCwd) && resolvedPath !== cwd) {
|
|
62934
63489
|
throw new Error("Invalid spec_file: path traversal detected");
|
|
62935
63490
|
}
|
|
62936
|
-
const ext =
|
|
63491
|
+
const ext = path53.extname(resolvedPath).toLowerCase();
|
|
62937
63492
|
if (!ALLOWED_EXTENSIONS.includes(ext)) {
|
|
62938
63493
|
throw new Error(`Invalid spec_file: must end in .json, .yaml, or .yml, got ${ext}`);
|
|
62939
63494
|
}
|
|
62940
|
-
const stats =
|
|
63495
|
+
const stats = fs41.statSync(resolvedPath);
|
|
62941
63496
|
if (stats.size > MAX_SPEC_SIZE) {
|
|
62942
63497
|
throw new Error(`Invalid spec_file: file exceeds ${MAX_SPEC_SIZE / 1024 / 1024}MB limit`);
|
|
62943
63498
|
}
|
|
62944
|
-
if (!
|
|
63499
|
+
if (!fs41.existsSync(resolvedPath)) {
|
|
62945
63500
|
throw new Error(`Spec file not found: ${resolvedPath}`);
|
|
62946
63501
|
}
|
|
62947
63502
|
return resolvedPath;
|
|
62948
63503
|
}
|
|
62949
63504
|
for (const candidate of SPEC_CANDIDATES) {
|
|
62950
|
-
const candidatePath =
|
|
62951
|
-
if (
|
|
62952
|
-
const stats =
|
|
63505
|
+
const candidatePath = path53.resolve(cwd, candidate);
|
|
63506
|
+
if (fs41.existsSync(candidatePath)) {
|
|
63507
|
+
const stats = fs41.statSync(candidatePath);
|
|
62953
63508
|
if (stats.size <= MAX_SPEC_SIZE) {
|
|
62954
63509
|
return candidatePath;
|
|
62955
63510
|
}
|
|
@@ -62958,8 +63513,8 @@ function discoverSpecFile(cwd, specFileArg) {
|
|
|
62958
63513
|
return null;
|
|
62959
63514
|
}
|
|
62960
63515
|
function parseSpec(specFile) {
|
|
62961
|
-
const content =
|
|
62962
|
-
const ext =
|
|
63516
|
+
const content = fs41.readFileSync(specFile, "utf-8");
|
|
63517
|
+
const ext = path53.extname(specFile).toLowerCase();
|
|
62963
63518
|
if (ext === ".json") {
|
|
62964
63519
|
return parseJsonSpec(content);
|
|
62965
63520
|
}
|
|
@@ -63030,12 +63585,12 @@ function extractRoutes(cwd) {
|
|
|
63030
63585
|
function walkDir(dir) {
|
|
63031
63586
|
let entries;
|
|
63032
63587
|
try {
|
|
63033
|
-
entries =
|
|
63588
|
+
entries = fs41.readdirSync(dir, { withFileTypes: true });
|
|
63034
63589
|
} catch {
|
|
63035
63590
|
return;
|
|
63036
63591
|
}
|
|
63037
63592
|
for (const entry of entries) {
|
|
63038
|
-
const fullPath =
|
|
63593
|
+
const fullPath = path53.join(dir, entry.name);
|
|
63039
63594
|
if (entry.isSymbolicLink()) {
|
|
63040
63595
|
continue;
|
|
63041
63596
|
}
|
|
@@ -63045,7 +63600,7 @@ function extractRoutes(cwd) {
|
|
|
63045
63600
|
}
|
|
63046
63601
|
walkDir(fullPath);
|
|
63047
63602
|
} else if (entry.isFile()) {
|
|
63048
|
-
const ext =
|
|
63603
|
+
const ext = path53.extname(entry.name).toLowerCase();
|
|
63049
63604
|
const baseName = entry.name.toLowerCase();
|
|
63050
63605
|
if (![".ts", ".js", ".mjs"].includes(ext)) {
|
|
63051
63606
|
continue;
|
|
@@ -63063,7 +63618,7 @@ function extractRoutes(cwd) {
|
|
|
63063
63618
|
}
|
|
63064
63619
|
function extractRoutesFromFile(filePath) {
|
|
63065
63620
|
const routes = [];
|
|
63066
|
-
const content =
|
|
63621
|
+
const content = fs41.readFileSync(filePath, "utf-8");
|
|
63067
63622
|
const lines = content.split(/\r?\n/);
|
|
63068
63623
|
const expressRegex = /(?:app|router|server|express)\.(get|post|put|patch|delete|options|head)\s*\(\s*['"`]([^'"`]+)['"`]/g;
|
|
63069
63624
|
const flaskRegex = /@(?:app|blueprint|bp)\.route\s*\(\s*['"]([^'"]+)['"]/g;
|
|
@@ -63214,8 +63769,8 @@ init_secretscan();
|
|
|
63214
63769
|
// src/tools/symbols.ts
|
|
63215
63770
|
init_tool();
|
|
63216
63771
|
init_create_tool();
|
|
63217
|
-
import * as
|
|
63218
|
-
import * as
|
|
63772
|
+
import * as fs42 from "fs";
|
|
63773
|
+
import * as path54 from "path";
|
|
63219
63774
|
var MAX_FILE_SIZE_BYTES7 = 1024 * 1024;
|
|
63220
63775
|
var WINDOWS_RESERVED_NAMES = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
|
|
63221
63776
|
function containsControlCharacters(str) {
|
|
@@ -63244,11 +63799,11 @@ function containsWindowsAttacks(str) {
|
|
|
63244
63799
|
}
|
|
63245
63800
|
function isPathInWorkspace(filePath, workspace) {
|
|
63246
63801
|
try {
|
|
63247
|
-
const resolvedPath =
|
|
63248
|
-
const realWorkspace =
|
|
63249
|
-
const realResolvedPath =
|
|
63250
|
-
const relativePath =
|
|
63251
|
-
if (relativePath.startsWith("..") ||
|
|
63802
|
+
const resolvedPath = path54.resolve(workspace, filePath);
|
|
63803
|
+
const realWorkspace = fs42.realpathSync(workspace);
|
|
63804
|
+
const realResolvedPath = fs42.realpathSync(resolvedPath);
|
|
63805
|
+
const relativePath = path54.relative(realWorkspace, realResolvedPath);
|
|
63806
|
+
if (relativePath.startsWith("..") || path54.isAbsolute(relativePath)) {
|
|
63252
63807
|
return false;
|
|
63253
63808
|
}
|
|
63254
63809
|
return true;
|
|
@@ -63260,17 +63815,17 @@ function validatePathForRead(filePath, workspace) {
|
|
|
63260
63815
|
return isPathInWorkspace(filePath, workspace);
|
|
63261
63816
|
}
|
|
63262
63817
|
function extractTSSymbols(filePath, cwd) {
|
|
63263
|
-
const fullPath =
|
|
63818
|
+
const fullPath = path54.join(cwd, filePath);
|
|
63264
63819
|
if (!validatePathForRead(fullPath, cwd)) {
|
|
63265
63820
|
return [];
|
|
63266
63821
|
}
|
|
63267
63822
|
let content;
|
|
63268
63823
|
try {
|
|
63269
|
-
const stats =
|
|
63824
|
+
const stats = fs42.statSync(fullPath);
|
|
63270
63825
|
if (stats.size > MAX_FILE_SIZE_BYTES7) {
|
|
63271
63826
|
throw new Error(`File too large: ${stats.size} bytes (max: ${MAX_FILE_SIZE_BYTES7})`);
|
|
63272
63827
|
}
|
|
63273
|
-
content =
|
|
63828
|
+
content = fs42.readFileSync(fullPath, "utf-8");
|
|
63274
63829
|
} catch {
|
|
63275
63830
|
return [];
|
|
63276
63831
|
}
|
|
@@ -63412,17 +63967,17 @@ function extractTSSymbols(filePath, cwd) {
|
|
|
63412
63967
|
});
|
|
63413
63968
|
}
|
|
63414
63969
|
function extractPythonSymbols(filePath, cwd) {
|
|
63415
|
-
const fullPath =
|
|
63970
|
+
const fullPath = path54.join(cwd, filePath);
|
|
63416
63971
|
if (!validatePathForRead(fullPath, cwd)) {
|
|
63417
63972
|
return [];
|
|
63418
63973
|
}
|
|
63419
63974
|
let content;
|
|
63420
63975
|
try {
|
|
63421
|
-
const stats =
|
|
63976
|
+
const stats = fs42.statSync(fullPath);
|
|
63422
63977
|
if (stats.size > MAX_FILE_SIZE_BYTES7) {
|
|
63423
63978
|
throw new Error(`File too large: ${stats.size} bytes (max: ${MAX_FILE_SIZE_BYTES7})`);
|
|
63424
63979
|
}
|
|
63425
|
-
content =
|
|
63980
|
+
content = fs42.readFileSync(fullPath, "utf-8");
|
|
63426
63981
|
} catch {
|
|
63427
63982
|
return [];
|
|
63428
63983
|
}
|
|
@@ -63495,7 +64050,7 @@ var symbols = createSwarmTool({
|
|
|
63495
64050
|
}, null, 2);
|
|
63496
64051
|
}
|
|
63497
64052
|
const cwd = directory;
|
|
63498
|
-
const ext =
|
|
64053
|
+
const ext = path54.extname(file3);
|
|
63499
64054
|
if (containsControlCharacters(file3)) {
|
|
63500
64055
|
return JSON.stringify({
|
|
63501
64056
|
file: file3,
|
|
@@ -63566,8 +64121,8 @@ init_test_runner();
|
|
|
63566
64121
|
init_dist();
|
|
63567
64122
|
init_utils();
|
|
63568
64123
|
init_create_tool();
|
|
63569
|
-
import * as
|
|
63570
|
-
import * as
|
|
64124
|
+
import * as fs43 from "fs";
|
|
64125
|
+
import * as path55 from "path";
|
|
63571
64126
|
var MAX_TEXT_LENGTH = 200;
|
|
63572
64127
|
var MAX_FILE_SIZE_BYTES8 = 1024 * 1024;
|
|
63573
64128
|
var SUPPORTED_EXTENSIONS2 = new Set([
|
|
@@ -63589,7 +64144,7 @@ var SUPPORTED_EXTENSIONS2 = new Set([
|
|
|
63589
64144
|
".swift",
|
|
63590
64145
|
".kt"
|
|
63591
64146
|
]);
|
|
63592
|
-
var
|
|
64147
|
+
var SKIP_DIRECTORIES4 = new Set([
|
|
63593
64148
|
"node_modules",
|
|
63594
64149
|
"dist",
|
|
63595
64150
|
"build",
|
|
@@ -63638,9 +64193,9 @@ function validatePathsInput(paths, cwd) {
|
|
|
63638
64193
|
return { error: "paths contains path traversal", resolvedPath: null };
|
|
63639
64194
|
}
|
|
63640
64195
|
try {
|
|
63641
|
-
const resolvedPath =
|
|
63642
|
-
const normalizedCwd =
|
|
63643
|
-
const normalizedResolved =
|
|
64196
|
+
const resolvedPath = path55.resolve(paths);
|
|
64197
|
+
const normalizedCwd = path55.resolve(cwd);
|
|
64198
|
+
const normalizedResolved = path55.resolve(resolvedPath);
|
|
63644
64199
|
if (!normalizedResolved.startsWith(normalizedCwd)) {
|
|
63645
64200
|
return {
|
|
63646
64201
|
error: "paths must be within the current working directory",
|
|
@@ -63656,25 +64211,25 @@ function validatePathsInput(paths, cwd) {
|
|
|
63656
64211
|
}
|
|
63657
64212
|
}
|
|
63658
64213
|
function isSupportedExtension(filePath) {
|
|
63659
|
-
const ext =
|
|
64214
|
+
const ext = path55.extname(filePath).toLowerCase();
|
|
63660
64215
|
return SUPPORTED_EXTENSIONS2.has(ext);
|
|
63661
64216
|
}
|
|
63662
64217
|
function findSourceFiles2(dir, files = []) {
|
|
63663
64218
|
let entries;
|
|
63664
64219
|
try {
|
|
63665
|
-
entries =
|
|
64220
|
+
entries = fs43.readdirSync(dir);
|
|
63666
64221
|
} catch {
|
|
63667
64222
|
return files;
|
|
63668
64223
|
}
|
|
63669
64224
|
entries.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
|
|
63670
64225
|
for (const entry of entries) {
|
|
63671
|
-
if (
|
|
64226
|
+
if (SKIP_DIRECTORIES4.has(entry)) {
|
|
63672
64227
|
continue;
|
|
63673
64228
|
}
|
|
63674
|
-
const fullPath =
|
|
64229
|
+
const fullPath = path55.join(dir, entry);
|
|
63675
64230
|
let stat2;
|
|
63676
64231
|
try {
|
|
63677
|
-
stat2 =
|
|
64232
|
+
stat2 = fs43.statSync(fullPath);
|
|
63678
64233
|
} catch {
|
|
63679
64234
|
continue;
|
|
63680
64235
|
}
|
|
@@ -63767,7 +64322,7 @@ var todo_extract = createSwarmTool({
|
|
|
63767
64322
|
return JSON.stringify(errorResult, null, 2);
|
|
63768
64323
|
}
|
|
63769
64324
|
const scanPath = resolvedPath;
|
|
63770
|
-
if (!
|
|
64325
|
+
if (!fs43.existsSync(scanPath)) {
|
|
63771
64326
|
const errorResult = {
|
|
63772
64327
|
error: `path not found: ${pathsInput}`,
|
|
63773
64328
|
total: 0,
|
|
@@ -63777,13 +64332,13 @@ var todo_extract = createSwarmTool({
|
|
|
63777
64332
|
return JSON.stringify(errorResult, null, 2);
|
|
63778
64333
|
}
|
|
63779
64334
|
const filesToScan = [];
|
|
63780
|
-
const stat2 =
|
|
64335
|
+
const stat2 = fs43.statSync(scanPath);
|
|
63781
64336
|
if (stat2.isFile()) {
|
|
63782
64337
|
if (isSupportedExtension(scanPath)) {
|
|
63783
64338
|
filesToScan.push(scanPath);
|
|
63784
64339
|
} else {
|
|
63785
64340
|
const errorResult = {
|
|
63786
|
-
error: `unsupported file extension: ${
|
|
64341
|
+
error: `unsupported file extension: ${path55.extname(scanPath)}`,
|
|
63787
64342
|
total: 0,
|
|
63788
64343
|
byPriority: { high: 0, medium: 0, low: 0 },
|
|
63789
64344
|
entries: []
|
|
@@ -63796,11 +64351,11 @@ var todo_extract = createSwarmTool({
|
|
|
63796
64351
|
const allEntries = [];
|
|
63797
64352
|
for (const filePath of filesToScan) {
|
|
63798
64353
|
try {
|
|
63799
|
-
const fileStat =
|
|
64354
|
+
const fileStat = fs43.statSync(filePath);
|
|
63800
64355
|
if (fileStat.size > MAX_FILE_SIZE_BYTES8) {
|
|
63801
64356
|
continue;
|
|
63802
64357
|
}
|
|
63803
|
-
const content =
|
|
64358
|
+
const content = fs43.readFileSync(filePath, "utf-8");
|
|
63804
64359
|
const entries = parseTodoComments(content, filePath, tagsSet);
|
|
63805
64360
|
allEntries.push(...entries);
|
|
63806
64361
|
} catch {}
|
|
@@ -63828,18 +64383,18 @@ var todo_extract = createSwarmTool({
|
|
|
63828
64383
|
// src/tools/update-task-status.ts
|
|
63829
64384
|
init_tool();
|
|
63830
64385
|
init_schema();
|
|
63831
|
-
import * as
|
|
63832
|
-
import * as
|
|
64386
|
+
import * as fs45 from "fs";
|
|
64387
|
+
import * as path57 from "path";
|
|
63833
64388
|
|
|
63834
64389
|
// src/hooks/diff-scope.ts
|
|
63835
|
-
import * as
|
|
63836
|
-
import * as
|
|
64390
|
+
import * as fs44 from "fs";
|
|
64391
|
+
import * as path56 from "path";
|
|
63837
64392
|
function getDeclaredScope(taskId, directory) {
|
|
63838
64393
|
try {
|
|
63839
|
-
const planPath =
|
|
63840
|
-
if (!
|
|
64394
|
+
const planPath = path56.join(directory, ".swarm", "plan.json");
|
|
64395
|
+
if (!fs44.existsSync(planPath))
|
|
63841
64396
|
return null;
|
|
63842
|
-
const raw =
|
|
64397
|
+
const raw = fs44.readFileSync(planPath, "utf-8");
|
|
63843
64398
|
const plan = JSON.parse(raw);
|
|
63844
64399
|
for (const phase of plan.phases ?? []) {
|
|
63845
64400
|
for (const task of phase.tasks ?? []) {
|
|
@@ -63951,7 +64506,7 @@ var TIER_3_PATTERNS = [
|
|
|
63951
64506
|
];
|
|
63952
64507
|
function matchesTier3Pattern(files) {
|
|
63953
64508
|
for (const file3 of files) {
|
|
63954
|
-
const fileName =
|
|
64509
|
+
const fileName = path57.basename(file3);
|
|
63955
64510
|
for (const pattern of TIER_3_PATTERNS) {
|
|
63956
64511
|
if (pattern.test(fileName)) {
|
|
63957
64512
|
return true;
|
|
@@ -63973,8 +64528,8 @@ function checkReviewerGate(taskId, workingDirectory) {
|
|
|
63973
64528
|
if (hasActiveTurboMode2()) {
|
|
63974
64529
|
const resolvedDir2 = workingDirectory;
|
|
63975
64530
|
try {
|
|
63976
|
-
const planPath =
|
|
63977
|
-
const planRaw =
|
|
64531
|
+
const planPath = path57.join(resolvedDir2, ".swarm", "plan.json");
|
|
64532
|
+
const planRaw = fs45.readFileSync(planPath, "utf-8");
|
|
63978
64533
|
const plan = JSON.parse(planRaw);
|
|
63979
64534
|
for (const planPhase of plan.phases ?? []) {
|
|
63980
64535
|
for (const task of planPhase.tasks ?? []) {
|
|
@@ -63993,8 +64548,8 @@ function checkReviewerGate(taskId, workingDirectory) {
|
|
|
63993
64548
|
}
|
|
63994
64549
|
const resolvedDir = workingDirectory;
|
|
63995
64550
|
try {
|
|
63996
|
-
const evidencePath =
|
|
63997
|
-
const raw =
|
|
64551
|
+
const evidencePath = path57.join(resolvedDir, ".swarm", "evidence", `${taskId}.json`);
|
|
64552
|
+
const raw = fs45.readFileSync(evidencePath, "utf-8");
|
|
63998
64553
|
const evidence = JSON.parse(raw);
|
|
63999
64554
|
if (evidence?.required_gates && Array.isArray(evidence.required_gates) && evidence?.gates) {
|
|
64000
64555
|
const allGatesMet = evidence.required_gates.every((gate) => evidence.gates[gate] != null);
|
|
@@ -64034,8 +64589,8 @@ function checkReviewerGate(taskId, workingDirectory) {
|
|
|
64034
64589
|
}
|
|
64035
64590
|
try {
|
|
64036
64591
|
const resolvedDir2 = workingDirectory;
|
|
64037
|
-
const planPath =
|
|
64038
|
-
const planRaw =
|
|
64592
|
+
const planPath = path57.join(resolvedDir2, ".swarm", "plan.json");
|
|
64593
|
+
const planRaw = fs45.readFileSync(planPath, "utf-8");
|
|
64039
64594
|
const plan = JSON.parse(planRaw);
|
|
64040
64595
|
for (const planPhase of plan.phases ?? []) {
|
|
64041
64596
|
for (const task of planPhase.tasks ?? []) {
|
|
@@ -64216,8 +64771,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
|
|
|
64216
64771
|
};
|
|
64217
64772
|
}
|
|
64218
64773
|
}
|
|
64219
|
-
normalizedDir =
|
|
64220
|
-
const pathParts = normalizedDir.split(
|
|
64774
|
+
normalizedDir = path57.normalize(args2.working_directory);
|
|
64775
|
+
const pathParts = normalizedDir.split(path57.sep);
|
|
64221
64776
|
if (pathParts.includes("..")) {
|
|
64222
64777
|
return {
|
|
64223
64778
|
success: false,
|
|
@@ -64227,11 +64782,11 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
|
|
|
64227
64782
|
]
|
|
64228
64783
|
};
|
|
64229
64784
|
}
|
|
64230
|
-
const resolvedDir =
|
|
64785
|
+
const resolvedDir = path57.resolve(normalizedDir);
|
|
64231
64786
|
try {
|
|
64232
|
-
const realPath =
|
|
64233
|
-
const planPath =
|
|
64234
|
-
if (!
|
|
64787
|
+
const realPath = fs45.realpathSync(resolvedDir);
|
|
64788
|
+
const planPath = path57.join(realPath, ".swarm", "plan.json");
|
|
64789
|
+
if (!fs45.existsSync(planPath)) {
|
|
64235
64790
|
return {
|
|
64236
64791
|
success: false,
|
|
64237
64792
|
message: `Invalid working_directory: plan not found in "${realPath}"`,
|
|
@@ -64453,7 +65008,7 @@ var OpenCodeSwarm = async (ctx) => {
|
|
|
64453
65008
|
const { PreflightTriggerManager: PTM } = await Promise.resolve().then(() => (init_trigger(), exports_trigger));
|
|
64454
65009
|
preflightTriggerManager = new PTM(automationConfig);
|
|
64455
65010
|
const { AutomationStatusArtifact: ASA } = await Promise.resolve().then(() => (init_status_artifact(), exports_status_artifact));
|
|
64456
|
-
const swarmDir =
|
|
65011
|
+
const swarmDir = path58.resolve(ctx.directory, ".swarm");
|
|
64457
65012
|
statusArtifact = new ASA(swarmDir);
|
|
64458
65013
|
statusArtifact.updateConfig(automationConfig.mode, automationConfig.capabilities);
|
|
64459
65014
|
if (automationConfig.capabilities?.evidence_auto_summaries === true) {
|
|
@@ -64745,7 +65300,9 @@ var OpenCodeSwarm = async (ctx) => {
|
|
|
64745
65300
|
await safeHook(activityHooks.toolBefore)(input, output);
|
|
64746
65301
|
},
|
|
64747
65302
|
"tool.execute.after": async (input, output) => {
|
|
64748
|
-
|
|
65303
|
+
if (process.env.DEBUG_SWARM) {
|
|
65304
|
+
console.debug("[hook-chain] toolAfter start sessionID=%s agent=%s tool=%s", input.sessionID, input.agent, input.tool?.name);
|
|
65305
|
+
}
|
|
64749
65306
|
await activityHooks.toolAfter(input, output);
|
|
64750
65307
|
await guardrailsHooks.toolAfter(input, output);
|
|
64751
65308
|
await safeHook(delegationLedgerHook.toolAfter)(input, output);
|
|
@@ -64805,7 +65362,9 @@ var OpenCodeSwarm = async (ctx) => {
|
|
|
64805
65362
|
deleteStoredInputArgs(input.callID);
|
|
64806
65363
|
},
|
|
64807
65364
|
"chat.message": safeHook(async (input, output) => {
|
|
64808
|
-
|
|
65365
|
+
if (process.env.DEBUG_SWARM) {
|
|
65366
|
+
console.debug("[session] chat.message sessionID=%s agent=%s", input.sessionID, input.agent);
|
|
65367
|
+
}
|
|
64809
65368
|
await delegationHandler(input, output);
|
|
64810
65369
|
}),
|
|
64811
65370
|
automation: automationManager
|