opencode-swarm 7.46.5 → 7.47.0

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