opencode-swarm 7.46.5 → 7.47.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/agents/architect.d.ts +1 -1
- package/dist/agents/docs.d.ts +10 -1
- package/dist/background/event-bus.d.ts +1 -1
- package/dist/cli/index.js +178 -16
- package/dist/commands/design-docs.d.ts +6 -0
- package/dist/commands/registry.d.ts +14 -0
- package/dist/config/constants.d.ts +2 -2
- package/dist/config/schema.d.ts +11 -0
- package/dist/hooks/curator-types.d.ts +25 -0
- package/dist/hooks/design-doc-drift.d.ts +24 -0
- package/dist/index.js +910 -460
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -69,7 +69,7 @@ var package_default;
|
|
|
69
69
|
var init_package = __esm(() => {
|
|
70
70
|
package_default = {
|
|
71
71
|
name: "opencode-swarm",
|
|
72
|
-
version: "7.
|
|
72
|
+
version: "7.47.0",
|
|
73
73
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
74
74
|
main: "dist/index.js",
|
|
75
75
|
types: "dist/index.d.ts",
|
|
@@ -350,6 +350,7 @@ var init_constants = __esm(() => {
|
|
|
350
350
|
ALL_SUBAGENT_NAMES = [
|
|
351
351
|
"sme",
|
|
352
352
|
"docs",
|
|
353
|
+
"docs_design",
|
|
353
354
|
"designer",
|
|
354
355
|
"critic_sounding_board",
|
|
355
356
|
"critic_drift_verifier",
|
|
@@ -740,6 +741,19 @@ var init_constants = __esm(() => {
|
|
|
740
741
|
"summarize_work",
|
|
741
742
|
"swarm_command"
|
|
742
743
|
],
|
|
744
|
+
docs_design: [
|
|
745
|
+
"detect_domains",
|
|
746
|
+
"extract_code_blocks",
|
|
747
|
+
"imports",
|
|
748
|
+
"retrieve_summary",
|
|
749
|
+
"search",
|
|
750
|
+
"symbols",
|
|
751
|
+
"doc_scan",
|
|
752
|
+
"doc_extract",
|
|
753
|
+
"knowledge_recall",
|
|
754
|
+
"summarize_work",
|
|
755
|
+
"swarm_command"
|
|
756
|
+
],
|
|
743
757
|
designer: [
|
|
744
758
|
"extract_code_blocks",
|
|
745
759
|
"retrieve_summary",
|
|
@@ -793,6 +807,7 @@ var init_constants = __esm(() => {
|
|
|
793
807
|
critic_hallucination_verifier: ["swarm_memory_recall"],
|
|
794
808
|
critic_architecture_supervisor: ["swarm_memory_recall"],
|
|
795
809
|
docs: ["swarm_memory_recall", "swarm_memory_propose"],
|
|
810
|
+
docs_design: ["swarm_memory_recall", "swarm_memory_propose"],
|
|
796
811
|
designer: ["swarm_memory_recall", "swarm_memory_propose"],
|
|
797
812
|
curator_init: ["swarm_memory_recall"],
|
|
798
813
|
curator_phase: ["swarm_memory_recall"],
|
|
@@ -913,6 +928,7 @@ var init_constants = __esm(() => {
|
|
|
913
928
|
critic_oversight: "opencode/gpt-5-nano",
|
|
914
929
|
critic_architecture_supervisor: "opencode/big-pickle",
|
|
915
930
|
docs: "opencode/big-pickle",
|
|
931
|
+
docs_design: "opencode/big-pickle",
|
|
916
932
|
designer: "opencode/big-pickle",
|
|
917
933
|
curator_init: "opencode/gpt-5-nano",
|
|
918
934
|
curator_phase: "opencode/gpt-5-nano",
|
|
@@ -15136,7 +15152,7 @@ function resolveGuardrailsConfig(config2, agentName) {
|
|
|
15136
15152
|
};
|
|
15137
15153
|
return resolved;
|
|
15138
15154
|
}
|
|
15139
|
-
var _internals, SEPARATORS, CANONICAL_ROLES_LONGEST_FIRST, CANONICAL_ROLES_SET, AgentOverrideConfigSchema, SwarmConfigSchema, HooksConfigSchema, ScoringWeightsSchema, DecisionDecaySchema, TokenRatiosSchema, ScoringConfigSchema, ContextBudgetConfigSchema, EvidenceConfigSchema, GateFeatureSchema, PlaceholderScanConfigSchema, QualityBudgetConfigSchema, GateConfigSchema, PipelineConfigSchema, PhaseCompleteConfigSchema, SummaryConfigSchema, ReviewPassesConfigSchema, AdversarialDetectionConfigSchema, AdversarialTestingConfigSchemaBase, AdversarialTestingConfigSchema, IntegrationAnalysisConfigSchema, DocsConfigSchema, UIReviewConfigSchema, CompactionAdvisoryConfigSchema, LintConfigSchema, SecretscanConfigSchema, GuardrailsProfileSchema, DEFAULT_AGENT_PROFILES, DEFAULT_ARCHITECT_PROFILE, GuardrailsConfigSchema, WatchdogConfigSchema, SelfReviewConfigSchema, ToolFilterConfigSchema, PlanCursorConfigSchema, CheckpointConfigSchema, AutomationModeSchema, AutomationCapabilitiesSchema, AutomationConfigSchemaBase, AutomationConfigSchema, KnowledgeConfigSchema, MemoryConfigSchema, CuratorConfigSchema, ArchitecturalSupervisionConfigSchema, KnowledgeApplicationConfigSchema, SkillImproverConfigSchema, SpecWriterConfigSchema, SlopDetectorConfigSchema, IncrementalVerifyConfigSchema, CompactionConfigSchema, PrmConfigSchema, AgentAuthorityRuleSchema, AuthorityConfigSchema, GeneralCouncilMemberConfigSchema, GeneralCouncilConfigSchema, CouncilConfigSchema, ParallelizationConfigSchema, LeanTurboConfigSchema, StandardTurboConfigSchema, LeanTurboStrategyConfigSchema, TurboConfigSchema, PluginConfigSchema;
|
|
15155
|
+
var _internals, SEPARATORS, CANONICAL_ROLES_LONGEST_FIRST, CANONICAL_ROLES_SET, AgentOverrideConfigSchema, SwarmConfigSchema, HooksConfigSchema, ScoringWeightsSchema, DecisionDecaySchema, TokenRatiosSchema, ScoringConfigSchema, ContextBudgetConfigSchema, EvidenceConfigSchema, GateFeatureSchema, PlaceholderScanConfigSchema, QualityBudgetConfigSchema, GateConfigSchema, PipelineConfigSchema, PhaseCompleteConfigSchema, SummaryConfigSchema, ReviewPassesConfigSchema, AdversarialDetectionConfigSchema, AdversarialTestingConfigSchemaBase, AdversarialTestingConfigSchema, IntegrationAnalysisConfigSchema, DocsConfigSchema, DesignDocsConfigSchema, UIReviewConfigSchema, CompactionAdvisoryConfigSchema, LintConfigSchema, SecretscanConfigSchema, GuardrailsProfileSchema, DEFAULT_AGENT_PROFILES, DEFAULT_ARCHITECT_PROFILE, GuardrailsConfigSchema, WatchdogConfigSchema, SelfReviewConfigSchema, ToolFilterConfigSchema, PlanCursorConfigSchema, CheckpointConfigSchema, AutomationModeSchema, AutomationCapabilitiesSchema, AutomationConfigSchemaBase, AutomationConfigSchema, KnowledgeConfigSchema, MemoryConfigSchema, CuratorConfigSchema, ArchitecturalSupervisionConfigSchema, KnowledgeApplicationConfigSchema, SkillImproverConfigSchema, SpecWriterConfigSchema, SlopDetectorConfigSchema, IncrementalVerifyConfigSchema, CompactionConfigSchema, PrmConfigSchema, AgentAuthorityRuleSchema, AuthorityConfigSchema, GeneralCouncilMemberConfigSchema, GeneralCouncilConfigSchema, CouncilConfigSchema, ParallelizationConfigSchema, LeanTurboConfigSchema, StandardTurboConfigSchema, LeanTurboStrategyConfigSchema, TurboConfigSchema, PluginConfigSchema;
|
|
15140
15156
|
var init_schema = __esm(() => {
|
|
15141
15157
|
init_zod();
|
|
15142
15158
|
init_constants();
|
|
@@ -15339,6 +15355,13 @@ var init_schema = __esm(() => {
|
|
|
15339
15355
|
"**/CHANGELOG.md"
|
|
15340
15356
|
])
|
|
15341
15357
|
});
|
|
15358
|
+
DesignDocsConfigSchema = exports_external.object({
|
|
15359
|
+
enabled: exports_external.boolean().default(false),
|
|
15360
|
+
out_dir: exports_external.string().default("docs").refine((v) => v.length > 0 && v !== "." && !v.includes("..") && !v.startsWith("/") && !v.startsWith("\\") && !/^[A-Za-z]:/.test(v), {
|
|
15361
|
+
message: 'design_docs.out_dir must be a non-empty project-relative path with no "..", leading slash, or drive letter'
|
|
15362
|
+
}),
|
|
15363
|
+
language: exports_external.string().optional()
|
|
15364
|
+
});
|
|
15342
15365
|
UIReviewConfigSchema = exports_external.object({
|
|
15343
15366
|
enabled: exports_external.boolean().default(false),
|
|
15344
15367
|
trigger_paths: exports_external.array(exports_external.string()).default([
|
|
@@ -15862,6 +15885,7 @@ var init_schema = __esm(() => {
|
|
|
15862
15885
|
adversarial_testing: AdversarialTestingConfigSchema.optional(),
|
|
15863
15886
|
integration_analysis: IntegrationAnalysisConfigSchema.optional(),
|
|
15864
15887
|
docs: DocsConfigSchema.optional(),
|
|
15888
|
+
design_docs: DesignDocsConfigSchema.optional(),
|
|
15865
15889
|
ui_review: UIReviewConfigSchema.optional(),
|
|
15866
15890
|
compaction_advisory: CompactionAdvisoryConfigSchema.optional(),
|
|
15867
15891
|
lint: LintConfigSchema.optional(),
|
|
@@ -40256,6 +40280,18 @@ var init_guardrails = __esm(() => {
|
|
|
40256
40280
|
allowedGlobs: ["**/docs/**", "**/*.md", "**/*.mdx", "**/*.rst"],
|
|
40257
40281
|
blockedZones: ["generated"]
|
|
40258
40282
|
},
|
|
40283
|
+
docs_design: {
|
|
40284
|
+
allowedPrefix: ["docs/", ".swarm/outputs/"],
|
|
40285
|
+
blockedGlobs: ["src/**", "lib/**"],
|
|
40286
|
+
allowedGlobs: [
|
|
40287
|
+
"**/docs/**",
|
|
40288
|
+
"**/*.md",
|
|
40289
|
+
"**/*.mdx",
|
|
40290
|
+
"**/*.rst",
|
|
40291
|
+
"**/reference/traceability.json"
|
|
40292
|
+
],
|
|
40293
|
+
blockedZones: ["generated"]
|
|
40294
|
+
},
|
|
40259
40295
|
designer: {
|
|
40260
40296
|
allowedPrefix: ["docs/", ".swarm/outputs/"],
|
|
40261
40297
|
allowedGlobs: ["**/docs/**", "**/*.md", "**/*.mdx", "**/*.rst"],
|
|
@@ -62438,6 +62474,122 @@ var init_deep_dive = __esm(() => {
|
|
|
62438
62474
|
]);
|
|
62439
62475
|
});
|
|
62440
62476
|
|
|
62477
|
+
// src/commands/design-docs.ts
|
|
62478
|
+
function sanitizeDescription(raw) {
|
|
62479
|
+
const collapsed = raw.replace(/\s+/g, " ").trim();
|
|
62480
|
+
const stripped1 = collapsed.replace(/\[\s*MODE\s*:[^\]]*\]/gi, "");
|
|
62481
|
+
const stripped2 = stripped1.replace(/\[\s*MODE\s*:.*$/gi, "");
|
|
62482
|
+
const normalized = stripped2.replace(/\s+/g, " ").trim();
|
|
62483
|
+
if (normalized.length <= MAX_DESC_LEN)
|
|
62484
|
+
return normalized;
|
|
62485
|
+
return `${normalized.slice(0, MAX_DESC_LEN)}…`;
|
|
62486
|
+
}
|
|
62487
|
+
function cleanFlagValue(raw) {
|
|
62488
|
+
if (raw.includes("[") || raw.includes("]") || /\s/.test(raw))
|
|
62489
|
+
return null;
|
|
62490
|
+
if (/\[\s*MODE\s*:/i.test(raw))
|
|
62491
|
+
return null;
|
|
62492
|
+
return raw;
|
|
62493
|
+
}
|
|
62494
|
+
function parseArgs3(args2) {
|
|
62495
|
+
const result = {
|
|
62496
|
+
out: "docs",
|
|
62497
|
+
lang: "auto",
|
|
62498
|
+
update: false,
|
|
62499
|
+
rest: []
|
|
62500
|
+
};
|
|
62501
|
+
let i2 = 0;
|
|
62502
|
+
while (i2 < args2.length) {
|
|
62503
|
+
const token = args2[i2];
|
|
62504
|
+
if (token === "--out") {
|
|
62505
|
+
if (i2 + 1 >= args2.length || args2[i2 + 1].startsWith("--")) {
|
|
62506
|
+
return { ...result, error: `Flag "${token}" requires a value` };
|
|
62507
|
+
}
|
|
62508
|
+
const value = args2[++i2];
|
|
62509
|
+
const clean = cleanFlagValue(value);
|
|
62510
|
+
if (clean === null || value.includes("..") || value.startsWith("/") || value.startsWith("\\") || /^[A-Za-z]:/.test(value)) {
|
|
62511
|
+
return {
|
|
62512
|
+
...result,
|
|
62513
|
+
error: `Invalid --out value "${value}". Must be a project-relative directory with no brackets or spaces.`
|
|
62514
|
+
};
|
|
62515
|
+
}
|
|
62516
|
+
const trimmed = clean.replace(/[/\\]+$/, "");
|
|
62517
|
+
if (!trimmed || trimmed === ".") {
|
|
62518
|
+
return {
|
|
62519
|
+
...result,
|
|
62520
|
+
error: `Invalid --out value "${value}". Must name a non-empty subdirectory.`
|
|
62521
|
+
};
|
|
62522
|
+
}
|
|
62523
|
+
result.out = trimmed;
|
|
62524
|
+
} else if (token === "--lang") {
|
|
62525
|
+
if (i2 + 1 >= args2.length || args2[i2 + 1].startsWith("--")) {
|
|
62526
|
+
return { ...result, error: `Flag "${token}" requires a value` };
|
|
62527
|
+
}
|
|
62528
|
+
const value = args2[++i2];
|
|
62529
|
+
const clean = cleanFlagValue(value);
|
|
62530
|
+
if (clean === null) {
|
|
62531
|
+
return {
|
|
62532
|
+
...result,
|
|
62533
|
+
error: `Invalid --lang value "${value}". Must be a single token with no brackets or spaces.`
|
|
62534
|
+
};
|
|
62535
|
+
}
|
|
62536
|
+
result.lang = clean;
|
|
62537
|
+
} else if (token === "--update") {
|
|
62538
|
+
result.update = true;
|
|
62539
|
+
} else if (token.startsWith("--")) {
|
|
62540
|
+
return { ...result, error: `Unknown flag "${token}"` };
|
|
62541
|
+
} else {
|
|
62542
|
+
result.rest.push(token);
|
|
62543
|
+
}
|
|
62544
|
+
i2++;
|
|
62545
|
+
}
|
|
62546
|
+
return result;
|
|
62547
|
+
}
|
|
62548
|
+
async function handleDesignDocsCommand(directory, args2) {
|
|
62549
|
+
const parsed = parseArgs3(args2);
|
|
62550
|
+
if (parsed.error) {
|
|
62551
|
+
return `Error: ${parsed.error}
|
|
62552
|
+
|
|
62553
|
+
${USAGE3}`;
|
|
62554
|
+
}
|
|
62555
|
+
try {
|
|
62556
|
+
const { config: config3 } = loadPluginConfigWithMeta(directory);
|
|
62557
|
+
if (config3.design_docs?.enabled !== true) {
|
|
62558
|
+
return "Error: design docs are disabled. Set `design_docs.enabled: true` in " + `opencode-swarm.json to enable the docs_design agent and this command.
|
|
62559
|
+
|
|
62560
|
+
` + USAGE3;
|
|
62561
|
+
}
|
|
62562
|
+
} catch (configErr) {
|
|
62563
|
+
console.warn(`[design-docs] Could not read opencode-swarm.json (${String(configErr)}). ` + "Falling through — the architect will abort if docs_design is not registered.");
|
|
62564
|
+
}
|
|
62565
|
+
const description = sanitizeDescription(parsed.rest.join(" "));
|
|
62566
|
+
if (!description && !parsed.update) {
|
|
62567
|
+
return USAGE3;
|
|
62568
|
+
}
|
|
62569
|
+
const header = `[MODE: DESIGN_DOCS out=${parsed.out} lang=${parsed.lang} update=${parsed.update}] ${description}`;
|
|
62570
|
+
return header.trimEnd();
|
|
62571
|
+
}
|
|
62572
|
+
var MAX_DESC_LEN = 2000, USAGE3 = `Usage: /swarm design-docs <description> [--out <dir>] [--lang <name>] [--update]
|
|
62573
|
+
|
|
62574
|
+
Generate or sync language-agnostic design docs for the project under build:
|
|
62575
|
+
<out>/domain.md, <out>/technical-spec.md, <out>/behavior-spec.md,
|
|
62576
|
+
<out>/reference/{reference-impl,idiom-notes}.md, <out>/reference/traceability.json
|
|
62577
|
+
|
|
62578
|
+
Requires design_docs.enabled: true in opencode-swarm.json.
|
|
62579
|
+
|
|
62580
|
+
Examples:
|
|
62581
|
+
/swarm design-docs "terminal GitHub PR client"
|
|
62582
|
+
/swarm design-docs auth-service --lang rust
|
|
62583
|
+
/swarm design docs --update --out design
|
|
62584
|
+
|
|
62585
|
+
Flags:
|
|
62586
|
+
--out <dir> output directory (default "docs")
|
|
62587
|
+
--lang <name> target language for the reference/ docs (default: inferred)
|
|
62588
|
+
--update sync existing docs to current code/spec instead of generating fresh`;
|
|
62589
|
+
var init_design_docs = __esm(() => {
|
|
62590
|
+
init_config();
|
|
62591
|
+
});
|
|
62592
|
+
|
|
62441
62593
|
// src/config/cache-paths.ts
|
|
62442
62594
|
import * as os10 from "node:os";
|
|
62443
62595
|
import * as path35 from "node:path";
|
|
@@ -67940,7 +68092,7 @@ function validateAndSanitizeUrl(rawUrl) {
|
|
|
67940
68092
|
return { error: "Invalid URL format" };
|
|
67941
68093
|
}
|
|
67942
68094
|
}
|
|
67943
|
-
function
|
|
68095
|
+
function parseArgs4(args2) {
|
|
67944
68096
|
const out2 = {
|
|
67945
68097
|
plan: false,
|
|
67946
68098
|
trace: false,
|
|
@@ -68031,24 +68183,24 @@ function parseGitRemoteUrl(remoteUrl) {
|
|
|
68031
68183
|
return null;
|
|
68032
68184
|
}
|
|
68033
68185
|
function handleIssueCommand(_directory, args2) {
|
|
68034
|
-
const parsed =
|
|
68186
|
+
const parsed = parseArgs4(args2);
|
|
68035
68187
|
const rawInput = parsed.rest.join(" ").trim();
|
|
68036
68188
|
if (!rawInput) {
|
|
68037
|
-
return
|
|
68189
|
+
return USAGE4;
|
|
68038
68190
|
}
|
|
68039
68191
|
const isFullUrl = /^https?:\/\//i.test(rawInput);
|
|
68040
68192
|
const issueInfo = parseIssueRef(isFullUrl ? sanitizeUrl(rawInput) : rawInput);
|
|
68041
68193
|
if (!issueInfo) {
|
|
68042
68194
|
return `Error: Could not parse issue reference from "${rawInput}"
|
|
68043
68195
|
|
|
68044
|
-
${
|
|
68196
|
+
${USAGE4}`;
|
|
68045
68197
|
}
|
|
68046
68198
|
const issueUrl = `https://github.com/${issueInfo.owner}/${issueInfo.repo}/issues/${issueInfo.number}`;
|
|
68047
68199
|
const result = validateAndSanitizeUrl(issueUrl);
|
|
68048
68200
|
if ("error" in result) {
|
|
68049
68201
|
return `Error: ${result.error}
|
|
68050
68202
|
|
|
68051
|
-
${
|
|
68203
|
+
${USAGE4}`;
|
|
68052
68204
|
}
|
|
68053
68205
|
const flags2 = [];
|
|
68054
68206
|
if (parsed.plan)
|
|
@@ -68060,9 +68212,9 @@ ${USAGE3}`;
|
|
|
68060
68212
|
const flagsStr = flags2.length > 0 ? ` ${flags2.join(" ")}` : "";
|
|
68061
68213
|
return `[MODE: ISSUE_INGEST issue="${result.sanitized}"${flagsStr}]`;
|
|
68062
68214
|
}
|
|
68063
|
-
var MAX_URL_LEN = 2048,
|
|
68215
|
+
var MAX_URL_LEN = 2048, USAGE4;
|
|
68064
68216
|
var init_issue = __esm(() => {
|
|
68065
|
-
|
|
68217
|
+
USAGE4 = [
|
|
68066
68218
|
"Usage: /swarm issue <url|owner/repo#N|N> [--plan] [--trace] [--no-repro]",
|
|
68067
68219
|
"",
|
|
68068
68220
|
"Ingest a GitHub issue into the swarm workflow.",
|
|
@@ -73009,7 +73161,7 @@ function validateAndSanitizeUrl2(rawUrl) {
|
|
|
73009
73161
|
return { error: "Invalid URL format" };
|
|
73010
73162
|
}
|
|
73011
73163
|
}
|
|
73012
|
-
function
|
|
73164
|
+
function parseArgs5(args2) {
|
|
73013
73165
|
const out2 = { council: false, rest: [] };
|
|
73014
73166
|
for (const token of args2) {
|
|
73015
73167
|
if (token === "--council") {
|
|
@@ -73093,31 +73245,31 @@ function parseGitRemoteUrl2(remoteUrl) {
|
|
|
73093
73245
|
return null;
|
|
73094
73246
|
}
|
|
73095
73247
|
function handlePrReviewCommand(_directory, args2) {
|
|
73096
|
-
const parsed =
|
|
73248
|
+
const parsed = parseArgs5(args2);
|
|
73097
73249
|
const rawInput = parsed.rest.join(" ").trim();
|
|
73098
73250
|
if (!rawInput) {
|
|
73099
|
-
return
|
|
73251
|
+
return USAGE5;
|
|
73100
73252
|
}
|
|
73101
73253
|
const isFullUrl = /^https?:\/\//i.test(rawInput);
|
|
73102
73254
|
const prInfo = parsePrRef(isFullUrl ? sanitizeUrl2(rawInput) : rawInput);
|
|
73103
73255
|
if (!prInfo) {
|
|
73104
73256
|
return `Error: Could not parse PR reference from "${rawInput}"
|
|
73105
73257
|
|
|
73106
|
-
${
|
|
73258
|
+
${USAGE5}`;
|
|
73107
73259
|
}
|
|
73108
73260
|
const prUrl = `https://github.com/${prInfo.owner}/${prInfo.repo}/pull/${prInfo.number}`;
|
|
73109
73261
|
const result = validateAndSanitizeUrl2(prUrl);
|
|
73110
73262
|
if ("error" in result) {
|
|
73111
73263
|
return `Error: ${result.error}
|
|
73112
73264
|
|
|
73113
|
-
${
|
|
73265
|
+
${USAGE5}`;
|
|
73114
73266
|
}
|
|
73115
73267
|
const councilFlag = parsed.council ? "council=true" : "council=false";
|
|
73116
73268
|
return `[MODE: PR_REVIEW pr="${result.sanitized}" ${councilFlag}]`;
|
|
73117
73269
|
}
|
|
73118
|
-
var MAX_URL_LEN2 = 2048,
|
|
73270
|
+
var MAX_URL_LEN2 = 2048, USAGE5;
|
|
73119
73271
|
var init_pr_review = __esm(() => {
|
|
73120
|
-
|
|
73272
|
+
USAGE5 = [
|
|
73121
73273
|
"Usage: /swarm pr-review <url|owner/repo#N|N> [--council]",
|
|
73122
73274
|
"",
|
|
73123
73275
|
"Run a full swarm PR review on a GitHub pull request.",
|
|
@@ -81887,6 +82039,7 @@ var init_registry = __esm(() => {
|
|
|
81887
82039
|
init_curate();
|
|
81888
82040
|
init_dark_matter();
|
|
81889
82041
|
init_deep_dive();
|
|
82042
|
+
init_design_docs();
|
|
81890
82043
|
init_diagnose();
|
|
81891
82044
|
init_doctor();
|
|
81892
82045
|
init_evidence();
|
|
@@ -82202,6 +82355,20 @@ Subcommands:
|
|
|
82202
82355
|
category: "agent",
|
|
82203
82356
|
aliasOf: "deep-dive"
|
|
82204
82357
|
},
|
|
82358
|
+
"design-docs": {
|
|
82359
|
+
handler: async (ctx) => handleDesignDocsCommand(ctx.directory, ctx.args),
|
|
82360
|
+
description: "Generate or sync language-agnostic design docs (domain, technical-spec, behavior-spec, reference/) for the project under build [description]",
|
|
82361
|
+
args: "<description> [--out <dir>] [--lang <name>] [--update]",
|
|
82362
|
+
details: "Triggers the architect to enter MODE: DESIGN_DOCS — delegates to the docs_design agent to author/sync docs/domain.md, docs/technical-spec.md, docs/behavior-spec.md, and docs/reference/* (plus reference/traceability.json and design-changelog.md). Normative docs are 100% language-agnostic; all framework-specific material is quarantined under reference/. --update syncs existing docs to current code/spec instead of generating fresh. Requires design_docs.enabled: true.",
|
|
82363
|
+
category: "agent"
|
|
82364
|
+
},
|
|
82365
|
+
"design docs": {
|
|
82366
|
+
handler: async (ctx) => handleDesignDocsCommand(ctx.directory, ctx.args),
|
|
82367
|
+
description: "Alias for /swarm design-docs — generate or sync design docs",
|
|
82368
|
+
args: "<description> [--out <dir>] [--lang <name>] [--update]",
|
|
82369
|
+
category: "agent",
|
|
82370
|
+
aliasOf: "design-docs"
|
|
82371
|
+
},
|
|
82205
82372
|
issue: {
|
|
82206
82373
|
handler: async (ctx) => handleIssueCommand(ctx.directory, ctx.args),
|
|
82207
82374
|
description: "Ingest a GitHub issue into the swarm workflow [url] [--plan] [--trace] [--no-repro]",
|
|
@@ -82761,7 +82928,7 @@ function buildSlashCommandsList() {
|
|
|
82761
82928
|
return lines.join(`
|
|
82762
82929
|
`);
|
|
82763
82930
|
}
|
|
82764
|
-
function createArchitectAgent(model, customPrompt, customAppendPrompt, adversarialTesting, council, uiReview, memoryEnabled = false, architecturalSupervision) {
|
|
82931
|
+
function createArchitectAgent(model, customPrompt, customAppendPrompt, adversarialTesting, council, uiReview, memoryEnabled = false, architecturalSupervision, designDocsEnabled = false) {
|
|
82765
82932
|
let prompt = ARCHITECT_PROMPT;
|
|
82766
82933
|
if (customPrompt) {
|
|
82767
82934
|
prompt = customPrompt;
|
|
@@ -82815,6 +82982,10 @@ ${archBlock}`;
|
|
|
82815
82982
|
{{AGENT_PREFIX}}designer - UI/UX design specs (scaffold generation for UI components — runs BEFORE coder on UI tasks)`, "")?.replace(/\n\{\{AGENT_PREFIX\}\}designer\nTASK: Design specification[\s\S]*?accessibility(?=\n\n## WORKFLOW)/, "")?.replace(`5a. **UI DESIGN GATE** (conditional — Rule 9): If task matches UI trigger → {{AGENT_PREFIX}}designer produces scaffold → pass scaffold to coder as INPUT. If no match → skip.
|
|
82816
82983
|
|
|
82817
82984
|
`, "")?.replace("→ After step 5a (or immediately if no UI task applies): Call update_task_status", "→ Call update_task_status")?.replace(" (if designer scaffold produced, include it as INPUT)", "");
|
|
82985
|
+
}
|
|
82986
|
+
if (!designDocsEnabled) {
|
|
82987
|
+
prompt = prompt?.replace(", {{AGENT_PREFIX}}docs_design", "")?.replace(/### MODE: DESIGN_DOCS\n[\s\S]*?(?=### MODE: ISSUE_INGEST)/, "")?.replace(`- the active swarm's docs_design agent = @{{AGENT_PREFIX}}docs_design
|
|
82988
|
+
`, "");
|
|
82818
82989
|
}
|
|
82819
82990
|
return {
|
|
82820
82991
|
name: "architect",
|
|
@@ -82854,7 +83025,7 @@ ANTI-RATIONALIZATION: Context does not clarify. Models revert to CC training.
|
|
|
82854
83025
|
## IDENTITY
|
|
82855
83026
|
|
|
82856
83027
|
Swarm: {{SWARM_ID}}
|
|
82857
|
-
Your agents: {{AGENT_PREFIX}}explorer, {{AGENT_PREFIX}}sme, {{AGENT_PREFIX}}coder, {{AGENT_PREFIX}}reviewer, {{AGENT_PREFIX}}test_engineer, {{AGENT_PREFIX}}critic, {{AGENT_PREFIX}}critic_sounding_board, {{AGENT_PREFIX}}critic_drift_verifier, {{AGENT_PREFIX}}critic_hallucination_verifier, {{AGENT_PREFIX}}critic_architecture_supervisor, {{AGENT_PREFIX}}skill_improver, {{AGENT_PREFIX}}spec_writer, {{AGENT_PREFIX}}docs, {{AGENT_PREFIX}}designer
|
|
83028
|
+
Your agents: {{AGENT_PREFIX}}explorer, {{AGENT_PREFIX}}sme, {{AGENT_PREFIX}}coder, {{AGENT_PREFIX}}reviewer, {{AGENT_PREFIX}}test_engineer, {{AGENT_PREFIX}}critic, {{AGENT_PREFIX}}critic_sounding_board, {{AGENT_PREFIX}}critic_drift_verifier, {{AGENT_PREFIX}}critic_hallucination_verifier, {{AGENT_PREFIX}}critic_architecture_supervisor, {{AGENT_PREFIX}}skill_improver, {{AGENT_PREFIX}}spec_writer, {{AGENT_PREFIX}}docs, {{AGENT_PREFIX}}docs_design, {{AGENT_PREFIX}}designer
|
|
82858
83029
|
|
|
82859
83030
|
## PROJECT CONTEXT
|
|
82860
83031
|
Session-start priming block. Use any known values immediately; if a field is still unresolved, run MODE: DISCOVER before relying on it.
|
|
@@ -83427,6 +83598,7 @@ Every loaded mode skill is written with active-swarm role phrases. Before follow
|
|
|
83427
83598
|
- the active swarm's test_engineer agent = @{{AGENT_PREFIX}}test_engineer
|
|
83428
83599
|
- the active swarm's critic agent = @{{AGENT_PREFIX}}critic
|
|
83429
83600
|
- the active swarm's docs agent = @{{AGENT_PREFIX}}docs
|
|
83601
|
+
- the active swarm's docs_design agent = @{{AGENT_PREFIX}}docs_design
|
|
83430
83602
|
- the active swarm's designer agent = @{{AGENT_PREFIX}}designer
|
|
83431
83603
|
- the active swarm's critic_drift_verifier agent = @{{AGENT_PREFIX}}critic_drift_verifier
|
|
83432
83604
|
- the active swarm's critic_hallucination_verifier agent = @{{AGENT_PREFIX}}critic_hallucination_verifier
|
|
@@ -83559,6 +83731,20 @@ HARD CONSTRAINTS (apply regardless of skill load success):
|
|
|
83559
83731
|
- Explorers generate candidate findings only — reviewers verify or reject
|
|
83560
83732
|
- Critics challenge only HIGH/CRITICAL findings — do NOT waste cycles on lower severity
|
|
83561
83733
|
|
|
83734
|
+
### MODE: DESIGN_DOCS
|
|
83735
|
+
Activates when: architect receives \`[MODE: DESIGN_DOCS out=X lang=X update=X] <description>\` signal from the design-docs command handler (issue #1080).
|
|
83736
|
+
|
|
83737
|
+
Purpose: Generate or sync the project's structured, language-agnostic design docs (domain.md, technical-spec.md, behavior-spec.md, reference/) in the target project repo. Authoring is delegated to the active swarm's docs_design agent.
|
|
83738
|
+
|
|
83739
|
+
ACTION: Load skill file:.opencode/skills/design-docs/SKILL.md immediately and follow its protocol.
|
|
83740
|
+
|
|
83741
|
+
HARD CONSTRAINTS (apply regardless of skill load success):
|
|
83742
|
+
- Delegate authoring to the active swarm's docs_design agent (never the standard docs agent, never coder).
|
|
83743
|
+
- Inject the design-docs skill into the docs_design delegation via the SKILLS field as \`file:.opencode/skills/design-docs/SKILL.md\`.
|
|
83744
|
+
- The docs_design agent may create/modify ONLY: <out>/domain.md, <out>/technical-spec.md, <out>/behavior-spec.md, <out>/reference/reference-impl.md, <out>/reference/idiom-notes.md, <out>/reference/traceability.json, and <out>/design-changelog.md. No other files.
|
|
83745
|
+
- Do NOT touch .swarm/spec.md, CHANGELOG.md, or docs/releases/pending/* in this mode.
|
|
83746
|
+
- Requires design_docs.enabled: true — if the docs_design agent is not registered, instruct the user to enable it and stop.
|
|
83747
|
+
|
|
83562
83748
|
### MODE: ISSUE_INGEST
|
|
83563
83749
|
Activates when the user invokes /swarm issue <url> or the architect receives an ISSUE_INGEST signal.
|
|
83564
83750
|
|
|
@@ -84941,18 +85127,19 @@ RULES:
|
|
|
84941
85127
|
`;
|
|
84942
85128
|
|
|
84943
85129
|
// src/agents/docs.ts
|
|
84944
|
-
function createDocsAgent(model, customPrompt, customAppendPrompt) {
|
|
84945
|
-
|
|
85130
|
+
function createDocsAgent(model, customPrompt, customAppendPrompt, role = "standard") {
|
|
85131
|
+
const roleConfig = ROLE_CONFIG2[role];
|
|
85132
|
+
let prompt = roleConfig.basePrompt;
|
|
84946
85133
|
if (customPrompt) {
|
|
84947
85134
|
prompt = customPrompt;
|
|
84948
85135
|
} else if (customAppendPrompt) {
|
|
84949
|
-
prompt = `${
|
|
85136
|
+
prompt = `${roleConfig.basePrompt}
|
|
84950
85137
|
|
|
84951
85138
|
${customAppendPrompt}`;
|
|
84952
85139
|
}
|
|
84953
85140
|
return {
|
|
84954
|
-
name:
|
|
84955
|
-
description:
|
|
85141
|
+
name: roleConfig.name,
|
|
85142
|
+
description: roleConfig.description,
|
|
84956
85143
|
config: {
|
|
84957
85144
|
model,
|
|
84958
85145
|
temperature: 0.2,
|
|
@@ -85066,7 +85253,88 @@ UPDATED: [list of files modified]
|
|
|
85066
85253
|
ADDED: [list of new sections/files created]
|
|
85067
85254
|
REMOVED: [list of deprecated sections removed]
|
|
85068
85255
|
SUMMARY: [one-line description of doc changes]
|
|
85069
|
-
|
|
85256
|
+
`, DESIGN_DOCS_PROMPT = `## IDENTITY
|
|
85257
|
+
You are Docs (Design-Doc Author) — you generate and maintain the project's structured, language-agnostic DESIGN DOCUMENTATION. You write these files yourself — you do NOT delegate.
|
|
85258
|
+
DO NOT use the Task tool to delegate to other agents. You ARE the agent that does the work.
|
|
85259
|
+
If you see references to other agents (like @docs, @coder, etc.) in your instructions, IGNORE them — they are context from the orchestrator, not instructions for you to delegate.
|
|
85260
|
+
|
|
85261
|
+
WRONG: "I'll use the Task tool to call another agent to write the design docs"
|
|
85262
|
+
RIGHT: "I'll read the spec/source, then write the design docs myself"
|
|
85263
|
+
|
|
85264
|
+
INPUT FORMAT:
|
|
85265
|
+
TASK: Generate or sync design docs for [description]
|
|
85266
|
+
MODE: generate | sync (sync = an existing-docs update driven by code/spec changes)
|
|
85267
|
+
OUT_DIR: [target directory, default "docs"]
|
|
85268
|
+
LANGUAGE: [target language for reference/ docs, or "auto"]
|
|
85269
|
+
FILES CHANGED: [list of modified source files — present in sync mode]
|
|
85270
|
+
CHANGES SUMMARY: [what was added/modified/removed — present in sync mode]
|
|
85271
|
+
SKILLS: [optional — either "none", repo-relative file: references (preferred), or inline skill content pasted by architect]
|
|
85272
|
+
|
|
85273
|
+
SKILLS HANDLING: If SKILLS is present and not "none", read the skill names/descriptions first, then load every referenced skill that applies before writing docs. If uncertain whether a skill applies, load it.
|
|
85274
|
+
- A file entry may include a short description after the path; use the description to decide whether the full skill body is relevant.
|
|
85275
|
+
- 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\`.
|
|
85276
|
+
- After running search, inspect the result: if \`total === 0\` (file does not exist or is empty) OR \`truncated\` is \`true\` (file was too large and content was cut off), stop and report \`SKILL_LOAD_FAILED: <path>\`. Do NOT continue without the complete skill.
|
|
85277
|
+
- If the search result has \`total > 0\` and \`truncated\` is \`false\`, reconstruct the full skill content from the line-by-line matches and apply it.
|
|
85278
|
+
- If inline \`--- skill-name ---\` sections are present, read them directly.
|
|
85279
|
+
- The design-docs SKILL.md is the authoritative protocol — follow its layout, section-ID, version-header, traceability, and changelog rules exactly.
|
|
85280
|
+
|
|
85281
|
+
SCOPE — you OWN exactly these files under OUT_DIR (default "docs"):
|
|
85282
|
+
- domain.md — 100% language-agnostic. Entities/fields in neutral notation (field: type-class), domain invariants. ZERO framework names in normative text.
|
|
85283
|
+
- technical-spec.md — language-agnostic architecture: layers, dependency rules, contract SHAPES (inputs→outputs→error-kinds), algorithms, invariants. Plus the human-readable traceability table.
|
|
85284
|
+
- behavior-spec.md — 100% language-agnostic Given/When/Then conformance specs.
|
|
85285
|
+
- reference/reference-impl.md — ALL language/framework-specific material: exact signatures, CLI strings, SQL, code. Mapped back to spec sections by ID.
|
|
85286
|
+
- reference/idiom-notes.md — "here is how the reference solved X" — examples only.
|
|
85287
|
+
- reference/traceability.json — machine-readable section-ID registry (see below). The SINGLE SOURCE OF TRUTH for drift mapping.
|
|
85288
|
+
- design-changelog.md — append-only Keep-a-Changelog log of design-doc changes.
|
|
85289
|
+
|
|
85290
|
+
IMPORTANT — this OVERRIDES the standard docs agent rule "NEVER create new documentation files": creating and maintaining the files above IS your job. But do NOT create any files outside this list.
|
|
85291
|
+
|
|
85292
|
+
LANGUAGE-AGNOSTIC RULE: domain.md, technical-spec.md, and behavior-spec.md MUST contain ZERO framework/library/language names in their normative text. ALL incidental, language-specific material (TS/Effect signatures, gh-CLI strings, SQL, exact code) belongs ONLY in reference/.
|
|
85293
|
+
|
|
85294
|
+
SECTION IDs & VERSION HEADER:
|
|
85295
|
+
- Every doc starts with: \`<!-- design-doc: <name> version: <phase-or-counter> generated: <ISO-8601> spec-hash: <8 chars> -->\`
|
|
85296
|
+
- Section IDs are assigned ONCE and NEVER renumbered: D-### (domain), S-### (technical-spec), B-### (behavior-spec), R-### (reference).
|
|
85297
|
+
- Each section ends with a traceability footer: \`> Traceability: FR-012, FR-013 | invariant: <id-or-none>\`.
|
|
85298
|
+
- On a SYNC, FIRST read OUT_DIR/reference/traceability.json and the existing docs; REUSE every existing section ID; mint a new ID only for a genuinely new section; record adds/removes in design-changelog.md.
|
|
85299
|
+
|
|
85300
|
+
TRACEABILITY REGISTRY (reference/traceability.json):
|
|
85301
|
+
- A JSON object \`{ "schema_version": 1, "sections": [ { "section_id": "S-001", "doc": "technical-spec", "title": "...", "spec_frs": ["FR-003"], "invariants": ["INV-..."], "code_anchors": ["src/foo.ts"] }, ... ] }\`.
|
|
85302
|
+
- Keep it in sync with the docs on every generate/sync. technical-spec.md must render a human-readable mirror: \`| Doc Section | Spec FR | Invariant | Code anchors |\`.
|
|
85303
|
+
|
|
85304
|
+
CHANGELOG (design-changelog.md):
|
|
85305
|
+
- This is SEPARATE from CHANGELOG.md and docs/releases/pending/* (release-please owns those). NEVER touch release files here.
|
|
85306
|
+
- Append an entry per generate/sync: \`- <ISO date> phase <N>: <sections touched> (<FR refs>)\` under \`## [Unreleased]\` using Keep a Changelog headings (Added/Changed/Removed).
|
|
85307
|
+
|
|
85308
|
+
GUARDRAIL NOTE: if a spec-staleness block is reported when you try to write, surface it (SPEC_STALENESS_BLOCK) rather than retrying blindly — the architect resolves spec staleness first.
|
|
85309
|
+
|
|
85310
|
+
## QUALITY RULES
|
|
85311
|
+
- Normative docs (domain/technical-spec/behavior-spec) describe WHAT each boundary guarantees, not which library provides it.
|
|
85312
|
+
- Code examples live ONLY in reference/ and MUST be syntactically valid for LANGUAGE.
|
|
85313
|
+
- Be accurate: docs MUST match the actual spec (.swarm/spec.md) and code. No fabrication — if behavior is undetermined, say so explicitly.
|
|
85314
|
+
- On sync, update ONLY the sections affected by FILES CHANGED / CHANGES SUMMARY; do not rewrite untouched sections or renumber IDs.
|
|
85315
|
+
|
|
85316
|
+
OUTPUT FORMAT (MANDATORY — deviations will be rejected):
|
|
85317
|
+
Begin directly with UPDATED. Do NOT prepend any conversational preamble.
|
|
85318
|
+
|
|
85319
|
+
UPDATED: [list of files modified]
|
|
85320
|
+
ADDED: [list of new sections/files created, with their section IDs]
|
|
85321
|
+
REMOVED: [list of removed sections, with their section IDs]
|
|
85322
|
+
SUMMARY: [one-line description of design-doc changes]
|
|
85323
|
+
`, ROLE_CONFIG2;
|
|
85324
|
+
var init_docs = __esm(() => {
|
|
85325
|
+
ROLE_CONFIG2 = {
|
|
85326
|
+
standard: {
|
|
85327
|
+
basePrompt: DOCS_PROMPT,
|
|
85328
|
+
name: "docs",
|
|
85329
|
+
description: "Documentation synthesizer. Updates README, API docs, and guides to reflect code changes after each phase."
|
|
85330
|
+
},
|
|
85331
|
+
design_docs: {
|
|
85332
|
+
basePrompt: DESIGN_DOCS_PROMPT,
|
|
85333
|
+
name: "docs_design",
|
|
85334
|
+
description: "Design-doc author. Generates and syncs language-agnostic design docs (domain, technical-spec, behavior-spec, reference/) for the project under build (issue #1080)."
|
|
85335
|
+
}
|
|
85336
|
+
};
|
|
85337
|
+
});
|
|
85070
85338
|
|
|
85071
85339
|
// src/agents/reviewer.ts
|
|
85072
85340
|
function createReviewerAgent(model, customPrompt, customAppendPrompt) {
|
|
@@ -85963,7 +86231,7 @@ function createSwarmAgents(swarmId, swarmConfig, isDefault, pluginConfig, projec
|
|
|
85963
86231
|
const prefixName = (name2) => `${prefix}${name2}`;
|
|
85964
86232
|
if (!isAgentDisabled("architect", swarmAgents, swarmPrefix)) {
|
|
85965
86233
|
const architectPrompts = getPrompts("architect");
|
|
85966
|
-
const architect = createArchitectAgent(getModel("architect"), architectPrompts.prompt, architectPrompts.appendPrompt, pluginConfig?.adversarial_testing, pluginConfig?.council, pluginConfig?.ui_review, pluginConfig?.memory?.enabled === true, pluginConfig?.architectural_supervision);
|
|
86234
|
+
const architect = createArchitectAgent(getModel("architect"), architectPrompts.prompt, architectPrompts.appendPrompt, pluginConfig?.adversarial_testing, pluginConfig?.council, pluginConfig?.ui_review, pluginConfig?.memory?.enabled === true, pluginConfig?.architectural_supervision, pluginConfig?.design_docs?.enabled === true);
|
|
85967
86235
|
architect.name = prefixName("architect");
|
|
85968
86236
|
const swarmName = swarmConfig.name || swarmId;
|
|
85969
86237
|
const swarmIdentity = isDefault ? "default" : swarmId;
|
|
@@ -86100,6 +86368,12 @@ If you call @coder instead of @${swarmId}_coder, the call will FAIL or go to the
|
|
|
86100
86368
|
docs.name = prefixName("docs");
|
|
86101
86369
|
agents.push(applyOverrides(docs, swarmAgents, swarmPrefix, quiet));
|
|
86102
86370
|
}
|
|
86371
|
+
if (pluginConfig?.design_docs?.enabled === true && !isAgentDisabled("docs_design", swarmAgents, swarmPrefix)) {
|
|
86372
|
+
const docsDesignPrompts = getPrompts("docs_design");
|
|
86373
|
+
const docsDesign = createDocsAgent(getModel("docs_design"), docsDesignPrompts.prompt, docsDesignPrompts.appendPrompt, "design_docs");
|
|
86374
|
+
docsDesign.name = prefixName("docs_design");
|
|
86375
|
+
agents.push(applyOverrides(docsDesign, swarmAgents, swarmPrefix, quiet));
|
|
86376
|
+
}
|
|
86103
86377
|
if (pluginConfig?.ui_review?.enabled === true && !isAgentDisabled("designer", swarmAgents, swarmPrefix)) {
|
|
86104
86378
|
const designerPrompts = getPrompts("designer");
|
|
86105
86379
|
const designer = createDesignerAgent(getModel("designer"), designerPrompts.prompt, designerPrompts.appendPrompt);
|
|
@@ -86301,11 +86575,13 @@ var init_agents2 = __esm(() => {
|
|
|
86301
86575
|
init_council_prompts();
|
|
86302
86576
|
init_critic();
|
|
86303
86577
|
init_curator_agent();
|
|
86578
|
+
init_docs();
|
|
86304
86579
|
init_reviewer();
|
|
86305
86580
|
init_architect();
|
|
86306
86581
|
init_council_prompts();
|
|
86307
86582
|
init_critic();
|
|
86308
86583
|
init_curator_agent();
|
|
86584
|
+
init_docs();
|
|
86309
86585
|
init_reviewer();
|
|
86310
86586
|
warnedAgents = new Set;
|
|
86311
86587
|
KNOWN_VARIANT_VALUES = new Set([
|
|
@@ -91996,19 +92272,176 @@ var init_curator_drift = __esm(() => {
|
|
|
91996
92272
|
};
|
|
91997
92273
|
});
|
|
91998
92274
|
|
|
92275
|
+
// src/hooks/design-doc-drift.ts
|
|
92276
|
+
var exports_design_doc_drift = {};
|
|
92277
|
+
__export(exports_design_doc_drift, {
|
|
92278
|
+
runDesignDocDriftCheck: () => runDesignDocDriftCheck,
|
|
92279
|
+
_internals: () => _internals55
|
|
92280
|
+
});
|
|
92281
|
+
import * as fs89 from "node:fs";
|
|
92282
|
+
import * as path126 from "node:path";
|
|
92283
|
+
function mtimeMsOrNull(absPath) {
|
|
92284
|
+
try {
|
|
92285
|
+
return fs89.statSync(absPath).mtimeMs;
|
|
92286
|
+
} catch {
|
|
92287
|
+
return null;
|
|
92288
|
+
}
|
|
92289
|
+
}
|
|
92290
|
+
function resolveAnchorWithin(directory, anchor) {
|
|
92291
|
+
if (!anchor || typeof anchor !== "string")
|
|
92292
|
+
return null;
|
|
92293
|
+
const root = path126.resolve(directory);
|
|
92294
|
+
const resolved = path126.resolve(root, anchor);
|
|
92295
|
+
const rel = path126.relative(root, resolved);
|
|
92296
|
+
if (rel.startsWith("..") || path126.isAbsolute(rel))
|
|
92297
|
+
return null;
|
|
92298
|
+
return resolved;
|
|
92299
|
+
}
|
|
92300
|
+
async function runDesignDocDriftCheck(directory, phase, outDir) {
|
|
92301
|
+
try {
|
|
92302
|
+
const root = path126.resolve(directory);
|
|
92303
|
+
const outAbs = path126.resolve(root, outDir);
|
|
92304
|
+
const outRel = path126.relative(root, outAbs);
|
|
92305
|
+
if (outRel.startsWith("..") || path126.isAbsolute(outRel)) {
|
|
92306
|
+
return null;
|
|
92307
|
+
}
|
|
92308
|
+
const docMtimes = new Map;
|
|
92309
|
+
const checkedDocs = [];
|
|
92310
|
+
const missingDocs = [];
|
|
92311
|
+
for (const [docName, relFile] of Object.entries(DESIGN_DOC_FILES)) {
|
|
92312
|
+
const abs = path126.join(outAbs, relFile);
|
|
92313
|
+
const mtime = mtimeMsOrNull(abs);
|
|
92314
|
+
docMtimes.set(docName, mtime);
|
|
92315
|
+
if (mtime === null) {
|
|
92316
|
+
missingDocs.push(path126.join(outDir, relFile));
|
|
92317
|
+
} else {
|
|
92318
|
+
checkedDocs.push(path126.join(outDir, relFile));
|
|
92319
|
+
}
|
|
92320
|
+
}
|
|
92321
|
+
const traceabilityAbs = path126.join(outAbs, TRACEABILITY_REL);
|
|
92322
|
+
let registry3 = null;
|
|
92323
|
+
try {
|
|
92324
|
+
const stat9 = await fs89.promises.stat(traceabilityAbs);
|
|
92325
|
+
if (stat9.size <= MAX_TRACEABILITY_BYTES) {
|
|
92326
|
+
const raw = await fs89.promises.readFile(traceabilityAbs, "utf-8");
|
|
92327
|
+
const parsed = JSON.parse(raw);
|
|
92328
|
+
registry3 = parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
92329
|
+
}
|
|
92330
|
+
} catch {
|
|
92331
|
+
registry3 = null;
|
|
92332
|
+
}
|
|
92333
|
+
const noDocs = checkedDocs.length === 0 || registry3 === null;
|
|
92334
|
+
const specMtime = mtimeMsOrNull(path126.join(root, ".swarm", "spec.md"));
|
|
92335
|
+
const staleSections = [];
|
|
92336
|
+
if (!noDocs && Array.isArray(registry3?.sections)) {
|
|
92337
|
+
for (const section of registry3.sections) {
|
|
92338
|
+
if (!section || typeof section.section_id !== "string")
|
|
92339
|
+
continue;
|
|
92340
|
+
if (typeof section.doc !== "string" || !docMtimes.has(section.doc)) {
|
|
92341
|
+
continue;
|
|
92342
|
+
}
|
|
92343
|
+
const docMtime = docMtimes.get(section.doc) ?? null;
|
|
92344
|
+
if (docMtime === null) {
|
|
92345
|
+
staleSections.push({
|
|
92346
|
+
section_id: section.section_id,
|
|
92347
|
+
doc: section.doc,
|
|
92348
|
+
reason: "owning design doc is missing"
|
|
92349
|
+
});
|
|
92350
|
+
continue;
|
|
92351
|
+
}
|
|
92352
|
+
let flagged = false;
|
|
92353
|
+
for (const anchor of section.code_anchors ?? []) {
|
|
92354
|
+
const anchorAbs = resolveAnchorWithin(directory, anchor);
|
|
92355
|
+
if (anchorAbs === null)
|
|
92356
|
+
continue;
|
|
92357
|
+
const anchorMtime = mtimeMsOrNull(anchorAbs);
|
|
92358
|
+
if (anchorMtime !== null && anchorMtime > docMtime) {
|
|
92359
|
+
staleSections.push({
|
|
92360
|
+
section_id: section.section_id,
|
|
92361
|
+
doc: section.doc,
|
|
92362
|
+
reason: `code anchor ${anchor} changed after the doc`
|
|
92363
|
+
});
|
|
92364
|
+
flagged = true;
|
|
92365
|
+
break;
|
|
92366
|
+
}
|
|
92367
|
+
}
|
|
92368
|
+
if (!flagged && specMtime !== null && specMtime > docMtime && (section.spec_frs?.length ?? 0) > 0) {
|
|
92369
|
+
staleSections.push({
|
|
92370
|
+
section_id: section.section_id,
|
|
92371
|
+
doc: section.doc,
|
|
92372
|
+
reason: "spec.md changed after the doc"
|
|
92373
|
+
});
|
|
92374
|
+
}
|
|
92375
|
+
}
|
|
92376
|
+
}
|
|
92377
|
+
const verdict = noDocs ? "NO_DOCS" : staleSections.length > 0 ? "DOC_STALE" : "DOC_FRESH";
|
|
92378
|
+
const report = {
|
|
92379
|
+
schema_version: 1,
|
|
92380
|
+
phase,
|
|
92381
|
+
timestamp: new Date().toISOString(),
|
|
92382
|
+
out_dir: outDir,
|
|
92383
|
+
verdict,
|
|
92384
|
+
stale_sections: staleSections,
|
|
92385
|
+
missing_docs: missingDocs,
|
|
92386
|
+
checked_docs: checkedDocs
|
|
92387
|
+
};
|
|
92388
|
+
const filename = `${DOC_DRIFT_REPORT_PREFIX}${phase}.json`;
|
|
92389
|
+
const filePath = validateSwarmPath(directory, filename);
|
|
92390
|
+
await fs89.promises.mkdir(path126.dirname(filePath), { recursive: true });
|
|
92391
|
+
await fs89.promises.writeFile(filePath, JSON.stringify(report, null, 2), "utf-8");
|
|
92392
|
+
getGlobalEventBus().publish("curator.docdrift.completed", {
|
|
92393
|
+
phase,
|
|
92394
|
+
verdict,
|
|
92395
|
+
stale_count: staleSections.length,
|
|
92396
|
+
report_path: filePath
|
|
92397
|
+
});
|
|
92398
|
+
return report;
|
|
92399
|
+
} catch (err2) {
|
|
92400
|
+
try {
|
|
92401
|
+
getGlobalEventBus().publish("curator.error", {
|
|
92402
|
+
operation: "docdrift",
|
|
92403
|
+
phase,
|
|
92404
|
+
error: String(err2)
|
|
92405
|
+
});
|
|
92406
|
+
} catch {}
|
|
92407
|
+
warn(`[design-doc-drift] check failed for phase ${phase}: ${String(err2)}`);
|
|
92408
|
+
return null;
|
|
92409
|
+
}
|
|
92410
|
+
}
|
|
92411
|
+
var DOC_DRIFT_REPORT_PREFIX = "doc-drift-phase-", MAX_TRACEABILITY_BYTES, DESIGN_DOC_FILES, TRACEABILITY_REL, _internals55;
|
|
92412
|
+
var init_design_doc_drift = __esm(() => {
|
|
92413
|
+
init_event_bus();
|
|
92414
|
+
init_logger();
|
|
92415
|
+
init_utils2();
|
|
92416
|
+
MAX_TRACEABILITY_BYTES = 1024 * 1024;
|
|
92417
|
+
DESIGN_DOC_FILES = {
|
|
92418
|
+
domain: "domain.md",
|
|
92419
|
+
"technical-spec": "technical-spec.md",
|
|
92420
|
+
"behavior-spec": "behavior-spec.md",
|
|
92421
|
+
"reference-impl": path126.join("reference", "reference-impl.md"),
|
|
92422
|
+
"idiom-notes": path126.join("reference", "idiom-notes.md")
|
|
92423
|
+
};
|
|
92424
|
+
TRACEABILITY_REL = path126.join("reference", "traceability.json");
|
|
92425
|
+
_internals55 = {
|
|
92426
|
+
mtimeMsOrNull,
|
|
92427
|
+
resolveAnchorWithin,
|
|
92428
|
+
DESIGN_DOC_FILES
|
|
92429
|
+
};
|
|
92430
|
+
});
|
|
92431
|
+
|
|
91999
92432
|
// src/agents/project-context.ts
|
|
92000
92433
|
var exports_project_context = {};
|
|
92001
92434
|
__export(exports_project_context, {
|
|
92002
92435
|
buildProjectContext: () => buildProjectContext,
|
|
92003
|
-
_internals: () =>
|
|
92436
|
+
_internals: () => _internals71,
|
|
92004
92437
|
LANG_BACKEND_DETECTION_TIMEOUT_MS: () => LANG_BACKEND_DETECTION_TIMEOUT_MS
|
|
92005
92438
|
});
|
|
92006
|
-
import * as
|
|
92007
|
-
import * as
|
|
92439
|
+
import * as fs118 from "node:fs";
|
|
92440
|
+
import * as path161 from "node:path";
|
|
92008
92441
|
function detectFileExists2(directory, pattern) {
|
|
92009
92442
|
if (pattern.includes("*") || pattern.includes("?")) {
|
|
92010
92443
|
try {
|
|
92011
|
-
const files =
|
|
92444
|
+
const files = fs118.readdirSync(directory);
|
|
92012
92445
|
const regex = new RegExp(`^${pattern.replace(/\./g, "\\.").replace(/\*/g, ".*").replace(/\?/g, ".")}$`);
|
|
92013
92446
|
return files.some((f) => regex.test(f));
|
|
92014
92447
|
} catch {
|
|
@@ -92016,7 +92449,7 @@ function detectFileExists2(directory, pattern) {
|
|
|
92016
92449
|
}
|
|
92017
92450
|
}
|
|
92018
92451
|
try {
|
|
92019
|
-
|
|
92452
|
+
fs118.accessSync(path161.join(directory, pattern));
|
|
92020
92453
|
return true;
|
|
92021
92454
|
} catch {
|
|
92022
92455
|
return false;
|
|
@@ -92025,7 +92458,7 @@ function detectFileExists2(directory, pattern) {
|
|
|
92025
92458
|
function selectTestCommandFromScriptsTest(backend, directory) {
|
|
92026
92459
|
let pkgRaw;
|
|
92027
92460
|
try {
|
|
92028
|
-
pkgRaw =
|
|
92461
|
+
pkgRaw = fs118.readFileSync(path161.join(directory, "package.json"), "utf-8");
|
|
92029
92462
|
} catch {
|
|
92030
92463
|
return null;
|
|
92031
92464
|
}
|
|
@@ -92084,7 +92517,7 @@ function selectLintCommand(backend, directory) {
|
|
|
92084
92517
|
return null;
|
|
92085
92518
|
}
|
|
92086
92519
|
async function buildProjectContext(directory) {
|
|
92087
|
-
const backend = await
|
|
92520
|
+
const backend = await _internals71.pickBackend(directory);
|
|
92088
92521
|
if (!backend)
|
|
92089
92522
|
return null;
|
|
92090
92523
|
const ctx = emptyProjectContext();
|
|
@@ -92115,16 +92548,16 @@ async function buildProjectContext(directory) {
|
|
|
92115
92548
|
if (backend.prompts.reviewerChecklist.length > 0) {
|
|
92116
92549
|
ctx.REVIEWER_CHECKLIST = bulletList(backend.prompts.reviewerChecklist);
|
|
92117
92550
|
}
|
|
92118
|
-
const profiles =
|
|
92551
|
+
const profiles = _internals71.pickedProfiles(directory);
|
|
92119
92552
|
if (profiles.length > 1) {
|
|
92120
92553
|
ctx.PROJECT_CONTEXT_SECONDARY_LANGUAGES = profiles.slice(1).map((p) => p.id).join(", ");
|
|
92121
92554
|
}
|
|
92122
92555
|
return ctx;
|
|
92123
92556
|
}
|
|
92124
|
-
var LANG_BACKEND_DETECTION_TIMEOUT_MS = 300,
|
|
92557
|
+
var LANG_BACKEND_DETECTION_TIMEOUT_MS = 300, _internals71;
|
|
92125
92558
|
var init_project_context = __esm(() => {
|
|
92126
92559
|
init_dispatch();
|
|
92127
|
-
|
|
92560
|
+
_internals71 = {
|
|
92128
92561
|
pickBackend,
|
|
92129
92562
|
pickedProfiles
|
|
92130
92563
|
};
|
|
@@ -92134,7 +92567,7 @@ var init_project_context = __esm(() => {
|
|
|
92134
92567
|
init_package();
|
|
92135
92568
|
init_agents2();
|
|
92136
92569
|
init_critic();
|
|
92137
|
-
import * as
|
|
92570
|
+
import * as path162 from "node:path";
|
|
92138
92571
|
|
|
92139
92572
|
// src/background/index.ts
|
|
92140
92573
|
init_event_bus();
|
|
@@ -111030,8 +111463,8 @@ init_config();
|
|
|
111030
111463
|
init_schema();
|
|
111031
111464
|
init_qa_gate_profile();
|
|
111032
111465
|
init_manager2();
|
|
111033
|
-
import * as
|
|
111034
|
-
import * as
|
|
111466
|
+
import * as fs90 from "node:fs";
|
|
111467
|
+
import * as path127 from "node:path";
|
|
111035
111468
|
|
|
111036
111469
|
// src/full-auto/phase-approval.ts
|
|
111037
111470
|
init_utils2();
|
|
@@ -111944,8 +112377,8 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
111944
112377
|
let driftCheckEnabled = true;
|
|
111945
112378
|
let driftHasSpecMd = false;
|
|
111946
112379
|
try {
|
|
111947
|
-
const specMdPath =
|
|
111948
|
-
driftHasSpecMd =
|
|
112380
|
+
const specMdPath = path127.join(dir, ".swarm", "spec.md");
|
|
112381
|
+
driftHasSpecMd = fs90.existsSync(specMdPath);
|
|
111949
112382
|
const gatePlan = await loadPlan(dir);
|
|
111950
112383
|
if (gatePlan) {
|
|
111951
112384
|
const gatePlanId = derivePlanId(gatePlan);
|
|
@@ -111965,9 +112398,9 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
111965
112398
|
} else {
|
|
111966
112399
|
let phaseType;
|
|
111967
112400
|
try {
|
|
111968
|
-
const planPath =
|
|
111969
|
-
if (
|
|
111970
|
-
const planRaw =
|
|
112401
|
+
const planPath = path127.join(dir, ".swarm", "plan.json");
|
|
112402
|
+
if (fs90.existsSync(planPath)) {
|
|
112403
|
+
const planRaw = fs90.readFileSync(planPath, "utf-8");
|
|
111971
112404
|
const plan = JSON.parse(planRaw);
|
|
111972
112405
|
const targetPhase = plan.phases?.find((p) => p.id === phase);
|
|
111973
112406
|
phaseType = targetPhase?.type;
|
|
@@ -111977,11 +112410,11 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
111977
112410
|
warnings.push(`Phase ${phase} is annotated as 'non-code'. Drift verification was skipped per phase type annotation.`);
|
|
111978
112411
|
} else {
|
|
111979
112412
|
try {
|
|
111980
|
-
const driftEvidencePath =
|
|
112413
|
+
const driftEvidencePath = path127.join(dir, ".swarm", "evidence", String(phase), "drift-verifier.json");
|
|
111981
112414
|
let driftVerdictFound = false;
|
|
111982
112415
|
let driftVerdictApproved = false;
|
|
111983
112416
|
try {
|
|
111984
|
-
const driftEvidenceContent =
|
|
112417
|
+
const driftEvidenceContent = fs90.readFileSync(driftEvidencePath, "utf-8");
|
|
111985
112418
|
const driftEvidence = JSON.parse(driftEvidenceContent);
|
|
111986
112419
|
const entries = driftEvidence.entries ?? [];
|
|
111987
112420
|
for (const entry of entries) {
|
|
@@ -112015,9 +112448,9 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
112015
112448
|
let incompleteTaskCount = 0;
|
|
112016
112449
|
let planParseable = false;
|
|
112017
112450
|
try {
|
|
112018
|
-
const planPath =
|
|
112019
|
-
if (
|
|
112020
|
-
const planRaw =
|
|
112451
|
+
const planPath = path127.join(dir, ".swarm", "plan.json");
|
|
112452
|
+
if (fs90.existsSync(planPath)) {
|
|
112453
|
+
const planRaw = fs90.readFileSync(planPath, "utf-8");
|
|
112021
112454
|
const plan = JSON.parse(planRaw);
|
|
112022
112455
|
planParseable = true;
|
|
112023
112456
|
const planPhase = plan.phases?.find((p) => p.id === phase);
|
|
@@ -112082,11 +112515,11 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
112082
112515
|
const overrides = session2?.qaGateSessionOverrides ?? {};
|
|
112083
112516
|
const effective = getEffectiveGates(profile, overrides);
|
|
112084
112517
|
if (effective.hallucination_guard === true) {
|
|
112085
|
-
const hgPath =
|
|
112518
|
+
const hgPath = path127.join(dir, ".swarm", "evidence", String(phase), "hallucination-guard.json");
|
|
112086
112519
|
let hgVerdictFound = false;
|
|
112087
112520
|
let hgVerdictApproved = false;
|
|
112088
112521
|
try {
|
|
112089
|
-
const hgContent =
|
|
112522
|
+
const hgContent = fs90.readFileSync(hgPath, "utf-8");
|
|
112090
112523
|
const hgBundle = JSON.parse(hgContent);
|
|
112091
112524
|
for (const entry of hgBundle.entries ?? []) {
|
|
112092
112525
|
if (typeof entry.type === "string" && entry.type.includes("hallucination") && typeof entry.verdict === "string") {
|
|
@@ -112154,11 +112587,11 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
112154
112587
|
const overrides = session2?.qaGateSessionOverrides ?? {};
|
|
112155
112588
|
const effective = getEffectiveGates(profile, overrides);
|
|
112156
112589
|
if (effective.mutation_test === true) {
|
|
112157
|
-
const mgPath =
|
|
112590
|
+
const mgPath = path127.join(dir, ".swarm", "evidence", String(phase), "mutation-gate.json");
|
|
112158
112591
|
let mgVerdictFound = false;
|
|
112159
112592
|
let mgVerdict;
|
|
112160
112593
|
try {
|
|
112161
|
-
const mgContent =
|
|
112594
|
+
const mgContent = fs90.readFileSync(mgPath, "utf-8");
|
|
112162
112595
|
const mgBundle = JSON.parse(mgContent);
|
|
112163
112596
|
for (const entry of mgBundle.entries ?? []) {
|
|
112164
112597
|
if (typeof entry.type === "string" && entry.type === "mutation-gate" && typeof entry.verdict === "string") {
|
|
@@ -112228,14 +112661,14 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
112228
112661
|
const effective = getEffectiveGates(profile, overrides);
|
|
112229
112662
|
if (effective.council_mode === true) {
|
|
112230
112663
|
councilModeEnabled = true;
|
|
112231
|
-
const pcPath =
|
|
112664
|
+
const pcPath = path127.join(dir, ".swarm", "evidence", String(phase), "phase-council.json");
|
|
112232
112665
|
let pcVerdictFound = false;
|
|
112233
112666
|
let _pcVerdict;
|
|
112234
112667
|
let pcQuorumSize;
|
|
112235
112668
|
let pcTimestamp;
|
|
112236
112669
|
let pcPhaseNumber;
|
|
112237
112670
|
try {
|
|
112238
|
-
const pcContent =
|
|
112671
|
+
const pcContent = fs90.readFileSync(pcPath, "utf-8");
|
|
112239
112672
|
const pcBundle = JSON.parse(pcContent);
|
|
112240
112673
|
for (const entry of pcBundle.entries ?? []) {
|
|
112241
112674
|
if (typeof entry.type === "string" && entry.type === "phase-council" && typeof entry.verdict === "string") {
|
|
@@ -112491,11 +112924,11 @@ Findings: ${details.join("; ")}` : "";
|
|
|
112491
112924
|
const effective = getEffectiveGates(profile, overrides);
|
|
112492
112925
|
if (effective.final_council === true) {
|
|
112493
112926
|
finalCouncilEnabled = true;
|
|
112494
|
-
const fcPath =
|
|
112927
|
+
const fcPath = path127.join(dir, ".swarm", "evidence", "final-council.json");
|
|
112495
112928
|
let fcVerdictFound = false;
|
|
112496
112929
|
let _fcVerdict;
|
|
112497
112930
|
try {
|
|
112498
|
-
const fcContent =
|
|
112931
|
+
const fcContent = fs90.readFileSync(fcPath, "utf-8");
|
|
112499
112932
|
const fcBundle = JSON.parse(fcContent);
|
|
112500
112933
|
for (const entry of fcBundle.entries ?? []) {
|
|
112501
112934
|
if (typeof entry.type === "string" && entry.type === "final-council" && typeof entry.verdict === "string") {
|
|
@@ -112679,7 +113112,7 @@ Findings: ${details.join("; ")}` : "";
|
|
|
112679
113112
|
}
|
|
112680
113113
|
if (retroFound && retroEntry?.lessons_learned && retroEntry.lessons_learned.length > 0) {
|
|
112681
113114
|
try {
|
|
112682
|
-
const projectName =
|
|
113115
|
+
const projectName = path127.basename(dir);
|
|
112683
113116
|
const curationResult = await curateAndStoreSwarm(retroEntry.lessons_learned, projectName, { phase_number: phase }, dir, knowledgeConfig);
|
|
112684
113117
|
if (curationResult) {
|
|
112685
113118
|
const sessionState = swarmState.agentSessions.get(sessionID);
|
|
@@ -112758,18 +113191,35 @@ Findings: ${details.join("; ")}` : "";
|
|
|
112758
113191
|
} catch (curatorError) {
|
|
112759
113192
|
safeWarn("[phase_complete] Curator pipeline error (non-blocking):", curatorError);
|
|
112760
113193
|
}
|
|
113194
|
+
try {
|
|
113195
|
+
if (config3.design_docs?.enabled === true) {
|
|
113196
|
+
const outDir = config3.design_docs.out_dir ?? "docs";
|
|
113197
|
+
const { runDesignDocDriftCheck: runDesignDocDriftCheck2 } = await Promise.resolve().then(() => (init_design_doc_drift(), exports_design_doc_drift));
|
|
113198
|
+
const docReport = await runDesignDocDriftCheck2(dir, phase, outDir);
|
|
113199
|
+
if (docReport?.verdict === "DOC_STALE") {
|
|
113200
|
+
const callerSessionState = swarmState.agentSessions.get(sessionID);
|
|
113201
|
+
if (callerSessionState) {
|
|
113202
|
+
callerSessionState.pendingAdvisoryMessages ??= [];
|
|
113203
|
+
const staleIds = docReport.stale_sections.map((s) => s.section_id).slice(0, 8).join(", ");
|
|
113204
|
+
callerSessionState.pendingAdvisoryMessages.push(`[DESIGN-DOC DRIFT (phase ${phase})]: ${docReport.stale_sections.length} design-doc section(s) are stale (${staleIds}). Run /swarm design-docs --update to sync ${outDir}/ and append a design-changelog entry. Advisory only — does not block completion.`);
|
|
113205
|
+
}
|
|
113206
|
+
}
|
|
113207
|
+
}
|
|
113208
|
+
} catch (docDriftError) {
|
|
113209
|
+
safeWarn("[phase_complete] Design-doc drift check error (non-blocking):", docDriftError);
|
|
113210
|
+
}
|
|
112761
113211
|
try {
|
|
112762
113212
|
const markerPath = validateSwarmPath(dir, "skill-usage-last-processed.json");
|
|
112763
113213
|
let sinceTimestamp;
|
|
112764
113214
|
try {
|
|
112765
|
-
const markerData = JSON.parse(
|
|
113215
|
+
const markerData = JSON.parse(fs90.readFileSync(markerPath, "utf-8"));
|
|
112766
113216
|
sinceTimestamp = markerData.lastProcessedTimestamp;
|
|
112767
113217
|
} catch {}
|
|
112768
113218
|
const feedbackResult = await applySkillUsageFeedback(dir, {
|
|
112769
113219
|
sinceTimestamp
|
|
112770
113220
|
});
|
|
112771
113221
|
try {
|
|
112772
|
-
|
|
113222
|
+
fs90.writeFileSync(markerPath, JSON.stringify({ lastProcessedTimestamp: new Date().toISOString() }), "utf-8");
|
|
112773
113223
|
} catch {}
|
|
112774
113224
|
if (feedbackResult.processed > 0) {
|
|
112775
113225
|
const sessionState = swarmState.agentSessions.get(sessionID);
|
|
@@ -112789,7 +113239,7 @@ Findings: ${details.join("; ")}` : "";
|
|
|
112789
113239
|
let phaseRequiredAgents;
|
|
112790
113240
|
try {
|
|
112791
113241
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
112792
|
-
const planRaw =
|
|
113242
|
+
const planRaw = fs90.readFileSync(planPath, "utf-8");
|
|
112793
113243
|
const plan = JSON.parse(planRaw);
|
|
112794
113244
|
const phaseObj = plan.phases.find((p) => p.id === phase);
|
|
112795
113245
|
phaseRequiredAgents = phaseObj?.required_agents;
|
|
@@ -112804,7 +113254,7 @@ Findings: ${details.join("; ")}` : "";
|
|
|
112804
113254
|
if (agentsMissing.length > 0) {
|
|
112805
113255
|
try {
|
|
112806
113256
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
112807
|
-
const planRaw =
|
|
113257
|
+
const planRaw = fs90.readFileSync(planPath, "utf-8");
|
|
112808
113258
|
const plan = JSON.parse(planRaw);
|
|
112809
113259
|
const targetPhase = plan.phases.find((p) => p.id === phase);
|
|
112810
113260
|
if (targetPhase && targetPhase.tasks.length > 0 && canInferMissingAgentsFromTaskGates(agentsMissing) && await allCompletedTasksHavePassedGateEvidence(dir, targetPhase.tasks)) {
|
|
@@ -112844,7 +113294,7 @@ Findings: ${details.join("; ")}` : "";
|
|
|
112844
113294
|
if (phaseCompleteConfig.regression_sweep?.enforce) {
|
|
112845
113295
|
try {
|
|
112846
113296
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
112847
|
-
const planRaw =
|
|
113297
|
+
const planRaw = fs90.readFileSync(planPath, "utf-8");
|
|
112848
113298
|
const plan = JSON.parse(planRaw);
|
|
112849
113299
|
const targetPhase = plan.phases.find((p) => p.id === phase);
|
|
112850
113300
|
if (targetPhase) {
|
|
@@ -112898,7 +113348,7 @@ Findings: ${details.join("; ")}` : "";
|
|
|
112898
113348
|
}
|
|
112899
113349
|
try {
|
|
112900
113350
|
const eventsPath = validateSwarmPath(dir, "events.jsonl");
|
|
112901
|
-
|
|
113351
|
+
fs90.appendFileSync(eventsPath, `${JSON.stringify(event)}
|
|
112902
113352
|
`, "utf-8");
|
|
112903
113353
|
} catch (writeError) {
|
|
112904
113354
|
warnings.push(`Warning: failed to write phase complete event: ${writeError instanceof Error ? writeError.message : String(writeError)}`);
|
|
@@ -112973,12 +113423,12 @@ Findings: ${details.join("; ")}` : "";
|
|
|
112973
113423
|
warnings.push(`Warning: failed to update plan.json phase status`);
|
|
112974
113424
|
try {
|
|
112975
113425
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
112976
|
-
const planRaw =
|
|
113426
|
+
const planRaw = fs90.readFileSync(planPath, "utf-8");
|
|
112977
113427
|
const plan2 = JSON.parse(planRaw);
|
|
112978
113428
|
const phaseObj = plan2.phases.find((p) => p.id === phase);
|
|
112979
113429
|
if (phaseObj) {
|
|
112980
113430
|
phaseObj.status = "complete";
|
|
112981
|
-
|
|
113431
|
+
fs90.writeFileSync(planPath, JSON.stringify(plan2, null, 2), "utf-8");
|
|
112982
113432
|
}
|
|
112983
113433
|
} catch {}
|
|
112984
113434
|
} else if (plan) {
|
|
@@ -113015,12 +113465,12 @@ Findings: ${details.join("; ")}` : "";
|
|
|
113015
113465
|
warnings.push(`Warning: failed to update plan.json phase status`);
|
|
113016
113466
|
try {
|
|
113017
113467
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
113018
|
-
const planRaw =
|
|
113468
|
+
const planRaw = fs90.readFileSync(planPath, "utf-8");
|
|
113019
113469
|
const plan = JSON.parse(planRaw);
|
|
113020
113470
|
const phaseObj = plan.phases.find((p) => p.id === phase);
|
|
113021
113471
|
if (phaseObj) {
|
|
113022
113472
|
phaseObj.status = "complete";
|
|
113023
|
-
|
|
113473
|
+
fs90.writeFileSync(planPath, JSON.stringify(plan, null, 2), "utf-8");
|
|
113024
113474
|
}
|
|
113025
113475
|
} catch {}
|
|
113026
113476
|
}
|
|
@@ -113078,8 +113528,8 @@ init_discovery();
|
|
|
113078
113528
|
init_utils();
|
|
113079
113529
|
init_bun_compat();
|
|
113080
113530
|
init_create_tool();
|
|
113081
|
-
import * as
|
|
113082
|
-
import * as
|
|
113531
|
+
import * as fs91 from "node:fs";
|
|
113532
|
+
import * as path128 from "node:path";
|
|
113083
113533
|
var MAX_OUTPUT_BYTES5 = 52428800;
|
|
113084
113534
|
var AUDIT_TIMEOUT_MS = 120000;
|
|
113085
113535
|
function isValidEcosystem(value) {
|
|
@@ -113107,31 +113557,31 @@ function validateArgs3(args2) {
|
|
|
113107
113557
|
function detectEcosystems(directory) {
|
|
113108
113558
|
const ecosystems = [];
|
|
113109
113559
|
const cwd = directory;
|
|
113110
|
-
if (
|
|
113560
|
+
if (fs91.existsSync(path128.join(cwd, "package.json"))) {
|
|
113111
113561
|
ecosystems.push("npm");
|
|
113112
113562
|
}
|
|
113113
|
-
if (
|
|
113563
|
+
if (fs91.existsSync(path128.join(cwd, "pyproject.toml")) || fs91.existsSync(path128.join(cwd, "requirements.txt"))) {
|
|
113114
113564
|
ecosystems.push("pip");
|
|
113115
113565
|
}
|
|
113116
|
-
if (
|
|
113566
|
+
if (fs91.existsSync(path128.join(cwd, "Cargo.toml"))) {
|
|
113117
113567
|
ecosystems.push("cargo");
|
|
113118
113568
|
}
|
|
113119
|
-
if (
|
|
113569
|
+
if (fs91.existsSync(path128.join(cwd, "go.mod"))) {
|
|
113120
113570
|
ecosystems.push("go");
|
|
113121
113571
|
}
|
|
113122
113572
|
try {
|
|
113123
|
-
const files =
|
|
113573
|
+
const files = fs91.readdirSync(cwd);
|
|
113124
113574
|
if (files.some((f) => f.endsWith(".csproj") || f.endsWith(".sln"))) {
|
|
113125
113575
|
ecosystems.push("dotnet");
|
|
113126
113576
|
}
|
|
113127
113577
|
} catch {}
|
|
113128
|
-
if (
|
|
113578
|
+
if (fs91.existsSync(path128.join(cwd, "Gemfile")) || fs91.existsSync(path128.join(cwd, "Gemfile.lock"))) {
|
|
113129
113579
|
ecosystems.push("ruby");
|
|
113130
113580
|
}
|
|
113131
|
-
if (
|
|
113581
|
+
if (fs91.existsSync(path128.join(cwd, "pubspec.yaml"))) {
|
|
113132
113582
|
ecosystems.push("dart");
|
|
113133
113583
|
}
|
|
113134
|
-
if (
|
|
113584
|
+
if (fs91.existsSync(path128.join(cwd, "composer.lock"))) {
|
|
113135
113585
|
ecosystems.push("composer");
|
|
113136
113586
|
}
|
|
113137
113587
|
return ecosystems;
|
|
@@ -113144,7 +113594,7 @@ async function runNpmAudit(directory) {
|
|
|
113144
113594
|
stderr: "pipe",
|
|
113145
113595
|
cwd: directory
|
|
113146
113596
|
});
|
|
113147
|
-
const timeoutPromise = new Promise((
|
|
113597
|
+
const timeoutPromise = new Promise((resolve45) => setTimeout(() => resolve45("timeout"), AUDIT_TIMEOUT_MS));
|
|
113148
113598
|
const result = await Promise.race([
|
|
113149
113599
|
Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr2]) => ({ stdout: stdout2, stderr: stderr2 })),
|
|
113150
113600
|
timeoutPromise
|
|
@@ -113264,7 +113714,7 @@ async function runPipAudit(directory) {
|
|
|
113264
113714
|
stderr: "pipe",
|
|
113265
113715
|
cwd: directory
|
|
113266
113716
|
});
|
|
113267
|
-
const timeoutPromise = new Promise((
|
|
113717
|
+
const timeoutPromise = new Promise((resolve45) => setTimeout(() => resolve45("timeout"), AUDIT_TIMEOUT_MS));
|
|
113268
113718
|
const result = await Promise.race([
|
|
113269
113719
|
Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr2]) => ({ stdout: stdout2, stderr: stderr2 })),
|
|
113270
113720
|
timeoutPromise
|
|
@@ -113392,7 +113842,7 @@ async function runCargoAudit(directory) {
|
|
|
113392
113842
|
stderr: "pipe",
|
|
113393
113843
|
cwd: directory
|
|
113394
113844
|
});
|
|
113395
|
-
const timeoutPromise = new Promise((
|
|
113845
|
+
const timeoutPromise = new Promise((resolve45) => setTimeout(() => resolve45("timeout"), AUDIT_TIMEOUT_MS));
|
|
113396
113846
|
const result = await Promise.race([
|
|
113397
113847
|
Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
|
|
113398
113848
|
timeoutPromise
|
|
@@ -113516,7 +113966,7 @@ async function runGoAudit(directory) {
|
|
|
113516
113966
|
stderr: "pipe",
|
|
113517
113967
|
cwd: directory
|
|
113518
113968
|
});
|
|
113519
|
-
const timeoutPromise = new Promise((
|
|
113969
|
+
const timeoutPromise = new Promise((resolve45) => setTimeout(() => resolve45("timeout"), AUDIT_TIMEOUT_MS));
|
|
113520
113970
|
const result = await Promise.race([
|
|
113521
113971
|
Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
|
|
113522
113972
|
timeoutPromise
|
|
@@ -113649,7 +114099,7 @@ async function runDotnetAudit(directory) {
|
|
|
113649
114099
|
stderr: "pipe",
|
|
113650
114100
|
cwd: directory
|
|
113651
114101
|
});
|
|
113652
|
-
const timeoutPromise = new Promise((
|
|
114102
|
+
const timeoutPromise = new Promise((resolve45) => setTimeout(() => resolve45("timeout"), AUDIT_TIMEOUT_MS));
|
|
113653
114103
|
const result = await Promise.race([
|
|
113654
114104
|
Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
|
|
113655
114105
|
timeoutPromise
|
|
@@ -113765,7 +114215,7 @@ async function runBundleAudit(directory) {
|
|
|
113765
114215
|
stderr: "pipe",
|
|
113766
114216
|
cwd: directory
|
|
113767
114217
|
});
|
|
113768
|
-
const timeoutPromise = new Promise((
|
|
114218
|
+
const timeoutPromise = new Promise((resolve45) => setTimeout(() => resolve45("timeout"), AUDIT_TIMEOUT_MS));
|
|
113769
114219
|
const result = await Promise.race([
|
|
113770
114220
|
Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
|
|
113771
114221
|
timeoutPromise
|
|
@@ -113910,7 +114360,7 @@ async function runDartAudit(directory) {
|
|
|
113910
114360
|
stderr: "pipe",
|
|
113911
114361
|
cwd: directory
|
|
113912
114362
|
});
|
|
113913
|
-
const timeoutPromise = new Promise((
|
|
114363
|
+
const timeoutPromise = new Promise((resolve45) => setTimeout(() => resolve45("timeout"), AUDIT_TIMEOUT_MS));
|
|
113914
114364
|
const result = await Promise.race([
|
|
113915
114365
|
Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
|
|
113916
114366
|
timeoutPromise
|
|
@@ -114025,7 +114475,7 @@ async function runComposerAudit(directory) {
|
|
|
114025
114475
|
stderr: "pipe",
|
|
114026
114476
|
cwd: directory
|
|
114027
114477
|
});
|
|
114028
|
-
const timeoutPromise = new Promise((
|
|
114478
|
+
const timeoutPromise = new Promise((resolve45) => setTimeout(() => resolve45("timeout"), AUDIT_TIMEOUT_MS));
|
|
114029
114479
|
const result = await Promise.race([
|
|
114030
114480
|
Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
|
|
114031
114481
|
timeoutPromise
|
|
@@ -114266,8 +114716,8 @@ var pkg_audit = createSwarmTool({
|
|
|
114266
114716
|
// src/tools/placeholder-scan.ts
|
|
114267
114717
|
init_zod();
|
|
114268
114718
|
init_manager2();
|
|
114269
|
-
import * as
|
|
114270
|
-
import * as
|
|
114719
|
+
import * as fs92 from "node:fs";
|
|
114720
|
+
import * as path129 from "node:path";
|
|
114271
114721
|
init_utils();
|
|
114272
114722
|
init_create_tool();
|
|
114273
114723
|
var MAX_FILE_SIZE = 1024 * 1024;
|
|
@@ -114390,7 +114840,7 @@ function isScaffoldFile(filePath) {
|
|
|
114390
114840
|
if (SCAFFOLD_PATH_PATTERNS.some((pattern) => pattern.test(normalizedPath))) {
|
|
114391
114841
|
return true;
|
|
114392
114842
|
}
|
|
114393
|
-
const filename =
|
|
114843
|
+
const filename = path129.basename(filePath);
|
|
114394
114844
|
if (SCAFFOLD_FILENAME_PATTERNS.some((pattern) => pattern.test(filename))) {
|
|
114395
114845
|
return true;
|
|
114396
114846
|
}
|
|
@@ -114407,7 +114857,7 @@ function isAllowedByGlobs(filePath, allowGlobs) {
|
|
|
114407
114857
|
if (regex.test(normalizedPath)) {
|
|
114408
114858
|
return true;
|
|
114409
114859
|
}
|
|
114410
|
-
const filename =
|
|
114860
|
+
const filename = path129.basename(filePath);
|
|
114411
114861
|
const filenameRegex = new RegExp(`^${regexPattern}$`, "i");
|
|
114412
114862
|
if (filenameRegex.test(filename)) {
|
|
114413
114863
|
return true;
|
|
@@ -114416,7 +114866,7 @@ function isAllowedByGlobs(filePath, allowGlobs) {
|
|
|
114416
114866
|
return false;
|
|
114417
114867
|
}
|
|
114418
114868
|
function isParserSupported(filePath) {
|
|
114419
|
-
const ext =
|
|
114869
|
+
const ext = path129.extname(filePath).toLowerCase();
|
|
114420
114870
|
return SUPPORTED_PARSER_EXTENSIONS.has(ext);
|
|
114421
114871
|
}
|
|
114422
114872
|
function isPlanFile(filePath) {
|
|
@@ -114663,28 +115113,28 @@ async function placeholderScan(input, directory) {
|
|
|
114663
115113
|
let filesScanned = 0;
|
|
114664
115114
|
const filesWithFindings = new Set;
|
|
114665
115115
|
for (const filePath of changed_files) {
|
|
114666
|
-
const fullPath =
|
|
114667
|
-
const resolvedDirectory =
|
|
114668
|
-
if (!fullPath.startsWith(resolvedDirectory +
|
|
115116
|
+
const fullPath = path129.isAbsolute(filePath) ? filePath : path129.resolve(directory, filePath);
|
|
115117
|
+
const resolvedDirectory = path129.resolve(directory);
|
|
115118
|
+
if (!fullPath.startsWith(resolvedDirectory + path129.sep) && fullPath !== resolvedDirectory) {
|
|
114669
115119
|
continue;
|
|
114670
115120
|
}
|
|
114671
|
-
if (!
|
|
115121
|
+
if (!fs92.existsSync(fullPath)) {
|
|
114672
115122
|
continue;
|
|
114673
115123
|
}
|
|
114674
115124
|
if (isAllowedByGlobs(filePath, allow_globs)) {
|
|
114675
115125
|
continue;
|
|
114676
115126
|
}
|
|
114677
|
-
const relativeFilePath =
|
|
115127
|
+
const relativeFilePath = path129.relative(directory, fullPath).replace(/\\/g, "/");
|
|
114678
115128
|
if (FILE_ALLOWLIST.some((allowed) => relativeFilePath.endsWith(allowed))) {
|
|
114679
115129
|
continue;
|
|
114680
115130
|
}
|
|
114681
115131
|
let content;
|
|
114682
115132
|
try {
|
|
114683
|
-
const stat9 =
|
|
115133
|
+
const stat9 = fs92.statSync(fullPath);
|
|
114684
115134
|
if (stat9.size > MAX_FILE_SIZE) {
|
|
114685
115135
|
continue;
|
|
114686
115136
|
}
|
|
114687
|
-
content =
|
|
115137
|
+
content = fs92.readFileSync(fullPath, "utf-8");
|
|
114688
115138
|
} catch {
|
|
114689
115139
|
continue;
|
|
114690
115140
|
}
|
|
@@ -114745,8 +115195,8 @@ var placeholder_scan = createSwarmTool({
|
|
|
114745
115195
|
}
|
|
114746
115196
|
});
|
|
114747
115197
|
// src/tools/pre-check-batch.ts
|
|
114748
|
-
import * as
|
|
114749
|
-
import * as
|
|
115198
|
+
import * as fs96 from "node:fs";
|
|
115199
|
+
import * as path133 from "node:path";
|
|
114750
115200
|
init_zod();
|
|
114751
115201
|
init_manager2();
|
|
114752
115202
|
init_utils();
|
|
@@ -114874,11 +115324,11 @@ var quality_budget = createSwarmTool({
|
|
|
114874
115324
|
}).optional().describe("Quality budget thresholds")
|
|
114875
115325
|
},
|
|
114876
115326
|
async execute(args2, directory) {
|
|
114877
|
-
const result = await
|
|
115327
|
+
const result = await _internals56.qualityBudget(args2, directory);
|
|
114878
115328
|
return JSON.stringify(result);
|
|
114879
115329
|
}
|
|
114880
115330
|
});
|
|
114881
|
-
var
|
|
115331
|
+
var _internals56 = {
|
|
114882
115332
|
qualityBudget
|
|
114883
115333
|
};
|
|
114884
115334
|
|
|
@@ -114886,8 +115336,8 @@ var _internals55 = {
|
|
|
114886
115336
|
init_zod();
|
|
114887
115337
|
init_manager2();
|
|
114888
115338
|
init_detector();
|
|
114889
|
-
import * as
|
|
114890
|
-
import * as
|
|
115339
|
+
import * as fs95 from "node:fs";
|
|
115340
|
+
import * as path132 from "node:path";
|
|
114891
115341
|
import { extname as extname20 } from "node:path";
|
|
114892
115342
|
|
|
114893
115343
|
// src/sast/rules/c.ts
|
|
@@ -115602,12 +116052,12 @@ function executeRulesSync(filePath, content, language) {
|
|
|
115602
116052
|
|
|
115603
116053
|
// src/sast/semgrep.ts
|
|
115604
116054
|
import * as child_process9 from "node:child_process";
|
|
115605
|
-
import * as
|
|
115606
|
-
import * as
|
|
116055
|
+
import * as fs93 from "node:fs";
|
|
116056
|
+
import * as path130 from "node:path";
|
|
115607
116057
|
var semgrepAvailableCache = null;
|
|
115608
116058
|
var DEFAULT_RULES_DIR = ".swarm/semgrep-rules";
|
|
115609
116059
|
var DEFAULT_TIMEOUT_MS3 = 30000;
|
|
115610
|
-
var
|
|
116060
|
+
var _internals57 = {
|
|
115611
116061
|
isSemgrepAvailable,
|
|
115612
116062
|
checkSemgrepAvailable,
|
|
115613
116063
|
resetSemgrepCache,
|
|
@@ -115632,7 +116082,7 @@ function isSemgrepAvailable() {
|
|
|
115632
116082
|
}
|
|
115633
116083
|
}
|
|
115634
116084
|
async function checkSemgrepAvailable() {
|
|
115635
|
-
return
|
|
116085
|
+
return _internals57.isSemgrepAvailable();
|
|
115636
116086
|
}
|
|
115637
116087
|
function resetSemgrepCache() {
|
|
115638
116088
|
semgrepAvailableCache = null;
|
|
@@ -115684,7 +116134,7 @@ function mapSemgrepSeverity(severity) {
|
|
|
115684
116134
|
}
|
|
115685
116135
|
}
|
|
115686
116136
|
async function executeWithTimeout(command, args2, options) {
|
|
115687
|
-
return new Promise((
|
|
116137
|
+
return new Promise((resolve47) => {
|
|
115688
116138
|
const child = child_process9.spawn(command, args2, {
|
|
115689
116139
|
shell: false,
|
|
115690
116140
|
cwd: options.cwd
|
|
@@ -115693,7 +116143,7 @@ async function executeWithTimeout(command, args2, options) {
|
|
|
115693
116143
|
let stderr = "";
|
|
115694
116144
|
const timeout = setTimeout(() => {
|
|
115695
116145
|
child.kill("SIGTERM");
|
|
115696
|
-
|
|
116146
|
+
resolve47({
|
|
115697
116147
|
stdout,
|
|
115698
116148
|
stderr: "Process timed out",
|
|
115699
116149
|
exitCode: 124
|
|
@@ -115707,7 +116157,7 @@ async function executeWithTimeout(command, args2, options) {
|
|
|
115707
116157
|
});
|
|
115708
116158
|
child.on("close", (code) => {
|
|
115709
116159
|
clearTimeout(timeout);
|
|
115710
|
-
|
|
116160
|
+
resolve47({
|
|
115711
116161
|
stdout,
|
|
115712
116162
|
stderr,
|
|
115713
116163
|
exitCode: code ?? 0
|
|
@@ -115715,7 +116165,7 @@ async function executeWithTimeout(command, args2, options) {
|
|
|
115715
116165
|
});
|
|
115716
116166
|
child.on("error", (err2) => {
|
|
115717
116167
|
clearTimeout(timeout);
|
|
115718
|
-
|
|
116168
|
+
resolve47({
|
|
115719
116169
|
stdout,
|
|
115720
116170
|
stderr: err2.message,
|
|
115721
116171
|
exitCode: 1
|
|
@@ -115729,12 +116179,12 @@ async function runSemgrep(options) {
|
|
|
115729
116179
|
const timeoutMs = options.timeoutMs || DEFAULT_TIMEOUT_MS3;
|
|
115730
116180
|
if (files.length === 0) {
|
|
115731
116181
|
return {
|
|
115732
|
-
available:
|
|
116182
|
+
available: _internals57.isSemgrepAvailable(),
|
|
115733
116183
|
findings: [],
|
|
115734
116184
|
engine: "tier_a"
|
|
115735
116185
|
};
|
|
115736
116186
|
}
|
|
115737
|
-
if (!
|
|
116187
|
+
if (!_internals57.isSemgrepAvailable()) {
|
|
115738
116188
|
return {
|
|
115739
116189
|
available: false,
|
|
115740
116190
|
findings: [],
|
|
@@ -115790,14 +116240,14 @@ async function runSemgrep(options) {
|
|
|
115790
116240
|
}
|
|
115791
116241
|
function getRulesDirectory(projectRoot) {
|
|
115792
116242
|
if (projectRoot) {
|
|
115793
|
-
return
|
|
116243
|
+
return path130.resolve(projectRoot, DEFAULT_RULES_DIR);
|
|
115794
116244
|
}
|
|
115795
116245
|
return DEFAULT_RULES_DIR;
|
|
115796
116246
|
}
|
|
115797
116247
|
function hasBundledRules(projectRoot) {
|
|
115798
116248
|
const rulesDir = getRulesDirectory(projectRoot);
|
|
115799
116249
|
try {
|
|
115800
|
-
return
|
|
116250
|
+
return fs93.existsSync(rulesDir);
|
|
115801
116251
|
} catch {
|
|
115802
116252
|
return false;
|
|
115803
116253
|
}
|
|
@@ -115810,25 +116260,25 @@ init_create_tool();
|
|
|
115810
116260
|
// src/tools/sast-baseline.ts
|
|
115811
116261
|
init_utils2();
|
|
115812
116262
|
import * as crypto11 from "node:crypto";
|
|
115813
|
-
import * as
|
|
115814
|
-
import * as
|
|
116263
|
+
import * as fs94 from "node:fs";
|
|
116264
|
+
import * as path131 from "node:path";
|
|
115815
116265
|
var BASELINE_SCHEMA_VERSION = "1.0.0";
|
|
115816
116266
|
var MAX_BASELINE_FINDINGS = 2000;
|
|
115817
116267
|
var MAX_BASELINE_BYTES = 2 * 1048576;
|
|
115818
116268
|
var LOCK_RETRY_DELAYS_MS = [50, 100, 200, 400, 800];
|
|
115819
116269
|
function normalizeFindingPath(directory, file3) {
|
|
115820
|
-
const resolved =
|
|
115821
|
-
const rel =
|
|
116270
|
+
const resolved = path131.isAbsolute(file3) ? file3 : path131.resolve(directory, file3);
|
|
116271
|
+
const rel = path131.relative(path131.resolve(directory), resolved);
|
|
115822
116272
|
return rel.replace(/\\/g, "/");
|
|
115823
116273
|
}
|
|
115824
116274
|
function baselineRelPath(phase) {
|
|
115825
|
-
return
|
|
116275
|
+
return path131.join("evidence", String(phase), "sast-baseline.json");
|
|
115826
116276
|
}
|
|
115827
116277
|
function tempRelPath(phase) {
|
|
115828
|
-
return
|
|
116278
|
+
return path131.join("evidence", String(phase), `sast-baseline.json.tmp.${Date.now()}.${process.pid}`);
|
|
115829
116279
|
}
|
|
115830
116280
|
function lockRelPath(phase) {
|
|
115831
|
-
return
|
|
116281
|
+
return path131.join("evidence", String(phase), "sast-baseline.json.lock");
|
|
115832
116282
|
}
|
|
115833
116283
|
function getLine(lines, idx) {
|
|
115834
116284
|
if (idx < 0 || idx >= lines.length)
|
|
@@ -115845,7 +116295,7 @@ function fingerprintFinding(finding, directory, occurrenceIndex) {
|
|
|
115845
116295
|
}
|
|
115846
116296
|
const lineNum = finding.location.line;
|
|
115847
116297
|
try {
|
|
115848
|
-
const content =
|
|
116298
|
+
const content = fs94.readFileSync(finding.location.file, "utf-8");
|
|
115849
116299
|
const lines = content.split(`
|
|
115850
116300
|
`);
|
|
115851
116301
|
const idx = lineNum - 1;
|
|
@@ -115876,7 +116326,7 @@ function assignOccurrenceIndices(findings, directory) {
|
|
|
115876
116326
|
try {
|
|
115877
116327
|
if (relFile.startsWith(".."))
|
|
115878
116328
|
throw new Error("escapes workspace");
|
|
115879
|
-
const content =
|
|
116329
|
+
const content = fs94.readFileSync(finding.location.file, "utf-8");
|
|
115880
116330
|
const lines = content.split(`
|
|
115881
116331
|
`);
|
|
115882
116332
|
const idx = lineNum - 1;
|
|
@@ -115893,7 +116343,7 @@ function assignOccurrenceIndices(findings, directory) {
|
|
|
115893
116343
|
}
|
|
115894
116344
|
const occIdx = countMap.get(baseKey) ?? 0;
|
|
115895
116345
|
countMap.set(baseKey, occIdx + 1);
|
|
115896
|
-
const fp =
|
|
116346
|
+
const fp = _internals58.fingerprintFinding(finding, directory, occIdx);
|
|
115897
116347
|
return {
|
|
115898
116348
|
finding,
|
|
115899
116349
|
index: occIdx,
|
|
@@ -115905,16 +116355,16 @@ function assignOccurrenceIndices(findings, directory) {
|
|
|
115905
116355
|
async function acquireLock2(lockPath) {
|
|
115906
116356
|
for (let attempt = 0;attempt <= LOCK_RETRY_DELAYS_MS.length; attempt++) {
|
|
115907
116357
|
try {
|
|
115908
|
-
const fd =
|
|
115909
|
-
|
|
116358
|
+
const fd = fs94.openSync(lockPath, "wx");
|
|
116359
|
+
fs94.closeSync(fd);
|
|
115910
116360
|
return () => {
|
|
115911
116361
|
try {
|
|
115912
|
-
|
|
116362
|
+
fs94.unlinkSync(lockPath);
|
|
115913
116363
|
} catch {}
|
|
115914
116364
|
};
|
|
115915
116365
|
} catch {
|
|
115916
116366
|
if (attempt < LOCK_RETRY_DELAYS_MS.length) {
|
|
115917
|
-
await new Promise((
|
|
116367
|
+
await new Promise((resolve48) => setTimeout(resolve48, LOCK_RETRY_DELAYS_MS[attempt]));
|
|
115918
116368
|
}
|
|
115919
116369
|
}
|
|
115920
116370
|
}
|
|
@@ -115949,20 +116399,20 @@ async function captureOrMergeBaseline(directory, phase, findings, engine, scanne
|
|
|
115949
116399
|
message: e instanceof Error ? e.message : "Path validation failed"
|
|
115950
116400
|
};
|
|
115951
116401
|
}
|
|
115952
|
-
|
|
115953
|
-
|
|
116402
|
+
fs94.mkdirSync(path131.dirname(baselinePath), { recursive: true });
|
|
116403
|
+
fs94.mkdirSync(path131.dirname(tempPath), { recursive: true });
|
|
115954
116404
|
const releaseLock = await acquireLock2(lockPath);
|
|
115955
116405
|
try {
|
|
115956
116406
|
let existing = null;
|
|
115957
116407
|
try {
|
|
115958
|
-
const raw =
|
|
116408
|
+
const raw = fs94.readFileSync(baselinePath, "utf-8");
|
|
115959
116409
|
const parsed = JSON.parse(raw);
|
|
115960
116410
|
if (parsed.schema_version === BASELINE_SCHEMA_VERSION) {
|
|
115961
116411
|
existing = parsed;
|
|
115962
116412
|
}
|
|
115963
116413
|
} catch {}
|
|
115964
116414
|
const scannedRelFiles = new Set(scannedFiles.map((f) => normalizeFindingPath(directory, f)));
|
|
115965
|
-
const indexed =
|
|
116415
|
+
const indexed = _internals58.assignOccurrenceIndices(findings, directory);
|
|
115966
116416
|
if (existing && !opts?.force) {
|
|
115967
116417
|
const prunedFingerprints = existing.fingerprints.filter((fp) => {
|
|
115968
116418
|
const relFile = fp.slice(0, fp.indexOf("|"));
|
|
@@ -116015,8 +116465,8 @@ async function captureOrMergeBaseline(directory, phase, findings, engine, scanne
|
|
|
116015
116465
|
message: `Baseline would exceed size cap (${json4.length} bytes > ${MAX_BASELINE_BYTES})`
|
|
116016
116466
|
};
|
|
116017
116467
|
}
|
|
116018
|
-
|
|
116019
|
-
|
|
116468
|
+
fs94.writeFileSync(tempPath, json4, "utf-8");
|
|
116469
|
+
fs94.renameSync(tempPath, baselinePath);
|
|
116020
116470
|
return {
|
|
116021
116471
|
status: "merged",
|
|
116022
116472
|
path: baselinePath,
|
|
@@ -116047,8 +116497,8 @@ async function captureOrMergeBaseline(directory, phase, findings, engine, scanne
|
|
|
116047
116497
|
message: `Baseline would exceed size cap (${json3.length} bytes > ${MAX_BASELINE_BYTES})`
|
|
116048
116498
|
};
|
|
116049
116499
|
}
|
|
116050
|
-
|
|
116051
|
-
|
|
116500
|
+
fs94.writeFileSync(tempPath, json3, "utf-8");
|
|
116501
|
+
fs94.renameSync(tempPath, baselinePath);
|
|
116052
116502
|
return {
|
|
116053
116503
|
status: "written",
|
|
116054
116504
|
path: baselinePath,
|
|
@@ -116073,7 +116523,7 @@ function loadBaseline(directory, phase) {
|
|
|
116073
116523
|
};
|
|
116074
116524
|
}
|
|
116075
116525
|
try {
|
|
116076
|
-
const raw =
|
|
116526
|
+
const raw = fs94.readFileSync(baselinePath, "utf-8");
|
|
116077
116527
|
const parsed = JSON.parse(raw);
|
|
116078
116528
|
if (parsed.schema_version !== BASELINE_SCHEMA_VERSION) {
|
|
116079
116529
|
return {
|
|
@@ -116102,7 +116552,7 @@ function loadBaseline(directory, phase) {
|
|
|
116102
116552
|
};
|
|
116103
116553
|
}
|
|
116104
116554
|
}
|
|
116105
|
-
var
|
|
116555
|
+
var _internals58 = {
|
|
116106
116556
|
fingerprintFinding,
|
|
116107
116557
|
assignOccurrenceIndices,
|
|
116108
116558
|
captureOrMergeBaseline,
|
|
@@ -116121,17 +116571,17 @@ var SEVERITY_ORDER = {
|
|
|
116121
116571
|
};
|
|
116122
116572
|
function shouldSkipFile(filePath) {
|
|
116123
116573
|
try {
|
|
116124
|
-
const stats =
|
|
116574
|
+
const stats = fs95.statSync(filePath);
|
|
116125
116575
|
if (stats.size > MAX_FILE_SIZE_BYTES8) {
|
|
116126
116576
|
return { skip: true, reason: "file too large" };
|
|
116127
116577
|
}
|
|
116128
116578
|
if (stats.size === 0) {
|
|
116129
116579
|
return { skip: true, reason: "empty file" };
|
|
116130
116580
|
}
|
|
116131
|
-
const fd =
|
|
116581
|
+
const fd = fs95.openSync(filePath, "r");
|
|
116132
116582
|
const buffer = Buffer.alloc(8192);
|
|
116133
|
-
const bytesRead =
|
|
116134
|
-
|
|
116583
|
+
const bytesRead = fs95.readSync(fd, buffer, 0, 8192, 0);
|
|
116584
|
+
fs95.closeSync(fd);
|
|
116135
116585
|
if (bytesRead > 0) {
|
|
116136
116586
|
let nullCount = 0;
|
|
116137
116587
|
for (let i2 = 0;i2 < bytesRead; i2++) {
|
|
@@ -116170,7 +116620,7 @@ function countBySeverity(findings) {
|
|
|
116170
116620
|
}
|
|
116171
116621
|
function scanFileWithTierA(filePath, language) {
|
|
116172
116622
|
try {
|
|
116173
|
-
const content =
|
|
116623
|
+
const content = fs95.readFileSync(filePath, "utf-8");
|
|
116174
116624
|
const findings = executeRulesSync(filePath, content, language);
|
|
116175
116625
|
return findings.map((f) => ({
|
|
116176
116626
|
rule_id: f.rule_id,
|
|
@@ -116223,13 +116673,13 @@ async function sastScan(input, directory, config3) {
|
|
|
116223
116673
|
_filesSkipped++;
|
|
116224
116674
|
continue;
|
|
116225
116675
|
}
|
|
116226
|
-
const resolvedPath =
|
|
116227
|
-
const resolvedDirectory =
|
|
116228
|
-
if (!resolvedPath.startsWith(resolvedDirectory +
|
|
116676
|
+
const resolvedPath = path132.isAbsolute(filePath) ? filePath : path132.resolve(directory, filePath);
|
|
116677
|
+
const resolvedDirectory = path132.resolve(directory);
|
|
116678
|
+
if (!resolvedPath.startsWith(resolvedDirectory + path132.sep) && resolvedPath !== resolvedDirectory) {
|
|
116229
116679
|
_filesSkipped++;
|
|
116230
116680
|
continue;
|
|
116231
116681
|
}
|
|
116232
|
-
if (!
|
|
116682
|
+
if (!fs95.existsSync(resolvedPath)) {
|
|
116233
116683
|
_filesSkipped++;
|
|
116234
116684
|
continue;
|
|
116235
116685
|
}
|
|
@@ -116512,11 +116962,11 @@ var sast_scan = createSwarmTool({
|
|
|
116512
116962
|
capture_baseline: safeArgs.capture_baseline,
|
|
116513
116963
|
phase: safeArgs.phase
|
|
116514
116964
|
};
|
|
116515
|
-
const result = await
|
|
116965
|
+
const result = await _internals59.sastScan(input, directory);
|
|
116516
116966
|
return JSON.stringify(result, null, 2);
|
|
116517
116967
|
}
|
|
116518
116968
|
});
|
|
116519
|
-
var
|
|
116969
|
+
var _internals59 = {
|
|
116520
116970
|
sastScan,
|
|
116521
116971
|
sast_scan
|
|
116522
116972
|
};
|
|
@@ -116540,20 +116990,20 @@ function validatePath(inputPath, baseDir, workspaceDir) {
|
|
|
116540
116990
|
let resolved;
|
|
116541
116991
|
const isWinAbs = isWindowsAbsolutePath(inputPath);
|
|
116542
116992
|
if (isWinAbs) {
|
|
116543
|
-
resolved =
|
|
116544
|
-
} else if (
|
|
116545
|
-
resolved =
|
|
116993
|
+
resolved = path133.win32.resolve(inputPath);
|
|
116994
|
+
} else if (path133.isAbsolute(inputPath)) {
|
|
116995
|
+
resolved = path133.resolve(inputPath);
|
|
116546
116996
|
} else {
|
|
116547
|
-
resolved =
|
|
116997
|
+
resolved = path133.resolve(baseDir, inputPath);
|
|
116548
116998
|
}
|
|
116549
|
-
const workspaceResolved =
|
|
116550
|
-
let
|
|
116999
|
+
const workspaceResolved = path133.resolve(workspaceDir);
|
|
117000
|
+
let relative27;
|
|
116551
117001
|
if (isWinAbs) {
|
|
116552
|
-
|
|
117002
|
+
relative27 = path133.win32.relative(workspaceResolved, resolved);
|
|
116553
117003
|
} else {
|
|
116554
|
-
|
|
117004
|
+
relative27 = path133.relative(workspaceResolved, resolved);
|
|
116555
117005
|
}
|
|
116556
|
-
if (
|
|
117006
|
+
if (relative27.startsWith("..")) {
|
|
116557
117007
|
return "path traversal detected";
|
|
116558
117008
|
}
|
|
116559
117009
|
return null;
|
|
@@ -116616,7 +117066,7 @@ async function runLintOnFiles(linter, files, workspaceDir) {
|
|
|
116616
117066
|
if (typeof file3 !== "string") {
|
|
116617
117067
|
continue;
|
|
116618
117068
|
}
|
|
116619
|
-
const resolvedPath =
|
|
117069
|
+
const resolvedPath = path133.resolve(file3);
|
|
116620
117070
|
const validationError = validatePath(resolvedPath, workspaceDir, workspaceDir);
|
|
116621
117071
|
if (validationError) {
|
|
116622
117072
|
continue;
|
|
@@ -116773,7 +117223,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
116773
117223
|
skippedFiles++;
|
|
116774
117224
|
continue;
|
|
116775
117225
|
}
|
|
116776
|
-
const resolvedPath =
|
|
117226
|
+
const resolvedPath = path133.resolve(file3);
|
|
116777
117227
|
const validationError = validatePath(resolvedPath, directory, directory);
|
|
116778
117228
|
if (validationError) {
|
|
116779
117229
|
skippedFiles++;
|
|
@@ -116791,14 +117241,14 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
116791
117241
|
};
|
|
116792
117242
|
}
|
|
116793
117243
|
for (const file3 of validatedFiles) {
|
|
116794
|
-
const ext =
|
|
117244
|
+
const ext = path133.extname(file3).toLowerCase();
|
|
116795
117245
|
if (DEFAULT_EXCLUDE_EXTENSIONS2.has(ext)) {
|
|
116796
117246
|
skippedFiles++;
|
|
116797
117247
|
continue;
|
|
116798
117248
|
}
|
|
116799
117249
|
let stat9;
|
|
116800
117250
|
try {
|
|
116801
|
-
stat9 =
|
|
117251
|
+
stat9 = fs96.statSync(file3);
|
|
116802
117252
|
} catch {
|
|
116803
117253
|
skippedFiles++;
|
|
116804
117254
|
continue;
|
|
@@ -116809,7 +117259,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
116809
117259
|
}
|
|
116810
117260
|
let content;
|
|
116811
117261
|
try {
|
|
116812
|
-
const buffer =
|
|
117262
|
+
const buffer = fs96.readFileSync(file3);
|
|
116813
117263
|
if (buffer.includes(0)) {
|
|
116814
117264
|
skippedFiles++;
|
|
116815
117265
|
continue;
|
|
@@ -117010,7 +117460,7 @@ function classifySastFindings(findings, changedLineRanges, directory) {
|
|
|
117010
117460
|
const preexistingFindings = [];
|
|
117011
117461
|
for (const finding of findings) {
|
|
117012
117462
|
const filePath = finding.location.file;
|
|
117013
|
-
const normalised =
|
|
117463
|
+
const normalised = path133.relative(directory, filePath).replace(/\\/g, "/");
|
|
117014
117464
|
const changedLines = changedLineRanges.get(normalised);
|
|
117015
117465
|
if (changedLines?.has(finding.location.line)) {
|
|
117016
117466
|
newFindings.push(finding);
|
|
@@ -117061,7 +117511,7 @@ async function runPreCheckBatch(input, workspaceDir, contextDir) {
|
|
|
117061
117511
|
warn(`pre_check_batch: Invalid file path: ${file3}`);
|
|
117062
117512
|
continue;
|
|
117063
117513
|
}
|
|
117064
|
-
changedFiles.push(
|
|
117514
|
+
changedFiles.push(path133.resolve(directory, file3));
|
|
117065
117515
|
}
|
|
117066
117516
|
if (changedFiles.length === 0) {
|
|
117067
117517
|
warn("pre_check_batch: No valid files after validation, skipping all tools (fail-closed)");
|
|
@@ -117262,9 +117712,9 @@ var pre_check_batch = createSwarmTool({
|
|
|
117262
117712
|
};
|
|
117263
117713
|
return JSON.stringify(errorResult, null, 2);
|
|
117264
117714
|
}
|
|
117265
|
-
const resolvedDirectory =
|
|
117266
|
-
const workspaceAnchor =
|
|
117267
|
-
if (resolvedDirectory !== workspaceAnchor && resolvedDirectory.startsWith(workspaceAnchor +
|
|
117715
|
+
const resolvedDirectory = path133.resolve(typedArgs.directory);
|
|
117716
|
+
const workspaceAnchor = path133.resolve(directory);
|
|
117717
|
+
if (resolvedDirectory !== workspaceAnchor && resolvedDirectory.startsWith(workspaceAnchor + path133.sep)) {
|
|
117268
117718
|
const subDirError = `directory "${typedArgs.directory}" is a subdirectory of the project root — pre_check_batch requires the project root directory "${workspaceAnchor}"`;
|
|
117269
117719
|
const subDirResult = {
|
|
117270
117720
|
gates_passed: false,
|
|
@@ -117315,7 +117765,7 @@ var pre_check_batch = createSwarmTool({
|
|
|
117315
117765
|
});
|
|
117316
117766
|
// src/tools/repo-map.ts
|
|
117317
117767
|
init_zod();
|
|
117318
|
-
import * as
|
|
117768
|
+
import * as path134 from "node:path";
|
|
117319
117769
|
init_path_security();
|
|
117320
117770
|
init_create_tool();
|
|
117321
117771
|
var VALID_ACTIONS = [
|
|
@@ -117340,7 +117790,7 @@ function validateFile(p) {
|
|
|
117340
117790
|
return "file contains control characters";
|
|
117341
117791
|
if (containsPathTraversal(p))
|
|
117342
117792
|
return "file contains path traversal";
|
|
117343
|
-
if (
|
|
117793
|
+
if (path134.isAbsolute(p) || /^[a-zA-Z]:[\\/]/.test(p)) {
|
|
117344
117794
|
return "file must be a workspace-relative path, not absolute";
|
|
117345
117795
|
}
|
|
117346
117796
|
return null;
|
|
@@ -117363,8 +117813,8 @@ function ok(action, payload) {
|
|
|
117363
117813
|
}
|
|
117364
117814
|
function toRelativeGraphPath(input, workspaceRoot) {
|
|
117365
117815
|
const normalized = input.replace(/\\/g, "/");
|
|
117366
|
-
if (
|
|
117367
|
-
const rel =
|
|
117816
|
+
if (path134.isAbsolute(normalized)) {
|
|
117817
|
+
const rel = path134.relative(workspaceRoot, normalized).replace(/\\/g, "/");
|
|
117368
117818
|
return normalizeGraphPath2(rel);
|
|
117369
117819
|
}
|
|
117370
117820
|
return normalizeGraphPath2(normalized);
|
|
@@ -117508,8 +117958,8 @@ var repo_map = createSwarmTool({
|
|
|
117508
117958
|
// src/tools/req-coverage.ts
|
|
117509
117959
|
init_zod();
|
|
117510
117960
|
init_create_tool();
|
|
117511
|
-
import * as
|
|
117512
|
-
import * as
|
|
117961
|
+
import * as fs97 from "node:fs";
|
|
117962
|
+
import * as path135 from "node:path";
|
|
117513
117963
|
var SPEC_FILE = ".swarm/spec.md";
|
|
117514
117964
|
var EVIDENCE_DIR4 = ".swarm/evidence";
|
|
117515
117965
|
var OBLIGATION_KEYWORDS = ["MUST", "SHOULD", "SHALL"];
|
|
@@ -117568,19 +118018,19 @@ function extractObligationAndText(id, lineText) {
|
|
|
117568
118018
|
var PHASE_TASK_ID_REGEX = /^\d+\.\d+(\.\d+)*$/;
|
|
117569
118019
|
function readTouchedFiles(evidenceDir, phase, cwd) {
|
|
117570
118020
|
const touchedFiles = new Set;
|
|
117571
|
-
if (!
|
|
118021
|
+
if (!fs97.existsSync(evidenceDir) || !fs97.statSync(evidenceDir).isDirectory()) {
|
|
117572
118022
|
return [];
|
|
117573
118023
|
}
|
|
117574
118024
|
let entries;
|
|
117575
118025
|
try {
|
|
117576
|
-
entries =
|
|
118026
|
+
entries = fs97.readdirSync(evidenceDir);
|
|
117577
118027
|
} catch {
|
|
117578
118028
|
return [];
|
|
117579
118029
|
}
|
|
117580
118030
|
for (const entry of entries) {
|
|
117581
|
-
const entryPath =
|
|
118031
|
+
const entryPath = path135.join(evidenceDir, entry);
|
|
117582
118032
|
try {
|
|
117583
|
-
const stat9 =
|
|
118033
|
+
const stat9 = fs97.statSync(entryPath);
|
|
117584
118034
|
if (!stat9.isDirectory()) {
|
|
117585
118035
|
continue;
|
|
117586
118036
|
}
|
|
@@ -117594,14 +118044,14 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
|
|
|
117594
118044
|
if (entryPhase !== String(phase)) {
|
|
117595
118045
|
continue;
|
|
117596
118046
|
}
|
|
117597
|
-
const evidenceFilePath =
|
|
118047
|
+
const evidenceFilePath = path135.join(entryPath, "evidence.json");
|
|
117598
118048
|
try {
|
|
117599
|
-
const resolvedPath =
|
|
117600
|
-
const evidenceDirResolved =
|
|
117601
|
-
if (!resolvedPath.startsWith(evidenceDirResolved +
|
|
118049
|
+
const resolvedPath = path135.resolve(evidenceFilePath);
|
|
118050
|
+
const evidenceDirResolved = path135.resolve(evidenceDir);
|
|
118051
|
+
if (!resolvedPath.startsWith(evidenceDirResolved + path135.sep)) {
|
|
117602
118052
|
continue;
|
|
117603
118053
|
}
|
|
117604
|
-
const stat9 =
|
|
118054
|
+
const stat9 = fs97.lstatSync(evidenceFilePath);
|
|
117605
118055
|
if (!stat9.isFile()) {
|
|
117606
118056
|
continue;
|
|
117607
118057
|
}
|
|
@@ -117613,7 +118063,7 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
|
|
|
117613
118063
|
}
|
|
117614
118064
|
let content;
|
|
117615
118065
|
try {
|
|
117616
|
-
content =
|
|
118066
|
+
content = fs97.readFileSync(evidenceFilePath, "utf-8");
|
|
117617
118067
|
} catch {
|
|
117618
118068
|
continue;
|
|
117619
118069
|
}
|
|
@@ -117632,7 +118082,7 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
|
|
|
117632
118082
|
if (Array.isArray(diffEntry.files_changed)) {
|
|
117633
118083
|
for (const file3 of diffEntry.files_changed) {
|
|
117634
118084
|
if (typeof file3 === "string") {
|
|
117635
|
-
touchedFiles.add(
|
|
118085
|
+
touchedFiles.add(path135.resolve(cwd, file3));
|
|
117636
118086
|
}
|
|
117637
118087
|
}
|
|
117638
118088
|
}
|
|
@@ -117645,12 +118095,12 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
|
|
|
117645
118095
|
}
|
|
117646
118096
|
function searchFileForKeywords(filePath, keywords, cwd) {
|
|
117647
118097
|
try {
|
|
117648
|
-
const resolvedPath =
|
|
117649
|
-
const cwdResolved =
|
|
118098
|
+
const resolvedPath = path135.resolve(filePath);
|
|
118099
|
+
const cwdResolved = path135.resolve(cwd);
|
|
117650
118100
|
if (!resolvedPath.startsWith(cwdResolved)) {
|
|
117651
118101
|
return false;
|
|
117652
118102
|
}
|
|
117653
|
-
const content =
|
|
118103
|
+
const content = fs97.readFileSync(resolvedPath, "utf-8");
|
|
117654
118104
|
for (const keyword of keywords) {
|
|
117655
118105
|
const regex = new RegExp(`\\b${keyword}\\b`, "i");
|
|
117656
118106
|
if (regex.test(content)) {
|
|
@@ -117780,10 +118230,10 @@ var req_coverage = createSwarmTool({
|
|
|
117780
118230
|
}, null, 2);
|
|
117781
118231
|
}
|
|
117782
118232
|
const cwd = inputDirectory || directory;
|
|
117783
|
-
const specPath =
|
|
118233
|
+
const specPath = path135.join(cwd, SPEC_FILE);
|
|
117784
118234
|
let specContent;
|
|
117785
118235
|
try {
|
|
117786
|
-
specContent =
|
|
118236
|
+
specContent = fs97.readFileSync(specPath, "utf-8");
|
|
117787
118237
|
} catch (readError) {
|
|
117788
118238
|
return JSON.stringify({
|
|
117789
118239
|
success: false,
|
|
@@ -117807,7 +118257,7 @@ var req_coverage = createSwarmTool({
|
|
|
117807
118257
|
message: "No FR requirements found in spec.md"
|
|
117808
118258
|
}, null, 2);
|
|
117809
118259
|
}
|
|
117810
|
-
const evidenceDir =
|
|
118260
|
+
const evidenceDir = path135.join(cwd, EVIDENCE_DIR4);
|
|
117811
118261
|
const touchedFiles = readTouchedFiles(evidenceDir, phase, cwd);
|
|
117812
118262
|
const analyzedRequirements = [];
|
|
117813
118263
|
let coveredCount = 0;
|
|
@@ -117833,12 +118283,12 @@ var req_coverage = createSwarmTool({
|
|
|
117833
118283
|
requirements: analyzedRequirements
|
|
117834
118284
|
};
|
|
117835
118285
|
const reportFilename = `req-coverage-phase-${phase}.json`;
|
|
117836
|
-
const reportPath =
|
|
118286
|
+
const reportPath = path135.join(evidenceDir, reportFilename);
|
|
117837
118287
|
try {
|
|
117838
|
-
if (!
|
|
117839
|
-
|
|
118288
|
+
if (!fs97.existsSync(evidenceDir)) {
|
|
118289
|
+
fs97.mkdirSync(evidenceDir, { recursive: true });
|
|
117840
118290
|
}
|
|
117841
|
-
|
|
118291
|
+
fs97.writeFileSync(reportPath, JSON.stringify(result, null, 2), "utf-8");
|
|
117842
118292
|
} catch (writeError) {
|
|
117843
118293
|
console.warn(`Failed to write coverage report: ${writeError instanceof Error ? writeError.message : String(writeError)}`);
|
|
117844
118294
|
}
|
|
@@ -117920,8 +118370,8 @@ init_plan_schema();
|
|
|
117920
118370
|
init_qa_gate_profile();
|
|
117921
118371
|
init_file_locks();
|
|
117922
118372
|
import * as crypto12 from "node:crypto";
|
|
117923
|
-
import * as
|
|
117924
|
-
import * as
|
|
118373
|
+
import * as fs98 from "node:fs";
|
|
118374
|
+
import * as path136 from "node:path";
|
|
117925
118375
|
init_ledger();
|
|
117926
118376
|
init_manager();
|
|
117927
118377
|
init_state();
|
|
@@ -118002,17 +118452,17 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
118002
118452
|
};
|
|
118003
118453
|
}
|
|
118004
118454
|
if (args2.working_directory && fallbackDir) {
|
|
118005
|
-
const resolvedTarget =
|
|
118006
|
-
const resolvedRoot =
|
|
118455
|
+
const resolvedTarget = path136.resolve(args2.working_directory);
|
|
118456
|
+
const resolvedRoot = path136.resolve(fallbackDir);
|
|
118007
118457
|
let fallbackExists = false;
|
|
118008
118458
|
try {
|
|
118009
|
-
|
|
118459
|
+
fs98.accessSync(resolvedRoot, fs98.constants.F_OK);
|
|
118010
118460
|
fallbackExists = true;
|
|
118011
118461
|
} catch {
|
|
118012
118462
|
fallbackExists = false;
|
|
118013
118463
|
}
|
|
118014
118464
|
if (fallbackExists) {
|
|
118015
|
-
const isSubdirectory = resolvedTarget.startsWith(resolvedRoot +
|
|
118465
|
+
const isSubdirectory = resolvedTarget.startsWith(resolvedRoot + path136.sep);
|
|
118016
118466
|
if (isSubdirectory) {
|
|
118017
118467
|
return {
|
|
118018
118468
|
success: false,
|
|
@@ -118028,11 +118478,11 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
118028
118478
|
let specMtime;
|
|
118029
118479
|
let specHash;
|
|
118030
118480
|
if (process.env.SWARM_SKIP_SPEC_GATE !== "1") {
|
|
118031
|
-
const specPath =
|
|
118481
|
+
const specPath = path136.join(targetWorkspace, ".swarm", "spec.md");
|
|
118032
118482
|
try {
|
|
118033
|
-
const stat9 = await
|
|
118483
|
+
const stat9 = await fs98.promises.stat(specPath);
|
|
118034
118484
|
specMtime = stat9.mtime.toISOString();
|
|
118035
|
-
const content = await
|
|
118485
|
+
const content = await fs98.promises.readFile(specPath, "utf8");
|
|
118036
118486
|
specHash = crypto12.createHash("sha256").update(content).digest("hex");
|
|
118037
118487
|
} catch {
|
|
118038
118488
|
return {
|
|
@@ -118044,10 +118494,10 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
118044
118494
|
}
|
|
118045
118495
|
}
|
|
118046
118496
|
if (process.env.SWARM_SKIP_GATE_SELECTION !== "1") {
|
|
118047
|
-
const contextPath =
|
|
118497
|
+
const contextPath = path136.join(targetWorkspace, ".swarm", "context.md");
|
|
118048
118498
|
let contextContent = "";
|
|
118049
118499
|
try {
|
|
118050
|
-
contextContent = await
|
|
118500
|
+
contextContent = await fs98.promises.readFile(contextPath, "utf8");
|
|
118051
118501
|
} catch {}
|
|
118052
118502
|
const hasPendingSection = contextContent.includes("## Pending QA Gate Selection");
|
|
118053
118503
|
if (!hasPendingSection) {
|
|
@@ -118334,14 +118784,14 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
118334
118784
|
}
|
|
118335
118785
|
await writeCheckpoint(dir).catch(() => {});
|
|
118336
118786
|
try {
|
|
118337
|
-
const markerPath =
|
|
118787
|
+
const markerPath = path136.join(dir, ".swarm", ".plan-write-marker");
|
|
118338
118788
|
const marker = JSON.stringify({
|
|
118339
118789
|
source: "save_plan",
|
|
118340
118790
|
timestamp: new Date().toISOString(),
|
|
118341
118791
|
phases_count: plan.phases.length,
|
|
118342
118792
|
tasks_count: tasksCount
|
|
118343
118793
|
});
|
|
118344
|
-
await
|
|
118794
|
+
await fs98.promises.writeFile(markerPath, marker, "utf8");
|
|
118345
118795
|
} catch {}
|
|
118346
118796
|
const warnings = [];
|
|
118347
118797
|
let criticReviewFound = false;
|
|
@@ -118357,7 +118807,7 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
118357
118807
|
return {
|
|
118358
118808
|
success: true,
|
|
118359
118809
|
message: "Plan saved successfully",
|
|
118360
|
-
plan_path:
|
|
118810
|
+
plan_path: path136.join(dir, ".swarm", "plan.json"),
|
|
118361
118811
|
phases_count: plan.phases.length,
|
|
118362
118812
|
tasks_count: tasksCount,
|
|
118363
118813
|
...resolvedProfile !== undefined ? { execution_profile: resolvedProfile } : {},
|
|
@@ -118422,8 +118872,8 @@ var save_plan = createSwarmTool({
|
|
|
118422
118872
|
// src/tools/sbom-generate.ts
|
|
118423
118873
|
init_zod();
|
|
118424
118874
|
init_manager2();
|
|
118425
|
-
import * as
|
|
118426
|
-
import * as
|
|
118875
|
+
import * as fs99 from "node:fs";
|
|
118876
|
+
import * as path137 from "node:path";
|
|
118427
118877
|
|
|
118428
118878
|
// src/sbom/detectors/index.ts
|
|
118429
118879
|
init_utils();
|
|
@@ -119271,9 +119721,9 @@ function findManifestFiles(rootDir) {
|
|
|
119271
119721
|
const patterns = [...new Set(allDetectors.flatMap((d) => d.patterns))];
|
|
119272
119722
|
function searchDir(dir) {
|
|
119273
119723
|
try {
|
|
119274
|
-
const entries =
|
|
119724
|
+
const entries = fs99.readdirSync(dir, { withFileTypes: true });
|
|
119275
119725
|
for (const entry of entries) {
|
|
119276
|
-
const fullPath =
|
|
119726
|
+
const fullPath = path137.join(dir, entry.name);
|
|
119277
119727
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "target") {
|
|
119278
119728
|
continue;
|
|
119279
119729
|
}
|
|
@@ -119282,7 +119732,7 @@ function findManifestFiles(rootDir) {
|
|
|
119282
119732
|
} else if (entry.isFile()) {
|
|
119283
119733
|
for (const pattern of patterns) {
|
|
119284
119734
|
if (simpleGlobToRegex(pattern).test(entry.name)) {
|
|
119285
|
-
manifestFiles.push(
|
|
119735
|
+
manifestFiles.push(path137.relative(rootDir, fullPath));
|
|
119286
119736
|
break;
|
|
119287
119737
|
}
|
|
119288
119738
|
}
|
|
@@ -119298,13 +119748,13 @@ function findManifestFilesInDirs(directories, workingDir) {
|
|
|
119298
119748
|
const patterns = [...new Set(allDetectors.flatMap((d) => d.patterns))];
|
|
119299
119749
|
for (const dir of directories) {
|
|
119300
119750
|
try {
|
|
119301
|
-
const entries =
|
|
119751
|
+
const entries = fs99.readdirSync(dir, { withFileTypes: true });
|
|
119302
119752
|
for (const entry of entries) {
|
|
119303
|
-
const fullPath =
|
|
119753
|
+
const fullPath = path137.join(dir, entry.name);
|
|
119304
119754
|
if (entry.isFile()) {
|
|
119305
119755
|
for (const pattern of patterns) {
|
|
119306
119756
|
if (simpleGlobToRegex(pattern).test(entry.name)) {
|
|
119307
|
-
found.push(
|
|
119757
|
+
found.push(path137.relative(workingDir, fullPath));
|
|
119308
119758
|
break;
|
|
119309
119759
|
}
|
|
119310
119760
|
}
|
|
@@ -119317,11 +119767,11 @@ function findManifestFilesInDirs(directories, workingDir) {
|
|
|
119317
119767
|
function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
|
|
119318
119768
|
const dirs = new Set;
|
|
119319
119769
|
for (const file3 of changedFiles) {
|
|
119320
|
-
let currentDir =
|
|
119770
|
+
let currentDir = path137.dirname(file3);
|
|
119321
119771
|
while (true) {
|
|
119322
|
-
if (currentDir && currentDir !== "." && currentDir !==
|
|
119323
|
-
dirs.add(
|
|
119324
|
-
const parent =
|
|
119772
|
+
if (currentDir && currentDir !== "." && currentDir !== path137.sep) {
|
|
119773
|
+
dirs.add(path137.join(workingDir, currentDir));
|
|
119774
|
+
const parent = path137.dirname(currentDir);
|
|
119325
119775
|
if (parent === currentDir)
|
|
119326
119776
|
break;
|
|
119327
119777
|
currentDir = parent;
|
|
@@ -119335,7 +119785,7 @@ function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
|
|
|
119335
119785
|
}
|
|
119336
119786
|
function ensureOutputDir(outputDir) {
|
|
119337
119787
|
try {
|
|
119338
|
-
|
|
119788
|
+
fs99.mkdirSync(outputDir, { recursive: true });
|
|
119339
119789
|
} catch (error93) {
|
|
119340
119790
|
if (!error93 || error93.code !== "EEXIST") {
|
|
119341
119791
|
throw error93;
|
|
@@ -119405,7 +119855,7 @@ var sbom_generate = createSwarmTool({
|
|
|
119405
119855
|
const changedFiles = obj.changed_files;
|
|
119406
119856
|
const relativeOutputDir = obj.output_dir || DEFAULT_OUTPUT_DIR;
|
|
119407
119857
|
const workingDir = directory;
|
|
119408
|
-
const outputDir =
|
|
119858
|
+
const outputDir = path137.isAbsolute(relativeOutputDir) ? relativeOutputDir : path137.join(workingDir, relativeOutputDir);
|
|
119409
119859
|
let manifestFiles = [];
|
|
119410
119860
|
if (scope === "all") {
|
|
119411
119861
|
manifestFiles = findManifestFiles(workingDir);
|
|
@@ -119428,11 +119878,11 @@ var sbom_generate = createSwarmTool({
|
|
|
119428
119878
|
const processedFiles = [];
|
|
119429
119879
|
for (const manifestFile of manifestFiles) {
|
|
119430
119880
|
try {
|
|
119431
|
-
const fullPath =
|
|
119432
|
-
if (!
|
|
119881
|
+
const fullPath = path137.isAbsolute(manifestFile) ? manifestFile : path137.join(workingDir, manifestFile);
|
|
119882
|
+
if (!fs99.existsSync(fullPath)) {
|
|
119433
119883
|
continue;
|
|
119434
119884
|
}
|
|
119435
|
-
const content =
|
|
119885
|
+
const content = fs99.readFileSync(fullPath, "utf-8");
|
|
119436
119886
|
const components = detectComponents(manifestFile, content);
|
|
119437
119887
|
processedFiles.push(manifestFile);
|
|
119438
119888
|
if (components.length > 0) {
|
|
@@ -119445,8 +119895,8 @@ var sbom_generate = createSwarmTool({
|
|
|
119445
119895
|
const bom = generateCycloneDX(allComponents);
|
|
119446
119896
|
const bomJson = serializeCycloneDX(bom);
|
|
119447
119897
|
const filename = generateSbomFilename();
|
|
119448
|
-
const outputPath =
|
|
119449
|
-
|
|
119898
|
+
const outputPath = path137.join(outputDir, filename);
|
|
119899
|
+
fs99.writeFileSync(outputPath, bomJson, "utf-8");
|
|
119450
119900
|
const verdict = processedFiles.length > 0 ? "pass" : "pass";
|
|
119451
119901
|
try {
|
|
119452
119902
|
const timestamp = new Date().toISOString();
|
|
@@ -119488,8 +119938,8 @@ var sbom_generate = createSwarmTool({
|
|
|
119488
119938
|
// src/tools/schema-drift.ts
|
|
119489
119939
|
init_zod();
|
|
119490
119940
|
init_create_tool();
|
|
119491
|
-
import * as
|
|
119492
|
-
import * as
|
|
119941
|
+
import * as fs100 from "node:fs";
|
|
119942
|
+
import * as path138 from "node:path";
|
|
119493
119943
|
var SPEC_CANDIDATES = [
|
|
119494
119944
|
"openapi.json",
|
|
119495
119945
|
"openapi.yaml",
|
|
@@ -119521,28 +119971,28 @@ function normalizePath4(p) {
|
|
|
119521
119971
|
}
|
|
119522
119972
|
function discoverSpecFile(cwd, specFileArg) {
|
|
119523
119973
|
if (specFileArg) {
|
|
119524
|
-
const resolvedPath =
|
|
119525
|
-
const normalizedCwd = cwd.endsWith(
|
|
119974
|
+
const resolvedPath = path138.resolve(cwd, specFileArg);
|
|
119975
|
+
const normalizedCwd = cwd.endsWith(path138.sep) ? cwd : cwd + path138.sep;
|
|
119526
119976
|
if (!resolvedPath.startsWith(normalizedCwd) && resolvedPath !== cwd) {
|
|
119527
119977
|
throw new Error("Invalid spec_file: path traversal detected");
|
|
119528
119978
|
}
|
|
119529
|
-
const ext =
|
|
119979
|
+
const ext = path138.extname(resolvedPath).toLowerCase();
|
|
119530
119980
|
if (!ALLOWED_EXTENSIONS.includes(ext)) {
|
|
119531
119981
|
throw new Error(`Invalid spec_file: must end in .json, .yaml, or .yml, got ${ext}`);
|
|
119532
119982
|
}
|
|
119533
|
-
const stats =
|
|
119983
|
+
const stats = fs100.statSync(resolvedPath);
|
|
119534
119984
|
if (stats.size > MAX_SPEC_SIZE) {
|
|
119535
119985
|
throw new Error(`Invalid spec_file: file exceeds ${MAX_SPEC_SIZE / 1024 / 1024}MB limit`);
|
|
119536
119986
|
}
|
|
119537
|
-
if (!
|
|
119987
|
+
if (!fs100.existsSync(resolvedPath)) {
|
|
119538
119988
|
throw new Error(`Spec file not found: ${resolvedPath}`);
|
|
119539
119989
|
}
|
|
119540
119990
|
return resolvedPath;
|
|
119541
119991
|
}
|
|
119542
119992
|
for (const candidate of SPEC_CANDIDATES) {
|
|
119543
|
-
const candidatePath =
|
|
119544
|
-
if (
|
|
119545
|
-
const stats =
|
|
119993
|
+
const candidatePath = path138.resolve(cwd, candidate);
|
|
119994
|
+
if (fs100.existsSync(candidatePath)) {
|
|
119995
|
+
const stats = fs100.statSync(candidatePath);
|
|
119546
119996
|
if (stats.size <= MAX_SPEC_SIZE) {
|
|
119547
119997
|
return candidatePath;
|
|
119548
119998
|
}
|
|
@@ -119551,8 +120001,8 @@ function discoverSpecFile(cwd, specFileArg) {
|
|
|
119551
120001
|
return null;
|
|
119552
120002
|
}
|
|
119553
120003
|
function parseSpec(specFile) {
|
|
119554
|
-
const content =
|
|
119555
|
-
const ext =
|
|
120004
|
+
const content = fs100.readFileSync(specFile, "utf-8");
|
|
120005
|
+
const ext = path138.extname(specFile).toLowerCase();
|
|
119556
120006
|
if (ext === ".json") {
|
|
119557
120007
|
return parseJsonSpec(content);
|
|
119558
120008
|
}
|
|
@@ -119623,12 +120073,12 @@ function extractRoutes(cwd) {
|
|
|
119623
120073
|
function walkDir(dir) {
|
|
119624
120074
|
let entries;
|
|
119625
120075
|
try {
|
|
119626
|
-
entries =
|
|
120076
|
+
entries = fs100.readdirSync(dir, { withFileTypes: true });
|
|
119627
120077
|
} catch {
|
|
119628
120078
|
return;
|
|
119629
120079
|
}
|
|
119630
120080
|
for (const entry of entries) {
|
|
119631
|
-
const fullPath =
|
|
120081
|
+
const fullPath = path138.join(dir, entry.name);
|
|
119632
120082
|
if (entry.isSymbolicLink()) {
|
|
119633
120083
|
continue;
|
|
119634
120084
|
}
|
|
@@ -119638,7 +120088,7 @@ function extractRoutes(cwd) {
|
|
|
119638
120088
|
}
|
|
119639
120089
|
walkDir(fullPath);
|
|
119640
120090
|
} else if (entry.isFile()) {
|
|
119641
|
-
const ext =
|
|
120091
|
+
const ext = path138.extname(entry.name).toLowerCase();
|
|
119642
120092
|
const baseName = entry.name.toLowerCase();
|
|
119643
120093
|
if (![".ts", ".js", ".mjs"].includes(ext)) {
|
|
119644
120094
|
continue;
|
|
@@ -119656,7 +120106,7 @@ function extractRoutes(cwd) {
|
|
|
119656
120106
|
}
|
|
119657
120107
|
function extractRoutesFromFile(filePath) {
|
|
119658
120108
|
const routes = [];
|
|
119659
|
-
const content =
|
|
120109
|
+
const content = fs100.readFileSync(filePath, "utf-8");
|
|
119660
120110
|
const lines = content.split(/\r?\n/);
|
|
119661
120111
|
const expressRegex = /(?:app|router|server|express)\.(get|post|put|patch|delete|options|head)\s*\(\s*['"`]([^'"`]+)['"`]/g;
|
|
119662
120112
|
const flaskRegex = /@(?:app|blueprint|bp)\.route\s*\(\s*['"]([^'"]+)['"]/g;
|
|
@@ -119805,8 +120255,8 @@ init_zod();
|
|
|
119805
120255
|
init_bun_compat();
|
|
119806
120256
|
init_path_security();
|
|
119807
120257
|
init_create_tool();
|
|
119808
|
-
import * as
|
|
119809
|
-
import * as
|
|
120258
|
+
import * as fs101 from "node:fs";
|
|
120259
|
+
import * as path139 from "node:path";
|
|
119810
120260
|
var DEFAULT_MAX_RESULTS = 100;
|
|
119811
120261
|
var DEFAULT_MAX_LINES = 200;
|
|
119812
120262
|
var REGEX_TIMEOUT_MS = 5000;
|
|
@@ -119842,11 +120292,11 @@ function containsWindowsAttacks3(str) {
|
|
|
119842
120292
|
}
|
|
119843
120293
|
function isPathInWorkspace3(filePath, workspace) {
|
|
119844
120294
|
try {
|
|
119845
|
-
const resolvedPath =
|
|
119846
|
-
const realWorkspace =
|
|
119847
|
-
const realResolvedPath =
|
|
119848
|
-
const relativePath =
|
|
119849
|
-
if (relativePath.startsWith("..") ||
|
|
120295
|
+
const resolvedPath = path139.resolve(workspace, filePath);
|
|
120296
|
+
const realWorkspace = fs101.realpathSync(workspace);
|
|
120297
|
+
const realResolvedPath = fs101.realpathSync(resolvedPath);
|
|
120298
|
+
const relativePath = path139.relative(realWorkspace, realResolvedPath);
|
|
120299
|
+
if (relativePath.startsWith("..") || path139.isAbsolute(relativePath)) {
|
|
119850
120300
|
return false;
|
|
119851
120301
|
}
|
|
119852
120302
|
return true;
|
|
@@ -119859,12 +120309,12 @@ function validatePathForRead2(filePath, workspace) {
|
|
|
119859
120309
|
}
|
|
119860
120310
|
function findRgInEnvPath() {
|
|
119861
120311
|
const searchPath = process.env.PATH ?? "";
|
|
119862
|
-
for (const dir of searchPath.split(
|
|
120312
|
+
for (const dir of searchPath.split(path139.delimiter)) {
|
|
119863
120313
|
if (!dir)
|
|
119864
120314
|
continue;
|
|
119865
120315
|
const isWindows = process.platform === "win32";
|
|
119866
|
-
const candidate =
|
|
119867
|
-
if (
|
|
120316
|
+
const candidate = path139.join(dir, isWindows ? "rg.exe" : "rg");
|
|
120317
|
+
if (fs101.existsSync(candidate))
|
|
119868
120318
|
return candidate;
|
|
119869
120319
|
}
|
|
119870
120320
|
return null;
|
|
@@ -119918,7 +120368,7 @@ async function ripgrepSearch(opts) {
|
|
|
119918
120368
|
stderr: "pipe",
|
|
119919
120369
|
cwd: opts.workspace
|
|
119920
120370
|
});
|
|
119921
|
-
const timeout = new Promise((
|
|
120371
|
+
const timeout = new Promise((resolve54) => setTimeout(() => resolve54("timeout"), REGEX_TIMEOUT_MS));
|
|
119922
120372
|
const exitPromise = proc.exited;
|
|
119923
120373
|
const result = await Promise.race([exitPromise, timeout]);
|
|
119924
120374
|
if (result === "timeout") {
|
|
@@ -119991,10 +120441,10 @@ function collectFiles(dir, workspace, includeGlobs, excludeGlobs) {
|
|
|
119991
120441
|
return files;
|
|
119992
120442
|
}
|
|
119993
120443
|
try {
|
|
119994
|
-
const entries =
|
|
120444
|
+
const entries = fs101.readdirSync(dir, { withFileTypes: true });
|
|
119995
120445
|
for (const entry of entries) {
|
|
119996
|
-
const fullPath =
|
|
119997
|
-
const relativePath =
|
|
120446
|
+
const fullPath = path139.join(dir, entry.name);
|
|
120447
|
+
const relativePath = path139.relative(workspace, fullPath);
|
|
119998
120448
|
if (!validatePathForRead2(fullPath, workspace)) {
|
|
119999
120449
|
continue;
|
|
120000
120450
|
}
|
|
@@ -120035,13 +120485,13 @@ async function fallbackSearch(opts) {
|
|
|
120035
120485
|
const matches = [];
|
|
120036
120486
|
let total = 0;
|
|
120037
120487
|
for (const file3 of files) {
|
|
120038
|
-
const fullPath =
|
|
120488
|
+
const fullPath = path139.join(opts.workspace, file3);
|
|
120039
120489
|
if (!validatePathForRead2(fullPath, opts.workspace)) {
|
|
120040
120490
|
continue;
|
|
120041
120491
|
}
|
|
120042
120492
|
let stats;
|
|
120043
120493
|
try {
|
|
120044
|
-
stats =
|
|
120494
|
+
stats = fs101.statSync(fullPath);
|
|
120045
120495
|
if (stats.size > MAX_FILE_SIZE_BYTES10) {
|
|
120046
120496
|
continue;
|
|
120047
120497
|
}
|
|
@@ -120050,7 +120500,7 @@ async function fallbackSearch(opts) {
|
|
|
120050
120500
|
}
|
|
120051
120501
|
let content;
|
|
120052
120502
|
try {
|
|
120053
|
-
content =
|
|
120503
|
+
content = fs101.readFileSync(fullPath, "utf-8");
|
|
120054
120504
|
} catch {
|
|
120055
120505
|
continue;
|
|
120056
120506
|
}
|
|
@@ -120162,7 +120612,7 @@ var search = createSwarmTool({
|
|
|
120162
120612
|
message: "Exclude pattern contains invalid Windows-specific sequence"
|
|
120163
120613
|
}, null, 2);
|
|
120164
120614
|
}
|
|
120165
|
-
if (!
|
|
120615
|
+
if (!fs101.existsSync(directory)) {
|
|
120166
120616
|
return JSON.stringify({
|
|
120167
120617
|
error: true,
|
|
120168
120618
|
type: "unknown",
|
|
@@ -120440,7 +120890,7 @@ init_config();
|
|
|
120440
120890
|
init_schema();
|
|
120441
120891
|
init_create_tool();
|
|
120442
120892
|
import { mkdir as mkdir23, rename as rename9, writeFile as writeFile18 } from "node:fs/promises";
|
|
120443
|
-
import * as
|
|
120893
|
+
import * as path140 from "node:path";
|
|
120444
120894
|
var MAX_SPEC_BYTES = 256 * 1024;
|
|
120445
120895
|
var spec_write = createSwarmTool({
|
|
120446
120896
|
description: "Write the canonical project spec to .swarm/spec.md. Atomic write, size-bounded (256 KiB), heading-required. Honors spec_writer.allow_spec_write.",
|
|
@@ -120481,14 +120931,14 @@ var spec_write = createSwarmTool({
|
|
|
120481
120931
|
reason: 'spec must contain at least one top-level "# Heading"'
|
|
120482
120932
|
}, null, 2);
|
|
120483
120933
|
}
|
|
120484
|
-
const target =
|
|
120485
|
-
await mkdir23(
|
|
120934
|
+
const target = path140.join(directory, ".swarm", "spec.md");
|
|
120935
|
+
await mkdir23(path140.dirname(target), { recursive: true });
|
|
120486
120936
|
const tmp = `${target}.tmp-${process.pid}-${Date.now()}`;
|
|
120487
120937
|
let finalContent = content;
|
|
120488
120938
|
if (mode === "append") {
|
|
120489
120939
|
try {
|
|
120490
|
-
const
|
|
120491
|
-
const prior = await
|
|
120940
|
+
const fs102 = await import("node:fs/promises");
|
|
120941
|
+
const prior = await fs102.readFile(target, "utf-8");
|
|
120492
120942
|
finalContent = `${prior.replace(/\s+$/, "")}
|
|
120493
120943
|
|
|
120494
120944
|
${content}
|
|
@@ -120517,7 +120967,7 @@ import {
|
|
|
120517
120967
|
unlinkSync as unlinkSync18,
|
|
120518
120968
|
writeFileSync as writeFileSync28
|
|
120519
120969
|
} from "node:fs";
|
|
120520
|
-
import
|
|
120970
|
+
import path141 from "node:path";
|
|
120521
120971
|
init_create_tool();
|
|
120522
120972
|
init_resolve_working_directory();
|
|
120523
120973
|
var VerdictSchema2 = exports_external.object({
|
|
@@ -120647,7 +121097,7 @@ var submit_phase_council_verdicts = createSwarmTool({
|
|
|
120647
121097
|
}
|
|
120648
121098
|
});
|
|
120649
121099
|
function getPhaseMutationGapFinding(phaseNumber, workingDir) {
|
|
120650
|
-
const mutationGatePath =
|
|
121100
|
+
const mutationGatePath = path141.join(workingDir, ".swarm", "evidence", String(phaseNumber), "mutation-gate.json");
|
|
120651
121101
|
try {
|
|
120652
121102
|
const raw = readFileSync63(mutationGatePath, "utf-8");
|
|
120653
121103
|
const parsed = JSON.parse(raw);
|
|
@@ -120709,9 +121159,9 @@ function getPhaseMutationGapFinding(phaseNumber, workingDir) {
|
|
|
120709
121159
|
}
|
|
120710
121160
|
}
|
|
120711
121161
|
function writePhaseCouncilEvidence(workingDir, synthesis) {
|
|
120712
|
-
const evidenceDir =
|
|
121162
|
+
const evidenceDir = path141.join(workingDir, ".swarm", "evidence", String(synthesis.phaseNumber));
|
|
120713
121163
|
mkdirSync35(evidenceDir, { recursive: true });
|
|
120714
|
-
const evidenceFile =
|
|
121164
|
+
const evidenceFile = path141.join(evidenceDir, "phase-council.json");
|
|
120715
121165
|
const evidenceBundle = {
|
|
120716
121166
|
entries: [
|
|
120717
121167
|
{
|
|
@@ -120933,7 +121383,7 @@ var swarm_memory_propose = createSwarmTool({
|
|
|
120933
121383
|
evidenceRefs: exports_external.array(exports_external.string().min(1).max(500)).max(20).optional().describe("Evidence refs such as files, commits, test outputs, or URLs")
|
|
120934
121384
|
},
|
|
120935
121385
|
execute: async (args2, directory, ctx) => {
|
|
120936
|
-
const { config: config3 } =
|
|
121386
|
+
const { config: config3 } = _internals60.loadPluginConfigWithMeta(directory);
|
|
120937
121387
|
if (config3.memory?.enabled !== true) {
|
|
120938
121388
|
return JSON.stringify({
|
|
120939
121389
|
success: false,
|
|
@@ -120949,7 +121399,7 @@ var swarm_memory_propose = createSwarmTool({
|
|
|
120949
121399
|
});
|
|
120950
121400
|
}
|
|
120951
121401
|
const agent = getContextAgent2(ctx);
|
|
120952
|
-
const gateway =
|
|
121402
|
+
const gateway = _internals60.createMemoryGateway({
|
|
120953
121403
|
directory,
|
|
120954
121404
|
sessionID: ctx?.sessionID,
|
|
120955
121405
|
agentRole: agent,
|
|
@@ -120974,7 +121424,7 @@ var swarm_memory_propose = createSwarmTool({
|
|
|
120974
121424
|
}
|
|
120975
121425
|
}
|
|
120976
121426
|
});
|
|
120977
|
-
var
|
|
121427
|
+
var _internals60 = {
|
|
120978
121428
|
loadPluginConfigWithMeta,
|
|
120979
121429
|
createMemoryGateway
|
|
120980
121430
|
};
|
|
@@ -121011,7 +121461,7 @@ var swarm_memory_recall = createSwarmTool({
|
|
|
121011
121461
|
maxItems: exports_external.number().int().min(1).max(20).optional().describe("Maximum memories to return")
|
|
121012
121462
|
},
|
|
121013
121463
|
execute: async (args2, directory, ctx) => {
|
|
121014
|
-
const { config: config3 } =
|
|
121464
|
+
const { config: config3 } = _internals61.loadPluginConfigWithMeta(directory);
|
|
121015
121465
|
if (config3.memory?.enabled !== true) {
|
|
121016
121466
|
return JSON.stringify({
|
|
121017
121467
|
success: false,
|
|
@@ -121027,7 +121477,7 @@ var swarm_memory_recall = createSwarmTool({
|
|
|
121027
121477
|
});
|
|
121028
121478
|
}
|
|
121029
121479
|
const agent = getContextAgent3(ctx);
|
|
121030
|
-
const gateway =
|
|
121480
|
+
const gateway = _internals61.createMemoryGateway({
|
|
121031
121481
|
directory,
|
|
121032
121482
|
sessionID: ctx?.sessionID,
|
|
121033
121483
|
agentRole: agent,
|
|
@@ -121060,7 +121510,7 @@ var RecallArgsSchema = exports_external.object({
|
|
|
121060
121510
|
kinds: exports_external.array(exports_external.enum(MEMORY_KINDS2)).optional(),
|
|
121061
121511
|
maxItems: exports_external.number().int().min(1).max(20).optional()
|
|
121062
121512
|
});
|
|
121063
|
-
var
|
|
121513
|
+
var _internals61 = {
|
|
121064
121514
|
loadPluginConfigWithMeta,
|
|
121065
121515
|
createMemoryGateway
|
|
121066
121516
|
};
|
|
@@ -121080,7 +121530,7 @@ init_schema3();
|
|
|
121080
121530
|
init_store();
|
|
121081
121531
|
init_create_tool();
|
|
121082
121532
|
init_resolve_working_directory();
|
|
121083
|
-
import * as
|
|
121533
|
+
import * as path142 from "node:path";
|
|
121084
121534
|
var FindingSchema2 = exports_external.object({
|
|
121085
121535
|
severity: exports_external.enum(["low", "medium", "high", "critical"]),
|
|
121086
121536
|
category: exports_external.string().min(1),
|
|
@@ -121144,7 +121594,7 @@ var write_architecture_supervisor_evidence = createSwarmTool({
|
|
|
121144
121594
|
if (config3.architectural_supervision?.persist_knowledge_recommendations && args2.knowledge_recommendations.length > 0) {
|
|
121145
121595
|
const knowledgeConfig = KnowledgeConfigSchema.parse(config3.knowledge ?? {});
|
|
121146
121596
|
const lessons = args2.knowledge_recommendations.map((r) => r.lesson);
|
|
121147
|
-
const result = await curateAndStoreSwarm(lessons,
|
|
121597
|
+
const result = await curateAndStoreSwarm(lessons, path142.basename(dirResult.directory), { phase_number: args2.phase }, dirResult.directory, knowledgeConfig, { skipAutoPromotion: true });
|
|
121148
121598
|
knowledgeProposed = result.stored;
|
|
121149
121599
|
}
|
|
121150
121600
|
} catch {}
|
|
@@ -121175,8 +121625,8 @@ var write_architecture_supervisor_evidence = createSwarmTool({
|
|
|
121175
121625
|
init_zod();
|
|
121176
121626
|
init_path_security();
|
|
121177
121627
|
init_create_tool();
|
|
121178
|
-
import * as
|
|
121179
|
-
import * as
|
|
121628
|
+
import * as fs102 from "node:fs";
|
|
121629
|
+
import * as path143 from "node:path";
|
|
121180
121630
|
var WINDOWS_RESERVED_NAMES4 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
|
|
121181
121631
|
function containsWindowsAttacks4(str) {
|
|
121182
121632
|
if (/:[^\\/]/.test(str))
|
|
@@ -121190,14 +121640,14 @@ function containsWindowsAttacks4(str) {
|
|
|
121190
121640
|
}
|
|
121191
121641
|
function isPathInWorkspace4(filePath, workspace) {
|
|
121192
121642
|
try {
|
|
121193
|
-
const resolvedPath =
|
|
121194
|
-
if (!
|
|
121643
|
+
const resolvedPath = path143.resolve(workspace, filePath);
|
|
121644
|
+
if (!fs102.existsSync(resolvedPath)) {
|
|
121195
121645
|
return true;
|
|
121196
121646
|
}
|
|
121197
|
-
const realWorkspace =
|
|
121198
|
-
const realResolvedPath =
|
|
121199
|
-
const relativePath =
|
|
121200
|
-
if (relativePath.startsWith("..") ||
|
|
121647
|
+
const realWorkspace = fs102.realpathSync(workspace);
|
|
121648
|
+
const realResolvedPath = fs102.realpathSync(resolvedPath);
|
|
121649
|
+
const relativePath = path143.relative(realWorkspace, realResolvedPath);
|
|
121650
|
+
if (relativePath.startsWith("..") || path143.isAbsolute(relativePath)) {
|
|
121201
121651
|
return false;
|
|
121202
121652
|
}
|
|
121203
121653
|
return true;
|
|
@@ -121369,7 +121819,7 @@ var suggestPatch = createSwarmTool({
|
|
|
121369
121819
|
message: "changes cannot be empty"
|
|
121370
121820
|
}, null, 2);
|
|
121371
121821
|
}
|
|
121372
|
-
if (!
|
|
121822
|
+
if (!fs102.existsSync(directory)) {
|
|
121373
121823
|
return JSON.stringify({
|
|
121374
121824
|
success: false,
|
|
121375
121825
|
error: true,
|
|
@@ -121405,8 +121855,8 @@ var suggestPatch = createSwarmTool({
|
|
|
121405
121855
|
});
|
|
121406
121856
|
continue;
|
|
121407
121857
|
}
|
|
121408
|
-
const fullPath =
|
|
121409
|
-
if (!
|
|
121858
|
+
const fullPath = path143.resolve(directory, change.file);
|
|
121859
|
+
if (!fs102.existsSync(fullPath)) {
|
|
121410
121860
|
errors5.push({
|
|
121411
121861
|
success: false,
|
|
121412
121862
|
error: true,
|
|
@@ -121420,7 +121870,7 @@ var suggestPatch = createSwarmTool({
|
|
|
121420
121870
|
}
|
|
121421
121871
|
let content;
|
|
121422
121872
|
try {
|
|
121423
|
-
content =
|
|
121873
|
+
content = fs102.readFileSync(fullPath, "utf-8");
|
|
121424
121874
|
} catch (err3) {
|
|
121425
121875
|
errors5.push({
|
|
121426
121876
|
success: false,
|
|
@@ -121708,12 +122158,12 @@ var lean_turbo_acquire_locks = createSwarmTool({
|
|
|
121708
122158
|
// src/tools/lean-turbo-plan-lanes.ts
|
|
121709
122159
|
init_zod();
|
|
121710
122160
|
init_constants();
|
|
121711
|
-
import * as
|
|
121712
|
-
import * as
|
|
122161
|
+
import * as fs104 from "node:fs";
|
|
122162
|
+
import * as path145 from "node:path";
|
|
121713
122163
|
|
|
121714
122164
|
// src/turbo/lean/conflicts.ts
|
|
121715
|
-
import * as
|
|
121716
|
-
import * as
|
|
122165
|
+
import * as fs103 from "node:fs";
|
|
122166
|
+
import * as path144 from "node:path";
|
|
121717
122167
|
var DEFAULT_GLOBAL_FILES = [
|
|
121718
122168
|
"package.json",
|
|
121719
122169
|
"package-lock.json",
|
|
@@ -121840,12 +122290,12 @@ function isProtectedPath2(normalizedPath) {
|
|
|
121840
122290
|
return false;
|
|
121841
122291
|
}
|
|
121842
122292
|
function readTaskScopes(directory, taskId) {
|
|
121843
|
-
const scopePath =
|
|
122293
|
+
const scopePath = path144.join(directory, ".swarm", "scopes", `scope-${taskId}.json`);
|
|
121844
122294
|
try {
|
|
121845
|
-
if (!
|
|
122295
|
+
if (!fs103.existsSync(scopePath)) {
|
|
121846
122296
|
return null;
|
|
121847
122297
|
}
|
|
121848
|
-
const raw =
|
|
122298
|
+
const raw = fs103.readFileSync(scopePath, "utf-8");
|
|
121849
122299
|
const parsed = JSON.parse(raw);
|
|
121850
122300
|
if (!parsed || !Array.isArray(parsed.files)) {
|
|
121851
122301
|
return null;
|
|
@@ -122228,12 +122678,12 @@ function createEmptyPlan(phaseNumber, planId) {
|
|
|
122228
122678
|
// src/tools/lean-turbo-plan-lanes.ts
|
|
122229
122679
|
init_create_tool();
|
|
122230
122680
|
function readPlanJson(directory) {
|
|
122231
|
-
const planPath =
|
|
122232
|
-
if (!
|
|
122681
|
+
const planPath = path145.join(directory, ".swarm", "plan.json");
|
|
122682
|
+
if (!fs104.existsSync(planPath)) {
|
|
122233
122683
|
return null;
|
|
122234
122684
|
}
|
|
122235
122685
|
try {
|
|
122236
|
-
return JSON.parse(
|
|
122686
|
+
return JSON.parse(fs104.readFileSync(planPath, "utf-8"));
|
|
122237
122687
|
} catch {
|
|
122238
122688
|
return null;
|
|
122239
122689
|
}
|
|
@@ -122282,8 +122732,8 @@ init_config();
|
|
|
122282
122732
|
|
|
122283
122733
|
// src/turbo/lean/reviewer.ts
|
|
122284
122734
|
init_state();
|
|
122285
|
-
import * as
|
|
122286
|
-
import * as
|
|
122735
|
+
import * as fs105 from "node:fs/promises";
|
|
122736
|
+
import * as path146 from "node:path";
|
|
122287
122737
|
init_state3();
|
|
122288
122738
|
var DEFAULT_CONFIG3 = {
|
|
122289
122739
|
reviewerAgent: "",
|
|
@@ -122305,7 +122755,7 @@ function resolveDefaultReviewerAgent(generatedAgentNames) {
|
|
|
122305
122755
|
}
|
|
122306
122756
|
async function compileReviewPackage(directory, phase, sessionID, requireDiffSummary) {
|
|
122307
122757
|
const lanes = await listLaneEvidence(directory, phase);
|
|
122308
|
-
const persisted =
|
|
122758
|
+
const persisted = _internals62.readPersisted?.(directory) ?? null;
|
|
122309
122759
|
if (persisted) {
|
|
122310
122760
|
let matchingRunState = null;
|
|
122311
122761
|
for (const sessionState of Object.values(persisted.sessions)) {
|
|
@@ -122399,9 +122849,9 @@ function parseReviewerVerdict(responseText) {
|
|
|
122399
122849
|
return { verdict, reason };
|
|
122400
122850
|
}
|
|
122401
122851
|
async function writeReviewerEvidence(directory, phase, verdict, reason) {
|
|
122402
|
-
const evidenceDir =
|
|
122403
|
-
await
|
|
122404
|
-
const evidencePath =
|
|
122852
|
+
const evidenceDir = path146.join(directory, ".swarm", "evidence", String(phase));
|
|
122853
|
+
await fs105.mkdir(evidenceDir, { recursive: true });
|
|
122854
|
+
const evidencePath = path146.join(evidenceDir, "lean-turbo-reviewer.json");
|
|
122405
122855
|
const content = JSON.stringify({
|
|
122406
122856
|
phase,
|
|
122407
122857
|
verdict,
|
|
@@ -122410,11 +122860,11 @@ async function writeReviewerEvidence(directory, phase, verdict, reason) {
|
|
|
122410
122860
|
}, null, 2);
|
|
122411
122861
|
const tempPath = `${evidencePath}.tmp.${process.pid}.${Date.now()}`;
|
|
122412
122862
|
try {
|
|
122413
|
-
await
|
|
122414
|
-
await
|
|
122863
|
+
await fs105.writeFile(tempPath, content, "utf-8");
|
|
122864
|
+
await fs105.rename(tempPath, evidencePath);
|
|
122415
122865
|
} catch (error93) {
|
|
122416
122866
|
try {
|
|
122417
|
-
await
|
|
122867
|
+
await fs105.unlink(tempPath);
|
|
122418
122868
|
} catch {}
|
|
122419
122869
|
throw error93;
|
|
122420
122870
|
}
|
|
@@ -122497,7 +122947,7 @@ Be specific and evidence-based. Do not approve a phase with unresolved degraded
|
|
|
122497
122947
|
client.session.delete({ path: { id: sessionId } }).catch(() => {});
|
|
122498
122948
|
}
|
|
122499
122949
|
}
|
|
122500
|
-
var
|
|
122950
|
+
var _internals62 = {
|
|
122501
122951
|
compileReviewPackage,
|
|
122502
122952
|
parseReviewerVerdict,
|
|
122503
122953
|
writeReviewerEvidence,
|
|
@@ -122514,28 +122964,28 @@ async function dispatchPhaseReviewer(directory, phase, sessionID, config3) {
|
|
|
122514
122964
|
};
|
|
122515
122965
|
const generatedAgentNames = swarmState.generatedAgentNames;
|
|
122516
122966
|
const agentName = mergedConfig.reviewerAgent || resolveDefaultReviewerAgent(generatedAgentNames);
|
|
122517
|
-
const pkg = await
|
|
122967
|
+
const pkg = await _internals62.compileReviewPackage(directory, phase, sessionID, mergedConfig.requireDiffSummary);
|
|
122518
122968
|
let responseText;
|
|
122519
122969
|
try {
|
|
122520
|
-
responseText = await
|
|
122970
|
+
responseText = await _internals62.dispatchReviewerAgent(directory, pkg, agentName, mergedConfig.timeoutMs);
|
|
122521
122971
|
} catch (error93) {
|
|
122522
|
-
const evidencePath2 = await
|
|
122972
|
+
const evidencePath2 = await _internals62.writeReviewerEvidence(directory, phase, "REJECTED", error93 instanceof Error ? error93.message : String(error93));
|
|
122523
122973
|
return {
|
|
122524
122974
|
verdict: "REJECTED",
|
|
122525
122975
|
reason: `Reviewer dispatch failed: ${error93 instanceof Error ? error93.message : String(error93)}`,
|
|
122526
122976
|
evidencePath: evidencePath2
|
|
122527
122977
|
};
|
|
122528
122978
|
}
|
|
122529
|
-
const parsed =
|
|
122979
|
+
const parsed = _internals62.parseReviewerVerdict(responseText);
|
|
122530
122980
|
if (!parsed) {
|
|
122531
|
-
const evidencePath2 = await
|
|
122981
|
+
const evidencePath2 = await _internals62.writeReviewerEvidence(directory, phase, "REJECTED", "Reviewer response could not be parsed");
|
|
122532
122982
|
return {
|
|
122533
122983
|
verdict: "REJECTED",
|
|
122534
122984
|
reason: "Reviewer response could not be parsed",
|
|
122535
122985
|
evidencePath: evidencePath2
|
|
122536
122986
|
};
|
|
122537
122987
|
}
|
|
122538
|
-
const evidencePath = await
|
|
122988
|
+
const evidencePath = await _internals62.writeReviewerEvidence(directory, phase, parsed.verdict, parsed.reason);
|
|
122539
122989
|
return {
|
|
122540
122990
|
verdict: parsed.verdict,
|
|
122541
122991
|
reason: parsed.reason,
|
|
@@ -123041,7 +123491,7 @@ ${fileList}
|
|
|
123041
123491
|
|
|
123042
123492
|
// src/tools/lean-turbo-run-phase.ts
|
|
123043
123493
|
init_create_tool();
|
|
123044
|
-
var
|
|
123494
|
+
var _internals63 = {
|
|
123045
123495
|
LeanTurboRunner,
|
|
123046
123496
|
loadPluginConfigWithMeta
|
|
123047
123497
|
};
|
|
@@ -123051,9 +123501,9 @@ async function executeLeanTurboRunPhase(args2) {
|
|
|
123051
123501
|
let runError = null;
|
|
123052
123502
|
let runner = null;
|
|
123053
123503
|
try {
|
|
123054
|
-
const { config: config3 } =
|
|
123504
|
+
const { config: config3 } = _internals63.loadPluginConfigWithMeta(directory);
|
|
123055
123505
|
const leanConfig = config3.turbo?.strategy === "lean" ? config3.turbo.lean : undefined;
|
|
123056
|
-
runner = new
|
|
123506
|
+
runner = new _internals63.LeanTurboRunner({
|
|
123057
123507
|
directory,
|
|
123058
123508
|
sessionID,
|
|
123059
123509
|
opencodeClient: swarmState.opencodeClient ?? null,
|
|
@@ -123205,8 +123655,8 @@ var lean_turbo_status = createSwarmTool({
|
|
|
123205
123655
|
// src/tools/lint-spec.ts
|
|
123206
123656
|
init_spec_schema();
|
|
123207
123657
|
init_create_tool();
|
|
123208
|
-
import * as
|
|
123209
|
-
import * as
|
|
123658
|
+
import * as fs106 from "node:fs";
|
|
123659
|
+
import * as path147 from "node:path";
|
|
123210
123660
|
var SPEC_FILE_NAME = "spec.md";
|
|
123211
123661
|
var SWARM_DIR2 = ".swarm";
|
|
123212
123662
|
var OBLIGATION_KEYWORDS2 = ["MUST", "SHALL", "SHOULD", "MAY"];
|
|
@@ -123259,8 +123709,8 @@ var lint_spec = createSwarmTool({
|
|
|
123259
123709
|
async execute(_args, directory) {
|
|
123260
123710
|
const errors5 = [];
|
|
123261
123711
|
const warnings = [];
|
|
123262
|
-
const specPath =
|
|
123263
|
-
if (!
|
|
123712
|
+
const specPath = path147.join(directory, SWARM_DIR2, SPEC_FILE_NAME);
|
|
123713
|
+
if (!fs106.existsSync(specPath)) {
|
|
123264
123714
|
const result2 = {
|
|
123265
123715
|
valid: false,
|
|
123266
123716
|
specMtime: null,
|
|
@@ -123279,12 +123729,12 @@ var lint_spec = createSwarmTool({
|
|
|
123279
123729
|
}
|
|
123280
123730
|
let specMtime = null;
|
|
123281
123731
|
try {
|
|
123282
|
-
const stats =
|
|
123732
|
+
const stats = fs106.statSync(specPath);
|
|
123283
123733
|
specMtime = stats.mtime.toISOString();
|
|
123284
123734
|
} catch {}
|
|
123285
123735
|
let content;
|
|
123286
123736
|
try {
|
|
123287
|
-
content =
|
|
123737
|
+
content = fs106.readFileSync(specPath, "utf-8");
|
|
123288
123738
|
} catch (e) {
|
|
123289
123739
|
const result2 = {
|
|
123290
123740
|
valid: false,
|
|
@@ -123329,13 +123779,13 @@ var lint_spec = createSwarmTool({
|
|
|
123329
123779
|
});
|
|
123330
123780
|
// src/tools/mutation-test.ts
|
|
123331
123781
|
init_zod();
|
|
123332
|
-
import * as
|
|
123333
|
-
import * as
|
|
123782
|
+
import * as fs107 from "node:fs";
|
|
123783
|
+
import * as path149 from "node:path";
|
|
123334
123784
|
|
|
123335
123785
|
// src/mutation/engine.ts
|
|
123336
123786
|
import { spawnSync as spawnSync8 } from "node:child_process";
|
|
123337
123787
|
import { unlinkSync as unlinkSync19, writeFileSync as writeFileSync29 } from "node:fs";
|
|
123338
|
-
import * as
|
|
123788
|
+
import * as path148 from "node:path";
|
|
123339
123789
|
|
|
123340
123790
|
// src/mutation/equivalence.ts
|
|
123341
123791
|
function isStaticallyEquivalent(originalCode, mutatedCode) {
|
|
@@ -123407,7 +123857,7 @@ function isStaticallyEquivalent(originalCode, mutatedCode) {
|
|
|
123407
123857
|
const strippedMutated = stripCode(mutatedCode);
|
|
123408
123858
|
return strippedOriginal === strippedMutated;
|
|
123409
123859
|
}
|
|
123410
|
-
var
|
|
123860
|
+
var _internals64 = {
|
|
123411
123861
|
isStaticallyEquivalent,
|
|
123412
123862
|
checkEquivalence,
|
|
123413
123863
|
batchCheckEquivalence
|
|
@@ -123447,7 +123897,7 @@ async function batchCheckEquivalence(patches, llmJudge) {
|
|
|
123447
123897
|
const results = [];
|
|
123448
123898
|
for (const { patch, originalCode, mutatedCode } of patches) {
|
|
123449
123899
|
try {
|
|
123450
|
-
const result = await
|
|
123900
|
+
const result = await _internals64.checkEquivalence(patch, originalCode, mutatedCode, llmJudge);
|
|
123451
123901
|
results.push(result);
|
|
123452
123902
|
} catch (err3) {
|
|
123453
123903
|
results.push({
|
|
@@ -123466,7 +123916,7 @@ async function batchCheckEquivalence(patches, llmJudge) {
|
|
|
123466
123916
|
var MUTATION_TIMEOUT_MS = 30000;
|
|
123467
123917
|
var TOTAL_BUDGET_MS = 300000;
|
|
123468
123918
|
var GIT_APPLY_TIMEOUT_MS = 5000;
|
|
123469
|
-
var
|
|
123919
|
+
var _internals65 = {
|
|
123470
123920
|
executeMutation,
|
|
123471
123921
|
computeReport,
|
|
123472
123922
|
executeMutationSuite,
|
|
@@ -123481,7 +123931,7 @@ async function executeMutation(patch, testCommand, _testFiles, workingDir) {
|
|
|
123481
123931
|
let patchFile;
|
|
123482
123932
|
try {
|
|
123483
123933
|
const safeId2 = patch.id.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
123484
|
-
patchFile =
|
|
123934
|
+
patchFile = path148.join(workingDir, `.mutation_patch_${safeId2}.diff`);
|
|
123485
123935
|
try {
|
|
123486
123936
|
writeFileSync29(patchFile, patch.patch);
|
|
123487
123937
|
} catch (writeErr) {
|
|
@@ -123498,7 +123948,7 @@ async function executeMutation(patch, testCommand, _testFiles, workingDir) {
|
|
|
123498
123948
|
};
|
|
123499
123949
|
}
|
|
123500
123950
|
try {
|
|
123501
|
-
const applyResult =
|
|
123951
|
+
const applyResult = _internals65.spawnSync("git", ["apply", "--", patchFile], {
|
|
123502
123952
|
cwd: workingDir,
|
|
123503
123953
|
timeout: GIT_APPLY_TIMEOUT_MS,
|
|
123504
123954
|
stdio: "pipe"
|
|
@@ -123527,7 +123977,7 @@ async function executeMutation(patch, testCommand, _testFiles, workingDir) {
|
|
|
123527
123977
|
}
|
|
123528
123978
|
let testPassed = false;
|
|
123529
123979
|
try {
|
|
123530
|
-
const spawnResult =
|
|
123980
|
+
const spawnResult = _internals65.spawnSync(testCommand[0], testCommand.slice(1), {
|
|
123531
123981
|
cwd: workingDir,
|
|
123532
123982
|
timeout: MUTATION_TIMEOUT_MS,
|
|
123533
123983
|
stdio: "pipe"
|
|
@@ -123560,7 +124010,7 @@ async function executeMutation(patch, testCommand, _testFiles, workingDir) {
|
|
|
123560
124010
|
} finally {
|
|
123561
124011
|
if (patchFile) {
|
|
123562
124012
|
try {
|
|
123563
|
-
const revertResult =
|
|
124013
|
+
const revertResult = _internals65.spawnSync("git", ["apply", "-R", "--", patchFile], {
|
|
123564
124014
|
cwd: workingDir,
|
|
123565
124015
|
timeout: GIT_APPLY_TIMEOUT_MS,
|
|
123566
124016
|
stdio: "pipe"
|
|
@@ -123753,7 +124203,7 @@ async function executeMutationSuite(patches, testCommand, testFiles, workingDir,
|
|
|
123753
124203
|
}
|
|
123754
124204
|
|
|
123755
124205
|
// src/mutation/gate.ts
|
|
123756
|
-
var
|
|
124206
|
+
var _internals66 = {
|
|
123757
124207
|
evaluateMutationGate,
|
|
123758
124208
|
buildTestImprovementPrompt,
|
|
123759
124209
|
buildMessage
|
|
@@ -123774,8 +124224,8 @@ function evaluateMutationGate(report, passThreshold = PASS_THRESHOLD, warnThresh
|
|
|
123774
124224
|
} else {
|
|
123775
124225
|
verdict = "fail";
|
|
123776
124226
|
}
|
|
123777
|
-
const testImprovementPrompt =
|
|
123778
|
-
const message =
|
|
124227
|
+
const testImprovementPrompt = _internals66.buildTestImprovementPrompt(report, passThreshold, verdict);
|
|
124228
|
+
const message = _internals66.buildMessage(verdict, adjustedKillRate, report.killed, report.totalMutants, report.equivalent, warnThreshold);
|
|
123779
124229
|
return {
|
|
123780
124230
|
verdict,
|
|
123781
124231
|
killRate: report.killRate,
|
|
@@ -123885,8 +124335,8 @@ var mutation_test = createSwarmTool({
|
|
|
123885
124335
|
];
|
|
123886
124336
|
for (const filePath of uniquePaths) {
|
|
123887
124337
|
try {
|
|
123888
|
-
const resolvedPath =
|
|
123889
|
-
sourceFiles.set(filePath,
|
|
124338
|
+
const resolvedPath = path149.resolve(cwd, filePath);
|
|
124339
|
+
sourceFiles.set(filePath, fs107.readFileSync(resolvedPath, "utf-8"));
|
|
123890
124340
|
} catch {}
|
|
123891
124341
|
}
|
|
123892
124342
|
const report = await executeMutationSuite(typedArgs.patches, typedArgs.test_command, typedArgs.files, cwd, undefined, undefined, sourceFiles.size > 0 ? sourceFiles : undefined);
|
|
@@ -123904,8 +124354,8 @@ var mutation_test = createSwarmTool({
|
|
|
123904
124354
|
init_zod();
|
|
123905
124355
|
init_manager2();
|
|
123906
124356
|
init_detector();
|
|
123907
|
-
import * as
|
|
123908
|
-
import * as
|
|
124357
|
+
import * as fs108 from "node:fs";
|
|
124358
|
+
import * as path150 from "node:path";
|
|
123909
124359
|
init_create_tool();
|
|
123910
124360
|
var MAX_FILE_SIZE2 = 2 * 1024 * 1024;
|
|
123911
124361
|
var BINARY_CHECK_BYTES = 8192;
|
|
@@ -123971,7 +124421,7 @@ async function syntaxCheck(input, directory, config3) {
|
|
|
123971
124421
|
if (languages?.length) {
|
|
123972
124422
|
const lowerLangs = languages.map((l) => l.toLowerCase());
|
|
123973
124423
|
filesToCheck = filesToCheck.filter((file3) => {
|
|
123974
|
-
const ext =
|
|
124424
|
+
const ext = path150.extname(file3.path).toLowerCase();
|
|
123975
124425
|
const langDef = getLanguageForExtension(ext);
|
|
123976
124426
|
const fileProfile = getProfileForFile(file3.path);
|
|
123977
124427
|
const langId = fileProfile?.id || langDef?.id;
|
|
@@ -123984,7 +124434,7 @@ async function syntaxCheck(input, directory, config3) {
|
|
|
123984
124434
|
let skippedCount = 0;
|
|
123985
124435
|
for (const fileInfo of filesToCheck) {
|
|
123986
124436
|
const { path: filePath } = fileInfo;
|
|
123987
|
-
const fullPath =
|
|
124437
|
+
const fullPath = path150.isAbsolute(filePath) ? filePath : path150.join(directory, filePath);
|
|
123988
124438
|
const result = {
|
|
123989
124439
|
path: filePath,
|
|
123990
124440
|
language: "",
|
|
@@ -124014,7 +124464,7 @@ async function syntaxCheck(input, directory, config3) {
|
|
|
124014
124464
|
}
|
|
124015
124465
|
let content;
|
|
124016
124466
|
try {
|
|
124017
|
-
content =
|
|
124467
|
+
content = fs108.readFileSync(fullPath, "utf8");
|
|
124018
124468
|
} catch {
|
|
124019
124469
|
result.skipped_reason = "file_read_error";
|
|
124020
124470
|
skippedCount++;
|
|
@@ -124033,7 +124483,7 @@ async function syntaxCheck(input, directory, config3) {
|
|
|
124033
124483
|
results.push(result);
|
|
124034
124484
|
continue;
|
|
124035
124485
|
}
|
|
124036
|
-
const ext =
|
|
124486
|
+
const ext = path150.extname(filePath).toLowerCase();
|
|
124037
124487
|
const langDef = getLanguageForExtension(ext);
|
|
124038
124488
|
result.language = profile?.id || langDef?.id || "unknown";
|
|
124039
124489
|
const errors5 = extractSyntaxErrors(parser, content);
|
|
@@ -124130,8 +124580,8 @@ init_zod();
|
|
|
124130
124580
|
init_utils();
|
|
124131
124581
|
init_create_tool();
|
|
124132
124582
|
init_path_security();
|
|
124133
|
-
import * as
|
|
124134
|
-
import * as
|
|
124583
|
+
import * as fs109 from "node:fs";
|
|
124584
|
+
import * as path151 from "node:path";
|
|
124135
124585
|
var MAX_TEXT_LENGTH = 200;
|
|
124136
124586
|
var MAX_FILE_SIZE_BYTES11 = 1024 * 1024;
|
|
124137
124587
|
var SUPPORTED_EXTENSIONS4 = new Set([
|
|
@@ -124197,9 +124647,9 @@ function validatePathsInput(paths, cwd) {
|
|
|
124197
124647
|
return { error: "paths contains path traversal", resolvedPath: null };
|
|
124198
124648
|
}
|
|
124199
124649
|
try {
|
|
124200
|
-
const resolvedPath =
|
|
124201
|
-
const normalizedCwd =
|
|
124202
|
-
const normalizedResolved =
|
|
124650
|
+
const resolvedPath = path151.resolve(paths);
|
|
124651
|
+
const normalizedCwd = path151.resolve(cwd);
|
|
124652
|
+
const normalizedResolved = path151.resolve(resolvedPath);
|
|
124203
124653
|
if (!normalizedResolved.startsWith(normalizedCwd)) {
|
|
124204
124654
|
return {
|
|
124205
124655
|
error: "paths must be within the current working directory",
|
|
@@ -124215,13 +124665,13 @@ function validatePathsInput(paths, cwd) {
|
|
|
124215
124665
|
}
|
|
124216
124666
|
}
|
|
124217
124667
|
function isSupportedExtension(filePath) {
|
|
124218
|
-
const ext =
|
|
124668
|
+
const ext = path151.extname(filePath).toLowerCase();
|
|
124219
124669
|
return SUPPORTED_EXTENSIONS4.has(ext);
|
|
124220
124670
|
}
|
|
124221
124671
|
function findSourceFiles3(dir, files = []) {
|
|
124222
124672
|
let entries;
|
|
124223
124673
|
try {
|
|
124224
|
-
entries =
|
|
124674
|
+
entries = fs109.readdirSync(dir);
|
|
124225
124675
|
} catch {
|
|
124226
124676
|
return files;
|
|
124227
124677
|
}
|
|
@@ -124230,10 +124680,10 @@ function findSourceFiles3(dir, files = []) {
|
|
|
124230
124680
|
if (SKIP_DIRECTORIES5.has(entry)) {
|
|
124231
124681
|
continue;
|
|
124232
124682
|
}
|
|
124233
|
-
const fullPath =
|
|
124683
|
+
const fullPath = path151.join(dir, entry);
|
|
124234
124684
|
let stat9;
|
|
124235
124685
|
try {
|
|
124236
|
-
stat9 =
|
|
124686
|
+
stat9 = fs109.statSync(fullPath);
|
|
124237
124687
|
} catch {
|
|
124238
124688
|
continue;
|
|
124239
124689
|
}
|
|
@@ -124326,7 +124776,7 @@ var todo_extract = createSwarmTool({
|
|
|
124326
124776
|
return JSON.stringify(errorResult, null, 2);
|
|
124327
124777
|
}
|
|
124328
124778
|
const scanPath = resolvedPath;
|
|
124329
|
-
if (!
|
|
124779
|
+
if (!fs109.existsSync(scanPath)) {
|
|
124330
124780
|
const errorResult = {
|
|
124331
124781
|
error: `path not found: ${pathsInput}`,
|
|
124332
124782
|
total: 0,
|
|
@@ -124336,13 +124786,13 @@ var todo_extract = createSwarmTool({
|
|
|
124336
124786
|
return JSON.stringify(errorResult, null, 2);
|
|
124337
124787
|
}
|
|
124338
124788
|
const filesToScan = [];
|
|
124339
|
-
const stat9 =
|
|
124789
|
+
const stat9 = fs109.statSync(scanPath);
|
|
124340
124790
|
if (stat9.isFile()) {
|
|
124341
124791
|
if (isSupportedExtension(scanPath)) {
|
|
124342
124792
|
filesToScan.push(scanPath);
|
|
124343
124793
|
} else {
|
|
124344
124794
|
const errorResult = {
|
|
124345
|
-
error: `unsupported file extension: ${
|
|
124795
|
+
error: `unsupported file extension: ${path151.extname(scanPath)}`,
|
|
124346
124796
|
total: 0,
|
|
124347
124797
|
byPriority: { high: 0, medium: 0, low: 0 },
|
|
124348
124798
|
entries: []
|
|
@@ -124355,11 +124805,11 @@ var todo_extract = createSwarmTool({
|
|
|
124355
124805
|
const allEntries = [];
|
|
124356
124806
|
for (const filePath of filesToScan) {
|
|
124357
124807
|
try {
|
|
124358
|
-
const fileStat =
|
|
124808
|
+
const fileStat = fs109.statSync(filePath);
|
|
124359
124809
|
if (fileStat.size > MAX_FILE_SIZE_BYTES11) {
|
|
124360
124810
|
continue;
|
|
124361
124811
|
}
|
|
124362
|
-
const content =
|
|
124812
|
+
const content = fs109.readFileSync(filePath, "utf-8");
|
|
124363
124813
|
const entries = parseTodoComments(content, filePath, tagsSet);
|
|
124364
124814
|
allEntries.push(...entries);
|
|
124365
124815
|
} catch {}
|
|
@@ -124390,19 +124840,19 @@ init_loader();
|
|
|
124390
124840
|
init_schema();
|
|
124391
124841
|
init_qa_gate_profile();
|
|
124392
124842
|
init_gate_evidence();
|
|
124393
|
-
import * as
|
|
124394
|
-
import * as
|
|
124843
|
+
import * as fs113 from "node:fs";
|
|
124844
|
+
import * as path155 from "node:path";
|
|
124395
124845
|
|
|
124396
124846
|
// src/hooks/diff-scope.ts
|
|
124397
124847
|
init_bun_compat();
|
|
124398
|
-
import * as
|
|
124399
|
-
import * as
|
|
124848
|
+
import * as fs111 from "node:fs";
|
|
124849
|
+
import * as path153 from "node:path";
|
|
124400
124850
|
|
|
124401
124851
|
// src/utils/gitignore-warning.ts
|
|
124402
124852
|
init_bun_compat();
|
|
124403
|
-
import * as
|
|
124404
|
-
import * as
|
|
124405
|
-
var
|
|
124853
|
+
import * as fs110 from "node:fs";
|
|
124854
|
+
import * as path152 from "node:path";
|
|
124855
|
+
var _internals67 = { bunSpawn };
|
|
124406
124856
|
var _swarmGitExcludedChecked = false;
|
|
124407
124857
|
function fileCoversSwarm(content) {
|
|
124408
124858
|
for (const rawLine of content.split(`
|
|
@@ -124435,7 +124885,7 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
|
|
|
124435
124885
|
checkIgnoreExitCode
|
|
124436
124886
|
] = await Promise.all([
|
|
124437
124887
|
(async () => {
|
|
124438
|
-
const proc =
|
|
124888
|
+
const proc = _internals67.bunSpawn(["git", "-C", directory, "rev-parse", "--show-toplevel"], GIT_SPAWN_OPTIONS);
|
|
124439
124889
|
try {
|
|
124440
124890
|
return await Promise.all([proc.exited, proc.stdout.text()]);
|
|
124441
124891
|
} finally {
|
|
@@ -124445,7 +124895,7 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
|
|
|
124445
124895
|
}
|
|
124446
124896
|
})(),
|
|
124447
124897
|
(async () => {
|
|
124448
|
-
const proc =
|
|
124898
|
+
const proc = _internals67.bunSpawn(["git", "-C", directory, "rev-parse", "--git-path", "info/exclude"], GIT_SPAWN_OPTIONS);
|
|
124449
124899
|
try {
|
|
124450
124900
|
return await Promise.all([proc.exited, proc.stdout.text()]);
|
|
124451
124901
|
} finally {
|
|
@@ -124455,7 +124905,7 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
|
|
|
124455
124905
|
}
|
|
124456
124906
|
})(),
|
|
124457
124907
|
(async () => {
|
|
124458
|
-
const proc =
|
|
124908
|
+
const proc = _internals67.bunSpawn(["git", "-C", directory, "check-ignore", "-q", ".swarm/.gitkeep"], GIT_SPAWN_OPTIONS);
|
|
124459
124909
|
try {
|
|
124460
124910
|
return await proc.exited;
|
|
124461
124911
|
} finally {
|
|
@@ -124475,16 +124925,16 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
|
|
|
124475
124925
|
const excludeRelPath = excludePathRaw.trim();
|
|
124476
124926
|
if (!excludeRelPath)
|
|
124477
124927
|
return;
|
|
124478
|
-
const excludePath =
|
|
124928
|
+
const excludePath = path152.isAbsolute(excludeRelPath) ? excludeRelPath : path152.join(directory, excludeRelPath);
|
|
124479
124929
|
if (checkIgnoreExitCode !== 0) {
|
|
124480
124930
|
try {
|
|
124481
|
-
|
|
124931
|
+
fs110.mkdirSync(path152.dirname(excludePath), { recursive: true });
|
|
124482
124932
|
let existing = "";
|
|
124483
124933
|
try {
|
|
124484
|
-
existing =
|
|
124934
|
+
existing = fs110.readFileSync(excludePath, "utf8");
|
|
124485
124935
|
} catch {}
|
|
124486
124936
|
if (!fileCoversSwarm(existing)) {
|
|
124487
|
-
|
|
124937
|
+
fs110.appendFileSync(excludePath, `
|
|
124488
124938
|
# opencode-swarm local runtime state
|
|
124489
124939
|
.swarm/
|
|
124490
124940
|
`, "utf8");
|
|
@@ -124494,7 +124944,7 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
|
|
|
124494
124944
|
}
|
|
124495
124945
|
} catch {}
|
|
124496
124946
|
}
|
|
124497
|
-
const trackedProc =
|
|
124947
|
+
const trackedProc = _internals67.bunSpawn(["git", "-C", directory, "ls-files", "--", ".swarm"], GIT_SPAWN_OPTIONS);
|
|
124498
124948
|
let trackedExitCode;
|
|
124499
124949
|
let trackedOutput;
|
|
124500
124950
|
try {
|
|
@@ -124519,13 +124969,13 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
|
|
|
124519
124969
|
}
|
|
124520
124970
|
|
|
124521
124971
|
// src/hooks/diff-scope.ts
|
|
124522
|
-
var
|
|
124972
|
+
var _internals68 = { bunSpawn };
|
|
124523
124973
|
function getDeclaredScope(taskId, directory) {
|
|
124524
124974
|
try {
|
|
124525
|
-
const planPath =
|
|
124526
|
-
if (!
|
|
124975
|
+
const planPath = path153.join(directory, ".swarm", "plan.json");
|
|
124976
|
+
if (!fs111.existsSync(planPath))
|
|
124527
124977
|
return null;
|
|
124528
|
-
const raw =
|
|
124978
|
+
const raw = fs111.readFileSync(planPath, "utf-8");
|
|
124529
124979
|
const plan = JSON.parse(raw);
|
|
124530
124980
|
for (const phase of plan.phases ?? []) {
|
|
124531
124981
|
for (const task of phase.tasks ?? []) {
|
|
@@ -124554,7 +125004,7 @@ var GIT_DIFF_SPAWN_OPTIONS = {
|
|
|
124554
125004
|
};
|
|
124555
125005
|
async function getChangedFiles(directory) {
|
|
124556
125006
|
try {
|
|
124557
|
-
const proc =
|
|
125007
|
+
const proc = _internals68.bunSpawn(["git", "diff", "--name-only", "HEAD~1"], {
|
|
124558
125008
|
cwd: directory,
|
|
124559
125009
|
...GIT_DIFF_SPAWN_OPTIONS
|
|
124560
125010
|
});
|
|
@@ -124571,7 +125021,7 @@ async function getChangedFiles(directory) {
|
|
|
124571
125021
|
return stdout.trim().split(`
|
|
124572
125022
|
`).map((f) => f.trim()).filter((f) => f.length > 0);
|
|
124573
125023
|
}
|
|
124574
|
-
const proc2 =
|
|
125024
|
+
const proc2 = _internals68.bunSpawn(["git", "diff", "--name-only", "HEAD"], {
|
|
124575
125025
|
cwd: directory,
|
|
124576
125026
|
...GIT_DIFF_SPAWN_OPTIONS
|
|
124577
125027
|
});
|
|
@@ -124627,9 +125077,9 @@ init_telemetry();
|
|
|
124627
125077
|
|
|
124628
125078
|
// src/turbo/lean/task-completion.ts
|
|
124629
125079
|
init_file_locks();
|
|
124630
|
-
import * as
|
|
124631
|
-
import * as
|
|
124632
|
-
var
|
|
125080
|
+
import * as fs112 from "node:fs";
|
|
125081
|
+
import * as path154 from "node:path";
|
|
125082
|
+
var _internals69 = {
|
|
124633
125083
|
listActiveLocks,
|
|
124634
125084
|
verifyLeanTurboTaskCompletion
|
|
124635
125085
|
};
|
|
@@ -124647,7 +125097,7 @@ var TIER_3_PATTERNS = [
|
|
|
124647
125097
|
];
|
|
124648
125098
|
function matchesTier3Pattern(files) {
|
|
124649
125099
|
for (const file3 of files) {
|
|
124650
|
-
const fileName =
|
|
125100
|
+
const fileName = path154.basename(file3);
|
|
124651
125101
|
for (const pattern of TIER_3_PATTERNS) {
|
|
124652
125102
|
if (pattern.test(fileName)) {
|
|
124653
125103
|
return true;
|
|
@@ -124659,14 +125109,14 @@ function matchesTier3Pattern(files) {
|
|
|
124659
125109
|
function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
|
|
124660
125110
|
let persisted = null;
|
|
124661
125111
|
try {
|
|
124662
|
-
const statePath =
|
|
124663
|
-
if (!
|
|
125112
|
+
const statePath = path154.join(directory, ".swarm", "turbo-state.json");
|
|
125113
|
+
if (!fs112.existsSync(statePath)) {
|
|
124664
125114
|
return {
|
|
124665
125115
|
ok: false,
|
|
124666
125116
|
reason: "Lean Turbo state file not found"
|
|
124667
125117
|
};
|
|
124668
125118
|
}
|
|
124669
|
-
const raw =
|
|
125119
|
+
const raw = fs112.readFileSync(statePath, "utf-8");
|
|
124670
125120
|
persisted = JSON.parse(raw);
|
|
124671
125121
|
} catch {
|
|
124672
125122
|
return {
|
|
@@ -124743,11 +125193,11 @@ function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
|
|
|
124743
125193
|
};
|
|
124744
125194
|
}
|
|
124745
125195
|
const phase = runState.phase ?? 0;
|
|
124746
|
-
const evidencePath =
|
|
124747
|
-
const expectedDir =
|
|
124748
|
-
const resolvedPath =
|
|
124749
|
-
const resolvedDir =
|
|
124750
|
-
if (!resolvedPath.startsWith(resolvedDir +
|
|
125196
|
+
const evidencePath = path154.join(directory, ".swarm", "evidence", String(phase), "lean-turbo", `${lane.laneId}.json`);
|
|
125197
|
+
const expectedDir = path154.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
|
|
125198
|
+
const resolvedPath = path154.resolve(evidencePath);
|
|
125199
|
+
const resolvedDir = path154.resolve(expectedDir);
|
|
125200
|
+
if (!resolvedPath.startsWith(resolvedDir + path154.sep) && resolvedPath !== resolvedDir) {
|
|
124751
125201
|
return {
|
|
124752
125202
|
ok: false,
|
|
124753
125203
|
reason: `Lane ID causes path traversal: ${lane.laneId}`,
|
|
@@ -124759,7 +125209,7 @@ function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
|
|
|
124759
125209
|
}
|
|
124760
125210
|
};
|
|
124761
125211
|
}
|
|
124762
|
-
if (!
|
|
125212
|
+
if (!fs112.existsSync(evidencePath)) {
|
|
124763
125213
|
return {
|
|
124764
125214
|
ok: false,
|
|
124765
125215
|
reason: `Lane ${lane.laneId} evidence file not found: ${evidencePath}`,
|
|
@@ -124771,7 +125221,7 @@ function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
|
|
|
124771
125221
|
}
|
|
124772
125222
|
};
|
|
124773
125223
|
}
|
|
124774
|
-
const activeLocks =
|
|
125224
|
+
const activeLocks = _internals69.listActiveLocks(directory);
|
|
124775
125225
|
const laneLocks = activeLocks.filter((lock) => lock.laneId === lane.laneId);
|
|
124776
125226
|
if (laneLocks.length > 0) {
|
|
124777
125227
|
return {
|
|
@@ -124787,8 +125237,8 @@ function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
|
|
|
124787
125237
|
}
|
|
124788
125238
|
let filesTouched = [];
|
|
124789
125239
|
try {
|
|
124790
|
-
const planPath =
|
|
124791
|
-
const planRaw =
|
|
125240
|
+
const planPath = path154.join(directory, ".swarm", "plan.json");
|
|
125241
|
+
const planRaw = fs112.readFileSync(planPath, "utf-8");
|
|
124792
125242
|
const plan = JSON.parse(planRaw);
|
|
124793
125243
|
for (const planPhase of plan.phases ?? []) {
|
|
124794
125244
|
for (const task of planPhase.tasks ?? []) {
|
|
@@ -124871,7 +125321,7 @@ var TIER_3_PATTERNS2 = [
|
|
|
124871
125321
|
];
|
|
124872
125322
|
function matchesTier3Pattern2(files) {
|
|
124873
125323
|
for (const file3 of files) {
|
|
124874
|
-
const fileName =
|
|
125324
|
+
const fileName = path155.basename(file3);
|
|
124875
125325
|
for (const pattern of TIER_3_PATTERNS2) {
|
|
124876
125326
|
if (pattern.test(fileName)) {
|
|
124877
125327
|
return true;
|
|
@@ -124910,8 +125360,8 @@ function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = fal
|
|
|
124910
125360
|
if (!skipStandardTurboBypass && hasActiveTurboMode()) {
|
|
124911
125361
|
const resolvedDir2 = workingDirectory;
|
|
124912
125362
|
try {
|
|
124913
|
-
const planPath =
|
|
124914
|
-
const planRaw =
|
|
125363
|
+
const planPath = path155.join(resolvedDir2, ".swarm", "plan.json");
|
|
125364
|
+
const planRaw = fs113.readFileSync(planPath, "utf-8");
|
|
124915
125365
|
const plan = JSON.parse(planRaw);
|
|
124916
125366
|
for (const planPhase of plan.phases ?? []) {
|
|
124917
125367
|
for (const task of planPhase.tasks ?? []) {
|
|
@@ -124988,8 +125438,8 @@ function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = fal
|
|
|
124988
125438
|
}
|
|
124989
125439
|
if (resolvedDir) {
|
|
124990
125440
|
try {
|
|
124991
|
-
const planPath =
|
|
124992
|
-
const planRaw =
|
|
125441
|
+
const planPath = path155.join(resolvedDir, ".swarm", "plan.json");
|
|
125442
|
+
const planRaw = fs113.readFileSync(planPath, "utf-8");
|
|
124993
125443
|
const plan = JSON.parse(planRaw);
|
|
124994
125444
|
for (const planPhase of plan.phases ?? []) {
|
|
124995
125445
|
for (const task of planPhase.tasks ?? []) {
|
|
@@ -125225,8 +125675,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
|
|
|
125225
125675
|
};
|
|
125226
125676
|
}
|
|
125227
125677
|
}
|
|
125228
|
-
normalizedDir =
|
|
125229
|
-
const pathParts = normalizedDir.split(
|
|
125678
|
+
normalizedDir = path155.normalize(args2.working_directory);
|
|
125679
|
+
const pathParts = normalizedDir.split(path155.sep);
|
|
125230
125680
|
if (pathParts.includes("..")) {
|
|
125231
125681
|
return {
|
|
125232
125682
|
success: false,
|
|
@@ -125236,11 +125686,11 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
|
|
|
125236
125686
|
]
|
|
125237
125687
|
};
|
|
125238
125688
|
}
|
|
125239
|
-
const resolvedDir =
|
|
125689
|
+
const resolvedDir = path155.resolve(normalizedDir);
|
|
125240
125690
|
try {
|
|
125241
|
-
const realPath =
|
|
125242
|
-
const planPath =
|
|
125243
|
-
if (!
|
|
125691
|
+
const realPath = fs113.realpathSync(resolvedDir);
|
|
125692
|
+
const planPath = path155.join(realPath, ".swarm", "plan.json");
|
|
125693
|
+
if (!fs113.existsSync(planPath)) {
|
|
125244
125694
|
return {
|
|
125245
125695
|
success: false,
|
|
125246
125696
|
message: `Invalid working_directory: plan not found in "${realPath}"`,
|
|
@@ -125270,9 +125720,9 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
|
|
|
125270
125720
|
directory = fallbackDir;
|
|
125271
125721
|
}
|
|
125272
125722
|
if (fallbackDir && directory !== fallbackDir) {
|
|
125273
|
-
const canonicalDir =
|
|
125274
|
-
const canonicalRoot =
|
|
125275
|
-
if (canonicalDir.startsWith(canonicalRoot +
|
|
125723
|
+
const canonicalDir = fs113.realpathSync(path155.resolve(directory));
|
|
125724
|
+
const canonicalRoot = fs113.realpathSync(path155.resolve(fallbackDir));
|
|
125725
|
+
if (canonicalDir.startsWith(canonicalRoot + path155.sep)) {
|
|
125276
125726
|
return {
|
|
125277
125727
|
success: false,
|
|
125278
125728
|
message: `Invalid working_directory: "${directory}" is a subdirectory of ` + `the project root "${fallbackDir}". Pass the project root path or ` + `omit working_directory entirely.`,
|
|
@@ -125284,22 +125734,22 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
|
|
|
125284
125734
|
}
|
|
125285
125735
|
if (args2.status === "in_progress") {
|
|
125286
125736
|
try {
|
|
125287
|
-
const evidencePath =
|
|
125288
|
-
|
|
125289
|
-
const fd =
|
|
125737
|
+
const evidencePath = path155.join(directory, ".swarm", "evidence", `${args2.task_id}.json`);
|
|
125738
|
+
fs113.mkdirSync(path155.dirname(evidencePath), { recursive: true });
|
|
125739
|
+
const fd = fs113.openSync(evidencePath, "wx");
|
|
125290
125740
|
let writeOk = false;
|
|
125291
125741
|
try {
|
|
125292
|
-
|
|
125742
|
+
fs113.writeSync(fd, JSON.stringify({
|
|
125293
125743
|
taskId: args2.task_id,
|
|
125294
125744
|
required_gates: [],
|
|
125295
125745
|
gates: {}
|
|
125296
125746
|
}, null, 2));
|
|
125297
125747
|
writeOk = true;
|
|
125298
125748
|
} finally {
|
|
125299
|
-
|
|
125749
|
+
fs113.closeSync(fd);
|
|
125300
125750
|
if (!writeOk) {
|
|
125301
125751
|
try {
|
|
125302
|
-
|
|
125752
|
+
fs113.unlinkSync(evidencePath);
|
|
125303
125753
|
} catch {}
|
|
125304
125754
|
}
|
|
125305
125755
|
}
|
|
@@ -125309,8 +125759,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
|
|
|
125309
125759
|
recoverTaskStateFromDelegations(args2.task_id, directory);
|
|
125310
125760
|
let phaseRequiresReviewer = true;
|
|
125311
125761
|
try {
|
|
125312
|
-
const planPath =
|
|
125313
|
-
const planRaw =
|
|
125762
|
+
const planPath = path155.join(directory, ".swarm", "plan.json");
|
|
125763
|
+
const planRaw = fs113.readFileSync(planPath, "utf-8");
|
|
125314
125764
|
const plan = JSON.parse(planRaw);
|
|
125315
125765
|
const taskPhase = plan.phases.find((p) => p.tasks.some((t) => t.id === args2.task_id));
|
|
125316
125766
|
if (taskPhase?.required_agents && !taskPhase.required_agents.includes("reviewer")) {
|
|
@@ -125537,7 +125987,7 @@ init_utils2();
|
|
|
125537
125987
|
init_redaction();
|
|
125538
125988
|
import { createHash as createHash12 } from "node:crypto";
|
|
125539
125989
|
import { appendFile as appendFile14, mkdir as mkdir25 } from "node:fs/promises";
|
|
125540
|
-
import * as
|
|
125990
|
+
import * as path156 from "node:path";
|
|
125541
125991
|
var EVIDENCE_CACHE_FILE = "evidence-cache/documents.jsonl";
|
|
125542
125992
|
var MAX_EVIDENCE_TEXT_LENGTH = 4000;
|
|
125543
125993
|
async function writeEvidenceDocuments(directory, inputs, now = () => new Date) {
|
|
@@ -125545,7 +125995,7 @@ async function writeEvidenceDocuments(directory, inputs, now = () => new Date) {
|
|
|
125545
125995
|
const capturedAt = now().toISOString();
|
|
125546
125996
|
const records = inputs.map((input) => createEvidenceDocumentRecord(input, capturedAt)).filter((record3) => record3 !== null);
|
|
125547
125997
|
if (records.length > 0) {
|
|
125548
|
-
await mkdir25(
|
|
125998
|
+
await mkdir25(path156.dirname(filePath), { recursive: true });
|
|
125549
125999
|
await appendFile14(filePath, `${records.map((record3) => JSON.stringify(record3)).join(`
|
|
125550
126000
|
`)}
|
|
125551
126001
|
`, "utf-8");
|
|
@@ -125700,7 +126150,7 @@ var web_search = createSwarmTool({
|
|
|
125700
126150
|
});
|
|
125701
126151
|
async function captureSearchEvidence(directory, query, results) {
|
|
125702
126152
|
try {
|
|
125703
|
-
const written = await
|
|
126153
|
+
const written = await _internals70.writeEvidenceDocuments(directory, results.map((result) => ({
|
|
125704
126154
|
sourceType: "web_search",
|
|
125705
126155
|
query,
|
|
125706
126156
|
title: result.title,
|
|
@@ -125728,7 +126178,7 @@ async function captureSearchEvidence(directory, query, results) {
|
|
|
125728
126178
|
};
|
|
125729
126179
|
}
|
|
125730
126180
|
}
|
|
125731
|
-
var
|
|
126181
|
+
var _internals70 = {
|
|
125732
126182
|
writeEvidenceDocuments
|
|
125733
126183
|
};
|
|
125734
126184
|
// src/tools/write-drift-evidence.ts
|
|
@@ -125738,8 +126188,8 @@ init_utils2();
|
|
|
125738
126188
|
init_ledger();
|
|
125739
126189
|
init_manager();
|
|
125740
126190
|
init_create_tool();
|
|
125741
|
-
import
|
|
125742
|
-
import
|
|
126191
|
+
import fs114 from "node:fs";
|
|
126192
|
+
import path157 from "node:path";
|
|
125743
126193
|
function normalizeVerdict(verdict) {
|
|
125744
126194
|
switch (verdict) {
|
|
125745
126195
|
case "APPROVED":
|
|
@@ -125787,7 +126237,7 @@ async function executeWriteDriftEvidence(args2, directory) {
|
|
|
125787
126237
|
entries: [evidenceEntry]
|
|
125788
126238
|
};
|
|
125789
126239
|
const filename = "drift-verifier.json";
|
|
125790
|
-
const relativePath =
|
|
126240
|
+
const relativePath = path157.join("evidence", String(phase), filename);
|
|
125791
126241
|
let validatedPath;
|
|
125792
126242
|
try {
|
|
125793
126243
|
validatedPath = validateSwarmPath(directory, relativePath);
|
|
@@ -125798,12 +126248,12 @@ async function executeWriteDriftEvidence(args2, directory) {
|
|
|
125798
126248
|
message: error93 instanceof Error ? error93.message : "Failed to validate path"
|
|
125799
126249
|
}, null, 2);
|
|
125800
126250
|
}
|
|
125801
|
-
const evidenceDir =
|
|
126251
|
+
const evidenceDir = path157.dirname(validatedPath);
|
|
125802
126252
|
try {
|
|
125803
|
-
await
|
|
125804
|
-
const tempPath =
|
|
125805
|
-
await
|
|
125806
|
-
await
|
|
126253
|
+
await fs114.promises.mkdir(evidenceDir, { recursive: true });
|
|
126254
|
+
const tempPath = path157.join(evidenceDir, `.${filename}.tmp`);
|
|
126255
|
+
await fs114.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
|
|
126256
|
+
await fs114.promises.rename(tempPath, validatedPath);
|
|
125807
126257
|
let snapshotInfo;
|
|
125808
126258
|
let snapshotError;
|
|
125809
126259
|
let qaProfileLocked;
|
|
@@ -125896,8 +126346,8 @@ var write_drift_evidence = createSwarmTool({
|
|
|
125896
126346
|
// src/tools/write-final-council-evidence.ts
|
|
125897
126347
|
init_zod();
|
|
125898
126348
|
init_loader();
|
|
125899
|
-
import
|
|
125900
|
-
import
|
|
126349
|
+
import fs115 from "node:fs";
|
|
126350
|
+
import path158 from "node:path";
|
|
125901
126351
|
init_utils2();
|
|
125902
126352
|
init_manager();
|
|
125903
126353
|
init_create_tool();
|
|
@@ -125985,7 +126435,7 @@ async function executeWriteFinalCouncilEvidence(args2, directory) {
|
|
|
125985
126435
|
timestamp: synthesis.timestamp
|
|
125986
126436
|
};
|
|
125987
126437
|
const filename = "final-council.json";
|
|
125988
|
-
const relativePath =
|
|
126438
|
+
const relativePath = path158.join("evidence", filename);
|
|
125989
126439
|
let validatedPath;
|
|
125990
126440
|
try {
|
|
125991
126441
|
validatedPath = validateSwarmPath(directory, relativePath);
|
|
@@ -125999,12 +126449,12 @@ async function executeWriteFinalCouncilEvidence(args2, directory) {
|
|
|
125999
126449
|
const evidenceContent = {
|
|
126000
126450
|
entries: [evidenceEntry]
|
|
126001
126451
|
};
|
|
126002
|
-
const evidenceDir =
|
|
126452
|
+
const evidenceDir = path158.dirname(validatedPath);
|
|
126003
126453
|
try {
|
|
126004
|
-
await
|
|
126005
|
-
const tempPath =
|
|
126006
|
-
await
|
|
126007
|
-
await
|
|
126454
|
+
await fs115.promises.mkdir(evidenceDir, { recursive: true });
|
|
126455
|
+
const tempPath = path158.join(evidenceDir, `.${filename}.tmp`);
|
|
126456
|
+
await fs115.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
|
|
126457
|
+
await fs115.promises.rename(tempPath, validatedPath);
|
|
126008
126458
|
return JSON.stringify({
|
|
126009
126459
|
success: true,
|
|
126010
126460
|
phase: input.phase,
|
|
@@ -126060,8 +126510,8 @@ var write_final_council_evidence = createSwarmTool({
|
|
|
126060
126510
|
init_zod();
|
|
126061
126511
|
init_utils2();
|
|
126062
126512
|
init_create_tool();
|
|
126063
|
-
import
|
|
126064
|
-
import
|
|
126513
|
+
import fs116 from "node:fs";
|
|
126514
|
+
import path159 from "node:path";
|
|
126065
126515
|
function normalizeVerdict2(verdict) {
|
|
126066
126516
|
switch (verdict) {
|
|
126067
126517
|
case "APPROVED":
|
|
@@ -126109,7 +126559,7 @@ async function executeWriteHallucinationEvidence(args2, directory) {
|
|
|
126109
126559
|
entries: [evidenceEntry]
|
|
126110
126560
|
};
|
|
126111
126561
|
const filename = "hallucination-guard.json";
|
|
126112
|
-
const relativePath =
|
|
126562
|
+
const relativePath = path159.join("evidence", String(phase), filename);
|
|
126113
126563
|
let validatedPath;
|
|
126114
126564
|
try {
|
|
126115
126565
|
validatedPath = validateSwarmPath(directory, relativePath);
|
|
@@ -126120,12 +126570,12 @@ async function executeWriteHallucinationEvidence(args2, directory) {
|
|
|
126120
126570
|
message: error93 instanceof Error ? error93.message : "Failed to validate path"
|
|
126121
126571
|
}, null, 2);
|
|
126122
126572
|
}
|
|
126123
|
-
const evidenceDir =
|
|
126573
|
+
const evidenceDir = path159.dirname(validatedPath);
|
|
126124
126574
|
try {
|
|
126125
|
-
await
|
|
126126
|
-
const tempPath =
|
|
126127
|
-
await
|
|
126128
|
-
await
|
|
126575
|
+
await fs116.promises.mkdir(evidenceDir, { recursive: true });
|
|
126576
|
+
const tempPath = path159.join(evidenceDir, `.${filename}.tmp`);
|
|
126577
|
+
await fs116.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
|
|
126578
|
+
await fs116.promises.rename(tempPath, validatedPath);
|
|
126129
126579
|
return JSON.stringify({
|
|
126130
126580
|
success: true,
|
|
126131
126581
|
phase,
|
|
@@ -126171,8 +126621,8 @@ var write_hallucination_evidence = createSwarmTool({
|
|
|
126171
126621
|
init_zod();
|
|
126172
126622
|
init_utils2();
|
|
126173
126623
|
init_create_tool();
|
|
126174
|
-
import
|
|
126175
|
-
import
|
|
126624
|
+
import fs117 from "node:fs";
|
|
126625
|
+
import path160 from "node:path";
|
|
126176
126626
|
function normalizeVerdict3(verdict) {
|
|
126177
126627
|
switch (verdict) {
|
|
126178
126628
|
case "PASS":
|
|
@@ -126246,7 +126696,7 @@ async function executeWriteMutationEvidence(args2, directory) {
|
|
|
126246
126696
|
entries: [evidenceEntry]
|
|
126247
126697
|
};
|
|
126248
126698
|
const filename = "mutation-gate.json";
|
|
126249
|
-
const relativePath =
|
|
126699
|
+
const relativePath = path160.join("evidence", String(phase), filename);
|
|
126250
126700
|
let validatedPath;
|
|
126251
126701
|
try {
|
|
126252
126702
|
validatedPath = validateSwarmPath(directory, relativePath);
|
|
@@ -126257,12 +126707,12 @@ async function executeWriteMutationEvidence(args2, directory) {
|
|
|
126257
126707
|
message: error93 instanceof Error ? error93.message : "Failed to validate path"
|
|
126258
126708
|
}, null, 2);
|
|
126259
126709
|
}
|
|
126260
|
-
const evidenceDir =
|
|
126710
|
+
const evidenceDir = path160.dirname(validatedPath);
|
|
126261
126711
|
try {
|
|
126262
|
-
await
|
|
126263
|
-
const tempPath =
|
|
126264
|
-
await
|
|
126265
|
-
await
|
|
126712
|
+
await fs117.promises.mkdir(evidenceDir, { recursive: true });
|
|
126713
|
+
const tempPath = path160.join(evidenceDir, `.${filename}.tmp`);
|
|
126714
|
+
await fs117.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
|
|
126715
|
+
await fs117.promises.rename(tempPath, validatedPath);
|
|
126266
126716
|
return JSON.stringify({
|
|
126267
126717
|
success: true,
|
|
126268
126718
|
phase,
|
|
@@ -126610,7 +127060,7 @@ async function initializeOpenCodeSwarm(ctx) {
|
|
|
126610
127060
|
const { PreflightTriggerManager: PTM } = await Promise.resolve().then(() => (init_trigger(), exports_trigger));
|
|
126611
127061
|
preflightTriggerManager = new PTM(automationConfig);
|
|
126612
127062
|
const { AutomationStatusArtifact: ASA } = await Promise.resolve().then(() => (init_status_artifact(), exports_status_artifact));
|
|
126613
|
-
const swarmDir =
|
|
127063
|
+
const swarmDir = path162.resolve(ctx.directory, ".swarm");
|
|
126614
127064
|
statusArtifact = new ASA(swarmDir);
|
|
126615
127065
|
statusArtifact.updateConfig(automationConfig.mode, automationConfig.capabilities);
|
|
126616
127066
|
if (automationConfig.capabilities?.evidence_auto_summaries === true) {
|
|
@@ -127207,7 +127657,7 @@ ${promptRaw}`;
|
|
|
127207
127657
|
const meta3 = readSkillMetadata(s.skillPath, ctx.directory);
|
|
127208
127658
|
let desc = meta3.description || "";
|
|
127209
127659
|
if (!desc || desc === "No description provided") {
|
|
127210
|
-
desc =
|
|
127660
|
+
desc = path162.basename(path162.dirname(s.skillPath));
|
|
127211
127661
|
}
|
|
127212
127662
|
desc = desc.replace(/,/g, ";");
|
|
127213
127663
|
return `file:${s.skillPath} (-- ${desc})`;
|
|
@@ -127217,7 +127667,7 @@ ${promptRaw}`;
|
|
|
127217
127667
|
|
|
127218
127668
|
${promptRaw}`;
|
|
127219
127669
|
argsRecord.prompt = newPrompt;
|
|
127220
|
-
const skillNames = topSkills.map((s) => `${
|
|
127670
|
+
const skillNames = topSkills.map((s) => `${path162.basename(s.skillPath)} (score: ${s.score.toFixed(2)})`).join(", ");
|
|
127221
127671
|
console.warn(`[skill-propagation-gate] Injected skills: ${skillNames}`);
|
|
127222
127672
|
for (const skill of topSkills) {
|
|
127223
127673
|
try {
|