opencode-swarm 6.29.2 → 6.29.4
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 +49 -13
- package/dist/cli/index.js +15 -12
- package/dist/hooks/incremental-verify.d.ts +2 -1
- package/dist/index.js +322 -204
- package/dist/tools/test-runner.d.ts +1 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -35193,7 +35193,8 @@ var init_test_runner = __esm(() => {
|
|
|
35193
35193
|
scope: tool.schema.enum(["all", "convention", "graph"]).optional().describe('Test scope: "all" runs full suite, "convention" maps source files to test files by naming, "graph" finds related tests via imports'),
|
|
35194
35194
|
files: tool.schema.array(tool.schema.string()).optional().describe("Specific files to test (used with convention or graph scope)"),
|
|
35195
35195
|
coverage: tool.schema.boolean().optional().describe("Enable coverage reporting if supported"),
|
|
35196
|
-
timeout_ms: tool.schema.number().optional().describe("Timeout in milliseconds (default 60000, max 300000)")
|
|
35196
|
+
timeout_ms: tool.schema.number().optional().describe("Timeout in milliseconds (default 60000, max 300000)"),
|
|
35197
|
+
allow_full_suite: tool.schema.boolean().optional().describe('Explicit opt-in for scope "all". Required because full-suite output can destabilize SSE streaming.')
|
|
35197
35198
|
},
|
|
35198
35199
|
async execute(args2, directory) {
|
|
35199
35200
|
const workingDir = directory.trim() || directory;
|
|
@@ -35245,14 +35246,16 @@ var init_test_runner = __esm(() => {
|
|
|
35245
35246
|
}
|
|
35246
35247
|
const scope = args2.scope || "all";
|
|
35247
35248
|
if (scope === "all") {
|
|
35248
|
-
|
|
35249
|
-
|
|
35250
|
-
|
|
35251
|
-
|
|
35252
|
-
|
|
35253
|
-
|
|
35254
|
-
|
|
35255
|
-
|
|
35249
|
+
if (!args2.allow_full_suite) {
|
|
35250
|
+
const errorResult = {
|
|
35251
|
+
success: false,
|
|
35252
|
+
framework: "none",
|
|
35253
|
+
scope: "all",
|
|
35254
|
+
error: 'Full-suite test execution (scope: "all") requires allow_full_suite: true',
|
|
35255
|
+
message: 'Set allow_full_suite: true to confirm intentional full-suite execution. Use scope "convention" or "graph" for targeted tests. Full-suite output is large and may destabilize SSE streaming on some opencode versions.'
|
|
35256
|
+
};
|
|
35257
|
+
return JSON.stringify(errorResult, null, 2);
|
|
35258
|
+
}
|
|
35256
35259
|
}
|
|
35257
35260
|
if ((scope === "convention" || scope === "graph") && (!args2.files || args2.files.length === 0)) {
|
|
35258
35261
|
const errorResult = {
|
|
@@ -35287,7 +35290,7 @@ var init_test_runner = __esm(() => {
|
|
|
35287
35290
|
let testFiles = [];
|
|
35288
35291
|
let graphFallbackReason;
|
|
35289
35292
|
let effectiveScope = scope;
|
|
35290
|
-
if (scope === "convention") {
|
|
35293
|
+
if (scope === "all") {} else if (scope === "convention") {
|
|
35291
35294
|
const sourceFiles = args2.files.filter((f) => {
|
|
35292
35295
|
const ext = path23.extname(f).toLowerCase();
|
|
35293
35296
|
return SOURCE_EXTENSIONS.has(ext);
|
|
@@ -35327,7 +35330,7 @@ var init_test_runner = __esm(() => {
|
|
|
35327
35330
|
testFiles = getTestFilesFromConvention(sourceFiles);
|
|
35328
35331
|
}
|
|
35329
35332
|
}
|
|
35330
|
-
if (testFiles.length === 0) {
|
|
35333
|
+
if (scope !== "all" && testFiles.length === 0) {
|
|
35331
35334
|
const errorResult = {
|
|
35332
35335
|
success: false,
|
|
35333
35336
|
framework,
|
|
@@ -35337,7 +35340,7 @@ var init_test_runner = __esm(() => {
|
|
|
35337
35340
|
};
|
|
35338
35341
|
return JSON.stringify(errorResult, null, 2);
|
|
35339
35342
|
}
|
|
35340
|
-
if (testFiles.length > MAX_SAFE_TEST_FILES) {
|
|
35343
|
+
if (scope !== "all" && testFiles.length > MAX_SAFE_TEST_FILES) {
|
|
35341
35344
|
const sampleFiles = testFiles.slice(0, 5);
|
|
35342
35345
|
const errorResult = {
|
|
35343
35346
|
success: false,
|
|
@@ -37601,11 +37604,11 @@ ${JSON.stringify(symbolNames, null, 2)}`);
|
|
|
37601
37604
|
throw toThrow;
|
|
37602
37605
|
}, "quit_");
|
|
37603
37606
|
var scriptDirectory = "";
|
|
37604
|
-
function locateFile(
|
|
37607
|
+
function locateFile(path47) {
|
|
37605
37608
|
if (Module["locateFile"]) {
|
|
37606
|
-
return Module["locateFile"](
|
|
37609
|
+
return Module["locateFile"](path47, scriptDirectory);
|
|
37607
37610
|
}
|
|
37608
|
-
return scriptDirectory +
|
|
37611
|
+
return scriptDirectory + path47;
|
|
37609
37612
|
}
|
|
37610
37613
|
__name(locateFile, "locateFile");
|
|
37611
37614
|
var readAsync, readBinary;
|
|
@@ -39353,7 +39356,7 @@ var init_runtime = __esm(() => {
|
|
|
39353
39356
|
});
|
|
39354
39357
|
|
|
39355
39358
|
// src/index.ts
|
|
39356
|
-
import * as
|
|
39359
|
+
import * as path57 from "path";
|
|
39357
39360
|
|
|
39358
39361
|
// src/agents/index.ts
|
|
39359
39362
|
init_config();
|
|
@@ -40412,6 +40415,22 @@ TASK GRANULARITY RULES:
|
|
|
40412
40415
|
- Compound verbs are OK when they describe a single logical change: "add validation to handler and update its test" = 1 task. "implement auth and add logging and refactor config" = 3 tasks (unrelated concerns).
|
|
40413
40416
|
- Coder receives ONE task. You make ALL scope decisions in the plan. Coder makes zero scope decisions.
|
|
40414
40417
|
|
|
40418
|
+
TEST TASK DEDUPLICATION:
|
|
40419
|
+
The QA gate (Stage B, step 5l) runs test_engineer-verification on EVERY implementation task.
|
|
40420
|
+
This means tests are written, run, and verified as part of the gate \u2014 NOT as separate plan tasks.
|
|
40421
|
+
|
|
40422
|
+
DO NOT create separate "write tests for X" or "add test coverage for X" tasks. They are redundant with the gate and waste execution budget.
|
|
40423
|
+
|
|
40424
|
+
Research confirms this: controlled experiments across 6 LLMs (arXiv:2602.07900) found that large shifts in test-writing volume yielded only 0\u20132.6% resolution change while consuming 20\u201349% more tokens. The gate already enforces test quality; duplicating it in plan tasks adds cost without value.
|
|
40425
|
+
|
|
40426
|
+
CREATE a dedicated test task ONLY when:
|
|
40427
|
+
- The work is PURE test infrastructure (new fixtures, test helpers, mock factories, CI config) with no implementation
|
|
40428
|
+
- Integration tests span multiple modules changed across different implementation tasks within the same phase
|
|
40429
|
+
- Coverage is explicitly below threshold and the user requests a dedicated coverage pass
|
|
40430
|
+
|
|
40431
|
+
If in doubt, do NOT create a test task. The gate handles it.
|
|
40432
|
+
Note: this is prompt-level guidance for the architect's planning behavior, not a hard gate \u2014 the behavioral enforcement is that test_engineer already writes tests at the QA gate level.
|
|
40433
|
+
|
|
40415
40434
|
PHASE COUNT GUIDANCE:
|
|
40416
40435
|
- Plans with 5+ tasks SHOULD be split into at least 2 phases.
|
|
40417
40436
|
- Plans with 10+ tasks MUST be split into at least 3 phases.
|
|
@@ -40531,6 +40550,18 @@ Treating pre_check_batch as a substitute for {{AGENT_PREFIX}}reviewer is a PROCE
|
|
|
40531
40550
|
\u2192 If TRIGGERED: Print "security-reviewer: [APPROVED | REJECTED \u2014 reason]"
|
|
40532
40551
|
5l. {{AGENT_PREFIX}}test_engineer - Verification tests. FAIL \u2192 coder retry from 5g.
|
|
40533
40552
|
\u2192 REQUIRED: Print "testengineer-verification: [PASS N/N | FAIL \u2014 details]"
|
|
40553
|
+
5l-bis. REGRESSION SWEEP (automatic after test_engineer-verification PASS):
|
|
40554
|
+
Run test_runner with { scope: "graph", files: [<all source files changed by coder in this task>] }.
|
|
40555
|
+
scope:"graph" traces imports to discover test files beyond the task's own tests that may be affected by this change.
|
|
40556
|
+
|
|
40557
|
+
Outcomes:
|
|
40558
|
+
- If scope:"graph" returns ONLY the same test files test_engineer already ran \u2192 SKIP (no additional tests found). Print "regression-sweep: SKIPPED \u2014 no related tests beyond task scope"
|
|
40559
|
+
- If scope:"graph" returns additional test files AND all pass \u2192 PASS. Print "regression-sweep: PASS [N additional tests, M files]"
|
|
40560
|
+
- If scope:"graph" returns additional test files AND any FAIL \u2192 return to coder with: "REGRESSION DETECTED: Your changes in [files] broke [N] tests in [test files]. The failing tests are CORRECT \u2014 fix the source code, not the tests." Coder retry from 5g.
|
|
40561
|
+
- If test_runner fails to execute (error, timeout, no framework detected) \u2192 SKIP. Print "regression-sweep: SKIPPED \u2014 test_runner error" and continue pipeline. Do NOT block on test_runner infrastructure failures.
|
|
40562
|
+
|
|
40563
|
+
IMPORTANT: The regression sweep runs test_runner DIRECTLY (architect calls the tool). Do NOT delegate to test_engineer for this \u2014 the test_engineer's EXECUTION BOUNDARY restricts it to its own test files. The architect has unrestricted test_runner access.
|
|
40564
|
+
\u2192 REQUIRED: Print "regression-sweep: [PASS N additional tests | SKIPPED \u2014 no related tests beyond task scope | SKIPPED \u2014 test_runner error | FAIL \u2014 REGRESSION DETECTED in files]"
|
|
40534
40565
|
{{ADVERSARIAL_TEST_STEP}}
|
|
40535
40566
|
5n. COVERAGE CHECK: If {{AGENT_PREFIX}}test_engineer reports coverage < 70% \u2192 delegate {{AGENT_PREFIX}}test_engineer for an additional test pass targeting uncovered paths. This is a soft guideline; use judgment for trivial tasks.
|
|
40536
40567
|
|
|
@@ -40540,6 +40571,7 @@ PRE-COMMIT RULE \u2014 Before ANY commit or push:
|
|
|
40540
40571
|
[ ] Did {{AGENT_PREFIX}}test_engineer run and return PASS? (not "the code looks correct" \u2014 the agent must have run)
|
|
40541
40572
|
[ ] Did pre_check_batch run with gates_passed true?
|
|
40542
40573
|
[ ] Did the diff step run?
|
|
40574
|
+
[ ] Did regression-sweep run (or SKIP with no related tests or test_runner error)?
|
|
40543
40575
|
|
|
40544
40576
|
If ANY box is unchecked: DO NOT COMMIT. Return to step 5b.
|
|
40545
40577
|
There is no override. A commit without a completed QA gate is a workflow violation.
|
|
@@ -40555,6 +40587,7 @@ PRE-COMMIT RULE \u2014 Before ANY commit or push:
|
|
|
40555
40587
|
[GATE] reviewer: APPROVED \u2014 value: ___
|
|
40556
40588
|
[GATE] security-reviewer: APPROVED / SKIPPED \u2014 value: ___
|
|
40557
40589
|
[GATE] test_engineer-verification: PASS \u2014 value: ___
|
|
40590
|
+
[GATE] regression-sweep: PASS / SKIPPED \u2014 value: ___
|
|
40558
40591
|
{{ADVERSARIAL_TEST_CHECKLIST}}
|
|
40559
40592
|
[GATE] coverage: \u226570% / soft-skip \u2014 value: ___
|
|
40560
40593
|
|
|
@@ -41787,7 +41820,8 @@ WORKFLOW:
|
|
|
41787
41820
|
EXECUTION BOUNDARY:
|
|
41788
41821
|
- Blast radius is the FILE path(s) in input
|
|
41789
41822
|
- When calling test_runner, use: { scope: "convention", files: ["<your-test-file-path>"] }
|
|
41790
|
-
-
|
|
41823
|
+
- scope: "all" is PROHIBITED for test_engineer \u2014 full-suite output can destabilize opencode's SSE streaming, and the architect handles regression sweeps separately via scope: "graph"
|
|
41824
|
+
- If you need to verify tests beyond your assigned file, report the concern in your VERDICT and the architect will handle it
|
|
41791
41825
|
- If you wrote tests/foo.test.ts for src/foo.ts, you MUST run only tests/foo.test.ts
|
|
41792
41826
|
|
|
41793
41827
|
TOOL USAGE:
|
|
@@ -45541,6 +45575,58 @@ async function checkSteeringDirectives(directory) {
|
|
|
45541
45575
|
};
|
|
45542
45576
|
}
|
|
45543
45577
|
}
|
|
45578
|
+
async function checkCurator(directory) {
|
|
45579
|
+
try {
|
|
45580
|
+
const config3 = loadPluginConfig(directory);
|
|
45581
|
+
if (!config3.curator?.enabled) {
|
|
45582
|
+
return {
|
|
45583
|
+
name: "Curator",
|
|
45584
|
+
status: "\u2705",
|
|
45585
|
+
detail: "Disabled (enable via curator.enabled)"
|
|
45586
|
+
};
|
|
45587
|
+
}
|
|
45588
|
+
const summaryPath = path16.join(directory, ".swarm/curator-summary.json");
|
|
45589
|
+
if (!existsSync6(summaryPath)) {
|
|
45590
|
+
return {
|
|
45591
|
+
name: "Curator",
|
|
45592
|
+
status: "\u2705",
|
|
45593
|
+
detail: "Enabled, no summary yet (waiting for first phase)"
|
|
45594
|
+
};
|
|
45595
|
+
}
|
|
45596
|
+
try {
|
|
45597
|
+
const content = readFileSync4(summaryPath, "utf-8");
|
|
45598
|
+
const parsed = JSON.parse(content);
|
|
45599
|
+
if (typeof parsed.schema_version !== "number" || parsed.schema_version !== 1) {
|
|
45600
|
+
return {
|
|
45601
|
+
name: "Curator",
|
|
45602
|
+
status: "\u274C",
|
|
45603
|
+
detail: `curator-summary.json has invalid schema_version (expected 1, got ${JSON.stringify(parsed.schema_version)})`
|
|
45604
|
+
};
|
|
45605
|
+
}
|
|
45606
|
+
const phaseInfo = parsed.last_phase_covered !== undefined ? `phase ${parsed.last_phase_covered}` : "unknown phase";
|
|
45607
|
+
const timeInfo = parsed.last_updated ? `, updated ${parsed.last_updated}` : "";
|
|
45608
|
+
return {
|
|
45609
|
+
name: "Curator",
|
|
45610
|
+
status: "\u2705",
|
|
45611
|
+
detail: `Summary present \u2014 covering ${phaseInfo}${timeInfo}`
|
|
45612
|
+
};
|
|
45613
|
+
} catch (err2) {
|
|
45614
|
+
const message = err2 instanceof Error ? err2.message : "Unknown error";
|
|
45615
|
+
return {
|
|
45616
|
+
name: "Curator",
|
|
45617
|
+
status: "\u274C",
|
|
45618
|
+
detail: `curator-summary.json is corrupt or invalid: ${message}`
|
|
45619
|
+
};
|
|
45620
|
+
}
|
|
45621
|
+
} catch (err2) {
|
|
45622
|
+
const message = err2 instanceof Error ? err2.message : "Unknown error";
|
|
45623
|
+
return {
|
|
45624
|
+
name: "Curator",
|
|
45625
|
+
status: "\u274C",
|
|
45626
|
+
detail: `Could not check curator state: ${message}`
|
|
45627
|
+
};
|
|
45628
|
+
}
|
|
45629
|
+
}
|
|
45544
45630
|
async function getDiagnoseData(directory) {
|
|
45545
45631
|
const checks5 = [];
|
|
45546
45632
|
const plan = await loadPlanJsonOnly(directory);
|
|
@@ -45645,6 +45731,7 @@ async function getDiagnoseData(directory) {
|
|
|
45645
45731
|
checks5.push(await checkCheckpointManifest(directory));
|
|
45646
45732
|
checks5.push(await checkEventStreamIntegrity(directory));
|
|
45647
45733
|
checks5.push(await checkSteeringDirectives(directory));
|
|
45734
|
+
checks5.push(await checkCurator(directory));
|
|
45648
45735
|
const passCount = checks5.filter((c) => c.status === "\u2705").length;
|
|
45649
45736
|
const totalCount = checks5.length;
|
|
45650
45737
|
const allPassed = passCount === totalCount;
|
|
@@ -50713,6 +50800,7 @@ function consolidateSystemMessages(messages) {
|
|
|
50713
50800
|
// src/hooks/phase-monitor.ts
|
|
50714
50801
|
init_schema();
|
|
50715
50802
|
init_manager2();
|
|
50803
|
+
import * as path31 from "path";
|
|
50716
50804
|
init_utils2();
|
|
50717
50805
|
function createPhaseMonitorHook(directory, preflightManager, curatorRunner = runCuratorInit) {
|
|
50718
50806
|
let lastKnownPhase = null;
|
|
@@ -50728,7 +50816,13 @@ function createPhaseMonitorHook(directory, preflightManager, curatorRunner = run
|
|
|
50728
50816
|
const { config: config3 } = loadPluginConfigWithMeta2(directory);
|
|
50729
50817
|
const curatorConfig = CuratorConfigSchema.parse(config3.curator ?? {});
|
|
50730
50818
|
if (curatorConfig.enabled && curatorConfig.init_enabled) {
|
|
50731
|
-
await curatorRunner(directory, curatorConfig);
|
|
50819
|
+
const initResult = await curatorRunner(directory, curatorConfig);
|
|
50820
|
+
if (initResult.briefing) {
|
|
50821
|
+
const briefingPath = path31.join(directory, ".swarm", "curator-briefing.md");
|
|
50822
|
+
const fs18 = await import("fs");
|
|
50823
|
+
fs18.mkdirSync(path31.dirname(briefingPath), { recursive: true });
|
|
50824
|
+
fs18.writeFileSync(briefingPath, initResult.briefing, "utf-8");
|
|
50825
|
+
}
|
|
50732
50826
|
}
|
|
50733
50827
|
} catch {}
|
|
50734
50828
|
return;
|
|
@@ -50844,7 +50938,7 @@ import * as fs19 from "fs";
|
|
|
50844
50938
|
init_utils2();
|
|
50845
50939
|
init_manager2();
|
|
50846
50940
|
import * as fs18 from "fs";
|
|
50847
|
-
import * as
|
|
50941
|
+
import * as path32 from "path";
|
|
50848
50942
|
var DEFAULT_DRIFT_CONFIG = {
|
|
50849
50943
|
staleThresholdPhases: 1,
|
|
50850
50944
|
detectContradictions: true,
|
|
@@ -50998,7 +51092,7 @@ async function analyzeDecisionDrift(directory, config3 = {}) {
|
|
|
50998
51092
|
currentPhase = legacyPhase;
|
|
50999
51093
|
}
|
|
51000
51094
|
}
|
|
51001
|
-
const contextPath =
|
|
51095
|
+
const contextPath = path32.join(directory, ".swarm", "context.md");
|
|
51002
51096
|
let contextContent = "";
|
|
51003
51097
|
try {
|
|
51004
51098
|
if (fs18.existsSync(contextPath)) {
|
|
@@ -52463,7 +52557,7 @@ function createDarkMatterDetectorHook(directory) {
|
|
|
52463
52557
|
|
|
52464
52558
|
// src/hooks/incremental-verify.ts
|
|
52465
52559
|
import * as fs20 from "fs";
|
|
52466
|
-
import * as
|
|
52560
|
+
import * as path33 from "path";
|
|
52467
52561
|
|
|
52468
52562
|
// src/hooks/spawn-helper.ts
|
|
52469
52563
|
import { spawn } from "child_process";
|
|
@@ -52519,7 +52613,7 @@ function spawnAsync(command, cwd, timeoutMs) {
|
|
|
52519
52613
|
// src/hooks/incremental-verify.ts
|
|
52520
52614
|
var emittedSkipAdvisories = new Set;
|
|
52521
52615
|
function detectTypecheckCommand(projectDir) {
|
|
52522
|
-
const pkgPath =
|
|
52616
|
+
const pkgPath = path33.join(projectDir, "package.json");
|
|
52523
52617
|
if (fs20.existsSync(pkgPath)) {
|
|
52524
52618
|
try {
|
|
52525
52619
|
const pkg = JSON.parse(fs20.readFileSync(pkgPath, "utf8"));
|
|
@@ -52535,21 +52629,22 @@ function detectTypecheckCommand(projectDir) {
|
|
|
52535
52629
|
...pkg.dependencies,
|
|
52536
52630
|
...pkg.devDependencies
|
|
52537
52631
|
};
|
|
52538
|
-
if (!deps?.typescript && !fs20.existsSync(
|
|
52539
|
-
|
|
52632
|
+
if (!deps?.typescript && !fs20.existsSync(path33.join(projectDir, "tsconfig.json"))) {}
|
|
52633
|
+
const hasTSMarkers = deps?.typescript || fs20.existsSync(path33.join(projectDir, "tsconfig.json"));
|
|
52634
|
+
if (hasTSMarkers) {
|
|
52635
|
+
return { command: ["npx", "tsc", "--noEmit"], language: "typescript" };
|
|
52540
52636
|
}
|
|
52541
|
-
return { command: ["npx", "tsc", "--noEmit"], language: "typescript" };
|
|
52542
52637
|
} catch {
|
|
52543
52638
|
return null;
|
|
52544
52639
|
}
|
|
52545
52640
|
}
|
|
52546
|
-
if (fs20.existsSync(
|
|
52641
|
+
if (fs20.existsSync(path33.join(projectDir, "go.mod"))) {
|
|
52547
52642
|
return { command: ["go", "vet", "./..."], language: "go" };
|
|
52548
52643
|
}
|
|
52549
|
-
if (fs20.existsSync(
|
|
52644
|
+
if (fs20.existsSync(path33.join(projectDir, "Cargo.toml"))) {
|
|
52550
52645
|
return { command: ["cargo", "check"], language: "rust" };
|
|
52551
52646
|
}
|
|
52552
|
-
if (fs20.existsSync(
|
|
52647
|
+
if (fs20.existsSync(path33.join(projectDir, "pyproject.toml")) || fs20.existsSync(path33.join(projectDir, "requirements.txt")) || fs20.existsSync(path33.join(projectDir, "setup.py"))) {
|
|
52553
52648
|
return { command: null, language: "python" };
|
|
52554
52649
|
}
|
|
52555
52650
|
try {
|
|
@@ -52620,7 +52715,7 @@ ${errorSummary}`);
|
|
|
52620
52715
|
// src/hooks/knowledge-reader.ts
|
|
52621
52716
|
import { existsSync as existsSync19 } from "fs";
|
|
52622
52717
|
import { mkdir as mkdir4, readFile as readFile5, writeFile as writeFile4 } from "fs/promises";
|
|
52623
|
-
import * as
|
|
52718
|
+
import * as path34 from "path";
|
|
52624
52719
|
var JACCARD_THRESHOLD = 0.6;
|
|
52625
52720
|
var HIVE_TIER_BOOST = 0.05;
|
|
52626
52721
|
var SAME_PROJECT_PENALTY = -0.05;
|
|
@@ -52668,7 +52763,7 @@ function inferCategoriesFromPhase(phaseDescription) {
|
|
|
52668
52763
|
return ["process", "tooling"];
|
|
52669
52764
|
}
|
|
52670
52765
|
async function recordLessonsShown(directory, lessonIds, currentPhase) {
|
|
52671
|
-
const shownFile =
|
|
52766
|
+
const shownFile = path34.join(directory, ".swarm", ".knowledge-shown.json");
|
|
52672
52767
|
try {
|
|
52673
52768
|
let shownData = {};
|
|
52674
52769
|
if (existsSync19(shownFile)) {
|
|
@@ -52676,7 +52771,7 @@ async function recordLessonsShown(directory, lessonIds, currentPhase) {
|
|
|
52676
52771
|
shownData = JSON.parse(content);
|
|
52677
52772
|
}
|
|
52678
52773
|
shownData[currentPhase] = lessonIds;
|
|
52679
|
-
await mkdir4(
|
|
52774
|
+
await mkdir4(path34.dirname(shownFile), { recursive: true });
|
|
52680
52775
|
await writeFile4(shownFile, JSON.stringify(shownData, null, 2), "utf-8");
|
|
52681
52776
|
} catch {
|
|
52682
52777
|
console.warn("[swarm] Knowledge: failed to record shown lessons");
|
|
@@ -52771,7 +52866,7 @@ async function readMergedKnowledge(directory, config3, context) {
|
|
|
52771
52866
|
return topN;
|
|
52772
52867
|
}
|
|
52773
52868
|
async function updateRetrievalOutcome(directory, phaseInfo, phaseSucceeded) {
|
|
52774
|
-
const shownFile =
|
|
52869
|
+
const shownFile = path34.join(directory, ".swarm", ".knowledge-shown.json");
|
|
52775
52870
|
try {
|
|
52776
52871
|
if (!existsSync19(shownFile)) {
|
|
52777
52872
|
return;
|
|
@@ -53244,10 +53339,10 @@ Use this data to avoid repeating known failure patterns.`;
|
|
|
53244
53339
|
init_event_bus();
|
|
53245
53340
|
init_utils2();
|
|
53246
53341
|
import * as fs21 from "fs";
|
|
53247
|
-
import * as
|
|
53342
|
+
import * as path35 from "path";
|
|
53248
53343
|
var DRIFT_REPORT_PREFIX = "drift-report-phase-";
|
|
53249
53344
|
async function readPriorDriftReports(directory) {
|
|
53250
|
-
const swarmDir =
|
|
53345
|
+
const swarmDir = path35.join(directory, ".swarm");
|
|
53251
53346
|
const entries = await fs21.promises.readdir(swarmDir).catch(() => null);
|
|
53252
53347
|
if (entries === null)
|
|
53253
53348
|
return [];
|
|
@@ -53274,7 +53369,7 @@ async function readPriorDriftReports(directory) {
|
|
|
53274
53369
|
async function writeDriftReport(directory, report) {
|
|
53275
53370
|
const filename = `${DRIFT_REPORT_PREFIX}${report.phase}.json`;
|
|
53276
53371
|
const filePath = validateSwarmPath(directory, filename);
|
|
53277
|
-
const swarmDir =
|
|
53372
|
+
const swarmDir = path35.dirname(filePath);
|
|
53278
53373
|
await fs21.promises.mkdir(swarmDir, { recursive: true });
|
|
53279
53374
|
try {
|
|
53280
53375
|
await fs21.promises.writeFile(filePath, JSON.stringify(report, null, 2), "utf-8");
|
|
@@ -53428,7 +53523,7 @@ function isOrchestratorAgent(agentName) {
|
|
|
53428
53523
|
function injectKnowledgeMessage(output, text) {
|
|
53429
53524
|
if (!output.messages)
|
|
53430
53525
|
return;
|
|
53431
|
-
const alreadyInjected = output.messages.some((m) => m.parts?.some((p) => p.text?.includes("\uD83D\uDCDA Knowledge")));
|
|
53526
|
+
const alreadyInjected = output.messages.some((m) => m.parts?.some((p) => p.text?.includes("\uD83D\uDCDA Knowledge") || p.text?.includes("<drift_report>") || p.text?.includes("<curator_briefing>")));
|
|
53432
53527
|
if (alreadyInjected)
|
|
53433
53528
|
return;
|
|
53434
53529
|
const systemIdx = output.messages.findIndex((m) => m.info?.role === "system");
|
|
@@ -53474,8 +53569,33 @@ function createKnowledgeInjectorHook(directory, config3) {
|
|
|
53474
53569
|
currentPhase: phaseDescription
|
|
53475
53570
|
};
|
|
53476
53571
|
const entries = await readMergedKnowledge(directory, config3, context);
|
|
53477
|
-
|
|
53572
|
+
try {
|
|
53573
|
+
const driftReports = await readPriorDriftReports(directory);
|
|
53574
|
+
if (driftReports.length > 0) {
|
|
53575
|
+
const latestReport = driftReports[driftReports.length - 1];
|
|
53576
|
+
const driftText = buildDriftInjectionText(latestReport, 500);
|
|
53577
|
+
if (driftText) {
|
|
53578
|
+
cachedInjectionText = cachedInjectionText ? `${driftText}
|
|
53579
|
+
|
|
53580
|
+
${cachedInjectionText}` : driftText;
|
|
53581
|
+
}
|
|
53582
|
+
}
|
|
53583
|
+
} catch {}
|
|
53584
|
+
try {
|
|
53585
|
+
const briefingContent = await readSwarmFileAsync(directory, "curator-briefing.md");
|
|
53586
|
+
if (briefingContent) {
|
|
53587
|
+
const truncatedBriefing = briefingContent.slice(0, 500);
|
|
53588
|
+
cachedInjectionText = cachedInjectionText ? `<curator_briefing>${truncatedBriefing}</curator_briefing>
|
|
53589
|
+
|
|
53590
|
+
${cachedInjectionText}` : `<curator_briefing>${truncatedBriefing}</curator_briefing>`;
|
|
53591
|
+
}
|
|
53592
|
+
} catch {}
|
|
53593
|
+
if (entries.length === 0) {
|
|
53594
|
+
if (cachedInjectionText === null)
|
|
53595
|
+
return;
|
|
53596
|
+
injectKnowledgeMessage(output, cachedInjectionText);
|
|
53478
53597
|
return;
|
|
53598
|
+
}
|
|
53479
53599
|
const runMemory = await getRunMemorySummary(directory);
|
|
53480
53600
|
const lines = entries.map((entry) => {
|
|
53481
53601
|
const stars = formatStars(entry.confidence);
|
|
@@ -53494,13 +53614,15 @@ function createKnowledgeInjectorHook(directory, config3) {
|
|
|
53494
53614
|
"These are lessons learned from this project and past projects. Consider them as context but use your judgment \u2014 they may not all apply."
|
|
53495
53615
|
].join(`
|
|
53496
53616
|
`);
|
|
53617
|
+
let injectionText = cachedInjectionText ? `${cachedInjectionText}
|
|
53618
|
+
|
|
53619
|
+
${knowledgeSection}` : knowledgeSection;
|
|
53497
53620
|
if (runMemory) {
|
|
53498
|
-
|
|
53621
|
+
injectionText = `${runMemory}
|
|
53499
53622
|
|
|
53500
|
-
${
|
|
53501
|
-
} else {
|
|
53502
|
-
cachedInjectionText = knowledgeSection;
|
|
53623
|
+
${injectionText}`;
|
|
53503
53624
|
}
|
|
53625
|
+
cachedInjectionText = injectionText;
|
|
53504
53626
|
const rejected = await readRejectedLessons(directory);
|
|
53505
53627
|
if (rejected.length > 0) {
|
|
53506
53628
|
const recentRejected = rejected.slice(-3);
|
|
@@ -53511,25 +53633,13 @@ ${knowledgeSection}`;
|
|
|
53511
53633
|
` + rejectedLines.join(`
|
|
53512
53634
|
`);
|
|
53513
53635
|
}
|
|
53514
|
-
try {
|
|
53515
|
-
const driftReports = await readPriorDriftReports(directory);
|
|
53516
|
-
if (driftReports.length > 0 && cachedInjectionText !== null) {
|
|
53517
|
-
const latestReport = driftReports[driftReports.length - 1];
|
|
53518
|
-
const driftText = buildDriftInjectionText(latestReport, 500);
|
|
53519
|
-
if (driftText) {
|
|
53520
|
-
cachedInjectionText = `${driftText}
|
|
53521
|
-
|
|
53522
|
-
${cachedInjectionText}`;
|
|
53523
|
-
}
|
|
53524
|
-
}
|
|
53525
|
-
} catch {}
|
|
53526
53636
|
injectKnowledgeMessage(output, cachedInjectionText);
|
|
53527
53637
|
});
|
|
53528
53638
|
}
|
|
53529
53639
|
|
|
53530
53640
|
// src/hooks/slop-detector.ts
|
|
53531
53641
|
import * as fs22 from "fs";
|
|
53532
|
-
import * as
|
|
53642
|
+
import * as path36 from "path";
|
|
53533
53643
|
var WRITE_EDIT_TOOLS = new Set([
|
|
53534
53644
|
"write",
|
|
53535
53645
|
"edit",
|
|
@@ -53579,7 +53689,7 @@ function walkFiles(dir, exts, deadline) {
|
|
|
53579
53689
|
break;
|
|
53580
53690
|
if (entry.isSymbolicLink())
|
|
53581
53691
|
continue;
|
|
53582
|
-
const full =
|
|
53692
|
+
const full = path36.join(dir, entry.name);
|
|
53583
53693
|
if (entry.isDirectory()) {
|
|
53584
53694
|
if (entry.name === "node_modules" || entry.name === ".git")
|
|
53585
53695
|
continue;
|
|
@@ -53594,7 +53704,7 @@ function walkFiles(dir, exts, deadline) {
|
|
|
53594
53704
|
return results;
|
|
53595
53705
|
}
|
|
53596
53706
|
function checkDeadExports(content, projectDir, startTime) {
|
|
53597
|
-
const hasPackageJson = fs22.existsSync(
|
|
53707
|
+
const hasPackageJson = fs22.existsSync(path36.join(projectDir, "package.json"));
|
|
53598
53708
|
if (!hasPackageJson)
|
|
53599
53709
|
return null;
|
|
53600
53710
|
const exportMatches = content.matchAll(/^\+(?:export)\s+(?:function|class|const|type|interface)\s+(\w{3,})/gm);
|
|
@@ -53744,7 +53854,7 @@ init_config_doctor();
|
|
|
53744
53854
|
|
|
53745
53855
|
// src/session/snapshot-reader.ts
|
|
53746
53856
|
init_utils2();
|
|
53747
|
-
import
|
|
53857
|
+
import path37 from "path";
|
|
53748
53858
|
var VALID_TASK_WORKFLOW_STATES = [
|
|
53749
53859
|
"idle",
|
|
53750
53860
|
"coder_delegated",
|
|
@@ -53869,7 +53979,7 @@ function rehydrateState(snapshot) {
|
|
|
53869
53979
|
async function reconcileTaskStatesFromPlan(directory) {
|
|
53870
53980
|
let raw;
|
|
53871
53981
|
try {
|
|
53872
|
-
raw = await Bun.file(
|
|
53982
|
+
raw = await Bun.file(path37.join(directory, ".swarm/plan.json")).text();
|
|
53873
53983
|
} catch {
|
|
53874
53984
|
return;
|
|
53875
53985
|
}
|
|
@@ -54092,7 +54202,7 @@ var build_check = createSwarmTool({
|
|
|
54092
54202
|
init_dist();
|
|
54093
54203
|
init_create_tool();
|
|
54094
54204
|
import * as fs24 from "fs";
|
|
54095
|
-
import * as
|
|
54205
|
+
import * as path38 from "path";
|
|
54096
54206
|
var EVIDENCE_DIR = ".swarm/evidence";
|
|
54097
54207
|
var TASK_ID_PATTERN2 = /^\d+\.\d+(\.\d+)*$/;
|
|
54098
54208
|
function isValidTaskId3(taskId) {
|
|
@@ -54109,9 +54219,9 @@ function isValidTaskId3(taskId) {
|
|
|
54109
54219
|
return TASK_ID_PATTERN2.test(taskId);
|
|
54110
54220
|
}
|
|
54111
54221
|
function isPathWithinSwarm(filePath, workspaceRoot) {
|
|
54112
|
-
const normalizedWorkspace =
|
|
54113
|
-
const swarmPath =
|
|
54114
|
-
const normalizedPath =
|
|
54222
|
+
const normalizedWorkspace = path38.resolve(workspaceRoot);
|
|
54223
|
+
const swarmPath = path38.join(normalizedWorkspace, ".swarm", "evidence");
|
|
54224
|
+
const normalizedPath = path38.resolve(filePath);
|
|
54115
54225
|
return normalizedPath.startsWith(swarmPath);
|
|
54116
54226
|
}
|
|
54117
54227
|
function readEvidenceFile(evidencePath) {
|
|
@@ -54172,7 +54282,7 @@ var check_gate_status = createSwarmTool({
|
|
|
54172
54282
|
};
|
|
54173
54283
|
return JSON.stringify(errorResult, null, 2);
|
|
54174
54284
|
}
|
|
54175
|
-
const evidencePath =
|
|
54285
|
+
const evidencePath = path38.join(directory, EVIDENCE_DIR, `${taskIdInput}.json`);
|
|
54176
54286
|
if (!isPathWithinSwarm(evidencePath, directory)) {
|
|
54177
54287
|
const errorResult = {
|
|
54178
54288
|
taskId: taskIdInput,
|
|
@@ -54233,7 +54343,7 @@ init_tool();
|
|
|
54233
54343
|
init_create_tool();
|
|
54234
54344
|
import { spawnSync } from "child_process";
|
|
54235
54345
|
import * as fs25 from "fs";
|
|
54236
|
-
import * as
|
|
54346
|
+
import * as path39 from "path";
|
|
54237
54347
|
var CHECKPOINT_LOG_PATH = ".swarm/checkpoints.json";
|
|
54238
54348
|
var MAX_LABEL_LENGTH = 100;
|
|
54239
54349
|
var GIT_TIMEOUT_MS = 30000;
|
|
@@ -54284,7 +54394,7 @@ function validateLabel(label) {
|
|
|
54284
54394
|
return null;
|
|
54285
54395
|
}
|
|
54286
54396
|
function getCheckpointLogPath(directory) {
|
|
54287
|
-
return
|
|
54397
|
+
return path39.join(directory, CHECKPOINT_LOG_PATH);
|
|
54288
54398
|
}
|
|
54289
54399
|
function readCheckpointLog(directory) {
|
|
54290
54400
|
const logPath = getCheckpointLogPath(directory);
|
|
@@ -54302,7 +54412,7 @@ function readCheckpointLog(directory) {
|
|
|
54302
54412
|
}
|
|
54303
54413
|
function writeCheckpointLog(log2, directory) {
|
|
54304
54414
|
const logPath = getCheckpointLogPath(directory);
|
|
54305
|
-
const dir =
|
|
54415
|
+
const dir = path39.dirname(logPath);
|
|
54306
54416
|
if (!fs25.existsSync(dir)) {
|
|
54307
54417
|
fs25.mkdirSync(dir, { recursive: true });
|
|
54308
54418
|
}
|
|
@@ -54510,7 +54620,7 @@ var checkpoint = createSwarmTool({
|
|
|
54510
54620
|
init_dist();
|
|
54511
54621
|
init_create_tool();
|
|
54512
54622
|
import * as fs26 from "fs";
|
|
54513
|
-
import * as
|
|
54623
|
+
import * as path40 from "path";
|
|
54514
54624
|
var MAX_FILE_SIZE_BYTES2 = 256 * 1024;
|
|
54515
54625
|
var DEFAULT_DAYS = 90;
|
|
54516
54626
|
var DEFAULT_TOP_N = 20;
|
|
@@ -54654,7 +54764,7 @@ async function analyzeHotspots(days, topN, extensions, directory) {
|
|
|
54654
54764
|
const extSet = new Set(extensions.map((e) => e.startsWith(".") ? e : `.${e}`));
|
|
54655
54765
|
const filteredChurn = new Map;
|
|
54656
54766
|
for (const [file3, count] of churnMap) {
|
|
54657
|
-
const ext =
|
|
54767
|
+
const ext = path40.extname(file3).toLowerCase();
|
|
54658
54768
|
if (extSet.has(ext)) {
|
|
54659
54769
|
filteredChurn.set(file3, count);
|
|
54660
54770
|
}
|
|
@@ -54665,7 +54775,7 @@ async function analyzeHotspots(days, topN, extensions, directory) {
|
|
|
54665
54775
|
for (const [file3, churnCount] of filteredChurn) {
|
|
54666
54776
|
let fullPath = file3;
|
|
54667
54777
|
if (!fs26.existsSync(fullPath)) {
|
|
54668
|
-
fullPath =
|
|
54778
|
+
fullPath = path40.join(cwd, file3);
|
|
54669
54779
|
}
|
|
54670
54780
|
const complexity = getComplexityForFile(fullPath);
|
|
54671
54781
|
if (complexity !== null) {
|
|
@@ -54813,7 +54923,7 @@ var complexity_hotspots = createSwarmTool({
|
|
|
54813
54923
|
// src/tools/declare-scope.ts
|
|
54814
54924
|
init_tool();
|
|
54815
54925
|
import * as fs27 from "fs";
|
|
54816
|
-
import * as
|
|
54926
|
+
import * as path41 from "path";
|
|
54817
54927
|
init_create_tool();
|
|
54818
54928
|
function validateTaskIdFormat(taskId) {
|
|
54819
54929
|
const taskIdPattern = /^\d+\.\d+(\.\d+)*$/;
|
|
@@ -54892,8 +55002,8 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
54892
55002
|
};
|
|
54893
55003
|
}
|
|
54894
55004
|
}
|
|
54895
|
-
normalizedDir =
|
|
54896
|
-
const pathParts = normalizedDir.split(
|
|
55005
|
+
normalizedDir = path41.normalize(args2.working_directory);
|
|
55006
|
+
const pathParts = normalizedDir.split(path41.sep);
|
|
54897
55007
|
if (pathParts.includes("..")) {
|
|
54898
55008
|
return {
|
|
54899
55009
|
success: false,
|
|
@@ -54903,10 +55013,10 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
54903
55013
|
]
|
|
54904
55014
|
};
|
|
54905
55015
|
}
|
|
54906
|
-
const resolvedDir =
|
|
55016
|
+
const resolvedDir = path41.resolve(normalizedDir);
|
|
54907
55017
|
try {
|
|
54908
55018
|
const realPath = fs27.realpathSync(resolvedDir);
|
|
54909
|
-
const planPath2 =
|
|
55019
|
+
const planPath2 = path41.join(realPath, ".swarm", "plan.json");
|
|
54910
55020
|
if (!fs27.existsSync(planPath2)) {
|
|
54911
55021
|
return {
|
|
54912
55022
|
success: false,
|
|
@@ -54927,7 +55037,7 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
54927
55037
|
}
|
|
54928
55038
|
}
|
|
54929
55039
|
const directory = normalizedDir ?? fallbackDir ?? process.cwd();
|
|
54930
|
-
const planPath =
|
|
55040
|
+
const planPath = path41.resolve(directory, ".swarm", "plan.json");
|
|
54931
55041
|
if (!fs27.existsSync(planPath)) {
|
|
54932
55042
|
return {
|
|
54933
55043
|
success: false,
|
|
@@ -55017,20 +55127,20 @@ function validateBase(base) {
|
|
|
55017
55127
|
function validatePaths(paths) {
|
|
55018
55128
|
if (!paths)
|
|
55019
55129
|
return null;
|
|
55020
|
-
for (const
|
|
55021
|
-
if (!
|
|
55130
|
+
for (const path42 of paths) {
|
|
55131
|
+
if (!path42 || path42.length === 0) {
|
|
55022
55132
|
return "empty path not allowed";
|
|
55023
55133
|
}
|
|
55024
|
-
if (
|
|
55134
|
+
if (path42.length > MAX_PATH_LENGTH) {
|
|
55025
55135
|
return `path exceeds maximum length of ${MAX_PATH_LENGTH}`;
|
|
55026
55136
|
}
|
|
55027
|
-
if (SHELL_METACHARACTERS2.test(
|
|
55137
|
+
if (SHELL_METACHARACTERS2.test(path42)) {
|
|
55028
55138
|
return "path contains shell metacharacters";
|
|
55029
55139
|
}
|
|
55030
|
-
if (
|
|
55140
|
+
if (path42.startsWith("-")) {
|
|
55031
55141
|
return 'path cannot start with "-" (option-like arguments not allowed)';
|
|
55032
55142
|
}
|
|
55033
|
-
if (CONTROL_CHAR_PATTERN2.test(
|
|
55143
|
+
if (CONTROL_CHAR_PATTERN2.test(path42)) {
|
|
55034
55144
|
return "path contains control characters";
|
|
55035
55145
|
}
|
|
55036
55146
|
}
|
|
@@ -55110,8 +55220,8 @@ var diff = tool({
|
|
|
55110
55220
|
if (parts2.length >= 3) {
|
|
55111
55221
|
const additions = parseInt(parts2[0], 10) || 0;
|
|
55112
55222
|
const deletions = parseInt(parts2[1], 10) || 0;
|
|
55113
|
-
const
|
|
55114
|
-
files.push({ path:
|
|
55223
|
+
const path42 = parts2[2];
|
|
55224
|
+
files.push({ path: path42, additions, deletions });
|
|
55115
55225
|
}
|
|
55116
55226
|
}
|
|
55117
55227
|
const contractChanges = [];
|
|
@@ -55341,7 +55451,7 @@ Use these as DOMAIN values when delegating to @sme.`;
|
|
|
55341
55451
|
init_dist();
|
|
55342
55452
|
init_create_tool();
|
|
55343
55453
|
import * as fs28 from "fs";
|
|
55344
|
-
import * as
|
|
55454
|
+
import * as path42 from "path";
|
|
55345
55455
|
var MAX_FILE_SIZE_BYTES3 = 1024 * 1024;
|
|
55346
55456
|
var MAX_EVIDENCE_FILES = 1000;
|
|
55347
55457
|
var EVIDENCE_DIR2 = ".swarm/evidence";
|
|
@@ -55371,9 +55481,9 @@ function validateRequiredTypes(input) {
|
|
|
55371
55481
|
return null;
|
|
55372
55482
|
}
|
|
55373
55483
|
function isPathWithinSwarm2(filePath, cwd) {
|
|
55374
|
-
const normalizedCwd =
|
|
55375
|
-
const swarmPath =
|
|
55376
|
-
const normalizedPath =
|
|
55484
|
+
const normalizedCwd = path42.resolve(cwd);
|
|
55485
|
+
const swarmPath = path42.join(normalizedCwd, ".swarm");
|
|
55486
|
+
const normalizedPath = path42.resolve(filePath);
|
|
55377
55487
|
return normalizedPath.startsWith(swarmPath);
|
|
55378
55488
|
}
|
|
55379
55489
|
function parseCompletedTasks(planContent) {
|
|
@@ -55403,10 +55513,10 @@ function readEvidenceFiles(evidenceDir, _cwd) {
|
|
|
55403
55513
|
if (!VALID_EVIDENCE_FILENAME_REGEX.test(filename)) {
|
|
55404
55514
|
continue;
|
|
55405
55515
|
}
|
|
55406
|
-
const filePath =
|
|
55516
|
+
const filePath = path42.join(evidenceDir, filename);
|
|
55407
55517
|
try {
|
|
55408
|
-
const resolvedPath =
|
|
55409
|
-
const evidenceDirResolved =
|
|
55518
|
+
const resolvedPath = path42.resolve(filePath);
|
|
55519
|
+
const evidenceDirResolved = path42.resolve(evidenceDir);
|
|
55410
55520
|
if (!resolvedPath.startsWith(evidenceDirResolved)) {
|
|
55411
55521
|
continue;
|
|
55412
55522
|
}
|
|
@@ -55524,7 +55634,7 @@ var evidence_check = createSwarmTool({
|
|
|
55524
55634
|
return JSON.stringify(errorResult, null, 2);
|
|
55525
55635
|
}
|
|
55526
55636
|
const requiredTypes = requiredTypesValue.split(",").map((t) => t.trim()).filter((t) => t.length > 0).map(normalizeEvidenceType);
|
|
55527
|
-
const planPath =
|
|
55637
|
+
const planPath = path42.join(cwd, PLAN_FILE);
|
|
55528
55638
|
if (!isPathWithinSwarm2(planPath, cwd)) {
|
|
55529
55639
|
const errorResult = {
|
|
55530
55640
|
error: "plan file path validation failed",
|
|
@@ -55556,7 +55666,7 @@ var evidence_check = createSwarmTool({
|
|
|
55556
55666
|
};
|
|
55557
55667
|
return JSON.stringify(result2, null, 2);
|
|
55558
55668
|
}
|
|
55559
|
-
const evidenceDir =
|
|
55669
|
+
const evidenceDir = path42.join(cwd, EVIDENCE_DIR2);
|
|
55560
55670
|
const evidence = readEvidenceFiles(evidenceDir, cwd);
|
|
55561
55671
|
const { tasksWithFullEvidence, gaps } = analyzeGaps(completedTasks, evidence, requiredTypes);
|
|
55562
55672
|
const completeness = completedTasks.length > 0 ? Math.round(tasksWithFullEvidence.length / completedTasks.length * 100) / 100 : 1;
|
|
@@ -55574,7 +55684,7 @@ var evidence_check = createSwarmTool({
|
|
|
55574
55684
|
init_tool();
|
|
55575
55685
|
init_create_tool();
|
|
55576
55686
|
import * as fs29 from "fs";
|
|
55577
|
-
import * as
|
|
55687
|
+
import * as path43 from "path";
|
|
55578
55688
|
var EXT_MAP = {
|
|
55579
55689
|
python: ".py",
|
|
55580
55690
|
py: ".py",
|
|
@@ -55655,12 +55765,12 @@ var extract_code_blocks = createSwarmTool({
|
|
|
55655
55765
|
if (prefix) {
|
|
55656
55766
|
filename = `${prefix}_${filename}`;
|
|
55657
55767
|
}
|
|
55658
|
-
let filepath =
|
|
55659
|
-
const base =
|
|
55660
|
-
const ext =
|
|
55768
|
+
let filepath = path43.join(targetDir, filename);
|
|
55769
|
+
const base = path43.basename(filepath, path43.extname(filepath));
|
|
55770
|
+
const ext = path43.extname(filepath);
|
|
55661
55771
|
let counter = 1;
|
|
55662
55772
|
while (fs29.existsSync(filepath)) {
|
|
55663
|
-
filepath =
|
|
55773
|
+
filepath = path43.join(targetDir, `${base}_${counter}${ext}`);
|
|
55664
55774
|
counter++;
|
|
55665
55775
|
}
|
|
55666
55776
|
try {
|
|
@@ -55778,7 +55888,7 @@ var gitingest = tool({
|
|
|
55778
55888
|
// src/tools/imports.ts
|
|
55779
55889
|
init_dist();
|
|
55780
55890
|
import * as fs30 from "fs";
|
|
55781
|
-
import * as
|
|
55891
|
+
import * as path44 from "path";
|
|
55782
55892
|
var MAX_FILE_PATH_LENGTH2 = 500;
|
|
55783
55893
|
var MAX_SYMBOL_LENGTH = 256;
|
|
55784
55894
|
var MAX_FILE_SIZE_BYTES4 = 1024 * 1024;
|
|
@@ -55832,7 +55942,7 @@ function validateSymbolInput(symbol3) {
|
|
|
55832
55942
|
return null;
|
|
55833
55943
|
}
|
|
55834
55944
|
function isBinaryFile2(filePath, buffer) {
|
|
55835
|
-
const ext =
|
|
55945
|
+
const ext = path44.extname(filePath).toLowerCase();
|
|
55836
55946
|
if (ext === ".json" || ext === ".md" || ext === ".txt") {
|
|
55837
55947
|
return false;
|
|
55838
55948
|
}
|
|
@@ -55856,15 +55966,15 @@ function parseImports(content, targetFile, targetSymbol) {
|
|
|
55856
55966
|
const imports = [];
|
|
55857
55967
|
let _resolvedTarget;
|
|
55858
55968
|
try {
|
|
55859
|
-
_resolvedTarget =
|
|
55969
|
+
_resolvedTarget = path44.resolve(targetFile);
|
|
55860
55970
|
} catch {
|
|
55861
55971
|
_resolvedTarget = targetFile;
|
|
55862
55972
|
}
|
|
55863
|
-
const targetBasename =
|
|
55973
|
+
const targetBasename = path44.basename(targetFile, path44.extname(targetFile));
|
|
55864
55974
|
const targetWithExt = targetFile;
|
|
55865
55975
|
const targetWithoutExt = targetFile.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
|
|
55866
|
-
const normalizedTargetWithExt =
|
|
55867
|
-
const normalizedTargetWithoutExt =
|
|
55976
|
+
const normalizedTargetWithExt = path44.normalize(targetWithExt).replace(/\\/g, "/");
|
|
55977
|
+
const normalizedTargetWithoutExt = path44.normalize(targetWithoutExt).replace(/\\/g, "/");
|
|
55868
55978
|
const importRegex = /import\s+(?:\{[\s\S]*?\}|(?:\*\s+as\s+\w+)|\w+)\s+from\s+['"`]([^'"`]+)['"`]|import\s+['"`]([^'"`]+)['"`]|require\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g;
|
|
55869
55979
|
for (let match = importRegex.exec(content);match !== null; match = importRegex.exec(content)) {
|
|
55870
55980
|
const modulePath = match[1] || match[2] || match[3];
|
|
@@ -55887,9 +55997,9 @@ function parseImports(content, targetFile, targetSymbol) {
|
|
|
55887
55997
|
}
|
|
55888
55998
|
const _normalizedModule = modulePath.replace(/^\.\//, "").replace(/^\.\.\\/, "../");
|
|
55889
55999
|
let isMatch = false;
|
|
55890
|
-
const _targetDir =
|
|
55891
|
-
const targetExt =
|
|
55892
|
-
const targetBasenameNoExt =
|
|
56000
|
+
const _targetDir = path44.dirname(targetFile);
|
|
56001
|
+
const targetExt = path44.extname(targetFile);
|
|
56002
|
+
const targetBasenameNoExt = path44.basename(targetFile, targetExt);
|
|
55893
56003
|
const moduleNormalized = modulePath.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
55894
56004
|
const moduleName = modulePath.split(/[/\\]/).pop() || "";
|
|
55895
56005
|
const moduleNameNoExt = moduleName.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
|
|
@@ -55957,10 +56067,10 @@ function findSourceFiles(dir, files = [], stats = { skippedDirs: [], skippedFile
|
|
|
55957
56067
|
entries.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
|
|
55958
56068
|
for (const entry of entries) {
|
|
55959
56069
|
if (SKIP_DIRECTORIES2.has(entry)) {
|
|
55960
|
-
stats.skippedDirs.push(
|
|
56070
|
+
stats.skippedDirs.push(path44.join(dir, entry));
|
|
55961
56071
|
continue;
|
|
55962
56072
|
}
|
|
55963
|
-
const fullPath =
|
|
56073
|
+
const fullPath = path44.join(dir, entry);
|
|
55964
56074
|
let stat2;
|
|
55965
56075
|
try {
|
|
55966
56076
|
stat2 = fs30.statSync(fullPath);
|
|
@@ -55974,7 +56084,7 @@ function findSourceFiles(dir, files = [], stats = { skippedDirs: [], skippedFile
|
|
|
55974
56084
|
if (stat2.isDirectory()) {
|
|
55975
56085
|
findSourceFiles(fullPath, files, stats);
|
|
55976
56086
|
} else if (stat2.isFile()) {
|
|
55977
|
-
const ext =
|
|
56087
|
+
const ext = path44.extname(fullPath).toLowerCase();
|
|
55978
56088
|
if (SUPPORTED_EXTENSIONS.includes(ext)) {
|
|
55979
56089
|
files.push(fullPath);
|
|
55980
56090
|
}
|
|
@@ -56030,7 +56140,7 @@ var imports = tool({
|
|
|
56030
56140
|
return JSON.stringify(errorResult, null, 2);
|
|
56031
56141
|
}
|
|
56032
56142
|
try {
|
|
56033
|
-
const targetFile =
|
|
56143
|
+
const targetFile = path44.resolve(file3);
|
|
56034
56144
|
if (!fs30.existsSync(targetFile)) {
|
|
56035
56145
|
const errorResult = {
|
|
56036
56146
|
error: `target file not found: ${file3}`,
|
|
@@ -56052,7 +56162,7 @@ var imports = tool({
|
|
|
56052
56162
|
};
|
|
56053
56163
|
return JSON.stringify(errorResult, null, 2);
|
|
56054
56164
|
}
|
|
56055
|
-
const baseDir =
|
|
56165
|
+
const baseDir = path44.dirname(targetFile);
|
|
56056
56166
|
const scanStats = {
|
|
56057
56167
|
skippedDirs: [],
|
|
56058
56168
|
skippedFiles: 0,
|
|
@@ -56374,7 +56484,7 @@ init_config();
|
|
|
56374
56484
|
init_schema();
|
|
56375
56485
|
init_manager();
|
|
56376
56486
|
import * as fs31 from "fs";
|
|
56377
|
-
import * as
|
|
56487
|
+
import * as path45 from "path";
|
|
56378
56488
|
init_utils2();
|
|
56379
56489
|
init_create_tool();
|
|
56380
56490
|
function safeWarn(message, error93) {
|
|
@@ -56569,7 +56679,7 @@ async function executePhaseComplete(args2, workingDirectory) {
|
|
|
56569
56679
|
}
|
|
56570
56680
|
if (retroFound && retroEntry?.lessons_learned && retroEntry.lessons_learned.length > 0) {
|
|
56571
56681
|
try {
|
|
56572
|
-
const projectName =
|
|
56682
|
+
const projectName = path45.basename(dir);
|
|
56573
56683
|
const knowledgeConfig = {
|
|
56574
56684
|
enabled: true,
|
|
56575
56685
|
swarm_max_entries: 100,
|
|
@@ -56598,12 +56708,17 @@ async function executePhaseComplete(args2, workingDirectory) {
|
|
|
56598
56708
|
safeWarn("[phase_complete] Failed to curate lessons from retrospective:", error93);
|
|
56599
56709
|
}
|
|
56600
56710
|
}
|
|
56711
|
+
let complianceWarnings = [];
|
|
56601
56712
|
try {
|
|
56602
56713
|
const curatorConfig = CuratorConfigSchema.parse(config3.curator ?? {});
|
|
56603
56714
|
if (curatorConfig.enabled && curatorConfig.phase_enabled) {
|
|
56604
56715
|
const curatorResult = await runCuratorPhase(dir, phase, agentsDispatched, curatorConfig, {});
|
|
56605
56716
|
await applyCuratorKnowledgeUpdates(dir, curatorResult.knowledge_recommendations, {});
|
|
56606
56717
|
await runCriticDriftCheck(dir, phase, curatorResult, curatorConfig);
|
|
56718
|
+
if (curatorResult.compliance.length > 0 && !curatorConfig.suppress_warnings) {
|
|
56719
|
+
const complianceLines = curatorResult.compliance.map((obs) => `[${obs.severity.toUpperCase()}] ${obs.description}`).slice(0, 5);
|
|
56720
|
+
complianceWarnings = complianceLines;
|
|
56721
|
+
}
|
|
56607
56722
|
}
|
|
56608
56723
|
} catch (curatorError) {
|
|
56609
56724
|
safeWarn("[phase_complete] Curator pipeline error (non-blocking):", curatorError);
|
|
@@ -56689,6 +56804,9 @@ async function executePhaseComplete(args2, workingDirectory) {
|
|
|
56689
56804
|
warnings.push(`Warning: failed to update plan.json phase status: ${error93 instanceof Error ? error93.message : String(error93)}`);
|
|
56690
56805
|
}
|
|
56691
56806
|
}
|
|
56807
|
+
if (complianceWarnings.length > 0) {
|
|
56808
|
+
warnings.push(`Curator compliance: ${complianceWarnings.join("; ")}`);
|
|
56809
|
+
}
|
|
56692
56810
|
const result = {
|
|
56693
56811
|
success: success3,
|
|
56694
56812
|
phase,
|
|
@@ -56733,7 +56851,7 @@ init_discovery();
|
|
|
56733
56851
|
init_utils();
|
|
56734
56852
|
init_create_tool();
|
|
56735
56853
|
import * as fs32 from "fs";
|
|
56736
|
-
import * as
|
|
56854
|
+
import * as path46 from "path";
|
|
56737
56855
|
var MAX_OUTPUT_BYTES5 = 52428800;
|
|
56738
56856
|
var AUDIT_TIMEOUT_MS = 120000;
|
|
56739
56857
|
function isValidEcosystem(value) {
|
|
@@ -56751,16 +56869,16 @@ function validateArgs3(args2) {
|
|
|
56751
56869
|
function detectEcosystems(directory) {
|
|
56752
56870
|
const ecosystems = [];
|
|
56753
56871
|
const cwd = directory;
|
|
56754
|
-
if (fs32.existsSync(
|
|
56872
|
+
if (fs32.existsSync(path46.join(cwd, "package.json"))) {
|
|
56755
56873
|
ecosystems.push("npm");
|
|
56756
56874
|
}
|
|
56757
|
-
if (fs32.existsSync(
|
|
56875
|
+
if (fs32.existsSync(path46.join(cwd, "pyproject.toml")) || fs32.existsSync(path46.join(cwd, "requirements.txt"))) {
|
|
56758
56876
|
ecosystems.push("pip");
|
|
56759
56877
|
}
|
|
56760
|
-
if (fs32.existsSync(
|
|
56878
|
+
if (fs32.existsSync(path46.join(cwd, "Cargo.toml"))) {
|
|
56761
56879
|
ecosystems.push("cargo");
|
|
56762
56880
|
}
|
|
56763
|
-
if (fs32.existsSync(
|
|
56881
|
+
if (fs32.existsSync(path46.join(cwd, "go.mod"))) {
|
|
56764
56882
|
ecosystems.push("go");
|
|
56765
56883
|
}
|
|
56766
56884
|
try {
|
|
@@ -56769,10 +56887,10 @@ function detectEcosystems(directory) {
|
|
|
56769
56887
|
ecosystems.push("dotnet");
|
|
56770
56888
|
}
|
|
56771
56889
|
} catch {}
|
|
56772
|
-
if (fs32.existsSync(
|
|
56890
|
+
if (fs32.existsSync(path46.join(cwd, "Gemfile")) || fs32.existsSync(path46.join(cwd, "Gemfile.lock"))) {
|
|
56773
56891
|
ecosystems.push("ruby");
|
|
56774
56892
|
}
|
|
56775
|
-
if (fs32.existsSync(
|
|
56893
|
+
if (fs32.existsSync(path46.join(cwd, "pubspec.yaml"))) {
|
|
56776
56894
|
ecosystems.push("dart");
|
|
56777
56895
|
}
|
|
56778
56896
|
return ecosystems;
|
|
@@ -57835,7 +57953,7 @@ var SUPPORTED_PARSER_EXTENSIONS = new Set([
|
|
|
57835
57953
|
// src/tools/pre-check-batch.ts
|
|
57836
57954
|
init_dist();
|
|
57837
57955
|
import * as fs35 from "fs";
|
|
57838
|
-
import * as
|
|
57956
|
+
import * as path49 from "path";
|
|
57839
57957
|
|
|
57840
57958
|
// node_modules/yocto-queue/index.js
|
|
57841
57959
|
class Node2 {
|
|
@@ -58003,7 +58121,7 @@ init_manager();
|
|
|
58003
58121
|
|
|
58004
58122
|
// src/quality/metrics.ts
|
|
58005
58123
|
import * as fs33 from "fs";
|
|
58006
|
-
import * as
|
|
58124
|
+
import * as path47 from "path";
|
|
58007
58125
|
var MAX_FILE_SIZE_BYTES5 = 256 * 1024;
|
|
58008
58126
|
var MIN_DUPLICATION_LINES = 10;
|
|
58009
58127
|
function estimateCyclomaticComplexity(content) {
|
|
@@ -58055,7 +58173,7 @@ async function computeComplexityDelta(files, workingDir) {
|
|
|
58055
58173
|
let totalComplexity = 0;
|
|
58056
58174
|
const analyzedFiles = [];
|
|
58057
58175
|
for (const file3 of files) {
|
|
58058
|
-
const fullPath =
|
|
58176
|
+
const fullPath = path47.isAbsolute(file3) ? file3 : path47.join(workingDir, file3);
|
|
58059
58177
|
if (!fs33.existsSync(fullPath)) {
|
|
58060
58178
|
continue;
|
|
58061
58179
|
}
|
|
@@ -58178,7 +58296,7 @@ function countGoExports(content) {
|
|
|
58178
58296
|
function getExportCountForFile(filePath) {
|
|
58179
58297
|
try {
|
|
58180
58298
|
const content = fs33.readFileSync(filePath, "utf-8");
|
|
58181
|
-
const ext =
|
|
58299
|
+
const ext = path47.extname(filePath).toLowerCase();
|
|
58182
58300
|
switch (ext) {
|
|
58183
58301
|
case ".ts":
|
|
58184
58302
|
case ".tsx":
|
|
@@ -58204,7 +58322,7 @@ async function computePublicApiDelta(files, workingDir) {
|
|
|
58204
58322
|
let totalExports = 0;
|
|
58205
58323
|
const analyzedFiles = [];
|
|
58206
58324
|
for (const file3 of files) {
|
|
58207
|
-
const fullPath =
|
|
58325
|
+
const fullPath = path47.isAbsolute(file3) ? file3 : path47.join(workingDir, file3);
|
|
58208
58326
|
if (!fs33.existsSync(fullPath)) {
|
|
58209
58327
|
continue;
|
|
58210
58328
|
}
|
|
@@ -58238,7 +58356,7 @@ async function computeDuplicationRatio(files, workingDir) {
|
|
|
58238
58356
|
let duplicateLines = 0;
|
|
58239
58357
|
const analyzedFiles = [];
|
|
58240
58358
|
for (const file3 of files) {
|
|
58241
|
-
const fullPath =
|
|
58359
|
+
const fullPath = path47.isAbsolute(file3) ? file3 : path47.join(workingDir, file3);
|
|
58242
58360
|
if (!fs33.existsSync(fullPath)) {
|
|
58243
58361
|
continue;
|
|
58244
58362
|
}
|
|
@@ -58271,8 +58389,8 @@ function countCodeLines(content) {
|
|
|
58271
58389
|
return lines.length;
|
|
58272
58390
|
}
|
|
58273
58391
|
function isTestFile(filePath) {
|
|
58274
|
-
const basename8 =
|
|
58275
|
-
const _ext =
|
|
58392
|
+
const basename8 = path47.basename(filePath);
|
|
58393
|
+
const _ext = path47.extname(filePath).toLowerCase();
|
|
58276
58394
|
const testPatterns = [
|
|
58277
58395
|
".test.",
|
|
58278
58396
|
".spec.",
|
|
@@ -58353,8 +58471,8 @@ function matchGlobSegment(globSegments, pathSegments) {
|
|
|
58353
58471
|
}
|
|
58354
58472
|
return gIndex === globSegments.length && pIndex === pathSegments.length;
|
|
58355
58473
|
}
|
|
58356
|
-
function matchesGlobSegment(
|
|
58357
|
-
const normalizedPath =
|
|
58474
|
+
function matchesGlobSegment(path48, glob) {
|
|
58475
|
+
const normalizedPath = path48.replace(/\\/g, "/");
|
|
58358
58476
|
const normalizedGlob = glob.replace(/\\/g, "/");
|
|
58359
58477
|
if (normalizedPath.includes("//")) {
|
|
58360
58478
|
return false;
|
|
@@ -58385,8 +58503,8 @@ function simpleGlobToRegex2(glob) {
|
|
|
58385
58503
|
function hasGlobstar(glob) {
|
|
58386
58504
|
return glob.includes("**");
|
|
58387
58505
|
}
|
|
58388
|
-
function globMatches(
|
|
58389
|
-
const normalizedPath =
|
|
58506
|
+
function globMatches(path48, glob) {
|
|
58507
|
+
const normalizedPath = path48.replace(/\\/g, "/");
|
|
58390
58508
|
if (!glob || glob === "") {
|
|
58391
58509
|
if (normalizedPath.includes("//")) {
|
|
58392
58510
|
return false;
|
|
@@ -58422,7 +58540,7 @@ function shouldExcludeFile(filePath, excludeGlobs) {
|
|
|
58422
58540
|
async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
|
|
58423
58541
|
let testLines = 0;
|
|
58424
58542
|
let codeLines = 0;
|
|
58425
|
-
const srcDir =
|
|
58543
|
+
const srcDir = path47.join(workingDir, "src");
|
|
58426
58544
|
if (fs33.existsSync(srcDir)) {
|
|
58427
58545
|
await scanDirectoryForLines(srcDir, enforceGlobs, excludeGlobs, false, (lines) => {
|
|
58428
58546
|
codeLines += lines;
|
|
@@ -58430,14 +58548,14 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
|
|
|
58430
58548
|
}
|
|
58431
58549
|
const possibleSrcDirs = ["lib", "app", "source", "core"];
|
|
58432
58550
|
for (const dir of possibleSrcDirs) {
|
|
58433
|
-
const dirPath =
|
|
58551
|
+
const dirPath = path47.join(workingDir, dir);
|
|
58434
58552
|
if (fs33.existsSync(dirPath)) {
|
|
58435
58553
|
await scanDirectoryForLines(dirPath, enforceGlobs, excludeGlobs, false, (lines) => {
|
|
58436
58554
|
codeLines += lines;
|
|
58437
58555
|
});
|
|
58438
58556
|
}
|
|
58439
58557
|
}
|
|
58440
|
-
const testsDir =
|
|
58558
|
+
const testsDir = path47.join(workingDir, "tests");
|
|
58441
58559
|
if (fs33.existsSync(testsDir)) {
|
|
58442
58560
|
await scanDirectoryForLines(testsDir, ["**"], ["node_modules", "dist"], true, (lines) => {
|
|
58443
58561
|
testLines += lines;
|
|
@@ -58445,7 +58563,7 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
|
|
|
58445
58563
|
}
|
|
58446
58564
|
const possibleTestDirs = ["test", "__tests__", "specs"];
|
|
58447
58565
|
for (const dir of possibleTestDirs) {
|
|
58448
|
-
const dirPath =
|
|
58566
|
+
const dirPath = path47.join(workingDir, dir);
|
|
58449
58567
|
if (fs33.existsSync(dirPath) && dirPath !== testsDir) {
|
|
58450
58568
|
await scanDirectoryForLines(dirPath, ["**"], ["node_modules", "dist"], true, (lines) => {
|
|
58451
58569
|
testLines += lines;
|
|
@@ -58460,7 +58578,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
|
|
|
58460
58578
|
try {
|
|
58461
58579
|
const entries = fs33.readdirSync(dirPath, { withFileTypes: true });
|
|
58462
58580
|
for (const entry of entries) {
|
|
58463
|
-
const fullPath =
|
|
58581
|
+
const fullPath = path47.join(dirPath, entry.name);
|
|
58464
58582
|
if (entry.isDirectory()) {
|
|
58465
58583
|
if (entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === ".git") {
|
|
58466
58584
|
continue;
|
|
@@ -58468,7 +58586,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
|
|
|
58468
58586
|
await scanDirectoryForLines(fullPath, includeGlobs, excludeGlobs, isTestScan, callback);
|
|
58469
58587
|
} else if (entry.isFile()) {
|
|
58470
58588
|
const relativePath = fullPath.replace(`${process.cwd()}/`, "");
|
|
58471
|
-
const ext =
|
|
58589
|
+
const ext = path47.extname(entry.name).toLowerCase();
|
|
58472
58590
|
const validExts = [
|
|
58473
58591
|
".ts",
|
|
58474
58592
|
".tsx",
|
|
@@ -58719,7 +58837,7 @@ init_dist();
|
|
|
58719
58837
|
init_manager();
|
|
58720
58838
|
init_detector();
|
|
58721
58839
|
import * as fs34 from "fs";
|
|
58722
|
-
import * as
|
|
58840
|
+
import * as path48 from "path";
|
|
58723
58841
|
import { extname as extname9 } from "path";
|
|
58724
58842
|
|
|
58725
58843
|
// src/sast/rules/c.ts
|
|
@@ -59682,7 +59800,7 @@ async function sastScan(input, directory, config3) {
|
|
|
59682
59800
|
_filesSkipped++;
|
|
59683
59801
|
continue;
|
|
59684
59802
|
}
|
|
59685
|
-
const resolvedPath =
|
|
59803
|
+
const resolvedPath = path48.isAbsolute(filePath) ? filePath : path48.resolve(directory, filePath);
|
|
59686
59804
|
if (!fs34.existsSync(resolvedPath)) {
|
|
59687
59805
|
_filesSkipped++;
|
|
59688
59806
|
continue;
|
|
@@ -59881,18 +59999,18 @@ function validatePath(inputPath, baseDir, workspaceDir) {
|
|
|
59881
59999
|
let resolved;
|
|
59882
60000
|
const isWinAbs = isWindowsAbsolutePath(inputPath);
|
|
59883
60001
|
if (isWinAbs) {
|
|
59884
|
-
resolved =
|
|
59885
|
-
} else if (
|
|
59886
|
-
resolved =
|
|
60002
|
+
resolved = path49.win32.resolve(inputPath);
|
|
60003
|
+
} else if (path49.isAbsolute(inputPath)) {
|
|
60004
|
+
resolved = path49.resolve(inputPath);
|
|
59887
60005
|
} else {
|
|
59888
|
-
resolved =
|
|
60006
|
+
resolved = path49.resolve(baseDir, inputPath);
|
|
59889
60007
|
}
|
|
59890
|
-
const workspaceResolved =
|
|
60008
|
+
const workspaceResolved = path49.resolve(workspaceDir);
|
|
59891
60009
|
let relative5;
|
|
59892
60010
|
if (isWinAbs) {
|
|
59893
|
-
relative5 =
|
|
60011
|
+
relative5 = path49.win32.relative(workspaceResolved, resolved);
|
|
59894
60012
|
} else {
|
|
59895
|
-
relative5 =
|
|
60013
|
+
relative5 = path49.relative(workspaceResolved, resolved);
|
|
59896
60014
|
}
|
|
59897
60015
|
if (relative5.startsWith("..")) {
|
|
59898
60016
|
return "path traversal detected";
|
|
@@ -59953,13 +60071,13 @@ async function runLintWrapped(files, directory, _config) {
|
|
|
59953
60071
|
}
|
|
59954
60072
|
async function runLintOnFiles(linter, files, workspaceDir) {
|
|
59955
60073
|
const isWindows = process.platform === "win32";
|
|
59956
|
-
const binDir =
|
|
60074
|
+
const binDir = path49.join(workspaceDir, "node_modules", ".bin");
|
|
59957
60075
|
const validatedFiles = [];
|
|
59958
60076
|
for (const file3 of files) {
|
|
59959
60077
|
if (typeof file3 !== "string") {
|
|
59960
60078
|
continue;
|
|
59961
60079
|
}
|
|
59962
|
-
const resolvedPath =
|
|
60080
|
+
const resolvedPath = path49.resolve(file3);
|
|
59963
60081
|
const validationError = validatePath(resolvedPath, workspaceDir, workspaceDir);
|
|
59964
60082
|
if (validationError) {
|
|
59965
60083
|
continue;
|
|
@@ -59977,10 +60095,10 @@ async function runLintOnFiles(linter, files, workspaceDir) {
|
|
|
59977
60095
|
}
|
|
59978
60096
|
let command;
|
|
59979
60097
|
if (linter === "biome") {
|
|
59980
|
-
const biomeBin = isWindows ?
|
|
60098
|
+
const biomeBin = isWindows ? path49.join(binDir, "biome.EXE") : path49.join(binDir, "biome");
|
|
59981
60099
|
command = [biomeBin, "check", ...validatedFiles];
|
|
59982
60100
|
} else {
|
|
59983
|
-
const eslintBin = isWindows ?
|
|
60101
|
+
const eslintBin = isWindows ? path49.join(binDir, "eslint.cmd") : path49.join(binDir, "eslint");
|
|
59984
60102
|
command = [eslintBin, ...validatedFiles];
|
|
59985
60103
|
}
|
|
59986
60104
|
try {
|
|
@@ -60117,7 +60235,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
60117
60235
|
skippedFiles++;
|
|
60118
60236
|
continue;
|
|
60119
60237
|
}
|
|
60120
|
-
const resolvedPath =
|
|
60238
|
+
const resolvedPath = path49.resolve(file3);
|
|
60121
60239
|
const validationError = validatePath(resolvedPath, directory, directory);
|
|
60122
60240
|
if (validationError) {
|
|
60123
60241
|
skippedFiles++;
|
|
@@ -60135,7 +60253,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
60135
60253
|
};
|
|
60136
60254
|
}
|
|
60137
60255
|
for (const file3 of validatedFiles) {
|
|
60138
|
-
const ext =
|
|
60256
|
+
const ext = path49.extname(file3).toLowerCase();
|
|
60139
60257
|
if (DEFAULT_EXCLUDE_EXTENSIONS2.has(ext)) {
|
|
60140
60258
|
skippedFiles++;
|
|
60141
60259
|
continue;
|
|
@@ -60294,7 +60412,7 @@ async function runPreCheckBatch(input, workspaceDir) {
|
|
|
60294
60412
|
warn(`pre_check_batch: Invalid file path: ${file3}`);
|
|
60295
60413
|
continue;
|
|
60296
60414
|
}
|
|
60297
|
-
changedFiles.push(
|
|
60415
|
+
changedFiles.push(path49.resolve(directory, file3));
|
|
60298
60416
|
}
|
|
60299
60417
|
if (changedFiles.length === 0) {
|
|
60300
60418
|
warn("pre_check_batch: No valid files after validation, skipping all tools (fail-closed)");
|
|
@@ -60445,7 +60563,7 @@ var pre_check_batch = createSwarmTool({
|
|
|
60445
60563
|
};
|
|
60446
60564
|
return JSON.stringify(errorResult, null, 2);
|
|
60447
60565
|
}
|
|
60448
|
-
const resolvedDirectory =
|
|
60566
|
+
const resolvedDirectory = path49.resolve(typedArgs.directory);
|
|
60449
60567
|
const workspaceAnchor = resolvedDirectory;
|
|
60450
60568
|
const dirError = validateDirectory3(resolvedDirectory, workspaceAnchor);
|
|
60451
60569
|
if (dirError) {
|
|
@@ -60553,7 +60671,7 @@ init_tool();
|
|
|
60553
60671
|
init_manager2();
|
|
60554
60672
|
init_create_tool();
|
|
60555
60673
|
import * as fs36 from "fs";
|
|
60556
|
-
import * as
|
|
60674
|
+
import * as path50 from "path";
|
|
60557
60675
|
function detectPlaceholderContent(args2) {
|
|
60558
60676
|
const issues = [];
|
|
60559
60677
|
const placeholderPattern = /^\[\w[\w\s]*\]$/;
|
|
@@ -60657,7 +60775,7 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
60657
60775
|
try {
|
|
60658
60776
|
await savePlan(dir, plan);
|
|
60659
60777
|
try {
|
|
60660
|
-
const markerPath =
|
|
60778
|
+
const markerPath = path50.join(dir, ".swarm", ".plan-write-marker");
|
|
60661
60779
|
const marker = JSON.stringify({
|
|
60662
60780
|
source: "save_plan",
|
|
60663
60781
|
timestamp: new Date().toISOString(),
|
|
@@ -60669,7 +60787,7 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
60669
60787
|
return {
|
|
60670
60788
|
success: true,
|
|
60671
60789
|
message: "Plan saved successfully",
|
|
60672
|
-
plan_path:
|
|
60790
|
+
plan_path: path50.join(dir, ".swarm", "plan.json"),
|
|
60673
60791
|
phases_count: plan.phases.length,
|
|
60674
60792
|
tasks_count: tasksCount
|
|
60675
60793
|
};
|
|
@@ -60708,7 +60826,7 @@ var save_plan = createSwarmTool({
|
|
|
60708
60826
|
init_dist();
|
|
60709
60827
|
init_manager();
|
|
60710
60828
|
import * as fs37 from "fs";
|
|
60711
|
-
import * as
|
|
60829
|
+
import * as path51 from "path";
|
|
60712
60830
|
|
|
60713
60831
|
// src/sbom/detectors/index.ts
|
|
60714
60832
|
init_utils();
|
|
@@ -61556,7 +61674,7 @@ function findManifestFiles(rootDir) {
|
|
|
61556
61674
|
try {
|
|
61557
61675
|
const entries = fs37.readdirSync(dir, { withFileTypes: true });
|
|
61558
61676
|
for (const entry of entries) {
|
|
61559
|
-
const fullPath =
|
|
61677
|
+
const fullPath = path51.join(dir, entry.name);
|
|
61560
61678
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "target") {
|
|
61561
61679
|
continue;
|
|
61562
61680
|
}
|
|
@@ -61565,7 +61683,7 @@ function findManifestFiles(rootDir) {
|
|
|
61565
61683
|
} else if (entry.isFile()) {
|
|
61566
61684
|
for (const pattern of patterns) {
|
|
61567
61685
|
if (simpleGlobToRegex(pattern).test(entry.name)) {
|
|
61568
|
-
manifestFiles.push(
|
|
61686
|
+
manifestFiles.push(path51.relative(rootDir, fullPath));
|
|
61569
61687
|
break;
|
|
61570
61688
|
}
|
|
61571
61689
|
}
|
|
@@ -61583,11 +61701,11 @@ function findManifestFilesInDirs(directories, workingDir) {
|
|
|
61583
61701
|
try {
|
|
61584
61702
|
const entries = fs37.readdirSync(dir, { withFileTypes: true });
|
|
61585
61703
|
for (const entry of entries) {
|
|
61586
|
-
const fullPath =
|
|
61704
|
+
const fullPath = path51.join(dir, entry.name);
|
|
61587
61705
|
if (entry.isFile()) {
|
|
61588
61706
|
for (const pattern of patterns) {
|
|
61589
61707
|
if (simpleGlobToRegex(pattern).test(entry.name)) {
|
|
61590
|
-
found.push(
|
|
61708
|
+
found.push(path51.relative(workingDir, fullPath));
|
|
61591
61709
|
break;
|
|
61592
61710
|
}
|
|
61593
61711
|
}
|
|
@@ -61600,11 +61718,11 @@ function findManifestFilesInDirs(directories, workingDir) {
|
|
|
61600
61718
|
function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
|
|
61601
61719
|
const dirs = new Set;
|
|
61602
61720
|
for (const file3 of changedFiles) {
|
|
61603
|
-
let currentDir =
|
|
61721
|
+
let currentDir = path51.dirname(file3);
|
|
61604
61722
|
while (true) {
|
|
61605
|
-
if (currentDir && currentDir !== "." && currentDir !==
|
|
61606
|
-
dirs.add(
|
|
61607
|
-
const parent =
|
|
61723
|
+
if (currentDir && currentDir !== "." && currentDir !== path51.sep) {
|
|
61724
|
+
dirs.add(path51.join(workingDir, currentDir));
|
|
61725
|
+
const parent = path51.dirname(currentDir);
|
|
61608
61726
|
if (parent === currentDir)
|
|
61609
61727
|
break;
|
|
61610
61728
|
currentDir = parent;
|
|
@@ -61688,7 +61806,7 @@ var sbom_generate = createSwarmTool({
|
|
|
61688
61806
|
const changedFiles = obj.changed_files;
|
|
61689
61807
|
const relativeOutputDir = obj.output_dir || DEFAULT_OUTPUT_DIR;
|
|
61690
61808
|
const workingDir = directory;
|
|
61691
|
-
const outputDir =
|
|
61809
|
+
const outputDir = path51.isAbsolute(relativeOutputDir) ? relativeOutputDir : path51.join(workingDir, relativeOutputDir);
|
|
61692
61810
|
let manifestFiles = [];
|
|
61693
61811
|
if (scope === "all") {
|
|
61694
61812
|
manifestFiles = findManifestFiles(workingDir);
|
|
@@ -61711,7 +61829,7 @@ var sbom_generate = createSwarmTool({
|
|
|
61711
61829
|
const processedFiles = [];
|
|
61712
61830
|
for (const manifestFile of manifestFiles) {
|
|
61713
61831
|
try {
|
|
61714
|
-
const fullPath =
|
|
61832
|
+
const fullPath = path51.isAbsolute(manifestFile) ? manifestFile : path51.join(workingDir, manifestFile);
|
|
61715
61833
|
if (!fs37.existsSync(fullPath)) {
|
|
61716
61834
|
continue;
|
|
61717
61835
|
}
|
|
@@ -61728,7 +61846,7 @@ var sbom_generate = createSwarmTool({
|
|
|
61728
61846
|
const bom = generateCycloneDX(allComponents);
|
|
61729
61847
|
const bomJson = serializeCycloneDX(bom);
|
|
61730
61848
|
const filename = generateSbomFilename();
|
|
61731
|
-
const outputPath =
|
|
61849
|
+
const outputPath = path51.join(outputDir, filename);
|
|
61732
61850
|
fs37.writeFileSync(outputPath, bomJson, "utf-8");
|
|
61733
61851
|
const verdict = processedFiles.length > 0 ? "pass" : "pass";
|
|
61734
61852
|
try {
|
|
@@ -61772,7 +61890,7 @@ var sbom_generate = createSwarmTool({
|
|
|
61772
61890
|
init_dist();
|
|
61773
61891
|
init_create_tool();
|
|
61774
61892
|
import * as fs38 from "fs";
|
|
61775
|
-
import * as
|
|
61893
|
+
import * as path52 from "path";
|
|
61776
61894
|
var SPEC_CANDIDATES = [
|
|
61777
61895
|
"openapi.json",
|
|
61778
61896
|
"openapi.yaml",
|
|
@@ -61804,12 +61922,12 @@ function normalizePath2(p) {
|
|
|
61804
61922
|
}
|
|
61805
61923
|
function discoverSpecFile(cwd, specFileArg) {
|
|
61806
61924
|
if (specFileArg) {
|
|
61807
|
-
const resolvedPath =
|
|
61808
|
-
const normalizedCwd = cwd.endsWith(
|
|
61925
|
+
const resolvedPath = path52.resolve(cwd, specFileArg);
|
|
61926
|
+
const normalizedCwd = cwd.endsWith(path52.sep) ? cwd : cwd + path52.sep;
|
|
61809
61927
|
if (!resolvedPath.startsWith(normalizedCwd) && resolvedPath !== cwd) {
|
|
61810
61928
|
throw new Error("Invalid spec_file: path traversal detected");
|
|
61811
61929
|
}
|
|
61812
|
-
const ext =
|
|
61930
|
+
const ext = path52.extname(resolvedPath).toLowerCase();
|
|
61813
61931
|
if (!ALLOWED_EXTENSIONS.includes(ext)) {
|
|
61814
61932
|
throw new Error(`Invalid spec_file: must end in .json, .yaml, or .yml, got ${ext}`);
|
|
61815
61933
|
}
|
|
@@ -61823,7 +61941,7 @@ function discoverSpecFile(cwd, specFileArg) {
|
|
|
61823
61941
|
return resolvedPath;
|
|
61824
61942
|
}
|
|
61825
61943
|
for (const candidate of SPEC_CANDIDATES) {
|
|
61826
|
-
const candidatePath =
|
|
61944
|
+
const candidatePath = path52.resolve(cwd, candidate);
|
|
61827
61945
|
if (fs38.existsSync(candidatePath)) {
|
|
61828
61946
|
const stats = fs38.statSync(candidatePath);
|
|
61829
61947
|
if (stats.size <= MAX_SPEC_SIZE) {
|
|
@@ -61835,7 +61953,7 @@ function discoverSpecFile(cwd, specFileArg) {
|
|
|
61835
61953
|
}
|
|
61836
61954
|
function parseSpec(specFile) {
|
|
61837
61955
|
const content = fs38.readFileSync(specFile, "utf-8");
|
|
61838
|
-
const ext =
|
|
61956
|
+
const ext = path52.extname(specFile).toLowerCase();
|
|
61839
61957
|
if (ext === ".json") {
|
|
61840
61958
|
return parseJsonSpec(content);
|
|
61841
61959
|
}
|
|
@@ -61911,7 +62029,7 @@ function extractRoutes(cwd) {
|
|
|
61911
62029
|
return;
|
|
61912
62030
|
}
|
|
61913
62031
|
for (const entry of entries) {
|
|
61914
|
-
const fullPath =
|
|
62032
|
+
const fullPath = path52.join(dir, entry.name);
|
|
61915
62033
|
if (entry.isSymbolicLink()) {
|
|
61916
62034
|
continue;
|
|
61917
62035
|
}
|
|
@@ -61921,7 +62039,7 @@ function extractRoutes(cwd) {
|
|
|
61921
62039
|
}
|
|
61922
62040
|
walkDir(fullPath);
|
|
61923
62041
|
} else if (entry.isFile()) {
|
|
61924
|
-
const ext =
|
|
62042
|
+
const ext = path52.extname(entry.name).toLowerCase();
|
|
61925
62043
|
const baseName = entry.name.toLowerCase();
|
|
61926
62044
|
if (![".ts", ".js", ".mjs"].includes(ext)) {
|
|
61927
62045
|
continue;
|
|
@@ -62091,7 +62209,7 @@ init_secretscan();
|
|
|
62091
62209
|
init_tool();
|
|
62092
62210
|
init_create_tool();
|
|
62093
62211
|
import * as fs39 from "fs";
|
|
62094
|
-
import * as
|
|
62212
|
+
import * as path53 from "path";
|
|
62095
62213
|
var MAX_FILE_SIZE_BYTES7 = 1024 * 1024;
|
|
62096
62214
|
var WINDOWS_RESERVED_NAMES = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
|
|
62097
62215
|
function containsControlCharacters(str) {
|
|
@@ -62120,11 +62238,11 @@ function containsWindowsAttacks(str) {
|
|
|
62120
62238
|
}
|
|
62121
62239
|
function isPathInWorkspace(filePath, workspace) {
|
|
62122
62240
|
try {
|
|
62123
|
-
const resolvedPath =
|
|
62241
|
+
const resolvedPath = path53.resolve(workspace, filePath);
|
|
62124
62242
|
const realWorkspace = fs39.realpathSync(workspace);
|
|
62125
62243
|
const realResolvedPath = fs39.realpathSync(resolvedPath);
|
|
62126
|
-
const relativePath =
|
|
62127
|
-
if (relativePath.startsWith("..") ||
|
|
62244
|
+
const relativePath = path53.relative(realWorkspace, realResolvedPath);
|
|
62245
|
+
if (relativePath.startsWith("..") || path53.isAbsolute(relativePath)) {
|
|
62128
62246
|
return false;
|
|
62129
62247
|
}
|
|
62130
62248
|
return true;
|
|
@@ -62136,7 +62254,7 @@ function validatePathForRead(filePath, workspace) {
|
|
|
62136
62254
|
return isPathInWorkspace(filePath, workspace);
|
|
62137
62255
|
}
|
|
62138
62256
|
function extractTSSymbols(filePath, cwd) {
|
|
62139
|
-
const fullPath =
|
|
62257
|
+
const fullPath = path53.join(cwd, filePath);
|
|
62140
62258
|
if (!validatePathForRead(fullPath, cwd)) {
|
|
62141
62259
|
return [];
|
|
62142
62260
|
}
|
|
@@ -62288,7 +62406,7 @@ function extractTSSymbols(filePath, cwd) {
|
|
|
62288
62406
|
});
|
|
62289
62407
|
}
|
|
62290
62408
|
function extractPythonSymbols(filePath, cwd) {
|
|
62291
|
-
const fullPath =
|
|
62409
|
+
const fullPath = path53.join(cwd, filePath);
|
|
62292
62410
|
if (!validatePathForRead(fullPath, cwd)) {
|
|
62293
62411
|
return [];
|
|
62294
62412
|
}
|
|
@@ -62371,7 +62489,7 @@ var symbols = createSwarmTool({
|
|
|
62371
62489
|
}, null, 2);
|
|
62372
62490
|
}
|
|
62373
62491
|
const cwd = directory;
|
|
62374
|
-
const ext =
|
|
62492
|
+
const ext = path53.extname(file3);
|
|
62375
62493
|
if (containsControlCharacters(file3)) {
|
|
62376
62494
|
return JSON.stringify({
|
|
62377
62495
|
file: file3,
|
|
@@ -62443,7 +62561,7 @@ init_dist();
|
|
|
62443
62561
|
init_utils();
|
|
62444
62562
|
init_create_tool();
|
|
62445
62563
|
import * as fs40 from "fs";
|
|
62446
|
-
import * as
|
|
62564
|
+
import * as path54 from "path";
|
|
62447
62565
|
var MAX_TEXT_LENGTH = 200;
|
|
62448
62566
|
var MAX_FILE_SIZE_BYTES8 = 1024 * 1024;
|
|
62449
62567
|
var SUPPORTED_EXTENSIONS2 = new Set([
|
|
@@ -62514,9 +62632,9 @@ function validatePathsInput(paths, cwd) {
|
|
|
62514
62632
|
return { error: "paths contains path traversal", resolvedPath: null };
|
|
62515
62633
|
}
|
|
62516
62634
|
try {
|
|
62517
|
-
const resolvedPath =
|
|
62518
|
-
const normalizedCwd =
|
|
62519
|
-
const normalizedResolved =
|
|
62635
|
+
const resolvedPath = path54.resolve(paths);
|
|
62636
|
+
const normalizedCwd = path54.resolve(cwd);
|
|
62637
|
+
const normalizedResolved = path54.resolve(resolvedPath);
|
|
62520
62638
|
if (!normalizedResolved.startsWith(normalizedCwd)) {
|
|
62521
62639
|
return {
|
|
62522
62640
|
error: "paths must be within the current working directory",
|
|
@@ -62532,7 +62650,7 @@ function validatePathsInput(paths, cwd) {
|
|
|
62532
62650
|
}
|
|
62533
62651
|
}
|
|
62534
62652
|
function isSupportedExtension(filePath) {
|
|
62535
|
-
const ext =
|
|
62653
|
+
const ext = path54.extname(filePath).toLowerCase();
|
|
62536
62654
|
return SUPPORTED_EXTENSIONS2.has(ext);
|
|
62537
62655
|
}
|
|
62538
62656
|
function findSourceFiles2(dir, files = []) {
|
|
@@ -62547,7 +62665,7 @@ function findSourceFiles2(dir, files = []) {
|
|
|
62547
62665
|
if (SKIP_DIRECTORIES3.has(entry)) {
|
|
62548
62666
|
continue;
|
|
62549
62667
|
}
|
|
62550
|
-
const fullPath =
|
|
62668
|
+
const fullPath = path54.join(dir, entry);
|
|
62551
62669
|
let stat2;
|
|
62552
62670
|
try {
|
|
62553
62671
|
stat2 = fs40.statSync(fullPath);
|
|
@@ -62659,7 +62777,7 @@ var todo_extract = createSwarmTool({
|
|
|
62659
62777
|
filesToScan.push(scanPath);
|
|
62660
62778
|
} else {
|
|
62661
62779
|
const errorResult = {
|
|
62662
|
-
error: `unsupported file extension: ${
|
|
62780
|
+
error: `unsupported file extension: ${path54.extname(scanPath)}`,
|
|
62663
62781
|
total: 0,
|
|
62664
62782
|
byPriority: { high: 0, medium: 0, low: 0 },
|
|
62665
62783
|
entries: []
|
|
@@ -62705,14 +62823,14 @@ var todo_extract = createSwarmTool({
|
|
|
62705
62823
|
init_tool();
|
|
62706
62824
|
init_schema();
|
|
62707
62825
|
import * as fs42 from "fs";
|
|
62708
|
-
import * as
|
|
62826
|
+
import * as path56 from "path";
|
|
62709
62827
|
|
|
62710
62828
|
// src/hooks/diff-scope.ts
|
|
62711
62829
|
import * as fs41 from "fs";
|
|
62712
|
-
import * as
|
|
62830
|
+
import * as path55 from "path";
|
|
62713
62831
|
function getDeclaredScope(taskId, directory) {
|
|
62714
62832
|
try {
|
|
62715
|
-
const planPath =
|
|
62833
|
+
const planPath = path55.join(directory, ".swarm", "plan.json");
|
|
62716
62834
|
if (!fs41.existsSync(planPath))
|
|
62717
62835
|
return null;
|
|
62718
62836
|
const raw = fs41.readFileSync(planPath, "utf-8");
|
|
@@ -62827,7 +62945,7 @@ var TIER_3_PATTERNS = [
|
|
|
62827
62945
|
];
|
|
62828
62946
|
function matchesTier3Pattern(files) {
|
|
62829
62947
|
for (const file3 of files) {
|
|
62830
|
-
const fileName =
|
|
62948
|
+
const fileName = path56.basename(file3);
|
|
62831
62949
|
for (const pattern of TIER_3_PATTERNS) {
|
|
62832
62950
|
if (pattern.test(fileName)) {
|
|
62833
62951
|
return true;
|
|
@@ -62849,7 +62967,7 @@ function checkReviewerGate(taskId, workingDirectory) {
|
|
|
62849
62967
|
if (hasActiveTurboMode2()) {
|
|
62850
62968
|
const resolvedDir2 = workingDirectory ?? process.cwd();
|
|
62851
62969
|
try {
|
|
62852
|
-
const planPath =
|
|
62970
|
+
const planPath = path56.join(resolvedDir2, ".swarm", "plan.json");
|
|
62853
62971
|
const planRaw = fs42.readFileSync(planPath, "utf-8");
|
|
62854
62972
|
const plan = JSON.parse(planRaw);
|
|
62855
62973
|
for (const planPhase of plan.phases ?? []) {
|
|
@@ -62869,7 +62987,7 @@ function checkReviewerGate(taskId, workingDirectory) {
|
|
|
62869
62987
|
}
|
|
62870
62988
|
const resolvedDir = workingDirectory ?? process.cwd();
|
|
62871
62989
|
try {
|
|
62872
|
-
const evidencePath =
|
|
62990
|
+
const evidencePath = path56.join(resolvedDir, ".swarm", "evidence", `${taskId}.json`);
|
|
62873
62991
|
const raw = fs42.readFileSync(evidencePath, "utf-8");
|
|
62874
62992
|
const evidence = JSON.parse(raw);
|
|
62875
62993
|
if (evidence?.required_gates && Array.isArray(evidence.required_gates) && evidence?.gates) {
|
|
@@ -62910,7 +63028,7 @@ function checkReviewerGate(taskId, workingDirectory) {
|
|
|
62910
63028
|
}
|
|
62911
63029
|
try {
|
|
62912
63030
|
const resolvedDir2 = workingDirectory ?? process.cwd();
|
|
62913
|
-
const planPath =
|
|
63031
|
+
const planPath = path56.join(resolvedDir2, ".swarm", "plan.json");
|
|
62914
63032
|
const planRaw = fs42.readFileSync(planPath, "utf-8");
|
|
62915
63033
|
const plan = JSON.parse(planRaw);
|
|
62916
63034
|
for (const planPhase of plan.phases ?? []) {
|
|
@@ -63092,8 +63210,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
|
|
|
63092
63210
|
};
|
|
63093
63211
|
}
|
|
63094
63212
|
}
|
|
63095
|
-
normalizedDir =
|
|
63096
|
-
const pathParts = normalizedDir.split(
|
|
63213
|
+
normalizedDir = path56.normalize(args2.working_directory);
|
|
63214
|
+
const pathParts = normalizedDir.split(path56.sep);
|
|
63097
63215
|
if (pathParts.includes("..")) {
|
|
63098
63216
|
return {
|
|
63099
63217
|
success: false,
|
|
@@ -63103,10 +63221,10 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
|
|
|
63103
63221
|
]
|
|
63104
63222
|
};
|
|
63105
63223
|
}
|
|
63106
|
-
const resolvedDir =
|
|
63224
|
+
const resolvedDir = path56.resolve(normalizedDir);
|
|
63107
63225
|
try {
|
|
63108
63226
|
const realPath = fs42.realpathSync(resolvedDir);
|
|
63109
|
-
const planPath =
|
|
63227
|
+
const planPath = path56.join(realPath, ".swarm", "plan.json");
|
|
63110
63228
|
if (!fs42.existsSync(planPath)) {
|
|
63111
63229
|
return {
|
|
63112
63230
|
success: false,
|
|
@@ -63301,7 +63419,7 @@ var OpenCodeSwarm = async (ctx) => {
|
|
|
63301
63419
|
const { PreflightTriggerManager: PTM } = await Promise.resolve().then(() => (init_trigger(), exports_trigger));
|
|
63302
63420
|
preflightTriggerManager = new PTM(automationConfig);
|
|
63303
63421
|
const { AutomationStatusArtifact: ASA } = await Promise.resolve().then(() => (init_status_artifact(), exports_status_artifact));
|
|
63304
|
-
const swarmDir =
|
|
63422
|
+
const swarmDir = path57.resolve(ctx.directory, ".swarm");
|
|
63305
63423
|
statusArtifact = new ASA(swarmDir);
|
|
63306
63424
|
statusArtifact.updateConfig(automationConfig.mode, automationConfig.capabilities);
|
|
63307
63425
|
if (automationConfig.capabilities?.evidence_auto_summaries === true) {
|