opencode-swarm 7.46.4 → 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 +913 -462
- 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();
|
|
@@ -103988,6 +104421,7 @@ var WRITE_EDIT_TOOLS = new Set([
|
|
|
103988
104421
|
"apply_patch",
|
|
103989
104422
|
"create_file"
|
|
103990
104423
|
]);
|
|
104424
|
+
var NEW_EXPORT_RE = /^\+(?:export)\s+(?:function|class|const|type|interface)\s+(\w{3,})/gm;
|
|
103991
104425
|
function countMatches(text, pattern) {
|
|
103992
104426
|
return (text.match(pattern) ?? []).length;
|
|
103993
104427
|
}
|
|
@@ -104049,7 +104483,7 @@ function checkDeadExports(content, projectDir, startTime) {
|
|
|
104049
104483
|
const hasPackageJson = fs68.existsSync(path106.join(projectDir, "package.json"));
|
|
104050
104484
|
if (!hasPackageJson)
|
|
104051
104485
|
return null;
|
|
104052
|
-
const exportMatches = content.matchAll(
|
|
104486
|
+
const exportMatches = content.matchAll(NEW_EXPORT_RE);
|
|
104053
104487
|
const newExports = [];
|
|
104054
104488
|
for (const match of exportMatches) {
|
|
104055
104489
|
if (match[1])
|
|
@@ -104142,7 +104576,7 @@ function checkStaleImports(content, threshold) {
|
|
|
104142
104576
|
};
|
|
104143
104577
|
}
|
|
104144
104578
|
function checkDuplicateUtility(content, projectDir, startTime, targetFile) {
|
|
104145
|
-
const exportMatches = content.matchAll(
|
|
104579
|
+
const exportMatches = content.matchAll(NEW_EXPORT_RE);
|
|
104146
104580
|
const newExports = [];
|
|
104147
104581
|
for (const match of exportMatches) {
|
|
104148
104582
|
if (match[1])
|
|
@@ -111029,8 +111463,8 @@ init_config();
|
|
|
111029
111463
|
init_schema();
|
|
111030
111464
|
init_qa_gate_profile();
|
|
111031
111465
|
init_manager2();
|
|
111032
|
-
import * as
|
|
111033
|
-
import * as
|
|
111466
|
+
import * as fs90 from "node:fs";
|
|
111467
|
+
import * as path127 from "node:path";
|
|
111034
111468
|
|
|
111035
111469
|
// src/full-auto/phase-approval.ts
|
|
111036
111470
|
init_utils2();
|
|
@@ -111943,8 +112377,8 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
111943
112377
|
let driftCheckEnabled = true;
|
|
111944
112378
|
let driftHasSpecMd = false;
|
|
111945
112379
|
try {
|
|
111946
|
-
const specMdPath =
|
|
111947
|
-
driftHasSpecMd =
|
|
112380
|
+
const specMdPath = path127.join(dir, ".swarm", "spec.md");
|
|
112381
|
+
driftHasSpecMd = fs90.existsSync(specMdPath);
|
|
111948
112382
|
const gatePlan = await loadPlan(dir);
|
|
111949
112383
|
if (gatePlan) {
|
|
111950
112384
|
const gatePlanId = derivePlanId(gatePlan);
|
|
@@ -111964,9 +112398,9 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
111964
112398
|
} else {
|
|
111965
112399
|
let phaseType;
|
|
111966
112400
|
try {
|
|
111967
|
-
const planPath =
|
|
111968
|
-
if (
|
|
111969
|
-
const planRaw =
|
|
112401
|
+
const planPath = path127.join(dir, ".swarm", "plan.json");
|
|
112402
|
+
if (fs90.existsSync(planPath)) {
|
|
112403
|
+
const planRaw = fs90.readFileSync(planPath, "utf-8");
|
|
111970
112404
|
const plan = JSON.parse(planRaw);
|
|
111971
112405
|
const targetPhase = plan.phases?.find((p) => p.id === phase);
|
|
111972
112406
|
phaseType = targetPhase?.type;
|
|
@@ -111976,11 +112410,11 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
111976
112410
|
warnings.push(`Phase ${phase} is annotated as 'non-code'. Drift verification was skipped per phase type annotation.`);
|
|
111977
112411
|
} else {
|
|
111978
112412
|
try {
|
|
111979
|
-
const driftEvidencePath =
|
|
112413
|
+
const driftEvidencePath = path127.join(dir, ".swarm", "evidence", String(phase), "drift-verifier.json");
|
|
111980
112414
|
let driftVerdictFound = false;
|
|
111981
112415
|
let driftVerdictApproved = false;
|
|
111982
112416
|
try {
|
|
111983
|
-
const driftEvidenceContent =
|
|
112417
|
+
const driftEvidenceContent = fs90.readFileSync(driftEvidencePath, "utf-8");
|
|
111984
112418
|
const driftEvidence = JSON.parse(driftEvidenceContent);
|
|
111985
112419
|
const entries = driftEvidence.entries ?? [];
|
|
111986
112420
|
for (const entry of entries) {
|
|
@@ -112014,9 +112448,9 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
112014
112448
|
let incompleteTaskCount = 0;
|
|
112015
112449
|
let planParseable = false;
|
|
112016
112450
|
try {
|
|
112017
|
-
const planPath =
|
|
112018
|
-
if (
|
|
112019
|
-
const planRaw =
|
|
112451
|
+
const planPath = path127.join(dir, ".swarm", "plan.json");
|
|
112452
|
+
if (fs90.existsSync(planPath)) {
|
|
112453
|
+
const planRaw = fs90.readFileSync(planPath, "utf-8");
|
|
112020
112454
|
const plan = JSON.parse(planRaw);
|
|
112021
112455
|
planParseable = true;
|
|
112022
112456
|
const planPhase = plan.phases?.find((p) => p.id === phase);
|
|
@@ -112081,11 +112515,11 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
112081
112515
|
const overrides = session2?.qaGateSessionOverrides ?? {};
|
|
112082
112516
|
const effective = getEffectiveGates(profile, overrides);
|
|
112083
112517
|
if (effective.hallucination_guard === true) {
|
|
112084
|
-
const hgPath =
|
|
112518
|
+
const hgPath = path127.join(dir, ".swarm", "evidence", String(phase), "hallucination-guard.json");
|
|
112085
112519
|
let hgVerdictFound = false;
|
|
112086
112520
|
let hgVerdictApproved = false;
|
|
112087
112521
|
try {
|
|
112088
|
-
const hgContent =
|
|
112522
|
+
const hgContent = fs90.readFileSync(hgPath, "utf-8");
|
|
112089
112523
|
const hgBundle = JSON.parse(hgContent);
|
|
112090
112524
|
for (const entry of hgBundle.entries ?? []) {
|
|
112091
112525
|
if (typeof entry.type === "string" && entry.type.includes("hallucination") && typeof entry.verdict === "string") {
|
|
@@ -112153,11 +112587,11 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
112153
112587
|
const overrides = session2?.qaGateSessionOverrides ?? {};
|
|
112154
112588
|
const effective = getEffectiveGates(profile, overrides);
|
|
112155
112589
|
if (effective.mutation_test === true) {
|
|
112156
|
-
const mgPath =
|
|
112590
|
+
const mgPath = path127.join(dir, ".swarm", "evidence", String(phase), "mutation-gate.json");
|
|
112157
112591
|
let mgVerdictFound = false;
|
|
112158
112592
|
let mgVerdict;
|
|
112159
112593
|
try {
|
|
112160
|
-
const mgContent =
|
|
112594
|
+
const mgContent = fs90.readFileSync(mgPath, "utf-8");
|
|
112161
112595
|
const mgBundle = JSON.parse(mgContent);
|
|
112162
112596
|
for (const entry of mgBundle.entries ?? []) {
|
|
112163
112597
|
if (typeof entry.type === "string" && entry.type === "mutation-gate" && typeof entry.verdict === "string") {
|
|
@@ -112227,14 +112661,14 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
112227
112661
|
const effective = getEffectiveGates(profile, overrides);
|
|
112228
112662
|
if (effective.council_mode === true) {
|
|
112229
112663
|
councilModeEnabled = true;
|
|
112230
|
-
const pcPath =
|
|
112664
|
+
const pcPath = path127.join(dir, ".swarm", "evidence", String(phase), "phase-council.json");
|
|
112231
112665
|
let pcVerdictFound = false;
|
|
112232
112666
|
let _pcVerdict;
|
|
112233
112667
|
let pcQuorumSize;
|
|
112234
112668
|
let pcTimestamp;
|
|
112235
112669
|
let pcPhaseNumber;
|
|
112236
112670
|
try {
|
|
112237
|
-
const pcContent =
|
|
112671
|
+
const pcContent = fs90.readFileSync(pcPath, "utf-8");
|
|
112238
112672
|
const pcBundle = JSON.parse(pcContent);
|
|
112239
112673
|
for (const entry of pcBundle.entries ?? []) {
|
|
112240
112674
|
if (typeof entry.type === "string" && entry.type === "phase-council" && typeof entry.verdict === "string") {
|
|
@@ -112490,11 +112924,11 @@ Findings: ${details.join("; ")}` : "";
|
|
|
112490
112924
|
const effective = getEffectiveGates(profile, overrides);
|
|
112491
112925
|
if (effective.final_council === true) {
|
|
112492
112926
|
finalCouncilEnabled = true;
|
|
112493
|
-
const fcPath =
|
|
112927
|
+
const fcPath = path127.join(dir, ".swarm", "evidence", "final-council.json");
|
|
112494
112928
|
let fcVerdictFound = false;
|
|
112495
112929
|
let _fcVerdict;
|
|
112496
112930
|
try {
|
|
112497
|
-
const fcContent =
|
|
112931
|
+
const fcContent = fs90.readFileSync(fcPath, "utf-8");
|
|
112498
112932
|
const fcBundle = JSON.parse(fcContent);
|
|
112499
112933
|
for (const entry of fcBundle.entries ?? []) {
|
|
112500
112934
|
if (typeof entry.type === "string" && entry.type === "final-council" && typeof entry.verdict === "string") {
|
|
@@ -112678,7 +113112,7 @@ Findings: ${details.join("; ")}` : "";
|
|
|
112678
113112
|
}
|
|
112679
113113
|
if (retroFound && retroEntry?.lessons_learned && retroEntry.lessons_learned.length > 0) {
|
|
112680
113114
|
try {
|
|
112681
|
-
const projectName =
|
|
113115
|
+
const projectName = path127.basename(dir);
|
|
112682
113116
|
const curationResult = await curateAndStoreSwarm(retroEntry.lessons_learned, projectName, { phase_number: phase }, dir, knowledgeConfig);
|
|
112683
113117
|
if (curationResult) {
|
|
112684
113118
|
const sessionState = swarmState.agentSessions.get(sessionID);
|
|
@@ -112757,18 +113191,35 @@ Findings: ${details.join("; ")}` : "";
|
|
|
112757
113191
|
} catch (curatorError) {
|
|
112758
113192
|
safeWarn("[phase_complete] Curator pipeline error (non-blocking):", curatorError);
|
|
112759
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
|
+
}
|
|
112760
113211
|
try {
|
|
112761
113212
|
const markerPath = validateSwarmPath(dir, "skill-usage-last-processed.json");
|
|
112762
113213
|
let sinceTimestamp;
|
|
112763
113214
|
try {
|
|
112764
|
-
const markerData = JSON.parse(
|
|
113215
|
+
const markerData = JSON.parse(fs90.readFileSync(markerPath, "utf-8"));
|
|
112765
113216
|
sinceTimestamp = markerData.lastProcessedTimestamp;
|
|
112766
113217
|
} catch {}
|
|
112767
113218
|
const feedbackResult = await applySkillUsageFeedback(dir, {
|
|
112768
113219
|
sinceTimestamp
|
|
112769
113220
|
});
|
|
112770
113221
|
try {
|
|
112771
|
-
|
|
113222
|
+
fs90.writeFileSync(markerPath, JSON.stringify({ lastProcessedTimestamp: new Date().toISOString() }), "utf-8");
|
|
112772
113223
|
} catch {}
|
|
112773
113224
|
if (feedbackResult.processed > 0) {
|
|
112774
113225
|
const sessionState = swarmState.agentSessions.get(sessionID);
|
|
@@ -112788,7 +113239,7 @@ Findings: ${details.join("; ")}` : "";
|
|
|
112788
113239
|
let phaseRequiredAgents;
|
|
112789
113240
|
try {
|
|
112790
113241
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
112791
|
-
const planRaw =
|
|
113242
|
+
const planRaw = fs90.readFileSync(planPath, "utf-8");
|
|
112792
113243
|
const plan = JSON.parse(planRaw);
|
|
112793
113244
|
const phaseObj = plan.phases.find((p) => p.id === phase);
|
|
112794
113245
|
phaseRequiredAgents = phaseObj?.required_agents;
|
|
@@ -112803,7 +113254,7 @@ Findings: ${details.join("; ")}` : "";
|
|
|
112803
113254
|
if (agentsMissing.length > 0) {
|
|
112804
113255
|
try {
|
|
112805
113256
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
112806
|
-
const planRaw =
|
|
113257
|
+
const planRaw = fs90.readFileSync(planPath, "utf-8");
|
|
112807
113258
|
const plan = JSON.parse(planRaw);
|
|
112808
113259
|
const targetPhase = plan.phases.find((p) => p.id === phase);
|
|
112809
113260
|
if (targetPhase && targetPhase.tasks.length > 0 && canInferMissingAgentsFromTaskGates(agentsMissing) && await allCompletedTasksHavePassedGateEvidence(dir, targetPhase.tasks)) {
|
|
@@ -112843,7 +113294,7 @@ Findings: ${details.join("; ")}` : "";
|
|
|
112843
113294
|
if (phaseCompleteConfig.regression_sweep?.enforce) {
|
|
112844
113295
|
try {
|
|
112845
113296
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
112846
|
-
const planRaw =
|
|
113297
|
+
const planRaw = fs90.readFileSync(planPath, "utf-8");
|
|
112847
113298
|
const plan = JSON.parse(planRaw);
|
|
112848
113299
|
const targetPhase = plan.phases.find((p) => p.id === phase);
|
|
112849
113300
|
if (targetPhase) {
|
|
@@ -112897,7 +113348,7 @@ Findings: ${details.join("; ")}` : "";
|
|
|
112897
113348
|
}
|
|
112898
113349
|
try {
|
|
112899
113350
|
const eventsPath = validateSwarmPath(dir, "events.jsonl");
|
|
112900
|
-
|
|
113351
|
+
fs90.appendFileSync(eventsPath, `${JSON.stringify(event)}
|
|
112901
113352
|
`, "utf-8");
|
|
112902
113353
|
} catch (writeError) {
|
|
112903
113354
|
warnings.push(`Warning: failed to write phase complete event: ${writeError instanceof Error ? writeError.message : String(writeError)}`);
|
|
@@ -112972,12 +113423,12 @@ Findings: ${details.join("; ")}` : "";
|
|
|
112972
113423
|
warnings.push(`Warning: failed to update plan.json phase status`);
|
|
112973
113424
|
try {
|
|
112974
113425
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
112975
|
-
const planRaw =
|
|
113426
|
+
const planRaw = fs90.readFileSync(planPath, "utf-8");
|
|
112976
113427
|
const plan2 = JSON.parse(planRaw);
|
|
112977
113428
|
const phaseObj = plan2.phases.find((p) => p.id === phase);
|
|
112978
113429
|
if (phaseObj) {
|
|
112979
113430
|
phaseObj.status = "complete";
|
|
112980
|
-
|
|
113431
|
+
fs90.writeFileSync(planPath, JSON.stringify(plan2, null, 2), "utf-8");
|
|
112981
113432
|
}
|
|
112982
113433
|
} catch {}
|
|
112983
113434
|
} else if (plan) {
|
|
@@ -113014,12 +113465,12 @@ Findings: ${details.join("; ")}` : "";
|
|
|
113014
113465
|
warnings.push(`Warning: failed to update plan.json phase status`);
|
|
113015
113466
|
try {
|
|
113016
113467
|
const planPath = validateSwarmPath(dir, "plan.json");
|
|
113017
|
-
const planRaw =
|
|
113468
|
+
const planRaw = fs90.readFileSync(planPath, "utf-8");
|
|
113018
113469
|
const plan = JSON.parse(planRaw);
|
|
113019
113470
|
const phaseObj = plan.phases.find((p) => p.id === phase);
|
|
113020
113471
|
if (phaseObj) {
|
|
113021
113472
|
phaseObj.status = "complete";
|
|
113022
|
-
|
|
113473
|
+
fs90.writeFileSync(planPath, JSON.stringify(plan, null, 2), "utf-8");
|
|
113023
113474
|
}
|
|
113024
113475
|
} catch {}
|
|
113025
113476
|
}
|
|
@@ -113077,8 +113528,8 @@ init_discovery();
|
|
|
113077
113528
|
init_utils();
|
|
113078
113529
|
init_bun_compat();
|
|
113079
113530
|
init_create_tool();
|
|
113080
|
-
import * as
|
|
113081
|
-
import * as
|
|
113531
|
+
import * as fs91 from "node:fs";
|
|
113532
|
+
import * as path128 from "node:path";
|
|
113082
113533
|
var MAX_OUTPUT_BYTES5 = 52428800;
|
|
113083
113534
|
var AUDIT_TIMEOUT_MS = 120000;
|
|
113084
113535
|
function isValidEcosystem(value) {
|
|
@@ -113106,31 +113557,31 @@ function validateArgs3(args2) {
|
|
|
113106
113557
|
function detectEcosystems(directory) {
|
|
113107
113558
|
const ecosystems = [];
|
|
113108
113559
|
const cwd = directory;
|
|
113109
|
-
if (
|
|
113560
|
+
if (fs91.existsSync(path128.join(cwd, "package.json"))) {
|
|
113110
113561
|
ecosystems.push("npm");
|
|
113111
113562
|
}
|
|
113112
|
-
if (
|
|
113563
|
+
if (fs91.existsSync(path128.join(cwd, "pyproject.toml")) || fs91.existsSync(path128.join(cwd, "requirements.txt"))) {
|
|
113113
113564
|
ecosystems.push("pip");
|
|
113114
113565
|
}
|
|
113115
|
-
if (
|
|
113566
|
+
if (fs91.existsSync(path128.join(cwd, "Cargo.toml"))) {
|
|
113116
113567
|
ecosystems.push("cargo");
|
|
113117
113568
|
}
|
|
113118
|
-
if (
|
|
113569
|
+
if (fs91.existsSync(path128.join(cwd, "go.mod"))) {
|
|
113119
113570
|
ecosystems.push("go");
|
|
113120
113571
|
}
|
|
113121
113572
|
try {
|
|
113122
|
-
const files =
|
|
113573
|
+
const files = fs91.readdirSync(cwd);
|
|
113123
113574
|
if (files.some((f) => f.endsWith(".csproj") || f.endsWith(".sln"))) {
|
|
113124
113575
|
ecosystems.push("dotnet");
|
|
113125
113576
|
}
|
|
113126
113577
|
} catch {}
|
|
113127
|
-
if (
|
|
113578
|
+
if (fs91.existsSync(path128.join(cwd, "Gemfile")) || fs91.existsSync(path128.join(cwd, "Gemfile.lock"))) {
|
|
113128
113579
|
ecosystems.push("ruby");
|
|
113129
113580
|
}
|
|
113130
|
-
if (
|
|
113581
|
+
if (fs91.existsSync(path128.join(cwd, "pubspec.yaml"))) {
|
|
113131
113582
|
ecosystems.push("dart");
|
|
113132
113583
|
}
|
|
113133
|
-
if (
|
|
113584
|
+
if (fs91.existsSync(path128.join(cwd, "composer.lock"))) {
|
|
113134
113585
|
ecosystems.push("composer");
|
|
113135
113586
|
}
|
|
113136
113587
|
return ecosystems;
|
|
@@ -113143,7 +113594,7 @@ async function runNpmAudit(directory) {
|
|
|
113143
113594
|
stderr: "pipe",
|
|
113144
113595
|
cwd: directory
|
|
113145
113596
|
});
|
|
113146
|
-
const timeoutPromise = new Promise((
|
|
113597
|
+
const timeoutPromise = new Promise((resolve45) => setTimeout(() => resolve45("timeout"), AUDIT_TIMEOUT_MS));
|
|
113147
113598
|
const result = await Promise.race([
|
|
113148
113599
|
Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr2]) => ({ stdout: stdout2, stderr: stderr2 })),
|
|
113149
113600
|
timeoutPromise
|
|
@@ -113263,7 +113714,7 @@ async function runPipAudit(directory) {
|
|
|
113263
113714
|
stderr: "pipe",
|
|
113264
113715
|
cwd: directory
|
|
113265
113716
|
});
|
|
113266
|
-
const timeoutPromise = new Promise((
|
|
113717
|
+
const timeoutPromise = new Promise((resolve45) => setTimeout(() => resolve45("timeout"), AUDIT_TIMEOUT_MS));
|
|
113267
113718
|
const result = await Promise.race([
|
|
113268
113719
|
Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr2]) => ({ stdout: stdout2, stderr: stderr2 })),
|
|
113269
113720
|
timeoutPromise
|
|
@@ -113391,7 +113842,7 @@ async function runCargoAudit(directory) {
|
|
|
113391
113842
|
stderr: "pipe",
|
|
113392
113843
|
cwd: directory
|
|
113393
113844
|
});
|
|
113394
|
-
const timeoutPromise = new Promise((
|
|
113845
|
+
const timeoutPromise = new Promise((resolve45) => setTimeout(() => resolve45("timeout"), AUDIT_TIMEOUT_MS));
|
|
113395
113846
|
const result = await Promise.race([
|
|
113396
113847
|
Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
|
|
113397
113848
|
timeoutPromise
|
|
@@ -113515,7 +113966,7 @@ async function runGoAudit(directory) {
|
|
|
113515
113966
|
stderr: "pipe",
|
|
113516
113967
|
cwd: directory
|
|
113517
113968
|
});
|
|
113518
|
-
const timeoutPromise = new Promise((
|
|
113969
|
+
const timeoutPromise = new Promise((resolve45) => setTimeout(() => resolve45("timeout"), AUDIT_TIMEOUT_MS));
|
|
113519
113970
|
const result = await Promise.race([
|
|
113520
113971
|
Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
|
|
113521
113972
|
timeoutPromise
|
|
@@ -113648,7 +114099,7 @@ async function runDotnetAudit(directory) {
|
|
|
113648
114099
|
stderr: "pipe",
|
|
113649
114100
|
cwd: directory
|
|
113650
114101
|
});
|
|
113651
|
-
const timeoutPromise = new Promise((
|
|
114102
|
+
const timeoutPromise = new Promise((resolve45) => setTimeout(() => resolve45("timeout"), AUDIT_TIMEOUT_MS));
|
|
113652
114103
|
const result = await Promise.race([
|
|
113653
114104
|
Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
|
|
113654
114105
|
timeoutPromise
|
|
@@ -113764,7 +114215,7 @@ async function runBundleAudit(directory) {
|
|
|
113764
114215
|
stderr: "pipe",
|
|
113765
114216
|
cwd: directory
|
|
113766
114217
|
});
|
|
113767
|
-
const timeoutPromise = new Promise((
|
|
114218
|
+
const timeoutPromise = new Promise((resolve45) => setTimeout(() => resolve45("timeout"), AUDIT_TIMEOUT_MS));
|
|
113768
114219
|
const result = await Promise.race([
|
|
113769
114220
|
Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
|
|
113770
114221
|
timeoutPromise
|
|
@@ -113909,7 +114360,7 @@ async function runDartAudit(directory) {
|
|
|
113909
114360
|
stderr: "pipe",
|
|
113910
114361
|
cwd: directory
|
|
113911
114362
|
});
|
|
113912
|
-
const timeoutPromise = new Promise((
|
|
114363
|
+
const timeoutPromise = new Promise((resolve45) => setTimeout(() => resolve45("timeout"), AUDIT_TIMEOUT_MS));
|
|
113913
114364
|
const result = await Promise.race([
|
|
113914
114365
|
Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
|
|
113915
114366
|
timeoutPromise
|
|
@@ -114024,7 +114475,7 @@ async function runComposerAudit(directory) {
|
|
|
114024
114475
|
stderr: "pipe",
|
|
114025
114476
|
cwd: directory
|
|
114026
114477
|
});
|
|
114027
|
-
const timeoutPromise = new Promise((
|
|
114478
|
+
const timeoutPromise = new Promise((resolve45) => setTimeout(() => resolve45("timeout"), AUDIT_TIMEOUT_MS));
|
|
114028
114479
|
const result = await Promise.race([
|
|
114029
114480
|
Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
|
|
114030
114481
|
timeoutPromise
|
|
@@ -114265,8 +114716,8 @@ var pkg_audit = createSwarmTool({
|
|
|
114265
114716
|
// src/tools/placeholder-scan.ts
|
|
114266
114717
|
init_zod();
|
|
114267
114718
|
init_manager2();
|
|
114268
|
-
import * as
|
|
114269
|
-
import * as
|
|
114719
|
+
import * as fs92 from "node:fs";
|
|
114720
|
+
import * as path129 from "node:path";
|
|
114270
114721
|
init_utils();
|
|
114271
114722
|
init_create_tool();
|
|
114272
114723
|
var MAX_FILE_SIZE = 1024 * 1024;
|
|
@@ -114389,7 +114840,7 @@ function isScaffoldFile(filePath) {
|
|
|
114389
114840
|
if (SCAFFOLD_PATH_PATTERNS.some((pattern) => pattern.test(normalizedPath))) {
|
|
114390
114841
|
return true;
|
|
114391
114842
|
}
|
|
114392
|
-
const filename =
|
|
114843
|
+
const filename = path129.basename(filePath);
|
|
114393
114844
|
if (SCAFFOLD_FILENAME_PATTERNS.some((pattern) => pattern.test(filename))) {
|
|
114394
114845
|
return true;
|
|
114395
114846
|
}
|
|
@@ -114406,7 +114857,7 @@ function isAllowedByGlobs(filePath, allowGlobs) {
|
|
|
114406
114857
|
if (regex.test(normalizedPath)) {
|
|
114407
114858
|
return true;
|
|
114408
114859
|
}
|
|
114409
|
-
const filename =
|
|
114860
|
+
const filename = path129.basename(filePath);
|
|
114410
114861
|
const filenameRegex = new RegExp(`^${regexPattern}$`, "i");
|
|
114411
114862
|
if (filenameRegex.test(filename)) {
|
|
114412
114863
|
return true;
|
|
@@ -114415,7 +114866,7 @@ function isAllowedByGlobs(filePath, allowGlobs) {
|
|
|
114415
114866
|
return false;
|
|
114416
114867
|
}
|
|
114417
114868
|
function isParserSupported(filePath) {
|
|
114418
|
-
const ext =
|
|
114869
|
+
const ext = path129.extname(filePath).toLowerCase();
|
|
114419
114870
|
return SUPPORTED_PARSER_EXTENSIONS.has(ext);
|
|
114420
114871
|
}
|
|
114421
114872
|
function isPlanFile(filePath) {
|
|
@@ -114662,28 +115113,28 @@ async function placeholderScan(input, directory) {
|
|
|
114662
115113
|
let filesScanned = 0;
|
|
114663
115114
|
const filesWithFindings = new Set;
|
|
114664
115115
|
for (const filePath of changed_files) {
|
|
114665
|
-
const fullPath =
|
|
114666
|
-
const resolvedDirectory =
|
|
114667
|
-
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) {
|
|
114668
115119
|
continue;
|
|
114669
115120
|
}
|
|
114670
|
-
if (!
|
|
115121
|
+
if (!fs92.existsSync(fullPath)) {
|
|
114671
115122
|
continue;
|
|
114672
115123
|
}
|
|
114673
115124
|
if (isAllowedByGlobs(filePath, allow_globs)) {
|
|
114674
115125
|
continue;
|
|
114675
115126
|
}
|
|
114676
|
-
const relativeFilePath =
|
|
115127
|
+
const relativeFilePath = path129.relative(directory, fullPath).replace(/\\/g, "/");
|
|
114677
115128
|
if (FILE_ALLOWLIST.some((allowed) => relativeFilePath.endsWith(allowed))) {
|
|
114678
115129
|
continue;
|
|
114679
115130
|
}
|
|
114680
115131
|
let content;
|
|
114681
115132
|
try {
|
|
114682
|
-
const stat9 =
|
|
115133
|
+
const stat9 = fs92.statSync(fullPath);
|
|
114683
115134
|
if (stat9.size > MAX_FILE_SIZE) {
|
|
114684
115135
|
continue;
|
|
114685
115136
|
}
|
|
114686
|
-
content =
|
|
115137
|
+
content = fs92.readFileSync(fullPath, "utf-8");
|
|
114687
115138
|
} catch {
|
|
114688
115139
|
continue;
|
|
114689
115140
|
}
|
|
@@ -114744,8 +115195,8 @@ var placeholder_scan = createSwarmTool({
|
|
|
114744
115195
|
}
|
|
114745
115196
|
});
|
|
114746
115197
|
// src/tools/pre-check-batch.ts
|
|
114747
|
-
import * as
|
|
114748
|
-
import * as
|
|
115198
|
+
import * as fs96 from "node:fs";
|
|
115199
|
+
import * as path133 from "node:path";
|
|
114749
115200
|
init_zod();
|
|
114750
115201
|
init_manager2();
|
|
114751
115202
|
init_utils();
|
|
@@ -114873,11 +115324,11 @@ var quality_budget = createSwarmTool({
|
|
|
114873
115324
|
}).optional().describe("Quality budget thresholds")
|
|
114874
115325
|
},
|
|
114875
115326
|
async execute(args2, directory) {
|
|
114876
|
-
const result = await
|
|
115327
|
+
const result = await _internals56.qualityBudget(args2, directory);
|
|
114877
115328
|
return JSON.stringify(result);
|
|
114878
115329
|
}
|
|
114879
115330
|
});
|
|
114880
|
-
var
|
|
115331
|
+
var _internals56 = {
|
|
114881
115332
|
qualityBudget
|
|
114882
115333
|
};
|
|
114883
115334
|
|
|
@@ -114885,8 +115336,8 @@ var _internals55 = {
|
|
|
114885
115336
|
init_zod();
|
|
114886
115337
|
init_manager2();
|
|
114887
115338
|
init_detector();
|
|
114888
|
-
import * as
|
|
114889
|
-
import * as
|
|
115339
|
+
import * as fs95 from "node:fs";
|
|
115340
|
+
import * as path132 from "node:path";
|
|
114890
115341
|
import { extname as extname20 } from "node:path";
|
|
114891
115342
|
|
|
114892
115343
|
// src/sast/rules/c.ts
|
|
@@ -115601,12 +116052,12 @@ function executeRulesSync(filePath, content, language) {
|
|
|
115601
116052
|
|
|
115602
116053
|
// src/sast/semgrep.ts
|
|
115603
116054
|
import * as child_process9 from "node:child_process";
|
|
115604
|
-
import * as
|
|
115605
|
-
import * as
|
|
116055
|
+
import * as fs93 from "node:fs";
|
|
116056
|
+
import * as path130 from "node:path";
|
|
115606
116057
|
var semgrepAvailableCache = null;
|
|
115607
116058
|
var DEFAULT_RULES_DIR = ".swarm/semgrep-rules";
|
|
115608
116059
|
var DEFAULT_TIMEOUT_MS3 = 30000;
|
|
115609
|
-
var
|
|
116060
|
+
var _internals57 = {
|
|
115610
116061
|
isSemgrepAvailable,
|
|
115611
116062
|
checkSemgrepAvailable,
|
|
115612
116063
|
resetSemgrepCache,
|
|
@@ -115631,7 +116082,7 @@ function isSemgrepAvailable() {
|
|
|
115631
116082
|
}
|
|
115632
116083
|
}
|
|
115633
116084
|
async function checkSemgrepAvailable() {
|
|
115634
|
-
return
|
|
116085
|
+
return _internals57.isSemgrepAvailable();
|
|
115635
116086
|
}
|
|
115636
116087
|
function resetSemgrepCache() {
|
|
115637
116088
|
semgrepAvailableCache = null;
|
|
@@ -115683,7 +116134,7 @@ function mapSemgrepSeverity(severity) {
|
|
|
115683
116134
|
}
|
|
115684
116135
|
}
|
|
115685
116136
|
async function executeWithTimeout(command, args2, options) {
|
|
115686
|
-
return new Promise((
|
|
116137
|
+
return new Promise((resolve47) => {
|
|
115687
116138
|
const child = child_process9.spawn(command, args2, {
|
|
115688
116139
|
shell: false,
|
|
115689
116140
|
cwd: options.cwd
|
|
@@ -115692,7 +116143,7 @@ async function executeWithTimeout(command, args2, options) {
|
|
|
115692
116143
|
let stderr = "";
|
|
115693
116144
|
const timeout = setTimeout(() => {
|
|
115694
116145
|
child.kill("SIGTERM");
|
|
115695
|
-
|
|
116146
|
+
resolve47({
|
|
115696
116147
|
stdout,
|
|
115697
116148
|
stderr: "Process timed out",
|
|
115698
116149
|
exitCode: 124
|
|
@@ -115706,7 +116157,7 @@ async function executeWithTimeout(command, args2, options) {
|
|
|
115706
116157
|
});
|
|
115707
116158
|
child.on("close", (code) => {
|
|
115708
116159
|
clearTimeout(timeout);
|
|
115709
|
-
|
|
116160
|
+
resolve47({
|
|
115710
116161
|
stdout,
|
|
115711
116162
|
stderr,
|
|
115712
116163
|
exitCode: code ?? 0
|
|
@@ -115714,7 +116165,7 @@ async function executeWithTimeout(command, args2, options) {
|
|
|
115714
116165
|
});
|
|
115715
116166
|
child.on("error", (err2) => {
|
|
115716
116167
|
clearTimeout(timeout);
|
|
115717
|
-
|
|
116168
|
+
resolve47({
|
|
115718
116169
|
stdout,
|
|
115719
116170
|
stderr: err2.message,
|
|
115720
116171
|
exitCode: 1
|
|
@@ -115728,12 +116179,12 @@ async function runSemgrep(options) {
|
|
|
115728
116179
|
const timeoutMs = options.timeoutMs || DEFAULT_TIMEOUT_MS3;
|
|
115729
116180
|
if (files.length === 0) {
|
|
115730
116181
|
return {
|
|
115731
|
-
available:
|
|
116182
|
+
available: _internals57.isSemgrepAvailable(),
|
|
115732
116183
|
findings: [],
|
|
115733
116184
|
engine: "tier_a"
|
|
115734
116185
|
};
|
|
115735
116186
|
}
|
|
115736
|
-
if (!
|
|
116187
|
+
if (!_internals57.isSemgrepAvailable()) {
|
|
115737
116188
|
return {
|
|
115738
116189
|
available: false,
|
|
115739
116190
|
findings: [],
|
|
@@ -115789,14 +116240,14 @@ async function runSemgrep(options) {
|
|
|
115789
116240
|
}
|
|
115790
116241
|
function getRulesDirectory(projectRoot) {
|
|
115791
116242
|
if (projectRoot) {
|
|
115792
|
-
return
|
|
116243
|
+
return path130.resolve(projectRoot, DEFAULT_RULES_DIR);
|
|
115793
116244
|
}
|
|
115794
116245
|
return DEFAULT_RULES_DIR;
|
|
115795
116246
|
}
|
|
115796
116247
|
function hasBundledRules(projectRoot) {
|
|
115797
116248
|
const rulesDir = getRulesDirectory(projectRoot);
|
|
115798
116249
|
try {
|
|
115799
|
-
return
|
|
116250
|
+
return fs93.existsSync(rulesDir);
|
|
115800
116251
|
} catch {
|
|
115801
116252
|
return false;
|
|
115802
116253
|
}
|
|
@@ -115809,25 +116260,25 @@ init_create_tool();
|
|
|
115809
116260
|
// src/tools/sast-baseline.ts
|
|
115810
116261
|
init_utils2();
|
|
115811
116262
|
import * as crypto11 from "node:crypto";
|
|
115812
|
-
import * as
|
|
115813
|
-
import * as
|
|
116263
|
+
import * as fs94 from "node:fs";
|
|
116264
|
+
import * as path131 from "node:path";
|
|
115814
116265
|
var BASELINE_SCHEMA_VERSION = "1.0.0";
|
|
115815
116266
|
var MAX_BASELINE_FINDINGS = 2000;
|
|
115816
116267
|
var MAX_BASELINE_BYTES = 2 * 1048576;
|
|
115817
116268
|
var LOCK_RETRY_DELAYS_MS = [50, 100, 200, 400, 800];
|
|
115818
116269
|
function normalizeFindingPath(directory, file3) {
|
|
115819
|
-
const resolved =
|
|
115820
|
-
const rel =
|
|
116270
|
+
const resolved = path131.isAbsolute(file3) ? file3 : path131.resolve(directory, file3);
|
|
116271
|
+
const rel = path131.relative(path131.resolve(directory), resolved);
|
|
115821
116272
|
return rel.replace(/\\/g, "/");
|
|
115822
116273
|
}
|
|
115823
116274
|
function baselineRelPath(phase) {
|
|
115824
|
-
return
|
|
116275
|
+
return path131.join("evidence", String(phase), "sast-baseline.json");
|
|
115825
116276
|
}
|
|
115826
116277
|
function tempRelPath(phase) {
|
|
115827
|
-
return
|
|
116278
|
+
return path131.join("evidence", String(phase), `sast-baseline.json.tmp.${Date.now()}.${process.pid}`);
|
|
115828
116279
|
}
|
|
115829
116280
|
function lockRelPath(phase) {
|
|
115830
|
-
return
|
|
116281
|
+
return path131.join("evidence", String(phase), "sast-baseline.json.lock");
|
|
115831
116282
|
}
|
|
115832
116283
|
function getLine(lines, idx) {
|
|
115833
116284
|
if (idx < 0 || idx >= lines.length)
|
|
@@ -115844,7 +116295,7 @@ function fingerprintFinding(finding, directory, occurrenceIndex) {
|
|
|
115844
116295
|
}
|
|
115845
116296
|
const lineNum = finding.location.line;
|
|
115846
116297
|
try {
|
|
115847
|
-
const content =
|
|
116298
|
+
const content = fs94.readFileSync(finding.location.file, "utf-8");
|
|
115848
116299
|
const lines = content.split(`
|
|
115849
116300
|
`);
|
|
115850
116301
|
const idx = lineNum - 1;
|
|
@@ -115875,7 +116326,7 @@ function assignOccurrenceIndices(findings, directory) {
|
|
|
115875
116326
|
try {
|
|
115876
116327
|
if (relFile.startsWith(".."))
|
|
115877
116328
|
throw new Error("escapes workspace");
|
|
115878
|
-
const content =
|
|
116329
|
+
const content = fs94.readFileSync(finding.location.file, "utf-8");
|
|
115879
116330
|
const lines = content.split(`
|
|
115880
116331
|
`);
|
|
115881
116332
|
const idx = lineNum - 1;
|
|
@@ -115892,7 +116343,7 @@ function assignOccurrenceIndices(findings, directory) {
|
|
|
115892
116343
|
}
|
|
115893
116344
|
const occIdx = countMap.get(baseKey) ?? 0;
|
|
115894
116345
|
countMap.set(baseKey, occIdx + 1);
|
|
115895
|
-
const fp =
|
|
116346
|
+
const fp = _internals58.fingerprintFinding(finding, directory, occIdx);
|
|
115896
116347
|
return {
|
|
115897
116348
|
finding,
|
|
115898
116349
|
index: occIdx,
|
|
@@ -115904,16 +116355,16 @@ function assignOccurrenceIndices(findings, directory) {
|
|
|
115904
116355
|
async function acquireLock2(lockPath) {
|
|
115905
116356
|
for (let attempt = 0;attempt <= LOCK_RETRY_DELAYS_MS.length; attempt++) {
|
|
115906
116357
|
try {
|
|
115907
|
-
const fd =
|
|
115908
|
-
|
|
116358
|
+
const fd = fs94.openSync(lockPath, "wx");
|
|
116359
|
+
fs94.closeSync(fd);
|
|
115909
116360
|
return () => {
|
|
115910
116361
|
try {
|
|
115911
|
-
|
|
116362
|
+
fs94.unlinkSync(lockPath);
|
|
115912
116363
|
} catch {}
|
|
115913
116364
|
};
|
|
115914
116365
|
} catch {
|
|
115915
116366
|
if (attempt < LOCK_RETRY_DELAYS_MS.length) {
|
|
115916
|
-
await new Promise((
|
|
116367
|
+
await new Promise((resolve48) => setTimeout(resolve48, LOCK_RETRY_DELAYS_MS[attempt]));
|
|
115917
116368
|
}
|
|
115918
116369
|
}
|
|
115919
116370
|
}
|
|
@@ -115948,20 +116399,20 @@ async function captureOrMergeBaseline(directory, phase, findings, engine, scanne
|
|
|
115948
116399
|
message: e instanceof Error ? e.message : "Path validation failed"
|
|
115949
116400
|
};
|
|
115950
116401
|
}
|
|
115951
|
-
|
|
115952
|
-
|
|
116402
|
+
fs94.mkdirSync(path131.dirname(baselinePath), { recursive: true });
|
|
116403
|
+
fs94.mkdirSync(path131.dirname(tempPath), { recursive: true });
|
|
115953
116404
|
const releaseLock = await acquireLock2(lockPath);
|
|
115954
116405
|
try {
|
|
115955
116406
|
let existing = null;
|
|
115956
116407
|
try {
|
|
115957
|
-
const raw =
|
|
116408
|
+
const raw = fs94.readFileSync(baselinePath, "utf-8");
|
|
115958
116409
|
const parsed = JSON.parse(raw);
|
|
115959
116410
|
if (parsed.schema_version === BASELINE_SCHEMA_VERSION) {
|
|
115960
116411
|
existing = parsed;
|
|
115961
116412
|
}
|
|
115962
116413
|
} catch {}
|
|
115963
116414
|
const scannedRelFiles = new Set(scannedFiles.map((f) => normalizeFindingPath(directory, f)));
|
|
115964
|
-
const indexed =
|
|
116415
|
+
const indexed = _internals58.assignOccurrenceIndices(findings, directory);
|
|
115965
116416
|
if (existing && !opts?.force) {
|
|
115966
116417
|
const prunedFingerprints = existing.fingerprints.filter((fp) => {
|
|
115967
116418
|
const relFile = fp.slice(0, fp.indexOf("|"));
|
|
@@ -116014,8 +116465,8 @@ async function captureOrMergeBaseline(directory, phase, findings, engine, scanne
|
|
|
116014
116465
|
message: `Baseline would exceed size cap (${json4.length} bytes > ${MAX_BASELINE_BYTES})`
|
|
116015
116466
|
};
|
|
116016
116467
|
}
|
|
116017
|
-
|
|
116018
|
-
|
|
116468
|
+
fs94.writeFileSync(tempPath, json4, "utf-8");
|
|
116469
|
+
fs94.renameSync(tempPath, baselinePath);
|
|
116019
116470
|
return {
|
|
116020
116471
|
status: "merged",
|
|
116021
116472
|
path: baselinePath,
|
|
@@ -116046,8 +116497,8 @@ async function captureOrMergeBaseline(directory, phase, findings, engine, scanne
|
|
|
116046
116497
|
message: `Baseline would exceed size cap (${json3.length} bytes > ${MAX_BASELINE_BYTES})`
|
|
116047
116498
|
};
|
|
116048
116499
|
}
|
|
116049
|
-
|
|
116050
|
-
|
|
116500
|
+
fs94.writeFileSync(tempPath, json3, "utf-8");
|
|
116501
|
+
fs94.renameSync(tempPath, baselinePath);
|
|
116051
116502
|
return {
|
|
116052
116503
|
status: "written",
|
|
116053
116504
|
path: baselinePath,
|
|
@@ -116072,7 +116523,7 @@ function loadBaseline(directory, phase) {
|
|
|
116072
116523
|
};
|
|
116073
116524
|
}
|
|
116074
116525
|
try {
|
|
116075
|
-
const raw =
|
|
116526
|
+
const raw = fs94.readFileSync(baselinePath, "utf-8");
|
|
116076
116527
|
const parsed = JSON.parse(raw);
|
|
116077
116528
|
if (parsed.schema_version !== BASELINE_SCHEMA_VERSION) {
|
|
116078
116529
|
return {
|
|
@@ -116101,7 +116552,7 @@ function loadBaseline(directory, phase) {
|
|
|
116101
116552
|
};
|
|
116102
116553
|
}
|
|
116103
116554
|
}
|
|
116104
|
-
var
|
|
116555
|
+
var _internals58 = {
|
|
116105
116556
|
fingerprintFinding,
|
|
116106
116557
|
assignOccurrenceIndices,
|
|
116107
116558
|
captureOrMergeBaseline,
|
|
@@ -116120,17 +116571,17 @@ var SEVERITY_ORDER = {
|
|
|
116120
116571
|
};
|
|
116121
116572
|
function shouldSkipFile(filePath) {
|
|
116122
116573
|
try {
|
|
116123
|
-
const stats =
|
|
116574
|
+
const stats = fs95.statSync(filePath);
|
|
116124
116575
|
if (stats.size > MAX_FILE_SIZE_BYTES8) {
|
|
116125
116576
|
return { skip: true, reason: "file too large" };
|
|
116126
116577
|
}
|
|
116127
116578
|
if (stats.size === 0) {
|
|
116128
116579
|
return { skip: true, reason: "empty file" };
|
|
116129
116580
|
}
|
|
116130
|
-
const fd =
|
|
116581
|
+
const fd = fs95.openSync(filePath, "r");
|
|
116131
116582
|
const buffer = Buffer.alloc(8192);
|
|
116132
|
-
const bytesRead =
|
|
116133
|
-
|
|
116583
|
+
const bytesRead = fs95.readSync(fd, buffer, 0, 8192, 0);
|
|
116584
|
+
fs95.closeSync(fd);
|
|
116134
116585
|
if (bytesRead > 0) {
|
|
116135
116586
|
let nullCount = 0;
|
|
116136
116587
|
for (let i2 = 0;i2 < bytesRead; i2++) {
|
|
@@ -116169,7 +116620,7 @@ function countBySeverity(findings) {
|
|
|
116169
116620
|
}
|
|
116170
116621
|
function scanFileWithTierA(filePath, language) {
|
|
116171
116622
|
try {
|
|
116172
|
-
const content =
|
|
116623
|
+
const content = fs95.readFileSync(filePath, "utf-8");
|
|
116173
116624
|
const findings = executeRulesSync(filePath, content, language);
|
|
116174
116625
|
return findings.map((f) => ({
|
|
116175
116626
|
rule_id: f.rule_id,
|
|
@@ -116222,13 +116673,13 @@ async function sastScan(input, directory, config3) {
|
|
|
116222
116673
|
_filesSkipped++;
|
|
116223
116674
|
continue;
|
|
116224
116675
|
}
|
|
116225
|
-
const resolvedPath =
|
|
116226
|
-
const resolvedDirectory =
|
|
116227
|
-
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) {
|
|
116228
116679
|
_filesSkipped++;
|
|
116229
116680
|
continue;
|
|
116230
116681
|
}
|
|
116231
|
-
if (!
|
|
116682
|
+
if (!fs95.existsSync(resolvedPath)) {
|
|
116232
116683
|
_filesSkipped++;
|
|
116233
116684
|
continue;
|
|
116234
116685
|
}
|
|
@@ -116511,11 +116962,11 @@ var sast_scan = createSwarmTool({
|
|
|
116511
116962
|
capture_baseline: safeArgs.capture_baseline,
|
|
116512
116963
|
phase: safeArgs.phase
|
|
116513
116964
|
};
|
|
116514
|
-
const result = await
|
|
116965
|
+
const result = await _internals59.sastScan(input, directory);
|
|
116515
116966
|
return JSON.stringify(result, null, 2);
|
|
116516
116967
|
}
|
|
116517
116968
|
});
|
|
116518
|
-
var
|
|
116969
|
+
var _internals59 = {
|
|
116519
116970
|
sastScan,
|
|
116520
116971
|
sast_scan
|
|
116521
116972
|
};
|
|
@@ -116539,20 +116990,20 @@ function validatePath(inputPath, baseDir, workspaceDir) {
|
|
|
116539
116990
|
let resolved;
|
|
116540
116991
|
const isWinAbs = isWindowsAbsolutePath(inputPath);
|
|
116541
116992
|
if (isWinAbs) {
|
|
116542
|
-
resolved =
|
|
116543
|
-
} else if (
|
|
116544
|
-
resolved =
|
|
116993
|
+
resolved = path133.win32.resolve(inputPath);
|
|
116994
|
+
} else if (path133.isAbsolute(inputPath)) {
|
|
116995
|
+
resolved = path133.resolve(inputPath);
|
|
116545
116996
|
} else {
|
|
116546
|
-
resolved =
|
|
116997
|
+
resolved = path133.resolve(baseDir, inputPath);
|
|
116547
116998
|
}
|
|
116548
|
-
const workspaceResolved =
|
|
116549
|
-
let
|
|
116999
|
+
const workspaceResolved = path133.resolve(workspaceDir);
|
|
117000
|
+
let relative27;
|
|
116550
117001
|
if (isWinAbs) {
|
|
116551
|
-
|
|
117002
|
+
relative27 = path133.win32.relative(workspaceResolved, resolved);
|
|
116552
117003
|
} else {
|
|
116553
|
-
|
|
117004
|
+
relative27 = path133.relative(workspaceResolved, resolved);
|
|
116554
117005
|
}
|
|
116555
|
-
if (
|
|
117006
|
+
if (relative27.startsWith("..")) {
|
|
116556
117007
|
return "path traversal detected";
|
|
116557
117008
|
}
|
|
116558
117009
|
return null;
|
|
@@ -116615,7 +117066,7 @@ async function runLintOnFiles(linter, files, workspaceDir) {
|
|
|
116615
117066
|
if (typeof file3 !== "string") {
|
|
116616
117067
|
continue;
|
|
116617
117068
|
}
|
|
116618
|
-
const resolvedPath =
|
|
117069
|
+
const resolvedPath = path133.resolve(file3);
|
|
116619
117070
|
const validationError = validatePath(resolvedPath, workspaceDir, workspaceDir);
|
|
116620
117071
|
if (validationError) {
|
|
116621
117072
|
continue;
|
|
@@ -116772,7 +117223,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
116772
117223
|
skippedFiles++;
|
|
116773
117224
|
continue;
|
|
116774
117225
|
}
|
|
116775
|
-
const resolvedPath =
|
|
117226
|
+
const resolvedPath = path133.resolve(file3);
|
|
116776
117227
|
const validationError = validatePath(resolvedPath, directory, directory);
|
|
116777
117228
|
if (validationError) {
|
|
116778
117229
|
skippedFiles++;
|
|
@@ -116790,14 +117241,14 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
116790
117241
|
};
|
|
116791
117242
|
}
|
|
116792
117243
|
for (const file3 of validatedFiles) {
|
|
116793
|
-
const ext =
|
|
117244
|
+
const ext = path133.extname(file3).toLowerCase();
|
|
116794
117245
|
if (DEFAULT_EXCLUDE_EXTENSIONS2.has(ext)) {
|
|
116795
117246
|
skippedFiles++;
|
|
116796
117247
|
continue;
|
|
116797
117248
|
}
|
|
116798
117249
|
let stat9;
|
|
116799
117250
|
try {
|
|
116800
|
-
stat9 =
|
|
117251
|
+
stat9 = fs96.statSync(file3);
|
|
116801
117252
|
} catch {
|
|
116802
117253
|
skippedFiles++;
|
|
116803
117254
|
continue;
|
|
@@ -116808,7 +117259,7 @@ async function runSecretscanWithFiles(files, directory) {
|
|
|
116808
117259
|
}
|
|
116809
117260
|
let content;
|
|
116810
117261
|
try {
|
|
116811
|
-
const buffer =
|
|
117262
|
+
const buffer = fs96.readFileSync(file3);
|
|
116812
117263
|
if (buffer.includes(0)) {
|
|
116813
117264
|
skippedFiles++;
|
|
116814
117265
|
continue;
|
|
@@ -117009,7 +117460,7 @@ function classifySastFindings(findings, changedLineRanges, directory) {
|
|
|
117009
117460
|
const preexistingFindings = [];
|
|
117010
117461
|
for (const finding of findings) {
|
|
117011
117462
|
const filePath = finding.location.file;
|
|
117012
|
-
const normalised =
|
|
117463
|
+
const normalised = path133.relative(directory, filePath).replace(/\\/g, "/");
|
|
117013
117464
|
const changedLines = changedLineRanges.get(normalised);
|
|
117014
117465
|
if (changedLines?.has(finding.location.line)) {
|
|
117015
117466
|
newFindings.push(finding);
|
|
@@ -117060,7 +117511,7 @@ async function runPreCheckBatch(input, workspaceDir, contextDir) {
|
|
|
117060
117511
|
warn(`pre_check_batch: Invalid file path: ${file3}`);
|
|
117061
117512
|
continue;
|
|
117062
117513
|
}
|
|
117063
|
-
changedFiles.push(
|
|
117514
|
+
changedFiles.push(path133.resolve(directory, file3));
|
|
117064
117515
|
}
|
|
117065
117516
|
if (changedFiles.length === 0) {
|
|
117066
117517
|
warn("pre_check_batch: No valid files after validation, skipping all tools (fail-closed)");
|
|
@@ -117261,9 +117712,9 @@ var pre_check_batch = createSwarmTool({
|
|
|
117261
117712
|
};
|
|
117262
117713
|
return JSON.stringify(errorResult, null, 2);
|
|
117263
117714
|
}
|
|
117264
|
-
const resolvedDirectory =
|
|
117265
|
-
const workspaceAnchor =
|
|
117266
|
-
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)) {
|
|
117267
117718
|
const subDirError = `directory "${typedArgs.directory}" is a subdirectory of the project root — pre_check_batch requires the project root directory "${workspaceAnchor}"`;
|
|
117268
117719
|
const subDirResult = {
|
|
117269
117720
|
gates_passed: false,
|
|
@@ -117314,7 +117765,7 @@ var pre_check_batch = createSwarmTool({
|
|
|
117314
117765
|
});
|
|
117315
117766
|
// src/tools/repo-map.ts
|
|
117316
117767
|
init_zod();
|
|
117317
|
-
import * as
|
|
117768
|
+
import * as path134 from "node:path";
|
|
117318
117769
|
init_path_security();
|
|
117319
117770
|
init_create_tool();
|
|
117320
117771
|
var VALID_ACTIONS = [
|
|
@@ -117339,7 +117790,7 @@ function validateFile(p) {
|
|
|
117339
117790
|
return "file contains control characters";
|
|
117340
117791
|
if (containsPathTraversal(p))
|
|
117341
117792
|
return "file contains path traversal";
|
|
117342
|
-
if (
|
|
117793
|
+
if (path134.isAbsolute(p) || /^[a-zA-Z]:[\\/]/.test(p)) {
|
|
117343
117794
|
return "file must be a workspace-relative path, not absolute";
|
|
117344
117795
|
}
|
|
117345
117796
|
return null;
|
|
@@ -117362,8 +117813,8 @@ function ok(action, payload) {
|
|
|
117362
117813
|
}
|
|
117363
117814
|
function toRelativeGraphPath(input, workspaceRoot) {
|
|
117364
117815
|
const normalized = input.replace(/\\/g, "/");
|
|
117365
|
-
if (
|
|
117366
|
-
const rel =
|
|
117816
|
+
if (path134.isAbsolute(normalized)) {
|
|
117817
|
+
const rel = path134.relative(workspaceRoot, normalized).replace(/\\/g, "/");
|
|
117367
117818
|
return normalizeGraphPath2(rel);
|
|
117368
117819
|
}
|
|
117369
117820
|
return normalizeGraphPath2(normalized);
|
|
@@ -117507,8 +117958,8 @@ var repo_map = createSwarmTool({
|
|
|
117507
117958
|
// src/tools/req-coverage.ts
|
|
117508
117959
|
init_zod();
|
|
117509
117960
|
init_create_tool();
|
|
117510
|
-
import * as
|
|
117511
|
-
import * as
|
|
117961
|
+
import * as fs97 from "node:fs";
|
|
117962
|
+
import * as path135 from "node:path";
|
|
117512
117963
|
var SPEC_FILE = ".swarm/spec.md";
|
|
117513
117964
|
var EVIDENCE_DIR4 = ".swarm/evidence";
|
|
117514
117965
|
var OBLIGATION_KEYWORDS = ["MUST", "SHOULD", "SHALL"];
|
|
@@ -117567,19 +118018,19 @@ function extractObligationAndText(id, lineText) {
|
|
|
117567
118018
|
var PHASE_TASK_ID_REGEX = /^\d+\.\d+(\.\d+)*$/;
|
|
117568
118019
|
function readTouchedFiles(evidenceDir, phase, cwd) {
|
|
117569
118020
|
const touchedFiles = new Set;
|
|
117570
|
-
if (!
|
|
118021
|
+
if (!fs97.existsSync(evidenceDir) || !fs97.statSync(evidenceDir).isDirectory()) {
|
|
117571
118022
|
return [];
|
|
117572
118023
|
}
|
|
117573
118024
|
let entries;
|
|
117574
118025
|
try {
|
|
117575
|
-
entries =
|
|
118026
|
+
entries = fs97.readdirSync(evidenceDir);
|
|
117576
118027
|
} catch {
|
|
117577
118028
|
return [];
|
|
117578
118029
|
}
|
|
117579
118030
|
for (const entry of entries) {
|
|
117580
|
-
const entryPath =
|
|
118031
|
+
const entryPath = path135.join(evidenceDir, entry);
|
|
117581
118032
|
try {
|
|
117582
|
-
const stat9 =
|
|
118033
|
+
const stat9 = fs97.statSync(entryPath);
|
|
117583
118034
|
if (!stat9.isDirectory()) {
|
|
117584
118035
|
continue;
|
|
117585
118036
|
}
|
|
@@ -117593,14 +118044,14 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
|
|
|
117593
118044
|
if (entryPhase !== String(phase)) {
|
|
117594
118045
|
continue;
|
|
117595
118046
|
}
|
|
117596
|
-
const evidenceFilePath =
|
|
118047
|
+
const evidenceFilePath = path135.join(entryPath, "evidence.json");
|
|
117597
118048
|
try {
|
|
117598
|
-
const resolvedPath =
|
|
117599
|
-
const evidenceDirResolved =
|
|
117600
|
-
if (!resolvedPath.startsWith(evidenceDirResolved +
|
|
118049
|
+
const resolvedPath = path135.resolve(evidenceFilePath);
|
|
118050
|
+
const evidenceDirResolved = path135.resolve(evidenceDir);
|
|
118051
|
+
if (!resolvedPath.startsWith(evidenceDirResolved + path135.sep)) {
|
|
117601
118052
|
continue;
|
|
117602
118053
|
}
|
|
117603
|
-
const stat9 =
|
|
118054
|
+
const stat9 = fs97.lstatSync(evidenceFilePath);
|
|
117604
118055
|
if (!stat9.isFile()) {
|
|
117605
118056
|
continue;
|
|
117606
118057
|
}
|
|
@@ -117612,7 +118063,7 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
|
|
|
117612
118063
|
}
|
|
117613
118064
|
let content;
|
|
117614
118065
|
try {
|
|
117615
|
-
content =
|
|
118066
|
+
content = fs97.readFileSync(evidenceFilePath, "utf-8");
|
|
117616
118067
|
} catch {
|
|
117617
118068
|
continue;
|
|
117618
118069
|
}
|
|
@@ -117631,7 +118082,7 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
|
|
|
117631
118082
|
if (Array.isArray(diffEntry.files_changed)) {
|
|
117632
118083
|
for (const file3 of diffEntry.files_changed) {
|
|
117633
118084
|
if (typeof file3 === "string") {
|
|
117634
|
-
touchedFiles.add(
|
|
118085
|
+
touchedFiles.add(path135.resolve(cwd, file3));
|
|
117635
118086
|
}
|
|
117636
118087
|
}
|
|
117637
118088
|
}
|
|
@@ -117644,12 +118095,12 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
|
|
|
117644
118095
|
}
|
|
117645
118096
|
function searchFileForKeywords(filePath, keywords, cwd) {
|
|
117646
118097
|
try {
|
|
117647
|
-
const resolvedPath =
|
|
117648
|
-
const cwdResolved =
|
|
118098
|
+
const resolvedPath = path135.resolve(filePath);
|
|
118099
|
+
const cwdResolved = path135.resolve(cwd);
|
|
117649
118100
|
if (!resolvedPath.startsWith(cwdResolved)) {
|
|
117650
118101
|
return false;
|
|
117651
118102
|
}
|
|
117652
|
-
const content =
|
|
118103
|
+
const content = fs97.readFileSync(resolvedPath, "utf-8");
|
|
117653
118104
|
for (const keyword of keywords) {
|
|
117654
118105
|
const regex = new RegExp(`\\b${keyword}\\b`, "i");
|
|
117655
118106
|
if (regex.test(content)) {
|
|
@@ -117779,10 +118230,10 @@ var req_coverage = createSwarmTool({
|
|
|
117779
118230
|
}, null, 2);
|
|
117780
118231
|
}
|
|
117781
118232
|
const cwd = inputDirectory || directory;
|
|
117782
|
-
const specPath =
|
|
118233
|
+
const specPath = path135.join(cwd, SPEC_FILE);
|
|
117783
118234
|
let specContent;
|
|
117784
118235
|
try {
|
|
117785
|
-
specContent =
|
|
118236
|
+
specContent = fs97.readFileSync(specPath, "utf-8");
|
|
117786
118237
|
} catch (readError) {
|
|
117787
118238
|
return JSON.stringify({
|
|
117788
118239
|
success: false,
|
|
@@ -117806,7 +118257,7 @@ var req_coverage = createSwarmTool({
|
|
|
117806
118257
|
message: "No FR requirements found in spec.md"
|
|
117807
118258
|
}, null, 2);
|
|
117808
118259
|
}
|
|
117809
|
-
const evidenceDir =
|
|
118260
|
+
const evidenceDir = path135.join(cwd, EVIDENCE_DIR4);
|
|
117810
118261
|
const touchedFiles = readTouchedFiles(evidenceDir, phase, cwd);
|
|
117811
118262
|
const analyzedRequirements = [];
|
|
117812
118263
|
let coveredCount = 0;
|
|
@@ -117832,12 +118283,12 @@ var req_coverage = createSwarmTool({
|
|
|
117832
118283
|
requirements: analyzedRequirements
|
|
117833
118284
|
};
|
|
117834
118285
|
const reportFilename = `req-coverage-phase-${phase}.json`;
|
|
117835
|
-
const reportPath =
|
|
118286
|
+
const reportPath = path135.join(evidenceDir, reportFilename);
|
|
117836
118287
|
try {
|
|
117837
|
-
if (!
|
|
117838
|
-
|
|
118288
|
+
if (!fs97.existsSync(evidenceDir)) {
|
|
118289
|
+
fs97.mkdirSync(evidenceDir, { recursive: true });
|
|
117839
118290
|
}
|
|
117840
|
-
|
|
118291
|
+
fs97.writeFileSync(reportPath, JSON.stringify(result, null, 2), "utf-8");
|
|
117841
118292
|
} catch (writeError) {
|
|
117842
118293
|
console.warn(`Failed to write coverage report: ${writeError instanceof Error ? writeError.message : String(writeError)}`);
|
|
117843
118294
|
}
|
|
@@ -117919,8 +118370,8 @@ init_plan_schema();
|
|
|
117919
118370
|
init_qa_gate_profile();
|
|
117920
118371
|
init_file_locks();
|
|
117921
118372
|
import * as crypto12 from "node:crypto";
|
|
117922
|
-
import * as
|
|
117923
|
-
import * as
|
|
118373
|
+
import * as fs98 from "node:fs";
|
|
118374
|
+
import * as path136 from "node:path";
|
|
117924
118375
|
init_ledger();
|
|
117925
118376
|
init_manager();
|
|
117926
118377
|
init_state();
|
|
@@ -118001,17 +118452,17 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
118001
118452
|
};
|
|
118002
118453
|
}
|
|
118003
118454
|
if (args2.working_directory && fallbackDir) {
|
|
118004
|
-
const resolvedTarget =
|
|
118005
|
-
const resolvedRoot =
|
|
118455
|
+
const resolvedTarget = path136.resolve(args2.working_directory);
|
|
118456
|
+
const resolvedRoot = path136.resolve(fallbackDir);
|
|
118006
118457
|
let fallbackExists = false;
|
|
118007
118458
|
try {
|
|
118008
|
-
|
|
118459
|
+
fs98.accessSync(resolvedRoot, fs98.constants.F_OK);
|
|
118009
118460
|
fallbackExists = true;
|
|
118010
118461
|
} catch {
|
|
118011
118462
|
fallbackExists = false;
|
|
118012
118463
|
}
|
|
118013
118464
|
if (fallbackExists) {
|
|
118014
|
-
const isSubdirectory = resolvedTarget.startsWith(resolvedRoot +
|
|
118465
|
+
const isSubdirectory = resolvedTarget.startsWith(resolvedRoot + path136.sep);
|
|
118015
118466
|
if (isSubdirectory) {
|
|
118016
118467
|
return {
|
|
118017
118468
|
success: false,
|
|
@@ -118027,11 +118478,11 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
118027
118478
|
let specMtime;
|
|
118028
118479
|
let specHash;
|
|
118029
118480
|
if (process.env.SWARM_SKIP_SPEC_GATE !== "1") {
|
|
118030
|
-
const specPath =
|
|
118481
|
+
const specPath = path136.join(targetWorkspace, ".swarm", "spec.md");
|
|
118031
118482
|
try {
|
|
118032
|
-
const stat9 = await
|
|
118483
|
+
const stat9 = await fs98.promises.stat(specPath);
|
|
118033
118484
|
specMtime = stat9.mtime.toISOString();
|
|
118034
|
-
const content = await
|
|
118485
|
+
const content = await fs98.promises.readFile(specPath, "utf8");
|
|
118035
118486
|
specHash = crypto12.createHash("sha256").update(content).digest("hex");
|
|
118036
118487
|
} catch {
|
|
118037
118488
|
return {
|
|
@@ -118043,10 +118494,10 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
118043
118494
|
}
|
|
118044
118495
|
}
|
|
118045
118496
|
if (process.env.SWARM_SKIP_GATE_SELECTION !== "1") {
|
|
118046
|
-
const contextPath =
|
|
118497
|
+
const contextPath = path136.join(targetWorkspace, ".swarm", "context.md");
|
|
118047
118498
|
let contextContent = "";
|
|
118048
118499
|
try {
|
|
118049
|
-
contextContent = await
|
|
118500
|
+
contextContent = await fs98.promises.readFile(contextPath, "utf8");
|
|
118050
118501
|
} catch {}
|
|
118051
118502
|
const hasPendingSection = contextContent.includes("## Pending QA Gate Selection");
|
|
118052
118503
|
if (!hasPendingSection) {
|
|
@@ -118333,14 +118784,14 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
118333
118784
|
}
|
|
118334
118785
|
await writeCheckpoint(dir).catch(() => {});
|
|
118335
118786
|
try {
|
|
118336
|
-
const markerPath =
|
|
118787
|
+
const markerPath = path136.join(dir, ".swarm", ".plan-write-marker");
|
|
118337
118788
|
const marker = JSON.stringify({
|
|
118338
118789
|
source: "save_plan",
|
|
118339
118790
|
timestamp: new Date().toISOString(),
|
|
118340
118791
|
phases_count: plan.phases.length,
|
|
118341
118792
|
tasks_count: tasksCount
|
|
118342
118793
|
});
|
|
118343
|
-
await
|
|
118794
|
+
await fs98.promises.writeFile(markerPath, marker, "utf8");
|
|
118344
118795
|
} catch {}
|
|
118345
118796
|
const warnings = [];
|
|
118346
118797
|
let criticReviewFound = false;
|
|
@@ -118356,7 +118807,7 @@ async function executeSavePlan(args2, fallbackDir) {
|
|
|
118356
118807
|
return {
|
|
118357
118808
|
success: true,
|
|
118358
118809
|
message: "Plan saved successfully",
|
|
118359
|
-
plan_path:
|
|
118810
|
+
plan_path: path136.join(dir, ".swarm", "plan.json"),
|
|
118360
118811
|
phases_count: plan.phases.length,
|
|
118361
118812
|
tasks_count: tasksCount,
|
|
118362
118813
|
...resolvedProfile !== undefined ? { execution_profile: resolvedProfile } : {},
|
|
@@ -118421,8 +118872,8 @@ var save_plan = createSwarmTool({
|
|
|
118421
118872
|
// src/tools/sbom-generate.ts
|
|
118422
118873
|
init_zod();
|
|
118423
118874
|
init_manager2();
|
|
118424
|
-
import * as
|
|
118425
|
-
import * as
|
|
118875
|
+
import * as fs99 from "node:fs";
|
|
118876
|
+
import * as path137 from "node:path";
|
|
118426
118877
|
|
|
118427
118878
|
// src/sbom/detectors/index.ts
|
|
118428
118879
|
init_utils();
|
|
@@ -119270,9 +119721,9 @@ function findManifestFiles(rootDir) {
|
|
|
119270
119721
|
const patterns = [...new Set(allDetectors.flatMap((d) => d.patterns))];
|
|
119271
119722
|
function searchDir(dir) {
|
|
119272
119723
|
try {
|
|
119273
|
-
const entries =
|
|
119724
|
+
const entries = fs99.readdirSync(dir, { withFileTypes: true });
|
|
119274
119725
|
for (const entry of entries) {
|
|
119275
|
-
const fullPath =
|
|
119726
|
+
const fullPath = path137.join(dir, entry.name);
|
|
119276
119727
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "target") {
|
|
119277
119728
|
continue;
|
|
119278
119729
|
}
|
|
@@ -119281,7 +119732,7 @@ function findManifestFiles(rootDir) {
|
|
|
119281
119732
|
} else if (entry.isFile()) {
|
|
119282
119733
|
for (const pattern of patterns) {
|
|
119283
119734
|
if (simpleGlobToRegex(pattern).test(entry.name)) {
|
|
119284
|
-
manifestFiles.push(
|
|
119735
|
+
manifestFiles.push(path137.relative(rootDir, fullPath));
|
|
119285
119736
|
break;
|
|
119286
119737
|
}
|
|
119287
119738
|
}
|
|
@@ -119297,13 +119748,13 @@ function findManifestFilesInDirs(directories, workingDir) {
|
|
|
119297
119748
|
const patterns = [...new Set(allDetectors.flatMap((d) => d.patterns))];
|
|
119298
119749
|
for (const dir of directories) {
|
|
119299
119750
|
try {
|
|
119300
|
-
const entries =
|
|
119751
|
+
const entries = fs99.readdirSync(dir, { withFileTypes: true });
|
|
119301
119752
|
for (const entry of entries) {
|
|
119302
|
-
const fullPath =
|
|
119753
|
+
const fullPath = path137.join(dir, entry.name);
|
|
119303
119754
|
if (entry.isFile()) {
|
|
119304
119755
|
for (const pattern of patterns) {
|
|
119305
119756
|
if (simpleGlobToRegex(pattern).test(entry.name)) {
|
|
119306
|
-
found.push(
|
|
119757
|
+
found.push(path137.relative(workingDir, fullPath));
|
|
119307
119758
|
break;
|
|
119308
119759
|
}
|
|
119309
119760
|
}
|
|
@@ -119316,11 +119767,11 @@ function findManifestFilesInDirs(directories, workingDir) {
|
|
|
119316
119767
|
function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
|
|
119317
119768
|
const dirs = new Set;
|
|
119318
119769
|
for (const file3 of changedFiles) {
|
|
119319
|
-
let currentDir =
|
|
119770
|
+
let currentDir = path137.dirname(file3);
|
|
119320
119771
|
while (true) {
|
|
119321
|
-
if (currentDir && currentDir !== "." && currentDir !==
|
|
119322
|
-
dirs.add(
|
|
119323
|
-
const parent =
|
|
119772
|
+
if (currentDir && currentDir !== "." && currentDir !== path137.sep) {
|
|
119773
|
+
dirs.add(path137.join(workingDir, currentDir));
|
|
119774
|
+
const parent = path137.dirname(currentDir);
|
|
119324
119775
|
if (parent === currentDir)
|
|
119325
119776
|
break;
|
|
119326
119777
|
currentDir = parent;
|
|
@@ -119334,7 +119785,7 @@ function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
|
|
|
119334
119785
|
}
|
|
119335
119786
|
function ensureOutputDir(outputDir) {
|
|
119336
119787
|
try {
|
|
119337
|
-
|
|
119788
|
+
fs99.mkdirSync(outputDir, { recursive: true });
|
|
119338
119789
|
} catch (error93) {
|
|
119339
119790
|
if (!error93 || error93.code !== "EEXIST") {
|
|
119340
119791
|
throw error93;
|
|
@@ -119404,7 +119855,7 @@ var sbom_generate = createSwarmTool({
|
|
|
119404
119855
|
const changedFiles = obj.changed_files;
|
|
119405
119856
|
const relativeOutputDir = obj.output_dir || DEFAULT_OUTPUT_DIR;
|
|
119406
119857
|
const workingDir = directory;
|
|
119407
|
-
const outputDir =
|
|
119858
|
+
const outputDir = path137.isAbsolute(relativeOutputDir) ? relativeOutputDir : path137.join(workingDir, relativeOutputDir);
|
|
119408
119859
|
let manifestFiles = [];
|
|
119409
119860
|
if (scope === "all") {
|
|
119410
119861
|
manifestFiles = findManifestFiles(workingDir);
|
|
@@ -119427,11 +119878,11 @@ var sbom_generate = createSwarmTool({
|
|
|
119427
119878
|
const processedFiles = [];
|
|
119428
119879
|
for (const manifestFile of manifestFiles) {
|
|
119429
119880
|
try {
|
|
119430
|
-
const fullPath =
|
|
119431
|
-
if (!
|
|
119881
|
+
const fullPath = path137.isAbsolute(manifestFile) ? manifestFile : path137.join(workingDir, manifestFile);
|
|
119882
|
+
if (!fs99.existsSync(fullPath)) {
|
|
119432
119883
|
continue;
|
|
119433
119884
|
}
|
|
119434
|
-
const content =
|
|
119885
|
+
const content = fs99.readFileSync(fullPath, "utf-8");
|
|
119435
119886
|
const components = detectComponents(manifestFile, content);
|
|
119436
119887
|
processedFiles.push(manifestFile);
|
|
119437
119888
|
if (components.length > 0) {
|
|
@@ -119444,8 +119895,8 @@ var sbom_generate = createSwarmTool({
|
|
|
119444
119895
|
const bom = generateCycloneDX(allComponents);
|
|
119445
119896
|
const bomJson = serializeCycloneDX(bom);
|
|
119446
119897
|
const filename = generateSbomFilename();
|
|
119447
|
-
const outputPath =
|
|
119448
|
-
|
|
119898
|
+
const outputPath = path137.join(outputDir, filename);
|
|
119899
|
+
fs99.writeFileSync(outputPath, bomJson, "utf-8");
|
|
119449
119900
|
const verdict = processedFiles.length > 0 ? "pass" : "pass";
|
|
119450
119901
|
try {
|
|
119451
119902
|
const timestamp = new Date().toISOString();
|
|
@@ -119487,8 +119938,8 @@ var sbom_generate = createSwarmTool({
|
|
|
119487
119938
|
// src/tools/schema-drift.ts
|
|
119488
119939
|
init_zod();
|
|
119489
119940
|
init_create_tool();
|
|
119490
|
-
import * as
|
|
119491
|
-
import * as
|
|
119941
|
+
import * as fs100 from "node:fs";
|
|
119942
|
+
import * as path138 from "node:path";
|
|
119492
119943
|
var SPEC_CANDIDATES = [
|
|
119493
119944
|
"openapi.json",
|
|
119494
119945
|
"openapi.yaml",
|
|
@@ -119520,28 +119971,28 @@ function normalizePath4(p) {
|
|
|
119520
119971
|
}
|
|
119521
119972
|
function discoverSpecFile(cwd, specFileArg) {
|
|
119522
119973
|
if (specFileArg) {
|
|
119523
|
-
const resolvedPath =
|
|
119524
|
-
const normalizedCwd = cwd.endsWith(
|
|
119974
|
+
const resolvedPath = path138.resolve(cwd, specFileArg);
|
|
119975
|
+
const normalizedCwd = cwd.endsWith(path138.sep) ? cwd : cwd + path138.sep;
|
|
119525
119976
|
if (!resolvedPath.startsWith(normalizedCwd) && resolvedPath !== cwd) {
|
|
119526
119977
|
throw new Error("Invalid spec_file: path traversal detected");
|
|
119527
119978
|
}
|
|
119528
|
-
const ext =
|
|
119979
|
+
const ext = path138.extname(resolvedPath).toLowerCase();
|
|
119529
119980
|
if (!ALLOWED_EXTENSIONS.includes(ext)) {
|
|
119530
119981
|
throw new Error(`Invalid spec_file: must end in .json, .yaml, or .yml, got ${ext}`);
|
|
119531
119982
|
}
|
|
119532
|
-
const stats =
|
|
119983
|
+
const stats = fs100.statSync(resolvedPath);
|
|
119533
119984
|
if (stats.size > MAX_SPEC_SIZE) {
|
|
119534
119985
|
throw new Error(`Invalid spec_file: file exceeds ${MAX_SPEC_SIZE / 1024 / 1024}MB limit`);
|
|
119535
119986
|
}
|
|
119536
|
-
if (!
|
|
119987
|
+
if (!fs100.existsSync(resolvedPath)) {
|
|
119537
119988
|
throw new Error(`Spec file not found: ${resolvedPath}`);
|
|
119538
119989
|
}
|
|
119539
119990
|
return resolvedPath;
|
|
119540
119991
|
}
|
|
119541
119992
|
for (const candidate of SPEC_CANDIDATES) {
|
|
119542
|
-
const candidatePath =
|
|
119543
|
-
if (
|
|
119544
|
-
const stats =
|
|
119993
|
+
const candidatePath = path138.resolve(cwd, candidate);
|
|
119994
|
+
if (fs100.existsSync(candidatePath)) {
|
|
119995
|
+
const stats = fs100.statSync(candidatePath);
|
|
119545
119996
|
if (stats.size <= MAX_SPEC_SIZE) {
|
|
119546
119997
|
return candidatePath;
|
|
119547
119998
|
}
|
|
@@ -119550,8 +120001,8 @@ function discoverSpecFile(cwd, specFileArg) {
|
|
|
119550
120001
|
return null;
|
|
119551
120002
|
}
|
|
119552
120003
|
function parseSpec(specFile) {
|
|
119553
|
-
const content =
|
|
119554
|
-
const ext =
|
|
120004
|
+
const content = fs100.readFileSync(specFile, "utf-8");
|
|
120005
|
+
const ext = path138.extname(specFile).toLowerCase();
|
|
119555
120006
|
if (ext === ".json") {
|
|
119556
120007
|
return parseJsonSpec(content);
|
|
119557
120008
|
}
|
|
@@ -119622,12 +120073,12 @@ function extractRoutes(cwd) {
|
|
|
119622
120073
|
function walkDir(dir) {
|
|
119623
120074
|
let entries;
|
|
119624
120075
|
try {
|
|
119625
|
-
entries =
|
|
120076
|
+
entries = fs100.readdirSync(dir, { withFileTypes: true });
|
|
119626
120077
|
} catch {
|
|
119627
120078
|
return;
|
|
119628
120079
|
}
|
|
119629
120080
|
for (const entry of entries) {
|
|
119630
|
-
const fullPath =
|
|
120081
|
+
const fullPath = path138.join(dir, entry.name);
|
|
119631
120082
|
if (entry.isSymbolicLink()) {
|
|
119632
120083
|
continue;
|
|
119633
120084
|
}
|
|
@@ -119637,7 +120088,7 @@ function extractRoutes(cwd) {
|
|
|
119637
120088
|
}
|
|
119638
120089
|
walkDir(fullPath);
|
|
119639
120090
|
} else if (entry.isFile()) {
|
|
119640
|
-
const ext =
|
|
120091
|
+
const ext = path138.extname(entry.name).toLowerCase();
|
|
119641
120092
|
const baseName = entry.name.toLowerCase();
|
|
119642
120093
|
if (![".ts", ".js", ".mjs"].includes(ext)) {
|
|
119643
120094
|
continue;
|
|
@@ -119655,7 +120106,7 @@ function extractRoutes(cwd) {
|
|
|
119655
120106
|
}
|
|
119656
120107
|
function extractRoutesFromFile(filePath) {
|
|
119657
120108
|
const routes = [];
|
|
119658
|
-
const content =
|
|
120109
|
+
const content = fs100.readFileSync(filePath, "utf-8");
|
|
119659
120110
|
const lines = content.split(/\r?\n/);
|
|
119660
120111
|
const expressRegex = /(?:app|router|server|express)\.(get|post|put|patch|delete|options|head)\s*\(\s*['"`]([^'"`]+)['"`]/g;
|
|
119661
120112
|
const flaskRegex = /@(?:app|blueprint|bp)\.route\s*\(\s*['"]([^'"]+)['"]/g;
|
|
@@ -119804,8 +120255,8 @@ init_zod();
|
|
|
119804
120255
|
init_bun_compat();
|
|
119805
120256
|
init_path_security();
|
|
119806
120257
|
init_create_tool();
|
|
119807
|
-
import * as
|
|
119808
|
-
import * as
|
|
120258
|
+
import * as fs101 from "node:fs";
|
|
120259
|
+
import * as path139 from "node:path";
|
|
119809
120260
|
var DEFAULT_MAX_RESULTS = 100;
|
|
119810
120261
|
var DEFAULT_MAX_LINES = 200;
|
|
119811
120262
|
var REGEX_TIMEOUT_MS = 5000;
|
|
@@ -119841,11 +120292,11 @@ function containsWindowsAttacks3(str) {
|
|
|
119841
120292
|
}
|
|
119842
120293
|
function isPathInWorkspace3(filePath, workspace) {
|
|
119843
120294
|
try {
|
|
119844
|
-
const resolvedPath =
|
|
119845
|
-
const realWorkspace =
|
|
119846
|
-
const realResolvedPath =
|
|
119847
|
-
const relativePath =
|
|
119848
|
-
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)) {
|
|
119849
120300
|
return false;
|
|
119850
120301
|
}
|
|
119851
120302
|
return true;
|
|
@@ -119858,12 +120309,12 @@ function validatePathForRead2(filePath, workspace) {
|
|
|
119858
120309
|
}
|
|
119859
120310
|
function findRgInEnvPath() {
|
|
119860
120311
|
const searchPath = process.env.PATH ?? "";
|
|
119861
|
-
for (const dir of searchPath.split(
|
|
120312
|
+
for (const dir of searchPath.split(path139.delimiter)) {
|
|
119862
120313
|
if (!dir)
|
|
119863
120314
|
continue;
|
|
119864
120315
|
const isWindows = process.platform === "win32";
|
|
119865
|
-
const candidate =
|
|
119866
|
-
if (
|
|
120316
|
+
const candidate = path139.join(dir, isWindows ? "rg.exe" : "rg");
|
|
120317
|
+
if (fs101.existsSync(candidate))
|
|
119867
120318
|
return candidate;
|
|
119868
120319
|
}
|
|
119869
120320
|
return null;
|
|
@@ -119917,7 +120368,7 @@ async function ripgrepSearch(opts) {
|
|
|
119917
120368
|
stderr: "pipe",
|
|
119918
120369
|
cwd: opts.workspace
|
|
119919
120370
|
});
|
|
119920
|
-
const timeout = new Promise((
|
|
120371
|
+
const timeout = new Promise((resolve54) => setTimeout(() => resolve54("timeout"), REGEX_TIMEOUT_MS));
|
|
119921
120372
|
const exitPromise = proc.exited;
|
|
119922
120373
|
const result = await Promise.race([exitPromise, timeout]);
|
|
119923
120374
|
if (result === "timeout") {
|
|
@@ -119990,10 +120441,10 @@ function collectFiles(dir, workspace, includeGlobs, excludeGlobs) {
|
|
|
119990
120441
|
return files;
|
|
119991
120442
|
}
|
|
119992
120443
|
try {
|
|
119993
|
-
const entries =
|
|
120444
|
+
const entries = fs101.readdirSync(dir, { withFileTypes: true });
|
|
119994
120445
|
for (const entry of entries) {
|
|
119995
|
-
const fullPath =
|
|
119996
|
-
const relativePath =
|
|
120446
|
+
const fullPath = path139.join(dir, entry.name);
|
|
120447
|
+
const relativePath = path139.relative(workspace, fullPath);
|
|
119997
120448
|
if (!validatePathForRead2(fullPath, workspace)) {
|
|
119998
120449
|
continue;
|
|
119999
120450
|
}
|
|
@@ -120034,13 +120485,13 @@ async function fallbackSearch(opts) {
|
|
|
120034
120485
|
const matches = [];
|
|
120035
120486
|
let total = 0;
|
|
120036
120487
|
for (const file3 of files) {
|
|
120037
|
-
const fullPath =
|
|
120488
|
+
const fullPath = path139.join(opts.workspace, file3);
|
|
120038
120489
|
if (!validatePathForRead2(fullPath, opts.workspace)) {
|
|
120039
120490
|
continue;
|
|
120040
120491
|
}
|
|
120041
120492
|
let stats;
|
|
120042
120493
|
try {
|
|
120043
|
-
stats =
|
|
120494
|
+
stats = fs101.statSync(fullPath);
|
|
120044
120495
|
if (stats.size > MAX_FILE_SIZE_BYTES10) {
|
|
120045
120496
|
continue;
|
|
120046
120497
|
}
|
|
@@ -120049,7 +120500,7 @@ async function fallbackSearch(opts) {
|
|
|
120049
120500
|
}
|
|
120050
120501
|
let content;
|
|
120051
120502
|
try {
|
|
120052
|
-
content =
|
|
120503
|
+
content = fs101.readFileSync(fullPath, "utf-8");
|
|
120053
120504
|
} catch {
|
|
120054
120505
|
continue;
|
|
120055
120506
|
}
|
|
@@ -120161,7 +120612,7 @@ var search = createSwarmTool({
|
|
|
120161
120612
|
message: "Exclude pattern contains invalid Windows-specific sequence"
|
|
120162
120613
|
}, null, 2);
|
|
120163
120614
|
}
|
|
120164
|
-
if (!
|
|
120615
|
+
if (!fs101.existsSync(directory)) {
|
|
120165
120616
|
return JSON.stringify({
|
|
120166
120617
|
error: true,
|
|
120167
120618
|
type: "unknown",
|
|
@@ -120439,7 +120890,7 @@ init_config();
|
|
|
120439
120890
|
init_schema();
|
|
120440
120891
|
init_create_tool();
|
|
120441
120892
|
import { mkdir as mkdir23, rename as rename9, writeFile as writeFile18 } from "node:fs/promises";
|
|
120442
|
-
import * as
|
|
120893
|
+
import * as path140 from "node:path";
|
|
120443
120894
|
var MAX_SPEC_BYTES = 256 * 1024;
|
|
120444
120895
|
var spec_write = createSwarmTool({
|
|
120445
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.",
|
|
@@ -120480,14 +120931,14 @@ var spec_write = createSwarmTool({
|
|
|
120480
120931
|
reason: 'spec must contain at least one top-level "# Heading"'
|
|
120481
120932
|
}, null, 2);
|
|
120482
120933
|
}
|
|
120483
|
-
const target =
|
|
120484
|
-
await mkdir23(
|
|
120934
|
+
const target = path140.join(directory, ".swarm", "spec.md");
|
|
120935
|
+
await mkdir23(path140.dirname(target), { recursive: true });
|
|
120485
120936
|
const tmp = `${target}.tmp-${process.pid}-${Date.now()}`;
|
|
120486
120937
|
let finalContent = content;
|
|
120487
120938
|
if (mode === "append") {
|
|
120488
120939
|
try {
|
|
120489
|
-
const
|
|
120490
|
-
const prior = await
|
|
120940
|
+
const fs102 = await import("node:fs/promises");
|
|
120941
|
+
const prior = await fs102.readFile(target, "utf-8");
|
|
120491
120942
|
finalContent = `${prior.replace(/\s+$/, "")}
|
|
120492
120943
|
|
|
120493
120944
|
${content}
|
|
@@ -120516,7 +120967,7 @@ import {
|
|
|
120516
120967
|
unlinkSync as unlinkSync18,
|
|
120517
120968
|
writeFileSync as writeFileSync28
|
|
120518
120969
|
} from "node:fs";
|
|
120519
|
-
import
|
|
120970
|
+
import path141 from "node:path";
|
|
120520
120971
|
init_create_tool();
|
|
120521
120972
|
init_resolve_working_directory();
|
|
120522
120973
|
var VerdictSchema2 = exports_external.object({
|
|
@@ -120646,7 +121097,7 @@ var submit_phase_council_verdicts = createSwarmTool({
|
|
|
120646
121097
|
}
|
|
120647
121098
|
});
|
|
120648
121099
|
function getPhaseMutationGapFinding(phaseNumber, workingDir) {
|
|
120649
|
-
const mutationGatePath =
|
|
121100
|
+
const mutationGatePath = path141.join(workingDir, ".swarm", "evidence", String(phaseNumber), "mutation-gate.json");
|
|
120650
121101
|
try {
|
|
120651
121102
|
const raw = readFileSync63(mutationGatePath, "utf-8");
|
|
120652
121103
|
const parsed = JSON.parse(raw);
|
|
@@ -120708,9 +121159,9 @@ function getPhaseMutationGapFinding(phaseNumber, workingDir) {
|
|
|
120708
121159
|
}
|
|
120709
121160
|
}
|
|
120710
121161
|
function writePhaseCouncilEvidence(workingDir, synthesis) {
|
|
120711
|
-
const evidenceDir =
|
|
121162
|
+
const evidenceDir = path141.join(workingDir, ".swarm", "evidence", String(synthesis.phaseNumber));
|
|
120712
121163
|
mkdirSync35(evidenceDir, { recursive: true });
|
|
120713
|
-
const evidenceFile =
|
|
121164
|
+
const evidenceFile = path141.join(evidenceDir, "phase-council.json");
|
|
120714
121165
|
const evidenceBundle = {
|
|
120715
121166
|
entries: [
|
|
120716
121167
|
{
|
|
@@ -120932,7 +121383,7 @@ var swarm_memory_propose = createSwarmTool({
|
|
|
120932
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")
|
|
120933
121384
|
},
|
|
120934
121385
|
execute: async (args2, directory, ctx) => {
|
|
120935
|
-
const { config: config3 } =
|
|
121386
|
+
const { config: config3 } = _internals60.loadPluginConfigWithMeta(directory);
|
|
120936
121387
|
if (config3.memory?.enabled !== true) {
|
|
120937
121388
|
return JSON.stringify({
|
|
120938
121389
|
success: false,
|
|
@@ -120948,7 +121399,7 @@ var swarm_memory_propose = createSwarmTool({
|
|
|
120948
121399
|
});
|
|
120949
121400
|
}
|
|
120950
121401
|
const agent = getContextAgent2(ctx);
|
|
120951
|
-
const gateway =
|
|
121402
|
+
const gateway = _internals60.createMemoryGateway({
|
|
120952
121403
|
directory,
|
|
120953
121404
|
sessionID: ctx?.sessionID,
|
|
120954
121405
|
agentRole: agent,
|
|
@@ -120973,7 +121424,7 @@ var swarm_memory_propose = createSwarmTool({
|
|
|
120973
121424
|
}
|
|
120974
121425
|
}
|
|
120975
121426
|
});
|
|
120976
|
-
var
|
|
121427
|
+
var _internals60 = {
|
|
120977
121428
|
loadPluginConfigWithMeta,
|
|
120978
121429
|
createMemoryGateway
|
|
120979
121430
|
};
|
|
@@ -121010,7 +121461,7 @@ var swarm_memory_recall = createSwarmTool({
|
|
|
121010
121461
|
maxItems: exports_external.number().int().min(1).max(20).optional().describe("Maximum memories to return")
|
|
121011
121462
|
},
|
|
121012
121463
|
execute: async (args2, directory, ctx) => {
|
|
121013
|
-
const { config: config3 } =
|
|
121464
|
+
const { config: config3 } = _internals61.loadPluginConfigWithMeta(directory);
|
|
121014
121465
|
if (config3.memory?.enabled !== true) {
|
|
121015
121466
|
return JSON.stringify({
|
|
121016
121467
|
success: false,
|
|
@@ -121026,7 +121477,7 @@ var swarm_memory_recall = createSwarmTool({
|
|
|
121026
121477
|
});
|
|
121027
121478
|
}
|
|
121028
121479
|
const agent = getContextAgent3(ctx);
|
|
121029
|
-
const gateway =
|
|
121480
|
+
const gateway = _internals61.createMemoryGateway({
|
|
121030
121481
|
directory,
|
|
121031
121482
|
sessionID: ctx?.sessionID,
|
|
121032
121483
|
agentRole: agent,
|
|
@@ -121059,7 +121510,7 @@ var RecallArgsSchema = exports_external.object({
|
|
|
121059
121510
|
kinds: exports_external.array(exports_external.enum(MEMORY_KINDS2)).optional(),
|
|
121060
121511
|
maxItems: exports_external.number().int().min(1).max(20).optional()
|
|
121061
121512
|
});
|
|
121062
|
-
var
|
|
121513
|
+
var _internals61 = {
|
|
121063
121514
|
loadPluginConfigWithMeta,
|
|
121064
121515
|
createMemoryGateway
|
|
121065
121516
|
};
|
|
@@ -121079,7 +121530,7 @@ init_schema3();
|
|
|
121079
121530
|
init_store();
|
|
121080
121531
|
init_create_tool();
|
|
121081
121532
|
init_resolve_working_directory();
|
|
121082
|
-
import * as
|
|
121533
|
+
import * as path142 from "node:path";
|
|
121083
121534
|
var FindingSchema2 = exports_external.object({
|
|
121084
121535
|
severity: exports_external.enum(["low", "medium", "high", "critical"]),
|
|
121085
121536
|
category: exports_external.string().min(1),
|
|
@@ -121143,7 +121594,7 @@ var write_architecture_supervisor_evidence = createSwarmTool({
|
|
|
121143
121594
|
if (config3.architectural_supervision?.persist_knowledge_recommendations && args2.knowledge_recommendations.length > 0) {
|
|
121144
121595
|
const knowledgeConfig = KnowledgeConfigSchema.parse(config3.knowledge ?? {});
|
|
121145
121596
|
const lessons = args2.knowledge_recommendations.map((r) => r.lesson);
|
|
121146
|
-
const result = await curateAndStoreSwarm(lessons,
|
|
121597
|
+
const result = await curateAndStoreSwarm(lessons, path142.basename(dirResult.directory), { phase_number: args2.phase }, dirResult.directory, knowledgeConfig, { skipAutoPromotion: true });
|
|
121147
121598
|
knowledgeProposed = result.stored;
|
|
121148
121599
|
}
|
|
121149
121600
|
} catch {}
|
|
@@ -121174,8 +121625,8 @@ var write_architecture_supervisor_evidence = createSwarmTool({
|
|
|
121174
121625
|
init_zod();
|
|
121175
121626
|
init_path_security();
|
|
121176
121627
|
init_create_tool();
|
|
121177
|
-
import * as
|
|
121178
|
-
import * as
|
|
121628
|
+
import * as fs102 from "node:fs";
|
|
121629
|
+
import * as path143 from "node:path";
|
|
121179
121630
|
var WINDOWS_RESERVED_NAMES4 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
|
|
121180
121631
|
function containsWindowsAttacks4(str) {
|
|
121181
121632
|
if (/:[^\\/]/.test(str))
|
|
@@ -121189,14 +121640,14 @@ function containsWindowsAttacks4(str) {
|
|
|
121189
121640
|
}
|
|
121190
121641
|
function isPathInWorkspace4(filePath, workspace) {
|
|
121191
121642
|
try {
|
|
121192
|
-
const resolvedPath =
|
|
121193
|
-
if (!
|
|
121643
|
+
const resolvedPath = path143.resolve(workspace, filePath);
|
|
121644
|
+
if (!fs102.existsSync(resolvedPath)) {
|
|
121194
121645
|
return true;
|
|
121195
121646
|
}
|
|
121196
|
-
const realWorkspace =
|
|
121197
|
-
const realResolvedPath =
|
|
121198
|
-
const relativePath =
|
|
121199
|
-
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)) {
|
|
121200
121651
|
return false;
|
|
121201
121652
|
}
|
|
121202
121653
|
return true;
|
|
@@ -121368,7 +121819,7 @@ var suggestPatch = createSwarmTool({
|
|
|
121368
121819
|
message: "changes cannot be empty"
|
|
121369
121820
|
}, null, 2);
|
|
121370
121821
|
}
|
|
121371
|
-
if (!
|
|
121822
|
+
if (!fs102.existsSync(directory)) {
|
|
121372
121823
|
return JSON.stringify({
|
|
121373
121824
|
success: false,
|
|
121374
121825
|
error: true,
|
|
@@ -121404,8 +121855,8 @@ var suggestPatch = createSwarmTool({
|
|
|
121404
121855
|
});
|
|
121405
121856
|
continue;
|
|
121406
121857
|
}
|
|
121407
|
-
const fullPath =
|
|
121408
|
-
if (!
|
|
121858
|
+
const fullPath = path143.resolve(directory, change.file);
|
|
121859
|
+
if (!fs102.existsSync(fullPath)) {
|
|
121409
121860
|
errors5.push({
|
|
121410
121861
|
success: false,
|
|
121411
121862
|
error: true,
|
|
@@ -121419,7 +121870,7 @@ var suggestPatch = createSwarmTool({
|
|
|
121419
121870
|
}
|
|
121420
121871
|
let content;
|
|
121421
121872
|
try {
|
|
121422
|
-
content =
|
|
121873
|
+
content = fs102.readFileSync(fullPath, "utf-8");
|
|
121423
121874
|
} catch (err3) {
|
|
121424
121875
|
errors5.push({
|
|
121425
121876
|
success: false,
|
|
@@ -121707,12 +122158,12 @@ var lean_turbo_acquire_locks = createSwarmTool({
|
|
|
121707
122158
|
// src/tools/lean-turbo-plan-lanes.ts
|
|
121708
122159
|
init_zod();
|
|
121709
122160
|
init_constants();
|
|
121710
|
-
import * as
|
|
121711
|
-
import * as
|
|
122161
|
+
import * as fs104 from "node:fs";
|
|
122162
|
+
import * as path145 from "node:path";
|
|
121712
122163
|
|
|
121713
122164
|
// src/turbo/lean/conflicts.ts
|
|
121714
|
-
import * as
|
|
121715
|
-
import * as
|
|
122165
|
+
import * as fs103 from "node:fs";
|
|
122166
|
+
import * as path144 from "node:path";
|
|
121716
122167
|
var DEFAULT_GLOBAL_FILES = [
|
|
121717
122168
|
"package.json",
|
|
121718
122169
|
"package-lock.json",
|
|
@@ -121839,12 +122290,12 @@ function isProtectedPath2(normalizedPath) {
|
|
|
121839
122290
|
return false;
|
|
121840
122291
|
}
|
|
121841
122292
|
function readTaskScopes(directory, taskId) {
|
|
121842
|
-
const scopePath =
|
|
122293
|
+
const scopePath = path144.join(directory, ".swarm", "scopes", `scope-${taskId}.json`);
|
|
121843
122294
|
try {
|
|
121844
|
-
if (!
|
|
122295
|
+
if (!fs103.existsSync(scopePath)) {
|
|
121845
122296
|
return null;
|
|
121846
122297
|
}
|
|
121847
|
-
const raw =
|
|
122298
|
+
const raw = fs103.readFileSync(scopePath, "utf-8");
|
|
121848
122299
|
const parsed = JSON.parse(raw);
|
|
121849
122300
|
if (!parsed || !Array.isArray(parsed.files)) {
|
|
121850
122301
|
return null;
|
|
@@ -122227,12 +122678,12 @@ function createEmptyPlan(phaseNumber, planId) {
|
|
|
122227
122678
|
// src/tools/lean-turbo-plan-lanes.ts
|
|
122228
122679
|
init_create_tool();
|
|
122229
122680
|
function readPlanJson(directory) {
|
|
122230
|
-
const planPath =
|
|
122231
|
-
if (!
|
|
122681
|
+
const planPath = path145.join(directory, ".swarm", "plan.json");
|
|
122682
|
+
if (!fs104.existsSync(planPath)) {
|
|
122232
122683
|
return null;
|
|
122233
122684
|
}
|
|
122234
122685
|
try {
|
|
122235
|
-
return JSON.parse(
|
|
122686
|
+
return JSON.parse(fs104.readFileSync(planPath, "utf-8"));
|
|
122236
122687
|
} catch {
|
|
122237
122688
|
return null;
|
|
122238
122689
|
}
|
|
@@ -122281,8 +122732,8 @@ init_config();
|
|
|
122281
122732
|
|
|
122282
122733
|
// src/turbo/lean/reviewer.ts
|
|
122283
122734
|
init_state();
|
|
122284
|
-
import * as
|
|
122285
|
-
import * as
|
|
122735
|
+
import * as fs105 from "node:fs/promises";
|
|
122736
|
+
import * as path146 from "node:path";
|
|
122286
122737
|
init_state3();
|
|
122287
122738
|
var DEFAULT_CONFIG3 = {
|
|
122288
122739
|
reviewerAgent: "",
|
|
@@ -122304,7 +122755,7 @@ function resolveDefaultReviewerAgent(generatedAgentNames) {
|
|
|
122304
122755
|
}
|
|
122305
122756
|
async function compileReviewPackage(directory, phase, sessionID, requireDiffSummary) {
|
|
122306
122757
|
const lanes = await listLaneEvidence(directory, phase);
|
|
122307
|
-
const persisted =
|
|
122758
|
+
const persisted = _internals62.readPersisted?.(directory) ?? null;
|
|
122308
122759
|
if (persisted) {
|
|
122309
122760
|
let matchingRunState = null;
|
|
122310
122761
|
for (const sessionState of Object.values(persisted.sessions)) {
|
|
@@ -122398,9 +122849,9 @@ function parseReviewerVerdict(responseText) {
|
|
|
122398
122849
|
return { verdict, reason };
|
|
122399
122850
|
}
|
|
122400
122851
|
async function writeReviewerEvidence(directory, phase, verdict, reason) {
|
|
122401
|
-
const evidenceDir =
|
|
122402
|
-
await
|
|
122403
|
-
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");
|
|
122404
122855
|
const content = JSON.stringify({
|
|
122405
122856
|
phase,
|
|
122406
122857
|
verdict,
|
|
@@ -122409,11 +122860,11 @@ async function writeReviewerEvidence(directory, phase, verdict, reason) {
|
|
|
122409
122860
|
}, null, 2);
|
|
122410
122861
|
const tempPath = `${evidencePath}.tmp.${process.pid}.${Date.now()}`;
|
|
122411
122862
|
try {
|
|
122412
|
-
await
|
|
122413
|
-
await
|
|
122863
|
+
await fs105.writeFile(tempPath, content, "utf-8");
|
|
122864
|
+
await fs105.rename(tempPath, evidencePath);
|
|
122414
122865
|
} catch (error93) {
|
|
122415
122866
|
try {
|
|
122416
|
-
await
|
|
122867
|
+
await fs105.unlink(tempPath);
|
|
122417
122868
|
} catch {}
|
|
122418
122869
|
throw error93;
|
|
122419
122870
|
}
|
|
@@ -122496,7 +122947,7 @@ Be specific and evidence-based. Do not approve a phase with unresolved degraded
|
|
|
122496
122947
|
client.session.delete({ path: { id: sessionId } }).catch(() => {});
|
|
122497
122948
|
}
|
|
122498
122949
|
}
|
|
122499
|
-
var
|
|
122950
|
+
var _internals62 = {
|
|
122500
122951
|
compileReviewPackage,
|
|
122501
122952
|
parseReviewerVerdict,
|
|
122502
122953
|
writeReviewerEvidence,
|
|
@@ -122513,28 +122964,28 @@ async function dispatchPhaseReviewer(directory, phase, sessionID, config3) {
|
|
|
122513
122964
|
};
|
|
122514
122965
|
const generatedAgentNames = swarmState.generatedAgentNames;
|
|
122515
122966
|
const agentName = mergedConfig.reviewerAgent || resolveDefaultReviewerAgent(generatedAgentNames);
|
|
122516
|
-
const pkg = await
|
|
122967
|
+
const pkg = await _internals62.compileReviewPackage(directory, phase, sessionID, mergedConfig.requireDiffSummary);
|
|
122517
122968
|
let responseText;
|
|
122518
122969
|
try {
|
|
122519
|
-
responseText = await
|
|
122970
|
+
responseText = await _internals62.dispatchReviewerAgent(directory, pkg, agentName, mergedConfig.timeoutMs);
|
|
122520
122971
|
} catch (error93) {
|
|
122521
|
-
const evidencePath2 = await
|
|
122972
|
+
const evidencePath2 = await _internals62.writeReviewerEvidence(directory, phase, "REJECTED", error93 instanceof Error ? error93.message : String(error93));
|
|
122522
122973
|
return {
|
|
122523
122974
|
verdict: "REJECTED",
|
|
122524
122975
|
reason: `Reviewer dispatch failed: ${error93 instanceof Error ? error93.message : String(error93)}`,
|
|
122525
122976
|
evidencePath: evidencePath2
|
|
122526
122977
|
};
|
|
122527
122978
|
}
|
|
122528
|
-
const parsed =
|
|
122979
|
+
const parsed = _internals62.parseReviewerVerdict(responseText);
|
|
122529
122980
|
if (!parsed) {
|
|
122530
|
-
const evidencePath2 = await
|
|
122981
|
+
const evidencePath2 = await _internals62.writeReviewerEvidence(directory, phase, "REJECTED", "Reviewer response could not be parsed");
|
|
122531
122982
|
return {
|
|
122532
122983
|
verdict: "REJECTED",
|
|
122533
122984
|
reason: "Reviewer response could not be parsed",
|
|
122534
122985
|
evidencePath: evidencePath2
|
|
122535
122986
|
};
|
|
122536
122987
|
}
|
|
122537
|
-
const evidencePath = await
|
|
122988
|
+
const evidencePath = await _internals62.writeReviewerEvidence(directory, phase, parsed.verdict, parsed.reason);
|
|
122538
122989
|
return {
|
|
122539
122990
|
verdict: parsed.verdict,
|
|
122540
122991
|
reason: parsed.reason,
|
|
@@ -123040,7 +123491,7 @@ ${fileList}
|
|
|
123040
123491
|
|
|
123041
123492
|
// src/tools/lean-turbo-run-phase.ts
|
|
123042
123493
|
init_create_tool();
|
|
123043
|
-
var
|
|
123494
|
+
var _internals63 = {
|
|
123044
123495
|
LeanTurboRunner,
|
|
123045
123496
|
loadPluginConfigWithMeta
|
|
123046
123497
|
};
|
|
@@ -123050,9 +123501,9 @@ async function executeLeanTurboRunPhase(args2) {
|
|
|
123050
123501
|
let runError = null;
|
|
123051
123502
|
let runner = null;
|
|
123052
123503
|
try {
|
|
123053
|
-
const { config: config3 } =
|
|
123504
|
+
const { config: config3 } = _internals63.loadPluginConfigWithMeta(directory);
|
|
123054
123505
|
const leanConfig = config3.turbo?.strategy === "lean" ? config3.turbo.lean : undefined;
|
|
123055
|
-
runner = new
|
|
123506
|
+
runner = new _internals63.LeanTurboRunner({
|
|
123056
123507
|
directory,
|
|
123057
123508
|
sessionID,
|
|
123058
123509
|
opencodeClient: swarmState.opencodeClient ?? null,
|
|
@@ -123204,8 +123655,8 @@ var lean_turbo_status = createSwarmTool({
|
|
|
123204
123655
|
// src/tools/lint-spec.ts
|
|
123205
123656
|
init_spec_schema();
|
|
123206
123657
|
init_create_tool();
|
|
123207
|
-
import * as
|
|
123208
|
-
import * as
|
|
123658
|
+
import * as fs106 from "node:fs";
|
|
123659
|
+
import * as path147 from "node:path";
|
|
123209
123660
|
var SPEC_FILE_NAME = "spec.md";
|
|
123210
123661
|
var SWARM_DIR2 = ".swarm";
|
|
123211
123662
|
var OBLIGATION_KEYWORDS2 = ["MUST", "SHALL", "SHOULD", "MAY"];
|
|
@@ -123258,8 +123709,8 @@ var lint_spec = createSwarmTool({
|
|
|
123258
123709
|
async execute(_args, directory) {
|
|
123259
123710
|
const errors5 = [];
|
|
123260
123711
|
const warnings = [];
|
|
123261
|
-
const specPath =
|
|
123262
|
-
if (!
|
|
123712
|
+
const specPath = path147.join(directory, SWARM_DIR2, SPEC_FILE_NAME);
|
|
123713
|
+
if (!fs106.existsSync(specPath)) {
|
|
123263
123714
|
const result2 = {
|
|
123264
123715
|
valid: false,
|
|
123265
123716
|
specMtime: null,
|
|
@@ -123278,12 +123729,12 @@ var lint_spec = createSwarmTool({
|
|
|
123278
123729
|
}
|
|
123279
123730
|
let specMtime = null;
|
|
123280
123731
|
try {
|
|
123281
|
-
const stats =
|
|
123732
|
+
const stats = fs106.statSync(specPath);
|
|
123282
123733
|
specMtime = stats.mtime.toISOString();
|
|
123283
123734
|
} catch {}
|
|
123284
123735
|
let content;
|
|
123285
123736
|
try {
|
|
123286
|
-
content =
|
|
123737
|
+
content = fs106.readFileSync(specPath, "utf-8");
|
|
123287
123738
|
} catch (e) {
|
|
123288
123739
|
const result2 = {
|
|
123289
123740
|
valid: false,
|
|
@@ -123328,13 +123779,13 @@ var lint_spec = createSwarmTool({
|
|
|
123328
123779
|
});
|
|
123329
123780
|
// src/tools/mutation-test.ts
|
|
123330
123781
|
init_zod();
|
|
123331
|
-
import * as
|
|
123332
|
-
import * as
|
|
123782
|
+
import * as fs107 from "node:fs";
|
|
123783
|
+
import * as path149 from "node:path";
|
|
123333
123784
|
|
|
123334
123785
|
// src/mutation/engine.ts
|
|
123335
123786
|
import { spawnSync as spawnSync8 } from "node:child_process";
|
|
123336
123787
|
import { unlinkSync as unlinkSync19, writeFileSync as writeFileSync29 } from "node:fs";
|
|
123337
|
-
import * as
|
|
123788
|
+
import * as path148 from "node:path";
|
|
123338
123789
|
|
|
123339
123790
|
// src/mutation/equivalence.ts
|
|
123340
123791
|
function isStaticallyEquivalent(originalCode, mutatedCode) {
|
|
@@ -123406,7 +123857,7 @@ function isStaticallyEquivalent(originalCode, mutatedCode) {
|
|
|
123406
123857
|
const strippedMutated = stripCode(mutatedCode);
|
|
123407
123858
|
return strippedOriginal === strippedMutated;
|
|
123408
123859
|
}
|
|
123409
|
-
var
|
|
123860
|
+
var _internals64 = {
|
|
123410
123861
|
isStaticallyEquivalent,
|
|
123411
123862
|
checkEquivalence,
|
|
123412
123863
|
batchCheckEquivalence
|
|
@@ -123446,7 +123897,7 @@ async function batchCheckEquivalence(patches, llmJudge) {
|
|
|
123446
123897
|
const results = [];
|
|
123447
123898
|
for (const { patch, originalCode, mutatedCode } of patches) {
|
|
123448
123899
|
try {
|
|
123449
|
-
const result = await
|
|
123900
|
+
const result = await _internals64.checkEquivalence(patch, originalCode, mutatedCode, llmJudge);
|
|
123450
123901
|
results.push(result);
|
|
123451
123902
|
} catch (err3) {
|
|
123452
123903
|
results.push({
|
|
@@ -123465,7 +123916,7 @@ async function batchCheckEquivalence(patches, llmJudge) {
|
|
|
123465
123916
|
var MUTATION_TIMEOUT_MS = 30000;
|
|
123466
123917
|
var TOTAL_BUDGET_MS = 300000;
|
|
123467
123918
|
var GIT_APPLY_TIMEOUT_MS = 5000;
|
|
123468
|
-
var
|
|
123919
|
+
var _internals65 = {
|
|
123469
123920
|
executeMutation,
|
|
123470
123921
|
computeReport,
|
|
123471
123922
|
executeMutationSuite,
|
|
@@ -123480,7 +123931,7 @@ async function executeMutation(patch, testCommand, _testFiles, workingDir) {
|
|
|
123480
123931
|
let patchFile;
|
|
123481
123932
|
try {
|
|
123482
123933
|
const safeId2 = patch.id.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
123483
|
-
patchFile =
|
|
123934
|
+
patchFile = path148.join(workingDir, `.mutation_patch_${safeId2}.diff`);
|
|
123484
123935
|
try {
|
|
123485
123936
|
writeFileSync29(patchFile, patch.patch);
|
|
123486
123937
|
} catch (writeErr) {
|
|
@@ -123497,7 +123948,7 @@ async function executeMutation(patch, testCommand, _testFiles, workingDir) {
|
|
|
123497
123948
|
};
|
|
123498
123949
|
}
|
|
123499
123950
|
try {
|
|
123500
|
-
const applyResult =
|
|
123951
|
+
const applyResult = _internals65.spawnSync("git", ["apply", "--", patchFile], {
|
|
123501
123952
|
cwd: workingDir,
|
|
123502
123953
|
timeout: GIT_APPLY_TIMEOUT_MS,
|
|
123503
123954
|
stdio: "pipe"
|
|
@@ -123526,7 +123977,7 @@ async function executeMutation(patch, testCommand, _testFiles, workingDir) {
|
|
|
123526
123977
|
}
|
|
123527
123978
|
let testPassed = false;
|
|
123528
123979
|
try {
|
|
123529
|
-
const spawnResult =
|
|
123980
|
+
const spawnResult = _internals65.spawnSync(testCommand[0], testCommand.slice(1), {
|
|
123530
123981
|
cwd: workingDir,
|
|
123531
123982
|
timeout: MUTATION_TIMEOUT_MS,
|
|
123532
123983
|
stdio: "pipe"
|
|
@@ -123559,7 +124010,7 @@ async function executeMutation(patch, testCommand, _testFiles, workingDir) {
|
|
|
123559
124010
|
} finally {
|
|
123560
124011
|
if (patchFile) {
|
|
123561
124012
|
try {
|
|
123562
|
-
const revertResult =
|
|
124013
|
+
const revertResult = _internals65.spawnSync("git", ["apply", "-R", "--", patchFile], {
|
|
123563
124014
|
cwd: workingDir,
|
|
123564
124015
|
timeout: GIT_APPLY_TIMEOUT_MS,
|
|
123565
124016
|
stdio: "pipe"
|
|
@@ -123752,7 +124203,7 @@ async function executeMutationSuite(patches, testCommand, testFiles, workingDir,
|
|
|
123752
124203
|
}
|
|
123753
124204
|
|
|
123754
124205
|
// src/mutation/gate.ts
|
|
123755
|
-
var
|
|
124206
|
+
var _internals66 = {
|
|
123756
124207
|
evaluateMutationGate,
|
|
123757
124208
|
buildTestImprovementPrompt,
|
|
123758
124209
|
buildMessage
|
|
@@ -123773,8 +124224,8 @@ function evaluateMutationGate(report, passThreshold = PASS_THRESHOLD, warnThresh
|
|
|
123773
124224
|
} else {
|
|
123774
124225
|
verdict = "fail";
|
|
123775
124226
|
}
|
|
123776
|
-
const testImprovementPrompt =
|
|
123777
|
-
const message =
|
|
124227
|
+
const testImprovementPrompt = _internals66.buildTestImprovementPrompt(report, passThreshold, verdict);
|
|
124228
|
+
const message = _internals66.buildMessage(verdict, adjustedKillRate, report.killed, report.totalMutants, report.equivalent, warnThreshold);
|
|
123778
124229
|
return {
|
|
123779
124230
|
verdict,
|
|
123780
124231
|
killRate: report.killRate,
|
|
@@ -123884,8 +124335,8 @@ var mutation_test = createSwarmTool({
|
|
|
123884
124335
|
];
|
|
123885
124336
|
for (const filePath of uniquePaths) {
|
|
123886
124337
|
try {
|
|
123887
|
-
const resolvedPath =
|
|
123888
|
-
sourceFiles.set(filePath,
|
|
124338
|
+
const resolvedPath = path149.resolve(cwd, filePath);
|
|
124339
|
+
sourceFiles.set(filePath, fs107.readFileSync(resolvedPath, "utf-8"));
|
|
123889
124340
|
} catch {}
|
|
123890
124341
|
}
|
|
123891
124342
|
const report = await executeMutationSuite(typedArgs.patches, typedArgs.test_command, typedArgs.files, cwd, undefined, undefined, sourceFiles.size > 0 ? sourceFiles : undefined);
|
|
@@ -123903,8 +124354,8 @@ var mutation_test = createSwarmTool({
|
|
|
123903
124354
|
init_zod();
|
|
123904
124355
|
init_manager2();
|
|
123905
124356
|
init_detector();
|
|
123906
|
-
import * as
|
|
123907
|
-
import * as
|
|
124357
|
+
import * as fs108 from "node:fs";
|
|
124358
|
+
import * as path150 from "node:path";
|
|
123908
124359
|
init_create_tool();
|
|
123909
124360
|
var MAX_FILE_SIZE2 = 2 * 1024 * 1024;
|
|
123910
124361
|
var BINARY_CHECK_BYTES = 8192;
|
|
@@ -123970,7 +124421,7 @@ async function syntaxCheck(input, directory, config3) {
|
|
|
123970
124421
|
if (languages?.length) {
|
|
123971
124422
|
const lowerLangs = languages.map((l) => l.toLowerCase());
|
|
123972
124423
|
filesToCheck = filesToCheck.filter((file3) => {
|
|
123973
|
-
const ext =
|
|
124424
|
+
const ext = path150.extname(file3.path).toLowerCase();
|
|
123974
124425
|
const langDef = getLanguageForExtension(ext);
|
|
123975
124426
|
const fileProfile = getProfileForFile(file3.path);
|
|
123976
124427
|
const langId = fileProfile?.id || langDef?.id;
|
|
@@ -123983,7 +124434,7 @@ async function syntaxCheck(input, directory, config3) {
|
|
|
123983
124434
|
let skippedCount = 0;
|
|
123984
124435
|
for (const fileInfo of filesToCheck) {
|
|
123985
124436
|
const { path: filePath } = fileInfo;
|
|
123986
|
-
const fullPath =
|
|
124437
|
+
const fullPath = path150.isAbsolute(filePath) ? filePath : path150.join(directory, filePath);
|
|
123987
124438
|
const result = {
|
|
123988
124439
|
path: filePath,
|
|
123989
124440
|
language: "",
|
|
@@ -124013,7 +124464,7 @@ async function syntaxCheck(input, directory, config3) {
|
|
|
124013
124464
|
}
|
|
124014
124465
|
let content;
|
|
124015
124466
|
try {
|
|
124016
|
-
content =
|
|
124467
|
+
content = fs108.readFileSync(fullPath, "utf8");
|
|
124017
124468
|
} catch {
|
|
124018
124469
|
result.skipped_reason = "file_read_error";
|
|
124019
124470
|
skippedCount++;
|
|
@@ -124032,7 +124483,7 @@ async function syntaxCheck(input, directory, config3) {
|
|
|
124032
124483
|
results.push(result);
|
|
124033
124484
|
continue;
|
|
124034
124485
|
}
|
|
124035
|
-
const ext =
|
|
124486
|
+
const ext = path150.extname(filePath).toLowerCase();
|
|
124036
124487
|
const langDef = getLanguageForExtension(ext);
|
|
124037
124488
|
result.language = profile?.id || langDef?.id || "unknown";
|
|
124038
124489
|
const errors5 = extractSyntaxErrors(parser, content);
|
|
@@ -124129,8 +124580,8 @@ init_zod();
|
|
|
124129
124580
|
init_utils();
|
|
124130
124581
|
init_create_tool();
|
|
124131
124582
|
init_path_security();
|
|
124132
|
-
import * as
|
|
124133
|
-
import * as
|
|
124583
|
+
import * as fs109 from "node:fs";
|
|
124584
|
+
import * as path151 from "node:path";
|
|
124134
124585
|
var MAX_TEXT_LENGTH = 200;
|
|
124135
124586
|
var MAX_FILE_SIZE_BYTES11 = 1024 * 1024;
|
|
124136
124587
|
var SUPPORTED_EXTENSIONS4 = new Set([
|
|
@@ -124196,9 +124647,9 @@ function validatePathsInput(paths, cwd) {
|
|
|
124196
124647
|
return { error: "paths contains path traversal", resolvedPath: null };
|
|
124197
124648
|
}
|
|
124198
124649
|
try {
|
|
124199
|
-
const resolvedPath =
|
|
124200
|
-
const normalizedCwd =
|
|
124201
|
-
const normalizedResolved =
|
|
124650
|
+
const resolvedPath = path151.resolve(paths);
|
|
124651
|
+
const normalizedCwd = path151.resolve(cwd);
|
|
124652
|
+
const normalizedResolved = path151.resolve(resolvedPath);
|
|
124202
124653
|
if (!normalizedResolved.startsWith(normalizedCwd)) {
|
|
124203
124654
|
return {
|
|
124204
124655
|
error: "paths must be within the current working directory",
|
|
@@ -124214,13 +124665,13 @@ function validatePathsInput(paths, cwd) {
|
|
|
124214
124665
|
}
|
|
124215
124666
|
}
|
|
124216
124667
|
function isSupportedExtension(filePath) {
|
|
124217
|
-
const ext =
|
|
124668
|
+
const ext = path151.extname(filePath).toLowerCase();
|
|
124218
124669
|
return SUPPORTED_EXTENSIONS4.has(ext);
|
|
124219
124670
|
}
|
|
124220
124671
|
function findSourceFiles3(dir, files = []) {
|
|
124221
124672
|
let entries;
|
|
124222
124673
|
try {
|
|
124223
|
-
entries =
|
|
124674
|
+
entries = fs109.readdirSync(dir);
|
|
124224
124675
|
} catch {
|
|
124225
124676
|
return files;
|
|
124226
124677
|
}
|
|
@@ -124229,10 +124680,10 @@ function findSourceFiles3(dir, files = []) {
|
|
|
124229
124680
|
if (SKIP_DIRECTORIES5.has(entry)) {
|
|
124230
124681
|
continue;
|
|
124231
124682
|
}
|
|
124232
|
-
const fullPath =
|
|
124683
|
+
const fullPath = path151.join(dir, entry);
|
|
124233
124684
|
let stat9;
|
|
124234
124685
|
try {
|
|
124235
|
-
stat9 =
|
|
124686
|
+
stat9 = fs109.statSync(fullPath);
|
|
124236
124687
|
} catch {
|
|
124237
124688
|
continue;
|
|
124238
124689
|
}
|
|
@@ -124325,7 +124776,7 @@ var todo_extract = createSwarmTool({
|
|
|
124325
124776
|
return JSON.stringify(errorResult, null, 2);
|
|
124326
124777
|
}
|
|
124327
124778
|
const scanPath = resolvedPath;
|
|
124328
|
-
if (!
|
|
124779
|
+
if (!fs109.existsSync(scanPath)) {
|
|
124329
124780
|
const errorResult = {
|
|
124330
124781
|
error: `path not found: ${pathsInput}`,
|
|
124331
124782
|
total: 0,
|
|
@@ -124335,13 +124786,13 @@ var todo_extract = createSwarmTool({
|
|
|
124335
124786
|
return JSON.stringify(errorResult, null, 2);
|
|
124336
124787
|
}
|
|
124337
124788
|
const filesToScan = [];
|
|
124338
|
-
const stat9 =
|
|
124789
|
+
const stat9 = fs109.statSync(scanPath);
|
|
124339
124790
|
if (stat9.isFile()) {
|
|
124340
124791
|
if (isSupportedExtension(scanPath)) {
|
|
124341
124792
|
filesToScan.push(scanPath);
|
|
124342
124793
|
} else {
|
|
124343
124794
|
const errorResult = {
|
|
124344
|
-
error: `unsupported file extension: ${
|
|
124795
|
+
error: `unsupported file extension: ${path151.extname(scanPath)}`,
|
|
124345
124796
|
total: 0,
|
|
124346
124797
|
byPriority: { high: 0, medium: 0, low: 0 },
|
|
124347
124798
|
entries: []
|
|
@@ -124354,11 +124805,11 @@ var todo_extract = createSwarmTool({
|
|
|
124354
124805
|
const allEntries = [];
|
|
124355
124806
|
for (const filePath of filesToScan) {
|
|
124356
124807
|
try {
|
|
124357
|
-
const fileStat =
|
|
124808
|
+
const fileStat = fs109.statSync(filePath);
|
|
124358
124809
|
if (fileStat.size > MAX_FILE_SIZE_BYTES11) {
|
|
124359
124810
|
continue;
|
|
124360
124811
|
}
|
|
124361
|
-
const content =
|
|
124812
|
+
const content = fs109.readFileSync(filePath, "utf-8");
|
|
124362
124813
|
const entries = parseTodoComments(content, filePath, tagsSet);
|
|
124363
124814
|
allEntries.push(...entries);
|
|
124364
124815
|
} catch {}
|
|
@@ -124389,19 +124840,19 @@ init_loader();
|
|
|
124389
124840
|
init_schema();
|
|
124390
124841
|
init_qa_gate_profile();
|
|
124391
124842
|
init_gate_evidence();
|
|
124392
|
-
import * as
|
|
124393
|
-
import * as
|
|
124843
|
+
import * as fs113 from "node:fs";
|
|
124844
|
+
import * as path155 from "node:path";
|
|
124394
124845
|
|
|
124395
124846
|
// src/hooks/diff-scope.ts
|
|
124396
124847
|
init_bun_compat();
|
|
124397
|
-
import * as
|
|
124398
|
-
import * as
|
|
124848
|
+
import * as fs111 from "node:fs";
|
|
124849
|
+
import * as path153 from "node:path";
|
|
124399
124850
|
|
|
124400
124851
|
// src/utils/gitignore-warning.ts
|
|
124401
124852
|
init_bun_compat();
|
|
124402
|
-
import * as
|
|
124403
|
-
import * as
|
|
124404
|
-
var
|
|
124853
|
+
import * as fs110 from "node:fs";
|
|
124854
|
+
import * as path152 from "node:path";
|
|
124855
|
+
var _internals67 = { bunSpawn };
|
|
124405
124856
|
var _swarmGitExcludedChecked = false;
|
|
124406
124857
|
function fileCoversSwarm(content) {
|
|
124407
124858
|
for (const rawLine of content.split(`
|
|
@@ -124434,7 +124885,7 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
|
|
|
124434
124885
|
checkIgnoreExitCode
|
|
124435
124886
|
] = await Promise.all([
|
|
124436
124887
|
(async () => {
|
|
124437
|
-
const proc =
|
|
124888
|
+
const proc = _internals67.bunSpawn(["git", "-C", directory, "rev-parse", "--show-toplevel"], GIT_SPAWN_OPTIONS);
|
|
124438
124889
|
try {
|
|
124439
124890
|
return await Promise.all([proc.exited, proc.stdout.text()]);
|
|
124440
124891
|
} finally {
|
|
@@ -124444,7 +124895,7 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
|
|
|
124444
124895
|
}
|
|
124445
124896
|
})(),
|
|
124446
124897
|
(async () => {
|
|
124447
|
-
const proc =
|
|
124898
|
+
const proc = _internals67.bunSpawn(["git", "-C", directory, "rev-parse", "--git-path", "info/exclude"], GIT_SPAWN_OPTIONS);
|
|
124448
124899
|
try {
|
|
124449
124900
|
return await Promise.all([proc.exited, proc.stdout.text()]);
|
|
124450
124901
|
} finally {
|
|
@@ -124454,7 +124905,7 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
|
|
|
124454
124905
|
}
|
|
124455
124906
|
})(),
|
|
124456
124907
|
(async () => {
|
|
124457
|
-
const proc =
|
|
124908
|
+
const proc = _internals67.bunSpawn(["git", "-C", directory, "check-ignore", "-q", ".swarm/.gitkeep"], GIT_SPAWN_OPTIONS);
|
|
124458
124909
|
try {
|
|
124459
124910
|
return await proc.exited;
|
|
124460
124911
|
} finally {
|
|
@@ -124474,16 +124925,16 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
|
|
|
124474
124925
|
const excludeRelPath = excludePathRaw.trim();
|
|
124475
124926
|
if (!excludeRelPath)
|
|
124476
124927
|
return;
|
|
124477
|
-
const excludePath =
|
|
124928
|
+
const excludePath = path152.isAbsolute(excludeRelPath) ? excludeRelPath : path152.join(directory, excludeRelPath);
|
|
124478
124929
|
if (checkIgnoreExitCode !== 0) {
|
|
124479
124930
|
try {
|
|
124480
|
-
|
|
124931
|
+
fs110.mkdirSync(path152.dirname(excludePath), { recursive: true });
|
|
124481
124932
|
let existing = "";
|
|
124482
124933
|
try {
|
|
124483
|
-
existing =
|
|
124934
|
+
existing = fs110.readFileSync(excludePath, "utf8");
|
|
124484
124935
|
} catch {}
|
|
124485
124936
|
if (!fileCoversSwarm(existing)) {
|
|
124486
|
-
|
|
124937
|
+
fs110.appendFileSync(excludePath, `
|
|
124487
124938
|
# opencode-swarm local runtime state
|
|
124488
124939
|
.swarm/
|
|
124489
124940
|
`, "utf8");
|
|
@@ -124493,7 +124944,7 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
|
|
|
124493
124944
|
}
|
|
124494
124945
|
} catch {}
|
|
124495
124946
|
}
|
|
124496
|
-
const trackedProc =
|
|
124947
|
+
const trackedProc = _internals67.bunSpawn(["git", "-C", directory, "ls-files", "--", ".swarm"], GIT_SPAWN_OPTIONS);
|
|
124497
124948
|
let trackedExitCode;
|
|
124498
124949
|
let trackedOutput;
|
|
124499
124950
|
try {
|
|
@@ -124518,13 +124969,13 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
|
|
|
124518
124969
|
}
|
|
124519
124970
|
|
|
124520
124971
|
// src/hooks/diff-scope.ts
|
|
124521
|
-
var
|
|
124972
|
+
var _internals68 = { bunSpawn };
|
|
124522
124973
|
function getDeclaredScope(taskId, directory) {
|
|
124523
124974
|
try {
|
|
124524
|
-
const planPath =
|
|
124525
|
-
if (!
|
|
124975
|
+
const planPath = path153.join(directory, ".swarm", "plan.json");
|
|
124976
|
+
if (!fs111.existsSync(planPath))
|
|
124526
124977
|
return null;
|
|
124527
|
-
const raw =
|
|
124978
|
+
const raw = fs111.readFileSync(planPath, "utf-8");
|
|
124528
124979
|
const plan = JSON.parse(raw);
|
|
124529
124980
|
for (const phase of plan.phases ?? []) {
|
|
124530
124981
|
for (const task of phase.tasks ?? []) {
|
|
@@ -124553,7 +125004,7 @@ var GIT_DIFF_SPAWN_OPTIONS = {
|
|
|
124553
125004
|
};
|
|
124554
125005
|
async function getChangedFiles(directory) {
|
|
124555
125006
|
try {
|
|
124556
|
-
const proc =
|
|
125007
|
+
const proc = _internals68.bunSpawn(["git", "diff", "--name-only", "HEAD~1"], {
|
|
124557
125008
|
cwd: directory,
|
|
124558
125009
|
...GIT_DIFF_SPAWN_OPTIONS
|
|
124559
125010
|
});
|
|
@@ -124570,7 +125021,7 @@ async function getChangedFiles(directory) {
|
|
|
124570
125021
|
return stdout.trim().split(`
|
|
124571
125022
|
`).map((f) => f.trim()).filter((f) => f.length > 0);
|
|
124572
125023
|
}
|
|
124573
|
-
const proc2 =
|
|
125024
|
+
const proc2 = _internals68.bunSpawn(["git", "diff", "--name-only", "HEAD"], {
|
|
124574
125025
|
cwd: directory,
|
|
124575
125026
|
...GIT_DIFF_SPAWN_OPTIONS
|
|
124576
125027
|
});
|
|
@@ -124626,9 +125077,9 @@ init_telemetry();
|
|
|
124626
125077
|
|
|
124627
125078
|
// src/turbo/lean/task-completion.ts
|
|
124628
125079
|
init_file_locks();
|
|
124629
|
-
import * as
|
|
124630
|
-
import * as
|
|
124631
|
-
var
|
|
125080
|
+
import * as fs112 from "node:fs";
|
|
125081
|
+
import * as path154 from "node:path";
|
|
125082
|
+
var _internals69 = {
|
|
124632
125083
|
listActiveLocks,
|
|
124633
125084
|
verifyLeanTurboTaskCompletion
|
|
124634
125085
|
};
|
|
@@ -124646,7 +125097,7 @@ var TIER_3_PATTERNS = [
|
|
|
124646
125097
|
];
|
|
124647
125098
|
function matchesTier3Pattern(files) {
|
|
124648
125099
|
for (const file3 of files) {
|
|
124649
|
-
const fileName =
|
|
125100
|
+
const fileName = path154.basename(file3);
|
|
124650
125101
|
for (const pattern of TIER_3_PATTERNS) {
|
|
124651
125102
|
if (pattern.test(fileName)) {
|
|
124652
125103
|
return true;
|
|
@@ -124658,14 +125109,14 @@ function matchesTier3Pattern(files) {
|
|
|
124658
125109
|
function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
|
|
124659
125110
|
let persisted = null;
|
|
124660
125111
|
try {
|
|
124661
|
-
const statePath =
|
|
124662
|
-
if (!
|
|
125112
|
+
const statePath = path154.join(directory, ".swarm", "turbo-state.json");
|
|
125113
|
+
if (!fs112.existsSync(statePath)) {
|
|
124663
125114
|
return {
|
|
124664
125115
|
ok: false,
|
|
124665
125116
|
reason: "Lean Turbo state file not found"
|
|
124666
125117
|
};
|
|
124667
125118
|
}
|
|
124668
|
-
const raw =
|
|
125119
|
+
const raw = fs112.readFileSync(statePath, "utf-8");
|
|
124669
125120
|
persisted = JSON.parse(raw);
|
|
124670
125121
|
} catch {
|
|
124671
125122
|
return {
|
|
@@ -124742,11 +125193,11 @@ function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
|
|
|
124742
125193
|
};
|
|
124743
125194
|
}
|
|
124744
125195
|
const phase = runState.phase ?? 0;
|
|
124745
|
-
const evidencePath =
|
|
124746
|
-
const expectedDir =
|
|
124747
|
-
const resolvedPath =
|
|
124748
|
-
const resolvedDir =
|
|
124749
|
-
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) {
|
|
124750
125201
|
return {
|
|
124751
125202
|
ok: false,
|
|
124752
125203
|
reason: `Lane ID causes path traversal: ${lane.laneId}`,
|
|
@@ -124758,7 +125209,7 @@ function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
|
|
|
124758
125209
|
}
|
|
124759
125210
|
};
|
|
124760
125211
|
}
|
|
124761
|
-
if (!
|
|
125212
|
+
if (!fs112.existsSync(evidencePath)) {
|
|
124762
125213
|
return {
|
|
124763
125214
|
ok: false,
|
|
124764
125215
|
reason: `Lane ${lane.laneId} evidence file not found: ${evidencePath}`,
|
|
@@ -124770,7 +125221,7 @@ function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
|
|
|
124770
125221
|
}
|
|
124771
125222
|
};
|
|
124772
125223
|
}
|
|
124773
|
-
const activeLocks =
|
|
125224
|
+
const activeLocks = _internals69.listActiveLocks(directory);
|
|
124774
125225
|
const laneLocks = activeLocks.filter((lock) => lock.laneId === lane.laneId);
|
|
124775
125226
|
if (laneLocks.length > 0) {
|
|
124776
125227
|
return {
|
|
@@ -124786,8 +125237,8 @@ function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
|
|
|
124786
125237
|
}
|
|
124787
125238
|
let filesTouched = [];
|
|
124788
125239
|
try {
|
|
124789
|
-
const planPath =
|
|
124790
|
-
const planRaw =
|
|
125240
|
+
const planPath = path154.join(directory, ".swarm", "plan.json");
|
|
125241
|
+
const planRaw = fs112.readFileSync(planPath, "utf-8");
|
|
124791
125242
|
const plan = JSON.parse(planRaw);
|
|
124792
125243
|
for (const planPhase of plan.phases ?? []) {
|
|
124793
125244
|
for (const task of planPhase.tasks ?? []) {
|
|
@@ -124870,7 +125321,7 @@ var TIER_3_PATTERNS2 = [
|
|
|
124870
125321
|
];
|
|
124871
125322
|
function matchesTier3Pattern2(files) {
|
|
124872
125323
|
for (const file3 of files) {
|
|
124873
|
-
const fileName =
|
|
125324
|
+
const fileName = path155.basename(file3);
|
|
124874
125325
|
for (const pattern of TIER_3_PATTERNS2) {
|
|
124875
125326
|
if (pattern.test(fileName)) {
|
|
124876
125327
|
return true;
|
|
@@ -124909,8 +125360,8 @@ function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = fal
|
|
|
124909
125360
|
if (!skipStandardTurboBypass && hasActiveTurboMode()) {
|
|
124910
125361
|
const resolvedDir2 = workingDirectory;
|
|
124911
125362
|
try {
|
|
124912
|
-
const planPath =
|
|
124913
|
-
const planRaw =
|
|
125363
|
+
const planPath = path155.join(resolvedDir2, ".swarm", "plan.json");
|
|
125364
|
+
const planRaw = fs113.readFileSync(planPath, "utf-8");
|
|
124914
125365
|
const plan = JSON.parse(planRaw);
|
|
124915
125366
|
for (const planPhase of plan.phases ?? []) {
|
|
124916
125367
|
for (const task of planPhase.tasks ?? []) {
|
|
@@ -124987,8 +125438,8 @@ function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = fal
|
|
|
124987
125438
|
}
|
|
124988
125439
|
if (resolvedDir) {
|
|
124989
125440
|
try {
|
|
124990
|
-
const planPath =
|
|
124991
|
-
const planRaw =
|
|
125441
|
+
const planPath = path155.join(resolvedDir, ".swarm", "plan.json");
|
|
125442
|
+
const planRaw = fs113.readFileSync(planPath, "utf-8");
|
|
124992
125443
|
const plan = JSON.parse(planRaw);
|
|
124993
125444
|
for (const planPhase of plan.phases ?? []) {
|
|
124994
125445
|
for (const task of planPhase.tasks ?? []) {
|
|
@@ -125224,8 +125675,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
|
|
|
125224
125675
|
};
|
|
125225
125676
|
}
|
|
125226
125677
|
}
|
|
125227
|
-
normalizedDir =
|
|
125228
|
-
const pathParts = normalizedDir.split(
|
|
125678
|
+
normalizedDir = path155.normalize(args2.working_directory);
|
|
125679
|
+
const pathParts = normalizedDir.split(path155.sep);
|
|
125229
125680
|
if (pathParts.includes("..")) {
|
|
125230
125681
|
return {
|
|
125231
125682
|
success: false,
|
|
@@ -125235,11 +125686,11 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
|
|
|
125235
125686
|
]
|
|
125236
125687
|
};
|
|
125237
125688
|
}
|
|
125238
|
-
const resolvedDir =
|
|
125689
|
+
const resolvedDir = path155.resolve(normalizedDir);
|
|
125239
125690
|
try {
|
|
125240
|
-
const realPath =
|
|
125241
|
-
const planPath =
|
|
125242
|
-
if (!
|
|
125691
|
+
const realPath = fs113.realpathSync(resolvedDir);
|
|
125692
|
+
const planPath = path155.join(realPath, ".swarm", "plan.json");
|
|
125693
|
+
if (!fs113.existsSync(planPath)) {
|
|
125243
125694
|
return {
|
|
125244
125695
|
success: false,
|
|
125245
125696
|
message: `Invalid working_directory: plan not found in "${realPath}"`,
|
|
@@ -125269,9 +125720,9 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
|
|
|
125269
125720
|
directory = fallbackDir;
|
|
125270
125721
|
}
|
|
125271
125722
|
if (fallbackDir && directory !== fallbackDir) {
|
|
125272
|
-
const canonicalDir =
|
|
125273
|
-
const canonicalRoot =
|
|
125274
|
-
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)) {
|
|
125275
125726
|
return {
|
|
125276
125727
|
success: false,
|
|
125277
125728
|
message: `Invalid working_directory: "${directory}" is a subdirectory of ` + `the project root "${fallbackDir}". Pass the project root path or ` + `omit working_directory entirely.`,
|
|
@@ -125283,22 +125734,22 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
|
|
|
125283
125734
|
}
|
|
125284
125735
|
if (args2.status === "in_progress") {
|
|
125285
125736
|
try {
|
|
125286
|
-
const evidencePath =
|
|
125287
|
-
|
|
125288
|
-
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");
|
|
125289
125740
|
let writeOk = false;
|
|
125290
125741
|
try {
|
|
125291
|
-
|
|
125742
|
+
fs113.writeSync(fd, JSON.stringify({
|
|
125292
125743
|
taskId: args2.task_id,
|
|
125293
125744
|
required_gates: [],
|
|
125294
125745
|
gates: {}
|
|
125295
125746
|
}, null, 2));
|
|
125296
125747
|
writeOk = true;
|
|
125297
125748
|
} finally {
|
|
125298
|
-
|
|
125749
|
+
fs113.closeSync(fd);
|
|
125299
125750
|
if (!writeOk) {
|
|
125300
125751
|
try {
|
|
125301
|
-
|
|
125752
|
+
fs113.unlinkSync(evidencePath);
|
|
125302
125753
|
} catch {}
|
|
125303
125754
|
}
|
|
125304
125755
|
}
|
|
@@ -125308,8 +125759,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
|
|
|
125308
125759
|
recoverTaskStateFromDelegations(args2.task_id, directory);
|
|
125309
125760
|
let phaseRequiresReviewer = true;
|
|
125310
125761
|
try {
|
|
125311
|
-
const planPath =
|
|
125312
|
-
const planRaw =
|
|
125762
|
+
const planPath = path155.join(directory, ".swarm", "plan.json");
|
|
125763
|
+
const planRaw = fs113.readFileSync(planPath, "utf-8");
|
|
125313
125764
|
const plan = JSON.parse(planRaw);
|
|
125314
125765
|
const taskPhase = plan.phases.find((p) => p.tasks.some((t) => t.id === args2.task_id));
|
|
125315
125766
|
if (taskPhase?.required_agents && !taskPhase.required_agents.includes("reviewer")) {
|
|
@@ -125536,7 +125987,7 @@ init_utils2();
|
|
|
125536
125987
|
init_redaction();
|
|
125537
125988
|
import { createHash as createHash12 } from "node:crypto";
|
|
125538
125989
|
import { appendFile as appendFile14, mkdir as mkdir25 } from "node:fs/promises";
|
|
125539
|
-
import * as
|
|
125990
|
+
import * as path156 from "node:path";
|
|
125540
125991
|
var EVIDENCE_CACHE_FILE = "evidence-cache/documents.jsonl";
|
|
125541
125992
|
var MAX_EVIDENCE_TEXT_LENGTH = 4000;
|
|
125542
125993
|
async function writeEvidenceDocuments(directory, inputs, now = () => new Date) {
|
|
@@ -125544,7 +125995,7 @@ async function writeEvidenceDocuments(directory, inputs, now = () => new Date) {
|
|
|
125544
125995
|
const capturedAt = now().toISOString();
|
|
125545
125996
|
const records = inputs.map((input) => createEvidenceDocumentRecord(input, capturedAt)).filter((record3) => record3 !== null);
|
|
125546
125997
|
if (records.length > 0) {
|
|
125547
|
-
await mkdir25(
|
|
125998
|
+
await mkdir25(path156.dirname(filePath), { recursive: true });
|
|
125548
125999
|
await appendFile14(filePath, `${records.map((record3) => JSON.stringify(record3)).join(`
|
|
125549
126000
|
`)}
|
|
125550
126001
|
`, "utf-8");
|
|
@@ -125699,7 +126150,7 @@ var web_search = createSwarmTool({
|
|
|
125699
126150
|
});
|
|
125700
126151
|
async function captureSearchEvidence(directory, query, results) {
|
|
125701
126152
|
try {
|
|
125702
|
-
const written = await
|
|
126153
|
+
const written = await _internals70.writeEvidenceDocuments(directory, results.map((result) => ({
|
|
125703
126154
|
sourceType: "web_search",
|
|
125704
126155
|
query,
|
|
125705
126156
|
title: result.title,
|
|
@@ -125727,7 +126178,7 @@ async function captureSearchEvidence(directory, query, results) {
|
|
|
125727
126178
|
};
|
|
125728
126179
|
}
|
|
125729
126180
|
}
|
|
125730
|
-
var
|
|
126181
|
+
var _internals70 = {
|
|
125731
126182
|
writeEvidenceDocuments
|
|
125732
126183
|
};
|
|
125733
126184
|
// src/tools/write-drift-evidence.ts
|
|
@@ -125737,8 +126188,8 @@ init_utils2();
|
|
|
125737
126188
|
init_ledger();
|
|
125738
126189
|
init_manager();
|
|
125739
126190
|
init_create_tool();
|
|
125740
|
-
import
|
|
125741
|
-
import
|
|
126191
|
+
import fs114 from "node:fs";
|
|
126192
|
+
import path157 from "node:path";
|
|
125742
126193
|
function normalizeVerdict(verdict) {
|
|
125743
126194
|
switch (verdict) {
|
|
125744
126195
|
case "APPROVED":
|
|
@@ -125786,7 +126237,7 @@ async function executeWriteDriftEvidence(args2, directory) {
|
|
|
125786
126237
|
entries: [evidenceEntry]
|
|
125787
126238
|
};
|
|
125788
126239
|
const filename = "drift-verifier.json";
|
|
125789
|
-
const relativePath =
|
|
126240
|
+
const relativePath = path157.join("evidence", String(phase), filename);
|
|
125790
126241
|
let validatedPath;
|
|
125791
126242
|
try {
|
|
125792
126243
|
validatedPath = validateSwarmPath(directory, relativePath);
|
|
@@ -125797,12 +126248,12 @@ async function executeWriteDriftEvidence(args2, directory) {
|
|
|
125797
126248
|
message: error93 instanceof Error ? error93.message : "Failed to validate path"
|
|
125798
126249
|
}, null, 2);
|
|
125799
126250
|
}
|
|
125800
|
-
const evidenceDir =
|
|
126251
|
+
const evidenceDir = path157.dirname(validatedPath);
|
|
125801
126252
|
try {
|
|
125802
|
-
await
|
|
125803
|
-
const tempPath =
|
|
125804
|
-
await
|
|
125805
|
-
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);
|
|
125806
126257
|
let snapshotInfo;
|
|
125807
126258
|
let snapshotError;
|
|
125808
126259
|
let qaProfileLocked;
|
|
@@ -125895,8 +126346,8 @@ var write_drift_evidence = createSwarmTool({
|
|
|
125895
126346
|
// src/tools/write-final-council-evidence.ts
|
|
125896
126347
|
init_zod();
|
|
125897
126348
|
init_loader();
|
|
125898
|
-
import
|
|
125899
|
-
import
|
|
126349
|
+
import fs115 from "node:fs";
|
|
126350
|
+
import path158 from "node:path";
|
|
125900
126351
|
init_utils2();
|
|
125901
126352
|
init_manager();
|
|
125902
126353
|
init_create_tool();
|
|
@@ -125984,7 +126435,7 @@ async function executeWriteFinalCouncilEvidence(args2, directory) {
|
|
|
125984
126435
|
timestamp: synthesis.timestamp
|
|
125985
126436
|
};
|
|
125986
126437
|
const filename = "final-council.json";
|
|
125987
|
-
const relativePath =
|
|
126438
|
+
const relativePath = path158.join("evidence", filename);
|
|
125988
126439
|
let validatedPath;
|
|
125989
126440
|
try {
|
|
125990
126441
|
validatedPath = validateSwarmPath(directory, relativePath);
|
|
@@ -125998,12 +126449,12 @@ async function executeWriteFinalCouncilEvidence(args2, directory) {
|
|
|
125998
126449
|
const evidenceContent = {
|
|
125999
126450
|
entries: [evidenceEntry]
|
|
126000
126451
|
};
|
|
126001
|
-
const evidenceDir =
|
|
126452
|
+
const evidenceDir = path158.dirname(validatedPath);
|
|
126002
126453
|
try {
|
|
126003
|
-
await
|
|
126004
|
-
const tempPath =
|
|
126005
|
-
await
|
|
126006
|
-
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);
|
|
126007
126458
|
return JSON.stringify({
|
|
126008
126459
|
success: true,
|
|
126009
126460
|
phase: input.phase,
|
|
@@ -126059,8 +126510,8 @@ var write_final_council_evidence = createSwarmTool({
|
|
|
126059
126510
|
init_zod();
|
|
126060
126511
|
init_utils2();
|
|
126061
126512
|
init_create_tool();
|
|
126062
|
-
import
|
|
126063
|
-
import
|
|
126513
|
+
import fs116 from "node:fs";
|
|
126514
|
+
import path159 from "node:path";
|
|
126064
126515
|
function normalizeVerdict2(verdict) {
|
|
126065
126516
|
switch (verdict) {
|
|
126066
126517
|
case "APPROVED":
|
|
@@ -126108,7 +126559,7 @@ async function executeWriteHallucinationEvidence(args2, directory) {
|
|
|
126108
126559
|
entries: [evidenceEntry]
|
|
126109
126560
|
};
|
|
126110
126561
|
const filename = "hallucination-guard.json";
|
|
126111
|
-
const relativePath =
|
|
126562
|
+
const relativePath = path159.join("evidence", String(phase), filename);
|
|
126112
126563
|
let validatedPath;
|
|
126113
126564
|
try {
|
|
126114
126565
|
validatedPath = validateSwarmPath(directory, relativePath);
|
|
@@ -126119,12 +126570,12 @@ async function executeWriteHallucinationEvidence(args2, directory) {
|
|
|
126119
126570
|
message: error93 instanceof Error ? error93.message : "Failed to validate path"
|
|
126120
126571
|
}, null, 2);
|
|
126121
126572
|
}
|
|
126122
|
-
const evidenceDir =
|
|
126573
|
+
const evidenceDir = path159.dirname(validatedPath);
|
|
126123
126574
|
try {
|
|
126124
|
-
await
|
|
126125
|
-
const tempPath =
|
|
126126
|
-
await
|
|
126127
|
-
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);
|
|
126128
126579
|
return JSON.stringify({
|
|
126129
126580
|
success: true,
|
|
126130
126581
|
phase,
|
|
@@ -126170,8 +126621,8 @@ var write_hallucination_evidence = createSwarmTool({
|
|
|
126170
126621
|
init_zod();
|
|
126171
126622
|
init_utils2();
|
|
126172
126623
|
init_create_tool();
|
|
126173
|
-
import
|
|
126174
|
-
import
|
|
126624
|
+
import fs117 from "node:fs";
|
|
126625
|
+
import path160 from "node:path";
|
|
126175
126626
|
function normalizeVerdict3(verdict) {
|
|
126176
126627
|
switch (verdict) {
|
|
126177
126628
|
case "PASS":
|
|
@@ -126245,7 +126696,7 @@ async function executeWriteMutationEvidence(args2, directory) {
|
|
|
126245
126696
|
entries: [evidenceEntry]
|
|
126246
126697
|
};
|
|
126247
126698
|
const filename = "mutation-gate.json";
|
|
126248
|
-
const relativePath =
|
|
126699
|
+
const relativePath = path160.join("evidence", String(phase), filename);
|
|
126249
126700
|
let validatedPath;
|
|
126250
126701
|
try {
|
|
126251
126702
|
validatedPath = validateSwarmPath(directory, relativePath);
|
|
@@ -126256,12 +126707,12 @@ async function executeWriteMutationEvidence(args2, directory) {
|
|
|
126256
126707
|
message: error93 instanceof Error ? error93.message : "Failed to validate path"
|
|
126257
126708
|
}, null, 2);
|
|
126258
126709
|
}
|
|
126259
|
-
const evidenceDir =
|
|
126710
|
+
const evidenceDir = path160.dirname(validatedPath);
|
|
126260
126711
|
try {
|
|
126261
|
-
await
|
|
126262
|
-
const tempPath =
|
|
126263
|
-
await
|
|
126264
|
-
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);
|
|
126265
126716
|
return JSON.stringify({
|
|
126266
126717
|
success: true,
|
|
126267
126718
|
phase,
|
|
@@ -126609,7 +127060,7 @@ async function initializeOpenCodeSwarm(ctx) {
|
|
|
126609
127060
|
const { PreflightTriggerManager: PTM } = await Promise.resolve().then(() => (init_trigger(), exports_trigger));
|
|
126610
127061
|
preflightTriggerManager = new PTM(automationConfig);
|
|
126611
127062
|
const { AutomationStatusArtifact: ASA } = await Promise.resolve().then(() => (init_status_artifact(), exports_status_artifact));
|
|
126612
|
-
const swarmDir =
|
|
127063
|
+
const swarmDir = path162.resolve(ctx.directory, ".swarm");
|
|
126613
127064
|
statusArtifact = new ASA(swarmDir);
|
|
126614
127065
|
statusArtifact.updateConfig(automationConfig.mode, automationConfig.capabilities);
|
|
126615
127066
|
if (automationConfig.capabilities?.evidence_auto_summaries === true) {
|
|
@@ -127206,7 +127657,7 @@ ${promptRaw}`;
|
|
|
127206
127657
|
const meta3 = readSkillMetadata(s.skillPath, ctx.directory);
|
|
127207
127658
|
let desc = meta3.description || "";
|
|
127208
127659
|
if (!desc || desc === "No description provided") {
|
|
127209
|
-
desc =
|
|
127660
|
+
desc = path162.basename(path162.dirname(s.skillPath));
|
|
127210
127661
|
}
|
|
127211
127662
|
desc = desc.replace(/,/g, ";");
|
|
127212
127663
|
return `file:${s.skillPath} (-- ${desc})`;
|
|
@@ -127216,7 +127667,7 @@ ${promptRaw}`;
|
|
|
127216
127667
|
|
|
127217
127668
|
${promptRaw}`;
|
|
127218
127669
|
argsRecord.prompt = newPrompt;
|
|
127219
|
-
const skillNames = topSkills.map((s) => `${
|
|
127670
|
+
const skillNames = topSkills.map((s) => `${path162.basename(s.skillPath)} (score: ${s.score.toFixed(2)})`).join(", ");
|
|
127220
127671
|
console.warn(`[skill-propagation-gate] Injected skills: ${skillNames}`);
|
|
127221
127672
|
for (const skill of topSkills) {
|
|
127222
127673
|
try {
|