opencode-swarm 7.46.5 → 7.47.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -70,4 +70,4 @@ export declare function buildCouncilWorkflow(council?: CouncilWorkflowConfig): s
70
70
  * BRAINSTORM, and PLAN inline paths stay in lockstep.
71
71
  */
72
72
  export declare function buildQaGateSelectionDialogue(modeLabel: 'BRAINSTORM' | 'SPECIFY' | 'PLAN'): string;
73
- export declare function createArchitectAgent(model: string, customPrompt?: string, customAppendPrompt?: string, adversarialTesting?: AdversarialTestingConfig, council?: CouncilWorkflowConfig, uiReview?: UIReviewConfig, memoryEnabled?: boolean, architecturalSupervision?: ArchitectureSupervisionWorkflowConfig): AgentDefinition;
73
+ export declare function createArchitectAgent(model: string, customPrompt?: string, customAppendPrompt?: string, adversarialTesting?: AdversarialTestingConfig, council?: CouncilWorkflowConfig, uiReview?: UIReviewConfig, memoryEnabled?: boolean, architecturalSupervision?: ArchitectureSupervisionWorkflowConfig, designDocsEnabled?: boolean): AgentDefinition;
@@ -1,2 +1,11 @@
1
1
  import type { AgentDefinition } from './architect';
2
- export declare function createDocsAgent(model: string, customPrompt?: string, customAppendPrompt?: string): AgentDefinition;
2
+ /**
3
+ * Role discriminator for the docs agent. Mirrors the critic agent's `CriticRole`
4
+ * pattern: a single factory + a role-keyed prompt/name table produces multiple
5
+ * registered variants that share one base.
6
+ * - `standard` — the README/CHANGELOG/API-doc synthesizer (default).
7
+ * - `design_docs` — the structured design-doc author (issue #1080): generates
8
+ * the language-agnostic domain/technical-spec/behavior-spec docs + reference/.
9
+ */
10
+ export type DocsRole = 'standard' | 'design_docs';
11
+ export declare function createDocsAgent(model: string, customPrompt?: string, customAppendPrompt?: string, role?: DocsRole): AgentDefinition;
@@ -5,7 +5,7 @@
5
5
  * Events flow through the system without external dependencies.
6
6
  */
7
7
  /** Automation event types */
8
- export type AutomationEventType = 'queue.item.enqueued' | 'queue.item.dequeued' | 'queue.item.completed' | 'queue.item.failed' | 'queue.item.retry scheduled' | 'worker.started' | 'worker.stopped' | 'worker.error' | 'circuit.breaker.opened' | 'circuit.breaker.half-open' | 'circuit.breaker.closed' | 'loop.protection.triggered' | 'automation.started' | 'automation.stopped' | 'preflight.requested' | 'preflight.triggered' | 'preflight.skipped' | 'preflight.completed' | 'phase.boundary.detected' | 'phase.status.checked' | 'task.completed' | 'evidence.summary.generated' | 'evidence.summary.error' | 'curator.init.completed' | 'curator.init.llm_completed' | 'curator.init.llm_fallback' | 'curator.phase.completed' | 'curator.phase.llm_completed' | 'curator.phase.llm_fallback' | 'curator.drift.completed' | 'curator.error';
8
+ export type AutomationEventType = 'queue.item.enqueued' | 'queue.item.dequeued' | 'queue.item.completed' | 'queue.item.failed' | 'queue.item.retry scheduled' | 'worker.started' | 'worker.stopped' | 'worker.error' | 'circuit.breaker.opened' | 'circuit.breaker.half-open' | 'circuit.breaker.closed' | 'loop.protection.triggered' | 'automation.started' | 'automation.stopped' | 'preflight.requested' | 'preflight.triggered' | 'preflight.skipped' | 'preflight.completed' | 'phase.boundary.detected' | 'phase.status.checked' | 'task.completed' | 'evidence.summary.generated' | 'evidence.summary.error' | 'curator.init.completed' | 'curator.init.llm_completed' | 'curator.init.llm_fallback' | 'curator.phase.completed' | 'curator.phase.llm_completed' | 'curator.phase.llm_fallback' | 'curator.drift.completed' | 'curator.docdrift.completed' | 'curator.error';
9
9
  /** Base automation event */
10
10
  export interface AutomationEvent<T = unknown> {
11
11
  type: AutomationEventType;
package/dist/cli/index.js CHANGED
@@ -52,7 +52,7 @@ var package_default;
52
52
  var init_package = __esm(() => {
53
53
  package_default = {
54
54
  name: "opencode-swarm",
55
- version: "7.46.5",
55
+ version: "7.47.0",
56
56
  description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
57
57
  main: "dist/index.js",
58
58
  types: "dist/index.d.ts",
@@ -16581,6 +16581,7 @@ var init_constants = __esm(() => {
16581
16581
  ALL_SUBAGENT_NAMES = [
16582
16582
  "sme",
16583
16583
  "docs",
16584
+ "docs_design",
16584
16585
  "designer",
16585
16586
  "critic_sounding_board",
16586
16587
  "critic_drift_verifier",
@@ -16971,6 +16972,19 @@ var init_constants = __esm(() => {
16971
16972
  "summarize_work",
16972
16973
  "swarm_command"
16973
16974
  ],
16975
+ docs_design: [
16976
+ "detect_domains",
16977
+ "extract_code_blocks",
16978
+ "imports",
16979
+ "retrieve_summary",
16980
+ "search",
16981
+ "symbols",
16982
+ "doc_scan",
16983
+ "doc_extract",
16984
+ "knowledge_recall",
16985
+ "summarize_work",
16986
+ "swarm_command"
16987
+ ],
16974
16988
  designer: [
16975
16989
  "extract_code_blocks",
16976
16990
  "retrieve_summary",
@@ -17130,6 +17144,10 @@ var init_constants = __esm(() => {
17130
17144
  model: "opencode/big-pickle",
17131
17145
  fallback_models: ["opencode/gpt-5-nano", "opencode/big-pickle"]
17132
17146
  },
17147
+ docs_design: {
17148
+ model: "opencode/big-pickle",
17149
+ fallback_models: ["opencode/gpt-5-nano", "opencode/big-pickle"]
17150
+ },
17133
17151
  designer: {
17134
17152
  model: "opencode/big-pickle",
17135
17153
  fallback_models: ["opencode/gpt-5-nano", "opencode/big-pickle"]
@@ -17202,7 +17220,7 @@ function getCanonicalAgentRole(agentName, generatedAgentNames) {
17202
17220
  function stripKnownSwarmPrefix(agentName) {
17203
17221
  return getCanonicalAgentRole(agentName);
17204
17222
  }
17205
- var 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;
17223
+ var 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;
17206
17224
  var init_schema = __esm(() => {
17207
17225
  init_zod();
17208
17226
  init_constants();
@@ -17400,6 +17418,13 @@ var init_schema = __esm(() => {
17400
17418
  "**/CHANGELOG.md"
17401
17419
  ])
17402
17420
  });
17421
+ DesignDocsConfigSchema = exports_external.object({
17422
+ enabled: exports_external.boolean().default(false),
17423
+ out_dir: exports_external.string().default("docs").refine((v) => v.length > 0 && v !== "." && !v.includes("..") && !v.startsWith("/") && !v.startsWith("\\") && !/^[A-Za-z]:/.test(v), {
17424
+ message: 'design_docs.out_dir must be a non-empty project-relative path with no "..", leading slash, or drive letter'
17425
+ }),
17426
+ language: exports_external.string().optional()
17427
+ });
17403
17428
  UIReviewConfigSchema = exports_external.object({
17404
17429
  enabled: exports_external.boolean().default(false),
17405
17430
  trigger_paths: exports_external.array(exports_external.string()).default([
@@ -17923,6 +17948,7 @@ var init_schema = __esm(() => {
17923
17948
  adversarial_testing: AdversarialTestingConfigSchema.optional(),
17924
17949
  integration_analysis: IntegrationAnalysisConfigSchema.optional(),
17925
17950
  docs: DocsConfigSchema.optional(),
17951
+ design_docs: DesignDocsConfigSchema.optional(),
17926
17952
  ui_review: UIReviewConfigSchema.optional(),
17927
17953
  compaction_advisory: CompactionAdvisoryConfigSchema.optional(),
17928
17954
  lint: LintConfigSchema.optional(),
@@ -21341,6 +21367,9 @@ ${HARD_RULES}
21341
21367
  var init_critic = () => {};
21342
21368
  // src/agents/curator-agent.ts
21343
21369
  var init_curator_agent = () => {};
21370
+ // src/agents/docs.ts
21371
+ var init_docs = () => {};
21372
+
21344
21373
  // src/agents/reviewer.ts
21345
21374
  var init_reviewer = () => {};
21346
21375
  // src/agents/index.ts
@@ -21354,11 +21383,13 @@ var init_agents2 = __esm(() => {
21354
21383
  init_council_prompts();
21355
21384
  init_critic();
21356
21385
  init_curator_agent();
21386
+ init_docs();
21357
21387
  init_reviewer();
21358
21388
  init_architect();
21359
21389
  init_council_prompts();
21360
21390
  init_critic();
21361
21391
  init_curator_agent();
21392
+ init_docs();
21362
21393
  init_reviewer();
21363
21394
  warnedAgents = new Set;
21364
21395
  KNOWN_VARIANT_VALUES = new Set([
@@ -40234,6 +40265,122 @@ var init_deep_dive = __esm(() => {
40234
40265
  ]);
40235
40266
  });
40236
40267
 
40268
+ // src/commands/design-docs.ts
40269
+ function sanitizeDescription(raw) {
40270
+ const collapsed = raw.replace(/\s+/g, " ").trim();
40271
+ const stripped1 = collapsed.replace(/\[\s*MODE\s*:[^\]]*\]/gi, "");
40272
+ const stripped2 = stripped1.replace(/\[\s*MODE\s*:.*$/gi, "");
40273
+ const normalized = stripped2.replace(/\s+/g, " ").trim();
40274
+ if (normalized.length <= MAX_DESC_LEN)
40275
+ return normalized;
40276
+ return `${normalized.slice(0, MAX_DESC_LEN)}\u2026`;
40277
+ }
40278
+ function cleanFlagValue(raw) {
40279
+ if (raw.includes("[") || raw.includes("]") || /\s/.test(raw))
40280
+ return null;
40281
+ if (/\[\s*MODE\s*:/i.test(raw))
40282
+ return null;
40283
+ return raw;
40284
+ }
40285
+ function parseArgs3(args) {
40286
+ const result = {
40287
+ out: "docs",
40288
+ lang: "auto",
40289
+ update: false,
40290
+ rest: []
40291
+ };
40292
+ let i = 0;
40293
+ while (i < args.length) {
40294
+ const token = args[i];
40295
+ if (token === "--out") {
40296
+ if (i + 1 >= args.length || args[i + 1].startsWith("--")) {
40297
+ return { ...result, error: `Flag "${token}" requires a value` };
40298
+ }
40299
+ const value = args[++i];
40300
+ const clean = cleanFlagValue(value);
40301
+ if (clean === null || value.includes("..") || value.startsWith("/") || value.startsWith("\\") || /^[A-Za-z]:/.test(value)) {
40302
+ return {
40303
+ ...result,
40304
+ error: `Invalid --out value "${value}". Must be a project-relative directory with no brackets or spaces.`
40305
+ };
40306
+ }
40307
+ const trimmed = clean.replace(/[/\\]+$/, "");
40308
+ if (!trimmed || trimmed === ".") {
40309
+ return {
40310
+ ...result,
40311
+ error: `Invalid --out value "${value}". Must name a non-empty subdirectory.`
40312
+ };
40313
+ }
40314
+ result.out = trimmed;
40315
+ } else if (token === "--lang") {
40316
+ if (i + 1 >= args.length || args[i + 1].startsWith("--")) {
40317
+ return { ...result, error: `Flag "${token}" requires a value` };
40318
+ }
40319
+ const value = args[++i];
40320
+ const clean = cleanFlagValue(value);
40321
+ if (clean === null) {
40322
+ return {
40323
+ ...result,
40324
+ error: `Invalid --lang value "${value}". Must be a single token with no brackets or spaces.`
40325
+ };
40326
+ }
40327
+ result.lang = clean;
40328
+ } else if (token === "--update") {
40329
+ result.update = true;
40330
+ } else if (token.startsWith("--")) {
40331
+ return { ...result, error: `Unknown flag "${token}"` };
40332
+ } else {
40333
+ result.rest.push(token);
40334
+ }
40335
+ i++;
40336
+ }
40337
+ return result;
40338
+ }
40339
+ async function handleDesignDocsCommand(directory, args) {
40340
+ const parsed = parseArgs3(args);
40341
+ if (parsed.error) {
40342
+ return `Error: ${parsed.error}
40343
+
40344
+ ${USAGE3}`;
40345
+ }
40346
+ try {
40347
+ const { config: config3 } = loadPluginConfigWithMeta(directory);
40348
+ if (config3.design_docs?.enabled !== true) {
40349
+ return "Error: design docs are disabled. Set `design_docs.enabled: true` in " + `opencode-swarm.json to enable the docs_design agent and this command.
40350
+
40351
+ ` + USAGE3;
40352
+ }
40353
+ } catch (configErr) {
40354
+ console.warn(`[design-docs] Could not read opencode-swarm.json (${String(configErr)}). ` + "Falling through \u2014 the architect will abort if docs_design is not registered.");
40355
+ }
40356
+ const description = sanitizeDescription(parsed.rest.join(" "));
40357
+ if (!description && !parsed.update) {
40358
+ return USAGE3;
40359
+ }
40360
+ const header = `[MODE: DESIGN_DOCS out=${parsed.out} lang=${parsed.lang} update=${parsed.update}] ${description}`;
40361
+ return header.trimEnd();
40362
+ }
40363
+ var MAX_DESC_LEN = 2000, USAGE3 = `Usage: /swarm design-docs <description> [--out <dir>] [--lang <name>] [--update]
40364
+
40365
+ Generate or sync language-agnostic design docs for the project under build:
40366
+ <out>/domain.md, <out>/technical-spec.md, <out>/behavior-spec.md,
40367
+ <out>/reference/{reference-impl,idiom-notes}.md, <out>/reference/traceability.json
40368
+
40369
+ Requires design_docs.enabled: true in opencode-swarm.json.
40370
+
40371
+ Examples:
40372
+ /swarm design-docs "terminal GitHub PR client"
40373
+ /swarm design-docs auth-service --lang rust
40374
+ /swarm design docs --update --out design
40375
+
40376
+ Flags:
40377
+ --out <dir> output directory (default "docs")
40378
+ --lang <name> target language for the reference/ docs (default: inferred)
40379
+ --update sync existing docs to current code/spec instead of generating fresh`;
40380
+ var init_design_docs = __esm(() => {
40381
+ init_config();
40382
+ });
40383
+
40237
40384
  // src/config/cache-paths.ts
40238
40385
  import * as os5 from "os";
40239
40386
  import * as path23 from "path";
@@ -45621,7 +45768,7 @@ function validateAndSanitizeUrl(rawUrl) {
45621
45768
  return { error: "Invalid URL format" };
45622
45769
  }
45623
45770
  }
45624
- function parseArgs3(args) {
45771
+ function parseArgs4(args) {
45625
45772
  const out = {
45626
45773
  plan: false,
45627
45774
  trace: false,
@@ -45712,24 +45859,24 @@ function parseGitRemoteUrl(remoteUrl) {
45712
45859
  return null;
45713
45860
  }
45714
45861
  function handleIssueCommand(_directory, args) {
45715
- const parsed = parseArgs3(args);
45862
+ const parsed = parseArgs4(args);
45716
45863
  const rawInput = parsed.rest.join(" ").trim();
45717
45864
  if (!rawInput) {
45718
- return USAGE3;
45865
+ return USAGE4;
45719
45866
  }
45720
45867
  const isFullUrl = /^https?:\/\//i.test(rawInput);
45721
45868
  const issueInfo = parseIssueRef(isFullUrl ? sanitizeUrl(rawInput) : rawInput);
45722
45869
  if (!issueInfo) {
45723
45870
  return `Error: Could not parse issue reference from "${rawInput}"
45724
45871
 
45725
- ${USAGE3}`;
45872
+ ${USAGE4}`;
45726
45873
  }
45727
45874
  const issueUrl = `https://github.com/${issueInfo.owner}/${issueInfo.repo}/issues/${issueInfo.number}`;
45728
45875
  const result = validateAndSanitizeUrl(issueUrl);
45729
45876
  if ("error" in result) {
45730
45877
  return `Error: ${result.error}
45731
45878
 
45732
- ${USAGE3}`;
45879
+ ${USAGE4}`;
45733
45880
  }
45734
45881
  const flags = [];
45735
45882
  if (parsed.plan)
@@ -45741,9 +45888,9 @@ ${USAGE3}`;
45741
45888
  const flagsStr = flags.length > 0 ? ` ${flags.join(" ")}` : "";
45742
45889
  return `[MODE: ISSUE_INGEST issue="${result.sanitized}"${flagsStr}]`;
45743
45890
  }
45744
- var MAX_URL_LEN = 2048, USAGE3;
45891
+ var MAX_URL_LEN = 2048, USAGE4;
45745
45892
  var init_issue = __esm(() => {
45746
- USAGE3 = [
45893
+ USAGE4 = [
45747
45894
  "Usage: /swarm issue <url|owner/repo#N|N> [--plan] [--trace] [--no-repro]",
45748
45895
  "",
45749
45896
  "Ingest a GitHub issue into the swarm workflow.",
@@ -49699,7 +49846,7 @@ function validateAndSanitizeUrl2(rawUrl) {
49699
49846
  return { error: "Invalid URL format" };
49700
49847
  }
49701
49848
  }
49702
- function parseArgs4(args) {
49849
+ function parseArgs5(args) {
49703
49850
  const out = { council: false, rest: [] };
49704
49851
  for (const token of args) {
49705
49852
  if (token === "--council") {
@@ -49783,31 +49930,31 @@ function parseGitRemoteUrl2(remoteUrl) {
49783
49930
  return null;
49784
49931
  }
49785
49932
  function handlePrReviewCommand(_directory, args) {
49786
- const parsed = parseArgs4(args);
49933
+ const parsed = parseArgs5(args);
49787
49934
  const rawInput = parsed.rest.join(" ").trim();
49788
49935
  if (!rawInput) {
49789
- return USAGE4;
49936
+ return USAGE5;
49790
49937
  }
49791
49938
  const isFullUrl = /^https?:\/\//i.test(rawInput);
49792
49939
  const prInfo = parsePrRef(isFullUrl ? sanitizeUrl2(rawInput) : rawInput);
49793
49940
  if (!prInfo) {
49794
49941
  return `Error: Could not parse PR reference from "${rawInput}"
49795
49942
 
49796
- ${USAGE4}`;
49943
+ ${USAGE5}`;
49797
49944
  }
49798
49945
  const prUrl = `https://github.com/${prInfo.owner}/${prInfo.repo}/pull/${prInfo.number}`;
49799
49946
  const result = validateAndSanitizeUrl2(prUrl);
49800
49947
  if ("error" in result) {
49801
49948
  return `Error: ${result.error}
49802
49949
 
49803
- ${USAGE4}`;
49950
+ ${USAGE5}`;
49804
49951
  }
49805
49952
  const councilFlag = parsed.council ? "council=true" : "council=false";
49806
49953
  return `[MODE: PR_REVIEW pr="${result.sanitized}" ${councilFlag}]`;
49807
49954
  }
49808
- var MAX_URL_LEN2 = 2048, USAGE4;
49955
+ var MAX_URL_LEN2 = 2048, USAGE5;
49809
49956
  var init_pr_review = __esm(() => {
49810
- USAGE4 = [
49957
+ USAGE5 = [
49811
49958
  "Usage: /swarm pr-review <url|owner/repo#N|N> [--council]",
49812
49959
  "",
49813
49960
  "Run a full swarm PR review on a GitHub pull request.",
@@ -58252,6 +58399,7 @@ var init_registry = __esm(() => {
58252
58399
  init_curate();
58253
58400
  init_dark_matter();
58254
58401
  init_deep_dive();
58402
+ init_design_docs();
58255
58403
  init_diagnose();
58256
58404
  init_doctor();
58257
58405
  init_evidence();
@@ -58567,6 +58715,20 @@ Subcommands:
58567
58715
  category: "agent",
58568
58716
  aliasOf: "deep-dive"
58569
58717
  },
58718
+ "design-docs": {
58719
+ handler: async (ctx) => handleDesignDocsCommand(ctx.directory, ctx.args),
58720
+ description: "Generate or sync language-agnostic design docs (domain, technical-spec, behavior-spec, reference/) for the project under build [description]",
58721
+ args: "<description> [--out <dir>] [--lang <name>] [--update]",
58722
+ details: "Triggers the architect to enter MODE: DESIGN_DOCS \u2014 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.",
58723
+ category: "agent"
58724
+ },
58725
+ "design docs": {
58726
+ handler: async (ctx) => handleDesignDocsCommand(ctx.directory, ctx.args),
58727
+ description: "Alias for /swarm design-docs \u2014 generate or sync design docs",
58728
+ args: "<description> [--out <dir>] [--lang <name>] [--update]",
58729
+ category: "agent",
58730
+ aliasOf: "design-docs"
58731
+ },
58570
58732
  issue: {
58571
58733
  handler: async (ctx) => handleIssueCommand(ctx.directory, ctx.args),
58572
58734
  description: "Ingest a GitHub issue into the swarm workflow [url] [--plan] [--trace] [--no-repro]",
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Handle /swarm design-docs command (issue #1080).
3
+ * Sanitizes the description, parses flags, and emits a DESIGN_DOCS mode signal
4
+ * that routes the architect into the design-doc generation/sync workflow.
5
+ */
6
+ export declare function handleDesignDocsCommand(directory: string, args: string[]): Promise<string>;
@@ -322,6 +322,20 @@ export declare const COMMAND_REGISTRY: {
322
322
  readonly category: "agent";
323
323
  readonly aliasOf: "deep-dive";
324
324
  };
325
+ readonly 'design-docs': {
326
+ readonly handler: (ctx: CommandContext) => Promise<string>;
327
+ readonly description: "Generate or sync language-agnostic design docs (domain, technical-spec, behavior-spec, reference/) for the project under build [description]";
328
+ readonly args: "<description> [--out <dir>] [--lang <name>] [--update]";
329
+ readonly 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.";
330
+ readonly category: "agent";
331
+ };
332
+ readonly 'design docs': {
333
+ readonly handler: (ctx: CommandContext) => Promise<string>;
334
+ readonly description: "Alias for /swarm design-docs — generate or sync design docs";
335
+ readonly args: "<description> [--out <dir>] [--lang <name>] [--update]";
336
+ readonly category: "agent";
337
+ readonly aliasOf: "design-docs";
338
+ };
325
339
  readonly issue: {
326
340
  readonly handler: (ctx: CommandContext) => Promise<string>;
327
341
  readonly description: "Ingest a GitHub issue into the swarm workflow [url] [--plan] [--trace] [--no-repro]";
@@ -2,8 +2,8 @@ import type { ToolName } from '../tools/tool-names';
2
2
  export declare const QA_AGENTS: readonly ["reviewer", "critic", "critic_oversight"];
3
3
  export declare const PIPELINE_AGENTS: readonly ["explorer", "coder", "test_engineer"];
4
4
  export declare const ORCHESTRATOR_NAME: "architect";
5
- export declare const ALL_SUBAGENT_NAMES: readonly ["sme", "docs", "designer", "critic_sounding_board", "critic_drift_verifier", "critic_hallucination_verifier", "critic_architecture_supervisor", "curator_init", "curator_phase", "council_generalist", "council_skeptic", "council_domain_expert", "skill_improver", "spec_writer", "reviewer", "critic", "critic_oversight", "explorer", "coder", "test_engineer"];
6
- export declare const ALL_AGENT_NAMES: readonly ["architect", "sme", "docs", "designer", "critic_sounding_board", "critic_drift_verifier", "critic_hallucination_verifier", "critic_architecture_supervisor", "curator_init", "curator_phase", "council_generalist", "council_skeptic", "council_domain_expert", "skill_improver", "spec_writer", "reviewer", "critic", "critic_oversight", "explorer", "coder", "test_engineer"];
5
+ export declare const ALL_SUBAGENT_NAMES: readonly ["sme", "docs", "docs_design", "designer", "critic_sounding_board", "critic_drift_verifier", "critic_hallucination_verifier", "critic_architecture_supervisor", "curator_init", "curator_phase", "council_generalist", "council_skeptic", "council_domain_expert", "skill_improver", "spec_writer", "reviewer", "critic", "critic_oversight", "explorer", "coder", "test_engineer"];
6
+ export declare const ALL_AGENT_NAMES: readonly ["architect", "sme", "docs", "docs_design", "designer", "critic_sounding_board", "critic_drift_verifier", "critic_hallucination_verifier", "critic_architecture_supervisor", "curator_init", "curator_phase", "council_generalist", "council_skeptic", "council_domain_expert", "skill_improver", "spec_writer", "reviewer", "critic", "critic_oversight", "explorer", "coder", "test_engineer"];
7
7
  export declare const OPENCODE_NATIVE_AGENTS: Set<"compaction" | "title" | "build" | "general" | "plan" | "explore" | "summary">;
8
8
  export declare const CLAUDE_CODE_NATIVE_COMMANDS: ReadonlySet<string>;
9
9
  export type QAAgentName = (typeof QA_AGENTS)[number];
@@ -308,6 +308,12 @@ export declare const DocsConfigSchema: z.ZodObject<{
308
308
  doc_patterns: z.ZodDefault<z.ZodArray<z.ZodString>>;
309
309
  }, z.core.$strip>;
310
310
  export type DocsConfig = z.infer<typeof DocsConfigSchema>;
311
+ export declare const DesignDocsConfigSchema: z.ZodObject<{
312
+ enabled: z.ZodDefault<z.ZodBoolean>;
313
+ out_dir: z.ZodDefault<z.ZodString>;
314
+ language: z.ZodOptional<z.ZodString>;
315
+ }, z.core.$strip>;
316
+ export type DesignDocsConfig = z.infer<typeof DesignDocsConfigSchema>;
311
317
  export declare const UIReviewConfigSchema: z.ZodObject<{
312
318
  enabled: z.ZodDefault<z.ZodBoolean>;
313
319
  trigger_paths: z.ZodDefault<z.ZodArray<z.ZodString>>;
@@ -1110,6 +1116,11 @@ export declare const PluginConfigSchema: z.ZodObject<{
1110
1116
  enabled: z.ZodDefault<z.ZodBoolean>;
1111
1117
  doc_patterns: z.ZodDefault<z.ZodArray<z.ZodString>>;
1112
1118
  }, z.core.$strip>>;
1119
+ design_docs: z.ZodOptional<z.ZodObject<{
1120
+ enabled: z.ZodDefault<z.ZodBoolean>;
1121
+ out_dir: z.ZodDefault<z.ZodString>;
1122
+ language: z.ZodOptional<z.ZodString>;
1123
+ }, z.core.$strip>>;
1113
1124
  ui_review: z.ZodOptional<z.ZodObject<{
1114
1125
  enabled: z.ZodDefault<z.ZodBoolean>;
1115
1126
  trigger_paths: z.ZodDefault<z.ZodArray<z.ZodString>>;
@@ -71,6 +71,31 @@ export interface DriftReport {
71
71
  /** Truncated summary for architect context injection */
72
72
  injection_summary: string;
73
73
  }
74
+ /**
75
+ * Design-doc drift report (issue #1080) — produced by the deterministic
76
+ * design-doc drift check at phase wrap. Compares the generated design docs
77
+ * (domain/technical-spec/behavior-spec/reference) against code/spec mtimes via
78
+ * the traceability registry. Advisory only — never blocks phase completion.
79
+ */
80
+ export interface DocDriftReport {
81
+ schema_version: 1;
82
+ phase: number;
83
+ timestamp: string;
84
+ /** Output directory the docs were checked under (project-relative). */
85
+ out_dir: string;
86
+ /** Overall verdict for the phase. */
87
+ verdict: 'DOC_FRESH' | 'DOC_STALE' | 'NO_DOCS';
88
+ /** Sections whose owning doc is older than a mapped code anchor or the spec. */
89
+ stale_sections: Array<{
90
+ section_id: string;
91
+ doc: string;
92
+ reason: string;
93
+ }>;
94
+ /** Expected design docs that are missing from out_dir. */
95
+ missing_docs: string[];
96
+ /** Design docs that were found and checked. */
97
+ checked_docs: string[];
98
+ }
74
99
  export interface CuratorConfig {
75
100
  enabled: boolean;
76
101
  init_enabled: boolean;
@@ -0,0 +1,24 @@
1
+ import type { DocDriftReport } from './curator-types.js';
2
+ /** Return mtime in ms for a path, or null if it does not exist / cannot stat. */
3
+ declare function mtimeMsOrNull(absPath: string): number | null;
4
+ /**
5
+ * Resolve a project-relative anchor path safely under `directory`. Returns null
6
+ * if the anchor escapes the project root (defense against `..`/absolute paths
7
+ * in a hand-edited traceability.json).
8
+ */
9
+ declare function resolveAnchorWithin(directory: string, anchor: string): string | null;
10
+ /**
11
+ * Run the deterministic design-doc drift check for a phase.
12
+ *
13
+ * @param directory project root
14
+ * @param phase phase number
15
+ * @param outDir design-doc output directory (project-relative, e.g. "docs")
16
+ * @returns the written DocDriftReport, or null if the check failed (fail-open).
17
+ */
18
+ export declare function runDesignDocDriftCheck(directory: string, phase: number, outDir: string): Promise<DocDriftReport | null>;
19
+ export declare const _internals: {
20
+ mtimeMsOrNull: typeof mtimeMsOrNull;
21
+ resolveAnchorWithin: typeof resolveAnchorWithin;
22
+ DESIGN_DOC_FILES: Record<string, string>;
23
+ };
24
+ export {};