opencode-swarm 7.20.2 → 7.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +1 -1
- package/dist/hooks/skill-propagation-gate.d.ts +113 -0
- package/dist/hooks/skill-scoring.d.ts +127 -0
- package/dist/hooks/skill-usage-log.d.ts +109 -0
- package/dist/index.js +1428 -699
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -33,7 +33,7 @@ var package_default;
|
|
|
33
33
|
var init_package = __esm(() => {
|
|
34
34
|
package_default = {
|
|
35
35
|
name: "opencode-swarm",
|
|
36
|
-
version: "7.
|
|
36
|
+
version: "7.21.0",
|
|
37
37
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
38
38
|
main: "dist/index.js",
|
|
39
39
|
types: "dist/index.d.ts",
|
|
@@ -62852,9 +62852,14 @@ At session start, before your first delegation:
|
|
|
62852
62852
|
1. Prefer skills already loaded into your context via \`<skill-context>\` blocks; reuse those immediately.
|
|
62853
62853
|
2. When you need to inspect on-disk skills, use the \`search\` tool with \`include\` patterns like \`.opencode/skills/*/SKILL.md,.claude/skills/*/SKILL.md\` and frontmatter queries such as \`^name:\` / \`^description:\` so you only read the YAML lines you need.
|
|
62854
62854
|
3. Write a brief skill index to \`.swarm/context.md\` under \`## Available Skills\`:
|
|
62855
|
-
- writing-tests: Guidelines for writing tests (
|
|
62856
|
-
- engineering-conventions: Engineering invariants
|
|
62857
|
-
- [name]: [description] → [applicable agents]
|
|
62855
|
+
- writing-tests: Guidelines for writing tests (used: 12, compliance: 95%) → test_engineer, coder
|
|
62856
|
+
- engineering-conventions: Engineering invariants (used: 8, compliance: 100%) → coder, reviewer, test_engineer
|
|
62857
|
+
- [name]: [description] (used: N, compliance: N%) → [applicable agents]
|
|
62858
|
+
|
|
62859
|
+
If \`.swarm/skill-usage.jsonl\` exists, read it at session start to inform skill prioritization. Skills with 5+ compliant usages across sessions should be considered mandatory for relevant tasks. Read \`.swarm/skill-usage.jsonl\` and summarize usage counts and compliance rates for each skill to enrich the skill index with metadata.
|
|
62860
|
+
|
|
62861
|
+
If skill-usage.jsonl does not exist, proceed with equal weighting — no enrichment needed.
|
|
62862
|
+
|
|
62858
62863
|
4. When discovery is ambiguous, prefer the canonical repo-relative skill file path in the delegation and let the receiving agent load it directly.
|
|
62859
62864
|
|
|
62860
62865
|
### Step 2 — Route skills to agents
|
|
@@ -62892,6 +62897,12 @@ Default to repo-relative \`file:\` references for coder, reviewer, test_engineer
|
|
|
62892
62897
|
|
|
62893
62898
|
**Mandatory for coding tasks:** Always provide \`writing-tests\` to test_engineer and \`engineering-conventions\` to coder + reviewer when those skills are present in the project. Prefer \`file:\` references when the files exist.
|
|
62894
62899
|
|
|
62900
|
+
### Step 4 — Forward skills to reviewer
|
|
62901
|
+
|
|
62902
|
+
When delegating to the reviewer after a coder task, include a \`SKILLS_USED_BY_CODER: [comma-separated list of skill paths from the coder delegation]\` field. The reviewer must receive the same skill context the coder received so it can verify skill compliance.
|
|
62903
|
+
|
|
62904
|
+
Example: If the coder received \`SKILLS: file:.claude/skills/writing-tests/SKILL.md\`, the reviewer delegation must include \`SKILLS_USED_BY_CODER: file:.claude/skills/writing-tests/SKILL.md\` in addition to the reviewer's own \`SKILLS:\` field.
|
|
62905
|
+
|
|
62895
62906
|
## SWARM KNOWLEDGE DIRECTIVES (v2 acknowledgment contract)
|
|
62896
62907
|
|
|
62897
62908
|
If a \`<swarm_knowledge_directives>\` block is present in your context, treat each
|
|
@@ -62942,6 +62953,7 @@ Continue handling small touch-ups (typos, cross-references) inline.
|
|
|
62942
62953
|
- ✗ "I don't know which skill is relevant" → When uncertain, pass ALL discovered skills. Subagents discard inapplicable content.
|
|
62943
62954
|
- ✗ "The skill was loaded earlier so the agent knows it" → Each subagent Task call is a fresh context. Skills do NOT persist across Task boundaries.
|
|
62944
62955
|
- ✗ "I'll paste the whole skill body every time just to be safe" → Inline bodies are fallback only. Prefer \`file:\` references to avoid unnecessary context bloat.
|
|
62956
|
+
- ✗ "The reviewer doesn't need the coder's skills" → WRONG. The reviewer cannot verify skill compliance without knowing what skills the coder received. Always forward via SKILLS_USED_BY_CODER.
|
|
62945
62957
|
|
|
62946
62958
|
## SLASH COMMANDS
|
|
62947
62959
|
{{SLASH_COMMANDS}}
|
|
@@ -63002,6 +63014,7 @@ TASK: Review login validation
|
|
|
63002
63014
|
FILE: src/auth/login.ts
|
|
63003
63015
|
CHECK: [security, correctness, edge-cases]
|
|
63004
63016
|
GATES: lint=PASS, sast_scan=PASS, secretscan=PASS
|
|
63017
|
+
SKILLS_USED_BY_CODER: file:.claude/skills/engineering-conventions/SKILL.md
|
|
63005
63018
|
OUTPUT: VERDICT + RISK + ISSUES
|
|
63006
63019
|
SKILLS: file:.claude/skills/engineering-conventions/SKILL.md
|
|
63007
63020
|
|
|
@@ -65696,6 +65709,7 @@ AFFECTS: [callers/consumers/dependents to inspect, or "infer from diff"]
|
|
|
65696
65709
|
CHECK: [list of dimensions to evaluate]
|
|
65697
65710
|
GATES: [pre-completed gate results (lint, SAST, secretscan, etc.), or "none" if unavailable]
|
|
65698
65711
|
SKILLS: [optional — either "none", repo-relative file: references (preferred), or inline skill content pasted by architect]
|
|
65712
|
+
SKILLS_USED_BY_CODER: [list of skill paths that were passed to the coder for this task, or "none" if no skills were used]
|
|
65699
65713
|
|
|
65700
65714
|
SKILLS HANDLING: If SKILLS is present and not "none", load EVERY referenced skill before beginning your review.
|
|
65701
65715
|
- For \`file:\` entries, use the search tool to read the referenced \`SKILL.md\` file with \`include\` set to that exact repo-relative path, \`mode: regex\`, \`query: .*\`, \`max_results: 1000\`, and \`max_lines: 1000\`.
|
|
@@ -65704,6 +65718,13 @@ SKILLS HANDLING: If SKILLS is present and not "none", load EVERY referenced skil
|
|
|
65704
65718
|
- If inline \`--- skill-name ---\` sections are present, read them directly.
|
|
65705
65719
|
- Skills contain project-specific constraints (coding standards, architectural invariants, security requirements) that supplement and may extend your normal review dimensions. Flag any violation of a skill rule at the same severity as a logic error.
|
|
65706
65720
|
|
|
65721
|
+
SKILL COMPLIANCE REVIEW: When SKILLS_USED_BY_CODER is provided and not "none":
|
|
65722
|
+
- Load each skill the coder received using the same SKILLS HANDLING procedure above
|
|
65723
|
+
- For each skill rule, verify the coder's changes comply
|
|
65724
|
+
- Flag violations at the same severity as logic errors
|
|
65725
|
+
- Report the overall compliance verdict in SKILL_COMPLIANCE field of your output
|
|
65726
|
+
- If you cannot load a skill (SKILL_LOAD_FAILED), report SKILL_COMPLIANCE: PARTIAL — [skill path] could not be loaded
|
|
65727
|
+
|
|
65707
65728
|
PROCESSING: If GATES is provided and includes passing results for lint, SAST, placeholder-scan, or secret-scan: skip the corresponding Tier 2 checks that those gates already cover. Focus Tier 2 time on checks NOT covered by automated gates.
|
|
65708
65729
|
|
|
65709
65730
|
## OUTPUT FORMAT (MANDATORY — deviations will be rejected)
|
|
@@ -65713,6 +65734,7 @@ VERDICT: APPROVED | REJECTED
|
|
|
65713
65734
|
REUSE_RE_VERIFICATION: [VERIFIED | DUPLICATION_DETECTED | SKIPPED] — DUPLICATION_DETECTED is only valid when VERDICT is REJECTED
|
|
65714
65735
|
RISK: LOW | MEDIUM | HIGH | CRITICAL
|
|
65715
65736
|
ISSUES: list with line numbers, grouped by CHECK dimension
|
|
65737
|
+
SKILL_COMPLIANCE: COMPLIANT | PARTIAL | VIOLATED — [list of violations or "all rules followed"]
|
|
65716
65738
|
FIXES: required changes if rejected
|
|
65717
65739
|
Use INFO only inside ISSUES for non-blocking suggestions. RISK reflects the highest blocking severity, so it never uses INFO.
|
|
65718
65740
|
|
|
@@ -71634,15 +71656,15 @@ var init_curator_drift = __esm(() => {
|
|
|
71634
71656
|
var exports_project_context = {};
|
|
71635
71657
|
__export(exports_project_context, {
|
|
71636
71658
|
buildProjectContext: () => buildProjectContext,
|
|
71637
|
-
_internals: () =>
|
|
71659
|
+
_internals: () => _internals55,
|
|
71638
71660
|
LANG_BACKEND_DETECTION_TIMEOUT_MS: () => LANG_BACKEND_DETECTION_TIMEOUT_MS
|
|
71639
71661
|
});
|
|
71640
|
-
import * as
|
|
71641
|
-
import * as
|
|
71662
|
+
import * as fs112 from "node:fs";
|
|
71663
|
+
import * as path142 from "node:path";
|
|
71642
71664
|
function detectFileExists2(directory, pattern) {
|
|
71643
71665
|
if (pattern.includes("*") || pattern.includes("?")) {
|
|
71644
71666
|
try {
|
|
71645
|
-
const files =
|
|
71667
|
+
const files = fs112.readdirSync(directory);
|
|
71646
71668
|
const regex = new RegExp(`^${pattern.replace(/\./g, "\\.").replace(/\*/g, ".*").replace(/\?/g, ".")}$`);
|
|
71647
71669
|
return files.some((f) => regex.test(f));
|
|
71648
71670
|
} catch {
|
|
@@ -71650,7 +71672,7 @@ function detectFileExists2(directory, pattern) {
|
|
|
71650
71672
|
}
|
|
71651
71673
|
}
|
|
71652
71674
|
try {
|
|
71653
|
-
|
|
71675
|
+
fs112.accessSync(path142.join(directory, pattern));
|
|
71654
71676
|
return true;
|
|
71655
71677
|
} catch {
|
|
71656
71678
|
return false;
|
|
@@ -71659,7 +71681,7 @@ function detectFileExists2(directory, pattern) {
|
|
|
71659
71681
|
function selectTestCommandFromScriptsTest(backend, directory) {
|
|
71660
71682
|
let pkgRaw;
|
|
71661
71683
|
try {
|
|
71662
|
-
pkgRaw =
|
|
71684
|
+
pkgRaw = fs112.readFileSync(path142.join(directory, "package.json"), "utf-8");
|
|
71663
71685
|
} catch {
|
|
71664
71686
|
return null;
|
|
71665
71687
|
}
|
|
@@ -71718,7 +71740,7 @@ function selectLintCommand(backend, directory) {
|
|
|
71718
71740
|
return null;
|
|
71719
71741
|
}
|
|
71720
71742
|
async function buildProjectContext(directory) {
|
|
71721
|
-
const backend = await
|
|
71743
|
+
const backend = await _internals55.pickBackend(directory);
|
|
71722
71744
|
if (!backend)
|
|
71723
71745
|
return null;
|
|
71724
71746
|
const ctx = emptyProjectContext();
|
|
@@ -71749,16 +71771,16 @@ async function buildProjectContext(directory) {
|
|
|
71749
71771
|
if (backend.prompts.reviewerChecklist.length > 0) {
|
|
71750
71772
|
ctx.REVIEWER_CHECKLIST = bulletList(backend.prompts.reviewerChecklist);
|
|
71751
71773
|
}
|
|
71752
|
-
const profiles =
|
|
71774
|
+
const profiles = _internals55.pickedProfiles(directory);
|
|
71753
71775
|
if (profiles.length > 1) {
|
|
71754
71776
|
ctx.PROJECT_CONTEXT_SECONDARY_LANGUAGES = profiles.slice(1).map((p) => p.id).join(", ");
|
|
71755
71777
|
}
|
|
71756
71778
|
return ctx;
|
|
71757
71779
|
}
|
|
71758
|
-
var LANG_BACKEND_DETECTION_TIMEOUT_MS = 300,
|
|
71780
|
+
var LANG_BACKEND_DETECTION_TIMEOUT_MS = 300, _internals55;
|
|
71759
71781
|
var init_project_context = __esm(() => {
|
|
71760
71782
|
init_dispatch();
|
|
71761
|
-
|
|
71783
|
+
_internals55 = {
|
|
71762
71784
|
pickBackend,
|
|
71763
71785
|
pickedProfiles
|
|
71764
71786
|
};
|
|
@@ -71768,7 +71790,7 @@ var init_project_context = __esm(() => {
|
|
|
71768
71790
|
init_package();
|
|
71769
71791
|
init_agents2();
|
|
71770
71792
|
init_critic();
|
|
71771
|
-
import * as
|
|
71793
|
+
import * as path143 from "node:path";
|
|
71772
71794
|
|
|
71773
71795
|
// src/background/index.ts
|
|
71774
71796
|
init_event_bus();
|
|
@@ -82651,9 +82673,702 @@ function createSelfReviewHook(config3, injectAdvisory) {
|
|
|
82651
82673
|
};
|
|
82652
82674
|
}
|
|
82653
82675
|
|
|
82654
|
-
// src/hooks/
|
|
82676
|
+
// src/hooks/skill-propagation-gate.ts
|
|
82677
|
+
init_schema();
|
|
82678
|
+
init_logger();
|
|
82679
|
+
import * as fs62 from "node:fs";
|
|
82680
|
+
import * as path89 from "node:path";
|
|
82681
|
+
|
|
82682
|
+
// src/hooks/skill-scoring.ts
|
|
82683
|
+
import * as path88 from "node:path";
|
|
82684
|
+
|
|
82685
|
+
// src/hooks/skill-usage-log.ts
|
|
82686
|
+
init_utils2();
|
|
82687
|
+
import * as crypto9 from "node:crypto";
|
|
82655
82688
|
import * as fs61 from "node:fs";
|
|
82656
82689
|
import * as path87 from "node:path";
|
|
82690
|
+
function resolveLogPath(directory) {
|
|
82691
|
+
return validateSwarmPath(directory, "skill-usage.jsonl");
|
|
82692
|
+
}
|
|
82693
|
+
var _internals40 = {
|
|
82694
|
+
generateId: () => crypto9.randomUUID(),
|
|
82695
|
+
appendFileSync: fs61.appendFileSync.bind(fs61),
|
|
82696
|
+
readFileSync: fs61.readFileSync.bind(fs61),
|
|
82697
|
+
writeFileSync: fs61.writeFileSync.bind(fs61),
|
|
82698
|
+
renameSync: fs61.renameSync.bind(fs61),
|
|
82699
|
+
mkdirSync: fs61.mkdirSync.bind(fs61),
|
|
82700
|
+
existsSync: fs61.existsSync.bind(fs61),
|
|
82701
|
+
statSync: fs61.statSync.bind(fs61),
|
|
82702
|
+
openSync: fs61.openSync.bind(fs61),
|
|
82703
|
+
readSync: fs61.readSync.bind(fs61),
|
|
82704
|
+
closeSync: fs61.closeSync.bind(fs61)
|
|
82705
|
+
};
|
|
82706
|
+
function appendSkillUsageEntry(directory, entry) {
|
|
82707
|
+
const {
|
|
82708
|
+
skillPath,
|
|
82709
|
+
agentName,
|
|
82710
|
+
taskID,
|
|
82711
|
+
timestamp,
|
|
82712
|
+
complianceVerdict,
|
|
82713
|
+
sessionID,
|
|
82714
|
+
reviewerNotes
|
|
82715
|
+
} = entry;
|
|
82716
|
+
if (!skillPath || typeof skillPath !== "string") {
|
|
82717
|
+
throw new Error("skillPath is required and must be a non-empty string");
|
|
82718
|
+
}
|
|
82719
|
+
if (/\.\.[/\\]/.test(skillPath)) {
|
|
82720
|
+
throw new Error("skillPath contains path traversal sequence");
|
|
82721
|
+
}
|
|
82722
|
+
if (!agentName || typeof agentName !== "string") {
|
|
82723
|
+
throw new Error("agentName is required and must be a non-empty string");
|
|
82724
|
+
}
|
|
82725
|
+
if (!taskID || typeof taskID !== "string") {
|
|
82726
|
+
throw new Error("taskID is required and must be a non-empty string");
|
|
82727
|
+
}
|
|
82728
|
+
if (!timestamp || typeof timestamp !== "string") {
|
|
82729
|
+
throw new Error("timestamp is required and must be a non-empty string");
|
|
82730
|
+
}
|
|
82731
|
+
if (!complianceVerdict || typeof complianceVerdict !== "string") {
|
|
82732
|
+
throw new Error("complianceVerdict is required and must be a non-empty string");
|
|
82733
|
+
}
|
|
82734
|
+
if (!sessionID || typeof sessionID !== "string") {
|
|
82735
|
+
throw new Error("sessionID is required and must be a non-empty string");
|
|
82736
|
+
}
|
|
82737
|
+
const resolved = validateSwarmPath(directory, "skill-usage.jsonl");
|
|
82738
|
+
const dir = path87.dirname(resolved);
|
|
82739
|
+
if (!_internals40.existsSync(dir)) {
|
|
82740
|
+
_internals40.mkdirSync(dir, { recursive: true });
|
|
82741
|
+
}
|
|
82742
|
+
const fullEntry = {
|
|
82743
|
+
id: _internals40.generateId(),
|
|
82744
|
+
skillPath,
|
|
82745
|
+
agentName,
|
|
82746
|
+
taskID,
|
|
82747
|
+
timestamp,
|
|
82748
|
+
complianceVerdict,
|
|
82749
|
+
sessionID,
|
|
82750
|
+
...reviewerNotes !== undefined && { reviewerNotes }
|
|
82751
|
+
};
|
|
82752
|
+
_internals40.appendFileSync(resolved, `${JSON.stringify(fullEntry)}
|
|
82753
|
+
`, "utf-8");
|
|
82754
|
+
}
|
|
82755
|
+
function readSkillUsageEntries(directory, options) {
|
|
82756
|
+
const resolved = resolveLogPath(directory);
|
|
82757
|
+
if (!_internals40.existsSync(resolved)) {
|
|
82758
|
+
return [];
|
|
82759
|
+
}
|
|
82760
|
+
const raw = _internals40.readFileSync(resolved, "utf-8");
|
|
82761
|
+
const entries = [];
|
|
82762
|
+
for (const line of raw.split(`
|
|
82763
|
+
`)) {
|
|
82764
|
+
const trimmed = line.trim();
|
|
82765
|
+
if (!trimmed)
|
|
82766
|
+
continue;
|
|
82767
|
+
try {
|
|
82768
|
+
entries.push(JSON.parse(trimmed));
|
|
82769
|
+
} catch {}
|
|
82770
|
+
}
|
|
82771
|
+
if (!options)
|
|
82772
|
+
return entries;
|
|
82773
|
+
return entries.filter((e) => {
|
|
82774
|
+
if (options.sessionID !== undefined && e.sessionID !== options.sessionID) {
|
|
82775
|
+
return false;
|
|
82776
|
+
}
|
|
82777
|
+
if (options.skillPath !== undefined && e.skillPath !== options.skillPath) {
|
|
82778
|
+
return false;
|
|
82779
|
+
}
|
|
82780
|
+
if (options.agentName !== undefined && e.agentName !== options.agentName) {
|
|
82781
|
+
return false;
|
|
82782
|
+
}
|
|
82783
|
+
if (options.taskID !== undefined && e.taskID !== options.taskID) {
|
|
82784
|
+
return false;
|
|
82785
|
+
}
|
|
82786
|
+
if (options.dateRange !== undefined) {
|
|
82787
|
+
if (e.timestamp < options.dateRange.start)
|
|
82788
|
+
return false;
|
|
82789
|
+
if (e.timestamp > options.dateRange.end)
|
|
82790
|
+
return false;
|
|
82791
|
+
}
|
|
82792
|
+
return true;
|
|
82793
|
+
});
|
|
82794
|
+
}
|
|
82795
|
+
var TAIL_BYTES_DEFAULT = 64 * 1024;
|
|
82796
|
+
function readSkillUsageEntriesTail(directory, filters, maxBytes = TAIL_BYTES_DEFAULT) {
|
|
82797
|
+
const logPath = resolveLogPath(directory);
|
|
82798
|
+
if (!_internals40.existsSync(logPath))
|
|
82799
|
+
return [];
|
|
82800
|
+
try {
|
|
82801
|
+
const stat7 = _internals40.statSync(logPath);
|
|
82802
|
+
const start2 = Math.max(0, stat7.size - maxBytes);
|
|
82803
|
+
const fd = _internals40.openSync(logPath, "r");
|
|
82804
|
+
try {
|
|
82805
|
+
const readLen = stat7.size - start2;
|
|
82806
|
+
if (readLen === 0)
|
|
82807
|
+
return [];
|
|
82808
|
+
const buf = Buffer.alloc(readLen);
|
|
82809
|
+
_internals40.readSync(fd, buf, 0, buf.length, start2);
|
|
82810
|
+
const content = buf.toString("utf-8");
|
|
82811
|
+
let usable;
|
|
82812
|
+
if (start2 > 0) {
|
|
82813
|
+
const firstNewline = content.indexOf(`
|
|
82814
|
+
`);
|
|
82815
|
+
usable = firstNewline >= 0 ? content.slice(firstNewline + 1) : "";
|
|
82816
|
+
} else {
|
|
82817
|
+
usable = content;
|
|
82818
|
+
}
|
|
82819
|
+
const entries = [];
|
|
82820
|
+
for (const line of usable.split(`
|
|
82821
|
+
`)) {
|
|
82822
|
+
if (!line.trim())
|
|
82823
|
+
continue;
|
|
82824
|
+
try {
|
|
82825
|
+
const entry = JSON.parse(line);
|
|
82826
|
+
if (filters.sessionID !== undefined && entry.sessionID !== filters.sessionID) {
|
|
82827
|
+
continue;
|
|
82828
|
+
}
|
|
82829
|
+
entries.push(entry);
|
|
82830
|
+
} catch {}
|
|
82831
|
+
}
|
|
82832
|
+
return entries;
|
|
82833
|
+
} finally {
|
|
82834
|
+
_internals40.closeSync(fd);
|
|
82835
|
+
}
|
|
82836
|
+
} catch {
|
|
82837
|
+
return [];
|
|
82838
|
+
}
|
|
82839
|
+
}
|
|
82840
|
+
|
|
82841
|
+
// src/hooks/skill-scoring.ts
|
|
82842
|
+
var FREQUENCY_CAP = 10;
|
|
82843
|
+
var FREQUENCY_WEIGHT = 0.3;
|
|
82844
|
+
var COMPLIANCE_WEIGHT = 0.3;
|
|
82845
|
+
var RECENCY_WEIGHT = 0.15;
|
|
82846
|
+
var TASK_DIVERSITY_WEIGHT = 0.05;
|
|
82847
|
+
var CONTEXT_WEIGHT = 0.2;
|
|
82848
|
+
var RECENCY_DECAY_MS = 30 * 24 * 60 * 60 * 1000;
|
|
82849
|
+
var _internals41 = {
|
|
82850
|
+
computeSkillRelevanceScore: null,
|
|
82851
|
+
rankSkillsForContext: null,
|
|
82852
|
+
getSkillStats: null,
|
|
82853
|
+
formatSkillIndexWithContext: null,
|
|
82854
|
+
extractSkillName: null,
|
|
82855
|
+
computeRecencyScore: null,
|
|
82856
|
+
computeContextMatchScore: null
|
|
82857
|
+
};
|
|
82858
|
+
function extractSkillName(skillPath) {
|
|
82859
|
+
const base = path88.basename(skillPath, path88.extname(skillPath));
|
|
82860
|
+
if (base !== "SKILL")
|
|
82861
|
+
return base;
|
|
82862
|
+
const parent = path88.basename(path88.dirname(skillPath));
|
|
82863
|
+
return parent;
|
|
82864
|
+
}
|
|
82865
|
+
function computeRecencyScore(lastUsedTimestamp) {
|
|
82866
|
+
if (!lastUsedTimestamp)
|
|
82867
|
+
return 0;
|
|
82868
|
+
const lastUsed = new Date(lastUsedTimestamp).getTime();
|
|
82869
|
+
if (Number.isNaN(lastUsed))
|
|
82870
|
+
return 0;
|
|
82871
|
+
const ageMs = Date.now() - lastUsed;
|
|
82872
|
+
if (ageMs <= 0)
|
|
82873
|
+
return 1;
|
|
82874
|
+
if (ageMs >= RECENCY_DECAY_MS)
|
|
82875
|
+
return 0;
|
|
82876
|
+
return 1 - ageMs / RECENCY_DECAY_MS;
|
|
82877
|
+
}
|
|
82878
|
+
var MIN_KEYWORD_LENGTH = 3;
|
|
82879
|
+
function extractKeywords(text) {
|
|
82880
|
+
const words = text.toLowerCase().split(/[^a-z0-9]+/).filter((w) => w.length >= MIN_KEYWORD_LENGTH);
|
|
82881
|
+
return new Set(words);
|
|
82882
|
+
}
|
|
82883
|
+
function computeContextMatchScore(taskDescription, skillPath) {
|
|
82884
|
+
const taskKeywords = extractKeywords(taskDescription);
|
|
82885
|
+
if (taskKeywords.size === 0)
|
|
82886
|
+
return 0;
|
|
82887
|
+
const skillName = extractSkillName(skillPath);
|
|
82888
|
+
const skillText = `${skillPath} ${skillName}`;
|
|
82889
|
+
const skillKeywords = extractKeywords(skillText);
|
|
82890
|
+
let matchCount = 0;
|
|
82891
|
+
for (const kw of taskKeywords) {
|
|
82892
|
+
if (skillKeywords.has(kw)) {
|
|
82893
|
+
matchCount++;
|
|
82894
|
+
}
|
|
82895
|
+
}
|
|
82896
|
+
return matchCount / taskKeywords.size;
|
|
82897
|
+
}
|
|
82898
|
+
function computeSkillRelevanceScore(skillPath, taskDescription, usageHistory) {
|
|
82899
|
+
const contextScore = computeContextMatchScore(taskDescription, skillPath) * CONTEXT_WEIGHT;
|
|
82900
|
+
if (usageHistory.length === 0)
|
|
82901
|
+
return contextScore;
|
|
82902
|
+
const usageCount = usageHistory.length;
|
|
82903
|
+
const frequencyScore = Math.min(1, usageCount / FREQUENCY_CAP) * FREQUENCY_WEIGHT;
|
|
82904
|
+
const entriesWithVerdict = usageHistory.filter((e) => e.complianceVerdict !== undefined && e.complianceVerdict !== "not_checked");
|
|
82905
|
+
const compliantCount = entriesWithVerdict.filter((e) => e.complianceVerdict === "compliant").length;
|
|
82906
|
+
const denominator = Math.max(1, entriesWithVerdict.length);
|
|
82907
|
+
const complianceScore = compliantCount / denominator * COMPLIANCE_WEIGHT;
|
|
82908
|
+
const sortedByTime = [...usageHistory].sort((a, b) => b.timestamp > a.timestamp ? 1 : b.timestamp < a.timestamp ? -1 : 0);
|
|
82909
|
+
const lastUsedTimestamp = sortedByTime[0]?.timestamp ?? "";
|
|
82910
|
+
const recencyScore = computeRecencyScore(lastUsedTimestamp) * RECENCY_WEIGHT;
|
|
82911
|
+
const distinctTaskIDs = new Set(usageHistory.map((e) => e.taskID).filter(Boolean)).size;
|
|
82912
|
+
const taskDiversityScore = distinctTaskIDs / Math.max(1, usageHistory.length) * TASK_DIVERSITY_WEIGHT;
|
|
82913
|
+
return frequencyScore + complianceScore + recencyScore + taskDiversityScore + contextScore;
|
|
82914
|
+
}
|
|
82915
|
+
function rankSkillsForContext(skills, taskContext, directory) {
|
|
82916
|
+
const allEntries = readSkillUsageEntries(directory);
|
|
82917
|
+
const results = [];
|
|
82918
|
+
for (const skillPath of skills) {
|
|
82919
|
+
const skillEntries = allEntries.filter((e) => e.skillPath === skillPath);
|
|
82920
|
+
const score = computeSkillRelevanceScore(skillPath, taskContext, skillEntries);
|
|
82921
|
+
const entriesWithVerdict = skillEntries.filter((e) => e.complianceVerdict !== undefined && e.complianceVerdict !== "not_checked");
|
|
82922
|
+
const compliantCount = entriesWithVerdict.filter((e) => e.complianceVerdict === "compliant").length;
|
|
82923
|
+
const complianceRate = entriesWithVerdict.length > 0 ? compliantCount / entriesWithVerdict.length : 0;
|
|
82924
|
+
results.push({
|
|
82925
|
+
skillPath,
|
|
82926
|
+
score,
|
|
82927
|
+
usageCount: skillEntries.length,
|
|
82928
|
+
complianceRate
|
|
82929
|
+
});
|
|
82930
|
+
}
|
|
82931
|
+
results.sort((a, b) => {
|
|
82932
|
+
if (b.score !== a.score)
|
|
82933
|
+
return b.score - a.score;
|
|
82934
|
+
return b.usageCount - a.usageCount;
|
|
82935
|
+
});
|
|
82936
|
+
return results;
|
|
82937
|
+
}
|
|
82938
|
+
function getSkillStats(skillPath, directory) {
|
|
82939
|
+
const entries = readSkillUsageEntries(directory, { skillPath });
|
|
82940
|
+
if (entries.length === 0) {
|
|
82941
|
+
return {
|
|
82942
|
+
totalUsage: 0,
|
|
82943
|
+
complianceRate: 0,
|
|
82944
|
+
lastUsed: "",
|
|
82945
|
+
topAgents: []
|
|
82946
|
+
};
|
|
82947
|
+
}
|
|
82948
|
+
const entriesWithVerdict = entries.filter((e) => e.complianceVerdict !== undefined && e.complianceVerdict !== "not_checked");
|
|
82949
|
+
const compliantCount = entriesWithVerdict.filter((e) => e.complianceVerdict === "compliant").length;
|
|
82950
|
+
const complianceRate = entriesWithVerdict.length > 0 ? compliantCount / entriesWithVerdict.length : 0;
|
|
82951
|
+
const sortedByTime = [...entries].sort((a, b) => b.timestamp > a.timestamp ? 1 : b.timestamp < a.timestamp ? -1 : 0);
|
|
82952
|
+
const lastUsed = sortedByTime[0]?.timestamp ?? "";
|
|
82953
|
+
const agentCounts = new Map;
|
|
82954
|
+
for (const entry of entries) {
|
|
82955
|
+
agentCounts.set(entry.agentName, (agentCounts.get(entry.agentName) ?? 0) + 1);
|
|
82956
|
+
}
|
|
82957
|
+
const topAgents = Array.from(agentCounts.entries()).sort((a, b) => b[1] - a[1]).map(([agent, count]) => ({ agent, count }));
|
|
82958
|
+
return {
|
|
82959
|
+
totalUsage: entries.length,
|
|
82960
|
+
complianceRate,
|
|
82961
|
+
lastUsed,
|
|
82962
|
+
topAgents
|
|
82963
|
+
};
|
|
82964
|
+
}
|
|
82965
|
+
function formatSkillIndexWithContext(skills, directory) {
|
|
82966
|
+
const allEntries = readSkillUsageEntries(directory);
|
|
82967
|
+
const hasHistory = allEntries.length > 0;
|
|
82968
|
+
if (!hasHistory) {
|
|
82969
|
+
return skills.map((sp) => ` - ${extractSkillName(sp)}`).join(`
|
|
82970
|
+
`);
|
|
82971
|
+
}
|
|
82972
|
+
const lines = [];
|
|
82973
|
+
for (const skillPath of skills) {
|
|
82974
|
+
const stats = getSkillStats(skillPath, directory);
|
|
82975
|
+
const name2 = extractSkillName(skillPath);
|
|
82976
|
+
const compliancePct = Math.round(stats.complianceRate * 100);
|
|
82977
|
+
const topAgentNames = stats.topAgents.slice(0, 3).map((a) => a.agent).join(", ");
|
|
82978
|
+
lines.push(` ${name2}: ${skillPath} (used: ${stats.totalUsage}, compliance: ${compliancePct}%)` + (stats.topAgents.length > 0 ? ` → ${topAgentNames}` : ""));
|
|
82979
|
+
}
|
|
82980
|
+
return lines.join(`
|
|
82981
|
+
`);
|
|
82982
|
+
}
|
|
82983
|
+
_internals41.computeSkillRelevanceScore = computeSkillRelevanceScore;
|
|
82984
|
+
_internals41.rankSkillsForContext = rankSkillsForContext;
|
|
82985
|
+
_internals41.getSkillStats = getSkillStats;
|
|
82986
|
+
_internals41.formatSkillIndexWithContext = formatSkillIndexWithContext;
|
|
82987
|
+
_internals41.extractSkillName = extractSkillName;
|
|
82988
|
+
_internals41.computeRecencyScore = computeRecencyScore;
|
|
82989
|
+
_internals41.computeContextMatchScore = computeContextMatchScore;
|
|
82990
|
+
|
|
82991
|
+
// src/hooks/skill-propagation-gate.ts
|
|
82992
|
+
var SKILL_CAPABLE_AGENTS = new Set([
|
|
82993
|
+
"coder",
|
|
82994
|
+
"reviewer",
|
|
82995
|
+
"test_engineer",
|
|
82996
|
+
"sme",
|
|
82997
|
+
"docs",
|
|
82998
|
+
"designer"
|
|
82999
|
+
]);
|
|
83000
|
+
var SKILL_SEARCH_ROOTS = [
|
|
83001
|
+
".opencode/skills",
|
|
83002
|
+
".opencode/skills/generated",
|
|
83003
|
+
".claude/skills"
|
|
83004
|
+
];
|
|
83005
|
+
var MAX_SCORING_SESSION_ENTRIES = 500;
|
|
83006
|
+
var _internals42 = {
|
|
83007
|
+
readdirSync: fs62.readdirSync.bind(fs62),
|
|
83008
|
+
existsSync: fs62.existsSync.bind(fs62),
|
|
83009
|
+
statSync: fs62.statSync.bind(fs62),
|
|
83010
|
+
mkdirSync: fs62.mkdirSync.bind(fs62),
|
|
83011
|
+
appendFileSync: fs62.appendFileSync.bind(fs62),
|
|
83012
|
+
skillPropagationGateBefore: null,
|
|
83013
|
+
skillPropagationTransformScan: null,
|
|
83014
|
+
SKILL_CAPABLE_AGENTS,
|
|
83015
|
+
MAX_SCORING_SESSION_ENTRIES,
|
|
83016
|
+
writeWarnEvent: null,
|
|
83017
|
+
discoverAvailableSkills: null,
|
|
83018
|
+
parseDelegationArgs: null,
|
|
83019
|
+
appendSkillUsageEntry,
|
|
83020
|
+
readSkillUsageEntries,
|
|
83021
|
+
readSkillUsageEntriesTail,
|
|
83022
|
+
parseSkillPaths: null,
|
|
83023
|
+
extractTaskIdFromPrompt: null,
|
|
83024
|
+
computeSkillRelevanceScore
|
|
83025
|
+
};
|
|
83026
|
+
function discoverAvailableSkills(directory) {
|
|
83027
|
+
const results = [];
|
|
83028
|
+
for (const root of SKILL_SEARCH_ROOTS) {
|
|
83029
|
+
const rootPath = path89.join(directory, root);
|
|
83030
|
+
if (!_internals42.existsSync(rootPath))
|
|
83031
|
+
continue;
|
|
83032
|
+
let entries;
|
|
83033
|
+
try {
|
|
83034
|
+
entries = _internals42.readdirSync(rootPath);
|
|
83035
|
+
} catch {
|
|
83036
|
+
continue;
|
|
83037
|
+
}
|
|
83038
|
+
for (const entry of entries) {
|
|
83039
|
+
if (entry.startsWith("."))
|
|
83040
|
+
continue;
|
|
83041
|
+
const skillDir = path89.join(rootPath, entry);
|
|
83042
|
+
const skillFile = path89.join(skillDir, "SKILL.md");
|
|
83043
|
+
try {
|
|
83044
|
+
if (_internals42.statSync(skillDir).isDirectory() && _internals42.existsSync(skillFile)) {
|
|
83045
|
+
results.push(path89.join(root, entry, "SKILL.md"));
|
|
83046
|
+
}
|
|
83047
|
+
} catch (err2) {
|
|
83048
|
+
warn(`[skill-propagation-gate] failed to stat skill directory ${entry}: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
83049
|
+
}
|
|
83050
|
+
}
|
|
83051
|
+
}
|
|
83052
|
+
return [...new Set(results)];
|
|
83053
|
+
}
|
|
83054
|
+
function parseDelegationArgs(args2) {
|
|
83055
|
+
if (!args2 || typeof args2 !== "object")
|
|
83056
|
+
return null;
|
|
83057
|
+
const record3 = args2;
|
|
83058
|
+
const subagentType = typeof record3.subagent_type === "string" ? record3.subagent_type : "";
|
|
83059
|
+
const prompt = typeof record3.prompt === "string" ? record3.prompt : "";
|
|
83060
|
+
if (!subagentType && !prompt)
|
|
83061
|
+
return null;
|
|
83062
|
+
let targetAgent = subagentType;
|
|
83063
|
+
if (!targetAgent && prompt) {
|
|
83064
|
+
const lines = prompt.split(`
|
|
83065
|
+
`);
|
|
83066
|
+
for (const line of lines) {
|
|
83067
|
+
const trimmed = line.trim();
|
|
83068
|
+
if (trimmed) {
|
|
83069
|
+
targetAgent = trimmed;
|
|
83070
|
+
break;
|
|
83071
|
+
}
|
|
83072
|
+
}
|
|
83073
|
+
}
|
|
83074
|
+
if (!targetAgent)
|
|
83075
|
+
return null;
|
|
83076
|
+
let skillsField = "";
|
|
83077
|
+
if (prompt) {
|
|
83078
|
+
const lines = prompt.split(`
|
|
83079
|
+
`);
|
|
83080
|
+
for (const line of lines) {
|
|
83081
|
+
const trimmed = line.trim();
|
|
83082
|
+
if (trimmed.startsWith("SKILLS:")) {
|
|
83083
|
+
skillsField = trimmed.slice("SKILLS:".length).trim();
|
|
83084
|
+
break;
|
|
83085
|
+
}
|
|
83086
|
+
}
|
|
83087
|
+
}
|
|
83088
|
+
return { targetAgent, skillsField };
|
|
83089
|
+
}
|
|
83090
|
+
function writeWarnEvent2(directory, record3) {
|
|
83091
|
+
const filePath = path89.join(directory, ".swarm", "events.jsonl");
|
|
83092
|
+
try {
|
|
83093
|
+
const dir = path89.dirname(filePath);
|
|
83094
|
+
if (!_internals42.existsSync(dir)) {
|
|
83095
|
+
_internals42.mkdirSync(dir, { recursive: true });
|
|
83096
|
+
}
|
|
83097
|
+
_internals42.appendFileSync(filePath, `${JSON.stringify(record3)}
|
|
83098
|
+
`, "utf-8");
|
|
83099
|
+
} catch (err2) {
|
|
83100
|
+
warn(`[skill-propagation-gate] failed to write warning event: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
83101
|
+
}
|
|
83102
|
+
}
|
|
83103
|
+
function parseSkillPaths(fieldValue) {
|
|
83104
|
+
if (!fieldValue || typeof fieldValue !== "string")
|
|
83105
|
+
return [];
|
|
83106
|
+
const trimmed = fieldValue.trim();
|
|
83107
|
+
if (trimmed.toLowerCase() === "none" || trimmed === "")
|
|
83108
|
+
return [];
|
|
83109
|
+
return trimmed.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
83110
|
+
}
|
|
83111
|
+
function extractTaskIdFromPrompt(prompt) {
|
|
83112
|
+
if (!prompt || typeof prompt !== "string")
|
|
83113
|
+
return "unknown";
|
|
83114
|
+
const taskIdMatch = prompt.match(/\btaskId\s*[:=]\s*(\S+)/i);
|
|
83115
|
+
if (taskIdMatch)
|
|
83116
|
+
return taskIdMatch[1];
|
|
83117
|
+
const taskMatch = prompt.match(/\bTASK\s*[:=]\s*(\S+)/i);
|
|
83118
|
+
if (taskMatch)
|
|
83119
|
+
return taskMatch[1];
|
|
83120
|
+
return "unknown";
|
|
83121
|
+
}
|
|
83122
|
+
async function skillPropagationGateBefore(directory, input, config3) {
|
|
83123
|
+
if (!config3.enabled)
|
|
83124
|
+
return;
|
|
83125
|
+
const toolName = typeof input.tool === "string" ? input.tool : "";
|
|
83126
|
+
if (toolName !== "task" && toolName !== "Task")
|
|
83127
|
+
return;
|
|
83128
|
+
const agentRaw = typeof input.agent === "string" ? input.agent : "";
|
|
83129
|
+
if (!agentRaw)
|
|
83130
|
+
return;
|
|
83131
|
+
const baseAgent = stripKnownSwarmPrefix(agentRaw);
|
|
83132
|
+
if (baseAgent !== "architect")
|
|
83133
|
+
return;
|
|
83134
|
+
const parsed = _internals42.parseDelegationArgs(input.args);
|
|
83135
|
+
if (!parsed)
|
|
83136
|
+
return;
|
|
83137
|
+
const targetBase = stripKnownSwarmPrefix(parsed.targetAgent);
|
|
83138
|
+
if (!_internals42.SKILL_CAPABLE_AGENTS.has(targetBase))
|
|
83139
|
+
return;
|
|
83140
|
+
const sessionID = typeof input.sessionID === "string" ? input.sessionID : "unknown";
|
|
83141
|
+
const availableSkills = _internals42.discoverAvailableSkills(directory);
|
|
83142
|
+
const skillsValue = parsed.skillsField.trim();
|
|
83143
|
+
if (skillsValue && skillsValue.toLowerCase() !== "none") {
|
|
83144
|
+
const prompt = typeof input.args?.prompt === "string" ? String(input.args.prompt) : "";
|
|
83145
|
+
const taskId = _internals42.extractTaskIdFromPrompt(prompt);
|
|
83146
|
+
const skillPaths = _internals42.parseSkillPaths(skillsValue);
|
|
83147
|
+
let coderSkillPaths = [];
|
|
83148
|
+
if (prompt) {
|
|
83149
|
+
for (const line of prompt.split(`
|
|
83150
|
+
`)) {
|
|
83151
|
+
const trimmed = line.trim();
|
|
83152
|
+
if (trimmed.startsWith("SKILLS_USED_BY_CODER:")) {
|
|
83153
|
+
const fieldVal = trimmed.slice("SKILLS_USED_BY_CODER:".length).trim();
|
|
83154
|
+
coderSkillPaths = _internals42.parseSkillPaths(fieldVal);
|
|
83155
|
+
break;
|
|
83156
|
+
}
|
|
83157
|
+
}
|
|
83158
|
+
}
|
|
83159
|
+
const allPaths = [...new Set([...skillPaths, ...coderSkillPaths])];
|
|
83160
|
+
for (const skillPath of allPaths) {
|
|
83161
|
+
try {
|
|
83162
|
+
_internals42.appendSkillUsageEntry(directory, {
|
|
83163
|
+
skillPath,
|
|
83164
|
+
agentName: targetBase,
|
|
83165
|
+
taskID: taskId,
|
|
83166
|
+
complianceVerdict: "not_checked",
|
|
83167
|
+
sessionID,
|
|
83168
|
+
timestamp: new Date().toISOString()
|
|
83169
|
+
});
|
|
83170
|
+
} catch (err2) {
|
|
83171
|
+
warn(`[skill-propagation-gate] failed to record skill usage entry: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
83172
|
+
}
|
|
83173
|
+
}
|
|
83174
|
+
}
|
|
83175
|
+
if (skillsValue && skillsValue.toLowerCase() !== "none" && availableSkills.length > 0) {
|
|
83176
|
+
try {
|
|
83177
|
+
const sessionEntries = _internals42.readSkillUsageEntriesTail(directory, {
|
|
83178
|
+
sessionID
|
|
83179
|
+
});
|
|
83180
|
+
if (sessionEntries.length > _internals42.MAX_SCORING_SESSION_ENTRIES) {
|
|
83181
|
+
warn(`[skill-propagation-gate] skipping scoring — session has ${sessionEntries.length} entries (limit: ${_internals42.MAX_SCORING_SESSION_ENTRIES})`);
|
|
83182
|
+
} else {
|
|
83183
|
+
const prompt = typeof input.args?.prompt === "string" ? String(input.args.prompt) : "";
|
|
83184
|
+
const scored = availableSkills.map((skillPath) => {
|
|
83185
|
+
const skillEntries = sessionEntries.filter((e) => e.skillPath === skillPath);
|
|
83186
|
+
const score = _internals42.computeSkillRelevanceScore(skillPath, prompt, skillEntries);
|
|
83187
|
+
return { skillPath, score, usageCount: skillEntries.length };
|
|
83188
|
+
}).sort((a, b) => b.score - a.score || b.usageCount - a.usageCount);
|
|
83189
|
+
if (scored.length > 0) {
|
|
83190
|
+
const topSkills = scored.slice(0, 5).map((r) => ` ${r.skillPath} (score: ${r.score.toFixed(3)}, used: ${r.usageCount})`).join(`
|
|
83191
|
+
`);
|
|
83192
|
+
warn(`[skill-propagation-gate] Skill recommendations for task: ${topSkills}`);
|
|
83193
|
+
}
|
|
83194
|
+
}
|
|
83195
|
+
} catch (err2) {
|
|
83196
|
+
warn(`[skill-propagation-gate] skill scoring failed (non-blocking): ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
83197
|
+
}
|
|
83198
|
+
}
|
|
83199
|
+
if (availableSkills.length === 0)
|
|
83200
|
+
return;
|
|
83201
|
+
const skillsLower = skillsValue.toLowerCase();
|
|
83202
|
+
if (skillsValue && skillsLower !== "none")
|
|
83203
|
+
return;
|
|
83204
|
+
try {
|
|
83205
|
+
_internals42.writeWarnEvent(directory, {
|
|
83206
|
+
type: "skill_propagation_warn",
|
|
83207
|
+
timestamp: new Date().toISOString(),
|
|
83208
|
+
tool: toolName,
|
|
83209
|
+
agent: agentRaw,
|
|
83210
|
+
target_agent: parsed.targetAgent,
|
|
83211
|
+
sessionID,
|
|
83212
|
+
skills_missing: true,
|
|
83213
|
+
available_skills: availableSkills
|
|
83214
|
+
});
|
|
83215
|
+
} catch {}
|
|
83216
|
+
}
|
|
83217
|
+
var COMPLIANCE_PATTERN = /SKILL_COMPLIANCE\s*:\s*(COMPLIANT|PARTIAL|VIOLATED)(?:\s*(?:—|-)\s*(.*))?\s*$/i;
|
|
83218
|
+
var CODER_SKILLS_PATTERN = /SKILLS_USED_BY_CODER\s*:\s*(.+)/i;
|
|
83219
|
+
async function skillPropagationTransformScan(directory, output, sessionID) {
|
|
83220
|
+
if (!output?.messages)
|
|
83221
|
+
return;
|
|
83222
|
+
if (!sessionID)
|
|
83223
|
+
return;
|
|
83224
|
+
const messages = output.messages;
|
|
83225
|
+
let hadRecordingError = false;
|
|
83226
|
+
let dedupKeys = new Set;
|
|
83227
|
+
let existingEntries = [];
|
|
83228
|
+
try {
|
|
83229
|
+
existingEntries = _internals42.readSkillUsageEntries(directory, {
|
|
83230
|
+
sessionID
|
|
83231
|
+
});
|
|
83232
|
+
dedupKeys = new Set(existingEntries.map((e) => `${e.skillPath}|${e.agentName}|${e.taskID}`));
|
|
83233
|
+
} catch (err2) {
|
|
83234
|
+
warn(`[skill-propagation-gate] dedup preload failed, continuing without dedup: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
83235
|
+
}
|
|
83236
|
+
function isDuplicate(skillPath, agentName, taskID) {
|
|
83237
|
+
const key = `${skillPath}|${agentName}|${taskID}`;
|
|
83238
|
+
if (dedupKeys.has(key))
|
|
83239
|
+
return true;
|
|
83240
|
+
dedupKeys.add(key);
|
|
83241
|
+
return false;
|
|
83242
|
+
}
|
|
83243
|
+
for (let i2 = messages.length - 1;i2 >= 0; i2--) {
|
|
83244
|
+
const m = messages[i2];
|
|
83245
|
+
const agent = m.info?.agent;
|
|
83246
|
+
if (typeof agent !== "string" || stripKnownSwarmPrefix(agent) !== "reviewer") {
|
|
83247
|
+
continue;
|
|
83248
|
+
}
|
|
83249
|
+
const text = (m.parts ?? []).map((p) => typeof p.text === "string" ? p.text : "").join(`
|
|
83250
|
+
`);
|
|
83251
|
+
if (!text)
|
|
83252
|
+
continue;
|
|
83253
|
+
const skillPaths = [];
|
|
83254
|
+
for (const line of text.split(`
|
|
83255
|
+
`)) {
|
|
83256
|
+
const coderMatch = line.trim().match(CODER_SKILLS_PATTERN);
|
|
83257
|
+
if (coderMatch) {
|
|
83258
|
+
const parsed = _internals42.parseSkillPaths(coderMatch[1]);
|
|
83259
|
+
skillPaths.push(...parsed);
|
|
83260
|
+
}
|
|
83261
|
+
}
|
|
83262
|
+
let resolvedTaskID = "unknown";
|
|
83263
|
+
if (existingEntries.length > 0) {
|
|
83264
|
+
const latestDelegation = [...existingEntries].reverse().find((e) => e.agentName !== "reviewer" && e.skillPath !== "__overall__");
|
|
83265
|
+
if (latestDelegation) {
|
|
83266
|
+
resolvedTaskID = latestDelegation.taskID;
|
|
83267
|
+
if (skillPaths.length === 0) {
|
|
83268
|
+
const delegatedPaths = existingEntries.filter((e) => e.agentName !== "reviewer" && e.skillPath !== "__overall__" && e.taskID === resolvedTaskID).map((e) => e.skillPath);
|
|
83269
|
+
if (delegatedPaths.length > 0) {
|
|
83270
|
+
skillPaths.push(...new Set(delegatedPaths));
|
|
83271
|
+
}
|
|
83272
|
+
}
|
|
83273
|
+
}
|
|
83274
|
+
}
|
|
83275
|
+
for (const line of text.split(`
|
|
83276
|
+
`)) {
|
|
83277
|
+
const complianceMatch = line.trim().match(COMPLIANCE_PATTERN);
|
|
83278
|
+
if (!complianceMatch)
|
|
83279
|
+
continue;
|
|
83280
|
+
const verdict = complianceMatch[1].toLowerCase();
|
|
83281
|
+
const notes = (complianceMatch[2] ?? "").trim();
|
|
83282
|
+
const paths = skillPaths.length > 0 ? skillPaths : ["__overall__"];
|
|
83283
|
+
for (const skillPath of paths) {
|
|
83284
|
+
if (hadRecordingError)
|
|
83285
|
+
break;
|
|
83286
|
+
if (isDuplicate(skillPath, "reviewer", resolvedTaskID))
|
|
83287
|
+
continue;
|
|
83288
|
+
try {
|
|
83289
|
+
_internals42.appendSkillUsageEntry(directory, {
|
|
83290
|
+
skillPath,
|
|
83291
|
+
agentName: "reviewer",
|
|
83292
|
+
taskID: resolvedTaskID,
|
|
83293
|
+
complianceVerdict: verdict,
|
|
83294
|
+
reviewerNotes: notes || undefined,
|
|
83295
|
+
sessionID,
|
|
83296
|
+
timestamp: new Date().toISOString()
|
|
83297
|
+
});
|
|
83298
|
+
} catch (err2) {
|
|
83299
|
+
hadRecordingError = true;
|
|
83300
|
+
warn(`[skill-propagation-gate] transform-scan compliance recording failed: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
83301
|
+
}
|
|
83302
|
+
}
|
|
83303
|
+
break;
|
|
83304
|
+
}
|
|
83305
|
+
break;
|
|
83306
|
+
}
|
|
83307
|
+
if (hadRecordingError)
|
|
83308
|
+
return;
|
|
83309
|
+
for (let i2 = messages.length - 1;i2 >= 0; i2--) {
|
|
83310
|
+
const m = messages[i2];
|
|
83311
|
+
const agent = m.info?.agent;
|
|
83312
|
+
if (typeof agent !== "string" || stripKnownSwarmPrefix(agent) !== "architect") {
|
|
83313
|
+
continue;
|
|
83314
|
+
}
|
|
83315
|
+
const text = (m.parts ?? []).map((p) => typeof p.text === "string" ? p.text : "").join(`
|
|
83316
|
+
`);
|
|
83317
|
+
if (!text)
|
|
83318
|
+
continue;
|
|
83319
|
+
let currentTargetAgent = "";
|
|
83320
|
+
let skillsField = "";
|
|
83321
|
+
for (const line of text.split(`
|
|
83322
|
+
`)) {
|
|
83323
|
+
const trimmed = line.trim();
|
|
83324
|
+
if (trimmed.match(/TO\s+(coder|reviewer|test_engineer|sme|docs|designer)/i)) {
|
|
83325
|
+
const agentMatch = trimmed.match(/TO\s+(coder|reviewer|test_engineer|sme|docs|designer)/i);
|
|
83326
|
+
if (agentMatch)
|
|
83327
|
+
currentTargetAgent = agentMatch[1].toLowerCase();
|
|
83328
|
+
}
|
|
83329
|
+
if (trimmed.startsWith("SKILLS:")) {
|
|
83330
|
+
skillsField = trimmed.slice("SKILLS:".length).trim();
|
|
83331
|
+
}
|
|
83332
|
+
if (currentTargetAgent && skillsField && skillsField.toLowerCase() !== "none") {
|
|
83333
|
+
const skillPaths = _internals42.parseSkillPaths(skillsField);
|
|
83334
|
+
const taskId = _internals42.extractTaskIdFromPrompt(text);
|
|
83335
|
+
for (const skillPath of skillPaths) {
|
|
83336
|
+
if (hadRecordingError)
|
|
83337
|
+
break;
|
|
83338
|
+
if (isDuplicate(skillPath, currentTargetAgent, taskId))
|
|
83339
|
+
continue;
|
|
83340
|
+
try {
|
|
83341
|
+
_internals42.appendSkillUsageEntry(directory, {
|
|
83342
|
+
skillPath,
|
|
83343
|
+
agentName: currentTargetAgent,
|
|
83344
|
+
taskID: taskId,
|
|
83345
|
+
complianceVerdict: "not_checked",
|
|
83346
|
+
sessionID,
|
|
83347
|
+
timestamp: new Date().toISOString()
|
|
83348
|
+
});
|
|
83349
|
+
} catch (err2) {
|
|
83350
|
+
hadRecordingError = true;
|
|
83351
|
+
warn(`[skill-propagation-gate] transform-scan delegation recording failed: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
83352
|
+
}
|
|
83353
|
+
}
|
|
83354
|
+
currentTargetAgent = "";
|
|
83355
|
+
skillsField = "";
|
|
83356
|
+
}
|
|
83357
|
+
}
|
|
83358
|
+
break;
|
|
83359
|
+
}
|
|
83360
|
+
}
|
|
83361
|
+
_internals42.skillPropagationGateBefore = skillPropagationGateBefore;
|
|
83362
|
+
_internals42.skillPropagationTransformScan = skillPropagationTransformScan;
|
|
83363
|
+
_internals42.writeWarnEvent = writeWarnEvent2;
|
|
83364
|
+
_internals42.discoverAvailableSkills = discoverAvailableSkills;
|
|
83365
|
+
_internals42.parseDelegationArgs = parseDelegationArgs;
|
|
83366
|
+
_internals42.parseSkillPaths = parseSkillPaths;
|
|
83367
|
+
_internals42.extractTaskIdFromPrompt = extractTaskIdFromPrompt;
|
|
83368
|
+
|
|
83369
|
+
// src/hooks/slop-detector.ts
|
|
83370
|
+
import * as fs63 from "node:fs";
|
|
83371
|
+
import * as path90 from "node:path";
|
|
82657
83372
|
var WRITE_EDIT_TOOLS = new Set([
|
|
82658
83373
|
"write",
|
|
82659
83374
|
"edit",
|
|
@@ -82698,12 +83413,12 @@ function checkBoilerplateExplosion(content, taskDescription, threshold) {
|
|
|
82698
83413
|
function walkFiles(dir, exts, deadline) {
|
|
82699
83414
|
const results = [];
|
|
82700
83415
|
try {
|
|
82701
|
-
for (const entry of
|
|
83416
|
+
for (const entry of fs63.readdirSync(dir, { withFileTypes: true })) {
|
|
82702
83417
|
if (deadline !== undefined && Date.now() > deadline)
|
|
82703
83418
|
break;
|
|
82704
83419
|
if (entry.isSymbolicLink())
|
|
82705
83420
|
continue;
|
|
82706
|
-
const full =
|
|
83421
|
+
const full = path90.join(dir, entry.name);
|
|
82707
83422
|
if (entry.isDirectory()) {
|
|
82708
83423
|
if (entry.name === "node_modules" || entry.name === ".git")
|
|
82709
83424
|
continue;
|
|
@@ -82718,7 +83433,7 @@ function walkFiles(dir, exts, deadline) {
|
|
|
82718
83433
|
return results;
|
|
82719
83434
|
}
|
|
82720
83435
|
function checkDeadExports(content, projectDir, startTime) {
|
|
82721
|
-
const hasPackageJson =
|
|
83436
|
+
const hasPackageJson = fs63.existsSync(path90.join(projectDir, "package.json"));
|
|
82722
83437
|
if (!hasPackageJson)
|
|
82723
83438
|
return null;
|
|
82724
83439
|
const exportMatches = content.matchAll(/^\+(?:export)\s+(?:function|class|const|type|interface)\s+(\w{3,})/gm);
|
|
@@ -82741,7 +83456,7 @@ function checkDeadExports(content, projectDir, startTime) {
|
|
|
82741
83456
|
if (found || Date.now() - startTime > 480)
|
|
82742
83457
|
break;
|
|
82743
83458
|
try {
|
|
82744
|
-
const text =
|
|
83459
|
+
const text = fs63.readFileSync(file3, "utf-8");
|
|
82745
83460
|
if (importPattern.test(text))
|
|
82746
83461
|
found = true;
|
|
82747
83462
|
importPattern.lastIndex = 0;
|
|
@@ -82832,17 +83547,17 @@ function checkDuplicateUtility(content, projectDir, startTime, targetFile) {
|
|
|
82832
83547
|
for (const utilDir of utilityDirs) {
|
|
82833
83548
|
if (Date.now() > deadline)
|
|
82834
83549
|
break;
|
|
82835
|
-
const utilPath =
|
|
82836
|
-
if (!
|
|
83550
|
+
const utilPath = path90.join(projectDir, utilDir);
|
|
83551
|
+
if (!fs63.existsSync(utilPath))
|
|
82837
83552
|
continue;
|
|
82838
83553
|
const files = walkFiles(utilPath, [".ts", ".tsx", ".js", ".jsx"], deadline);
|
|
82839
83554
|
for (const file3 of files) {
|
|
82840
83555
|
if (Date.now() > deadline)
|
|
82841
83556
|
break;
|
|
82842
|
-
if (targetFile &&
|
|
83557
|
+
if (targetFile && path90.resolve(file3) === path90.resolve(targetFile))
|
|
82843
83558
|
continue;
|
|
82844
83559
|
try {
|
|
82845
|
-
const text =
|
|
83560
|
+
const text = fs63.readFileSync(file3, "utf-8");
|
|
82846
83561
|
for (const name2 of newExports) {
|
|
82847
83562
|
const exportPattern = new RegExp(`\\bexport\\s+(?:function|class|const|type|interface)\\s+${name2}\\b`);
|
|
82848
83563
|
if (exportPattern.test(text)) {
|
|
@@ -82925,7 +83640,7 @@ Review before proceeding.`;
|
|
|
82925
83640
|
// src/hooks/steering-consumed.ts
|
|
82926
83641
|
init_bun_compat();
|
|
82927
83642
|
init_utils2();
|
|
82928
|
-
import * as
|
|
83643
|
+
import * as fs64 from "node:fs";
|
|
82929
83644
|
function recordSteeringConsumed(directory, directiveId) {
|
|
82930
83645
|
try {
|
|
82931
83646
|
const eventsPath = validateSwarmPath(directory, "events.jsonl");
|
|
@@ -82934,7 +83649,7 @@ function recordSteeringConsumed(directory, directiveId) {
|
|
|
82934
83649
|
directiveId,
|
|
82935
83650
|
timestamp: new Date().toISOString()
|
|
82936
83651
|
};
|
|
82937
|
-
|
|
83652
|
+
fs64.appendFileSync(eventsPath, `${JSON.stringify(event)}
|
|
82938
83653
|
`, "utf-8");
|
|
82939
83654
|
} catch {}
|
|
82940
83655
|
}
|
|
@@ -82976,15 +83691,15 @@ function createSteeringConsumedHook(directory) {
|
|
|
82976
83691
|
|
|
82977
83692
|
// src/hooks/trajectory-logger.ts
|
|
82978
83693
|
init_manager2();
|
|
82979
|
-
import * as
|
|
82980
|
-
import * as
|
|
83694
|
+
import * as fs66 from "node:fs/promises";
|
|
83695
|
+
import * as path92 from "node:path";
|
|
82981
83696
|
|
|
82982
83697
|
// src/prm/trajectory-store.ts
|
|
82983
83698
|
init_utils2();
|
|
82984
|
-
import * as
|
|
82985
|
-
import * as
|
|
83699
|
+
import * as fs65 from "node:fs/promises";
|
|
83700
|
+
import * as path91 from "node:path";
|
|
82986
83701
|
function getTrajectoryPath(sessionId, directory) {
|
|
82987
|
-
const relativePath =
|
|
83702
|
+
const relativePath = path91.join("trajectories", `${sessionId}.jsonl`);
|
|
82988
83703
|
return validateSwarmPath(directory, relativePath);
|
|
82989
83704
|
}
|
|
82990
83705
|
var _inMemoryTrajectoryCache = new Map;
|
|
@@ -83003,10 +83718,10 @@ async function appendTrajectoryEntry(sessionId, entry, directory, maxLines = 100
|
|
|
83003
83718
|
_inMemoryTrajectoryCache.set(sessionId, cached3);
|
|
83004
83719
|
}
|
|
83005
83720
|
const trajectoryPath = getTrajectoryPath(sessionId, directory);
|
|
83006
|
-
await
|
|
83721
|
+
await fs65.mkdir(path91.dirname(trajectoryPath), { recursive: true });
|
|
83007
83722
|
const line = `${JSON.stringify(entry)}
|
|
83008
83723
|
`;
|
|
83009
|
-
await
|
|
83724
|
+
await fs65.appendFile(trajectoryPath, line, "utf-8");
|
|
83010
83725
|
} catch (err2) {
|
|
83011
83726
|
console.warn(`[trajectory-store] Failed to append trajectory entry: ${err2}`);
|
|
83012
83727
|
}
|
|
@@ -83014,7 +83729,7 @@ async function appendTrajectoryEntry(sessionId, entry, directory, maxLines = 100
|
|
|
83014
83729
|
async function readTrajectory(sessionId, directory) {
|
|
83015
83730
|
try {
|
|
83016
83731
|
const trajectoryPath = getTrajectoryPath(sessionId, directory);
|
|
83017
|
-
const content = await
|
|
83732
|
+
const content = await fs65.readFile(trajectoryPath, "utf-8");
|
|
83018
83733
|
const lines = content.split(`
|
|
83019
83734
|
`).filter((line) => line.trim().length > 0);
|
|
83020
83735
|
const entries = [];
|
|
@@ -83038,15 +83753,15 @@ async function cleanupOldTrajectoryFiles(directory, maxAgeDays = 7) {
|
|
|
83038
83753
|
for (const subdir of ["trajectories", "replays"]) {
|
|
83039
83754
|
try {
|
|
83040
83755
|
const dirPath = validateSwarmPath(directory, subdir);
|
|
83041
|
-
const entries = await
|
|
83756
|
+
const entries = await fs65.readdir(dirPath, { withFileTypes: true });
|
|
83042
83757
|
for (const entry of entries) {
|
|
83043
83758
|
if (!entry.isFile())
|
|
83044
83759
|
continue;
|
|
83045
|
-
const filePath =
|
|
83760
|
+
const filePath = path91.join(dirPath, entry.name);
|
|
83046
83761
|
try {
|
|
83047
|
-
const stat8 = await
|
|
83762
|
+
const stat8 = await fs65.stat(filePath);
|
|
83048
83763
|
if (now - stat8.mtimeMs > cutoffMs) {
|
|
83049
|
-
await
|
|
83764
|
+
await fs65.unlink(filePath);
|
|
83050
83765
|
}
|
|
83051
83766
|
} catch {}
|
|
83052
83767
|
}
|
|
@@ -83096,7 +83811,7 @@ function isSensitiveKey(key) {
|
|
|
83096
83811
|
}
|
|
83097
83812
|
async function truncateTrajectoryFile(filePath, maxLines) {
|
|
83098
83813
|
try {
|
|
83099
|
-
const content = await
|
|
83814
|
+
const content = await fs66.readFile(filePath, "utf-8");
|
|
83100
83815
|
const lines = content.split(`
|
|
83101
83816
|
`).filter((line) => line.trim().length > 0);
|
|
83102
83817
|
if (lines.length <= maxLines) {
|
|
@@ -83104,7 +83819,7 @@ async function truncateTrajectoryFile(filePath, maxLines) {
|
|
|
83104
83819
|
}
|
|
83105
83820
|
const keepCount = Math.floor(maxLines / 2);
|
|
83106
83821
|
const keptLines = lines.slice(-keepCount);
|
|
83107
|
-
await
|
|
83822
|
+
await fs66.writeFile(filePath, `${keptLines.join(`
|
|
83108
83823
|
`)}
|
|
83109
83824
|
`, "utf-8");
|
|
83110
83825
|
} catch {}
|
|
@@ -83234,13 +83949,13 @@ function createTrajectoryLoggerHook(config3, _directory) {
|
|
|
83234
83949
|
elapsed_ms
|
|
83235
83950
|
};
|
|
83236
83951
|
const sanitized = sanitizeTaskId2(taskId);
|
|
83237
|
-
const relativePath =
|
|
83952
|
+
const relativePath = path92.join("evidence", sanitized, "trajectory.jsonl");
|
|
83238
83953
|
const trajectoryPath = validateSwarmPath(_directory, relativePath);
|
|
83239
83954
|
try {
|
|
83240
|
-
await
|
|
83955
|
+
await fs66.mkdir(path92.dirname(trajectoryPath), { recursive: true });
|
|
83241
83956
|
const line = `${JSON.stringify(entry)}
|
|
83242
83957
|
`;
|
|
83243
|
-
await
|
|
83958
|
+
await fs66.appendFile(trajectoryPath, line, "utf-8");
|
|
83244
83959
|
await truncateTrajectoryFile(trajectoryPath, maxLines);
|
|
83245
83960
|
} catch {}
|
|
83246
83961
|
try {
|
|
@@ -83787,17 +84502,17 @@ init_state();
|
|
|
83787
84502
|
init_telemetry();
|
|
83788
84503
|
|
|
83789
84504
|
// src/prm/replay.ts
|
|
83790
|
-
import { promises as
|
|
83791
|
-
import
|
|
84505
|
+
import { promises as fs67 } from "node:fs";
|
|
84506
|
+
import path93 from "node:path";
|
|
83792
84507
|
function isPathSafe2(targetPath, basePath) {
|
|
83793
|
-
const resolvedTarget =
|
|
83794
|
-
const resolvedBase =
|
|
83795
|
-
const rel =
|
|
83796
|
-
return !rel.startsWith("..") && !
|
|
84508
|
+
const resolvedTarget = path93.resolve(targetPath);
|
|
84509
|
+
const resolvedBase = path93.resolve(basePath);
|
|
84510
|
+
const rel = path93.relative(resolvedBase, resolvedTarget);
|
|
84511
|
+
return !rel.startsWith("..") && !path93.isAbsolute(rel);
|
|
83797
84512
|
}
|
|
83798
84513
|
function isWithinReplaysDir(targetPath) {
|
|
83799
|
-
const resolved =
|
|
83800
|
-
const parts2 = resolved.split(
|
|
84514
|
+
const resolved = path93.resolve(targetPath);
|
|
84515
|
+
const parts2 = resolved.split(path93.sep);
|
|
83801
84516
|
for (let i2 = 0;i2 < parts2.length - 1; i2++) {
|
|
83802
84517
|
if (parts2[i2] === ".swarm" && parts2[i2 + 1] === "replays") {
|
|
83803
84518
|
return true;
|
|
@@ -83810,15 +84525,15 @@ function sanitizeFilename(input) {
|
|
|
83810
84525
|
}
|
|
83811
84526
|
async function startReplayRecording(sessionID, directory) {
|
|
83812
84527
|
try {
|
|
83813
|
-
const replayDir =
|
|
84528
|
+
const replayDir = path93.join(directory, ".swarm", "replays");
|
|
83814
84529
|
const safeSessionID = sanitizeFilename(sessionID);
|
|
83815
84530
|
const filename = `${safeSessionID}-${Date.now()}.jsonl`;
|
|
83816
|
-
const filepath =
|
|
84531
|
+
const filepath = path93.join(replayDir, filename);
|
|
83817
84532
|
if (!isPathSafe2(filepath, replayDir)) {
|
|
83818
84533
|
console.warn(`[replay] Invalid path detected - path traversal attempt blocked for session ${sessionID}`);
|
|
83819
84534
|
return null;
|
|
83820
84535
|
}
|
|
83821
|
-
await
|
|
84536
|
+
await fs67.mkdir(replayDir, { recursive: true });
|
|
83822
84537
|
return filepath;
|
|
83823
84538
|
} catch (err2) {
|
|
83824
84539
|
console.warn(`[replay] Failed to start recording for session ${sessionID}: ${err2}`);
|
|
@@ -83838,7 +84553,7 @@ async function recordReplayEntry(artifactPath, sessionID, entry) {
|
|
|
83838
84553
|
};
|
|
83839
84554
|
const line = `${JSON.stringify(fullEntry)}
|
|
83840
84555
|
`;
|
|
83841
|
-
await
|
|
84556
|
+
await fs67.appendFile(artifactPath, line, "utf-8");
|
|
83842
84557
|
} catch (err2) {
|
|
83843
84558
|
console.warn(`[replay] Failed to record entry: ${err2}`);
|
|
83844
84559
|
}
|
|
@@ -83973,7 +84688,7 @@ init_version_check();
|
|
|
83973
84688
|
init_utils2();
|
|
83974
84689
|
init_state();
|
|
83975
84690
|
init_bun_compat();
|
|
83976
|
-
import { renameSync as
|
|
84691
|
+
import { renameSync as renameSync18 } from "node:fs";
|
|
83977
84692
|
var TRANSIENT_SESSION_FIELDS = [
|
|
83978
84693
|
{ name: "revisionLimitHit", resetValue: false },
|
|
83979
84694
|
{ name: "coderRevisions", resetValue: 0 },
|
|
@@ -84100,7 +84815,7 @@ async function readSnapshot(directory) {
|
|
|
84100
84815
|
if (parsed.version !== 1 && parsed.version !== 2) {
|
|
84101
84816
|
try {
|
|
84102
84817
|
const quarantinePath = validateSwarmPath(directory, "session/state.json.quarantine");
|
|
84103
|
-
|
|
84818
|
+
renameSync18(resolvedPath, quarantinePath);
|
|
84104
84819
|
} catch {}
|
|
84105
84820
|
return null;
|
|
84106
84821
|
}
|
|
@@ -84186,8 +84901,8 @@ init_telemetry();
|
|
|
84186
84901
|
// src/tools/batch-symbols.ts
|
|
84187
84902
|
init_dist();
|
|
84188
84903
|
init_create_tool();
|
|
84189
|
-
import * as
|
|
84190
|
-
import * as
|
|
84904
|
+
import * as fs68 from "node:fs";
|
|
84905
|
+
import * as path94 from "node:path";
|
|
84191
84906
|
init_path_security();
|
|
84192
84907
|
var WINDOWS_RESERVED_NAMES2 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
|
|
84193
84908
|
function containsWindowsAttacks2(str) {
|
|
@@ -84204,14 +84919,14 @@ function containsWindowsAttacks2(str) {
|
|
|
84204
84919
|
}
|
|
84205
84920
|
function isPathInWorkspace2(filePath, workspace) {
|
|
84206
84921
|
try {
|
|
84207
|
-
const resolvedPath =
|
|
84208
|
-
if (!
|
|
84922
|
+
const resolvedPath = path94.resolve(workspace, filePath);
|
|
84923
|
+
if (!fs68.existsSync(resolvedPath)) {
|
|
84209
84924
|
return true;
|
|
84210
84925
|
}
|
|
84211
|
-
const realWorkspace =
|
|
84212
|
-
const realResolvedPath =
|
|
84213
|
-
const relativePath =
|
|
84214
|
-
if (relativePath.startsWith("..") ||
|
|
84926
|
+
const realWorkspace = fs68.realpathSync(workspace);
|
|
84927
|
+
const realResolvedPath = fs68.realpathSync(resolvedPath);
|
|
84928
|
+
const relativePath = path94.relative(realWorkspace, realResolvedPath);
|
|
84929
|
+
if (relativePath.startsWith("..") || path94.isAbsolute(relativePath)) {
|
|
84215
84930
|
return false;
|
|
84216
84931
|
}
|
|
84217
84932
|
return true;
|
|
@@ -84220,7 +84935,7 @@ function isPathInWorkspace2(filePath, workspace) {
|
|
|
84220
84935
|
}
|
|
84221
84936
|
}
|
|
84222
84937
|
function processFile2(file3, cwd, exportedOnly) {
|
|
84223
|
-
const ext =
|
|
84938
|
+
const ext = path94.extname(file3);
|
|
84224
84939
|
if (containsControlChars(file3)) {
|
|
84225
84940
|
return {
|
|
84226
84941
|
file: file3,
|
|
@@ -84253,8 +84968,8 @@ function processFile2(file3, cwd, exportedOnly) {
|
|
|
84253
84968
|
errorType: "path-outside-workspace"
|
|
84254
84969
|
};
|
|
84255
84970
|
}
|
|
84256
|
-
const fullPath =
|
|
84257
|
-
if (!
|
|
84971
|
+
const fullPath = path94.join(cwd, file3);
|
|
84972
|
+
if (!fs68.existsSync(fullPath)) {
|
|
84258
84973
|
return {
|
|
84259
84974
|
file: file3,
|
|
84260
84975
|
success: false,
|
|
@@ -84285,14 +85000,14 @@ function processFile2(file3, cwd, exportedOnly) {
|
|
|
84285
85000
|
}
|
|
84286
85001
|
let isEmptyFile = false;
|
|
84287
85002
|
try {
|
|
84288
|
-
const stats =
|
|
85003
|
+
const stats = fs68.statSync(fullPath);
|
|
84289
85004
|
if (stats.size === 0) {
|
|
84290
85005
|
isEmptyFile = true;
|
|
84291
85006
|
}
|
|
84292
85007
|
} catch {}
|
|
84293
85008
|
if (syms.length === 0) {
|
|
84294
85009
|
try {
|
|
84295
|
-
const content =
|
|
85010
|
+
const content = fs68.readFileSync(fullPath, "utf-8");
|
|
84296
85011
|
if (content.trim().length === 0) {
|
|
84297
85012
|
isEmptyFile = true;
|
|
84298
85013
|
}
|
|
@@ -84544,25 +85259,25 @@ init_manager2();
|
|
|
84544
85259
|
init_task_id();
|
|
84545
85260
|
init_create_tool();
|
|
84546
85261
|
init_resolve_working_directory();
|
|
84547
|
-
import * as
|
|
84548
|
-
import * as
|
|
85262
|
+
import * as fs69 from "node:fs";
|
|
85263
|
+
import * as path95 from "node:path";
|
|
84549
85264
|
var EVIDENCE_DIR = ".swarm/evidence";
|
|
84550
85265
|
function isValidTaskId3(taskId) {
|
|
84551
85266
|
return isStrictTaskId(taskId);
|
|
84552
85267
|
}
|
|
84553
85268
|
function isPathWithinSwarm(filePath, workspaceRoot) {
|
|
84554
|
-
const normalizedWorkspace =
|
|
84555
|
-
const swarmPath =
|
|
84556
|
-
const normalizedPath =
|
|
85269
|
+
const normalizedWorkspace = path95.resolve(workspaceRoot);
|
|
85270
|
+
const swarmPath = path95.join(normalizedWorkspace, ".swarm", "evidence");
|
|
85271
|
+
const normalizedPath = path95.resolve(filePath);
|
|
84557
85272
|
return normalizedPath.startsWith(swarmPath);
|
|
84558
85273
|
}
|
|
84559
85274
|
function readEvidenceFile(evidencePath) {
|
|
84560
|
-
if (!
|
|
85275
|
+
if (!fs69.existsSync(evidencePath)) {
|
|
84561
85276
|
return null;
|
|
84562
85277
|
}
|
|
84563
85278
|
let content;
|
|
84564
85279
|
try {
|
|
84565
|
-
content =
|
|
85280
|
+
content = fs69.readFileSync(evidencePath, "utf-8");
|
|
84566
85281
|
} catch {
|
|
84567
85282
|
return null;
|
|
84568
85283
|
}
|
|
@@ -84634,7 +85349,7 @@ var check_gate_status = createSwarmTool({
|
|
|
84634
85349
|
};
|
|
84635
85350
|
return JSON.stringify(errorResult, null, 2);
|
|
84636
85351
|
}
|
|
84637
|
-
const evidencePath =
|
|
85352
|
+
const evidencePath = path95.join(directory, EVIDENCE_DIR, `${taskIdInput}.json`);
|
|
84638
85353
|
if (!isPathWithinSwarm(evidencePath, directory)) {
|
|
84639
85354
|
const errorResult = {
|
|
84640
85355
|
taskId: taskIdInput,
|
|
@@ -84730,8 +85445,8 @@ init_utils2();
|
|
|
84730
85445
|
init_state();
|
|
84731
85446
|
init_create_tool();
|
|
84732
85447
|
init_resolve_working_directory();
|
|
84733
|
-
import * as
|
|
84734
|
-
import * as
|
|
85448
|
+
import * as fs70 from "node:fs";
|
|
85449
|
+
import * as path96 from "node:path";
|
|
84735
85450
|
function extractMatches(regex, text) {
|
|
84736
85451
|
return Array.from(text.matchAll(regex));
|
|
84737
85452
|
}
|
|
@@ -84825,7 +85540,7 @@ async function executeCompletionVerify(args2, directory) {
|
|
|
84825
85540
|
let plan;
|
|
84826
85541
|
try {
|
|
84827
85542
|
const planPath = validateSwarmPath(directory, "plan.json");
|
|
84828
|
-
const planRaw =
|
|
85543
|
+
const planRaw = fs70.readFileSync(planPath, "utf-8");
|
|
84829
85544
|
plan = JSON.parse(planRaw);
|
|
84830
85545
|
} catch {
|
|
84831
85546
|
const result2 = {
|
|
@@ -84883,10 +85598,10 @@ async function executeCompletionVerify(args2, directory) {
|
|
|
84883
85598
|
let hasFileReadFailure = false;
|
|
84884
85599
|
for (const filePath of fileTargets) {
|
|
84885
85600
|
const normalizedPath = filePath.replace(/\\/g, "/");
|
|
84886
|
-
const resolvedPath =
|
|
84887
|
-
const projectRoot =
|
|
84888
|
-
const relative20 =
|
|
84889
|
-
const withinProject = relative20 === "" || !relative20.startsWith("..") && !
|
|
85601
|
+
const resolvedPath = path96.resolve(directory, normalizedPath);
|
|
85602
|
+
const projectRoot = path96.resolve(directory);
|
|
85603
|
+
const relative20 = path96.relative(projectRoot, resolvedPath);
|
|
85604
|
+
const withinProject = relative20 === "" || !relative20.startsWith("..") && !path96.isAbsolute(relative20);
|
|
84890
85605
|
if (!withinProject) {
|
|
84891
85606
|
blockedTasks.push({
|
|
84892
85607
|
task_id: task.id,
|
|
@@ -84899,7 +85614,7 @@ async function executeCompletionVerify(args2, directory) {
|
|
|
84899
85614
|
}
|
|
84900
85615
|
let fileContent;
|
|
84901
85616
|
try {
|
|
84902
|
-
fileContent =
|
|
85617
|
+
fileContent = fs70.readFileSync(resolvedPath, "utf-8");
|
|
84903
85618
|
} catch {
|
|
84904
85619
|
blockedTasks.push({
|
|
84905
85620
|
task_id: task.id,
|
|
@@ -84941,9 +85656,9 @@ async function executeCompletionVerify(args2, directory) {
|
|
|
84941
85656
|
blockedTasks
|
|
84942
85657
|
};
|
|
84943
85658
|
try {
|
|
84944
|
-
const evidenceDir =
|
|
84945
|
-
const evidencePath =
|
|
84946
|
-
|
|
85659
|
+
const evidenceDir = path96.join(directory, ".swarm", "evidence", `${phase}`);
|
|
85660
|
+
const evidencePath = path96.join(evidenceDir, "completion-verify.json");
|
|
85661
|
+
fs70.mkdirSync(evidenceDir, { recursive: true });
|
|
84947
85662
|
const evidenceBundle = {
|
|
84948
85663
|
schema_version: "1.0.0",
|
|
84949
85664
|
task_id: "completion-verify",
|
|
@@ -84964,7 +85679,7 @@ async function executeCompletionVerify(args2, directory) {
|
|
|
84964
85679
|
}
|
|
84965
85680
|
]
|
|
84966
85681
|
};
|
|
84967
|
-
|
|
85682
|
+
fs70.writeFileSync(evidencePath, JSON.stringify(evidenceBundle, null, 2), "utf-8");
|
|
84968
85683
|
} catch {}
|
|
84969
85684
|
return JSON.stringify(result, null, 2);
|
|
84970
85685
|
}
|
|
@@ -85018,12 +85733,12 @@ var completion_verify = createSwarmTool({
|
|
|
85018
85733
|
});
|
|
85019
85734
|
// src/tools/complexity-hotspots.ts
|
|
85020
85735
|
init_zod();
|
|
85021
|
-
import * as
|
|
85022
|
-
import * as
|
|
85736
|
+
import * as fs72 from "node:fs";
|
|
85737
|
+
import * as path98 from "node:path";
|
|
85023
85738
|
|
|
85024
85739
|
// src/quality/metrics.ts
|
|
85025
|
-
import * as
|
|
85026
|
-
import * as
|
|
85740
|
+
import * as fs71 from "node:fs";
|
|
85741
|
+
import * as path97 from "node:path";
|
|
85027
85742
|
var MAX_FILE_SIZE_BYTES4 = 256 * 1024;
|
|
85028
85743
|
var MIN_DUPLICATION_LINES = 10;
|
|
85029
85744
|
function estimateCyclomaticComplexity(content) {
|
|
@@ -85061,11 +85776,11 @@ function estimateCyclomaticComplexity(content) {
|
|
|
85061
85776
|
}
|
|
85062
85777
|
function getComplexityForFile(filePath) {
|
|
85063
85778
|
try {
|
|
85064
|
-
const stat8 =
|
|
85779
|
+
const stat8 = fs71.statSync(filePath);
|
|
85065
85780
|
if (stat8.size > MAX_FILE_SIZE_BYTES4) {
|
|
85066
85781
|
return null;
|
|
85067
85782
|
}
|
|
85068
|
-
const content =
|
|
85783
|
+
const content = fs71.readFileSync(filePath, "utf-8");
|
|
85069
85784
|
return estimateCyclomaticComplexity(content);
|
|
85070
85785
|
} catch {
|
|
85071
85786
|
return null;
|
|
@@ -85075,8 +85790,8 @@ async function computeComplexityDelta(files, workingDir) {
|
|
|
85075
85790
|
let totalComplexity = 0;
|
|
85076
85791
|
const analyzedFiles = [];
|
|
85077
85792
|
for (const file3 of files) {
|
|
85078
|
-
const fullPath =
|
|
85079
|
-
if (!
|
|
85793
|
+
const fullPath = path97.isAbsolute(file3) ? file3 : path97.join(workingDir, file3);
|
|
85794
|
+
if (!fs71.existsSync(fullPath)) {
|
|
85080
85795
|
continue;
|
|
85081
85796
|
}
|
|
85082
85797
|
const complexity = getComplexityForFile(fullPath);
|
|
@@ -85197,8 +85912,8 @@ function countGoExports(content) {
|
|
|
85197
85912
|
}
|
|
85198
85913
|
function getExportCountForFile(filePath) {
|
|
85199
85914
|
try {
|
|
85200
|
-
const content =
|
|
85201
|
-
const ext =
|
|
85915
|
+
const content = fs71.readFileSync(filePath, "utf-8");
|
|
85916
|
+
const ext = path97.extname(filePath).toLowerCase();
|
|
85202
85917
|
switch (ext) {
|
|
85203
85918
|
case ".ts":
|
|
85204
85919
|
case ".tsx":
|
|
@@ -85224,8 +85939,8 @@ async function computePublicApiDelta(files, workingDir) {
|
|
|
85224
85939
|
let totalExports = 0;
|
|
85225
85940
|
const analyzedFiles = [];
|
|
85226
85941
|
for (const file3 of files) {
|
|
85227
|
-
const fullPath =
|
|
85228
|
-
if (!
|
|
85942
|
+
const fullPath = path97.isAbsolute(file3) ? file3 : path97.join(workingDir, file3);
|
|
85943
|
+
if (!fs71.existsSync(fullPath)) {
|
|
85229
85944
|
continue;
|
|
85230
85945
|
}
|
|
85231
85946
|
const exports = getExportCountForFile(fullPath);
|
|
@@ -85258,16 +85973,16 @@ async function computeDuplicationRatio(files, workingDir) {
|
|
|
85258
85973
|
let duplicateLines = 0;
|
|
85259
85974
|
const analyzedFiles = [];
|
|
85260
85975
|
for (const file3 of files) {
|
|
85261
|
-
const fullPath =
|
|
85262
|
-
if (!
|
|
85976
|
+
const fullPath = path97.isAbsolute(file3) ? file3 : path97.join(workingDir, file3);
|
|
85977
|
+
if (!fs71.existsSync(fullPath)) {
|
|
85263
85978
|
continue;
|
|
85264
85979
|
}
|
|
85265
85980
|
try {
|
|
85266
|
-
const stat8 =
|
|
85981
|
+
const stat8 = fs71.statSync(fullPath);
|
|
85267
85982
|
if (stat8.size > MAX_FILE_SIZE_BYTES4) {
|
|
85268
85983
|
continue;
|
|
85269
85984
|
}
|
|
85270
|
-
const content =
|
|
85985
|
+
const content = fs71.readFileSync(fullPath, "utf-8");
|
|
85271
85986
|
const lines = content.split(`
|
|
85272
85987
|
`).filter((line) => line.trim().length > 0);
|
|
85273
85988
|
if (lines.length < MIN_DUPLICATION_LINES) {
|
|
@@ -85291,8 +86006,8 @@ function countCodeLines(content) {
|
|
|
85291
86006
|
return lines.length;
|
|
85292
86007
|
}
|
|
85293
86008
|
function isTestFile(filePath) {
|
|
85294
|
-
const
|
|
85295
|
-
const _ext =
|
|
86009
|
+
const basename13 = path97.basename(filePath);
|
|
86010
|
+
const _ext = path97.extname(filePath).toLowerCase();
|
|
85296
86011
|
const testPatterns = [
|
|
85297
86012
|
".test.",
|
|
85298
86013
|
".spec.",
|
|
@@ -85307,7 +86022,7 @@ function isTestFile(filePath) {
|
|
|
85307
86022
|
".spec.jsx"
|
|
85308
86023
|
];
|
|
85309
86024
|
for (const pattern of testPatterns) {
|
|
85310
|
-
if (
|
|
86025
|
+
if (basename13.includes(pattern)) {
|
|
85311
86026
|
return true;
|
|
85312
86027
|
}
|
|
85313
86028
|
}
|
|
@@ -85373,8 +86088,8 @@ function matchGlobSegment(globSegments, pathSegments) {
|
|
|
85373
86088
|
}
|
|
85374
86089
|
return gIndex === globSegments.length && pIndex === pathSegments.length;
|
|
85375
86090
|
}
|
|
85376
|
-
function matchesGlobSegment(
|
|
85377
|
-
const normalizedPath =
|
|
86091
|
+
function matchesGlobSegment(path98, glob) {
|
|
86092
|
+
const normalizedPath = path98.replace(/\\/g, "/");
|
|
85378
86093
|
const normalizedGlob = glob.replace(/\\/g, "/");
|
|
85379
86094
|
if (normalizedPath.includes("//")) {
|
|
85380
86095
|
return false;
|
|
@@ -85405,8 +86120,8 @@ function simpleGlobToRegex2(glob) {
|
|
|
85405
86120
|
function hasGlobstar(glob) {
|
|
85406
86121
|
return glob.includes("**");
|
|
85407
86122
|
}
|
|
85408
|
-
function globMatches(
|
|
85409
|
-
const normalizedPath =
|
|
86123
|
+
function globMatches(path98, glob) {
|
|
86124
|
+
const normalizedPath = path98.replace(/\\/g, "/");
|
|
85410
86125
|
if (!glob || glob === "") {
|
|
85411
86126
|
if (normalizedPath.includes("//")) {
|
|
85412
86127
|
return false;
|
|
@@ -85442,31 +86157,31 @@ function shouldExcludeFile(filePath, excludeGlobs) {
|
|
|
85442
86157
|
async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
|
|
85443
86158
|
let testLines = 0;
|
|
85444
86159
|
let codeLines = 0;
|
|
85445
|
-
const srcDir =
|
|
85446
|
-
if (
|
|
86160
|
+
const srcDir = path97.join(workingDir, "src");
|
|
86161
|
+
if (fs71.existsSync(srcDir)) {
|
|
85447
86162
|
await scanDirectoryForLines(srcDir, enforceGlobs, excludeGlobs, false, (lines) => {
|
|
85448
86163
|
codeLines += lines;
|
|
85449
86164
|
});
|
|
85450
86165
|
}
|
|
85451
86166
|
const possibleSrcDirs = ["lib", "app", "source", "core"];
|
|
85452
86167
|
for (const dir of possibleSrcDirs) {
|
|
85453
|
-
const dirPath =
|
|
85454
|
-
if (
|
|
86168
|
+
const dirPath = path97.join(workingDir, dir);
|
|
86169
|
+
if (fs71.existsSync(dirPath)) {
|
|
85455
86170
|
await scanDirectoryForLines(dirPath, enforceGlobs, excludeGlobs, false, (lines) => {
|
|
85456
86171
|
codeLines += lines;
|
|
85457
86172
|
});
|
|
85458
86173
|
}
|
|
85459
86174
|
}
|
|
85460
|
-
const testsDir =
|
|
85461
|
-
if (
|
|
86175
|
+
const testsDir = path97.join(workingDir, "tests");
|
|
86176
|
+
if (fs71.existsSync(testsDir)) {
|
|
85462
86177
|
await scanDirectoryForLines(testsDir, ["**"], ["node_modules", "dist"], true, (lines) => {
|
|
85463
86178
|
testLines += lines;
|
|
85464
86179
|
});
|
|
85465
86180
|
}
|
|
85466
86181
|
const possibleTestDirs = ["test", "__tests__", "specs"];
|
|
85467
86182
|
for (const dir of possibleTestDirs) {
|
|
85468
|
-
const dirPath =
|
|
85469
|
-
if (
|
|
86183
|
+
const dirPath = path97.join(workingDir, dir);
|
|
86184
|
+
if (fs71.existsSync(dirPath) && dirPath !== testsDir) {
|
|
85470
86185
|
await scanDirectoryForLines(dirPath, ["**"], ["node_modules", "dist"], true, (lines) => {
|
|
85471
86186
|
testLines += lines;
|
|
85472
86187
|
});
|
|
@@ -85478,9 +86193,9 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
|
|
|
85478
86193
|
}
|
|
85479
86194
|
async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTestScan, callback) {
|
|
85480
86195
|
try {
|
|
85481
|
-
const entries =
|
|
86196
|
+
const entries = fs71.readdirSync(dirPath, { withFileTypes: true });
|
|
85482
86197
|
for (const entry of entries) {
|
|
85483
|
-
const fullPath =
|
|
86198
|
+
const fullPath = path97.join(dirPath, entry.name);
|
|
85484
86199
|
if (entry.isDirectory()) {
|
|
85485
86200
|
if (entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === ".git") {
|
|
85486
86201
|
continue;
|
|
@@ -85488,7 +86203,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
|
|
|
85488
86203
|
await scanDirectoryForLines(fullPath, includeGlobs, excludeGlobs, isTestScan, callback);
|
|
85489
86204
|
} else if (entry.isFile()) {
|
|
85490
86205
|
const relativePath = fullPath.replace(`${dirPath}/`, "");
|
|
85491
|
-
const ext =
|
|
86206
|
+
const ext = path97.extname(entry.name).toLowerCase();
|
|
85492
86207
|
const validExts = [
|
|
85493
86208
|
".ts",
|
|
85494
86209
|
".tsx",
|
|
@@ -85524,7 +86239,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
|
|
|
85524
86239
|
continue;
|
|
85525
86240
|
}
|
|
85526
86241
|
try {
|
|
85527
|
-
const content =
|
|
86242
|
+
const content = fs71.readFileSync(fullPath, "utf-8");
|
|
85528
86243
|
const lines = countCodeLines(content);
|
|
85529
86244
|
callback(lines);
|
|
85530
86245
|
} catch {}
|
|
@@ -85724,11 +86439,11 @@ async function getGitChurn(days, directory) {
|
|
|
85724
86439
|
}
|
|
85725
86440
|
function getComplexityForFile2(filePath) {
|
|
85726
86441
|
try {
|
|
85727
|
-
const stat8 =
|
|
86442
|
+
const stat8 = fs72.statSync(filePath);
|
|
85728
86443
|
if (stat8.size > MAX_FILE_SIZE_BYTES5) {
|
|
85729
86444
|
return null;
|
|
85730
86445
|
}
|
|
85731
|
-
const content =
|
|
86446
|
+
const content = fs72.readFileSync(filePath, "utf-8");
|
|
85732
86447
|
return estimateCyclomaticComplexity(content);
|
|
85733
86448
|
} catch {
|
|
85734
86449
|
return null;
|
|
@@ -85739,7 +86454,7 @@ async function analyzeHotspots(days, topN, extensions, directory) {
|
|
|
85739
86454
|
const extSet = new Set(extensions.map((e) => e.startsWith(".") ? e : `.${e}`));
|
|
85740
86455
|
const filteredChurn = new Map;
|
|
85741
86456
|
for (const [file3, count] of churnMap) {
|
|
85742
|
-
const ext =
|
|
86457
|
+
const ext = path98.extname(file3).toLowerCase();
|
|
85743
86458
|
if (extSet.has(ext)) {
|
|
85744
86459
|
filteredChurn.set(file3, count);
|
|
85745
86460
|
}
|
|
@@ -85749,8 +86464,8 @@ async function analyzeHotspots(days, topN, extensions, directory) {
|
|
|
85749
86464
|
let analyzedFiles = 0;
|
|
85750
86465
|
for (const [file3, churnCount] of filteredChurn) {
|
|
85751
86466
|
let fullPath = file3;
|
|
85752
|
-
if (!
|
|
85753
|
-
fullPath =
|
|
86467
|
+
if (!fs72.existsSync(fullPath)) {
|
|
86468
|
+
fullPath = path98.join(cwd, file3);
|
|
85754
86469
|
}
|
|
85755
86470
|
const complexity = getComplexityForFile2(fullPath);
|
|
85756
86471
|
if (complexity !== null) {
|
|
@@ -85918,13 +86633,13 @@ ${body2}`);
|
|
|
85918
86633
|
|
|
85919
86634
|
// src/council/council-evidence-writer.ts
|
|
85920
86635
|
import {
|
|
85921
|
-
appendFileSync as
|
|
85922
|
-
existsSync as
|
|
85923
|
-
mkdirSync as
|
|
85924
|
-
readFileSync as
|
|
85925
|
-
writeFileSync as
|
|
86636
|
+
appendFileSync as appendFileSync11,
|
|
86637
|
+
existsSync as existsSync53,
|
|
86638
|
+
mkdirSync as mkdirSync24,
|
|
86639
|
+
readFileSync as readFileSync43,
|
|
86640
|
+
writeFileSync as writeFileSync16
|
|
85926
86641
|
} from "node:fs";
|
|
85927
|
-
import { join as
|
|
86642
|
+
import { join as join83 } from "node:path";
|
|
85928
86643
|
var EVIDENCE_DIR2 = ".swarm/evidence";
|
|
85929
86644
|
var VALID_TASK_ID = /^\d+\.\d+(\.\d+)*$/;
|
|
85930
86645
|
var COUNCIL_GATE_NAME = "council";
|
|
@@ -85958,13 +86673,13 @@ function writeCouncilEvidence(workingDir, synthesis) {
|
|
|
85958
86673
|
if (!VALID_TASK_ID.test(synthesis.taskId)) {
|
|
85959
86674
|
throw new Error(`writeCouncilEvidence: invalid taskId "${synthesis.taskId}" — must match N.M or N.M.P format`);
|
|
85960
86675
|
}
|
|
85961
|
-
const dir =
|
|
85962
|
-
|
|
85963
|
-
const filePath =
|
|
86676
|
+
const dir = join83(workingDir, EVIDENCE_DIR2);
|
|
86677
|
+
mkdirSync24(dir, { recursive: true });
|
|
86678
|
+
const filePath = join83(dir, `${synthesis.taskId}.json`);
|
|
85964
86679
|
const existingRoot = Object.create(null);
|
|
85965
|
-
if (
|
|
86680
|
+
if (existsSync53(filePath)) {
|
|
85966
86681
|
try {
|
|
85967
|
-
const parsed = JSON.parse(
|
|
86682
|
+
const parsed = JSON.parse(readFileSync43(filePath, "utf-8"));
|
|
85968
86683
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
85969
86684
|
safeAssignOwnProps(existingRoot, parsed);
|
|
85970
86685
|
}
|
|
@@ -85992,17 +86707,17 @@ function writeCouncilEvidence(workingDir, synthesis) {
|
|
|
85992
86707
|
updated.taskId = synthesis.taskId;
|
|
85993
86708
|
if (!Array.isArray(updated.required_gates))
|
|
85994
86709
|
updated.required_gates = [];
|
|
85995
|
-
|
|
86710
|
+
writeFileSync16(filePath, JSON.stringify(updated, null, 2));
|
|
85996
86711
|
try {
|
|
85997
|
-
const councilDir =
|
|
85998
|
-
|
|
86712
|
+
const councilDir = join83(workingDir, ".swarm", "council");
|
|
86713
|
+
mkdirSync24(councilDir, { recursive: true });
|
|
85999
86714
|
const auditLine = JSON.stringify({
|
|
86000
86715
|
round: synthesis.roundNumber,
|
|
86001
86716
|
verdict: synthesis.overallVerdict,
|
|
86002
86717
|
timestamp: synthesis.timestamp,
|
|
86003
86718
|
vetoedBy: synthesis.vetoedBy
|
|
86004
86719
|
});
|
|
86005
|
-
|
|
86720
|
+
appendFileSync11(join83(councilDir, `${synthesis.taskId}.rounds.jsonl`), `${auditLine}
|
|
86006
86721
|
`);
|
|
86007
86722
|
} catch (auditError) {
|
|
86008
86723
|
console.warn(`writeCouncilEvidence: failed to append round-history audit log: ${auditError instanceof Error ? auditError.message : String(auditError)}`);
|
|
@@ -86324,25 +87039,25 @@ function buildFinalCouncilFeedback(projectSummary, verdict, vetoedBy, requiredFi
|
|
|
86324
87039
|
}
|
|
86325
87040
|
|
|
86326
87041
|
// src/council/criteria-store.ts
|
|
86327
|
-
import { existsSync as
|
|
86328
|
-
import { join as
|
|
87042
|
+
import { existsSync as existsSync54, mkdirSync as mkdirSync25, readFileSync as readFileSync44, writeFileSync as writeFileSync17 } from "node:fs";
|
|
87043
|
+
import { join as join84 } from "node:path";
|
|
86329
87044
|
var COUNCIL_DIR = ".swarm/council";
|
|
86330
87045
|
function writeCriteria(workingDir, taskId, criteria) {
|
|
86331
|
-
const dir =
|
|
86332
|
-
|
|
87046
|
+
const dir = join84(workingDir, COUNCIL_DIR);
|
|
87047
|
+
mkdirSync25(dir, { recursive: true });
|
|
86333
87048
|
const payload = {
|
|
86334
87049
|
taskId,
|
|
86335
87050
|
criteria,
|
|
86336
87051
|
declaredAt: new Date().toISOString()
|
|
86337
87052
|
};
|
|
86338
|
-
|
|
87053
|
+
writeFileSync17(join84(dir, `${safeId(taskId)}.json`), JSON.stringify(payload, null, 2));
|
|
86339
87054
|
}
|
|
86340
87055
|
function readCriteria(workingDir, taskId) {
|
|
86341
|
-
const filePath =
|
|
86342
|
-
if (!
|
|
87056
|
+
const filePath = join84(workingDir, COUNCIL_DIR, `${safeId(taskId)}.json`);
|
|
87057
|
+
if (!existsSync54(filePath))
|
|
86343
87058
|
return null;
|
|
86344
87059
|
try {
|
|
86345
|
-
const parsed = JSON.parse(
|
|
87060
|
+
const parsed = JSON.parse(readFileSync44(filePath, "utf-8"));
|
|
86346
87061
|
if (parsed && typeof parsed === "object" && typeof parsed.taskId === "string" && Array.isArray(parsed.criteria)) {
|
|
86347
87062
|
return parsed;
|
|
86348
87063
|
}
|
|
@@ -86490,8 +87205,8 @@ var submit_council_verdicts = createSwarmTool({
|
|
|
86490
87205
|
// src/tools/convene-general-council.ts
|
|
86491
87206
|
init_zod();
|
|
86492
87207
|
init_loader();
|
|
86493
|
-
import * as
|
|
86494
|
-
import * as
|
|
87208
|
+
import * as fs73 from "node:fs";
|
|
87209
|
+
import * as path99 from "node:path";
|
|
86495
87210
|
|
|
86496
87211
|
// src/council/general-council-advisory.ts
|
|
86497
87212
|
var ADVISORY_HEADER = "[general_council] (advisory; not blocking)";
|
|
@@ -86919,13 +87634,13 @@ var convene_general_council = createSwarmTool({
|
|
|
86919
87634
|
const round1 = input.round1Responses;
|
|
86920
87635
|
const round2 = input.round2Responses ?? [];
|
|
86921
87636
|
const result = synthesizeGeneralCouncil(input.question, input.mode, round1, round2);
|
|
86922
|
-
const evidenceDir =
|
|
87637
|
+
const evidenceDir = path99.join(workingDir, ".swarm", "council", "general");
|
|
86923
87638
|
const safeTimestamp = result.timestamp.replace(/[:.]/g, "-");
|
|
86924
87639
|
const evidenceFile = `${safeTimestamp}-${input.mode}.json`;
|
|
86925
|
-
const evidencePath =
|
|
87640
|
+
const evidencePath = path99.join(evidenceDir, evidenceFile);
|
|
86926
87641
|
try {
|
|
86927
|
-
await
|
|
86928
|
-
await
|
|
87642
|
+
await fs73.promises.mkdir(evidenceDir, { recursive: true });
|
|
87643
|
+
await fs73.promises.writeFile(evidencePath, JSON.stringify(result, null, 2));
|
|
86929
87644
|
} catch (err2) {
|
|
86930
87645
|
const message = err2 instanceof Error ? err2.message : String(err2);
|
|
86931
87646
|
console.warn(`[convene_general_council] Failed to write evidence to ${evidencePath}: ${message}`);
|
|
@@ -87166,8 +87881,8 @@ init_scope_persistence();
|
|
|
87166
87881
|
init_state();
|
|
87167
87882
|
init_task_id();
|
|
87168
87883
|
init_create_tool();
|
|
87169
|
-
import * as
|
|
87170
|
-
import * as
|
|
87884
|
+
import * as fs74 from "node:fs";
|
|
87885
|
+
import * as path100 from "node:path";
|
|
87171
87886
|
function validateTaskIdFormat2(taskId) {
|
|
87172
87887
|
return validateTaskIdFormat(taskId);
|
|
87173
87888
|
}
|
|
@@ -87241,8 +87956,8 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
87241
87956
|
};
|
|
87242
87957
|
}
|
|
87243
87958
|
}
|
|
87244
|
-
normalizedDir =
|
|
87245
|
-
const pathParts = normalizedDir.split(
|
|
87959
|
+
normalizedDir = path100.normalize(args2.working_directory);
|
|
87960
|
+
const pathParts = normalizedDir.split(path100.sep);
|
|
87246
87961
|
if (pathParts.includes("..")) {
|
|
87247
87962
|
return {
|
|
87248
87963
|
success: false,
|
|
@@ -87252,11 +87967,11 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
87252
87967
|
]
|
|
87253
87968
|
};
|
|
87254
87969
|
}
|
|
87255
|
-
const resolvedDir =
|
|
87970
|
+
const resolvedDir = path100.resolve(normalizedDir);
|
|
87256
87971
|
try {
|
|
87257
|
-
const realPath =
|
|
87258
|
-
const planPath2 =
|
|
87259
|
-
if (!
|
|
87972
|
+
const realPath = fs74.realpathSync(resolvedDir);
|
|
87973
|
+
const planPath2 = path100.join(realPath, ".swarm", "plan.json");
|
|
87974
|
+
if (!fs74.existsSync(planPath2)) {
|
|
87260
87975
|
return {
|
|
87261
87976
|
success: false,
|
|
87262
87977
|
message: `Invalid working_directory: plan not found in "${realPath}"`,
|
|
@@ -87279,8 +87994,8 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
87279
87994
|
console.warn("[declare-scope] fallbackDir is undefined, falling back to process.cwd()");
|
|
87280
87995
|
}
|
|
87281
87996
|
const directory = normalizedDir || fallbackDir;
|
|
87282
|
-
const planPath =
|
|
87283
|
-
if (!
|
|
87997
|
+
const planPath = path100.resolve(directory, ".swarm", "plan.json");
|
|
87998
|
+
if (!fs74.existsSync(planPath)) {
|
|
87284
87999
|
return {
|
|
87285
88000
|
success: false,
|
|
87286
88001
|
message: "No plan found",
|
|
@@ -87289,7 +88004,7 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
87289
88004
|
}
|
|
87290
88005
|
let planContent;
|
|
87291
88006
|
try {
|
|
87292
|
-
planContent = JSON.parse(
|
|
88007
|
+
planContent = JSON.parse(fs74.readFileSync(planPath, "utf-8"));
|
|
87293
88008
|
} catch {
|
|
87294
88009
|
return {
|
|
87295
88010
|
success: false,
|
|
@@ -87319,8 +88034,8 @@ async function executeDeclareScope(args2, fallbackDir) {
|
|
|
87319
88034
|
const normalizeErrors = [];
|
|
87320
88035
|
const dir = normalizedDir || fallbackDir || process.cwd();
|
|
87321
88036
|
const mergedFiles = rawMergedFiles.map((file3) => {
|
|
87322
|
-
if (
|
|
87323
|
-
const relativePath =
|
|
88037
|
+
if (path100.isAbsolute(file3)) {
|
|
88038
|
+
const relativePath = path100.relative(dir, file3).replace(/\\/g, "/");
|
|
87324
88039
|
if (relativePath.startsWith("..")) {
|
|
87325
88040
|
normalizeErrors.push(`Path '${file3}' resolves outside the project directory`);
|
|
87326
88041
|
return file3;
|
|
@@ -87380,8 +88095,8 @@ var declare_scope = createSwarmTool({
|
|
|
87380
88095
|
// src/tools/diff.ts
|
|
87381
88096
|
init_zod();
|
|
87382
88097
|
import * as child_process7 from "node:child_process";
|
|
87383
|
-
import * as
|
|
87384
|
-
import * as
|
|
88098
|
+
import * as fs75 from "node:fs";
|
|
88099
|
+
import * as path101 from "node:path";
|
|
87385
88100
|
init_create_tool();
|
|
87386
88101
|
var MAX_DIFF_LINES = 500;
|
|
87387
88102
|
var DIFF_TIMEOUT_MS = 30000;
|
|
@@ -87410,20 +88125,20 @@ function validateBase(base) {
|
|
|
87410
88125
|
function validatePaths(paths) {
|
|
87411
88126
|
if (!paths)
|
|
87412
88127
|
return null;
|
|
87413
|
-
for (const
|
|
87414
|
-
if (!
|
|
88128
|
+
for (const path102 of paths) {
|
|
88129
|
+
if (!path102 || path102.length === 0) {
|
|
87415
88130
|
return "empty path not allowed";
|
|
87416
88131
|
}
|
|
87417
|
-
if (
|
|
88132
|
+
if (path102.length > MAX_PATH_LENGTH) {
|
|
87418
88133
|
return `path exceeds maximum length of ${MAX_PATH_LENGTH}`;
|
|
87419
88134
|
}
|
|
87420
|
-
if (SHELL_METACHARACTERS2.test(
|
|
88135
|
+
if (SHELL_METACHARACTERS2.test(path102)) {
|
|
87421
88136
|
return "path contains shell metacharacters";
|
|
87422
88137
|
}
|
|
87423
|
-
if (
|
|
88138
|
+
if (path102.startsWith("-")) {
|
|
87424
88139
|
return 'path cannot start with "-" (option-like arguments not allowed)';
|
|
87425
88140
|
}
|
|
87426
|
-
if (CONTROL_CHAR_PATTERN2.test(
|
|
88141
|
+
if (CONTROL_CHAR_PATTERN2.test(path102)) {
|
|
87427
88142
|
return "path contains control characters";
|
|
87428
88143
|
}
|
|
87429
88144
|
}
|
|
@@ -87531,8 +88246,8 @@ var diff = createSwarmTool({
|
|
|
87531
88246
|
if (parts2.length >= 3) {
|
|
87532
88247
|
const additions = parseInt(parts2[0], 10) || 0;
|
|
87533
88248
|
const deletions = parseInt(parts2[1], 10) || 0;
|
|
87534
|
-
const
|
|
87535
|
-
files.push({ path:
|
|
88249
|
+
const path102 = parts2[2];
|
|
88250
|
+
files.push({ path: path102, additions, deletions });
|
|
87536
88251
|
}
|
|
87537
88252
|
}
|
|
87538
88253
|
const contractChanges = [];
|
|
@@ -87572,7 +88287,7 @@ var diff = createSwarmTool({
|
|
|
87572
88287
|
} else if (base === "unstaged") {
|
|
87573
88288
|
const oldRef = `:${file3.path}`;
|
|
87574
88289
|
oldContent = fileExistsInRef(oldRef) ? getContentFromRef(oldRef) : "";
|
|
87575
|
-
newContent =
|
|
88290
|
+
newContent = fs75.readFileSync(path101.join(directory, file3.path), "utf-8");
|
|
87576
88291
|
} else {
|
|
87577
88292
|
const oldRef = `${base}:${file3.path}`;
|
|
87578
88293
|
oldContent = fileExistsInRef(oldRef) ? getContentFromRef(oldRef) : "";
|
|
@@ -87646,8 +88361,8 @@ var diff = createSwarmTool({
|
|
|
87646
88361
|
// src/tools/diff-summary.ts
|
|
87647
88362
|
init_zod();
|
|
87648
88363
|
import * as child_process8 from "node:child_process";
|
|
87649
|
-
import * as
|
|
87650
|
-
import * as
|
|
88364
|
+
import * as fs76 from "node:fs";
|
|
88365
|
+
import * as path102 from "node:path";
|
|
87651
88366
|
init_create_tool();
|
|
87652
88367
|
var diff_summary = createSwarmTool({
|
|
87653
88368
|
description: "Generate a filtered semantic diff summary from AST analysis. Returns SemanticDiffSummary with optional filtering by classification or riskLevel.",
|
|
@@ -87695,7 +88410,7 @@ var diff_summary = createSwarmTool({
|
|
|
87695
88410
|
}
|
|
87696
88411
|
try {
|
|
87697
88412
|
let oldContent;
|
|
87698
|
-
const newContent =
|
|
88413
|
+
const newContent = fs76.readFileSync(path102.join(workingDir, filePath), "utf-8");
|
|
87699
88414
|
if (fileExistsInHead) {
|
|
87700
88415
|
oldContent = child_process8.execFileSync("git", ["show", `HEAD:${filePath}`], {
|
|
87701
88416
|
encoding: "utf-8",
|
|
@@ -87923,8 +88638,8 @@ Use these as DOMAIN values when delegating to @sme.`;
|
|
|
87923
88638
|
init_zod();
|
|
87924
88639
|
init_create_tool();
|
|
87925
88640
|
init_path_security();
|
|
87926
|
-
import * as
|
|
87927
|
-
import * as
|
|
88641
|
+
import * as fs77 from "node:fs";
|
|
88642
|
+
import * as path103 from "node:path";
|
|
87928
88643
|
var MAX_FILE_SIZE_BYTES6 = 1024 * 1024;
|
|
87929
88644
|
var MAX_EVIDENCE_FILES = 1000;
|
|
87930
88645
|
var EVIDENCE_DIR3 = ".swarm/evidence";
|
|
@@ -87951,9 +88666,9 @@ function validateRequiredTypes(input) {
|
|
|
87951
88666
|
return null;
|
|
87952
88667
|
}
|
|
87953
88668
|
function isPathWithinSwarm2(filePath, cwd) {
|
|
87954
|
-
const normalizedCwd =
|
|
87955
|
-
const swarmPath =
|
|
87956
|
-
const normalizedPath =
|
|
88669
|
+
const normalizedCwd = path103.resolve(cwd);
|
|
88670
|
+
const swarmPath = path103.join(normalizedCwd, ".swarm");
|
|
88671
|
+
const normalizedPath = path103.resolve(filePath);
|
|
87957
88672
|
return normalizedPath.startsWith(swarmPath);
|
|
87958
88673
|
}
|
|
87959
88674
|
function parseCompletedTasks(planContent) {
|
|
@@ -87969,12 +88684,12 @@ function parseCompletedTasks(planContent) {
|
|
|
87969
88684
|
}
|
|
87970
88685
|
function readEvidenceFiles(evidenceDir, _cwd) {
|
|
87971
88686
|
const evidence = [];
|
|
87972
|
-
if (!
|
|
88687
|
+
if (!fs77.existsSync(evidenceDir) || !fs77.statSync(evidenceDir).isDirectory()) {
|
|
87973
88688
|
return evidence;
|
|
87974
88689
|
}
|
|
87975
88690
|
let files;
|
|
87976
88691
|
try {
|
|
87977
|
-
files =
|
|
88692
|
+
files = fs77.readdirSync(evidenceDir);
|
|
87978
88693
|
} catch {
|
|
87979
88694
|
return evidence;
|
|
87980
88695
|
}
|
|
@@ -87983,14 +88698,14 @@ function readEvidenceFiles(evidenceDir, _cwd) {
|
|
|
87983
88698
|
if (!VALID_EVIDENCE_FILENAME_REGEX.test(filename)) {
|
|
87984
88699
|
continue;
|
|
87985
88700
|
}
|
|
87986
|
-
const filePath =
|
|
88701
|
+
const filePath = path103.join(evidenceDir, filename);
|
|
87987
88702
|
try {
|
|
87988
|
-
const resolvedPath =
|
|
87989
|
-
const evidenceDirResolved =
|
|
88703
|
+
const resolvedPath = path103.resolve(filePath);
|
|
88704
|
+
const evidenceDirResolved = path103.resolve(evidenceDir);
|
|
87990
88705
|
if (!resolvedPath.startsWith(evidenceDirResolved)) {
|
|
87991
88706
|
continue;
|
|
87992
88707
|
}
|
|
87993
|
-
const stat8 =
|
|
88708
|
+
const stat8 = fs77.lstatSync(filePath);
|
|
87994
88709
|
if (!stat8.isFile()) {
|
|
87995
88710
|
continue;
|
|
87996
88711
|
}
|
|
@@ -87999,7 +88714,7 @@ function readEvidenceFiles(evidenceDir, _cwd) {
|
|
|
87999
88714
|
}
|
|
88000
88715
|
let fileStat;
|
|
88001
88716
|
try {
|
|
88002
|
-
fileStat =
|
|
88717
|
+
fileStat = fs77.statSync(filePath);
|
|
88003
88718
|
if (fileStat.size > MAX_FILE_SIZE_BYTES6) {
|
|
88004
88719
|
continue;
|
|
88005
88720
|
}
|
|
@@ -88008,7 +88723,7 @@ function readEvidenceFiles(evidenceDir, _cwd) {
|
|
|
88008
88723
|
}
|
|
88009
88724
|
let content;
|
|
88010
88725
|
try {
|
|
88011
|
-
content =
|
|
88726
|
+
content = fs77.readFileSync(filePath, "utf-8");
|
|
88012
88727
|
} catch {
|
|
88013
88728
|
continue;
|
|
88014
88729
|
}
|
|
@@ -88104,7 +88819,7 @@ var evidence_check = createSwarmTool({
|
|
|
88104
88819
|
return JSON.stringify(errorResult, null, 2);
|
|
88105
88820
|
}
|
|
88106
88821
|
const requiredTypes = requiredTypesValue.split(",").map((t) => t.trim()).filter((t) => t.length > 0).map(normalizeEvidenceType);
|
|
88107
|
-
const planPath =
|
|
88822
|
+
const planPath = path103.join(cwd, PLAN_FILE);
|
|
88108
88823
|
if (!isPathWithinSwarm2(planPath, cwd)) {
|
|
88109
88824
|
const errorResult = {
|
|
88110
88825
|
error: "plan file path validation failed",
|
|
@@ -88118,7 +88833,7 @@ var evidence_check = createSwarmTool({
|
|
|
88118
88833
|
}
|
|
88119
88834
|
let planContent;
|
|
88120
88835
|
try {
|
|
88121
|
-
planContent =
|
|
88836
|
+
planContent = fs77.readFileSync(planPath, "utf-8");
|
|
88122
88837
|
} catch {
|
|
88123
88838
|
const result2 = {
|
|
88124
88839
|
message: "No completed tasks found in plan.",
|
|
@@ -88136,7 +88851,7 @@ var evidence_check = createSwarmTool({
|
|
|
88136
88851
|
};
|
|
88137
88852
|
return JSON.stringify(result2, null, 2);
|
|
88138
88853
|
}
|
|
88139
|
-
const evidenceDir =
|
|
88854
|
+
const evidenceDir = path103.join(cwd, EVIDENCE_DIR3);
|
|
88140
88855
|
const evidence = readEvidenceFiles(evidenceDir, cwd);
|
|
88141
88856
|
const { tasksWithFullEvidence, gaps } = analyzeGaps(completedTasks, evidence, requiredTypes);
|
|
88142
88857
|
const completeness = completedTasks.length > 0 ? Math.round(tasksWithFullEvidence.length / completedTasks.length * 100) / 100 : 1;
|
|
@@ -88153,8 +88868,8 @@ var evidence_check = createSwarmTool({
|
|
|
88153
88868
|
// src/tools/file-extractor.ts
|
|
88154
88869
|
init_zod();
|
|
88155
88870
|
init_create_tool();
|
|
88156
|
-
import * as
|
|
88157
|
-
import * as
|
|
88871
|
+
import * as fs78 from "node:fs";
|
|
88872
|
+
import * as path104 from "node:path";
|
|
88158
88873
|
var EXT_MAP = {
|
|
88159
88874
|
python: ".py",
|
|
88160
88875
|
py: ".py",
|
|
@@ -88216,8 +88931,8 @@ var extract_code_blocks = createSwarmTool({
|
|
|
88216
88931
|
execute: async (args2, directory) => {
|
|
88217
88932
|
const { content, output_dir, prefix } = args2;
|
|
88218
88933
|
const targetDir = output_dir || directory;
|
|
88219
|
-
if (!
|
|
88220
|
-
|
|
88934
|
+
if (!fs78.existsSync(targetDir)) {
|
|
88935
|
+
fs78.mkdirSync(targetDir, { recursive: true });
|
|
88221
88936
|
}
|
|
88222
88937
|
if (!content) {
|
|
88223
88938
|
return "Error: content is required";
|
|
@@ -88235,16 +88950,16 @@ var extract_code_blocks = createSwarmTool({
|
|
|
88235
88950
|
if (prefix) {
|
|
88236
88951
|
filename = `${prefix}_${filename}`;
|
|
88237
88952
|
}
|
|
88238
|
-
let filepath =
|
|
88239
|
-
const base =
|
|
88240
|
-
const ext =
|
|
88953
|
+
let filepath = path104.join(targetDir, filename);
|
|
88954
|
+
const base = path104.basename(filepath, path104.extname(filepath));
|
|
88955
|
+
const ext = path104.extname(filepath);
|
|
88241
88956
|
let counter = 1;
|
|
88242
|
-
while (
|
|
88243
|
-
filepath =
|
|
88957
|
+
while (fs78.existsSync(filepath)) {
|
|
88958
|
+
filepath = path104.join(targetDir, `${base}_${counter}${ext}`);
|
|
88244
88959
|
counter++;
|
|
88245
88960
|
}
|
|
88246
88961
|
try {
|
|
88247
|
-
|
|
88962
|
+
fs78.writeFileSync(filepath, code.trim(), "utf-8");
|
|
88248
88963
|
savedFiles.push(filepath);
|
|
88249
88964
|
} catch (error93) {
|
|
88250
88965
|
errors5.push(`Failed to save ${filename}: ${error93 instanceof Error ? error93.message : String(error93)}`);
|
|
@@ -88497,8 +89212,8 @@ var gitingest = createSwarmTool({
|
|
|
88497
89212
|
init_zod();
|
|
88498
89213
|
init_create_tool();
|
|
88499
89214
|
init_path_security();
|
|
88500
|
-
import * as
|
|
88501
|
-
import * as
|
|
89215
|
+
import * as fs79 from "node:fs";
|
|
89216
|
+
import * as path105 from "node:path";
|
|
88502
89217
|
var MAX_FILE_PATH_LENGTH2 = 500;
|
|
88503
89218
|
var MAX_SYMBOL_LENGTH = 256;
|
|
88504
89219
|
var MAX_FILE_SIZE_BYTES7 = 1024 * 1024;
|
|
@@ -88546,7 +89261,7 @@ function validateSymbolInput(symbol3) {
|
|
|
88546
89261
|
return null;
|
|
88547
89262
|
}
|
|
88548
89263
|
function isBinaryFile2(filePath, buffer) {
|
|
88549
|
-
const ext =
|
|
89264
|
+
const ext = path105.extname(filePath).toLowerCase();
|
|
88550
89265
|
if (ext === ".json" || ext === ".md" || ext === ".txt") {
|
|
88551
89266
|
return false;
|
|
88552
89267
|
}
|
|
@@ -88570,15 +89285,15 @@ function parseImports(content, targetFile, targetSymbol) {
|
|
|
88570
89285
|
const imports = [];
|
|
88571
89286
|
let _resolvedTarget;
|
|
88572
89287
|
try {
|
|
88573
|
-
_resolvedTarget =
|
|
89288
|
+
_resolvedTarget = path105.resolve(targetFile);
|
|
88574
89289
|
} catch {
|
|
88575
89290
|
_resolvedTarget = targetFile;
|
|
88576
89291
|
}
|
|
88577
|
-
const targetBasename =
|
|
89292
|
+
const targetBasename = path105.basename(targetFile, path105.extname(targetFile));
|
|
88578
89293
|
const targetWithExt = targetFile;
|
|
88579
89294
|
const targetWithoutExt = targetFile.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
|
|
88580
|
-
const normalizedTargetWithExt =
|
|
88581
|
-
const normalizedTargetWithoutExt =
|
|
89295
|
+
const normalizedTargetWithExt = path105.normalize(targetWithExt).replace(/\\/g, "/");
|
|
89296
|
+
const normalizedTargetWithoutExt = path105.normalize(targetWithoutExt).replace(/\\/g, "/");
|
|
88582
89297
|
const importRegex = /import\s+(?:\{[\s\S]*?\}|(?:\*\s+as\s+\w+)|\w+)\s+from\s+['"`]([^'"`]+)['"`]|import\s+['"`]([^'"`]+)['"`]|require\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g;
|
|
88583
89298
|
for (let match = importRegex.exec(content);match !== null; match = importRegex.exec(content)) {
|
|
88584
89299
|
const modulePath = match[1] || match[2] || match[3];
|
|
@@ -88601,9 +89316,9 @@ function parseImports(content, targetFile, targetSymbol) {
|
|
|
88601
89316
|
}
|
|
88602
89317
|
const _normalizedModule = modulePath.replace(/^\.\//, "").replace(/^\.\.\\/, "../");
|
|
88603
89318
|
let isMatch = false;
|
|
88604
|
-
const _targetDir =
|
|
88605
|
-
const targetExt =
|
|
88606
|
-
const targetBasenameNoExt =
|
|
89319
|
+
const _targetDir = path105.dirname(targetFile);
|
|
89320
|
+
const targetExt = path105.extname(targetFile);
|
|
89321
|
+
const targetBasenameNoExt = path105.basename(targetFile, targetExt);
|
|
88607
89322
|
const moduleNormalized = modulePath.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
88608
89323
|
const moduleName = modulePath.split(/[/\\]/).pop() || "";
|
|
88609
89324
|
const moduleNameNoExt = moduleName.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
|
|
@@ -88660,7 +89375,7 @@ var SKIP_DIRECTORIES4 = new Set([
|
|
|
88660
89375
|
function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFiles: 0, fileErrors: [] }) {
|
|
88661
89376
|
let entries;
|
|
88662
89377
|
try {
|
|
88663
|
-
entries =
|
|
89378
|
+
entries = fs79.readdirSync(dir);
|
|
88664
89379
|
} catch (e) {
|
|
88665
89380
|
stats.fileErrors.push({
|
|
88666
89381
|
path: dir,
|
|
@@ -88671,13 +89386,13 @@ function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFil
|
|
|
88671
89386
|
entries.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
|
|
88672
89387
|
for (const entry of entries) {
|
|
88673
89388
|
if (SKIP_DIRECTORIES4.has(entry)) {
|
|
88674
|
-
stats.skippedDirs.push(
|
|
89389
|
+
stats.skippedDirs.push(path105.join(dir, entry));
|
|
88675
89390
|
continue;
|
|
88676
89391
|
}
|
|
88677
|
-
const fullPath =
|
|
89392
|
+
const fullPath = path105.join(dir, entry);
|
|
88678
89393
|
let stat8;
|
|
88679
89394
|
try {
|
|
88680
|
-
stat8 =
|
|
89395
|
+
stat8 = fs79.statSync(fullPath);
|
|
88681
89396
|
} catch (e) {
|
|
88682
89397
|
stats.fileErrors.push({
|
|
88683
89398
|
path: fullPath,
|
|
@@ -88688,7 +89403,7 @@ function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFil
|
|
|
88688
89403
|
if (stat8.isDirectory()) {
|
|
88689
89404
|
findSourceFiles2(fullPath, files, stats);
|
|
88690
89405
|
} else if (stat8.isFile()) {
|
|
88691
|
-
const ext =
|
|
89406
|
+
const ext = path105.extname(fullPath).toLowerCase();
|
|
88692
89407
|
if (SUPPORTED_EXTENSIONS3.includes(ext)) {
|
|
88693
89408
|
files.push(fullPath);
|
|
88694
89409
|
}
|
|
@@ -88745,8 +89460,8 @@ var imports = createSwarmTool({
|
|
|
88745
89460
|
return JSON.stringify(errorResult, null, 2);
|
|
88746
89461
|
}
|
|
88747
89462
|
try {
|
|
88748
|
-
const targetFile =
|
|
88749
|
-
if (!
|
|
89463
|
+
const targetFile = path105.resolve(file3);
|
|
89464
|
+
if (!fs79.existsSync(targetFile)) {
|
|
88750
89465
|
const errorResult = {
|
|
88751
89466
|
error: `target file not found: ${file3}`,
|
|
88752
89467
|
target: file3,
|
|
@@ -88756,7 +89471,7 @@ var imports = createSwarmTool({
|
|
|
88756
89471
|
};
|
|
88757
89472
|
return JSON.stringify(errorResult, null, 2);
|
|
88758
89473
|
}
|
|
88759
|
-
const targetStat =
|
|
89474
|
+
const targetStat = fs79.statSync(targetFile);
|
|
88760
89475
|
if (!targetStat.isFile()) {
|
|
88761
89476
|
const errorResult = {
|
|
88762
89477
|
error: "target must be a file, not a directory",
|
|
@@ -88767,7 +89482,7 @@ var imports = createSwarmTool({
|
|
|
88767
89482
|
};
|
|
88768
89483
|
return JSON.stringify(errorResult, null, 2);
|
|
88769
89484
|
}
|
|
88770
|
-
const baseDir =
|
|
89485
|
+
const baseDir = path105.dirname(targetFile);
|
|
88771
89486
|
const scanStats = {
|
|
88772
89487
|
skippedDirs: [],
|
|
88773
89488
|
skippedFiles: 0,
|
|
@@ -88782,12 +89497,12 @@ var imports = createSwarmTool({
|
|
|
88782
89497
|
if (consumers.length >= MAX_CONSUMERS)
|
|
88783
89498
|
break;
|
|
88784
89499
|
try {
|
|
88785
|
-
const stat8 =
|
|
89500
|
+
const stat8 = fs79.statSync(filePath);
|
|
88786
89501
|
if (stat8.size > MAX_FILE_SIZE_BYTES7) {
|
|
88787
89502
|
skippedFileCount++;
|
|
88788
89503
|
continue;
|
|
88789
89504
|
}
|
|
88790
|
-
const buffer =
|
|
89505
|
+
const buffer = fs79.readFileSync(filePath);
|
|
88791
89506
|
if (isBinaryFile2(filePath, buffer)) {
|
|
88792
89507
|
skippedFileCount++;
|
|
88793
89508
|
continue;
|
|
@@ -88852,7 +89567,7 @@ var imports = createSwarmTool({
|
|
|
88852
89567
|
});
|
|
88853
89568
|
// src/tools/knowledge-ack.ts
|
|
88854
89569
|
init_zod();
|
|
88855
|
-
import { randomUUID as
|
|
89570
|
+
import { randomUUID as randomUUID8 } from "node:crypto";
|
|
88856
89571
|
init_state();
|
|
88857
89572
|
init_logger();
|
|
88858
89573
|
init_create_tool();
|
|
@@ -88885,7 +89600,7 @@ var knowledge_ack = createSwarmTool({
|
|
|
88885
89600
|
let sessionId = ctx?.sessionID;
|
|
88886
89601
|
if (!sessionId) {
|
|
88887
89602
|
warn("[knowledge-ack] No sessionID in tool context — dedup disabled for this acknowledgment");
|
|
88888
|
-
sessionId =
|
|
89603
|
+
sessionId = randomUUID8();
|
|
88889
89604
|
}
|
|
88890
89605
|
const dedupKey = buildAckDedupKey(sessionId, a.id, a.result);
|
|
88891
89606
|
if (swarmState.knowledgeAckDedup.has(dedupKey)) {
|
|
@@ -88915,7 +89630,7 @@ init_knowledge_store();
|
|
|
88915
89630
|
init_knowledge_validator();
|
|
88916
89631
|
init_manager();
|
|
88917
89632
|
init_create_tool();
|
|
88918
|
-
import { randomUUID as
|
|
89633
|
+
import { randomUUID as randomUUID9 } from "node:crypto";
|
|
88919
89634
|
var VALID_CATEGORIES2 = [
|
|
88920
89635
|
"process",
|
|
88921
89636
|
"architecture",
|
|
@@ -88989,7 +89704,7 @@ var knowledge_add = createSwarmTool({
|
|
|
88989
89704
|
project_name = plan?.title ?? "";
|
|
88990
89705
|
} catch {}
|
|
88991
89706
|
const entry = {
|
|
88992
|
-
id:
|
|
89707
|
+
id: randomUUID9(),
|
|
88993
89708
|
tier: "swarm",
|
|
88994
89709
|
lesson,
|
|
88995
89710
|
category,
|
|
@@ -89058,7 +89773,7 @@ init_zod();
|
|
|
89058
89773
|
init_config();
|
|
89059
89774
|
init_knowledge_store();
|
|
89060
89775
|
init_create_tool();
|
|
89061
|
-
import { existsSync as
|
|
89776
|
+
import { existsSync as existsSync59 } from "node:fs";
|
|
89062
89777
|
var DEFAULT_LIMIT = 10;
|
|
89063
89778
|
var MAX_LESSON_LENGTH = 200;
|
|
89064
89779
|
var VALID_CATEGORIES3 = [
|
|
@@ -89128,14 +89843,14 @@ function validateLimit(limit) {
|
|
|
89128
89843
|
}
|
|
89129
89844
|
async function readSwarmKnowledge(directory) {
|
|
89130
89845
|
const swarmPath = resolveSwarmKnowledgePath(directory);
|
|
89131
|
-
if (!
|
|
89846
|
+
if (!existsSync59(swarmPath)) {
|
|
89132
89847
|
return [];
|
|
89133
89848
|
}
|
|
89134
89849
|
return readKnowledge(swarmPath);
|
|
89135
89850
|
}
|
|
89136
89851
|
async function readHiveKnowledge() {
|
|
89137
89852
|
const hivePath = resolveHiveKnowledgePath();
|
|
89138
|
-
if (!
|
|
89853
|
+
if (!existsSync59(hivePath)) {
|
|
89139
89854
|
return [];
|
|
89140
89855
|
}
|
|
89141
89856
|
return readKnowledge(hivePath);
|
|
@@ -89369,30 +90084,30 @@ init_config();
|
|
|
89369
90084
|
init_schema();
|
|
89370
90085
|
init_qa_gate_profile();
|
|
89371
90086
|
init_manager2();
|
|
89372
|
-
import * as
|
|
89373
|
-
import * as
|
|
90087
|
+
import * as fs84 from "node:fs";
|
|
90088
|
+
import * as path110 from "node:path";
|
|
89374
90089
|
|
|
89375
90090
|
// src/full-auto/phase-approval.ts
|
|
89376
90091
|
init_utils2();
|
|
89377
90092
|
init_logger();
|
|
89378
90093
|
init_state2();
|
|
89379
|
-
import * as
|
|
89380
|
-
import * as
|
|
90094
|
+
import * as fs80 from "node:fs";
|
|
90095
|
+
import * as path106 from "node:path";
|
|
89381
90096
|
var APPROVAL_TTL_MS = 24 * 60 * 60 * 1000;
|
|
89382
90097
|
function readEvidenceDir(directory, phase) {
|
|
89383
90098
|
try {
|
|
89384
|
-
const dirPath = validateSwarmPath(directory,
|
|
89385
|
-
if (!
|
|
90099
|
+
const dirPath = validateSwarmPath(directory, path106.posix.join("evidence", String(phase)));
|
|
90100
|
+
if (!fs80.existsSync(dirPath))
|
|
89386
90101
|
return [];
|
|
89387
|
-
const entries =
|
|
89388
|
-
return entries.filter((e) => e.startsWith("full-auto-") && e.endsWith(".json")).map((e) =>
|
|
90102
|
+
const entries = fs80.readdirSync(dirPath);
|
|
90103
|
+
return entries.filter((e) => e.startsWith("full-auto-") && e.endsWith(".json")).map((e) => path106.join(dirPath, e));
|
|
89389
90104
|
} catch {
|
|
89390
90105
|
return [];
|
|
89391
90106
|
}
|
|
89392
90107
|
}
|
|
89393
90108
|
function parseEvidence(filePath) {
|
|
89394
90109
|
try {
|
|
89395
|
-
const raw =
|
|
90110
|
+
const raw = fs80.readFileSync(filePath, "utf-8");
|
|
89396
90111
|
const parsed = JSON.parse(raw);
|
|
89397
90112
|
return parsed;
|
|
89398
90113
|
} catch (error93) {
|
|
@@ -89481,9 +90196,9 @@ function verifyFullAutoPhaseApproval(directory, sessionID, phase, config3) {
|
|
|
89481
90196
|
function phaseIsExplicitlyNonCode(directory, phase) {
|
|
89482
90197
|
try {
|
|
89483
90198
|
const planPath = validateSwarmPath(directory, "plan.json");
|
|
89484
|
-
if (!
|
|
90199
|
+
if (!fs80.existsSync(planPath))
|
|
89485
90200
|
return false;
|
|
89486
|
-
const raw =
|
|
90201
|
+
const raw = fs80.readFileSync(planPath, "utf-8");
|
|
89487
90202
|
const plan = JSON.parse(raw);
|
|
89488
90203
|
const phases = Array.isArray(plan.phases) ? plan.phases : [];
|
|
89489
90204
|
const entry = phases.find((p) => p.id === phase || p.phase === phase);
|
|
@@ -89523,20 +90238,20 @@ init_file_locks();
|
|
|
89523
90238
|
init_plan_schema();
|
|
89524
90239
|
init_ledger();
|
|
89525
90240
|
init_manager();
|
|
89526
|
-
import * as
|
|
89527
|
-
import * as
|
|
90241
|
+
import * as fs81 from "node:fs";
|
|
90242
|
+
import * as path107 from "node:path";
|
|
89528
90243
|
async function writeCheckpoint(directory) {
|
|
89529
90244
|
try {
|
|
89530
90245
|
const plan = await loadPlan(directory);
|
|
89531
90246
|
if (!plan)
|
|
89532
90247
|
return;
|
|
89533
|
-
const swarmDir =
|
|
89534
|
-
|
|
89535
|
-
const jsonPath =
|
|
89536
|
-
const mdPath =
|
|
89537
|
-
|
|
90248
|
+
const swarmDir = path107.join(directory, ".swarm");
|
|
90249
|
+
fs81.mkdirSync(swarmDir, { recursive: true });
|
|
90250
|
+
const jsonPath = path107.join(swarmDir, "SWARM_PLAN.json");
|
|
90251
|
+
const mdPath = path107.join(swarmDir, "SWARM_PLAN.md");
|
|
90252
|
+
fs81.writeFileSync(jsonPath, JSON.stringify(plan, null, 2), "utf8");
|
|
89538
90253
|
const md = derivePlanMarkdown(plan);
|
|
89539
|
-
|
|
90254
|
+
fs81.writeFileSync(mdPath, md, "utf8");
|
|
89540
90255
|
} catch (error93) {
|
|
89541
90256
|
console.warn(`[checkpoint] Failed to write SWARM_PLAN checkpoint: ${error93 instanceof Error ? error93.message : String(error93)}`);
|
|
89542
90257
|
}
|
|
@@ -89551,16 +90266,16 @@ init_telemetry();
|
|
|
89551
90266
|
|
|
89552
90267
|
// src/turbo/lean/phase-ready.ts
|
|
89553
90268
|
init_file_locks();
|
|
89554
|
-
import * as
|
|
89555
|
-
import * as
|
|
90269
|
+
import * as fs83 from "node:fs";
|
|
90270
|
+
import * as path109 from "node:path";
|
|
89556
90271
|
|
|
89557
90272
|
// src/turbo/lean/evidence.ts
|
|
89558
90273
|
init_bun_compat();
|
|
89559
90274
|
import { rmSync as rmSync5 } from "node:fs";
|
|
89560
|
-
import * as
|
|
89561
|
-
import * as
|
|
90275
|
+
import * as fs82 from "node:fs/promises";
|
|
90276
|
+
import * as path108 from "node:path";
|
|
89562
90277
|
function leanTurboEvidenceDir(directory, phase) {
|
|
89563
|
-
return
|
|
90278
|
+
return path108.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
|
|
89564
90279
|
}
|
|
89565
90280
|
function validateLaneId(laneId) {
|
|
89566
90281
|
if (laneId.length === 0) {
|
|
@@ -89582,21 +90297,21 @@ function validateLaneId(laneId) {
|
|
|
89582
90297
|
function laneEvidencePath(directory, phase, laneId) {
|
|
89583
90298
|
validateLaneId(laneId);
|
|
89584
90299
|
const expectedDir = leanTurboEvidenceDir(directory, phase);
|
|
89585
|
-
const resolvedPath =
|
|
89586
|
-
const resolvedDir =
|
|
89587
|
-
if (!resolvedPath.startsWith(resolvedDir +
|
|
90300
|
+
const resolvedPath = path108.resolve(path108.join(expectedDir, `${laneId}.json`));
|
|
90301
|
+
const resolvedDir = path108.resolve(expectedDir);
|
|
90302
|
+
if (!resolvedPath.startsWith(resolvedDir + path108.sep) && resolvedPath !== resolvedDir) {
|
|
89588
90303
|
throw new Error(`Invalid laneId: path traversal detected (got "${laneId}")`);
|
|
89589
90304
|
}
|
|
89590
90305
|
return resolvedPath;
|
|
89591
90306
|
}
|
|
89592
90307
|
async function atomicWriteJson(filePath, data) {
|
|
89593
90308
|
const content = JSON.stringify(data, null, 2);
|
|
89594
|
-
const dir =
|
|
89595
|
-
await
|
|
90309
|
+
const dir = path108.dirname(filePath);
|
|
90310
|
+
await fs82.mkdir(dir, { recursive: true });
|
|
89596
90311
|
const tempPath = `${filePath}.tmp.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2)}`;
|
|
89597
90312
|
try {
|
|
89598
90313
|
await bunWrite(tempPath, content);
|
|
89599
|
-
await
|
|
90314
|
+
await fs82.rename(tempPath, filePath);
|
|
89600
90315
|
} catch (error93) {
|
|
89601
90316
|
try {
|
|
89602
90317
|
rmSync5(tempPath, { force: true });
|
|
@@ -89605,7 +90320,7 @@ async function atomicWriteJson(filePath, data) {
|
|
|
89605
90320
|
}
|
|
89606
90321
|
}
|
|
89607
90322
|
function phaseEvidencePath(directory, phase) {
|
|
89608
|
-
return
|
|
90323
|
+
return path108.join(leanTurboEvidenceDir(directory, phase), "lean-turbo-phase.json");
|
|
89609
90324
|
}
|
|
89610
90325
|
async function writeLaneEvidence(directory, phase, evidence) {
|
|
89611
90326
|
const targetPath = laneEvidencePath(directory, phase, evidence.laneId);
|
|
@@ -89615,7 +90330,7 @@ async function readPhaseEvidence(directory, phase) {
|
|
|
89615
90330
|
const targetPath = phaseEvidencePath(directory, phase);
|
|
89616
90331
|
let content;
|
|
89617
90332
|
try {
|
|
89618
|
-
content = await
|
|
90333
|
+
content = await fs82.readFile(targetPath, "utf-8");
|
|
89619
90334
|
} catch (error93) {
|
|
89620
90335
|
const code = error93.code;
|
|
89621
90336
|
if (code === "ENOENT" || code === "ENOTDIR") {
|
|
@@ -89633,7 +90348,7 @@ async function listLaneEvidence(directory, phase) {
|
|
|
89633
90348
|
const evidenceDir = leanTurboEvidenceDir(directory, phase);
|
|
89634
90349
|
let entries;
|
|
89635
90350
|
try {
|
|
89636
|
-
entries = await
|
|
90351
|
+
entries = await fs82.readdir(evidenceDir);
|
|
89637
90352
|
} catch (error93) {
|
|
89638
90353
|
const code = error93.code;
|
|
89639
90354
|
if (code === "ENOENT" || code === "ENOTDIR") {
|
|
@@ -89649,10 +90364,10 @@ async function listLaneEvidence(directory, phase) {
|
|
|
89649
90364
|
if (entry === "lean-turbo-phase.json") {
|
|
89650
90365
|
continue;
|
|
89651
90366
|
}
|
|
89652
|
-
const filePath =
|
|
90367
|
+
const filePath = path108.join(evidenceDir, entry);
|
|
89653
90368
|
let content;
|
|
89654
90369
|
try {
|
|
89655
|
-
content = await
|
|
90370
|
+
content = await fs82.readFile(filePath, "utf-8");
|
|
89656
90371
|
} catch {
|
|
89657
90372
|
continue;
|
|
89658
90373
|
}
|
|
@@ -89673,10 +90388,10 @@ var DEFAULT_CONFIG2 = {
|
|
|
89673
90388
|
};
|
|
89674
90389
|
function defaultReadPlanJson(dir) {
|
|
89675
90390
|
try {
|
|
89676
|
-
const planPath =
|
|
89677
|
-
if (!
|
|
90391
|
+
const planPath = path109.join(dir, ".swarm", "plan.json");
|
|
90392
|
+
if (!fs83.existsSync(planPath))
|
|
89678
90393
|
return null;
|
|
89679
|
-
const raw =
|
|
90394
|
+
const raw = fs83.readFileSync(planPath, "utf-8");
|
|
89680
90395
|
const plan = JSON.parse(raw);
|
|
89681
90396
|
if (typeof plan !== "object" || plan === null || !Array.isArray(plan.phases)) {
|
|
89682
90397
|
return null;
|
|
@@ -89688,11 +90403,11 @@ function defaultReadPlanJson(dir) {
|
|
|
89688
90403
|
}
|
|
89689
90404
|
function readReviewerEvidenceFromFile(directory, phase) {
|
|
89690
90405
|
try {
|
|
89691
|
-
const evidencePath =
|
|
89692
|
-
if (!
|
|
90406
|
+
const evidencePath = path109.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-reviewer.json");
|
|
90407
|
+
if (!fs83.existsSync(evidencePath)) {
|
|
89693
90408
|
return null;
|
|
89694
90409
|
}
|
|
89695
|
-
const raw =
|
|
90410
|
+
const raw = fs83.readFileSync(evidencePath, "utf-8");
|
|
89696
90411
|
const parsed = JSON.parse(raw);
|
|
89697
90412
|
if (typeof parsed !== "object" || parsed === null || typeof parsed.verdict !== "string") {
|
|
89698
90413
|
return null;
|
|
@@ -89708,11 +90423,11 @@ function readReviewerEvidenceFromFile(directory, phase) {
|
|
|
89708
90423
|
}
|
|
89709
90424
|
function readCriticEvidenceFromFile(directory, phase) {
|
|
89710
90425
|
try {
|
|
89711
|
-
const evidencePath =
|
|
89712
|
-
if (!
|
|
90426
|
+
const evidencePath = path109.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-critic.json");
|
|
90427
|
+
if (!fs83.existsSync(evidencePath)) {
|
|
89713
90428
|
return null;
|
|
89714
90429
|
}
|
|
89715
|
-
const raw =
|
|
90430
|
+
const raw = fs83.readFileSync(evidencePath, "utf-8");
|
|
89716
90431
|
const parsed = JSON.parse(raw);
|
|
89717
90432
|
if (typeof parsed !== "object" || parsed === null || typeof parsed.verdict !== "string") {
|
|
89718
90433
|
return null;
|
|
@@ -89727,10 +90442,10 @@ function readCriticEvidenceFromFile(directory, phase) {
|
|
|
89727
90442
|
}
|
|
89728
90443
|
}
|
|
89729
90444
|
function listLaneEvidenceSync(directory, phase) {
|
|
89730
|
-
const evidenceDir =
|
|
90445
|
+
const evidenceDir = path109.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
|
|
89731
90446
|
let entries;
|
|
89732
90447
|
try {
|
|
89733
|
-
entries =
|
|
90448
|
+
entries = fs83.readdirSync(evidenceDir);
|
|
89734
90449
|
} catch {
|
|
89735
90450
|
return [];
|
|
89736
90451
|
}
|
|
@@ -89743,7 +90458,7 @@ function listLaneEvidenceSync(directory, phase) {
|
|
|
89743
90458
|
}
|
|
89744
90459
|
return laneIds;
|
|
89745
90460
|
}
|
|
89746
|
-
var
|
|
90461
|
+
var _internals43 = {
|
|
89747
90462
|
listActiveLocks,
|
|
89748
90463
|
readPersisted: readPersisted2,
|
|
89749
90464
|
readPlanJson: defaultReadPlanJson,
|
|
@@ -89797,14 +90512,14 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
|
|
|
89797
90512
|
...DEFAULT_CONFIG2,
|
|
89798
90513
|
...actualConfig
|
|
89799
90514
|
};
|
|
89800
|
-
const statePath =
|
|
89801
|
-
if (!
|
|
90515
|
+
const statePath = path109.join(directory, ".swarm", "turbo-state.json");
|
|
90516
|
+
if (!fs83.existsSync(statePath)) {
|
|
89802
90517
|
return {
|
|
89803
90518
|
ok: false,
|
|
89804
90519
|
reason: "Lean Turbo state unreadable or missing"
|
|
89805
90520
|
};
|
|
89806
90521
|
}
|
|
89807
|
-
const persisted =
|
|
90522
|
+
const persisted = _internals43.readPersisted(directory);
|
|
89808
90523
|
if (!persisted) {
|
|
89809
90524
|
return {
|
|
89810
90525
|
ok: false,
|
|
@@ -89868,7 +90583,7 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
|
|
|
89868
90583
|
}
|
|
89869
90584
|
}
|
|
89870
90585
|
if (runState.lanes.length > 0) {
|
|
89871
|
-
const evidenceLaneIds = new Set(
|
|
90586
|
+
const evidenceLaneIds = new Set(_internals43.listLaneEvidenceSync(directory, phase));
|
|
89872
90587
|
for (const lane of runState.lanes) {
|
|
89873
90588
|
if ((lane.status === "completed" || lane.status === "failed") && !evidenceLaneIds.has(lane.laneId)) {
|
|
89874
90589
|
return {
|
|
@@ -89878,7 +90593,7 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
|
|
|
89878
90593
|
}
|
|
89879
90594
|
}
|
|
89880
90595
|
}
|
|
89881
|
-
const activeLocks =
|
|
90596
|
+
const activeLocks = _internals43.listActiveLocks(directory);
|
|
89882
90597
|
const phaseLaneIds = new Set(laneIds);
|
|
89883
90598
|
for (const lock of activeLocks) {
|
|
89884
90599
|
if (lock.laneId && phaseLaneIds.has(lock.laneId)) {
|
|
@@ -89898,7 +90613,7 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
|
|
|
89898
90613
|
}
|
|
89899
90614
|
const serialDegradedTasks = runState.degradedTasks.filter((dt) => !laneTaskIds.has(dt.taskId));
|
|
89900
90615
|
if (serialDegradedTasks.length > 0) {
|
|
89901
|
-
const plan =
|
|
90616
|
+
const plan = _internals43.readPlanJson(directory);
|
|
89902
90617
|
if (!plan) {
|
|
89903
90618
|
return {
|
|
89904
90619
|
ok: false,
|
|
@@ -89942,7 +90657,7 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
|
|
|
89942
90657
|
}
|
|
89943
90658
|
const serializedTasks = runState.serializedTasks;
|
|
89944
90659
|
if (Array.isArray(serializedTasks) && serializedTasks.length > 0) {
|
|
89945
|
-
const plan =
|
|
90660
|
+
const plan = _internals43.readPlanJson(directory);
|
|
89946
90661
|
if (!plan) {
|
|
89947
90662
|
return {
|
|
89948
90663
|
ok: false,
|
|
@@ -89985,10 +90700,10 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
|
|
|
89985
90700
|
}
|
|
89986
90701
|
}
|
|
89987
90702
|
if (mergedConfig.integrated_diff_required) {
|
|
89988
|
-
const evidencePath =
|
|
90703
|
+
const evidencePath = path109.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-phase.json");
|
|
89989
90704
|
let hasDiff = false;
|
|
89990
90705
|
try {
|
|
89991
|
-
const content =
|
|
90706
|
+
const content = fs83.readFileSync(evidencePath, "utf-8");
|
|
89992
90707
|
const evidence = JSON.parse(content);
|
|
89993
90708
|
hasDiff = !!evidence.integratedDiffSummary;
|
|
89994
90709
|
} catch {}
|
|
@@ -90001,7 +90716,7 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
|
|
|
90001
90716
|
}
|
|
90002
90717
|
let reviewerVerdict = runState.lastReviewerVerdict;
|
|
90003
90718
|
if (!reviewerVerdict) {
|
|
90004
|
-
const evidence =
|
|
90719
|
+
const evidence = _internals43.readReviewerEvidence(directory, phase);
|
|
90005
90720
|
reviewerVerdict = evidence?.verdict ?? undefined;
|
|
90006
90721
|
}
|
|
90007
90722
|
if (mergedConfig.phase_reviewer) {
|
|
@@ -90014,7 +90729,7 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
|
|
|
90014
90729
|
}
|
|
90015
90730
|
let criticVerdict = runState.lastCriticVerdict;
|
|
90016
90731
|
if (!criticVerdict) {
|
|
90017
|
-
const evidence =
|
|
90732
|
+
const evidence = _internals43.readCriticEvidence(directory, phase);
|
|
90018
90733
|
criticVerdict = evidence?.verdict ?? undefined;
|
|
90019
90734
|
}
|
|
90020
90735
|
if (mergedConfig.phase_critic) {
|
|
@@ -90259,8 +90974,8 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
90259
90974
|
let driftCheckEnabled = true;
|
|
90260
90975
|
let driftHasSpecMd = false;
|
|
90261
90976
|
try {
|
|
90262
|
-
const specMdPath =
|
|
90263
|
-
driftHasSpecMd =
|
|
90977
|
+
const specMdPath = path110.join(dir, ".swarm", "spec.md");
|
|
90978
|
+
driftHasSpecMd = fs84.existsSync(specMdPath);
|
|
90264
90979
|
const gatePlan = await loadPlan(dir);
|
|
90265
90980
|
if (gatePlan) {
|
|
90266
90981
|
const gatePlanId = derivePlanId(gatePlan);
|
|
@@ -90280,9 +90995,9 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
90280
90995
|
} else {
|
|
90281
90996
|
let phaseType;
|
|
90282
90997
|
try {
|
|
90283
|
-
const planPath =
|
|
90284
|
-
if (
|
|
90285
|
-
const planRaw =
|
|
90998
|
+
const planPath = path110.join(dir, ".swarm", "plan.json");
|
|
90999
|
+
if (fs84.existsSync(planPath)) {
|
|
91000
|
+
const planRaw = fs84.readFileSync(planPath, "utf-8");
|
|
90286
91001
|
const plan = JSON.parse(planRaw);
|
|
90287
91002
|
const targetPhase = plan.phases?.find((p) => p.id === phase);
|
|
90288
91003
|
phaseType = targetPhase?.type;
|
|
@@ -90292,11 +91007,11 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
90292
91007
|
warnings.push(`Phase ${phase} is annotated as 'non-code'. Drift verification was skipped per phase type annotation.`);
|
|
90293
91008
|
} else {
|
|
90294
91009
|
try {
|
|
90295
|
-
const driftEvidencePath =
|
|
91010
|
+
const driftEvidencePath = path110.join(dir, ".swarm", "evidence", String(phase), "drift-verifier.json");
|
|
90296
91011
|
let driftVerdictFound = false;
|
|
90297
91012
|
let driftVerdictApproved = false;
|
|
90298
91013
|
try {
|
|
90299
|
-
const driftEvidenceContent =
|
|
91014
|
+
const driftEvidenceContent = fs84.readFileSync(driftEvidencePath, "utf-8");
|
|
90300
91015
|
const driftEvidence = JSON.parse(driftEvidenceContent);
|
|
90301
91016
|
const entries = driftEvidence.entries ?? [];
|
|
90302
91017
|
for (const entry of entries) {
|
|
@@ -90330,9 +91045,9 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
90330
91045
|
let incompleteTaskCount = 0;
|
|
90331
91046
|
let planParseable = false;
|
|
90332
91047
|
try {
|
|
90333
|
-
const planPath =
|
|
90334
|
-
if (
|
|
90335
|
-
const planRaw =
|
|
91048
|
+
const planPath = path110.join(dir, ".swarm", "plan.json");
|
|
91049
|
+
if (fs84.existsSync(planPath)) {
|
|
91050
|
+
const planRaw = fs84.readFileSync(planPath, "utf-8");
|
|
90336
91051
|
const plan = JSON.parse(planRaw);
|
|
90337
91052
|
planParseable = true;
|
|
90338
91053
|
const planPhase = plan.phases?.find((p) => p.id === phase);
|
|
@@ -90397,11 +91112,11 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
90397
91112
|
const overrides = session2?.qaGateSessionOverrides ?? {};
|
|
90398
91113
|
const effective = getEffectiveGates(profile, overrides);
|
|
90399
91114
|
if (effective.hallucination_guard === true) {
|
|
90400
|
-
const hgPath =
|
|
91115
|
+
const hgPath = path110.join(dir, ".swarm", "evidence", String(phase), "hallucination-guard.json");
|
|
90401
91116
|
let hgVerdictFound = false;
|
|
90402
91117
|
let hgVerdictApproved = false;
|
|
90403
91118
|
try {
|
|
90404
|
-
const hgContent =
|
|
91119
|
+
const hgContent = fs84.readFileSync(hgPath, "utf-8");
|
|
90405
91120
|
const hgBundle = JSON.parse(hgContent);
|
|
90406
91121
|
for (const entry of hgBundle.entries ?? []) {
|
|
90407
91122
|
if (typeof entry.type === "string" && entry.type.includes("hallucination") && typeof entry.verdict === "string") {
|
|
@@ -90469,11 +91184,11 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
90469
91184
|
const overrides = session2?.qaGateSessionOverrides ?? {};
|
|
90470
91185
|
const effective = getEffectiveGates(profile, overrides);
|
|
90471
91186
|
if (effective.mutation_test === true) {
|
|
90472
|
-
const mgPath =
|
|
91187
|
+
const mgPath = path110.join(dir, ".swarm", "evidence", String(phase), "mutation-gate.json");
|
|
90473
91188
|
let mgVerdictFound = false;
|
|
90474
91189
|
let mgVerdict;
|
|
90475
91190
|
try {
|
|
90476
|
-
const mgContent =
|
|
91191
|
+
const mgContent = fs84.readFileSync(mgPath, "utf-8");
|
|
90477
91192
|
const mgBundle = JSON.parse(mgContent);
|
|
90478
91193
|
for (const entry of mgBundle.entries ?? []) {
|
|
90479
91194
|
if (typeof entry.type === "string" && entry.type === "mutation-gate" && typeof entry.verdict === "string") {
|
|
@@ -90543,14 +91258,14 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
90543
91258
|
const effective = getEffectiveGates(profile, overrides);
|
|
90544
91259
|
if (effective.council_mode === true) {
|
|
90545
91260
|
councilModeEnabled = true;
|
|
90546
|
-
const pcPath =
|
|
91261
|
+
const pcPath = path110.join(dir, ".swarm", "evidence", String(phase), "phase-council.json");
|
|
90547
91262
|
let pcVerdictFound = false;
|
|
90548
91263
|
let _pcVerdict;
|
|
90549
91264
|
let pcQuorumSize;
|
|
90550
91265
|
let pcTimestamp;
|
|
90551
91266
|
let pcPhaseNumber;
|
|
90552
91267
|
try {
|
|
90553
|
-
const pcContent =
|
|
91268
|
+
const pcContent = fs84.readFileSync(pcPath, "utf-8");
|
|
90554
91269
|
const pcBundle = JSON.parse(pcContent);
|
|
90555
91270
|
for (const entry of pcBundle.entries ?? []) {
|
|
90556
91271
|
if (typeof entry.type === "string" && entry.type === "phase-council" && typeof entry.verdict === "string") {
|
|
@@ -90751,11 +91466,11 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
|
|
|
90751
91466
|
const effective = getEffectiveGates(profile, overrides);
|
|
90752
91467
|
if (effective.final_council === true) {
|
|
90753
91468
|
finalCouncilEnabled = true;
|
|
90754
|
-
const fcPath =
|
|
91469
|
+
const fcPath = path110.join(dir, ".swarm", "evidence", "final-council.json");
|
|
90755
91470
|
let fcVerdictFound = false;
|
|
90756
91471
|
let _fcVerdict;
|
|
90757
91472
|
try {
|
|
90758
|
-
const fcContent =
|
|
91473
|
+
const fcContent = fs84.readFileSync(fcPath, "utf-8");
|
|
90759
91474
|
const fcBundle = JSON.parse(fcContent);
|
|
90760
91475
|
for (const entry of fcBundle.entries ?? []) {
|
|
90761
91476
|
if (typeof entry.type === "string" && entry.type === "final-council" && typeof entry.verdict === "string") {
|
|
@@ -90916,7 +91631,7 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
|
|
|
90916
91631
|
phase_critic: leanConfig.phase_critic,
|
|
90917
91632
|
integrated_diff_required: leanConfig.integrated_diff_required
|
|
90918
91633
|
} : undefined;
|
|
90919
|
-
const leanCheck =
|
|
91634
|
+
const leanCheck = _internals43.verifyLeanTurboPhaseReady(dir, phase, sessionID, leanPhaseReadyConfig);
|
|
90920
91635
|
if (!leanCheck.ok) {
|
|
90921
91636
|
return JSON.stringify({
|
|
90922
91637
|
success: false,
|
|
@@ -90939,7 +91654,7 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
|
|
|
90939
91654
|
}
|
|
90940
91655
|
if (retroFound && retroEntry?.lessons_learned && retroEntry.lessons_learned.length > 0) {
|
|
90941
91656
|
try {
|
|
90942
|
-
const projectName =
|
|
91657
|
+
const projectName = path110.basename(dir);
|
|
90943
91658
|
const curationResult = await curateAndStoreSwarm(retroEntry.lessons_learned, projectName, { phase_number: phase }, dir, knowledgeConfig);
|
|
90944
91659
|
if (curationResult) {
|
|
90945
91660
|
const sessionState = swarmState.agentSessions.get(sessionID);
|
|
@@ -91019,7 +91734,7 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
|
|
|
91019
91734
|
let phaseRequiredAgents;
|
|
91020
91735
|
try {
|
|
91021
91736
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
91022
|
-
const planRaw =
|
|
91737
|
+
const planRaw = fs84.readFileSync(planPath, "utf-8");
|
|
91023
91738
|
const plan = JSON.parse(planRaw);
|
|
91024
91739
|
const phaseObj = plan.phases.find((p) => p.id === phase);
|
|
91025
91740
|
phaseRequiredAgents = phaseObj?.required_agents;
|
|
@@ -91034,7 +91749,7 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
|
|
|
91034
91749
|
if (agentsMissing.length > 0) {
|
|
91035
91750
|
try {
|
|
91036
91751
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
91037
|
-
const planRaw =
|
|
91752
|
+
const planRaw = fs84.readFileSync(planPath, "utf-8");
|
|
91038
91753
|
const plan = JSON.parse(planRaw);
|
|
91039
91754
|
const targetPhase = plan.phases.find((p) => p.id === phase);
|
|
91040
91755
|
if (targetPhase && targetPhase.tasks.length > 0 && targetPhase.tasks.every((t) => t.status === "completed")) {
|
|
@@ -91074,7 +91789,7 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
|
|
|
91074
91789
|
if (phaseCompleteConfig.regression_sweep?.enforce) {
|
|
91075
91790
|
try {
|
|
91076
91791
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
91077
|
-
const planRaw =
|
|
91792
|
+
const planRaw = fs84.readFileSync(planPath, "utf-8");
|
|
91078
91793
|
const plan = JSON.parse(planRaw);
|
|
91079
91794
|
const targetPhase = plan.phases.find((p) => p.id === phase);
|
|
91080
91795
|
if (targetPhase) {
|
|
@@ -91128,7 +91843,7 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
|
|
|
91128
91843
|
}
|
|
91129
91844
|
try {
|
|
91130
91845
|
const eventsPath = validateSwarmPath(dir, "events.jsonl");
|
|
91131
|
-
|
|
91846
|
+
fs84.appendFileSync(eventsPath, `${JSON.stringify(event)}
|
|
91132
91847
|
`, "utf-8");
|
|
91133
91848
|
} catch (writeError) {
|
|
91134
91849
|
warnings.push(`Warning: failed to write phase complete event: ${writeError instanceof Error ? writeError.message : String(writeError)}`);
|
|
@@ -91203,12 +91918,12 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
|
|
|
91203
91918
|
warnings.push(`Warning: failed to update plan.json phase status`);
|
|
91204
91919
|
try {
|
|
91205
91920
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
91206
|
-
const planRaw =
|
|
91921
|
+
const planRaw = fs84.readFileSync(planPath, "utf-8");
|
|
91207
91922
|
const plan2 = JSON.parse(planRaw);
|
|
91208
91923
|
const phaseObj = plan2.phases.find((p) => p.id === phase);
|
|
91209
91924
|
if (phaseObj) {
|
|
91210
91925
|
phaseObj.status = "complete";
|
|
91211
|
-
|
|
91926
|
+
fs84.writeFileSync(planPath, JSON.stringify(plan2, null, 2), "utf-8");
|
|
91212
91927
|
}
|
|
91213
91928
|
} catch {}
|
|
91214
91929
|
} else if (plan) {
|
|
@@ -91245,12 +91960,12 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
|
|
|
91245
91960
|
warnings.push(`Warning: failed to update plan.json phase status`);
|
|
91246
91961
|
try {
|
|
91247
91962
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
91248
|
-
const planRaw =
|
|
91963
|
+
const planRaw = fs84.readFileSync(planPath, "utf-8");
|
|
91249
91964
|
const plan = JSON.parse(planRaw);
|
|
91250
91965
|
const phaseObj = plan.phases.find((p) => p.id === phase);
|
|
91251
91966
|
if (phaseObj) {
|
|
91252
91967
|
phaseObj.status = "complete";
|
|
91253
|
-
|
|
91968
|
+
fs84.writeFileSync(planPath, JSON.stringify(plan, null, 2), "utf-8");
|
|
91254
91969
|
}
|
|
91255
91970
|
} catch {}
|
|
91256
91971
|
}
|
|
@@ -91308,8 +92023,8 @@ init_discovery();
|
|
|
91308
92023
|
init_utils();
|
|
91309
92024
|
init_bun_compat();
|
|
91310
92025
|
init_create_tool();
|
|
91311
|
-
import * as
|
|
91312
|
-
import * as
|
|
92026
|
+
import * as fs85 from "node:fs";
|
|
92027
|
+
import * as path111 from "node:path";
|
|
91313
92028
|
var MAX_OUTPUT_BYTES5 = 52428800;
|
|
91314
92029
|
var AUDIT_TIMEOUT_MS = 120000;
|
|
91315
92030
|
function isValidEcosystem(value) {
|
|
@@ -91337,31 +92052,31 @@ function validateArgs3(args2) {
|
|
|
91337
92052
|
function detectEcosystems(directory) {
|
|
91338
92053
|
const ecosystems = [];
|
|
91339
92054
|
const cwd = directory;
|
|
91340
|
-
if (
|
|
92055
|
+
if (fs85.existsSync(path111.join(cwd, "package.json"))) {
|
|
91341
92056
|
ecosystems.push("npm");
|
|
91342
92057
|
}
|
|
91343
|
-
if (
|
|
92058
|
+
if (fs85.existsSync(path111.join(cwd, "pyproject.toml")) || fs85.existsSync(path111.join(cwd, "requirements.txt"))) {
|
|
91344
92059
|
ecosystems.push("pip");
|
|
91345
92060
|
}
|
|
91346
|
-
if (
|
|
92061
|
+
if (fs85.existsSync(path111.join(cwd, "Cargo.toml"))) {
|
|
91347
92062
|
ecosystems.push("cargo");
|
|
91348
92063
|
}
|
|
91349
|
-
if (
|
|
92064
|
+
if (fs85.existsSync(path111.join(cwd, "go.mod"))) {
|
|
91350
92065
|
ecosystems.push("go");
|
|
91351
92066
|
}
|
|
91352
92067
|
try {
|
|
91353
|
-
const files =
|
|
92068
|
+
const files = fs85.readdirSync(cwd);
|
|
91354
92069
|
if (files.some((f) => f.endsWith(".csproj") || f.endsWith(".sln"))) {
|
|
91355
92070
|
ecosystems.push("dotnet");
|
|
91356
92071
|
}
|
|
91357
92072
|
} catch {}
|
|
91358
|
-
if (
|
|
92073
|
+
if (fs85.existsSync(path111.join(cwd, "Gemfile")) || fs85.existsSync(path111.join(cwd, "Gemfile.lock"))) {
|
|
91359
92074
|
ecosystems.push("ruby");
|
|
91360
92075
|
}
|
|
91361
|
-
if (
|
|
92076
|
+
if (fs85.existsSync(path111.join(cwd, "pubspec.yaml"))) {
|
|
91362
92077
|
ecosystems.push("dart");
|
|
91363
92078
|
}
|
|
91364
|
-
if (
|
|
92079
|
+
if (fs85.existsSync(path111.join(cwd, "composer.lock"))) {
|
|
91365
92080
|
ecosystems.push("composer");
|
|
91366
92081
|
}
|
|
91367
92082
|
return ecosystems;
|
|
@@ -92496,8 +93211,8 @@ var pkg_audit = createSwarmTool({
|
|
|
92496
93211
|
// src/tools/placeholder-scan.ts
|
|
92497
93212
|
init_zod();
|
|
92498
93213
|
init_manager2();
|
|
92499
|
-
import * as
|
|
92500
|
-
import * as
|
|
93214
|
+
import * as fs86 from "node:fs";
|
|
93215
|
+
import * as path112 from "node:path";
|
|
92501
93216
|
init_utils();
|
|
92502
93217
|
init_create_tool();
|
|
92503
93218
|
var MAX_FILE_SIZE = 1024 * 1024;
|
|
@@ -92620,7 +93335,7 @@ function isScaffoldFile(filePath) {
|
|
|
92620
93335
|
if (SCAFFOLD_PATH_PATTERNS.some((pattern) => pattern.test(normalizedPath))) {
|
|
92621
93336
|
return true;
|
|
92622
93337
|
}
|
|
92623
|
-
const filename =
|
|
93338
|
+
const filename = path112.basename(filePath);
|
|
92624
93339
|
if (SCAFFOLD_FILENAME_PATTERNS.some((pattern) => pattern.test(filename))) {
|
|
92625
93340
|
return true;
|
|
92626
93341
|
}
|
|
@@ -92637,7 +93352,7 @@ function isAllowedByGlobs(filePath, allowGlobs) {
|
|
|
92637
93352
|
if (regex.test(normalizedPath)) {
|
|
92638
93353
|
return true;
|
|
92639
93354
|
}
|
|
92640
|
-
const filename =
|
|
93355
|
+
const filename = path112.basename(filePath);
|
|
92641
93356
|
const filenameRegex = new RegExp(`^${regexPattern}$`, "i");
|
|
92642
93357
|
if (filenameRegex.test(filename)) {
|
|
92643
93358
|
return true;
|
|
@@ -92646,7 +93361,7 @@ function isAllowedByGlobs(filePath, allowGlobs) {
|
|
|
92646
93361
|
return false;
|
|
92647
93362
|
}
|
|
92648
93363
|
function isParserSupported(filePath) {
|
|
92649
|
-
const ext =
|
|
93364
|
+
const ext = path112.extname(filePath).toLowerCase();
|
|
92650
93365
|
return SUPPORTED_PARSER_EXTENSIONS.has(ext);
|
|
92651
93366
|
}
|
|
92652
93367
|
function isPlanFile(filePath) {
|
|
@@ -92893,28 +93608,28 @@ async function placeholderScan(input, directory) {
|
|
|
92893
93608
|
let filesScanned = 0;
|
|
92894
93609
|
const filesWithFindings = new Set;
|
|
92895
93610
|
for (const filePath of changed_files) {
|
|
92896
|
-
const fullPath =
|
|
92897
|
-
const resolvedDirectory =
|
|
92898
|
-
if (!fullPath.startsWith(resolvedDirectory +
|
|
93611
|
+
const fullPath = path112.isAbsolute(filePath) ? filePath : path112.resolve(directory, filePath);
|
|
93612
|
+
const resolvedDirectory = path112.resolve(directory);
|
|
93613
|
+
if (!fullPath.startsWith(resolvedDirectory + path112.sep) && fullPath !== resolvedDirectory) {
|
|
92899
93614
|
continue;
|
|
92900
93615
|
}
|
|
92901
|
-
if (!
|
|
93616
|
+
if (!fs86.existsSync(fullPath)) {
|
|
92902
93617
|
continue;
|
|
92903
93618
|
}
|
|
92904
93619
|
if (isAllowedByGlobs(filePath, allow_globs)) {
|
|
92905
93620
|
continue;
|
|
92906
93621
|
}
|
|
92907
|
-
const relativeFilePath =
|
|
93622
|
+
const relativeFilePath = path112.relative(directory, fullPath).replace(/\\/g, "/");
|
|
92908
93623
|
if (FILE_ALLOWLIST.some((allowed) => relativeFilePath.endsWith(allowed))) {
|
|
92909
93624
|
continue;
|
|
92910
93625
|
}
|
|
92911
93626
|
let content;
|
|
92912
93627
|
try {
|
|
92913
|
-
const stat8 =
|
|
93628
|
+
const stat8 = fs86.statSync(fullPath);
|
|
92914
93629
|
if (stat8.size > MAX_FILE_SIZE) {
|
|
92915
93630
|
continue;
|
|
92916
93631
|
}
|
|
92917
|
-
content =
|
|
93632
|
+
content = fs86.readFileSync(fullPath, "utf-8");
|
|
92918
93633
|
} catch {
|
|
92919
93634
|
continue;
|
|
92920
93635
|
}
|
|
@@ -92975,8 +93690,8 @@ var placeholder_scan = createSwarmTool({
|
|
|
92975
93690
|
}
|
|
92976
93691
|
});
|
|
92977
93692
|
// src/tools/pre-check-batch.ts
|
|
92978
|
-
import * as
|
|
92979
|
-
import * as
|
|
93693
|
+
import * as fs90 from "node:fs";
|
|
93694
|
+
import * as path116 from "node:path";
|
|
92980
93695
|
init_zod();
|
|
92981
93696
|
init_manager2();
|
|
92982
93697
|
init_utils();
|
|
@@ -93104,11 +93819,11 @@ var quality_budget = createSwarmTool({
|
|
|
93104
93819
|
}).optional().describe("Quality budget thresholds")
|
|
93105
93820
|
},
|
|
93106
93821
|
async execute(args2, directory) {
|
|
93107
|
-
const result = await
|
|
93822
|
+
const result = await _internals44.qualityBudget(args2, directory);
|
|
93108
93823
|
return JSON.stringify(result);
|
|
93109
93824
|
}
|
|
93110
93825
|
});
|
|
93111
|
-
var
|
|
93826
|
+
var _internals44 = {
|
|
93112
93827
|
qualityBudget
|
|
93113
93828
|
};
|
|
93114
93829
|
|
|
@@ -93116,9 +93831,9 @@ var _internals41 = {
|
|
|
93116
93831
|
init_zod();
|
|
93117
93832
|
init_manager2();
|
|
93118
93833
|
init_detector();
|
|
93119
|
-
import * as
|
|
93120
|
-
import * as
|
|
93121
|
-
import { extname as
|
|
93834
|
+
import * as fs89 from "node:fs";
|
|
93835
|
+
import * as path115 from "node:path";
|
|
93836
|
+
import { extname as extname20 } from "node:path";
|
|
93122
93837
|
|
|
93123
93838
|
// src/sast/rules/c.ts
|
|
93124
93839
|
var cRules = [
|
|
@@ -93832,12 +94547,12 @@ function executeRulesSync(filePath, content, language) {
|
|
|
93832
94547
|
|
|
93833
94548
|
// src/sast/semgrep.ts
|
|
93834
94549
|
import * as child_process9 from "node:child_process";
|
|
93835
|
-
import * as
|
|
93836
|
-
import * as
|
|
94550
|
+
import * as fs87 from "node:fs";
|
|
94551
|
+
import * as path113 from "node:path";
|
|
93837
94552
|
var semgrepAvailableCache = null;
|
|
93838
94553
|
var DEFAULT_RULES_DIR = ".swarm/semgrep-rules";
|
|
93839
94554
|
var DEFAULT_TIMEOUT_MS3 = 30000;
|
|
93840
|
-
var
|
|
94555
|
+
var _internals45 = {
|
|
93841
94556
|
isSemgrepAvailable,
|
|
93842
94557
|
checkSemgrepAvailable,
|
|
93843
94558
|
resetSemgrepCache,
|
|
@@ -93862,7 +94577,7 @@ function isSemgrepAvailable() {
|
|
|
93862
94577
|
}
|
|
93863
94578
|
}
|
|
93864
94579
|
async function checkSemgrepAvailable() {
|
|
93865
|
-
return
|
|
94580
|
+
return _internals45.isSemgrepAvailable();
|
|
93866
94581
|
}
|
|
93867
94582
|
function resetSemgrepCache() {
|
|
93868
94583
|
semgrepAvailableCache = null;
|
|
@@ -93959,12 +94674,12 @@ async function runSemgrep(options) {
|
|
|
93959
94674
|
const timeoutMs = options.timeoutMs || DEFAULT_TIMEOUT_MS3;
|
|
93960
94675
|
if (files.length === 0) {
|
|
93961
94676
|
return {
|
|
93962
|
-
available:
|
|
94677
|
+
available: _internals45.isSemgrepAvailable(),
|
|
93963
94678
|
findings: [],
|
|
93964
94679
|
engine: "tier_a"
|
|
93965
94680
|
};
|
|
93966
94681
|
}
|
|
93967
|
-
if (!
|
|
94682
|
+
if (!_internals45.isSemgrepAvailable()) {
|
|
93968
94683
|
return {
|
|
93969
94684
|
available: false,
|
|
93970
94685
|
findings: [],
|
|
@@ -94020,14 +94735,14 @@ async function runSemgrep(options) {
|
|
|
94020
94735
|
}
|
|
94021
94736
|
function getRulesDirectory(projectRoot) {
|
|
94022
94737
|
if (projectRoot) {
|
|
94023
|
-
return
|
|
94738
|
+
return path113.resolve(projectRoot, DEFAULT_RULES_DIR);
|
|
94024
94739
|
}
|
|
94025
94740
|
return DEFAULT_RULES_DIR;
|
|
94026
94741
|
}
|
|
94027
94742
|
function hasBundledRules(projectRoot) {
|
|
94028
94743
|
const rulesDir = getRulesDirectory(projectRoot);
|
|
94029
94744
|
try {
|
|
94030
|
-
return
|
|
94745
|
+
return fs87.existsSync(rulesDir);
|
|
94031
94746
|
} catch {
|
|
94032
94747
|
return false;
|
|
94033
94748
|
}
|
|
@@ -94039,26 +94754,26 @@ init_create_tool();
|
|
|
94039
94754
|
|
|
94040
94755
|
// src/tools/sast-baseline.ts
|
|
94041
94756
|
init_utils2();
|
|
94042
|
-
import * as
|
|
94043
|
-
import * as
|
|
94044
|
-
import * as
|
|
94757
|
+
import * as crypto10 from "node:crypto";
|
|
94758
|
+
import * as fs88 from "node:fs";
|
|
94759
|
+
import * as path114 from "node:path";
|
|
94045
94760
|
var BASELINE_SCHEMA_VERSION = "1.0.0";
|
|
94046
94761
|
var MAX_BASELINE_FINDINGS = 2000;
|
|
94047
94762
|
var MAX_BASELINE_BYTES = 2 * 1048576;
|
|
94048
94763
|
var LOCK_RETRY_DELAYS_MS = [50, 100, 200, 400, 800];
|
|
94049
94764
|
function normalizeFindingPath(directory, file3) {
|
|
94050
|
-
const resolved =
|
|
94051
|
-
const rel =
|
|
94765
|
+
const resolved = path114.isAbsolute(file3) ? file3 : path114.resolve(directory, file3);
|
|
94766
|
+
const rel = path114.relative(path114.resolve(directory), resolved);
|
|
94052
94767
|
return rel.replace(/\\/g, "/");
|
|
94053
94768
|
}
|
|
94054
94769
|
function baselineRelPath(phase) {
|
|
94055
|
-
return
|
|
94770
|
+
return path114.join("evidence", String(phase), "sast-baseline.json");
|
|
94056
94771
|
}
|
|
94057
94772
|
function tempRelPath(phase) {
|
|
94058
|
-
return
|
|
94773
|
+
return path114.join("evidence", String(phase), `sast-baseline.json.tmp.${Date.now()}.${process.pid}`);
|
|
94059
94774
|
}
|
|
94060
94775
|
function lockRelPath(phase) {
|
|
94061
|
-
return
|
|
94776
|
+
return path114.join("evidence", String(phase), "sast-baseline.json.lock");
|
|
94062
94777
|
}
|
|
94063
94778
|
function getLine(lines, idx) {
|
|
94064
94779
|
if (idx < 0 || idx >= lines.length)
|
|
@@ -94075,7 +94790,7 @@ function fingerprintFinding(finding, directory, occurrenceIndex) {
|
|
|
94075
94790
|
}
|
|
94076
94791
|
const lineNum = finding.location.line;
|
|
94077
94792
|
try {
|
|
94078
|
-
const content =
|
|
94793
|
+
const content = fs88.readFileSync(finding.location.file, "utf-8");
|
|
94079
94794
|
const lines = content.split(`
|
|
94080
94795
|
`);
|
|
94081
94796
|
const idx = lineNum - 1;
|
|
@@ -94085,7 +94800,7 @@ function fingerprintFinding(finding, directory, occurrenceIndex) {
|
|
|
94085
94800
|
getLine(lines, idx + 1)
|
|
94086
94801
|
].join(`
|
|
94087
94802
|
`);
|
|
94088
|
-
const hash3 =
|
|
94803
|
+
const hash3 = crypto10.createHash("sha256").update(window2).digest("hex").slice(0, 16);
|
|
94089
94804
|
return {
|
|
94090
94805
|
fingerprint: `${relFile}|${finding.rule_id}|${hash3}|#${occurrenceIndex}`,
|
|
94091
94806
|
stable: true
|
|
@@ -94106,7 +94821,7 @@ function assignOccurrenceIndices(findings, directory) {
|
|
|
94106
94821
|
try {
|
|
94107
94822
|
if (relFile.startsWith(".."))
|
|
94108
94823
|
throw new Error("escapes workspace");
|
|
94109
|
-
const content =
|
|
94824
|
+
const content = fs88.readFileSync(finding.location.file, "utf-8");
|
|
94110
94825
|
const lines = content.split(`
|
|
94111
94826
|
`);
|
|
94112
94827
|
const idx = lineNum - 1;
|
|
@@ -94116,14 +94831,14 @@ function assignOccurrenceIndices(findings, directory) {
|
|
|
94116
94831
|
getLine(lines, idx + 1)
|
|
94117
94832
|
].join(`
|
|
94118
94833
|
`);
|
|
94119
|
-
const hash3 =
|
|
94834
|
+
const hash3 = crypto10.createHash("sha256").update(window2).digest("hex").slice(0, 16);
|
|
94120
94835
|
baseKey = `${relFile}|${finding.rule_id}|${hash3}`;
|
|
94121
94836
|
} catch {
|
|
94122
94837
|
baseKey = `${relFile}|${finding.rule_id}|L${lineNum}|UNSTABLE`;
|
|
94123
94838
|
}
|
|
94124
94839
|
const occIdx = countMap.get(baseKey) ?? 0;
|
|
94125
94840
|
countMap.set(baseKey, occIdx + 1);
|
|
94126
|
-
const fp =
|
|
94841
|
+
const fp = _internals46.fingerprintFinding(finding, directory, occIdx);
|
|
94127
94842
|
return {
|
|
94128
94843
|
finding,
|
|
94129
94844
|
index: occIdx,
|
|
@@ -94135,11 +94850,11 @@ function assignOccurrenceIndices(findings, directory) {
|
|
|
94135
94850
|
async function acquireLock2(lockPath) {
|
|
94136
94851
|
for (let attempt = 0;attempt <= LOCK_RETRY_DELAYS_MS.length; attempt++) {
|
|
94137
94852
|
try {
|
|
94138
|
-
const fd =
|
|
94139
|
-
|
|
94853
|
+
const fd = fs88.openSync(lockPath, "wx");
|
|
94854
|
+
fs88.closeSync(fd);
|
|
94140
94855
|
return () => {
|
|
94141
94856
|
try {
|
|
94142
|
-
|
|
94857
|
+
fs88.unlinkSync(lockPath);
|
|
94143
94858
|
} catch {}
|
|
94144
94859
|
};
|
|
94145
94860
|
} catch {
|
|
@@ -94179,20 +94894,20 @@ async function captureOrMergeBaseline(directory, phase, findings, engine, scanne
|
|
|
94179
94894
|
message: e instanceof Error ? e.message : "Path validation failed"
|
|
94180
94895
|
};
|
|
94181
94896
|
}
|
|
94182
|
-
|
|
94183
|
-
|
|
94897
|
+
fs88.mkdirSync(path114.dirname(baselinePath), { recursive: true });
|
|
94898
|
+
fs88.mkdirSync(path114.dirname(tempPath), { recursive: true });
|
|
94184
94899
|
const releaseLock = await acquireLock2(lockPath);
|
|
94185
94900
|
try {
|
|
94186
94901
|
let existing = null;
|
|
94187
94902
|
try {
|
|
94188
|
-
const raw =
|
|
94903
|
+
const raw = fs88.readFileSync(baselinePath, "utf-8");
|
|
94189
94904
|
const parsed = JSON.parse(raw);
|
|
94190
94905
|
if (parsed.schema_version === BASELINE_SCHEMA_VERSION) {
|
|
94191
94906
|
existing = parsed;
|
|
94192
94907
|
}
|
|
94193
94908
|
} catch {}
|
|
94194
94909
|
const scannedRelFiles = new Set(scannedFiles.map((f) => normalizeFindingPath(directory, f)));
|
|
94195
|
-
const indexed =
|
|
94910
|
+
const indexed = _internals46.assignOccurrenceIndices(findings, directory);
|
|
94196
94911
|
if (existing && !opts?.force) {
|
|
94197
94912
|
const prunedFingerprints = existing.fingerprints.filter((fp) => {
|
|
94198
94913
|
const relFile = fp.slice(0, fp.indexOf("|"));
|
|
@@ -94245,8 +94960,8 @@ async function captureOrMergeBaseline(directory, phase, findings, engine, scanne
|
|
|
94245
94960
|
message: `Baseline would exceed size cap (${json4.length} bytes > ${MAX_BASELINE_BYTES})`
|
|
94246
94961
|
};
|
|
94247
94962
|
}
|
|
94248
|
-
|
|
94249
|
-
|
|
94963
|
+
fs88.writeFileSync(tempPath, json4, "utf-8");
|
|
94964
|
+
fs88.renameSync(tempPath, baselinePath);
|
|
94250
94965
|
return {
|
|
94251
94966
|
status: "merged",
|
|
94252
94967
|
path: baselinePath,
|
|
@@ -94277,8 +94992,8 @@ async function captureOrMergeBaseline(directory, phase, findings, engine, scanne
|
|
|
94277
94992
|
message: `Baseline would exceed size cap (${json3.length} bytes > ${MAX_BASELINE_BYTES})`
|
|
94278
94993
|
};
|
|
94279
94994
|
}
|
|
94280
|
-
|
|
94281
|
-
|
|
94995
|
+
fs88.writeFileSync(tempPath, json3, "utf-8");
|
|
94996
|
+
fs88.renameSync(tempPath, baselinePath);
|
|
94282
94997
|
return {
|
|
94283
94998
|
status: "written",
|
|
94284
94999
|
path: baselinePath,
|
|
@@ -94303,7 +95018,7 @@ function loadBaseline(directory, phase) {
|
|
|
94303
95018
|
};
|
|
94304
95019
|
}
|
|
94305
95020
|
try {
|
|
94306
|
-
const raw =
|
|
95021
|
+
const raw = fs88.readFileSync(baselinePath, "utf-8");
|
|
94307
95022
|
const parsed = JSON.parse(raw);
|
|
94308
95023
|
if (parsed.schema_version !== BASELINE_SCHEMA_VERSION) {
|
|
94309
95024
|
return {
|
|
@@ -94332,7 +95047,7 @@ function loadBaseline(directory, phase) {
|
|
|
94332
95047
|
};
|
|
94333
95048
|
}
|
|
94334
95049
|
}
|
|
94335
|
-
var
|
|
95050
|
+
var _internals46 = {
|
|
94336
95051
|
fingerprintFinding,
|
|
94337
95052
|
assignOccurrenceIndices,
|
|
94338
95053
|
captureOrMergeBaseline,
|
|
@@ -94351,17 +95066,17 @@ var SEVERITY_ORDER = {
|
|
|
94351
95066
|
};
|
|
94352
95067
|
function shouldSkipFile(filePath) {
|
|
94353
95068
|
try {
|
|
94354
|
-
const stats =
|
|
95069
|
+
const stats = fs89.statSync(filePath);
|
|
94355
95070
|
if (stats.size > MAX_FILE_SIZE_BYTES8) {
|
|
94356
95071
|
return { skip: true, reason: "file too large" };
|
|
94357
95072
|
}
|
|
94358
95073
|
if (stats.size === 0) {
|
|
94359
95074
|
return { skip: true, reason: "empty file" };
|
|
94360
95075
|
}
|
|
94361
|
-
const fd =
|
|
95076
|
+
const fd = fs89.openSync(filePath, "r");
|
|
94362
95077
|
const buffer = Buffer.alloc(8192);
|
|
94363
|
-
const bytesRead =
|
|
94364
|
-
|
|
95078
|
+
const bytesRead = fs89.readSync(fd, buffer, 0, 8192, 0);
|
|
95079
|
+
fs89.closeSync(fd);
|
|
94365
95080
|
if (bytesRead > 0) {
|
|
94366
95081
|
let nullCount = 0;
|
|
94367
95082
|
for (let i2 = 0;i2 < bytesRead; i2++) {
|
|
@@ -94400,7 +95115,7 @@ function countBySeverity(findings) {
|
|
|
94400
95115
|
}
|
|
94401
95116
|
function scanFileWithTierA(filePath, language) {
|
|
94402
95117
|
try {
|
|
94403
|
-
const content =
|
|
95118
|
+
const content = fs89.readFileSync(filePath, "utf-8");
|
|
94404
95119
|
const findings = executeRulesSync(filePath, content, language);
|
|
94405
95120
|
return findings.map((f) => ({
|
|
94406
95121
|
rule_id: f.rule_id,
|
|
@@ -94453,13 +95168,13 @@ async function sastScan(input, directory, config3) {
|
|
|
94453
95168
|
_filesSkipped++;
|
|
94454
95169
|
continue;
|
|
94455
95170
|
}
|
|
94456
|
-
const resolvedPath =
|
|
94457
|
-
const resolvedDirectory =
|
|
94458
|
-
if (!resolvedPath.startsWith(resolvedDirectory +
|
|
95171
|
+
const resolvedPath = path115.isAbsolute(filePath) ? filePath : path115.resolve(directory, filePath);
|
|
95172
|
+
const resolvedDirectory = path115.resolve(directory);
|
|
95173
|
+
if (!resolvedPath.startsWith(resolvedDirectory + path115.sep) && resolvedPath !== resolvedDirectory) {
|
|
94459
95174
|
_filesSkipped++;
|
|
94460
95175
|
continue;
|
|
94461
95176
|
}
|
|
94462
|
-
if (!
|
|
95177
|
+
if (!fs89.existsSync(resolvedPath)) {
|
|
94463
95178
|
_filesSkipped++;
|
|
94464
95179
|
continue;
|
|
94465
95180
|
}
|
|
@@ -94468,7 +95183,7 @@ async function sastScan(input, directory, config3) {
|
|
|
94468
95183
|
_filesSkipped++;
|
|
94469
95184
|
continue;
|
|
94470
95185
|
}
|
|
94471
|
-
const ext =
|
|
95186
|
+
const ext = extname20(resolvedPath).toLowerCase();
|
|
94472
95187
|
const profile = getProfileForFile(resolvedPath);
|
|
94473
95188
|
const langDef = getLanguageForExtension(ext);
|
|
94474
95189
|
if (!profile && !langDef) {
|
|
@@ -94742,11 +95457,11 @@ var sast_scan = createSwarmTool({
|
|
|
94742
95457
|
capture_baseline: safeArgs.capture_baseline,
|
|
94743
95458
|
phase: safeArgs.phase
|
|
94744
95459
|
};
|
|
94745
|
-
const result = await
|
|
95460
|
+
const result = await _internals47.sastScan(input, directory);
|
|
94746
95461
|
return JSON.stringify(result, null, 2);
|
|
94747
95462
|
}
|
|
94748
95463
|
});
|
|
94749
|
-
var
|
|
95464
|
+
var _internals47 = {
|
|
94750
95465
|
sastScan,
|
|
94751
95466
|
sast_scan
|
|
94752
95467
|
};
|
|
@@ -94770,18 +95485,18 @@ function validatePath(inputPath, baseDir, workspaceDir) {
|
|
|
94770
95485
|
let resolved;
|
|
94771
95486
|
const isWinAbs = isWindowsAbsolutePath(inputPath);
|
|
94772
95487
|
if (isWinAbs) {
|
|
94773
|
-
resolved =
|
|
94774
|
-
} else if (
|
|
94775
|
-
resolved =
|
|
95488
|
+
resolved = path116.win32.resolve(inputPath);
|
|
95489
|
+
} else if (path116.isAbsolute(inputPath)) {
|
|
95490
|
+
resolved = path116.resolve(inputPath);
|
|
94776
95491
|
} else {
|
|
94777
|
-
resolved =
|
|
95492
|
+
resolved = path116.resolve(baseDir, inputPath);
|
|
94778
95493
|
}
|
|
94779
|
-
const workspaceResolved =
|
|
95494
|
+
const workspaceResolved = path116.resolve(workspaceDir);
|
|
94780
95495
|
let relative24;
|
|
94781
95496
|
if (isWinAbs) {
|
|
94782
|
-
relative24 =
|
|
95497
|
+
relative24 = path116.win32.relative(workspaceResolved, resolved);
|
|
94783
95498
|
} else {
|
|
94784
|
-
relative24 =
|
|
95499
|
+
relative24 = path116.relative(workspaceResolved, resolved);
|
|
94785
95500
|
}
|
|
94786
95501
|
if (relative24.startsWith("..")) {
|
|
94787
95502
|
return "path traversal detected";
|
|
@@ -94846,7 +95561,7 @@ async function runLintOnFiles(linter, files, workspaceDir) {
|
|
|
94846
95561
|
if (typeof file3 !== "string") {
|
|
94847
95562
|
continue;
|
|
94848
95563
|
}
|
|
94849
|
-
const resolvedPath =
|
|
95564
|
+
const resolvedPath = path116.resolve(file3);
|
|
94850
95565
|
const validationError = validatePath(resolvedPath, workspaceDir, workspaceDir);
|
|
94851
95566
|
if (validationError) {
|
|
94852
95567
|
continue;
|
|
@@ -95003,7 +95718,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
95003
95718
|
skippedFiles++;
|
|
95004
95719
|
continue;
|
|
95005
95720
|
}
|
|
95006
|
-
const resolvedPath =
|
|
95721
|
+
const resolvedPath = path116.resolve(file3);
|
|
95007
95722
|
const validationError = validatePath(resolvedPath, directory, directory);
|
|
95008
95723
|
if (validationError) {
|
|
95009
95724
|
skippedFiles++;
|
|
@@ -95021,14 +95736,14 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
95021
95736
|
};
|
|
95022
95737
|
}
|
|
95023
95738
|
for (const file3 of validatedFiles) {
|
|
95024
|
-
const ext =
|
|
95739
|
+
const ext = path116.extname(file3).toLowerCase();
|
|
95025
95740
|
if (DEFAULT_EXCLUDE_EXTENSIONS2.has(ext)) {
|
|
95026
95741
|
skippedFiles++;
|
|
95027
95742
|
continue;
|
|
95028
95743
|
}
|
|
95029
95744
|
let stat8;
|
|
95030
95745
|
try {
|
|
95031
|
-
stat8 =
|
|
95746
|
+
stat8 = fs90.statSync(file3);
|
|
95032
95747
|
} catch {
|
|
95033
95748
|
skippedFiles++;
|
|
95034
95749
|
continue;
|
|
@@ -95039,7 +95754,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
95039
95754
|
}
|
|
95040
95755
|
let content;
|
|
95041
95756
|
try {
|
|
95042
|
-
const buffer =
|
|
95757
|
+
const buffer = fs90.readFileSync(file3);
|
|
95043
95758
|
if (buffer.includes(0)) {
|
|
95044
95759
|
skippedFiles++;
|
|
95045
95760
|
continue;
|
|
@@ -95240,7 +95955,7 @@ function classifySastFindings(findings, changedLineRanges, directory) {
|
|
|
95240
95955
|
const preexistingFindings = [];
|
|
95241
95956
|
for (const finding of findings) {
|
|
95242
95957
|
const filePath = finding.location.file;
|
|
95243
|
-
const normalised =
|
|
95958
|
+
const normalised = path116.relative(directory, filePath).replace(/\\/g, "/");
|
|
95244
95959
|
const changedLines = changedLineRanges.get(normalised);
|
|
95245
95960
|
if (changedLines?.has(finding.location.line)) {
|
|
95246
95961
|
newFindings.push(finding);
|
|
@@ -95291,7 +96006,7 @@ async function runPreCheckBatch(input, workspaceDir, contextDir) {
|
|
|
95291
96006
|
warn(`pre_check_batch: Invalid file path: ${file3}`);
|
|
95292
96007
|
continue;
|
|
95293
96008
|
}
|
|
95294
|
-
changedFiles.push(
|
|
96009
|
+
changedFiles.push(path116.resolve(directory, file3));
|
|
95295
96010
|
}
|
|
95296
96011
|
if (changedFiles.length === 0) {
|
|
95297
96012
|
warn("pre_check_batch: No valid files after validation, skipping all tools (fail-closed)");
|
|
@@ -95492,7 +96207,7 @@ var pre_check_batch = createSwarmTool({
|
|
|
95492
96207
|
};
|
|
95493
96208
|
return JSON.stringify(errorResult, null, 2);
|
|
95494
96209
|
}
|
|
95495
|
-
const resolvedDirectory =
|
|
96210
|
+
const resolvedDirectory = path116.resolve(typedArgs.directory);
|
|
95496
96211
|
const workspaceAnchor = resolvedDirectory;
|
|
95497
96212
|
const dirError = validateDirectory2(resolvedDirectory, workspaceAnchor);
|
|
95498
96213
|
if (dirError) {
|
|
@@ -95533,7 +96248,7 @@ var pre_check_batch = createSwarmTool({
|
|
|
95533
96248
|
});
|
|
95534
96249
|
// src/tools/repo-map.ts
|
|
95535
96250
|
init_zod();
|
|
95536
|
-
import * as
|
|
96251
|
+
import * as path117 from "node:path";
|
|
95537
96252
|
init_path_security();
|
|
95538
96253
|
init_create_tool();
|
|
95539
96254
|
var VALID_ACTIONS = [
|
|
@@ -95558,7 +96273,7 @@ function validateFile(p) {
|
|
|
95558
96273
|
return "file contains control characters";
|
|
95559
96274
|
if (containsPathTraversal(p))
|
|
95560
96275
|
return "file contains path traversal";
|
|
95561
|
-
if (
|
|
96276
|
+
if (path117.isAbsolute(p) || /^[a-zA-Z]:[\\/]/.test(p)) {
|
|
95562
96277
|
return "file must be a workspace-relative path, not absolute";
|
|
95563
96278
|
}
|
|
95564
96279
|
return null;
|
|
@@ -95581,8 +96296,8 @@ function ok(action, payload) {
|
|
|
95581
96296
|
}
|
|
95582
96297
|
function toRelativeGraphPath(input, workspaceRoot) {
|
|
95583
96298
|
const normalized = input.replace(/\\/g, "/");
|
|
95584
|
-
if (
|
|
95585
|
-
const rel =
|
|
96299
|
+
if (path117.isAbsolute(normalized)) {
|
|
96300
|
+
const rel = path117.relative(workspaceRoot, normalized).replace(/\\/g, "/");
|
|
95586
96301
|
return normalizeGraphPath2(rel);
|
|
95587
96302
|
}
|
|
95588
96303
|
return normalizeGraphPath2(normalized);
|
|
@@ -95726,8 +96441,8 @@ var repo_map = createSwarmTool({
|
|
|
95726
96441
|
// src/tools/req-coverage.ts
|
|
95727
96442
|
init_zod();
|
|
95728
96443
|
init_create_tool();
|
|
95729
|
-
import * as
|
|
95730
|
-
import * as
|
|
96444
|
+
import * as fs91 from "node:fs";
|
|
96445
|
+
import * as path118 from "node:path";
|
|
95731
96446
|
var SPEC_FILE = ".swarm/spec.md";
|
|
95732
96447
|
var EVIDENCE_DIR4 = ".swarm/evidence";
|
|
95733
96448
|
var OBLIGATION_KEYWORDS = ["MUST", "SHOULD", "SHALL"];
|
|
@@ -95786,19 +96501,19 @@ function extractObligationAndText(id, lineText) {
|
|
|
95786
96501
|
var PHASE_TASK_ID_REGEX = /^\d+\.\d+(\.\d+)*$/;
|
|
95787
96502
|
function readTouchedFiles(evidenceDir, phase, cwd) {
|
|
95788
96503
|
const touchedFiles = new Set;
|
|
95789
|
-
if (!
|
|
96504
|
+
if (!fs91.existsSync(evidenceDir) || !fs91.statSync(evidenceDir).isDirectory()) {
|
|
95790
96505
|
return [];
|
|
95791
96506
|
}
|
|
95792
96507
|
let entries;
|
|
95793
96508
|
try {
|
|
95794
|
-
entries =
|
|
96509
|
+
entries = fs91.readdirSync(evidenceDir);
|
|
95795
96510
|
} catch {
|
|
95796
96511
|
return [];
|
|
95797
96512
|
}
|
|
95798
96513
|
for (const entry of entries) {
|
|
95799
|
-
const entryPath =
|
|
96514
|
+
const entryPath = path118.join(evidenceDir, entry);
|
|
95800
96515
|
try {
|
|
95801
|
-
const stat8 =
|
|
96516
|
+
const stat8 = fs91.statSync(entryPath);
|
|
95802
96517
|
if (!stat8.isDirectory()) {
|
|
95803
96518
|
continue;
|
|
95804
96519
|
}
|
|
@@ -95812,14 +96527,14 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
|
|
|
95812
96527
|
if (entryPhase !== String(phase)) {
|
|
95813
96528
|
continue;
|
|
95814
96529
|
}
|
|
95815
|
-
const evidenceFilePath =
|
|
96530
|
+
const evidenceFilePath = path118.join(entryPath, "evidence.json");
|
|
95816
96531
|
try {
|
|
95817
|
-
const resolvedPath =
|
|
95818
|
-
const evidenceDirResolved =
|
|
95819
|
-
if (!resolvedPath.startsWith(evidenceDirResolved +
|
|
96532
|
+
const resolvedPath = path118.resolve(evidenceFilePath);
|
|
96533
|
+
const evidenceDirResolved = path118.resolve(evidenceDir);
|
|
96534
|
+
if (!resolvedPath.startsWith(evidenceDirResolved + path118.sep)) {
|
|
95820
96535
|
continue;
|
|
95821
96536
|
}
|
|
95822
|
-
const stat8 =
|
|
96537
|
+
const stat8 = fs91.lstatSync(evidenceFilePath);
|
|
95823
96538
|
if (!stat8.isFile()) {
|
|
95824
96539
|
continue;
|
|
95825
96540
|
}
|
|
@@ -95831,7 +96546,7 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
|
|
|
95831
96546
|
}
|
|
95832
96547
|
let content;
|
|
95833
96548
|
try {
|
|
95834
|
-
content =
|
|
96549
|
+
content = fs91.readFileSync(evidenceFilePath, "utf-8");
|
|
95835
96550
|
} catch {
|
|
95836
96551
|
continue;
|
|
95837
96552
|
}
|
|
@@ -95850,7 +96565,7 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
|
|
|
95850
96565
|
if (Array.isArray(diffEntry.files_changed)) {
|
|
95851
96566
|
for (const file3 of diffEntry.files_changed) {
|
|
95852
96567
|
if (typeof file3 === "string") {
|
|
95853
|
-
touchedFiles.add(
|
|
96568
|
+
touchedFiles.add(path118.resolve(cwd, file3));
|
|
95854
96569
|
}
|
|
95855
96570
|
}
|
|
95856
96571
|
}
|
|
@@ -95863,12 +96578,12 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
|
|
|
95863
96578
|
}
|
|
95864
96579
|
function searchFileForKeywords(filePath, keywords, cwd) {
|
|
95865
96580
|
try {
|
|
95866
|
-
const resolvedPath =
|
|
95867
|
-
const cwdResolved =
|
|
96581
|
+
const resolvedPath = path118.resolve(filePath);
|
|
96582
|
+
const cwdResolved = path118.resolve(cwd);
|
|
95868
96583
|
if (!resolvedPath.startsWith(cwdResolved)) {
|
|
95869
96584
|
return false;
|
|
95870
96585
|
}
|
|
95871
|
-
const content =
|
|
96586
|
+
const content = fs91.readFileSync(resolvedPath, "utf-8");
|
|
95872
96587
|
for (const keyword of keywords) {
|
|
95873
96588
|
const regex = new RegExp(`\\b${keyword}\\b`, "i");
|
|
95874
96589
|
if (regex.test(content)) {
|
|
@@ -95998,10 +96713,10 @@ var req_coverage = createSwarmTool({
|
|
|
95998
96713
|
}, null, 2);
|
|
95999
96714
|
}
|
|
96000
96715
|
const cwd = inputDirectory || directory;
|
|
96001
|
-
const specPath =
|
|
96716
|
+
const specPath = path118.join(cwd, SPEC_FILE);
|
|
96002
96717
|
let specContent;
|
|
96003
96718
|
try {
|
|
96004
|
-
specContent =
|
|
96719
|
+
specContent = fs91.readFileSync(specPath, "utf-8");
|
|
96005
96720
|
} catch (readError) {
|
|
96006
96721
|
return JSON.stringify({
|
|
96007
96722
|
success: false,
|
|
@@ -96025,7 +96740,7 @@ var req_coverage = createSwarmTool({
|
|
|
96025
96740
|
message: "No FR requirements found in spec.md"
|
|
96026
96741
|
}, null, 2);
|
|
96027
96742
|
}
|
|
96028
|
-
const evidenceDir =
|
|
96743
|
+
const evidenceDir = path118.join(cwd, EVIDENCE_DIR4);
|
|
96029
96744
|
const touchedFiles = readTouchedFiles(evidenceDir, phase, cwd);
|
|
96030
96745
|
const analyzedRequirements = [];
|
|
96031
96746
|
let coveredCount = 0;
|
|
@@ -96051,12 +96766,12 @@ var req_coverage = createSwarmTool({
|
|
|
96051
96766
|
requirements: analyzedRequirements
|
|
96052
96767
|
};
|
|
96053
96768
|
const reportFilename = `req-coverage-phase-${phase}.json`;
|
|
96054
|
-
const reportPath =
|
|
96769
|
+
const reportPath = path118.join(evidenceDir, reportFilename);
|
|
96055
96770
|
try {
|
|
96056
|
-
if (!
|
|
96057
|
-
|
|
96771
|
+
if (!fs91.existsSync(evidenceDir)) {
|
|
96772
|
+
fs91.mkdirSync(evidenceDir, { recursive: true });
|
|
96058
96773
|
}
|
|
96059
|
-
|
|
96774
|
+
fs91.writeFileSync(reportPath, JSON.stringify(result, null, 2), "utf-8");
|
|
96060
96775
|
} catch (writeError) {
|
|
96061
96776
|
console.warn(`Failed to write coverage report: ${writeError instanceof Error ? writeError.message : String(writeError)}`);
|
|
96062
96777
|
}
|
|
@@ -96137,9 +96852,9 @@ init_zod();
|
|
|
96137
96852
|
init_plan_schema();
|
|
96138
96853
|
init_qa_gate_profile();
|
|
96139
96854
|
init_file_locks();
|
|
96140
|
-
import * as
|
|
96141
|
-
import * as
|
|
96142
|
-
import * as
|
|
96855
|
+
import * as crypto11 from "node:crypto";
|
|
96856
|
+
import * as fs92 from "node:fs";
|
|
96857
|
+
import * as path119 from "node:path";
|
|
96143
96858
|
init_ledger();
|
|
96144
96859
|
init_manager();
|
|
96145
96860
|
init_state();
|
|
@@ -96217,17 +96932,17 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
96217
96932
|
};
|
|
96218
96933
|
}
|
|
96219
96934
|
if (args2.working_directory && fallbackDir) {
|
|
96220
|
-
const resolvedTarget =
|
|
96221
|
-
const resolvedRoot =
|
|
96935
|
+
const resolvedTarget = path119.resolve(args2.working_directory);
|
|
96936
|
+
const resolvedRoot = path119.resolve(fallbackDir);
|
|
96222
96937
|
let fallbackExists = false;
|
|
96223
96938
|
try {
|
|
96224
|
-
|
|
96939
|
+
fs92.accessSync(resolvedRoot, fs92.constants.F_OK);
|
|
96225
96940
|
fallbackExists = true;
|
|
96226
96941
|
} catch {
|
|
96227
96942
|
fallbackExists = false;
|
|
96228
96943
|
}
|
|
96229
96944
|
if (fallbackExists) {
|
|
96230
|
-
const isSubdirectory = resolvedTarget.startsWith(resolvedRoot +
|
|
96945
|
+
const isSubdirectory = resolvedTarget.startsWith(resolvedRoot + path119.sep);
|
|
96231
96946
|
if (isSubdirectory) {
|
|
96232
96947
|
return {
|
|
96233
96948
|
success: false,
|
|
@@ -96243,12 +96958,12 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
96243
96958
|
let specMtime;
|
|
96244
96959
|
let specHash;
|
|
96245
96960
|
if (process.env.SWARM_SKIP_SPEC_GATE !== "1") {
|
|
96246
|
-
const specPath =
|
|
96961
|
+
const specPath = path119.join(targetWorkspace, ".swarm", "spec.md");
|
|
96247
96962
|
try {
|
|
96248
|
-
const stat8 = await
|
|
96963
|
+
const stat8 = await fs92.promises.stat(specPath);
|
|
96249
96964
|
specMtime = stat8.mtime.toISOString();
|
|
96250
|
-
const content = await
|
|
96251
|
-
specHash =
|
|
96965
|
+
const content = await fs92.promises.readFile(specPath, "utf8");
|
|
96966
|
+
specHash = crypto11.createHash("sha256").update(content).digest("hex");
|
|
96252
96967
|
} catch {
|
|
96253
96968
|
return {
|
|
96254
96969
|
success: false,
|
|
@@ -96259,10 +96974,10 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
96259
96974
|
}
|
|
96260
96975
|
}
|
|
96261
96976
|
if (process.env.SWARM_SKIP_GATE_SELECTION !== "1") {
|
|
96262
|
-
const contextPath =
|
|
96977
|
+
const contextPath = path119.join(targetWorkspace, ".swarm", "context.md");
|
|
96263
96978
|
let contextContent = "";
|
|
96264
96979
|
try {
|
|
96265
|
-
contextContent = await
|
|
96980
|
+
contextContent = await fs92.promises.readFile(contextPath, "utf8");
|
|
96266
96981
|
} catch {}
|
|
96267
96982
|
const hasPendingSection = contextContent.includes("## Pending QA Gate Selection");
|
|
96268
96983
|
if (!hasPendingSection) {
|
|
@@ -96516,14 +97231,14 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
96516
97231
|
}
|
|
96517
97232
|
await writeCheckpoint(dir).catch(() => {});
|
|
96518
97233
|
try {
|
|
96519
|
-
const markerPath =
|
|
97234
|
+
const markerPath = path119.join(dir, ".swarm", ".plan-write-marker");
|
|
96520
97235
|
const marker = JSON.stringify({
|
|
96521
97236
|
source: "save_plan",
|
|
96522
97237
|
timestamp: new Date().toISOString(),
|
|
96523
97238
|
phases_count: plan.phases.length,
|
|
96524
97239
|
tasks_count: tasksCount
|
|
96525
97240
|
});
|
|
96526
|
-
await
|
|
97241
|
+
await fs92.promises.writeFile(markerPath, marker, "utf8");
|
|
96527
97242
|
} catch {}
|
|
96528
97243
|
const warnings = [];
|
|
96529
97244
|
let criticReviewFound = false;
|
|
@@ -96539,7 +97254,7 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
96539
97254
|
return {
|
|
96540
97255
|
success: true,
|
|
96541
97256
|
message: "Plan saved successfully",
|
|
96542
|
-
plan_path:
|
|
97257
|
+
plan_path: path119.join(dir, ".swarm", "plan.json"),
|
|
96543
97258
|
phases_count: plan.phases.length,
|
|
96544
97259
|
tasks_count: tasksCount,
|
|
96545
97260
|
...resolvedProfile !== undefined ? { execution_profile: resolvedProfile } : {},
|
|
@@ -96603,8 +97318,8 @@ var save_plan = createSwarmTool({
|
|
|
96603
97318
|
// src/tools/sbom-generate.ts
|
|
96604
97319
|
init_zod();
|
|
96605
97320
|
init_manager2();
|
|
96606
|
-
import * as
|
|
96607
|
-
import * as
|
|
97321
|
+
import * as fs93 from "node:fs";
|
|
97322
|
+
import * as path120 from "node:path";
|
|
96608
97323
|
|
|
96609
97324
|
// src/sbom/detectors/index.ts
|
|
96610
97325
|
init_utils();
|
|
@@ -97452,9 +98167,9 @@ function findManifestFiles(rootDir) {
|
|
|
97452
98167
|
const patterns = [...new Set(allDetectors.flatMap((d) => d.patterns))];
|
|
97453
98168
|
function searchDir(dir) {
|
|
97454
98169
|
try {
|
|
97455
|
-
const entries =
|
|
98170
|
+
const entries = fs93.readdirSync(dir, { withFileTypes: true });
|
|
97456
98171
|
for (const entry of entries) {
|
|
97457
|
-
const fullPath =
|
|
98172
|
+
const fullPath = path120.join(dir, entry.name);
|
|
97458
98173
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "target") {
|
|
97459
98174
|
continue;
|
|
97460
98175
|
}
|
|
@@ -97463,7 +98178,7 @@ function findManifestFiles(rootDir) {
|
|
|
97463
98178
|
} else if (entry.isFile()) {
|
|
97464
98179
|
for (const pattern of patterns) {
|
|
97465
98180
|
if (simpleGlobToRegex(pattern).test(entry.name)) {
|
|
97466
|
-
manifestFiles.push(
|
|
98181
|
+
manifestFiles.push(path120.relative(rootDir, fullPath));
|
|
97467
98182
|
break;
|
|
97468
98183
|
}
|
|
97469
98184
|
}
|
|
@@ -97479,13 +98194,13 @@ function findManifestFilesInDirs(directories, workingDir) {
|
|
|
97479
98194
|
const patterns = [...new Set(allDetectors.flatMap((d) => d.patterns))];
|
|
97480
98195
|
for (const dir of directories) {
|
|
97481
98196
|
try {
|
|
97482
|
-
const entries =
|
|
98197
|
+
const entries = fs93.readdirSync(dir, { withFileTypes: true });
|
|
97483
98198
|
for (const entry of entries) {
|
|
97484
|
-
const fullPath =
|
|
98199
|
+
const fullPath = path120.join(dir, entry.name);
|
|
97485
98200
|
if (entry.isFile()) {
|
|
97486
98201
|
for (const pattern of patterns) {
|
|
97487
98202
|
if (simpleGlobToRegex(pattern).test(entry.name)) {
|
|
97488
|
-
found.push(
|
|
98203
|
+
found.push(path120.relative(workingDir, fullPath));
|
|
97489
98204
|
break;
|
|
97490
98205
|
}
|
|
97491
98206
|
}
|
|
@@ -97498,11 +98213,11 @@ function findManifestFilesInDirs(directories, workingDir) {
|
|
|
97498
98213
|
function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
|
|
97499
98214
|
const dirs = new Set;
|
|
97500
98215
|
for (const file3 of changedFiles) {
|
|
97501
|
-
let currentDir =
|
|
98216
|
+
let currentDir = path120.dirname(file3);
|
|
97502
98217
|
while (true) {
|
|
97503
|
-
if (currentDir && currentDir !== "." && currentDir !==
|
|
97504
|
-
dirs.add(
|
|
97505
|
-
const parent =
|
|
98218
|
+
if (currentDir && currentDir !== "." && currentDir !== path120.sep) {
|
|
98219
|
+
dirs.add(path120.join(workingDir, currentDir));
|
|
98220
|
+
const parent = path120.dirname(currentDir);
|
|
97506
98221
|
if (parent === currentDir)
|
|
97507
98222
|
break;
|
|
97508
98223
|
currentDir = parent;
|
|
@@ -97516,7 +98231,7 @@ function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
|
|
|
97516
98231
|
}
|
|
97517
98232
|
function ensureOutputDir(outputDir) {
|
|
97518
98233
|
try {
|
|
97519
|
-
|
|
98234
|
+
fs93.mkdirSync(outputDir, { recursive: true });
|
|
97520
98235
|
} catch (error93) {
|
|
97521
98236
|
if (!error93 || error93.code !== "EEXIST") {
|
|
97522
98237
|
throw error93;
|
|
@@ -97586,7 +98301,7 @@ var sbom_generate = createSwarmTool({
|
|
|
97586
98301
|
const changedFiles = obj.changed_files;
|
|
97587
98302
|
const relativeOutputDir = obj.output_dir || DEFAULT_OUTPUT_DIR;
|
|
97588
98303
|
const workingDir = directory;
|
|
97589
|
-
const outputDir =
|
|
98304
|
+
const outputDir = path120.isAbsolute(relativeOutputDir) ? relativeOutputDir : path120.join(workingDir, relativeOutputDir);
|
|
97590
98305
|
let manifestFiles = [];
|
|
97591
98306
|
if (scope === "all") {
|
|
97592
98307
|
manifestFiles = findManifestFiles(workingDir);
|
|
@@ -97609,11 +98324,11 @@ var sbom_generate = createSwarmTool({
|
|
|
97609
98324
|
const processedFiles = [];
|
|
97610
98325
|
for (const manifestFile of manifestFiles) {
|
|
97611
98326
|
try {
|
|
97612
|
-
const fullPath =
|
|
97613
|
-
if (!
|
|
98327
|
+
const fullPath = path120.isAbsolute(manifestFile) ? manifestFile : path120.join(workingDir, manifestFile);
|
|
98328
|
+
if (!fs93.existsSync(fullPath)) {
|
|
97614
98329
|
continue;
|
|
97615
98330
|
}
|
|
97616
|
-
const content =
|
|
98331
|
+
const content = fs93.readFileSync(fullPath, "utf-8");
|
|
97617
98332
|
const components = detectComponents(manifestFile, content);
|
|
97618
98333
|
processedFiles.push(manifestFile);
|
|
97619
98334
|
if (components.length > 0) {
|
|
@@ -97626,8 +98341,8 @@ var sbom_generate = createSwarmTool({
|
|
|
97626
98341
|
const bom = generateCycloneDX(allComponents);
|
|
97627
98342
|
const bomJson = serializeCycloneDX(bom);
|
|
97628
98343
|
const filename = generateSbomFilename();
|
|
97629
|
-
const outputPath =
|
|
97630
|
-
|
|
98344
|
+
const outputPath = path120.join(outputDir, filename);
|
|
98345
|
+
fs93.writeFileSync(outputPath, bomJson, "utf-8");
|
|
97631
98346
|
const verdict = processedFiles.length > 0 ? "pass" : "pass";
|
|
97632
98347
|
try {
|
|
97633
98348
|
const timestamp = new Date().toISOString();
|
|
@@ -97669,8 +98384,8 @@ var sbom_generate = createSwarmTool({
|
|
|
97669
98384
|
// src/tools/schema-drift.ts
|
|
97670
98385
|
init_zod();
|
|
97671
98386
|
init_create_tool();
|
|
97672
|
-
import * as
|
|
97673
|
-
import * as
|
|
98387
|
+
import * as fs94 from "node:fs";
|
|
98388
|
+
import * as path121 from "node:path";
|
|
97674
98389
|
var SPEC_CANDIDATES = [
|
|
97675
98390
|
"openapi.json",
|
|
97676
98391
|
"openapi.yaml",
|
|
@@ -97702,28 +98417,28 @@ function normalizePath4(p) {
|
|
|
97702
98417
|
}
|
|
97703
98418
|
function discoverSpecFile(cwd, specFileArg) {
|
|
97704
98419
|
if (specFileArg) {
|
|
97705
|
-
const resolvedPath =
|
|
97706
|
-
const normalizedCwd = cwd.endsWith(
|
|
98420
|
+
const resolvedPath = path121.resolve(cwd, specFileArg);
|
|
98421
|
+
const normalizedCwd = cwd.endsWith(path121.sep) ? cwd : cwd + path121.sep;
|
|
97707
98422
|
if (!resolvedPath.startsWith(normalizedCwd) && resolvedPath !== cwd) {
|
|
97708
98423
|
throw new Error("Invalid spec_file: path traversal detected");
|
|
97709
98424
|
}
|
|
97710
|
-
const ext =
|
|
98425
|
+
const ext = path121.extname(resolvedPath).toLowerCase();
|
|
97711
98426
|
if (!ALLOWED_EXTENSIONS.includes(ext)) {
|
|
97712
98427
|
throw new Error(`Invalid spec_file: must end in .json, .yaml, or .yml, got ${ext}`);
|
|
97713
98428
|
}
|
|
97714
|
-
const stats =
|
|
98429
|
+
const stats = fs94.statSync(resolvedPath);
|
|
97715
98430
|
if (stats.size > MAX_SPEC_SIZE) {
|
|
97716
98431
|
throw new Error(`Invalid spec_file: file exceeds ${MAX_SPEC_SIZE / 1024 / 1024}MB limit`);
|
|
97717
98432
|
}
|
|
97718
|
-
if (!
|
|
98433
|
+
if (!fs94.existsSync(resolvedPath)) {
|
|
97719
98434
|
throw new Error(`Spec file not found: ${resolvedPath}`);
|
|
97720
98435
|
}
|
|
97721
98436
|
return resolvedPath;
|
|
97722
98437
|
}
|
|
97723
98438
|
for (const candidate of SPEC_CANDIDATES) {
|
|
97724
|
-
const candidatePath =
|
|
97725
|
-
if (
|
|
97726
|
-
const stats =
|
|
98439
|
+
const candidatePath = path121.resolve(cwd, candidate);
|
|
98440
|
+
if (fs94.existsSync(candidatePath)) {
|
|
98441
|
+
const stats = fs94.statSync(candidatePath);
|
|
97727
98442
|
if (stats.size <= MAX_SPEC_SIZE) {
|
|
97728
98443
|
return candidatePath;
|
|
97729
98444
|
}
|
|
@@ -97732,8 +98447,8 @@ function discoverSpecFile(cwd, specFileArg) {
|
|
|
97732
98447
|
return null;
|
|
97733
98448
|
}
|
|
97734
98449
|
function parseSpec(specFile) {
|
|
97735
|
-
const content =
|
|
97736
|
-
const ext =
|
|
98450
|
+
const content = fs94.readFileSync(specFile, "utf-8");
|
|
98451
|
+
const ext = path121.extname(specFile).toLowerCase();
|
|
97737
98452
|
if (ext === ".json") {
|
|
97738
98453
|
return parseJsonSpec(content);
|
|
97739
98454
|
}
|
|
@@ -97804,12 +98519,12 @@ function extractRoutes(cwd) {
|
|
|
97804
98519
|
function walkDir(dir) {
|
|
97805
98520
|
let entries;
|
|
97806
98521
|
try {
|
|
97807
|
-
entries =
|
|
98522
|
+
entries = fs94.readdirSync(dir, { withFileTypes: true });
|
|
97808
98523
|
} catch {
|
|
97809
98524
|
return;
|
|
97810
98525
|
}
|
|
97811
98526
|
for (const entry of entries) {
|
|
97812
|
-
const fullPath =
|
|
98527
|
+
const fullPath = path121.join(dir, entry.name);
|
|
97813
98528
|
if (entry.isSymbolicLink()) {
|
|
97814
98529
|
continue;
|
|
97815
98530
|
}
|
|
@@ -97819,7 +98534,7 @@ function extractRoutes(cwd) {
|
|
|
97819
98534
|
}
|
|
97820
98535
|
walkDir(fullPath);
|
|
97821
98536
|
} else if (entry.isFile()) {
|
|
97822
|
-
const ext =
|
|
98537
|
+
const ext = path121.extname(entry.name).toLowerCase();
|
|
97823
98538
|
const baseName = entry.name.toLowerCase();
|
|
97824
98539
|
if (![".ts", ".js", ".mjs"].includes(ext)) {
|
|
97825
98540
|
continue;
|
|
@@ -97837,7 +98552,7 @@ function extractRoutes(cwd) {
|
|
|
97837
98552
|
}
|
|
97838
98553
|
function extractRoutesFromFile(filePath) {
|
|
97839
98554
|
const routes = [];
|
|
97840
|
-
const content =
|
|
98555
|
+
const content = fs94.readFileSync(filePath, "utf-8");
|
|
97841
98556
|
const lines = content.split(/\r?\n/);
|
|
97842
98557
|
const expressRegex = /(?:app|router|server|express)\.(get|post|put|patch|delete|options|head)\s*\(\s*['"`]([^'"`]+)['"`]/g;
|
|
97843
98558
|
const flaskRegex = /@(?:app|blueprint|bp)\.route\s*\(\s*['"]([^'"]+)['"]/g;
|
|
@@ -97986,8 +98701,8 @@ init_zod();
|
|
|
97986
98701
|
init_bun_compat();
|
|
97987
98702
|
init_path_security();
|
|
97988
98703
|
init_create_tool();
|
|
97989
|
-
import * as
|
|
97990
|
-
import * as
|
|
98704
|
+
import * as fs95 from "node:fs";
|
|
98705
|
+
import * as path122 from "node:path";
|
|
97991
98706
|
var DEFAULT_MAX_RESULTS = 100;
|
|
97992
98707
|
var DEFAULT_MAX_LINES = 200;
|
|
97993
98708
|
var REGEX_TIMEOUT_MS = 5000;
|
|
@@ -98023,11 +98738,11 @@ function containsWindowsAttacks3(str) {
|
|
|
98023
98738
|
}
|
|
98024
98739
|
function isPathInWorkspace3(filePath, workspace) {
|
|
98025
98740
|
try {
|
|
98026
|
-
const resolvedPath =
|
|
98027
|
-
const realWorkspace =
|
|
98028
|
-
const realResolvedPath =
|
|
98029
|
-
const relativePath =
|
|
98030
|
-
if (relativePath.startsWith("..") ||
|
|
98741
|
+
const resolvedPath = path122.resolve(workspace, filePath);
|
|
98742
|
+
const realWorkspace = fs95.realpathSync(workspace);
|
|
98743
|
+
const realResolvedPath = fs95.realpathSync(resolvedPath);
|
|
98744
|
+
const relativePath = path122.relative(realWorkspace, realResolvedPath);
|
|
98745
|
+
if (relativePath.startsWith("..") || path122.isAbsolute(relativePath)) {
|
|
98031
98746
|
return false;
|
|
98032
98747
|
}
|
|
98033
98748
|
return true;
|
|
@@ -98040,12 +98755,12 @@ function validatePathForRead2(filePath, workspace) {
|
|
|
98040
98755
|
}
|
|
98041
98756
|
function findRgInEnvPath() {
|
|
98042
98757
|
const searchPath = process.env.PATH ?? "";
|
|
98043
|
-
for (const dir of searchPath.split(
|
|
98758
|
+
for (const dir of searchPath.split(path122.delimiter)) {
|
|
98044
98759
|
if (!dir)
|
|
98045
98760
|
continue;
|
|
98046
98761
|
const isWindows = process.platform === "win32";
|
|
98047
|
-
const candidate =
|
|
98048
|
-
if (
|
|
98762
|
+
const candidate = path122.join(dir, isWindows ? "rg.exe" : "rg");
|
|
98763
|
+
if (fs95.existsSync(candidate))
|
|
98049
98764
|
return candidate;
|
|
98050
98765
|
}
|
|
98051
98766
|
return null;
|
|
@@ -98172,10 +98887,10 @@ function collectFiles(dir, workspace, includeGlobs, excludeGlobs) {
|
|
|
98172
98887
|
return files;
|
|
98173
98888
|
}
|
|
98174
98889
|
try {
|
|
98175
|
-
const entries =
|
|
98890
|
+
const entries = fs95.readdirSync(dir, { withFileTypes: true });
|
|
98176
98891
|
for (const entry of entries) {
|
|
98177
|
-
const fullPath =
|
|
98178
|
-
const relativePath =
|
|
98892
|
+
const fullPath = path122.join(dir, entry.name);
|
|
98893
|
+
const relativePath = path122.relative(workspace, fullPath);
|
|
98179
98894
|
if (!validatePathForRead2(fullPath, workspace)) {
|
|
98180
98895
|
continue;
|
|
98181
98896
|
}
|
|
@@ -98216,13 +98931,13 @@ async function fallbackSearch(opts) {
|
|
|
98216
98931
|
const matches = [];
|
|
98217
98932
|
let total = 0;
|
|
98218
98933
|
for (const file3 of files) {
|
|
98219
|
-
const fullPath =
|
|
98934
|
+
const fullPath = path122.join(opts.workspace, file3);
|
|
98220
98935
|
if (!validatePathForRead2(fullPath, opts.workspace)) {
|
|
98221
98936
|
continue;
|
|
98222
98937
|
}
|
|
98223
98938
|
let stats;
|
|
98224
98939
|
try {
|
|
98225
|
-
stats =
|
|
98940
|
+
stats = fs95.statSync(fullPath);
|
|
98226
98941
|
if (stats.size > MAX_FILE_SIZE_BYTES10) {
|
|
98227
98942
|
continue;
|
|
98228
98943
|
}
|
|
@@ -98231,7 +98946,7 @@ async function fallbackSearch(opts) {
|
|
|
98231
98946
|
}
|
|
98232
98947
|
let content;
|
|
98233
98948
|
try {
|
|
98234
|
-
content =
|
|
98949
|
+
content = fs95.readFileSync(fullPath, "utf-8");
|
|
98235
98950
|
} catch {
|
|
98236
98951
|
continue;
|
|
98237
98952
|
}
|
|
@@ -98343,7 +99058,7 @@ var search = createSwarmTool({
|
|
|
98343
99058
|
message: "Exclude pattern contains invalid Windows-specific sequence"
|
|
98344
99059
|
}, null, 2);
|
|
98345
99060
|
}
|
|
98346
|
-
if (!
|
|
99061
|
+
if (!fs95.existsSync(directory)) {
|
|
98347
99062
|
return JSON.stringify({
|
|
98348
99063
|
error: true,
|
|
98349
99064
|
type: "unknown",
|
|
@@ -98584,7 +99299,7 @@ init_config();
|
|
|
98584
99299
|
init_schema();
|
|
98585
99300
|
init_create_tool();
|
|
98586
99301
|
import { mkdir as mkdir19, rename as rename8, writeFile as writeFile15 } from "node:fs/promises";
|
|
98587
|
-
import * as
|
|
99302
|
+
import * as path123 from "node:path";
|
|
98588
99303
|
var MAX_SPEC_BYTES = 256 * 1024;
|
|
98589
99304
|
var spec_write = createSwarmTool({
|
|
98590
99305
|
description: "Write the canonical project spec to .swarm/spec.md. Atomic write, size-bounded (256 KiB), heading-required. Honors spec_writer.allow_spec_write.",
|
|
@@ -98625,14 +99340,14 @@ var spec_write = createSwarmTool({
|
|
|
98625
99340
|
reason: 'spec must contain at least one top-level "# Heading"'
|
|
98626
99341
|
}, null, 2);
|
|
98627
99342
|
}
|
|
98628
|
-
const target =
|
|
98629
|
-
await mkdir19(
|
|
99343
|
+
const target = path123.join(directory, ".swarm", "spec.md");
|
|
99344
|
+
await mkdir19(path123.dirname(target), { recursive: true });
|
|
98630
99345
|
const tmp = `${target}.tmp-${process.pid}-${Date.now()}`;
|
|
98631
99346
|
let finalContent = content;
|
|
98632
99347
|
if (mode === "append") {
|
|
98633
99348
|
try {
|
|
98634
|
-
const
|
|
98635
|
-
const prior = await
|
|
99349
|
+
const fs96 = await import("node:fs/promises");
|
|
99350
|
+
const prior = await fs96.readFile(target, "utf-8");
|
|
98636
99351
|
finalContent = `${prior.replace(/\s+$/, "")}
|
|
98637
99352
|
|
|
98638
99353
|
${content}
|
|
@@ -98654,14 +99369,14 @@ ${content}
|
|
|
98654
99369
|
init_zod();
|
|
98655
99370
|
init_loader();
|
|
98656
99371
|
import {
|
|
98657
|
-
existsSync as
|
|
98658
|
-
mkdirSync as
|
|
98659
|
-
readFileSync as
|
|
98660
|
-
renameSync as
|
|
99372
|
+
existsSync as existsSync72,
|
|
99373
|
+
mkdirSync as mkdirSync31,
|
|
99374
|
+
readFileSync as readFileSync62,
|
|
99375
|
+
renameSync as renameSync20,
|
|
98661
99376
|
unlinkSync as unlinkSync15,
|
|
98662
|
-
writeFileSync as
|
|
99377
|
+
writeFileSync as writeFileSync24
|
|
98663
99378
|
} from "node:fs";
|
|
98664
|
-
import
|
|
99379
|
+
import path124 from "node:path";
|
|
98665
99380
|
init_create_tool();
|
|
98666
99381
|
init_resolve_working_directory();
|
|
98667
99382
|
var VerdictSchema2 = exports_external.object({
|
|
@@ -98791,9 +99506,9 @@ var submit_phase_council_verdicts = createSwarmTool({
|
|
|
98791
99506
|
}
|
|
98792
99507
|
});
|
|
98793
99508
|
function getPhaseMutationGapFinding(phaseNumber, workingDir) {
|
|
98794
|
-
const mutationGatePath =
|
|
99509
|
+
const mutationGatePath = path124.join(workingDir, ".swarm", "evidence", String(phaseNumber), "mutation-gate.json");
|
|
98795
99510
|
try {
|
|
98796
|
-
const raw =
|
|
99511
|
+
const raw = readFileSync62(mutationGatePath, "utf-8");
|
|
98797
99512
|
const parsed = JSON.parse(raw);
|
|
98798
99513
|
const gateEntry = (parsed.entries ?? []).find((entry) => entry?.type === "mutation-gate");
|
|
98799
99514
|
if (!gateEntry) {
|
|
@@ -98853,9 +99568,9 @@ function getPhaseMutationGapFinding(phaseNumber, workingDir) {
|
|
|
98853
99568
|
}
|
|
98854
99569
|
}
|
|
98855
99570
|
function writePhaseCouncilEvidence(workingDir, synthesis) {
|
|
98856
|
-
const evidenceDir =
|
|
98857
|
-
|
|
98858
|
-
const evidenceFile =
|
|
99571
|
+
const evidenceDir = path124.join(workingDir, ".swarm", "evidence", String(synthesis.phaseNumber));
|
|
99572
|
+
mkdirSync31(evidenceDir, { recursive: true });
|
|
99573
|
+
const evidenceFile = path124.join(evidenceDir, "phase-council.json");
|
|
98859
99574
|
const evidenceBundle = {
|
|
98860
99575
|
entries: [
|
|
98861
99576
|
{
|
|
@@ -98888,10 +99603,10 @@ function writePhaseCouncilEvidence(workingDir, synthesis) {
|
|
|
98888
99603
|
};
|
|
98889
99604
|
const tempFile = `${evidenceFile}.tmp-${Date.now()}`;
|
|
98890
99605
|
try {
|
|
98891
|
-
|
|
98892
|
-
|
|
99606
|
+
writeFileSync24(tempFile, JSON.stringify(evidenceBundle, null, 2), "utf-8");
|
|
99607
|
+
renameSync20(tempFile, evidenceFile);
|
|
98893
99608
|
} finally {
|
|
98894
|
-
if (
|
|
99609
|
+
if (existsSync72(tempFile)) {
|
|
98895
99610
|
unlinkSync15(tempFile);
|
|
98896
99611
|
}
|
|
98897
99612
|
}
|
|
@@ -98940,8 +99655,8 @@ function createSwarmCommandTool(agents) {
|
|
|
98940
99655
|
init_zod();
|
|
98941
99656
|
init_path_security();
|
|
98942
99657
|
init_create_tool();
|
|
98943
|
-
import * as
|
|
98944
|
-
import * as
|
|
99658
|
+
import * as fs96 from "node:fs";
|
|
99659
|
+
import * as path125 from "node:path";
|
|
98945
99660
|
var WINDOWS_RESERVED_NAMES4 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
|
|
98946
99661
|
function containsWindowsAttacks4(str) {
|
|
98947
99662
|
if (/:[^\\/]/.test(str))
|
|
@@ -98955,14 +99670,14 @@ function containsWindowsAttacks4(str) {
|
|
|
98955
99670
|
}
|
|
98956
99671
|
function isPathInWorkspace4(filePath, workspace) {
|
|
98957
99672
|
try {
|
|
98958
|
-
const resolvedPath =
|
|
98959
|
-
if (!
|
|
99673
|
+
const resolvedPath = path125.resolve(workspace, filePath);
|
|
99674
|
+
if (!fs96.existsSync(resolvedPath)) {
|
|
98960
99675
|
return true;
|
|
98961
99676
|
}
|
|
98962
|
-
const realWorkspace =
|
|
98963
|
-
const realResolvedPath =
|
|
98964
|
-
const relativePath =
|
|
98965
|
-
if (relativePath.startsWith("..") ||
|
|
99677
|
+
const realWorkspace = fs96.realpathSync(workspace);
|
|
99678
|
+
const realResolvedPath = fs96.realpathSync(resolvedPath);
|
|
99679
|
+
const relativePath = path125.relative(realWorkspace, realResolvedPath);
|
|
99680
|
+
if (relativePath.startsWith("..") || path125.isAbsolute(relativePath)) {
|
|
98966
99681
|
return false;
|
|
98967
99682
|
}
|
|
98968
99683
|
return true;
|
|
@@ -99134,7 +99849,7 @@ var suggestPatch = createSwarmTool({
|
|
|
99134
99849
|
message: "changes cannot be empty"
|
|
99135
99850
|
}, null, 2);
|
|
99136
99851
|
}
|
|
99137
|
-
if (!
|
|
99852
|
+
if (!fs96.existsSync(directory)) {
|
|
99138
99853
|
return JSON.stringify({
|
|
99139
99854
|
success: false,
|
|
99140
99855
|
error: true,
|
|
@@ -99170,8 +99885,8 @@ var suggestPatch = createSwarmTool({
|
|
|
99170
99885
|
});
|
|
99171
99886
|
continue;
|
|
99172
99887
|
}
|
|
99173
|
-
const fullPath =
|
|
99174
|
-
if (!
|
|
99888
|
+
const fullPath = path125.resolve(directory, change.file);
|
|
99889
|
+
if (!fs96.existsSync(fullPath)) {
|
|
99175
99890
|
errors5.push({
|
|
99176
99891
|
success: false,
|
|
99177
99892
|
error: true,
|
|
@@ -99185,7 +99900,7 @@ var suggestPatch = createSwarmTool({
|
|
|
99185
99900
|
}
|
|
99186
99901
|
let content;
|
|
99187
99902
|
try {
|
|
99188
|
-
content =
|
|
99903
|
+
content = fs96.readFileSync(fullPath, "utf-8");
|
|
99189
99904
|
} catch (err3) {
|
|
99190
99905
|
errors5.push({
|
|
99191
99906
|
success: false,
|
|
@@ -99473,12 +100188,12 @@ var lean_turbo_acquire_locks = createSwarmTool({
|
|
|
99473
100188
|
// src/tools/lean-turbo-plan-lanes.ts
|
|
99474
100189
|
init_zod();
|
|
99475
100190
|
init_constants();
|
|
99476
|
-
import * as
|
|
99477
|
-
import * as
|
|
100191
|
+
import * as fs98 from "node:fs";
|
|
100192
|
+
import * as path127 from "node:path";
|
|
99478
100193
|
|
|
99479
100194
|
// src/turbo/lean/conflicts.ts
|
|
99480
|
-
import * as
|
|
99481
|
-
import * as
|
|
100195
|
+
import * as fs97 from "node:fs";
|
|
100196
|
+
import * as path126 from "node:path";
|
|
99482
100197
|
var DEFAULT_GLOBAL_FILES = [
|
|
99483
100198
|
"package.json",
|
|
99484
100199
|
"package-lock.json",
|
|
@@ -99605,12 +100320,12 @@ function isProtectedPath2(normalizedPath) {
|
|
|
99605
100320
|
return false;
|
|
99606
100321
|
}
|
|
99607
100322
|
function readTaskScopes(directory, taskId) {
|
|
99608
|
-
const scopePath =
|
|
100323
|
+
const scopePath = path126.join(directory, ".swarm", "scopes", `scope-${taskId}.json`);
|
|
99609
100324
|
try {
|
|
99610
|
-
if (!
|
|
100325
|
+
if (!fs97.existsSync(scopePath)) {
|
|
99611
100326
|
return null;
|
|
99612
100327
|
}
|
|
99613
|
-
const raw =
|
|
100328
|
+
const raw = fs97.readFileSync(scopePath, "utf-8");
|
|
99614
100329
|
const parsed = JSON.parse(raw);
|
|
99615
100330
|
if (!parsed || !Array.isArray(parsed.files)) {
|
|
99616
100331
|
return null;
|
|
@@ -99993,12 +100708,12 @@ function createEmptyPlan(phaseNumber, planId) {
|
|
|
99993
100708
|
// src/tools/lean-turbo-plan-lanes.ts
|
|
99994
100709
|
init_create_tool();
|
|
99995
100710
|
function readPlanJson(directory) {
|
|
99996
|
-
const planPath =
|
|
99997
|
-
if (!
|
|
100711
|
+
const planPath = path127.join(directory, ".swarm", "plan.json");
|
|
100712
|
+
if (!fs98.existsSync(planPath)) {
|
|
99998
100713
|
return null;
|
|
99999
100714
|
}
|
|
100000
100715
|
try {
|
|
100001
|
-
return JSON.parse(
|
|
100716
|
+
return JSON.parse(fs98.readFileSync(planPath, "utf-8"));
|
|
100002
100717
|
} catch {
|
|
100003
100718
|
return null;
|
|
100004
100719
|
}
|
|
@@ -100047,8 +100762,8 @@ init_config();
|
|
|
100047
100762
|
|
|
100048
100763
|
// src/turbo/lean/reviewer.ts
|
|
100049
100764
|
init_state();
|
|
100050
|
-
import * as
|
|
100051
|
-
import * as
|
|
100765
|
+
import * as fs99 from "node:fs/promises";
|
|
100766
|
+
import * as path128 from "node:path";
|
|
100052
100767
|
init_state3();
|
|
100053
100768
|
var DEFAULT_CONFIG3 = {
|
|
100054
100769
|
reviewerAgent: "",
|
|
@@ -100070,7 +100785,7 @@ function resolveDefaultReviewerAgent(generatedAgentNames) {
|
|
|
100070
100785
|
}
|
|
100071
100786
|
async function compileReviewPackage(directory, phase, sessionID, requireDiffSummary) {
|
|
100072
100787
|
const lanes = await listLaneEvidence(directory, phase);
|
|
100073
|
-
const persisted =
|
|
100788
|
+
const persisted = _internals48.readPersisted?.(directory) ?? null;
|
|
100074
100789
|
if (persisted) {
|
|
100075
100790
|
let matchingRunState = null;
|
|
100076
100791
|
for (const sessionState of Object.values(persisted.sessions)) {
|
|
@@ -100164,9 +100879,9 @@ function parseReviewerVerdict(responseText) {
|
|
|
100164
100879
|
return { verdict, reason };
|
|
100165
100880
|
}
|
|
100166
100881
|
async function writeReviewerEvidence(directory, phase, verdict, reason) {
|
|
100167
|
-
const evidenceDir =
|
|
100168
|
-
await
|
|
100169
|
-
const evidencePath =
|
|
100882
|
+
const evidenceDir = path128.join(directory, ".swarm", "evidence", String(phase));
|
|
100883
|
+
await fs99.mkdir(evidenceDir, { recursive: true });
|
|
100884
|
+
const evidencePath = path128.join(evidenceDir, "lean-turbo-reviewer.json");
|
|
100170
100885
|
const content = JSON.stringify({
|
|
100171
100886
|
phase,
|
|
100172
100887
|
verdict,
|
|
@@ -100175,11 +100890,11 @@ async function writeReviewerEvidence(directory, phase, verdict, reason) {
|
|
|
100175
100890
|
}, null, 2);
|
|
100176
100891
|
const tempPath = `${evidencePath}.tmp.${process.pid}.${Date.now()}`;
|
|
100177
100892
|
try {
|
|
100178
|
-
await
|
|
100179
|
-
await
|
|
100893
|
+
await fs99.writeFile(tempPath, content, "utf-8");
|
|
100894
|
+
await fs99.rename(tempPath, evidencePath);
|
|
100180
100895
|
} catch (error93) {
|
|
100181
100896
|
try {
|
|
100182
|
-
await
|
|
100897
|
+
await fs99.unlink(tempPath);
|
|
100183
100898
|
} catch {}
|
|
100184
100899
|
throw error93;
|
|
100185
100900
|
}
|
|
@@ -100262,7 +100977,7 @@ Be specific and evidence-based. Do not approve a phase with unresolved degraded
|
|
|
100262
100977
|
client.session.delete({ path: { id: sessionId } }).catch(() => {});
|
|
100263
100978
|
}
|
|
100264
100979
|
}
|
|
100265
|
-
var
|
|
100980
|
+
var _internals48 = {
|
|
100266
100981
|
compileReviewPackage,
|
|
100267
100982
|
parseReviewerVerdict,
|
|
100268
100983
|
writeReviewerEvidence,
|
|
@@ -100279,28 +100994,28 @@ async function dispatchPhaseReviewer(directory, phase, sessionID, config3) {
|
|
|
100279
100994
|
};
|
|
100280
100995
|
const generatedAgentNames = swarmState.generatedAgentNames;
|
|
100281
100996
|
const agentName = mergedConfig.reviewerAgent || resolveDefaultReviewerAgent(generatedAgentNames);
|
|
100282
|
-
const pkg = await
|
|
100997
|
+
const pkg = await _internals48.compileReviewPackage(directory, phase, sessionID, mergedConfig.requireDiffSummary);
|
|
100283
100998
|
let responseText;
|
|
100284
100999
|
try {
|
|
100285
|
-
responseText = await
|
|
101000
|
+
responseText = await _internals48.dispatchReviewerAgent(directory, pkg, agentName, mergedConfig.timeoutMs);
|
|
100286
101001
|
} catch (error93) {
|
|
100287
|
-
const evidencePath2 = await
|
|
101002
|
+
const evidencePath2 = await _internals48.writeReviewerEvidence(directory, phase, "REJECTED", error93 instanceof Error ? error93.message : String(error93));
|
|
100288
101003
|
return {
|
|
100289
101004
|
verdict: "REJECTED",
|
|
100290
101005
|
reason: `Reviewer dispatch failed: ${error93 instanceof Error ? error93.message : String(error93)}`,
|
|
100291
101006
|
evidencePath: evidencePath2
|
|
100292
101007
|
};
|
|
100293
101008
|
}
|
|
100294
|
-
const parsed =
|
|
101009
|
+
const parsed = _internals48.parseReviewerVerdict(responseText);
|
|
100295
101010
|
if (!parsed) {
|
|
100296
|
-
const evidencePath2 = await
|
|
101011
|
+
const evidencePath2 = await _internals48.writeReviewerEvidence(directory, phase, "REJECTED", "Reviewer response could not be parsed");
|
|
100297
101012
|
return {
|
|
100298
101013
|
verdict: "REJECTED",
|
|
100299
101014
|
reason: "Reviewer response could not be parsed",
|
|
100300
101015
|
evidencePath: evidencePath2
|
|
100301
101016
|
};
|
|
100302
101017
|
}
|
|
100303
|
-
const evidencePath = await
|
|
101018
|
+
const evidencePath = await _internals48.writeReviewerEvidence(directory, phase, parsed.verdict, parsed.reason);
|
|
100304
101019
|
return {
|
|
100305
101020
|
verdict: parsed.verdict,
|
|
100306
101021
|
reason: parsed.reason,
|
|
@@ -100806,7 +101521,7 @@ ${fileList}
|
|
|
100806
101521
|
|
|
100807
101522
|
// src/tools/lean-turbo-run-phase.ts
|
|
100808
101523
|
init_create_tool();
|
|
100809
|
-
var
|
|
101524
|
+
var _internals49 = {
|
|
100810
101525
|
LeanTurboRunner,
|
|
100811
101526
|
loadPluginConfigWithMeta
|
|
100812
101527
|
};
|
|
@@ -100816,9 +101531,9 @@ async function executeLeanTurboRunPhase(args2) {
|
|
|
100816
101531
|
let runError = null;
|
|
100817
101532
|
let runner = null;
|
|
100818
101533
|
try {
|
|
100819
|
-
const { config: config3 } =
|
|
101534
|
+
const { config: config3 } = _internals49.loadPluginConfigWithMeta(directory);
|
|
100820
101535
|
const leanConfig = config3.turbo?.strategy === "lean" ? config3.turbo.lean : undefined;
|
|
100821
|
-
runner = new
|
|
101536
|
+
runner = new _internals49.LeanTurboRunner({
|
|
100822
101537
|
directory,
|
|
100823
101538
|
sessionID,
|
|
100824
101539
|
opencodeClient: swarmState.opencodeClient ?? null,
|
|
@@ -100970,8 +101685,8 @@ var lean_turbo_status = createSwarmTool({
|
|
|
100970
101685
|
// src/tools/lint-spec.ts
|
|
100971
101686
|
init_spec_schema();
|
|
100972
101687
|
init_create_tool();
|
|
100973
|
-
import * as
|
|
100974
|
-
import * as
|
|
101688
|
+
import * as fs100 from "node:fs";
|
|
101689
|
+
import * as path129 from "node:path";
|
|
100975
101690
|
var SPEC_FILE_NAME = "spec.md";
|
|
100976
101691
|
var SWARM_DIR2 = ".swarm";
|
|
100977
101692
|
var OBLIGATION_KEYWORDS2 = ["MUST", "SHALL", "SHOULD", "MAY"];
|
|
@@ -101024,8 +101739,8 @@ var lint_spec = createSwarmTool({
|
|
|
101024
101739
|
async execute(_args, directory) {
|
|
101025
101740
|
const errors5 = [];
|
|
101026
101741
|
const warnings = [];
|
|
101027
|
-
const specPath =
|
|
101028
|
-
if (!
|
|
101742
|
+
const specPath = path129.join(directory, SWARM_DIR2, SPEC_FILE_NAME);
|
|
101743
|
+
if (!fs100.existsSync(specPath)) {
|
|
101029
101744
|
const result2 = {
|
|
101030
101745
|
valid: false,
|
|
101031
101746
|
specMtime: null,
|
|
@@ -101044,12 +101759,12 @@ var lint_spec = createSwarmTool({
|
|
|
101044
101759
|
}
|
|
101045
101760
|
let specMtime = null;
|
|
101046
101761
|
try {
|
|
101047
|
-
const stats =
|
|
101762
|
+
const stats = fs100.statSync(specPath);
|
|
101048
101763
|
specMtime = stats.mtime.toISOString();
|
|
101049
101764
|
} catch {}
|
|
101050
101765
|
let content;
|
|
101051
101766
|
try {
|
|
101052
|
-
content =
|
|
101767
|
+
content = fs100.readFileSync(specPath, "utf-8");
|
|
101053
101768
|
} catch (e) {
|
|
101054
101769
|
const result2 = {
|
|
101055
101770
|
valid: false,
|
|
@@ -101094,13 +101809,13 @@ var lint_spec = createSwarmTool({
|
|
|
101094
101809
|
});
|
|
101095
101810
|
// src/tools/mutation-test.ts
|
|
101096
101811
|
init_zod();
|
|
101097
|
-
import * as
|
|
101098
|
-
import * as
|
|
101812
|
+
import * as fs101 from "node:fs";
|
|
101813
|
+
import * as path131 from "node:path";
|
|
101099
101814
|
|
|
101100
101815
|
// src/mutation/engine.ts
|
|
101101
101816
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
101102
|
-
import { unlinkSync as unlinkSync16, writeFileSync as
|
|
101103
|
-
import * as
|
|
101817
|
+
import { unlinkSync as unlinkSync16, writeFileSync as writeFileSync25 } from "node:fs";
|
|
101818
|
+
import * as path130 from "node:path";
|
|
101104
101819
|
|
|
101105
101820
|
// src/mutation/equivalence.ts
|
|
101106
101821
|
function isStaticallyEquivalent(originalCode, mutatedCode) {
|
|
@@ -101172,7 +101887,7 @@ function isStaticallyEquivalent(originalCode, mutatedCode) {
|
|
|
101172
101887
|
const strippedMutated = stripCode(mutatedCode);
|
|
101173
101888
|
return strippedOriginal === strippedMutated;
|
|
101174
101889
|
}
|
|
101175
|
-
var
|
|
101890
|
+
var _internals50 = {
|
|
101176
101891
|
isStaticallyEquivalent,
|
|
101177
101892
|
checkEquivalence,
|
|
101178
101893
|
batchCheckEquivalence
|
|
@@ -101212,7 +101927,7 @@ async function batchCheckEquivalence(patches, llmJudge) {
|
|
|
101212
101927
|
const results = [];
|
|
101213
101928
|
for (const { patch, originalCode, mutatedCode } of patches) {
|
|
101214
101929
|
try {
|
|
101215
|
-
const result = await
|
|
101930
|
+
const result = await _internals50.checkEquivalence(patch, originalCode, mutatedCode, llmJudge);
|
|
101216
101931
|
results.push(result);
|
|
101217
101932
|
} catch (err3) {
|
|
101218
101933
|
results.push({
|
|
@@ -101240,9 +101955,9 @@ async function executeMutation(patch, testCommand, _testFiles, workingDir) {
|
|
|
101240
101955
|
let patchFile;
|
|
101241
101956
|
try {
|
|
101242
101957
|
const safeId2 = patch.id.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
101243
|
-
patchFile =
|
|
101958
|
+
patchFile = path130.join(workingDir, `.mutation_patch_${safeId2}.diff`);
|
|
101244
101959
|
try {
|
|
101245
|
-
|
|
101960
|
+
writeFileSync25(patchFile, patch.patch);
|
|
101246
101961
|
} catch (writeErr) {
|
|
101247
101962
|
error93 = `Failed to write patch file: ${writeErr}`;
|
|
101248
101963
|
outcome = "error";
|
|
@@ -101512,7 +102227,7 @@ async function executeMutationSuite(patches, testCommand, testFiles, workingDir,
|
|
|
101512
102227
|
}
|
|
101513
102228
|
|
|
101514
102229
|
// src/mutation/gate.ts
|
|
101515
|
-
var
|
|
102230
|
+
var _internals51 = {
|
|
101516
102231
|
evaluateMutationGate,
|
|
101517
102232
|
buildTestImprovementPrompt,
|
|
101518
102233
|
buildMessage
|
|
@@ -101533,8 +102248,8 @@ function evaluateMutationGate(report, passThreshold = PASS_THRESHOLD, warnThresh
|
|
|
101533
102248
|
} else {
|
|
101534
102249
|
verdict = "fail";
|
|
101535
102250
|
}
|
|
101536
|
-
const testImprovementPrompt =
|
|
101537
|
-
const message =
|
|
102251
|
+
const testImprovementPrompt = _internals51.buildTestImprovementPrompt(report, passThreshold, verdict);
|
|
102252
|
+
const message = _internals51.buildMessage(verdict, adjustedKillRate, report.killed, report.totalMutants, report.equivalent, warnThreshold);
|
|
101538
102253
|
return {
|
|
101539
102254
|
verdict,
|
|
101540
102255
|
killRate: report.killRate,
|
|
@@ -101639,8 +102354,8 @@ var mutation_test = createSwarmTool({
|
|
|
101639
102354
|
];
|
|
101640
102355
|
for (const filePath of uniquePaths) {
|
|
101641
102356
|
try {
|
|
101642
|
-
const resolvedPath =
|
|
101643
|
-
sourceFiles.set(filePath,
|
|
102357
|
+
const resolvedPath = path131.resolve(cwd, filePath);
|
|
102358
|
+
sourceFiles.set(filePath, fs101.readFileSync(resolvedPath, "utf-8"));
|
|
101644
102359
|
} catch {}
|
|
101645
102360
|
}
|
|
101646
102361
|
const report = await executeMutationSuite(typedArgs.patches, typedArgs.test_command, typedArgs.files, cwd, undefined, undefined, sourceFiles.size > 0 ? sourceFiles : undefined);
|
|
@@ -101658,8 +102373,8 @@ var mutation_test = createSwarmTool({
|
|
|
101658
102373
|
init_zod();
|
|
101659
102374
|
init_manager2();
|
|
101660
102375
|
init_detector();
|
|
101661
|
-
import * as
|
|
101662
|
-
import * as
|
|
102376
|
+
import * as fs102 from "node:fs";
|
|
102377
|
+
import * as path132 from "node:path";
|
|
101663
102378
|
init_create_tool();
|
|
101664
102379
|
var MAX_FILE_SIZE2 = 2 * 1024 * 1024;
|
|
101665
102380
|
var BINARY_CHECK_BYTES = 8192;
|
|
@@ -101725,7 +102440,7 @@ async function syntaxCheck(input, directory, config3) {
|
|
|
101725
102440
|
if (languages?.length) {
|
|
101726
102441
|
const lowerLangs = languages.map((l) => l.toLowerCase());
|
|
101727
102442
|
filesToCheck = filesToCheck.filter((file3) => {
|
|
101728
|
-
const ext =
|
|
102443
|
+
const ext = path132.extname(file3.path).toLowerCase();
|
|
101729
102444
|
const langDef = getLanguageForExtension(ext);
|
|
101730
102445
|
const fileProfile = getProfileForFile(file3.path);
|
|
101731
102446
|
const langId = fileProfile?.id || langDef?.id;
|
|
@@ -101738,7 +102453,7 @@ async function syntaxCheck(input, directory, config3) {
|
|
|
101738
102453
|
let skippedCount = 0;
|
|
101739
102454
|
for (const fileInfo of filesToCheck) {
|
|
101740
102455
|
const { path: filePath } = fileInfo;
|
|
101741
|
-
const fullPath =
|
|
102456
|
+
const fullPath = path132.isAbsolute(filePath) ? filePath : path132.join(directory, filePath);
|
|
101742
102457
|
const result = {
|
|
101743
102458
|
path: filePath,
|
|
101744
102459
|
language: "",
|
|
@@ -101768,7 +102483,7 @@ async function syntaxCheck(input, directory, config3) {
|
|
|
101768
102483
|
}
|
|
101769
102484
|
let content;
|
|
101770
102485
|
try {
|
|
101771
|
-
content =
|
|
102486
|
+
content = fs102.readFileSync(fullPath, "utf8");
|
|
101772
102487
|
} catch {
|
|
101773
102488
|
result.skipped_reason = "file_read_error";
|
|
101774
102489
|
skippedCount++;
|
|
@@ -101787,7 +102502,7 @@ async function syntaxCheck(input, directory, config3) {
|
|
|
101787
102502
|
results.push(result);
|
|
101788
102503
|
continue;
|
|
101789
102504
|
}
|
|
101790
|
-
const ext =
|
|
102505
|
+
const ext = path132.extname(filePath).toLowerCase();
|
|
101791
102506
|
const langDef = getLanguageForExtension(ext);
|
|
101792
102507
|
result.language = profile?.id || langDef?.id || "unknown";
|
|
101793
102508
|
const errors5 = extractSyntaxErrors(parser, content);
|
|
@@ -101879,8 +102594,8 @@ init_zod();
|
|
|
101879
102594
|
init_utils();
|
|
101880
102595
|
init_create_tool();
|
|
101881
102596
|
init_path_security();
|
|
101882
|
-
import * as
|
|
101883
|
-
import * as
|
|
102597
|
+
import * as fs103 from "node:fs";
|
|
102598
|
+
import * as path133 from "node:path";
|
|
101884
102599
|
var MAX_TEXT_LENGTH = 200;
|
|
101885
102600
|
var MAX_FILE_SIZE_BYTES11 = 1024 * 1024;
|
|
101886
102601
|
var SUPPORTED_EXTENSIONS4 = new Set([
|
|
@@ -101946,9 +102661,9 @@ function validatePathsInput(paths, cwd) {
|
|
|
101946
102661
|
return { error: "paths contains path traversal", resolvedPath: null };
|
|
101947
102662
|
}
|
|
101948
102663
|
try {
|
|
101949
|
-
const resolvedPath =
|
|
101950
|
-
const normalizedCwd =
|
|
101951
|
-
const normalizedResolved =
|
|
102664
|
+
const resolvedPath = path133.resolve(paths);
|
|
102665
|
+
const normalizedCwd = path133.resolve(cwd);
|
|
102666
|
+
const normalizedResolved = path133.resolve(resolvedPath);
|
|
101952
102667
|
if (!normalizedResolved.startsWith(normalizedCwd)) {
|
|
101953
102668
|
return {
|
|
101954
102669
|
error: "paths must be within the current working directory",
|
|
@@ -101964,13 +102679,13 @@ function validatePathsInput(paths, cwd) {
|
|
|
101964
102679
|
}
|
|
101965
102680
|
}
|
|
101966
102681
|
function isSupportedExtension(filePath) {
|
|
101967
|
-
const ext =
|
|
102682
|
+
const ext = path133.extname(filePath).toLowerCase();
|
|
101968
102683
|
return SUPPORTED_EXTENSIONS4.has(ext);
|
|
101969
102684
|
}
|
|
101970
102685
|
function findSourceFiles3(dir, files = []) {
|
|
101971
102686
|
let entries;
|
|
101972
102687
|
try {
|
|
101973
|
-
entries =
|
|
102688
|
+
entries = fs103.readdirSync(dir);
|
|
101974
102689
|
} catch {
|
|
101975
102690
|
return files;
|
|
101976
102691
|
}
|
|
@@ -101979,10 +102694,10 @@ function findSourceFiles3(dir, files = []) {
|
|
|
101979
102694
|
if (SKIP_DIRECTORIES5.has(entry)) {
|
|
101980
102695
|
continue;
|
|
101981
102696
|
}
|
|
101982
|
-
const fullPath =
|
|
102697
|
+
const fullPath = path133.join(dir, entry);
|
|
101983
102698
|
let stat8;
|
|
101984
102699
|
try {
|
|
101985
|
-
stat8 =
|
|
102700
|
+
stat8 = fs103.statSync(fullPath);
|
|
101986
102701
|
} catch {
|
|
101987
102702
|
continue;
|
|
101988
102703
|
}
|
|
@@ -102075,7 +102790,7 @@ var todo_extract = createSwarmTool({
|
|
|
102075
102790
|
return JSON.stringify(errorResult, null, 2);
|
|
102076
102791
|
}
|
|
102077
102792
|
const scanPath = resolvedPath;
|
|
102078
|
-
if (!
|
|
102793
|
+
if (!fs103.existsSync(scanPath)) {
|
|
102079
102794
|
const errorResult = {
|
|
102080
102795
|
error: `path not found: ${pathsInput}`,
|
|
102081
102796
|
total: 0,
|
|
@@ -102085,13 +102800,13 @@ var todo_extract = createSwarmTool({
|
|
|
102085
102800
|
return JSON.stringify(errorResult, null, 2);
|
|
102086
102801
|
}
|
|
102087
102802
|
const filesToScan = [];
|
|
102088
|
-
const stat8 =
|
|
102803
|
+
const stat8 = fs103.statSync(scanPath);
|
|
102089
102804
|
if (stat8.isFile()) {
|
|
102090
102805
|
if (isSupportedExtension(scanPath)) {
|
|
102091
102806
|
filesToScan.push(scanPath);
|
|
102092
102807
|
} else {
|
|
102093
102808
|
const errorResult = {
|
|
102094
|
-
error: `unsupported file extension: ${
|
|
102809
|
+
error: `unsupported file extension: ${path133.extname(scanPath)}`,
|
|
102095
102810
|
total: 0,
|
|
102096
102811
|
byPriority: { high: 0, medium: 0, low: 0 },
|
|
102097
102812
|
entries: []
|
|
@@ -102104,11 +102819,11 @@ var todo_extract = createSwarmTool({
|
|
|
102104
102819
|
const allEntries = [];
|
|
102105
102820
|
for (const filePath of filesToScan) {
|
|
102106
102821
|
try {
|
|
102107
|
-
const fileStat =
|
|
102822
|
+
const fileStat = fs103.statSync(filePath);
|
|
102108
102823
|
if (fileStat.size > MAX_FILE_SIZE_BYTES11) {
|
|
102109
102824
|
continue;
|
|
102110
102825
|
}
|
|
102111
|
-
const content =
|
|
102826
|
+
const content = fs103.readFileSync(filePath, "utf-8");
|
|
102112
102827
|
const entries = parseTodoComments(content, filePath, tagsSet);
|
|
102113
102828
|
allEntries.push(...entries);
|
|
102114
102829
|
} catch {}
|
|
@@ -102139,19 +102854,19 @@ init_loader();
|
|
|
102139
102854
|
init_schema();
|
|
102140
102855
|
init_qa_gate_profile();
|
|
102141
102856
|
init_gate_evidence();
|
|
102142
|
-
import * as
|
|
102143
|
-
import * as
|
|
102857
|
+
import * as fs107 from "node:fs";
|
|
102858
|
+
import * as path137 from "node:path";
|
|
102144
102859
|
|
|
102145
102860
|
// src/hooks/diff-scope.ts
|
|
102146
102861
|
init_bun_compat();
|
|
102147
|
-
import * as
|
|
102148
|
-
import * as
|
|
102862
|
+
import * as fs105 from "node:fs";
|
|
102863
|
+
import * as path135 from "node:path";
|
|
102149
102864
|
|
|
102150
102865
|
// src/utils/gitignore-warning.ts
|
|
102151
102866
|
init_bun_compat();
|
|
102152
|
-
import * as
|
|
102153
|
-
import * as
|
|
102154
|
-
var
|
|
102867
|
+
import * as fs104 from "node:fs";
|
|
102868
|
+
import * as path134 from "node:path";
|
|
102869
|
+
var _internals52 = { bunSpawn };
|
|
102155
102870
|
var _swarmGitExcludedChecked = false;
|
|
102156
102871
|
function fileCoversSwarm(content) {
|
|
102157
102872
|
for (const rawLine of content.split(`
|
|
@@ -102184,7 +102899,7 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
|
|
|
102184
102899
|
checkIgnoreExitCode
|
|
102185
102900
|
] = await Promise.all([
|
|
102186
102901
|
(async () => {
|
|
102187
|
-
const proc =
|
|
102902
|
+
const proc = _internals52.bunSpawn(["git", "-C", directory, "rev-parse", "--show-toplevel"], GIT_SPAWN_OPTIONS);
|
|
102188
102903
|
try {
|
|
102189
102904
|
return await Promise.all([proc.exited, proc.stdout.text()]);
|
|
102190
102905
|
} finally {
|
|
@@ -102194,7 +102909,7 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
|
|
|
102194
102909
|
}
|
|
102195
102910
|
})(),
|
|
102196
102911
|
(async () => {
|
|
102197
|
-
const proc =
|
|
102912
|
+
const proc = _internals52.bunSpawn(["git", "-C", directory, "rev-parse", "--git-path", "info/exclude"], GIT_SPAWN_OPTIONS);
|
|
102198
102913
|
try {
|
|
102199
102914
|
return await Promise.all([proc.exited, proc.stdout.text()]);
|
|
102200
102915
|
} finally {
|
|
@@ -102204,7 +102919,7 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
|
|
|
102204
102919
|
}
|
|
102205
102920
|
})(),
|
|
102206
102921
|
(async () => {
|
|
102207
|
-
const proc =
|
|
102922
|
+
const proc = _internals52.bunSpawn(["git", "-C", directory, "check-ignore", "-q", ".swarm/.gitkeep"], GIT_SPAWN_OPTIONS);
|
|
102208
102923
|
try {
|
|
102209
102924
|
return await proc.exited;
|
|
102210
102925
|
} finally {
|
|
@@ -102224,16 +102939,16 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
|
|
|
102224
102939
|
const excludeRelPath = excludePathRaw.trim();
|
|
102225
102940
|
if (!excludeRelPath)
|
|
102226
102941
|
return;
|
|
102227
|
-
const excludePath =
|
|
102942
|
+
const excludePath = path134.isAbsolute(excludeRelPath) ? excludeRelPath : path134.join(directory, excludeRelPath);
|
|
102228
102943
|
if (checkIgnoreExitCode !== 0) {
|
|
102229
102944
|
try {
|
|
102230
|
-
|
|
102945
|
+
fs104.mkdirSync(path134.dirname(excludePath), { recursive: true });
|
|
102231
102946
|
let existing = "";
|
|
102232
102947
|
try {
|
|
102233
|
-
existing =
|
|
102948
|
+
existing = fs104.readFileSync(excludePath, "utf8");
|
|
102234
102949
|
} catch {}
|
|
102235
102950
|
if (!fileCoversSwarm(existing)) {
|
|
102236
|
-
|
|
102951
|
+
fs104.appendFileSync(excludePath, `
|
|
102237
102952
|
# opencode-swarm local runtime state
|
|
102238
102953
|
.swarm/
|
|
102239
102954
|
`, "utf8");
|
|
@@ -102243,7 +102958,7 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
|
|
|
102243
102958
|
}
|
|
102244
102959
|
} catch {}
|
|
102245
102960
|
}
|
|
102246
|
-
const trackedProc =
|
|
102961
|
+
const trackedProc = _internals52.bunSpawn(["git", "-C", directory, "ls-files", "--", ".swarm"], GIT_SPAWN_OPTIONS);
|
|
102247
102962
|
let trackedExitCode;
|
|
102248
102963
|
let trackedOutput;
|
|
102249
102964
|
try {
|
|
@@ -102268,13 +102983,13 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
|
|
|
102268
102983
|
}
|
|
102269
102984
|
|
|
102270
102985
|
// src/hooks/diff-scope.ts
|
|
102271
|
-
var
|
|
102986
|
+
var _internals53 = { bunSpawn };
|
|
102272
102987
|
function getDeclaredScope(taskId, directory) {
|
|
102273
102988
|
try {
|
|
102274
|
-
const planPath =
|
|
102275
|
-
if (!
|
|
102989
|
+
const planPath = path135.join(directory, ".swarm", "plan.json");
|
|
102990
|
+
if (!fs105.existsSync(planPath))
|
|
102276
102991
|
return null;
|
|
102277
|
-
const raw =
|
|
102992
|
+
const raw = fs105.readFileSync(planPath, "utf-8");
|
|
102278
102993
|
const plan = JSON.parse(raw);
|
|
102279
102994
|
for (const phase of plan.phases ?? []) {
|
|
102280
102995
|
for (const task of phase.tasks ?? []) {
|
|
@@ -102303,7 +103018,7 @@ var GIT_DIFF_SPAWN_OPTIONS = {
|
|
|
102303
103018
|
};
|
|
102304
103019
|
async function getChangedFiles(directory) {
|
|
102305
103020
|
try {
|
|
102306
|
-
const proc =
|
|
103021
|
+
const proc = _internals53.bunSpawn(["git", "diff", "--name-only", "HEAD~1"], {
|
|
102307
103022
|
cwd: directory,
|
|
102308
103023
|
...GIT_DIFF_SPAWN_OPTIONS
|
|
102309
103024
|
});
|
|
@@ -102320,7 +103035,7 @@ async function getChangedFiles(directory) {
|
|
|
102320
103035
|
return stdout.trim().split(`
|
|
102321
103036
|
`).map((f) => f.trim()).filter((f) => f.length > 0);
|
|
102322
103037
|
}
|
|
102323
|
-
const proc2 =
|
|
103038
|
+
const proc2 = _internals53.bunSpawn(["git", "diff", "--name-only", "HEAD"], {
|
|
102324
103039
|
cwd: directory,
|
|
102325
103040
|
...GIT_DIFF_SPAWN_OPTIONS
|
|
102326
103041
|
});
|
|
@@ -102376,9 +103091,9 @@ init_telemetry();
|
|
|
102376
103091
|
|
|
102377
103092
|
// src/turbo/lean/task-completion.ts
|
|
102378
103093
|
init_file_locks();
|
|
102379
|
-
import * as
|
|
102380
|
-
import * as
|
|
102381
|
-
var
|
|
103094
|
+
import * as fs106 from "node:fs";
|
|
103095
|
+
import * as path136 from "node:path";
|
|
103096
|
+
var _internals54 = {
|
|
102382
103097
|
listActiveLocks,
|
|
102383
103098
|
verifyLeanTurboTaskCompletion
|
|
102384
103099
|
};
|
|
@@ -102396,7 +103111,7 @@ var TIER_3_PATTERNS = [
|
|
|
102396
103111
|
];
|
|
102397
103112
|
function matchesTier3Pattern(files) {
|
|
102398
103113
|
for (const file3 of files) {
|
|
102399
|
-
const fileName =
|
|
103114
|
+
const fileName = path136.basename(file3);
|
|
102400
103115
|
for (const pattern of TIER_3_PATTERNS) {
|
|
102401
103116
|
if (pattern.test(fileName)) {
|
|
102402
103117
|
return true;
|
|
@@ -102408,14 +103123,14 @@ function matchesTier3Pattern(files) {
|
|
|
102408
103123
|
function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
|
|
102409
103124
|
let persisted = null;
|
|
102410
103125
|
try {
|
|
102411
|
-
const statePath =
|
|
102412
|
-
if (!
|
|
103126
|
+
const statePath = path136.join(directory, ".swarm", "turbo-state.json");
|
|
103127
|
+
if (!fs106.existsSync(statePath)) {
|
|
102413
103128
|
return {
|
|
102414
103129
|
ok: false,
|
|
102415
103130
|
reason: "Lean Turbo state file not found"
|
|
102416
103131
|
};
|
|
102417
103132
|
}
|
|
102418
|
-
const raw =
|
|
103133
|
+
const raw = fs106.readFileSync(statePath, "utf-8");
|
|
102419
103134
|
persisted = JSON.parse(raw);
|
|
102420
103135
|
} catch {
|
|
102421
103136
|
return {
|
|
@@ -102492,11 +103207,11 @@ function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
|
|
|
102492
103207
|
};
|
|
102493
103208
|
}
|
|
102494
103209
|
const phase = runState.phase ?? 0;
|
|
102495
|
-
const evidencePath =
|
|
102496
|
-
const expectedDir =
|
|
102497
|
-
const resolvedPath =
|
|
102498
|
-
const resolvedDir =
|
|
102499
|
-
if (!resolvedPath.startsWith(resolvedDir +
|
|
103210
|
+
const evidencePath = path136.join(directory, ".swarm", "evidence", String(phase), "lean-turbo", `${lane.laneId}.json`);
|
|
103211
|
+
const expectedDir = path136.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
|
|
103212
|
+
const resolvedPath = path136.resolve(evidencePath);
|
|
103213
|
+
const resolvedDir = path136.resolve(expectedDir);
|
|
103214
|
+
if (!resolvedPath.startsWith(resolvedDir + path136.sep) && resolvedPath !== resolvedDir) {
|
|
102500
103215
|
return {
|
|
102501
103216
|
ok: false,
|
|
102502
103217
|
reason: `Lane ID causes path traversal: ${lane.laneId}`,
|
|
@@ -102508,7 +103223,7 @@ function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
|
|
|
102508
103223
|
}
|
|
102509
103224
|
};
|
|
102510
103225
|
}
|
|
102511
|
-
if (!
|
|
103226
|
+
if (!fs106.existsSync(evidencePath)) {
|
|
102512
103227
|
return {
|
|
102513
103228
|
ok: false,
|
|
102514
103229
|
reason: `Lane ${lane.laneId} evidence file not found: ${evidencePath}`,
|
|
@@ -102520,7 +103235,7 @@ function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
|
|
|
102520
103235
|
}
|
|
102521
103236
|
};
|
|
102522
103237
|
}
|
|
102523
|
-
const activeLocks =
|
|
103238
|
+
const activeLocks = _internals54.listActiveLocks(directory);
|
|
102524
103239
|
const laneLocks = activeLocks.filter((lock) => lock.laneId === lane.laneId);
|
|
102525
103240
|
if (laneLocks.length > 0) {
|
|
102526
103241
|
return {
|
|
@@ -102536,8 +103251,8 @@ function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
|
|
|
102536
103251
|
}
|
|
102537
103252
|
let filesTouched = [];
|
|
102538
103253
|
try {
|
|
102539
|
-
const planPath =
|
|
102540
|
-
const planRaw =
|
|
103254
|
+
const planPath = path136.join(directory, ".swarm", "plan.json");
|
|
103255
|
+
const planRaw = fs106.readFileSync(planPath, "utf-8");
|
|
102541
103256
|
const plan = JSON.parse(planRaw);
|
|
102542
103257
|
for (const planPhase of plan.phases ?? []) {
|
|
102543
103258
|
for (const task of planPhase.tasks ?? []) {
|
|
@@ -102619,7 +103334,7 @@ var TIER_3_PATTERNS2 = [
|
|
|
102619
103334
|
];
|
|
102620
103335
|
function matchesTier3Pattern2(files) {
|
|
102621
103336
|
for (const file3 of files) {
|
|
102622
|
-
const fileName =
|
|
103337
|
+
const fileName = path137.basename(file3);
|
|
102623
103338
|
for (const pattern of TIER_3_PATTERNS2) {
|
|
102624
103339
|
if (pattern.test(fileName)) {
|
|
102625
103340
|
return true;
|
|
@@ -102651,8 +103366,8 @@ function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = fal
|
|
|
102651
103366
|
if (!skipStandardTurboBypass && hasActiveTurboMode()) {
|
|
102652
103367
|
const resolvedDir2 = workingDirectory;
|
|
102653
103368
|
try {
|
|
102654
|
-
const planPath =
|
|
102655
|
-
const planRaw =
|
|
103369
|
+
const planPath = path137.join(resolvedDir2, ".swarm", "plan.json");
|
|
103370
|
+
const planRaw = fs107.readFileSync(planPath, "utf-8");
|
|
102656
103371
|
const plan = JSON.parse(planRaw);
|
|
102657
103372
|
for (const planPhase of plan.phases ?? []) {
|
|
102658
103373
|
for (const task of planPhase.tasks ?? []) {
|
|
@@ -102718,8 +103433,8 @@ function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = fal
|
|
|
102718
103433
|
}
|
|
102719
103434
|
try {
|
|
102720
103435
|
const resolvedDir2 = workingDirectory;
|
|
102721
|
-
const planPath =
|
|
102722
|
-
const planRaw =
|
|
103436
|
+
const planPath = path137.join(resolvedDir2, ".swarm", "plan.json");
|
|
103437
|
+
const planRaw = fs107.readFileSync(planPath, "utf-8");
|
|
102723
103438
|
const plan = JSON.parse(planRaw);
|
|
102724
103439
|
for (const planPhase of plan.phases ?? []) {
|
|
102725
103440
|
for (const task of planPhase.tasks ?? []) {
|
|
@@ -102903,8 +103618,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
|
|
|
102903
103618
|
};
|
|
102904
103619
|
}
|
|
102905
103620
|
}
|
|
102906
|
-
normalizedDir =
|
|
102907
|
-
const pathParts = normalizedDir.split(
|
|
103621
|
+
normalizedDir = path137.normalize(args2.working_directory);
|
|
103622
|
+
const pathParts = normalizedDir.split(path137.sep);
|
|
102908
103623
|
if (pathParts.includes("..")) {
|
|
102909
103624
|
return {
|
|
102910
103625
|
success: false,
|
|
@@ -102914,11 +103629,11 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
|
|
|
102914
103629
|
]
|
|
102915
103630
|
};
|
|
102916
103631
|
}
|
|
102917
|
-
const resolvedDir =
|
|
103632
|
+
const resolvedDir = path137.resolve(normalizedDir);
|
|
102918
103633
|
try {
|
|
102919
|
-
const realPath =
|
|
102920
|
-
const planPath =
|
|
102921
|
-
if (!
|
|
103634
|
+
const realPath = fs107.realpathSync(resolvedDir);
|
|
103635
|
+
const planPath = path137.join(realPath, ".swarm", "plan.json");
|
|
103636
|
+
if (!fs107.existsSync(planPath)) {
|
|
102922
103637
|
return {
|
|
102923
103638
|
success: false,
|
|
102924
103639
|
message: `Invalid working_directory: plan not found in "${realPath}"`,
|
|
@@ -102949,22 +103664,22 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
|
|
|
102949
103664
|
}
|
|
102950
103665
|
if (args2.status === "in_progress") {
|
|
102951
103666
|
try {
|
|
102952
|
-
const evidencePath =
|
|
102953
|
-
|
|
102954
|
-
const fd =
|
|
103667
|
+
const evidencePath = path137.join(directory, ".swarm", "evidence", `${args2.task_id}.json`);
|
|
103668
|
+
fs107.mkdirSync(path137.dirname(evidencePath), { recursive: true });
|
|
103669
|
+
const fd = fs107.openSync(evidencePath, "wx");
|
|
102955
103670
|
let writeOk = false;
|
|
102956
103671
|
try {
|
|
102957
|
-
|
|
103672
|
+
fs107.writeSync(fd, JSON.stringify({
|
|
102958
103673
|
taskId: args2.task_id,
|
|
102959
103674
|
required_gates: ["reviewer", "test_engineer"],
|
|
102960
103675
|
gates: {}
|
|
102961
103676
|
}, null, 2));
|
|
102962
103677
|
writeOk = true;
|
|
102963
103678
|
} finally {
|
|
102964
|
-
|
|
103679
|
+
fs107.closeSync(fd);
|
|
102965
103680
|
if (!writeOk) {
|
|
102966
103681
|
try {
|
|
102967
|
-
|
|
103682
|
+
fs107.unlinkSync(evidencePath);
|
|
102968
103683
|
} catch {}
|
|
102969
103684
|
}
|
|
102970
103685
|
}
|
|
@@ -102974,8 +103689,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
|
|
|
102974
103689
|
recoverTaskStateFromDelegations(args2.task_id);
|
|
102975
103690
|
let phaseRequiresReviewer = true;
|
|
102976
103691
|
try {
|
|
102977
|
-
const planPath =
|
|
102978
|
-
const planRaw =
|
|
103692
|
+
const planPath = path137.join(directory, ".swarm", "plan.json");
|
|
103693
|
+
const planRaw = fs107.readFileSync(planPath, "utf-8");
|
|
102979
103694
|
const plan = JSON.parse(planRaw);
|
|
102980
103695
|
const taskPhase = plan.phases.find((p) => p.tasks.some((t) => t.id === args2.task_id));
|
|
102981
103696
|
if (taskPhase?.required_agents && !taskPhase.required_agents.includes("reviewer")) {
|
|
@@ -103285,8 +104000,8 @@ init_utils2();
|
|
|
103285
104000
|
init_ledger();
|
|
103286
104001
|
init_manager();
|
|
103287
104002
|
init_create_tool();
|
|
103288
|
-
import
|
|
103289
|
-
import
|
|
104003
|
+
import fs108 from "node:fs";
|
|
104004
|
+
import path138 from "node:path";
|
|
103290
104005
|
function normalizeVerdict(verdict) {
|
|
103291
104006
|
switch (verdict) {
|
|
103292
104007
|
case "APPROVED":
|
|
@@ -103334,7 +104049,7 @@ async function executeWriteDriftEvidence(args2, directory) {
|
|
|
103334
104049
|
entries: [evidenceEntry]
|
|
103335
104050
|
};
|
|
103336
104051
|
const filename = "drift-verifier.json";
|
|
103337
|
-
const relativePath =
|
|
104052
|
+
const relativePath = path138.join("evidence", String(phase), filename);
|
|
103338
104053
|
let validatedPath;
|
|
103339
104054
|
try {
|
|
103340
104055
|
validatedPath = validateSwarmPath(directory, relativePath);
|
|
@@ -103345,12 +104060,12 @@ async function executeWriteDriftEvidence(args2, directory) {
|
|
|
103345
104060
|
message: error93 instanceof Error ? error93.message : "Failed to validate path"
|
|
103346
104061
|
}, null, 2);
|
|
103347
104062
|
}
|
|
103348
|
-
const evidenceDir =
|
|
104063
|
+
const evidenceDir = path138.dirname(validatedPath);
|
|
103349
104064
|
try {
|
|
103350
|
-
await
|
|
103351
|
-
const tempPath =
|
|
103352
|
-
await
|
|
103353
|
-
await
|
|
104065
|
+
await fs108.promises.mkdir(evidenceDir, { recursive: true });
|
|
104066
|
+
const tempPath = path138.join(evidenceDir, `.${filename}.tmp`);
|
|
104067
|
+
await fs108.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
|
|
104068
|
+
await fs108.promises.rename(tempPath, validatedPath);
|
|
103354
104069
|
let snapshotInfo;
|
|
103355
104070
|
let snapshotError;
|
|
103356
104071
|
let qaProfileLocked;
|
|
@@ -103443,8 +104158,8 @@ var write_drift_evidence = createSwarmTool({
|
|
|
103443
104158
|
// src/tools/write-final-council-evidence.ts
|
|
103444
104159
|
init_zod();
|
|
103445
104160
|
init_loader();
|
|
103446
|
-
import
|
|
103447
|
-
import
|
|
104161
|
+
import fs109 from "node:fs";
|
|
104162
|
+
import path139 from "node:path";
|
|
103448
104163
|
init_utils2();
|
|
103449
104164
|
init_manager();
|
|
103450
104165
|
init_create_tool();
|
|
@@ -103532,7 +104247,7 @@ async function executeWriteFinalCouncilEvidence(args2, directory) {
|
|
|
103532
104247
|
timestamp: synthesis.timestamp
|
|
103533
104248
|
};
|
|
103534
104249
|
const filename = "final-council.json";
|
|
103535
|
-
const relativePath =
|
|
104250
|
+
const relativePath = path139.join("evidence", filename);
|
|
103536
104251
|
let validatedPath;
|
|
103537
104252
|
try {
|
|
103538
104253
|
validatedPath = validateSwarmPath(directory, relativePath);
|
|
@@ -103546,12 +104261,12 @@ async function executeWriteFinalCouncilEvidence(args2, directory) {
|
|
|
103546
104261
|
const evidenceContent = {
|
|
103547
104262
|
entries: [evidenceEntry]
|
|
103548
104263
|
};
|
|
103549
|
-
const evidenceDir =
|
|
104264
|
+
const evidenceDir = path139.dirname(validatedPath);
|
|
103550
104265
|
try {
|
|
103551
|
-
await
|
|
103552
|
-
const tempPath =
|
|
103553
|
-
await
|
|
103554
|
-
await
|
|
104266
|
+
await fs109.promises.mkdir(evidenceDir, { recursive: true });
|
|
104267
|
+
const tempPath = path139.join(evidenceDir, `.${filename}.tmp`);
|
|
104268
|
+
await fs109.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
|
|
104269
|
+
await fs109.promises.rename(tempPath, validatedPath);
|
|
103555
104270
|
return JSON.stringify({
|
|
103556
104271
|
success: true,
|
|
103557
104272
|
phase: input.phase,
|
|
@@ -103607,8 +104322,8 @@ var write_final_council_evidence = createSwarmTool({
|
|
|
103607
104322
|
init_zod();
|
|
103608
104323
|
init_utils2();
|
|
103609
104324
|
init_create_tool();
|
|
103610
|
-
import
|
|
103611
|
-
import
|
|
104325
|
+
import fs110 from "node:fs";
|
|
104326
|
+
import path140 from "node:path";
|
|
103612
104327
|
function normalizeVerdict2(verdict) {
|
|
103613
104328
|
switch (verdict) {
|
|
103614
104329
|
case "APPROVED":
|
|
@@ -103656,7 +104371,7 @@ async function executeWriteHallucinationEvidence(args2, directory) {
|
|
|
103656
104371
|
entries: [evidenceEntry]
|
|
103657
104372
|
};
|
|
103658
104373
|
const filename = "hallucination-guard.json";
|
|
103659
|
-
const relativePath =
|
|
104374
|
+
const relativePath = path140.join("evidence", String(phase), filename);
|
|
103660
104375
|
let validatedPath;
|
|
103661
104376
|
try {
|
|
103662
104377
|
validatedPath = validateSwarmPath(directory, relativePath);
|
|
@@ -103667,12 +104382,12 @@ async function executeWriteHallucinationEvidence(args2, directory) {
|
|
|
103667
104382
|
message: error93 instanceof Error ? error93.message : "Failed to validate path"
|
|
103668
104383
|
}, null, 2);
|
|
103669
104384
|
}
|
|
103670
|
-
const evidenceDir =
|
|
104385
|
+
const evidenceDir = path140.dirname(validatedPath);
|
|
103671
104386
|
try {
|
|
103672
|
-
await
|
|
103673
|
-
const tempPath =
|
|
103674
|
-
await
|
|
103675
|
-
await
|
|
104387
|
+
await fs110.promises.mkdir(evidenceDir, { recursive: true });
|
|
104388
|
+
const tempPath = path140.join(evidenceDir, `.${filename}.tmp`);
|
|
104389
|
+
await fs110.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
|
|
104390
|
+
await fs110.promises.rename(tempPath, validatedPath);
|
|
103676
104391
|
return JSON.stringify({
|
|
103677
104392
|
success: true,
|
|
103678
104393
|
phase,
|
|
@@ -103718,8 +104433,8 @@ var write_hallucination_evidence = createSwarmTool({
|
|
|
103718
104433
|
init_zod();
|
|
103719
104434
|
init_utils2();
|
|
103720
104435
|
init_create_tool();
|
|
103721
|
-
import
|
|
103722
|
-
import
|
|
104436
|
+
import fs111 from "node:fs";
|
|
104437
|
+
import path141 from "node:path";
|
|
103723
104438
|
function normalizeVerdict3(verdict) {
|
|
103724
104439
|
switch (verdict) {
|
|
103725
104440
|
case "PASS":
|
|
@@ -103793,7 +104508,7 @@ async function executeWriteMutationEvidence(args2, directory) {
|
|
|
103793
104508
|
entries: [evidenceEntry]
|
|
103794
104509
|
};
|
|
103795
104510
|
const filename = "mutation-gate.json";
|
|
103796
|
-
const relativePath =
|
|
104511
|
+
const relativePath = path141.join("evidence", String(phase), filename);
|
|
103797
104512
|
let validatedPath;
|
|
103798
104513
|
try {
|
|
103799
104514
|
validatedPath = validateSwarmPath(directory, relativePath);
|
|
@@ -103804,12 +104519,12 @@ async function executeWriteMutationEvidence(args2, directory) {
|
|
|
103804
104519
|
message: error93 instanceof Error ? error93.message : "Failed to validate path"
|
|
103805
104520
|
}, null, 2);
|
|
103806
104521
|
}
|
|
103807
|
-
const evidenceDir =
|
|
104522
|
+
const evidenceDir = path141.dirname(validatedPath);
|
|
103808
104523
|
try {
|
|
103809
|
-
await
|
|
103810
|
-
const tempPath =
|
|
103811
|
-
await
|
|
103812
|
-
await
|
|
104524
|
+
await fs111.promises.mkdir(evidenceDir, { recursive: true });
|
|
104525
|
+
const tempPath = path141.join(evidenceDir, `.${filename}.tmp`);
|
|
104526
|
+
await fs111.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
|
|
104527
|
+
await fs111.promises.rename(tempPath, validatedPath);
|
|
103813
104528
|
return JSON.stringify({
|
|
103814
104529
|
success: true,
|
|
103815
104530
|
phase,
|
|
@@ -104152,7 +104867,7 @@ async function initializeOpenCodeSwarm(ctx) {
|
|
|
104152
104867
|
const { PreflightTriggerManager: PTM } = await Promise.resolve().then(() => (init_trigger(), exports_trigger));
|
|
104153
104868
|
preflightTriggerManager = new PTM(automationConfig);
|
|
104154
104869
|
const { AutomationStatusArtifact: ASA } = await Promise.resolve().then(() => (init_status_artifact(), exports_status_artifact));
|
|
104155
|
-
const swarmDir =
|
|
104870
|
+
const swarmDir = path143.resolve(ctx.directory, ".swarm");
|
|
104156
104871
|
statusArtifact = new ASA(swarmDir);
|
|
104157
104872
|
statusArtifact.updateConfig(automationConfig.mode, automationConfig.capabilities);
|
|
104158
104873
|
if (automationConfig.capabilities?.evidence_auto_summaries === true) {
|
|
@@ -104551,6 +105266,14 @@ async function initializeOpenCodeSwarm(ctx) {
|
|
|
104551
105266
|
return Promise.resolve();
|
|
104552
105267
|
}
|
|
104553
105268
|
},
|
|
105269
|
+
(input, output) => {
|
|
105270
|
+
try {
|
|
105271
|
+
const p = input;
|
|
105272
|
+
return skillPropagationTransformScan(ctx.directory, output, p.sessionID);
|
|
105273
|
+
} catch {
|
|
105274
|
+
return Promise.resolve();
|
|
105275
|
+
}
|
|
105276
|
+
},
|
|
104554
105277
|
(_input, output) => {
|
|
104555
105278
|
if (output.messages) {
|
|
104556
105279
|
output.messages = consolidateSystemMessages(output.messages);
|
|
@@ -104624,6 +105347,12 @@ async function initializeOpenCodeSwarm(ctx) {
|
|
|
104624
105347
|
agent: input.agent,
|
|
104625
105348
|
sessionID: input.sessionID
|
|
104626
105349
|
}, KnowledgeApplicationConfigSchema.parse(config3.knowledge_application ?? {}));
|
|
105350
|
+
await skillPropagationGateBefore(ctx.directory, {
|
|
105351
|
+
tool: input.tool,
|
|
105352
|
+
agent: input.agent,
|
|
105353
|
+
sessionID: input.sessionID,
|
|
105354
|
+
args: input.args
|
|
105355
|
+
}, { enabled: true });
|
|
104627
105356
|
if (swarmState.lastBudgetPct >= 50) {
|
|
104628
105357
|
const pressureSession = ensureAgentSession(input.sessionID, swarmState.activeAgent.get(input.sessionID) ?? ORCHESTRATOR_NAME);
|
|
104629
105358
|
if (!pressureSession.contextPressureWarningSent) {
|