opencode-swarm 7.46.5 → 7.48.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.48.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",
@@ -16846,6 +16847,7 @@ var init_constants = __esm(() => {
16846
16847
  "syntax_check",
16847
16848
  "search",
16848
16849
  "summarize_work",
16850
+ "knowledge_recall",
16849
16851
  "swarm_command"
16850
16852
  ],
16851
16853
  sme: [
@@ -16971,6 +16973,19 @@ var init_constants = __esm(() => {
16971
16973
  "summarize_work",
16972
16974
  "swarm_command"
16973
16975
  ],
16976
+ docs_design: [
16977
+ "detect_domains",
16978
+ "extract_code_blocks",
16979
+ "imports",
16980
+ "retrieve_summary",
16981
+ "search",
16982
+ "symbols",
16983
+ "doc_scan",
16984
+ "doc_extract",
16985
+ "knowledge_recall",
16986
+ "summarize_work",
16987
+ "swarm_command"
16988
+ ],
16974
16989
  designer: [
16975
16990
  "extract_code_blocks",
16976
16991
  "retrieve_summary",
@@ -17130,6 +17145,10 @@ var init_constants = __esm(() => {
17130
17145
  model: "opencode/big-pickle",
17131
17146
  fallback_models: ["opencode/gpt-5-nano", "opencode/big-pickle"]
17132
17147
  },
17148
+ docs_design: {
17149
+ model: "opencode/big-pickle",
17150
+ fallback_models: ["opencode/gpt-5-nano", "opencode/big-pickle"]
17151
+ },
17133
17152
  designer: {
17134
17153
  model: "opencode/big-pickle",
17135
17154
  fallback_models: ["opencode/gpt-5-nano", "opencode/big-pickle"]
@@ -17202,7 +17221,7 @@ function getCanonicalAgentRole(agentName, generatedAgentNames) {
17202
17221
  function stripKnownSwarmPrefix(agentName) {
17203
17222
  return getCanonicalAgentRole(agentName);
17204
17223
  }
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;
17224
+ 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
17225
  var init_schema = __esm(() => {
17207
17226
  init_zod();
17208
17227
  init_constants();
@@ -17400,6 +17419,13 @@ var init_schema = __esm(() => {
17400
17419
  "**/CHANGELOG.md"
17401
17420
  ])
17402
17421
  });
17422
+ DesignDocsConfigSchema = exports_external.object({
17423
+ enabled: exports_external.boolean().default(false),
17424
+ out_dir: exports_external.string().default("docs").refine((v) => v.length > 0 && v !== "." && !v.includes("..") && !v.startsWith("/") && !v.startsWith("\\") && !/^[A-Za-z]:/.test(v), {
17425
+ message: 'design_docs.out_dir must be a non-empty project-relative path with no "..", leading slash, or drive letter'
17426
+ }),
17427
+ language: exports_external.string().optional()
17428
+ });
17403
17429
  UIReviewConfigSchema = exports_external.object({
17404
17430
  enabled: exports_external.boolean().default(false),
17405
17431
  trigger_paths: exports_external.array(exports_external.string()).default([
@@ -17923,6 +17949,7 @@ var init_schema = __esm(() => {
17923
17949
  adversarial_testing: AdversarialTestingConfigSchema.optional(),
17924
17950
  integration_analysis: IntegrationAnalysisConfigSchema.optional(),
17925
17951
  docs: DocsConfigSchema.optional(),
17952
+ design_docs: DesignDocsConfigSchema.optional(),
17926
17953
  ui_review: UIReviewConfigSchema.optional(),
17927
17954
  compaction_advisory: CompactionAdvisoryConfigSchema.optional(),
17928
17955
  lint: LintConfigSchema.optional(),
@@ -21341,6 +21368,9 @@ ${HARD_RULES}
21341
21368
  var init_critic = () => {};
21342
21369
  // src/agents/curator-agent.ts
21343
21370
  var init_curator_agent = () => {};
21371
+ // src/agents/docs.ts
21372
+ var init_docs = () => {};
21373
+
21344
21374
  // src/agents/reviewer.ts
21345
21375
  var init_reviewer = () => {};
21346
21376
  // src/agents/index.ts
@@ -21354,11 +21384,13 @@ var init_agents2 = __esm(() => {
21354
21384
  init_council_prompts();
21355
21385
  init_critic();
21356
21386
  init_curator_agent();
21387
+ init_docs();
21357
21388
  init_reviewer();
21358
21389
  init_architect();
21359
21390
  init_council_prompts();
21360
21391
  init_critic();
21361
21392
  init_curator_agent();
21393
+ init_docs();
21362
21394
  init_reviewer();
21363
21395
  warnedAgents = new Set;
21364
21396
  KNOWN_VARIANT_VALUES = new Set([
@@ -40234,6 +40266,122 @@ var init_deep_dive = __esm(() => {
40234
40266
  ]);
40235
40267
  });
40236
40268
 
40269
+ // src/commands/design-docs.ts
40270
+ function sanitizeDescription(raw) {
40271
+ const collapsed = raw.replace(/\s+/g, " ").trim();
40272
+ const stripped1 = collapsed.replace(/\[\s*MODE\s*:[^\]]*\]/gi, "");
40273
+ const stripped2 = stripped1.replace(/\[\s*MODE\s*:.*$/gi, "");
40274
+ const normalized = stripped2.replace(/\s+/g, " ").trim();
40275
+ if (normalized.length <= MAX_DESC_LEN)
40276
+ return normalized;
40277
+ return `${normalized.slice(0, MAX_DESC_LEN)}\u2026`;
40278
+ }
40279
+ function cleanFlagValue(raw) {
40280
+ if (raw.includes("[") || raw.includes("]") || /\s/.test(raw))
40281
+ return null;
40282
+ if (/\[\s*MODE\s*:/i.test(raw))
40283
+ return null;
40284
+ return raw;
40285
+ }
40286
+ function parseArgs3(args) {
40287
+ const result = {
40288
+ out: "docs",
40289
+ lang: "auto",
40290
+ update: false,
40291
+ rest: []
40292
+ };
40293
+ let i = 0;
40294
+ while (i < args.length) {
40295
+ const token = args[i];
40296
+ if (token === "--out") {
40297
+ if (i + 1 >= args.length || args[i + 1].startsWith("--")) {
40298
+ return { ...result, error: `Flag "${token}" requires a value` };
40299
+ }
40300
+ const value = args[++i];
40301
+ const clean = cleanFlagValue(value);
40302
+ if (clean === null || value.includes("..") || value.startsWith("/") || value.startsWith("\\") || /^[A-Za-z]:/.test(value)) {
40303
+ return {
40304
+ ...result,
40305
+ error: `Invalid --out value "${value}". Must be a project-relative directory with no brackets or spaces.`
40306
+ };
40307
+ }
40308
+ const trimmed = clean.replace(/[/\\]+$/, "");
40309
+ if (!trimmed || trimmed === ".") {
40310
+ return {
40311
+ ...result,
40312
+ error: `Invalid --out value "${value}". Must name a non-empty subdirectory.`
40313
+ };
40314
+ }
40315
+ result.out = trimmed;
40316
+ } else if (token === "--lang") {
40317
+ if (i + 1 >= args.length || args[i + 1].startsWith("--")) {
40318
+ return { ...result, error: `Flag "${token}" requires a value` };
40319
+ }
40320
+ const value = args[++i];
40321
+ const clean = cleanFlagValue(value);
40322
+ if (clean === null) {
40323
+ return {
40324
+ ...result,
40325
+ error: `Invalid --lang value "${value}". Must be a single token with no brackets or spaces.`
40326
+ };
40327
+ }
40328
+ result.lang = clean;
40329
+ } else if (token === "--update") {
40330
+ result.update = true;
40331
+ } else if (token.startsWith("--")) {
40332
+ return { ...result, error: `Unknown flag "${token}"` };
40333
+ } else {
40334
+ result.rest.push(token);
40335
+ }
40336
+ i++;
40337
+ }
40338
+ return result;
40339
+ }
40340
+ async function handleDesignDocsCommand(directory, args) {
40341
+ const parsed = parseArgs3(args);
40342
+ if (parsed.error) {
40343
+ return `Error: ${parsed.error}
40344
+
40345
+ ${USAGE3}`;
40346
+ }
40347
+ try {
40348
+ const { config: config3 } = loadPluginConfigWithMeta(directory);
40349
+ if (config3.design_docs?.enabled !== true) {
40350
+ return "Error: design docs are disabled. Set `design_docs.enabled: true` in " + `opencode-swarm.json to enable the docs_design agent and this command.
40351
+
40352
+ ` + USAGE3;
40353
+ }
40354
+ } catch (configErr) {
40355
+ 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.");
40356
+ }
40357
+ const description = sanitizeDescription(parsed.rest.join(" "));
40358
+ if (!description && !parsed.update) {
40359
+ return USAGE3;
40360
+ }
40361
+ const header = `[MODE: DESIGN_DOCS out=${parsed.out} lang=${parsed.lang} update=${parsed.update}] ${description}`;
40362
+ return header.trimEnd();
40363
+ }
40364
+ var MAX_DESC_LEN = 2000, USAGE3 = `Usage: /swarm design-docs <description> [--out <dir>] [--lang <name>] [--update]
40365
+
40366
+ Generate or sync language-agnostic design docs for the project under build:
40367
+ <out>/domain.md, <out>/technical-spec.md, <out>/behavior-spec.md,
40368
+ <out>/reference/{reference-impl,idiom-notes}.md, <out>/reference/traceability.json
40369
+
40370
+ Requires design_docs.enabled: true in opencode-swarm.json.
40371
+
40372
+ Examples:
40373
+ /swarm design-docs "terminal GitHub PR client"
40374
+ /swarm design-docs auth-service --lang rust
40375
+ /swarm design docs --update --out design
40376
+
40377
+ Flags:
40378
+ --out <dir> output directory (default "docs")
40379
+ --lang <name> target language for the reference/ docs (default: inferred)
40380
+ --update sync existing docs to current code/spec instead of generating fresh`;
40381
+ var init_design_docs = __esm(() => {
40382
+ init_config();
40383
+ });
40384
+
40237
40385
  // src/config/cache-paths.ts
40238
40386
  import * as os5 from "os";
40239
40387
  import * as path23 from "path";
@@ -45621,7 +45769,7 @@ function validateAndSanitizeUrl(rawUrl) {
45621
45769
  return { error: "Invalid URL format" };
45622
45770
  }
45623
45771
  }
45624
- function parseArgs3(args) {
45772
+ function parseArgs4(args) {
45625
45773
  const out = {
45626
45774
  plan: false,
45627
45775
  trace: false,
@@ -45712,24 +45860,24 @@ function parseGitRemoteUrl(remoteUrl) {
45712
45860
  return null;
45713
45861
  }
45714
45862
  function handleIssueCommand(_directory, args) {
45715
- const parsed = parseArgs3(args);
45863
+ const parsed = parseArgs4(args);
45716
45864
  const rawInput = parsed.rest.join(" ").trim();
45717
45865
  if (!rawInput) {
45718
- return USAGE3;
45866
+ return USAGE4;
45719
45867
  }
45720
45868
  const isFullUrl = /^https?:\/\//i.test(rawInput);
45721
45869
  const issueInfo = parseIssueRef(isFullUrl ? sanitizeUrl(rawInput) : rawInput);
45722
45870
  if (!issueInfo) {
45723
45871
  return `Error: Could not parse issue reference from "${rawInput}"
45724
45872
 
45725
- ${USAGE3}`;
45873
+ ${USAGE4}`;
45726
45874
  }
45727
45875
  const issueUrl = `https://github.com/${issueInfo.owner}/${issueInfo.repo}/issues/${issueInfo.number}`;
45728
45876
  const result = validateAndSanitizeUrl(issueUrl);
45729
45877
  if ("error" in result) {
45730
45878
  return `Error: ${result.error}
45731
45879
 
45732
- ${USAGE3}`;
45880
+ ${USAGE4}`;
45733
45881
  }
45734
45882
  const flags = [];
45735
45883
  if (parsed.plan)
@@ -45741,9 +45889,9 @@ ${USAGE3}`;
45741
45889
  const flagsStr = flags.length > 0 ? ` ${flags.join(" ")}` : "";
45742
45890
  return `[MODE: ISSUE_INGEST issue="${result.sanitized}"${flagsStr}]`;
45743
45891
  }
45744
- var MAX_URL_LEN = 2048, USAGE3;
45892
+ var MAX_URL_LEN = 2048, USAGE4;
45745
45893
  var init_issue = __esm(() => {
45746
- USAGE3 = [
45894
+ USAGE4 = [
45747
45895
  "Usage: /swarm issue <url|owner/repo#N|N> [--plan] [--trace] [--no-repro]",
45748
45896
  "",
45749
45897
  "Ingest a GitHub issue into the swarm workflow.",
@@ -49699,7 +49847,7 @@ function validateAndSanitizeUrl2(rawUrl) {
49699
49847
  return { error: "Invalid URL format" };
49700
49848
  }
49701
49849
  }
49702
- function parseArgs4(args) {
49850
+ function parseArgs5(args) {
49703
49851
  const out = { council: false, rest: [] };
49704
49852
  for (const token of args) {
49705
49853
  if (token === "--council") {
@@ -49783,31 +49931,31 @@ function parseGitRemoteUrl2(remoteUrl) {
49783
49931
  return null;
49784
49932
  }
49785
49933
  function handlePrReviewCommand(_directory, args) {
49786
- const parsed = parseArgs4(args);
49934
+ const parsed = parseArgs5(args);
49787
49935
  const rawInput = parsed.rest.join(" ").trim();
49788
49936
  if (!rawInput) {
49789
- return USAGE4;
49937
+ return USAGE5;
49790
49938
  }
49791
49939
  const isFullUrl = /^https?:\/\//i.test(rawInput);
49792
49940
  const prInfo = parsePrRef(isFullUrl ? sanitizeUrl2(rawInput) : rawInput);
49793
49941
  if (!prInfo) {
49794
49942
  return `Error: Could not parse PR reference from "${rawInput}"
49795
49943
 
49796
- ${USAGE4}`;
49944
+ ${USAGE5}`;
49797
49945
  }
49798
49946
  const prUrl = `https://github.com/${prInfo.owner}/${prInfo.repo}/pull/${prInfo.number}`;
49799
49947
  const result = validateAndSanitizeUrl2(prUrl);
49800
49948
  if ("error" in result) {
49801
49949
  return `Error: ${result.error}
49802
49950
 
49803
- ${USAGE4}`;
49951
+ ${USAGE5}`;
49804
49952
  }
49805
49953
  const councilFlag = parsed.council ? "council=true" : "council=false";
49806
49954
  return `[MODE: PR_REVIEW pr="${result.sanitized}" ${councilFlag}]`;
49807
49955
  }
49808
- var MAX_URL_LEN2 = 2048, USAGE4;
49956
+ var MAX_URL_LEN2 = 2048, USAGE5;
49809
49957
  var init_pr_review = __esm(() => {
49810
- USAGE4 = [
49958
+ USAGE5 = [
49811
49959
  "Usage: /swarm pr-review <url|owner/repo#N|N> [--council]",
49812
49960
  "",
49813
49961
  "Run a full swarm PR review on a GitHub pull request.",
@@ -57642,17 +57790,13 @@ var init_tool_policy = __esm(() => {
57642
57790
  "agents",
57643
57791
  "config",
57644
57792
  "config doctor",
57645
- "config-doctor",
57646
- "doctor",
57647
57793
  "doctor tools",
57648
57794
  "status",
57649
57795
  "show-plan",
57650
- "plan",
57651
57796
  "help",
57652
57797
  "history",
57653
57798
  "evidence",
57654
57799
  "evidence summary",
57655
- "evidence-summary",
57656
57800
  "retrieve",
57657
57801
  "diagnose",
57658
57802
  "preflight",
@@ -57669,8 +57813,7 @@ var init_tool_policy = __esm(() => {
57669
57813
  "memory import",
57670
57814
  "memory migrate",
57671
57815
  "sync-plan",
57672
- "export",
57673
- "list-agents"
57816
+ "export"
57674
57817
  ];
57675
57818
  SWARM_COMMAND_TOOL_ALLOWLIST = new Set([
57676
57819
  "agents",
@@ -58252,6 +58395,7 @@ var init_registry = __esm(() => {
58252
58395
  init_curate();
58253
58396
  init_dark_matter();
58254
58397
  init_deep_dive();
58398
+ init_design_docs();
58255
58399
  init_diagnose();
58256
58400
  init_doctor();
58257
58401
  init_evidence();
@@ -58567,6 +58711,20 @@ Subcommands:
58567
58711
  category: "agent",
58568
58712
  aliasOf: "deep-dive"
58569
58713
  },
58714
+ "design-docs": {
58715
+ handler: async (ctx) => handleDesignDocsCommand(ctx.directory, ctx.args),
58716
+ description: "Generate or sync language-agnostic design docs (domain, technical-spec, behavior-spec, reference/) for the project under build [description]",
58717
+ args: "<description> [--out <dir>] [--lang <name>] [--update]",
58718
+ 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.",
58719
+ category: "agent"
58720
+ },
58721
+ "design docs": {
58722
+ handler: async (ctx) => handleDesignDocsCommand(ctx.directory, ctx.args),
58723
+ description: "Alias for /swarm design-docs \u2014 generate or sync design docs",
58724
+ args: "<description> [--out <dir>] [--lang <name>] [--update]",
58725
+ category: "agent",
58726
+ aliasOf: "design-docs"
58727
+ },
58570
58728
  issue: {
58571
58729
  handler: async (ctx) => handleIssueCommand(ctx.directory, ctx.args),
58572
58730
  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]";
@@ -1,5 +1,5 @@
1
1
  import type { ResolvedSwarmCommand, SwarmCommandPolicyResult } from './command-dispatch.js';
2
- export declare const SWARM_COMMAND_TOOL_COMMANDS: readonly ["agents", "config", "config doctor", "config-doctor", "doctor", "doctor tools", "status", "show-plan", "plan", "help", "history", "evidence", "evidence summary", "evidence-summary", "retrieve", "diagnose", "preflight", "benchmark", "knowledge", "memory", "memory status", "memory pending", "memory recall-log", "memory compact", "memory stale", "memory export", "memory evaluate", "memory import", "memory migrate", "sync-plan", "export", "list-agents"];
2
+ export declare const SWARM_COMMAND_TOOL_COMMANDS: readonly ["agents", "config", "config doctor", "doctor tools", "status", "show-plan", "help", "history", "evidence", "evidence summary", "retrieve", "diagnose", "preflight", "benchmark", "knowledge", "memory", "memory status", "memory pending", "memory recall-log", "memory compact", "memory stale", "memory export", "memory evaluate", "memory import", "memory migrate", "sync-plan", "export"];
3
3
  export type SwarmCommandToolInputCommand = (typeof SWARM_COMMAND_TOOL_COMMANDS)[number];
4
4
  export declare const SWARM_COMMAND_TOOL_ALLOWLIST: Set<string>;
5
5
  /**
@@ -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 {};