opencode-swarm 7.46.4 → 7.47.0

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