@documentation-robotics/cli 0.3.0 → 0.4.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/README.md +10 -14
- package/dist/analyzers/active-analyzer.js +62 -0
- package/dist/analyzers/active-analyzer.js.map +7 -0
- package/dist/analyzers/cards/build.js +21 -1
- package/dist/analyzers/cards/build.js.map +2 -2
- package/dist/analyzers/cards/extract.js +138 -0
- package/dist/analyzers/cards/extract.js.map +7 -0
- package/dist/analyzers/cards/routes.js +96 -0
- package/dist/analyzers/cards/routes.js.map +7 -0
- package/dist/analyzers/cbm-analyzer.js +76 -4
- package/dist/analyzers/cbm-analyzer.js.map +2 -2
- package/dist/analyzers/cbm-responses.js +12 -6
- package/dist/analyzers/cbm-responses.js.map +2 -2
- package/dist/analyzers/code-changes.js +159 -0
- package/dist/analyzers/code-changes.js.map +7 -0
- package/dist/analyzers/edge-relationships.js +6 -2
- package/dist/analyzers/edge-relationships.js.map +2 -2
- package/dist/analyzers/extraction-plan.js +541 -0
- package/dist/analyzers/extraction-plan.js.map +7 -0
- package/dist/analyzers/index-job.js +229 -0
- package/dist/analyzers/index-job.js.map +7 -0
- package/dist/cli.js +12 -10
- package/dist/cli.js.map +2 -2
- package/dist/coding-agents/drbot-mcp.js +120 -18
- package/dist/coding-agents/drbot-mcp.js.map +2 -2
- package/dist/commands/add.js +4 -2
- package/dist/commands/add.js.map +2 -2
- package/dist/commands/analyzer.js +35 -35
- package/dist/commands/analyzer.js.map +2 -2
- package/dist/commands/changeset-verify.js +16 -8
- package/dist/commands/changeset-verify.js.map +2 -2
- package/dist/commands/changeset.js +41 -11
- package/dist/commands/changeset.js.map +2 -2
- package/dist/commands/init.js +9 -26
- package/dist/commands/init.js.map +2 -2
- package/dist/commands/mcp.js +35 -31
- package/dist/commands/mcp.js.map +3 -3
- package/dist/commands/relationship.js +2 -12
- package/dist/commands/relationship.js.map +2 -2
- package/dist/commands/reports.js +3 -3
- package/dist/commands/reports.js.map +2 -2
- package/dist/commands/update.js +14 -13
- package/dist/commands/update.js.map +2 -2
- package/dist/commands/upgrade.js +28 -120
- package/dist/commands/upgrade.js.map +2 -2
- package/dist/commands/validate.js +19 -3
- package/dist/commands/validate.js.map +2 -2
- package/dist/commands/version.js +1 -1
- package/dist/commands/visualize.js +30 -12
- package/dist/commands/visualize.js.map +2 -2
- package/dist/core/annotation-store.js +15 -5
- package/dist/core/annotation-store.js.map +2 -2
- package/dist/core/catalog-migration.js +2 -1
- package/dist/core/catalog-migration.js.map +2 -2
- package/dist/core/changeset-base-index.js +7 -0
- package/dist/core/changeset-base-index.js.map +2 -2
- package/dist/core/changeset-brief-compact.js +256 -0
- package/dist/core/changeset-brief-compact.js.map +7 -0
- package/dist/core/changeset-verify.js +356 -26
- package/dist/core/changeset-verify.js.map +3 -3
- package/dist/core/extraction-observability.js +161 -0
- package/dist/core/extraction-observability.js.map +7 -0
- package/dist/core/migration-registry.js +13 -1
- package/dist/core/migration-registry.js.map +2 -2
- package/dist/core/project-init.js +53 -0
- package/dist/core/project-init.js.map +7 -0
- package/dist/core/relationship-staging.js +94 -1
- package/dist/core/relationship-staging.js.map +2 -2
- package/dist/core/staged-changeset-storage.js +83 -3
- package/dist/core/staged-changeset-storage.js.map +2 -2
- package/dist/core/staging-area.js +85 -8
- package/dist/core/staging-area.js.map +2 -2
- package/dist/core/upgrade-plan.js +117 -0
- package/dist/core/upgrade-plan.js.map +7 -0
- package/dist/generated/relationship-index.js +124 -15
- package/dist/generated/relationship-index.js.map +2 -2
- package/dist/integrations/claude_code/.claude-plugin/plugin.json +24 -0
- package/dist/integrations/claude_code/agents/dr-architect.md +19 -5
- package/dist/integrations/claude_code/agents/dr-extractor.md +7 -1
- package/dist/integrations/claude_code/commands/dr-changeset.md +2 -1
- package/dist/integrations/claude_code/commands/dr-map.md +7 -1
- package/dist/integrations/claude_code/commands/dr-plan.md +42 -16
- package/dist/integrations/claude_code/docs/MCP_SERVER.md +28 -31
- package/dist/integrations/claude_code/docs/README.md +20 -1
- package/dist/integrations/claude_code/plugin-agents/dr-advisor.md +255 -0
- package/dist/integrations/claude_code/plugin-agents/dr-architect.md +306 -0
- package/dist/integrations/claude_code/skills/dr_13_testing_layer/SKILL.md +3 -0
- package/dist/integrations/claude_code/skills/dr_change_planning/SKILL.md +90 -31
- package/dist/integrations/claude_code/skills/dr_changeset_reviewer/SKILL.md +5 -0
- package/dist/integrations/claude_code/skills/dr_engineering_guide/SKILL.md +5 -0
- package/dist/integrations/github_copilot/agents/dr-architect.md +2 -0
- package/dist/integrations/github_copilot/skills/dr_13_testing_layer/SKILL.md +3 -0
- package/dist/integrations/github_copilot/skills/dr_change_planning/SKILL.md +88 -30
- package/dist/mcp/changeset-only.js +14 -3
- package/dist/mcp/changeset-only.js.map +2 -2
- package/dist/mcp/project-root.js +85 -0
- package/dist/mcp/project-root.js.map +7 -0
- package/dist/mcp/server-instructions.js +27 -0
- package/dist/mcp/server-instructions.js.map +7 -0
- package/dist/mcp/strict-schema.js +52 -0
- package/dist/mcp/strict-schema.js.map +7 -0
- package/dist/mcp/tool-registry.js +39 -5
- package/dist/mcp/tool-registry.js.map +2 -2
- package/dist/mcp/tools/changeset-analysis-tools.js +25 -5
- package/dist/mcp/tools/changeset-analysis-tools.js.map +3 -3
- package/dist/mcp/tools/changeset-commit.js +224 -0
- package/dist/mcp/tools/changeset-commit.js.map +7 -0
- package/dist/mcp/tools/changeset-editing.js +133 -57
- package/dist/mcp/tools/changeset-editing.js.map +3 -3
- package/dist/mcp/tools/changeset-lifecycle.js +1 -1
- package/dist/mcp/tools/changeset-lifecycle.js.map +2 -2
- package/dist/mcp/tools/changeset-verify.js +12 -6
- package/dist/mcp/tools/changeset-verify.js.map +2 -2
- package/dist/mcp/tools/codebase-extract.js +836 -0
- package/dist/mcp/tools/codebase-extract.js.map +7 -0
- package/dist/mcp/tools/codebase-index.js +125 -0
- package/dist/mcp/tools/codebase-index.js.map +7 -0
- package/dist/mcp/tools/codebase-shared.js +265 -0
- package/dist/mcp/tools/codebase-shared.js.map +7 -0
- package/dist/mcp/tools/codebase-verify.js +48 -0
- package/dist/mcp/tools/codebase-verify.js.map +7 -0
- package/dist/mcp/tools/index.js +15 -0
- package/dist/mcp/tools/index.js.map +2 -2
- package/dist/mcp/tools/model-add.js +189 -73
- package/dist/mcp/tools/model-add.js.map +2 -2
- package/dist/mcp/tools/model-update.js +16 -12
- package/dist/mcp/tools/model-update.js.map +2 -2
- package/dist/mcp/tools/model-validate.js +46 -4
- package/dist/mcp/tools/model-validate.js.map +2 -2
- package/dist/mcp/tools/project-status-collectors.js +381 -0
- package/dist/mcp/tools/project-status-collectors.js.map +7 -0
- package/dist/mcp/tools/project-status.js +237 -0
- package/dist/mcp/tools/project-status.js.map +7 -0
- package/dist/mcp/tools/project-tools.js +505 -0
- package/dist/mcp/tools/project-tools.js.map +7 -0
- package/dist/mcp/tools/relationship-tools.js +89 -20
- package/dist/mcp/tools/relationship-tools.js.map +2 -2
- package/dist/mcp/tools/review-open.js +210 -0
- package/dist/mcp/tools/review-open.js.map +7 -0
- package/dist/mcp/tools/shared.js +10 -2
- package/dist/mcp/tools/shared.js.map +2 -2
- package/dist/reports/model-report-orchestrator.js +31 -2
- package/dist/reports/model-report-orchestrator.js.map +2 -2
- package/dist/schemas/bundled/analyzers/cbm.json +22 -10
- package/dist/schemas/bundled/analyzers/manifest.json +2 -2
- package/dist/schemas/bundled/api.json +1 -1
- package/dist/schemas/bundled/apm.json +1 -1
- package/dist/schemas/bundled/application.json +1 -1
- package/dist/schemas/bundled/base.json +1 -1
- package/dist/schemas/bundled/business.json +1 -1
- package/dist/schemas/bundled/data-model.json +1 -1
- package/dist/schemas/bundled/data-store.json +1 -1
- package/dist/schemas/bundled/manifest.json +3 -3
- package/dist/schemas/bundled/motivation.json +1 -1
- package/dist/schemas/bundled/navigation.json +1 -1
- package/dist/schemas/bundled/product.json +1 -1
- package/dist/schemas/bundled/security.json +1 -1
- package/dist/schemas/bundled/technology.json +1 -1
- package/dist/schemas/bundled/testing.json +145 -1
- package/dist/schemas/bundled/ux.json +1 -1
- package/dist/server/server.js +508 -237
- package/dist/server/server.js.map +3 -3
- package/dist/server/viewer-registry.js +264 -0
- package/dist/server/viewer-registry.js.map +7 -0
- package/dist/telemetry/index.js +1 -1
- package/dist/utils/id-generator.js +5 -2
- package/dist/utils/id-generator.js.map +2 -2
- package/dist/utils/source-reference.js +58 -27
- package/dist/utils/source-reference.js.map +2 -2
- package/dist/utils/spec-version.js +2 -2
- package/dist/utils/spec-version.js.map +1 -1
- package/dist/validators/model-warnings.js +28 -0
- package/dist/validators/model-warnings.js.map +7 -0
- package/dist/viewer/README.md +6 -6
- package/dist/viewer/assets/main-CUOQGGRA.css +1 -0
- package/dist/viewer/assets/main-DvH3gYrI.js +84 -0
- package/dist/viewer/index.html +2 -2
- package/dist/viewer/manifest.json +10 -10
- package/dist/viewer/version.json +1 -1
- package/package.json +1 -1
- package/dist/viewer/assets/main-CxzcuU_o.js +0 -84
- package/dist/viewer/assets/main-j-7ULYpm.css +0 -1
package/dist/cli.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/cli.ts"],
|
|
4
|
-
"sourcesContent": ["#!/usr/bin/env node\n\n/**\n * Documentation Robotics CLI - Bun Implementation\n * Entry point for the command-line interface\n *\n * Instrumented with OpenTelemetry to create root spans for command execution.\n * Telemetry is controlled by the TELEMETRY_ENABLED build-time constant.\n */\n\nimport { Command, CommanderError } from \"commander\";\nimport { setGlobalOptions } from \"./utils/globals.js\";\nimport { installAnsiSuppressor } from \"./utils/ansi-suppressor.js\";\nimport { initCommand } from \"./commands/init.js\";\nimport { addCommand } from \"./commands/add.js\";\nimport { updateCommand } from \"./commands/update.js\";\nimport { deleteCommand } from \"./commands/delete.js\";\nimport { showCommand } from \"./commands/show.js\";\nimport { listCommand } from \"./commands/list.js\";\nimport { searchCommand } from \"./commands/search.js\";\nimport { validateCommand } from \"./commands/validate.js\";\nimport { infoCommand } from \"./commands/info.js\";\nimport { relationshipCommands } from \"./commands/relationship.js\";\nimport { elementCommands } from \"./commands/element.js\";\nimport { schemaCommands } from \"./commands/schema.js\";\nimport { catalogCommands } from \"./commands/catalog.js\";\nimport { docsCommands } from \"./commands/docs.js\";\nimport { traceCommand } from \"./commands/trace.js\";\nimport { exportCommand } from \"./commands/export.js\";\nimport { importCommand } from \"./commands/import.js\";\nimport { chatCommand } from \"./commands/chat.js\";\nimport { upgradeCommand } from \"./commands/upgrade.js\";\nimport { conformanceCommand } from \"./commands/conformance.js\";\nimport { changesetCommands } from \"./commands/changeset.js\";\nimport { farmCommands } from \"./commands/farm.js\";\nimport { claudeCommands } from \"./commands/claude.js\";\nimport { copilotCommands } from \"./commands/copilot.js\";\nimport { analyzerCommands } from \"./commands/analyzer.js\";\nimport { versionCommand } from \"./commands/version.js\";\nimport { statsCommand } from \"./commands/stats.js\";\nimport { reportCommand } from \"./commands/report.js\";\nimport { reportsCommands } from \"./commands/reports.js\";\nimport { auditCommand } from \"./commands/audit.js\";\nimport { auditDiffCommand } from \"./commands/audit-diff.js\";\nimport { auditSnapshotsCommand } from \"./commands/audit-snapshots.js\";\nimport { repairAttributeCollisionCommand } from \"./commands/repair.js\";\nimport { initTelemetry, startActiveSpan, shutdownTelemetry } from \"./telemetry/index.js\";\nimport { installConsoleInterceptor } from \"./telemetry/console-interceptor.js\";\nimport { getErrorMessage, CLIError } from \"./utils/errors.js\";\nimport { getCliVersion } from \"./utils/spec-version.js\";\n\n// Declare TELEMETRY_ENABLED as a build-time constant (substituted by esbuild)\n// Provide runtime fallback when not running through esbuild\ndeclare const TELEMETRY_ENABLED: boolean;\nconst isTelemetryEnabled = typeof TELEMETRY_ENABLED !== \"undefined\" ? TELEMETRY_ENABLED : false;\n\n// Commands that require console interceptor for telemetry logging\nconst CONSOLE_LOGGING_COMMANDS = new Set(['chat', 'validate', 'import', 'export']);\n\n// Suppress ANSI color output on non-TTY stdout\nif (!process.stdout.isTTY) {\n process.env.FORCE_COLOR = \"0\";\n process.env.NO_COLOR = \"1\";\n}\n\n// Install the ANSI suppressor to strip color codes from console output when not on TTY\ninstallAnsiSuppressor();\n\n/**\n * Extract exit code from an error object.\n * Handles CLIError instances and duck-typed objects with exitCode property.\n */\nasync function extractExitCode(error: unknown): Promise<number> {\n const { CLIError } = await import(\"./utils/errors.js\");\n\n if (error instanceof CLIError) {\n return error.exitCode;\n }\n\n // Commander's own errors (--help, unknown commands, etc.) carry exitCode as\n // expected control flow \u2014 handle them directly without duck-typing.\n if (error instanceof CommanderError) {\n return error.exitCode;\n }\n\n // Fallback for duck-typing (handles bundling/module issues)\n if (error && typeof error === \"object\" && \"exitCode\" in error) {\n const errorObj = error as any;\n if (typeof errorObj.exitCode === \"number\") {\n // Validate this looks like a CLIError before accepting\n if (errorObj.name === \"CLIError\" || errorObj.message) {\n if (process.argv.includes(\"--debug\")) {\n console.warn(\n \"[DEBUG] Using duck-typed error object as fallback - this may indicate a module loading issue\"\n );\n }\n return errorObj.exitCode;\n }\n }\n }\n\n return 1;\n}\n\nconst cliVersion = getCliVersion();\n\nconst program = new Command();\n\n// Handle --version and -V flags by redirecting to version command\n// This ensures they go through the telemetry wrapper\nif (process.argv.includes(\"--version\") || process.argv.includes(\"-V\")) {\n process.argv = [\"node\", \"dr\", \"version\"];\n}\n\nprogram\n .name(\"dr\")\n .description(\"Documentation Robotics CLI - Architecture Model Management\")\n .option(\"-v, --verbose\", \"Enable verbose output\")\n .option(\"--debug\", \"Enable debug mode\")\n .option(\"--json\", \"Output as JSON (supported on mutating and query commands)\")\n .option(\"--codebase-path <path>\", \"Override codebase root path (default: resolved from manifest or project root)\")\n .exitOverride() // Prevent Commander from calling process.exit() - we handle exit ourselves\n .showSuggestionAfterError() // \"Did you mean X?\" on unknown commands/options\n .hook(\"preAction\", async (thisCommand) => {\n // Set up global state (verbose/debug/json flags)\n const options = thisCommand.opts();\n setGlobalOptions({\n verbose: options.verbose as boolean | undefined,\n debug: options.debug as boolean | undefined,\n json: options.json as boolean | undefined,\n codebasePath: options.codebasePath as string | undefined,\n });\n });\n\n// Model commands\nprogram\n .command(\"init [name]\")\n .description(\"Initialize a new architecture model\")\n .option(\"--name <name>\", \"Model name (overrides positional argument)\")\n .option(\"--author <author>\", \"Model author\")\n .option(\"--description <desc>\", \"Model description\")\n .addHelpText(\n \"after\",\n `\nExamples:\n $ dr init\n $ dr init claudetoreum\n $ dr init \"Enterprise Architecture\" --author \"Team A\"\n $ dr init --name \"My Project\" --description \"13-layer federated model\"`\n )\n .action((name, options) => initCommand({ ...options, name: options.name || name }));\n\nprogram\n .command(\"add <layer> <type> <name>\")\n .description(\"Add an element to a layer\")\n .option(\"--model <path>\", \"Path to model root (contains model/manifest.yaml)\")\n .option(\"--name <name>\", \"Element display name (defaults to the name argument)\")\n .option(\"--description <desc>\", \"Element description\")\n .option(\"--attributes <json>\", \"Element type-specific attributes as JSON object\")\n .option(\"--source-file <path>\", \"Source file path (relative from repository root)\")\n .option(\"--source-symbol <name>\", \"Symbol name (class, function, variable) in source file\")\n .option(\"--source-provenance <type>\", \"Provenance type: extracted, manual, inferred, generated\")\n .option(\"--source-repo-remote <url>\", \"Git remote URL for repository context\")\n .option(\"--source-repo-commit <sha>\", \"Git commit SHA (40 hex characters) for repository context\")\n .option(\"--verbose\", \"Show detailed output (can also use global -v flag)\")\n .addHelpText(\n \"after\",\n `\nExamples:\n $ dr add business service \"Customer Management\"\n $ dr add api operation \"Create Customer\" --attributes '{\"operationId\":\"createCustomer\",\"summary\":\"Create a customer\",\"tags\":\"customers\"}'\n $ dr add application component \"Customer API\" --description \"REST API for customer operations\"\n $ dr add security policy \"Auth Validator\" --source-file \"src/auth/validator.ts\" --source-symbol \"validateToken\" --source-provenance \"extracted\"\n\nNote: Element IDs are generated automatically in format {layer}.{type}.{kebab-name}`\n )\n .action((layer, type, name, options) =>\n addCommand(layer, type, name, { ...options, verbose: options.verbose ?? program.opts().verbose }));\n\nprogram\n .command(\"update <id>\")\n .description(\"Update an element\")\n .option(\"--model <path>\", \"Path to model root (contains model/manifest.yaml)\")\n .option(\"--name <name>\", \"New element name\")\n .option(\"--description <desc>\", \"New description\")\n .option(\"--type <new-type>\", \"Change element type (must be valid for the element's layer; incompatible attributes must be cleaned up manually)\")\n .option(\"--attributes <json>\", \"Updated type-specific attributes (JSON)\")\n .option(\"--attribute-patch <json>\", \"Merge these attributes into the current ones (JSON object; null removes a key). Cannot be combined with --attributes\")\n .option(\"--source-file <path>\", \"Source file path (relative from repository root)\")\n .option(\"--source-symbol <name>\", \"Symbol name (class, function, variable) in source file\")\n .option(\"--source-provenance <type>\", \"Provenance type: extracted, manual, inferred, generated\")\n .option(\"--source-repo-remote <url>\", \"Git remote URL for repository context\")\n .option(\"--source-repo-commit <sha>\", \"Git commit SHA (40 hex characters) for repository context\")\n .option(\"--clear-source-reference\", \"Remove source reference from element\")\n .option(\"--verbose\", \"Show detailed output (can also use global -v flag)\")\n .addHelpText(\n \"after\",\n `\nNote: Changes are written immediately to model files.\nTo track changes for review, activate a changeset first:\n $ dr changeset activate my-changeset\n\nExamples:\n $ dr update api-endpoint-create-customer --name \"Create Customer (v2)\"\n $ dr update business-service-order --description \"Updated description\"\n $ dr update application-applicationfunction-process-orders --type applicationservice\n $ dr update api.operation.create-customer --attribute-patch '{\"summary\":\"Create a customer (v2)\"}'\n $ dr update security-policy-auth --source-file \"src/auth/policy.ts\" --source-provenance \"extracted\"`\n )\n .action((id, options) =>\n updateCommand(id, { ...options, verbose: options.verbose ?? program.opts().verbose }));\n\nprogram\n .command(\"delete <id>\")\n .description(\"Delete an element\")\n .option(\"--model <path>\", \"Path to model root (contains model/manifest.yaml)\")\n .option(\"--force\", \"Skip dependency checks (confirmation is also skipped in non-TTY environments)\")\n .option(\"--cascade\", \"Remove dependent elements automatically\")\n .option(\"--dry-run\", \"Show what would be removed without actually removing\")\n .option(\"--verbose\", \"Show detailed output (can also use global -v flag)\")\n .addHelpText(\n \"after\",\n `\nExamples:\n $ dr delete api-endpoint-old-endpoint\n $ dr delete api-endpoint-old-endpoint --force\n $ dr delete api-endpoint-old-endpoint --cascade\n $ dr delete api-endpoint-old-endpoint --dry-run\n $ dr delete api-endpoint-old-endpoint --cascade --dry-run`\n )\n .action((id, options) =>\n deleteCommand(id, { ...options, verbose: options.verbose ?? program.opts().verbose }));\n\nprogram\n .command(\"show <id>\")\n .description(\"Display element details\")\n .option(\"--model <path>\", \"Path to model root (contains model/manifest.yaml)\")\n .addHelpText(\n \"after\",\n `\nExamples:\n $ dr show api-endpoint-create-customer\n $ dr show business-service-order-mgmt`\n )\n .action((id, options) => showCommand(id, options));\n\nprogram\n .command(\"list [layer]\")\n .description(\"List elements in a layer (or all layers if omitted)\")\n .option(\"--type <type>\", \"Filter by element type\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--model <path>\", \"Path to model root (contains model/manifest.yaml)\")\n .addHelpText(\n \"after\",\n `\nExamples:\n $ dr list\n $ dr list api\n $ dr list business --type businessservice\n $ dr list api --json\n $ dr list --json`\n )\n .action((layer, options) => {\n return listCommand(layer, { ...options, json: options.json ?? program.opts().json });\n });\n\nprogram\n .command(\"search <query>\")\n .description(\"Search for elements by name or ID\")\n .option(\"--layer <layer>\", \"Limit search to specific layer\")\n .option(\"--type <type>\", \"Filter by element type\")\n .option(\n \"--source-file <path>\",\n \"Find elements referencing a source file (takes precedence over pattern matching)\"\n )\n .option(\"--json\", \"Output as JSON\")\n .addHelpText(\n \"after\",\n `\nExamples:\n $ dr search customer\n $ dr search \"order processing\" --layer business\n $ dr search create-* --type endpoint\n $ dr search \"\" --source-file src/api/customer.ts`\n )\n .action((query, options) => {\n return searchCommand(query, { ...options, json: options.json ?? program.opts().json });\n });\n\nprogram\n .command(\"validate\")\n .description(\"Validate the architecture model\")\n .option(\"--layers <layers...>\", \"Specific layers to validate\")\n .option(\"--strict\", \"Treat warnings as errors\")\n .option(\"--verbose\", \"Show detailed validation output with relationship breakdown\")\n .option(\"--quiet\", \"Show minimal output\")\n .option(\"--output <path>\", \"Export validation report to file (JSON or Markdown)\")\n .option(\"--model <path>\", \"Path to model root (contains model/manifest.yaml)\")\n .option(\"--orphans\", \"Show only orphaned elements grouped by layer with relationship suggestions\")\n .option(\"--all\", \"Run all validations (default behavior)\")\n .option(\"--markdown\", \"Validate markdown structure\")\n .option(\"--schemas\", \"Validate JSON schemas\")\n .option(\"--schema\", \"Validate JSON schemas (alias for --schemas)\")\n .option(\"--relationships\", \"Validate relationships\")\n .option(\"--structure\", \"Validate documentation structure\")\n .option(\"--naming\", \"Validate naming conventions\")\n .option(\"--references\", \"Validate cross-layer references\")\n .option(\"--scope <scope>\", \"Validation scope: 'local' (default) or 'composed' for cross-model validation\")\n .option(\"--model-path <mapping...>\", \"Override filesystem path for external model (format: model-name=/path/to/project-root, can be repeated)\")\n .addHelpText(\n \"after\",\n `\nExamples:\n $ dr validate\n $ dr validate --all --strict\n $ dr validate --verbose\n $ dr validate --quiet\n $ dr validate --output report.json\n $ dr validate --output report.md\n $ dr validate --schemas\n $ dr validate --relationships\n $ dr validate --layers business api\n $ dr validate --orphans\n $ dr validate --orphans --output orphans.json\n $ dr validate --scope composed --model-path auth-service=/path/to/auth-service-repo\n $ dr validate --scope composed --model-path auth-service=/path/to/auth-service-repo --model-path payment-service=/path/to/payment-repo\n\nNote: When using --model-path, pass the project root (where documentation-robotics/model/ is located).`\n )\n .action(validateCommand);\n\nprogram\n .command(\"export <format>\")\n .description(\"Export the architecture model to various formats\")\n .option(\"--output <path>\", \"Output file path (default: print to stdout)\")\n .option(\"--layers <layers...>\", \"Specific layers to export\")\n .option(\"--model <path>\", \"Path to model root directory or manifest.yaml file\")\n .option(\"--include-sources\", \"Include source file paths in PlantUML diagrams as notes\")\n .addHelpText(\n \"after\",\n `\nSupported formats:\n archimate Export to ArchiMate XML (layers 1, 2, 5, 6)\n openapi Export to OpenAPI 3.0 specification (layer 7)\n jsonschema Export to JSON Schema (layer 8)\n plantuml Export to PlantUML diagram\n graphml Export to GraphML (graph visualization)\n markdown Export to Markdown documentation\n\nExamples:\n $ dr export archimate --output model.xml\n $ dr export openapi --layers api\n $ dr export plantuml --include-sources --output diagram.puml\n $ dr export markdown --output docs/architecture.md`\n )\n .action(async (format, options) => {\n await exportCommand({\n format,\n output: options.output,\n layers: options.layers,\n model: options.model,\n includeSources: options.includeSources,\n });\n });\n\nprogram\n .command(\"import <format>\")\n .description(\"Import architecture model from various formats\")\n .option(\"--input <path>\", \"Input file path (required)\", undefined)\n .option(\"--model <path>\", \"Path to model root directory or manifest.yaml file\")\n .option(\n \"--merge-strategy <strategy>\",\n \"How to handle existing elements: add, update, skip (default: add)\"\n )\n .addHelpText(\n \"after\",\n `\nSupported formats:\n archimate Import from ArchiMate XML (layers 1, 2, 5, 6)\n openapi Import from OpenAPI 3.0 specification (layer 7)\n\nExamples:\n $ dr import archimate --input model.xml\n $ dr import openapi --input api.json --merge-strategy add\n $ dr import archimate --input model.xml --model ./myproject`\n )\n .action(async (format, options) => {\n if (!options.input) {\n console.error(\"Error: --input path is required\");\n process.exit(1);\n }\n await importCommand({\n format,\n input: options.input,\n model: options.model,\n mergeStrategy: options.mergeStrategy as \"add\" | \"update\" | \"skip\" | undefined,\n });\n });\n\nprogram\n .command(\"info\")\n .description(\"Show model information\")\n .option(\"--layer <layer>\", \"Show specific layer details\")\n .option(\"--verbose\", \"Show detailed breakdown by element type\")\n .addHelpText(\n \"after\",\n `\nExamples:\n $ dr info\n $ dr info --layer business\n $ dr info --layer api --verbose`\n )\n .action(infoCommand);\n\nprogram\n .command(\"stats\")\n .description(\"Display model statistics and health metrics\")\n .option(\"--model <path>\", \"Path to the model directory\")\n .option(\"--format <format>\", \"Output format: text (default), json, markdown, compact\")\n .option(\"--output <path>\", \"Output file path (auto-detects format from extension)\")\n .option(\"--compact\", \"Show compact one-line summary\")\n .option(\"--verbose\", \"Show detailed information\")\n .addHelpText(\n \"after\",\n `\nOutput formats:\n text Full formatted statistics (default)\n json JSON output for automation\n markdown Markdown report format\n compact Single-line summary\n\nExamples:\n $ dr stats # Show full statistics\n $ dr stats --compact # Show one-line summary\n $ dr stats --format json # Output as JSON\n $ dr stats --output stats.md # Save as markdown file\n $ dr stats --output stats.json # Save as JSON file\n $ dr stats --verbose # Show detailed information`\n )\n .action((options) => statsCommand(options));\n\nprogram\n .command(\"report\")\n .description(\"Generate comprehensive architecture reports\")\n .option(\"--model <path>\", \"Path to the model directory\")\n .option(\"--type <type>\", \"Report type: comprehensive (default), statistics, relationships, data-model, quality\")\n .option(\"--format <format>\", \"Output format: text (default), json, markdown\")\n .option(\"--output <path>\", \"Output file path (auto-detects format from extension)\")\n .option(\"--verbose\", \"Show detailed information\")\n .option(\"--include-data-model\", \"Include data model analysis (default: true)\")\n .option(\"--include-quality\", \"Include quality metrics (default: true)\")\n .addHelpText(\n \"after\",\n `\nReport types:\n comprehensive Full report with statistics, relationships, and data model (default)\n statistics Statistics and quality metrics\n relationships Relationship analysis and classification\n data-model Layer 8 data model analysis\n quality Quality metrics and recommendations\n\nOutput formats:\n text Full formatted report (default)\n json JSON output for automation\n markdown Markdown report format\n\nExamples:\n $ dr report # Show comprehensive report\n $ dr report --type relationships # Show relationship analysis\n $ dr report --format json # Output as JSON\n $ dr report --output report.md # Save as markdown file\n $ dr report --type data-model --output dm.md # Data model report as markdown\n $ dr report --verbose # Show detailed information`\n )\n .action((options) => reportCommand(options));\n\n// Reports subcommands (managed layer report files)\nconst reportsGroup = program.command(\"reports\").description(\"Manage architecture layer reports\");\nreportsCommands(reportsGroup);\n\n// Audit command - Relationship analysis\nprogram\n .command(\"audit [layer]\")\n .description(\"Analyze relationship coverage, gaps, duplicates, and balance\")\n .option(\"--type <type>\", \"Audit type: relationships (default), nodes, all\")\n .option(\"--format <format>\", \"Output format: text (default), json, markdown\")\n .option(\"--output <path>\", \"Output file path (auto-detects format from extension)\")\n .option(\"--verbose\", \"Show detailed analysis\")\n .option(\"--save-snapshot\", \"Save audit report as snapshot for differential analysis\")\n .addHelpText(\n \"after\",\n `\nAudit types:\n relationships Relationship coverage, gaps, duplicates, balance (default)\n nodes Node type usage distribution across model layers\n all Both relationship and node audits\n\nOutput formats:\n text Full formatted audit report (default)\n json JSON output for automation\n markdown Markdown audit report format\n\nExamples:\n $ dr audit # Full relationship audit of all layers\n $ dr audit security # Audit security layer only\n $ dr audit --type nodes # Node type distribution audit\n $ dr audit --type all # Combined relationship + node audit\n $ dr audit --format json # Output as JSON\n $ dr audit --output audit.md # Save as markdown file\n $ dr audit --verbose # Show detailed analysis\n $ dr audit --save-snapshot # Save snapshot for later comparison\n $ dr audit api --output api-audit.json # API layer audit as JSON`\n )\n .action((layer, options) =>\n auditCommand({ ...options, layer, verbose: options.verbose ?? program.opts().verbose }));\n\n// Audit diff command - Compare snapshots\nprogram\n .command(\"audit:diff\")\n .description(\"Compare before/after audit snapshots\")\n .option(\"--before <id>\", \"Before snapshot ID or timestamp\")\n .option(\"--after <id>\", \"After snapshot ID or timestamp\")\n .option(\"--format <format>\", \"Output format: text (default), json, markdown\")\n .option(\"--output <path>\", \"Output file path\")\n .option(\"--verbose\", \"Show detailed comparison\")\n .addHelpText(\n \"after\",\n `\nExamples:\n $ dr audit:diff # Compare latest two snapshots\n $ dr audit:diff --before 20260220-100000 --after 20260220-150000\n $ dr audit:diff --format markdown --output diff.md\n $ dr audit:diff --verbose # Show detailed changes`\n )\n .action((options) => auditDiffCommand(options));\n\n// Audit snapshots command - Manage snapshots\nprogram\n .command(\"audit:snapshots <action>\")\n .description(\"Manage audit snapshots (list, delete, clear)\")\n .option(\"--id <id>\", \"Snapshot ID (for delete action)\")\n .addHelpText(\n \"after\",\n `\nActions:\n list List all available snapshots\n delete Delete a specific snapshot (requires --id)\n clear Delete all snapshots\n\nExamples:\n $ dr audit:snapshots list\n $ dr audit:snapshots delete --id 20260220-100000\n $ dr audit:snapshots clear`\n )\n .action((action, options) => auditSnapshotsCommand({ ...options, action }));\n\n// Repair command - Detect and recover data lost to fixed data-integrity bugs\nprogram\n .command(\"repair:attribute-collision\")\n .description(\n 'Find and best-effort-recover model data lost to a fixed bug where saveLayer() stripped \"source\"/\"x-source-reference\" attributes from every element, even when a node type\\'s schema declared one as a real (sometimes required) attribute'\n )\n .option(\"--apply\", \"Restore recoverable values found in changeset history (default: report only)\")\n .option(\"--format <format>\", \"Output format: text (default), json\")\n .option(\"--output <path>\", \"Write the report to a file instead of stdout\")\n .addHelpText(\n \"after\",\n `\nThis repairs damage from a fixed bug in Model.saveLayer(): a hardcoded, type-blind \"internal\nfields\" blocklist unconditionally stripped any attribute literally named \"source\" or\n\"x-source-reference\" from every element's attributes before writing YAML, regardless of whether\nthe element's own schema declared it as a real domain attribute. 41 of 191 node schemas across 8\nlayers do (3 mark it required, meaning affected elements fail validation today).\n\nRecovery is best-effort: values can only be restored if they still exist in changeset history\n(committing a changeset does not delete it). Elements with no recoverable value are always\nreported, never fabricated \u2014 you'll need to re-supply those manually with\n\"dr update <id> --attributes '{...}'\".\n\nExamples:\n $ dr repair:attribute-collision # Report only \u2014 no changes made\n $ dr repair:attribute-collision --apply # Restore every recoverable value\n $ dr repair:attribute-collision --format json --output report.json`\n )\n .action((options) => repairAttributeCollisionCommand(options));\n\n// Relationship subcommands\nconst relationshipGroup = program.command(\"relationship\").description(\"Relationship operations\");\nrelationshipCommands(relationshipGroup, program);\n\n// Element subcommands\nconst elementGroup = program.command(\"element\").description(\"Element operations\");\nelementCommands(elementGroup, program);\n\n// Schema introspection subcommands\nschemaCommands(program);\n\n// Catalog subcommands (modern relationship catalog)\ncatalogCommands(program);\n\n// Documentation subcommands (schema-driven generation)\ndocsCommands(program);\n\n// Dependency analysis commands\nprogram\n .command(\"trace <elementId>\")\n .description(\"Trace dependencies for an element\")\n .option(\n \"--direction <dir>\",\n \"Trace direction: up (dependencies), down (dependents), both (default)\"\n )\n .option(\"--depth <num>\", \"Maximum traversal depth\")\n .option(\"--metrics\", \"Show graph and element metrics\")\n .option(\"--model <path>\", \"Path to model root (contains model/manifest.yaml)\")\n .addHelpText(\n \"after\",\n `\nExamples:\n $ dr trace api-endpoint-create-customer\n $ dr trace business-service-order --direction down --metrics\n $ dr trace application-component-api --depth 3`\n )\n .action(async (elementId, options) => {\n await traceCommand(elementId, {\n direction: options.direction as \"up\" | \"down\" | \"both\" | undefined,\n depth: options.depth ? parseInt(options.depth) : undefined,\n showMetrics: options.metrics,\n model: options.model,\n });\n });\n\nprogram\n .command(\"visualize\")\n .description(\"Launch visualization server with WebSocket support\")\n .option(\"--port <num>\", \"Server port (default: 8080)\")\n .option(\"--no-browser\", \"Do not auto-open browser\")\n .option(\"--no-auth\", \"Disable authentication (enabled by default)\")\n .option(\"--token <token>\", \"Custom auth token (auto-generated by default)\")\n .option(\"--with-danger\", \"Enable dangerous mode for chat (skip permissions)\")\n .option(\n \"--with-changesets\",\n \"Let chat stage model changes in a changeset (no commit, apply or delete)\"\n )\n .option(\n \"--viewer-path <path>\",\n \"Path to custom viewer build (e.g., ./dist/embedded/dr-viewer-bundle)\"\n )\n .addHelpText(\n \"after\",\n `\nExamples:\n $ dr visualize\n $ dr visualize --port 3000\n $ dr visualize --no-browser\n $ dr visualize --no-auth\n $ dr visualize --token my-secret-token\n $ dr visualize --with-danger\n $ dr visualize --with-changesets\n $ dr visualize --viewer-path ./dist/embedded/dr-viewer-bundle\n\nDefault mode (read-safe permissions) enables:\n - Running 'dr' CLI commands to query the architecture model\n - Reading the codebase\n - Reading the documentation-robotics/ model folder\n - Reading the .dr/ configuration folder\n\nChangeset mode (--with-changesets, Claude Code) adds to the read-safe mode:\n - Creating, activating and inspecting changesets\n - Staging new elements, element updates and new relationships (dr add,\n dr update, dr relationship add) in the active changeset\n - Never committing, applying, reverting or deleting: those stay with you.\n Writes outside an active changeset are refused.\n\nDangerous mode (--with-danger) enables unrestricted access:\n - Claude Code: --dangerously-skip-permissions (full tool access)\n - GitHub Copilot: --allow-all-tools (full tool access)\n\nThe --viewer-path option allows loading a local build of the web UI:\n - Point to a directory containing index.html and supporting files\n - Useful for developing custom viewers or using bundled distributions`\n )\n .action(async (options) => {\n const { visualizeCommand } = await import(\"./commands/visualize.js\");\n await visualizeCommand({\n port: options.port,\n noBrowser: options.browser === false, // Commander sets 'browser' to false when --no-browser is used\n noAuth: options.auth === false, // Commander sets 'auth' to false when --no-auth is used\n token: options.token,\n withDanger: options.withDanger,\n withChangesets: options.withChangesets,\n viewerPath: options.viewerPath,\n });\n });\n\nprogram\n .command(\"mcp\")\n .description(\"Start MCP server for AI assistant integration\")\n .option(\n \"--regenerate-key\",\n \"Generate a new MCP API key, overwrite it at the configured storage path, and print it (does not start the server)\"\n )\n .option(\n \"--transport <type>\",\n \"Transport type: stdio or http (default: stdio)\",\n \"stdio\"\n )\n .option(\n \"--port <number>\",\n \"Port for HTTP transport (default: 3100, only meaningful with --transport http)\",\n \"3100\"\n )\n .option(\n \"--host <address>\",\n \"Host address for HTTP transport (default: 127.0.0.1, only meaningful with --transport http)\",\n \"127.0.0.1\"\n )\n .addHelpText(\n \"after\",\n `\nExamples:\n\nStdio transport (default):\n $ dr mcp\n\nHTTP transport:\n $ dr mcp --transport http # HTTP on localhost:3100\n $ dr mcp --transport http --port 8200 # HTTP on custom port\n $ dr mcp --transport http --host 0.0.0.0 --port 3100 # Listen on all interfaces\n\nKey management:\n $ dr mcp --regenerate-key # Generate new API key\n\nInitial Setup:\nOn first launch, generates an API key and asks where to store it (interactive\nsessions only; non-interactive launches default to ~/.dr-mcp-key). The key is\nprinted to stderr on every launch and must be supplied via environment variable.\n\nStdio Configuration:\nFor stdio transport, supply the key via environment variable:\n\n {\n \"command\": \"dr\",\n \"args\": [\"mcp\"],\n \"env\": { \"DR_MCP_API_KEY\": \"<your-api-key>\" }\n }\n\nHTTP Configuration:\nFor HTTP transport, include the API key as a Bearer token in the Authorization header:\n\n {\n \"url\": \"http://localhost:3100/mcp\",\n \"headers\": {\n \"Authorization\": \"Bearer <your-api-key>\"\n }\n }\n\nUse --regenerate-key to rotate the key (e.g. after a suspected leak) without\nmanually deleting the stored key file or config.`\n )\n .action(async (options) => {\n const { mcpCommand } = await import(\"./commands/mcp.js\");\n const transport = (options.transport as string).toLowerCase();\n if (transport !== \"stdio\" && transport !== \"http\") {\n throw new CLIError(`Invalid transport: ${transport}. Allowed values: stdio, http`, 1);\n }\n const port = parseInt(options.port as string, 10);\n if (!Number.isFinite(port) || port < 1 || port > 65535) {\n throw new CLIError(`Invalid port: ${options.port}. Must be a number between 1 and 65535`, 1);\n }\n await mcpCommand({\n regenerateKey: options.regenerateKey,\n transport: transport as \"stdio\" | \"http\",\n port,\n host: options.host as string,\n });\n });\n\n// AI Integration command\nprogram\n .command(\"chat [client] [withDanger]\")\n .description(\"Interactive chat with AI about the architecture model\")\n .addHelpText(\n \"after\",\n `\nArguments:\n client Optional AI client to use: \"claude-code\" or \"github-copilot\"\n withDanger Enable dangerous mode: \"with-danger\"\n\nExamples:\n $ dr chat # Auto-detect or use saved preference\n $ dr chat claude-code # Use Claude Code, save as preference\n $ dr chat github-copilot # Use GitHub Copilot, save as preference\n $ dr chat with-danger # Auto-detect with dangerous mode\n $ dr chat claude-code with-danger # Use Claude Code with dangerous mode\n $ dr chat github-copilot with-danger # Use GitHub Copilot with dangerous mode\n\nDefault mode (read-safe permissions) enables:\n - Running 'dr' CLI commands to query the architecture model\n - Reading the codebase\n - Reading the documentation-robotics/ model folder\n - Reading the .dr/ configuration folder\n\nDangerous mode (--with-danger) enables unrestricted access:\n - Claude Code: --dangerously-skip-permissions (full tool access)\n - GitHub Copilot: --allow-all-tools (full tool access)\n\nThis launches an interactive chat interface where you can ask AI questions\nabout your architecture model. Supports Claude Code CLI and GitHub Copilot CLI.\n\nInstall instructions:\n - Claude Code: https://claude.ai\n - GitHub Copilot: gh extension install github/gh-copilot`\n )\n .action(async (client?: string, withDangerArg?: string) => {\n // Parse arguments - handle both \"with-danger\" as first or second arg\n let selectedClient: string | undefined;\n let withDanger = false;\n\n if (client === \"with-danger\") {\n // Format: dr chat with-danger\n withDanger = true;\n selectedClient = undefined;\n } else if (withDangerArg === \"with-danger\") {\n // Format: dr chat <client> with-danger\n withDanger = true;\n selectedClient = client;\n } else {\n // Format: dr chat <client>\n selectedClient = client;\n }\n\n await chatCommand(selectedClient, withDanger);\n });\n\n// Advanced commands\nprogram\n .command(\"version\")\n .description(\"Show CLI and embedded spec version information\")\n .addHelpText(\n \"after\",\n `\nExamples:\n $ dr version`\n )\n .action(async () => {\n await versionCommand();\n });\n\nprogram\n .command(\"upgrade\")\n .description(\"Upgrade spec reference and migrate model to latest versions\")\n .option(\"-y, --yes\", \"Automatically upgrade without prompting\")\n .option(\"--dry-run\", \"Show what would be upgraded without making changes\")\n .option(\"--force\", \"Force all upgrades regardless of current versions; skips migration validation\")\n .addHelpText(\n \"after\",\n `\nExamples:\n $ dr upgrade # Scan, show plan, and prompt for upgrades\n $ dr upgrade --dry-run # Preview available upgrades\n $ dr upgrade --yes # Upgrade without prompting\n $ dr upgrade --force # Force all upgrades, ignoring version checks`\n )\n .action(async (options) => {\n await upgradeCommand({\n yes: options.yes,\n dryRun: options.dryRun,\n force: options.force,\n });\n });\n\nprogram\n .command(\"conformance\")\n .description(\"Check model conformance to layer specifications\")\n .option(\"--layers <layers...>\", \"Specific layers to check\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--verbose\", \"Verbose output\")\n .addHelpText(\n \"after\",\n `\nExamples:\n $ dr conformance\n $ dr conformance --layers business api application\n $ dr conformance --json\n $ dr conformance --verbose`\n )\n .action(async (options) => {\n await conformanceCommand({\n layers: options.layers,\n json: options.json ?? program.opts().json,\n verbose: options.verbose ?? program.opts().verbose,\n });\n });\n\n// Changeset subcommands\nchangesetCommands(program);\n\n// Farm subcommands\nfarmCommands(program);\n\n// Claude Code integration subcommands\nclaudeCommands(program);\n\n// GitHub Copilot integration subcommands\ncopilotCommands(program);\n\n// Analyzer integration subcommands\nanalyzerCommands(program);\n\n// Execute CLI with proper telemetry span wrapping\n// This creates a root span that all child spans will be linked to\n(async () => {\n let exitCode = 0;\n try {\n if (isTelemetryEnabled) {\n // Initialize telemetry before execution\n await initTelemetry();\n\n // Only install console interceptor for commands that need it\n const commandName = process.argv[2] || \"unknown\";\n if (CONSOLE_LOGGING_COMMANDS.has(commandName)) {\n await installConsoleInterceptor();\n }\n\n const args = process.argv.slice(3).join(\" \");\n\n // Wrap entire CLI execution in active span for proper context propagation\n await startActiveSpan(\n \"cli.execute\",\n async (span) => {\n // Attributes already set via options parameter - no duplicate setAttributes needed\n try {\n // Execute command - all child spans will now link to this root span\n await program.parseAsync(process.argv);\n\n // Set success status\n span.setStatus({ code: 0 }); // SpanStatusCode.OK\n } catch (error) {\n // Record exception and set error status\n // CommanderError with exitCode 0 is help text / unknown subcommand shown \u2014 not a real error\n if (error instanceof CommanderError) {\n if (error.exitCode === 0) {\n span.setStatus({ code: 0 }); // SpanStatusCode.OK\n } else {\n span.recordException(error as Error);\n span.setStatus({\n code: 2, // SpanStatusCode.ERROR\n message: error.message,\n });\n }\n } else {\n span.recordException(error as Error);\n span.setStatus({\n code: 2, // SpanStatusCode.ERROR\n message: getErrorMessage(error),\n });\n }\n\n // Print error message for CLIError instances\n // Skip CommanderError \u2014 Commander already printed its own output (e.g. help text, unknown command)\n const { CLIError } = await import(\"./utils/errors.js\");\n const { isJson } = await import(\"./utils/globals.js\");\n if (error instanceof CommanderError) {\n // Commander handled its own output; nothing to print\n } else if (error instanceof CLIError) {\n // In JSON mode, handleError already output structured JSON; skip text formatting\n if (!isJson()) {\n console.error(error.format());\n }\n } else if (error instanceof Error) {\n console.error(error.message);\n } else {\n console.error(String(error));\n }\n\n // Extract exit code from CLIError if available\n exitCode = await extractExitCode(error);\n // Don't throw - let telemetry shutdown complete\n }\n },\n {\n \"cli.command\": commandName,\n \"cli.args\": args,\n \"cli.cwd\": process.cwd(),\n \"cli.version\": cliVersion,\n }\n );\n\n // Shutdown telemetry after execution completes\n await shutdownTelemetry();\n\n // Exit with exit code (keepAlive disabled in exporters prevents hanging)\n process.exit(exitCode);\n } else {\n // No telemetry - just parse normally with error handling\n try {\n await program.parseAsync(process.argv);\n } catch (error) {\n // Extract exit code from CLIError if available\n // Skip CommanderError \u2014 Commander already printed its own output (e.g. help text, unknown command)\n const { CLIError } = await import(\"./utils/errors.js\");\n const { isJson } = await import(\"./utils/globals.js\");\n if (error instanceof CommanderError) {\n // Commander handled its own output; nothing to print\n } else if (error instanceof CLIError) {\n // In JSON mode, handleError already output structured JSON; skip text formatting\n if (!isJson()) {\n console.error(error.format());\n }\n } else {\n // Unexpected exceptions need to be printed\n if (error instanceof Error) {\n console.error(error.message);\n } else {\n console.error(String(error));\n }\n }\n const exitCodeFromError = await extractExitCode(error);\n process.exit(exitCodeFromError);\n }\n }\n } catch (error) {\n // Error during telemetry init or shutdown\n if (!isTelemetryEnabled) {\n // No telemetry - exit immediately with error\n process.exit(1);\n }\n // Telemetry enabled - try to shutdown before exit\n await shutdownTelemetry();\n process.exit(1);\n }\n})();\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["#!/usr/bin/env node\n\n/**\n * Documentation Robotics CLI - Bun Implementation\n * Entry point for the command-line interface\n *\n * Instrumented with OpenTelemetry to create root spans for command execution.\n * Telemetry is controlled by the TELEMETRY_ENABLED build-time constant.\n */\n\nimport { Command, CommanderError } from \"commander\";\nimport { setGlobalOptions } from \"./utils/globals.js\";\nimport { installAnsiSuppressor } from \"./utils/ansi-suppressor.js\";\nimport { initCommand } from \"./commands/init.js\";\nimport { addCommand } from \"./commands/add.js\";\nimport { updateCommand } from \"./commands/update.js\";\nimport { deleteCommand } from \"./commands/delete.js\";\nimport { showCommand } from \"./commands/show.js\";\nimport { listCommand } from \"./commands/list.js\";\nimport { searchCommand } from \"./commands/search.js\";\nimport { validateCommand } from \"./commands/validate.js\";\nimport { infoCommand } from \"./commands/info.js\";\nimport { relationshipCommands } from \"./commands/relationship.js\";\nimport { elementCommands } from \"./commands/element.js\";\nimport { schemaCommands } from \"./commands/schema.js\";\nimport { catalogCommands } from \"./commands/catalog.js\";\nimport { docsCommands } from \"./commands/docs.js\";\nimport { traceCommand } from \"./commands/trace.js\";\nimport { exportCommand } from \"./commands/export.js\";\nimport { importCommand } from \"./commands/import.js\";\nimport { chatCommand } from \"./commands/chat.js\";\nimport { upgradeCommand } from \"./commands/upgrade.js\";\nimport { conformanceCommand } from \"./commands/conformance.js\";\nimport { changesetCommands } from \"./commands/changeset.js\";\nimport { farmCommands } from \"./commands/farm.js\";\nimport { claudeCommands } from \"./commands/claude.js\";\nimport { copilotCommands } from \"./commands/copilot.js\";\nimport { analyzerCommands } from \"./commands/analyzer.js\";\nimport { versionCommand } from \"./commands/version.js\";\nimport { statsCommand } from \"./commands/stats.js\";\nimport { reportCommand } from \"./commands/report.js\";\nimport { reportsCommands } from \"./commands/reports.js\";\nimport { auditCommand } from \"./commands/audit.js\";\nimport { auditDiffCommand } from \"./commands/audit-diff.js\";\nimport { auditSnapshotsCommand } from \"./commands/audit-snapshots.js\";\nimport { repairAttributeCollisionCommand } from \"./commands/repair.js\";\nimport { initTelemetry, startActiveSpan, shutdownTelemetry } from \"./telemetry/index.js\";\nimport { installConsoleInterceptor } from \"./telemetry/console-interceptor.js\";\nimport { getErrorMessage, CLIError } from \"./utils/errors.js\";\nimport { getCliVersion } from \"./utils/spec-version.js\";\n\n// Declare TELEMETRY_ENABLED as a build-time constant (substituted by esbuild)\n// Provide runtime fallback when not running through esbuild\ndeclare const TELEMETRY_ENABLED: boolean;\nconst isTelemetryEnabled = typeof TELEMETRY_ENABLED !== \"undefined\" ? TELEMETRY_ENABLED : false;\n\n// Commands that require console interceptor for telemetry logging\nconst CONSOLE_LOGGING_COMMANDS = new Set(['chat', 'validate', 'import', 'export']);\n\n// Suppress ANSI color output on non-TTY stdout\nif (!process.stdout.isTTY) {\n process.env.FORCE_COLOR = \"0\";\n process.env.NO_COLOR = \"1\";\n}\n\n// Install the ANSI suppressor to strip color codes from console output when not on TTY\ninstallAnsiSuppressor();\n\n/**\n * Extract exit code from an error object.\n * Handles CLIError instances and duck-typed objects with exitCode property.\n */\nasync function extractExitCode(error: unknown): Promise<number> {\n const { CLIError } = await import(\"./utils/errors.js\");\n\n if (error instanceof CLIError) {\n return error.exitCode;\n }\n\n // Commander's own errors (--help, unknown commands, etc.) carry exitCode as\n // expected control flow \u2014 handle them directly without duck-typing.\n if (error instanceof CommanderError) {\n return error.exitCode;\n }\n\n // Fallback for duck-typing (handles bundling/module issues)\n if (error && typeof error === \"object\" && \"exitCode\" in error) {\n const errorObj = error as any;\n if (typeof errorObj.exitCode === \"number\") {\n // Validate this looks like a CLIError before accepting\n if (errorObj.name === \"CLIError\" || errorObj.message) {\n if (process.argv.includes(\"--debug\")) {\n console.warn(\n \"[DEBUG] Using duck-typed error object as fallback - this may indicate a module loading issue\"\n );\n }\n return errorObj.exitCode;\n }\n }\n }\n\n return 1;\n}\n\nconst cliVersion = getCliVersion();\n\nconst program = new Command();\n\n// Handle --version and -V flags by redirecting to version command\n// This ensures they go through the telemetry wrapper\nif (process.argv.includes(\"--version\") || process.argv.includes(\"-V\")) {\n process.argv = [\"node\", \"dr\", \"version\"];\n}\n\nprogram\n .name(\"dr\")\n .description(\"Documentation Robotics CLI - Architecture Model Management\")\n .option(\"-v, --verbose\", \"Enable verbose output\")\n .option(\"--debug\", \"Enable debug mode\")\n .option(\"--json\", \"Output as JSON (supported on mutating and query commands)\")\n .option(\"--codebase-path <path>\", \"Override codebase root path (default: resolved from manifest or project root)\")\n .exitOverride() // Prevent Commander from calling process.exit() - we handle exit ourselves\n .showSuggestionAfterError() // \"Did you mean X?\" on unknown commands/options\n .hook(\"preAction\", async (thisCommand) => {\n // Set up global state (verbose/debug/json flags)\n const options = thisCommand.opts();\n setGlobalOptions({\n verbose: options.verbose as boolean | undefined,\n debug: options.debug as boolean | undefined,\n json: options.json as boolean | undefined,\n codebasePath: options.codebasePath as string | undefined,\n });\n });\n\n// Model commands\nprogram\n .command(\"init [name]\")\n .description(\"Initialize a new architecture model\")\n .option(\"--name <name>\", \"Model name (overrides positional argument)\")\n .option(\"--author <author>\", \"Model author\")\n .option(\"--description <desc>\", \"Model description\")\n .addHelpText(\n \"after\",\n `\nExamples:\n $ dr init\n $ dr init claudetoreum\n $ dr init \"Enterprise Architecture\" --author \"Team A\"\n $ dr init --name \"My Project\" --description \"13-layer federated model\"`\n )\n .action((name, options) => initCommand({ ...options, name: options.name || name }));\n\nprogram\n .command(\"add <layer> <type> <name>\")\n .description(\"Add an element to a layer\")\n .option(\"--model <path>\", \"Path to model root (contains model/manifest.yaml)\")\n .option(\"--name <name>\", \"Element display name (defaults to the name argument)\")\n .option(\"--description <desc>\", \"Element description\")\n .option(\"--attributes <json>\", \"Element type-specific attributes as JSON object\")\n .option(\"--source-file <path>\", \"Source file path (relative from repository root)\")\n .option(\"--source-symbol <name>\", \"Symbol name (class, function, variable) in source file\")\n .option(\"--source-provenance <type>\", \"Provenance type: extracted, manual, inferred, generated\")\n .option(\"--source-repo-remote <url>\", \"Git remote URL for repository context\")\n .option(\"--source-repo-commit <sha>\", \"Git commit SHA (40 hex characters) for repository context\")\n .option(\"--verbose\", \"Show detailed output (can also use global -v flag)\")\n .addHelpText(\n \"after\",\n `\nExamples:\n $ dr add business service \"Customer Management\"\n $ dr add api operation \"Create Customer\" --attributes '{\"operationId\":\"createCustomer\",\"summary\":\"Create a customer\",\"tags\":\"customers\"}'\n $ dr add application component \"Customer API\" --description \"REST API for customer operations\"\n $ dr add security policy \"Auth Validator\" --source-file \"src/auth/validator.ts\" --source-symbol \"validateToken\" --source-provenance \"extracted\"\n\nNote: Element IDs are generated automatically in format {layer}.{type}.{kebab-name}`\n )\n .action((layer, type, name, options) =>\n addCommand(layer, type, name, { ...options, verbose: options.verbose ?? program.opts().verbose }));\n\nprogram\n .command(\"update <id>\")\n .description(\"Update an element\")\n .option(\"--model <path>\", \"Path to model root (contains model/manifest.yaml)\")\n .option(\"--name <name>\", \"New element name\")\n .option(\"--description <desc>\", \"New description\")\n .option(\"--type <new-type>\", \"Change element type (must be valid for the element's layer; incompatible attributes must be cleaned up manually)\")\n .option(\"--attributes <json>\", \"Updated type-specific attributes (JSON)\")\n .option(\"--attribute-patch <json>\", \"Merge these attributes into the current ones (JSON object; null removes a key). Cannot be combined with --attributes\")\n .option(\"--source-file <path>\", \"Source file path (relative from repository root)\")\n .option(\"--source-symbol <name>\", \"Symbol name (class, function, variable) in source file. Without --source-file, added to the element's one source file, keeping its provenance\")\n .option(\"--source-provenance <type>\", \"Provenance type: extracted, manual, inferred, generated\")\n .option(\"--source-repo-remote <url>\", \"Git remote URL for repository context\")\n .option(\"--source-repo-commit <sha>\", \"Git commit SHA (40 hex characters) for repository context\")\n .option(\"--clear-source-reference\", \"Remove source reference from element\")\n .option(\"--verbose\", \"Show detailed output (can also use global -v flag)\")\n .addHelpText(\n \"after\",\n `\nNote: Changes are written immediately to model files.\nTo track changes for review, activate a changeset first:\n $ dr changeset activate my-changeset\n\nExamples:\n $ dr update api-endpoint-create-customer --name \"Create Customer (v2)\"\n $ dr update business-service-order --description \"Updated description\"\n $ dr update application-applicationfunction-process-orders --type applicationservice\n $ dr update api.operation.create-customer --attribute-patch '{\"summary\":\"Create a customer (v2)\"}'\n $ dr update security-policy-auth --source-file \"src/auth/policy.ts\" --source-provenance \"extracted\"`\n )\n .action((id, options) =>\n updateCommand(id, { ...options, verbose: options.verbose ?? program.opts().verbose }));\n\nprogram\n .command(\"delete <id>\")\n .description(\"Delete an element\")\n .option(\"--model <path>\", \"Path to model root (contains model/manifest.yaml)\")\n .option(\"--force\", \"Skip dependency checks (confirmation is also skipped in non-TTY environments)\")\n .option(\"--cascade\", \"Remove dependent elements automatically\")\n .option(\"--dry-run\", \"Show what would be removed without actually removing\")\n .option(\"--verbose\", \"Show detailed output (can also use global -v flag)\")\n .addHelpText(\n \"after\",\n `\nExamples:\n $ dr delete api-endpoint-old-endpoint\n $ dr delete api-endpoint-old-endpoint --force\n $ dr delete api-endpoint-old-endpoint --cascade\n $ dr delete api-endpoint-old-endpoint --dry-run\n $ dr delete api-endpoint-old-endpoint --cascade --dry-run`\n )\n .action((id, options) =>\n deleteCommand(id, { ...options, verbose: options.verbose ?? program.opts().verbose }));\n\nprogram\n .command(\"show <id>\")\n .description(\"Display element details\")\n .option(\"--model <path>\", \"Path to model root (contains model/manifest.yaml)\")\n .addHelpText(\n \"after\",\n `\nExamples:\n $ dr show api-endpoint-create-customer\n $ dr show business-service-order-mgmt`\n )\n .action((id, options) => showCommand(id, options));\n\nprogram\n .command(\"list [layer]\")\n .description(\"List elements in a layer (or all layers if omitted)\")\n .option(\"--type <type>\", \"Filter by element type\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--model <path>\", \"Path to model root (contains model/manifest.yaml)\")\n .addHelpText(\n \"after\",\n `\nExamples:\n $ dr list\n $ dr list api\n $ dr list business --type businessservice\n $ dr list api --json\n $ dr list --json`\n )\n .action((layer, options) => {\n return listCommand(layer, { ...options, json: options.json ?? program.opts().json });\n });\n\nprogram\n .command(\"search <query>\")\n .description(\"Search for elements by name or ID\")\n .option(\"--layer <layer>\", \"Limit search to specific layer\")\n .option(\"--type <type>\", \"Filter by element type\")\n .option(\n \"--source-file <path>\",\n \"Find elements referencing a source file (takes precedence over pattern matching)\"\n )\n .option(\"--json\", \"Output as JSON\")\n .addHelpText(\n \"after\",\n `\nExamples:\n $ dr search customer\n $ dr search \"order processing\" --layer business\n $ dr search create-* --type endpoint\n $ dr search \"\" --source-file src/api/customer.ts`\n )\n .action((query, options) => {\n return searchCommand(query, { ...options, json: options.json ?? program.opts().json });\n });\n\nprogram\n .command(\"validate\")\n .description(\"Validate the architecture model\")\n .option(\"--layers <layers...>\", \"Specific layers to validate\")\n .option(\"--strict\", \"Treat warnings as errors\")\n .option(\"--verbose\", \"Show detailed validation output with relationship breakdown\")\n .option(\"--quiet\", \"Show minimal output\")\n .option(\"--output <path>\", \"Export validation report to file (JSON or Markdown)\")\n .option(\"--model <path>\", \"Path to model root (contains model/manifest.yaml)\")\n .option(\"--orphans\", \"Show only orphaned elements grouped by layer with relationship suggestions\")\n .option(\"--all\", \"Run all validations (default behavior)\")\n .option(\"--markdown\", \"Validate markdown structure\")\n .option(\"--schemas\", \"Validate JSON schemas\")\n .option(\"--schema\", \"Validate JSON schemas (alias for --schemas)\")\n .option(\"--relationships\", \"Validate relationships\")\n .option(\"--structure\", \"Validate documentation structure\")\n .option(\"--naming\", \"Validate naming conventions\")\n .option(\"--references\", \"Validate cross-layer references\")\n .option(\"--scope <scope>\", \"Validation scope: 'local' (default) or 'composed' for cross-model validation\")\n .option(\"--model-path <mapping...>\", \"Override filesystem path for external model (format: model-name=/path/to/project-root, can be repeated)\")\n .addHelpText(\n \"after\",\n `\nExamples:\n $ dr validate\n $ dr validate --all --strict\n $ dr validate --verbose\n $ dr validate --quiet\n $ dr validate --output report.json\n $ dr validate --output report.md\n $ dr validate --schemas\n $ dr validate --relationships\n $ dr validate --layers business api\n $ dr validate --orphans\n $ dr validate --orphans --output orphans.json\n $ dr validate --scope composed --model-path auth-service=/path/to/auth-service-repo\n $ dr validate --scope composed --model-path auth-service=/path/to/auth-service-repo --model-path payment-service=/path/to/payment-repo\n\nNote: When using --model-path, pass the project root (where documentation-robotics/model/ is located).`\n )\n .action(validateCommand);\n\nprogram\n .command(\"export <format>\")\n .description(\"Export the architecture model to various formats\")\n .option(\"--output <path>\", \"Output file path (default: print to stdout)\")\n .option(\"--layers <layers...>\", \"Specific layers to export\")\n .option(\"--model <path>\", \"Path to model root directory or manifest.yaml file\")\n .option(\"--include-sources\", \"Include source file paths in PlantUML diagrams as notes\")\n .addHelpText(\n \"after\",\n `\nSupported formats:\n archimate Export to ArchiMate XML (layers 1, 2, 5, 6)\n openapi Export to OpenAPI 3.0 specification (layer 7)\n jsonschema Export to JSON Schema (layer 8)\n plantuml Export to PlantUML diagram\n graphml Export to GraphML (graph visualization)\n markdown Export to Markdown documentation\n\nExamples:\n $ dr export archimate --output model.xml\n $ dr export openapi --layers api\n $ dr export plantuml --include-sources --output diagram.puml\n $ dr export markdown --output docs/architecture.md`\n )\n .action(async (format, options) => {\n await exportCommand({\n format,\n output: options.output,\n layers: options.layers,\n model: options.model,\n includeSources: options.includeSources,\n });\n });\n\nprogram\n .command(\"import <format>\")\n .description(\"Import architecture model from various formats\")\n .option(\"--input <path>\", \"Input file path (required)\", undefined)\n .option(\"--model <path>\", \"Path to model root directory or manifest.yaml file\")\n .option(\n \"--merge-strategy <strategy>\",\n \"How to handle existing elements: add, update, skip (default: add)\"\n )\n .addHelpText(\n \"after\",\n `\nSupported formats:\n archimate Import from ArchiMate XML (layers 1, 2, 5, 6)\n openapi Import from OpenAPI 3.0 specification (layer 7)\n\nExamples:\n $ dr import archimate --input model.xml\n $ dr import openapi --input api.json --merge-strategy add\n $ dr import archimate --input model.xml --model ./myproject`\n )\n .action(async (format, options) => {\n if (!options.input) {\n console.error(\"Error: --input path is required\");\n process.exit(1);\n }\n await importCommand({\n format,\n input: options.input,\n model: options.model,\n mergeStrategy: options.mergeStrategy as \"add\" | \"update\" | \"skip\" | undefined,\n });\n });\n\nprogram\n .command(\"info\")\n .description(\"Show model information\")\n .option(\"--layer <layer>\", \"Show specific layer details\")\n .option(\"--verbose\", \"Show detailed breakdown by element type\")\n .addHelpText(\n \"after\",\n `\nExamples:\n $ dr info\n $ dr info --layer business\n $ dr info --layer api --verbose`\n )\n .action(infoCommand);\n\nprogram\n .command(\"stats\")\n .description(\"Display model statistics and health metrics\")\n .option(\"--model <path>\", \"Path to the model directory\")\n .option(\"--format <format>\", \"Output format: text (default), json, markdown, compact\")\n .option(\"--output <path>\", \"Output file path (auto-detects format from extension)\")\n .option(\"--compact\", \"Show compact one-line summary\")\n .option(\"--verbose\", \"Show detailed information\")\n .addHelpText(\n \"after\",\n `\nOutput formats:\n text Full formatted statistics (default)\n json JSON output for automation\n markdown Markdown report format\n compact Single-line summary\n\nExamples:\n $ dr stats # Show full statistics\n $ dr stats --compact # Show one-line summary\n $ dr stats --format json # Output as JSON\n $ dr stats --output stats.md # Save as markdown file\n $ dr stats --output stats.json # Save as JSON file\n $ dr stats --verbose # Show detailed information`\n )\n .action((options) => statsCommand(options));\n\nprogram\n .command(\"report\")\n .description(\"Generate comprehensive architecture reports\")\n .option(\"--model <path>\", \"Path to the model directory\")\n .option(\"--type <type>\", \"Report type: comprehensive (default), statistics, relationships, data-model, quality\")\n .option(\"--format <format>\", \"Output format: text (default), json, markdown\")\n .option(\"--output <path>\", \"Output file path (auto-detects format from extension)\")\n .option(\"--verbose\", \"Show detailed information\")\n .option(\"--include-data-model\", \"Include data model analysis (default: true)\")\n .option(\"--include-quality\", \"Include quality metrics (default: true)\")\n .addHelpText(\n \"after\",\n `\nReport types:\n comprehensive Full report with statistics, relationships, and data model (default)\n statistics Statistics and quality metrics\n relationships Relationship analysis and classification\n data-model Layer 8 data model analysis\n quality Quality metrics and recommendations\n\nOutput formats:\n text Full formatted report (default)\n json JSON output for automation\n markdown Markdown report format\n\nExamples:\n $ dr report # Show comprehensive report\n $ dr report --type relationships # Show relationship analysis\n $ dr report --format json # Output as JSON\n $ dr report --output report.md # Save as markdown file\n $ dr report --type data-model --output dm.md # Data model report as markdown\n $ dr report --verbose # Show detailed information`\n )\n .action((options) => reportCommand(options));\n\n// Reports subcommands (managed layer report files)\nconst reportsGroup = program.command(\"reports\").description(\"Manage architecture layer reports\");\nreportsCommands(reportsGroup);\n\n// Audit command - Relationship analysis\nprogram\n .command(\"audit [layer]\")\n .description(\"Analyze relationship coverage, gaps, duplicates, and balance\")\n .option(\"--type <type>\", \"Audit type: relationships (default), nodes, all\")\n .option(\"--format <format>\", \"Output format: text (default), json, markdown\")\n .option(\"--output <path>\", \"Output file path (auto-detects format from extension)\")\n .option(\"--verbose\", \"Show detailed analysis\")\n .option(\"--save-snapshot\", \"Save audit report as snapshot for differential analysis\")\n .addHelpText(\n \"after\",\n `\nAudit types:\n relationships Relationship coverage, gaps, duplicates, balance (default)\n nodes Node type usage distribution across model layers\n all Both relationship and node audits\n\nOutput formats:\n text Full formatted audit report (default)\n json JSON output for automation\n markdown Markdown audit report format\n\nExamples:\n $ dr audit # Full relationship audit of all layers\n $ dr audit security # Audit security layer only\n $ dr audit --type nodes # Node type distribution audit\n $ dr audit --type all # Combined relationship + node audit\n $ dr audit --format json # Output as JSON\n $ dr audit --output audit.md # Save as markdown file\n $ dr audit --verbose # Show detailed analysis\n $ dr audit --save-snapshot # Save snapshot for later comparison\n $ dr audit api --output api-audit.json # API layer audit as JSON`\n )\n .action((layer, options) =>\n auditCommand({ ...options, layer, verbose: options.verbose ?? program.opts().verbose }));\n\n// Audit diff command - Compare snapshots\nprogram\n .command(\"audit:diff\")\n .description(\"Compare before/after audit snapshots\")\n .option(\"--before <id>\", \"Before snapshot ID or timestamp\")\n .option(\"--after <id>\", \"After snapshot ID or timestamp\")\n .option(\"--format <format>\", \"Output format: text (default), json, markdown\")\n .option(\"--output <path>\", \"Output file path\")\n .option(\"--verbose\", \"Show detailed comparison\")\n .addHelpText(\n \"after\",\n `\nExamples:\n $ dr audit:diff # Compare latest two snapshots\n $ dr audit:diff --before 20260220-100000 --after 20260220-150000\n $ dr audit:diff --format markdown --output diff.md\n $ dr audit:diff --verbose # Show detailed changes`\n )\n .action((options) => auditDiffCommand(options));\n\n// Audit snapshots command - Manage snapshots\nprogram\n .command(\"audit:snapshots <action>\")\n .description(\"Manage audit snapshots (list, delete, clear)\")\n .option(\"--id <id>\", \"Snapshot ID (for delete action)\")\n .addHelpText(\n \"after\",\n `\nActions:\n list List all available snapshots\n delete Delete a specific snapshot (requires --id)\n clear Delete all snapshots\n\nExamples:\n $ dr audit:snapshots list\n $ dr audit:snapshots delete --id 20260220-100000\n $ dr audit:snapshots clear`\n )\n .action((action, options) => auditSnapshotsCommand({ ...options, action }));\n\n// Repair command - Detect and recover data lost to fixed data-integrity bugs\nprogram\n .command(\"repair:attribute-collision\")\n .description(\n 'Find and best-effort-recover model data lost to a fixed bug where saveLayer() stripped \"source\"/\"x-source-reference\" attributes from every element, even when a node type\\'s schema declared one as a real (sometimes required) attribute'\n )\n .option(\"--apply\", \"Restore recoverable values found in changeset history (default: report only)\")\n .option(\"--format <format>\", \"Output format: text (default), json\")\n .option(\"--output <path>\", \"Write the report to a file instead of stdout\")\n .addHelpText(\n \"after\",\n `\nThis repairs damage from a fixed bug in Model.saveLayer(): a hardcoded, type-blind \"internal\nfields\" blocklist unconditionally stripped any attribute literally named \"source\" or\n\"x-source-reference\" from every element's attributes before writing YAML, regardless of whether\nthe element's own schema declared it as a real domain attribute. 41 of 191 node schemas across 8\nlayers do (3 mark it required, meaning affected elements fail validation today).\n\nRecovery is best-effort: values can only be restored if they still exist in changeset history\n(committing a changeset does not delete it). Elements with no recoverable value are always\nreported, never fabricated \u2014 you'll need to re-supply those manually with\n\"dr update <id> --attributes '{...}'\".\n\nExamples:\n $ dr repair:attribute-collision # Report only \u2014 no changes made\n $ dr repair:attribute-collision --apply # Restore every recoverable value\n $ dr repair:attribute-collision --format json --output report.json`\n )\n .action((options) => repairAttributeCollisionCommand(options));\n\n// Relationship subcommands\nconst relationshipGroup = program.command(\"relationship\").description(\"Relationship operations\");\nrelationshipCommands(relationshipGroup, program);\n\n// Element subcommands\nconst elementGroup = program.command(\"element\").description(\"Element operations\");\nelementCommands(elementGroup, program);\n\n// Schema introspection subcommands\nschemaCommands(program);\n\n// Catalog subcommands (modern relationship catalog)\ncatalogCommands(program);\n\n// Documentation subcommands (schema-driven generation)\ndocsCommands(program);\n\n// Dependency analysis commands\nprogram\n .command(\"trace <elementId>\")\n .description(\"Trace dependencies for an element\")\n .option(\n \"--direction <dir>\",\n \"Trace direction: up (dependencies), down (dependents), both (default)\"\n )\n .option(\"--depth <num>\", \"Maximum traversal depth\")\n .option(\"--metrics\", \"Show graph and element metrics\")\n .option(\"--model <path>\", \"Path to model root (contains model/manifest.yaml)\")\n .addHelpText(\n \"after\",\n `\nExamples:\n $ dr trace api-endpoint-create-customer\n $ dr trace business-service-order --direction down --metrics\n $ dr trace application-component-api --depth 3`\n )\n .action(async (elementId, options) => {\n await traceCommand(elementId, {\n direction: options.direction as \"up\" | \"down\" | \"both\" | undefined,\n depth: options.depth ? parseInt(options.depth) : undefined,\n showMetrics: options.metrics,\n model: options.model,\n });\n });\n\nprogram\n .command(\"visualize\")\n .description(\"Launch visualization server with WebSocket support\")\n .option(\"--port <num>\", \"Server port (default: 8080)\")\n .option(\"--no-browser\", \"Do not auto-open browser\")\n .option(\"--no-auth\", \"Disable authentication (enabled by default)\")\n .option(\"--token <token>\", \"Custom auth token (auto-generated by default)\")\n .option(\"--with-danger\", \"Enable dangerous mode for chat (skip permissions)\")\n .option(\n \"--with-changesets\",\n \"Let chat stage model changes in a changeset (no commit, apply or delete)\"\n )\n .option(\n \"--viewer-path <path>\",\n \"Path to custom viewer build (e.g., ./dist/embedded/dr-viewer-bundle)\"\n )\n .addHelpText(\n \"after\",\n `\nExamples:\n $ dr visualize\n $ dr visualize --port 3000\n $ dr visualize --no-browser\n $ dr visualize --no-auth\n $ dr visualize --token my-secret-token\n $ dr visualize --with-danger\n $ dr visualize --with-changesets\n $ dr visualize --viewer-path ./dist/embedded/dr-viewer-bundle\n\nDefault mode (read-safe permissions) enables:\n - Running 'dr' CLI commands to query the architecture model\n - Reading the codebase\n - Reading the documentation-robotics/ model folder\n - Reading the .dr/ configuration folder\n - One 'dr' command per shell call: a call that adds pipes, &&, ; or\n redirects needs approval nobody can give in the chat, so it is denied\n\nChangeset mode (--with-changesets, Claude Code) adds to the read-safe mode:\n - Creating, activating and inspecting changesets\n - Staging new elements, element updates and new relationships (dr add,\n dr update, dr relationship add) in the active changeset\n - Never committing, applying, reverting or deleting: those stay with you.\n Writes outside an active changeset are refused.\n\nDangerous mode (--with-danger) enables unrestricted access:\n - Claude Code: --dangerously-skip-permissions (full tool access)\n - GitHub Copilot: --allow-all-tools (full tool access)\n\nThe --viewer-path option allows loading a local build of the web UI:\n - Point to a directory containing index.html and supporting files\n - Useful for developing custom viewers or using bundled distributions`\n )\n .action(async (options) => {\n const { visualizeCommand } = await import(\"./commands/visualize.js\");\n await visualizeCommand({\n port: options.port,\n noBrowser: options.browser === false, // Commander sets 'browser' to false when --no-browser is used\n noAuth: options.auth === false, // Commander sets 'auth' to false when --no-auth is used\n token: options.token,\n withDanger: options.withDanger,\n withChangesets: options.withChangesets,\n viewerPath: options.viewerPath,\n });\n });\n\nprogram\n .command(\"mcp\")\n .description(\"Start MCP server for AI assistant integration\")\n .option(\n \"--regenerate-key\",\n \"Generate a new MCP API key, overwrite it at the configured storage path, and print it (does not start the server)\"\n )\n .option(\n \"--transport <type>\",\n \"Transport type: stdio or http (default: stdio)\",\n \"stdio\"\n )\n .option(\n \"--port <number>\",\n \"Port for HTTP transport (default: 3100, only meaningful with --transport http)\",\n \"3100\"\n )\n .option(\n \"--host <address>\",\n \"Host address for HTTP transport (default: 127.0.0.1, only meaningful with --transport http)\",\n \"127.0.0.1\"\n )\n .addHelpText(\n \"after\",\n `\nExamples:\n\nStdio transport (default):\n $ dr mcp\n\nHTTP transport:\n $ dr mcp --transport http # HTTP on localhost:3100\n $ dr mcp --transport http --port 8200 # HTTP on custom port\n $ dr mcp --transport http --host 0.0.0.0 --port 3100 # Listen on all interfaces\n\nKey management:\n $ dr mcp --regenerate-key # Generate new API key\n\nStdio Configuration:\nNo API key: the client starts the server as your own user. In Claude Code, install the\ndr plugin (claude plugin install dr@documentation-robotics); other clients use:\n\n {\n \"command\": \"dr\",\n \"args\": [\"mcp\"]\n }\n\nThe server serves the project the client has open (its MCP roots); DR_MCP_ROOT_PATH\npins it to one model instead.\n\nHTTP Configuration:\nHTTP clients authenticate with an API key, generated on first launch (stored at\n~/.dr-mcp-key unless you choose a path interactively) and printed to stderr on every\nlaunch. Include it as a Bearer token in the Authorization header:\n\n {\n \"url\": \"http://localhost:3100/mcp\",\n \"headers\": {\n \"Authorization\": \"Bearer <your-api-key>\"\n }\n }\n\nUse --regenerate-key to rotate the key (e.g. after a suspected leak) without\nmanually deleting the stored key file or config.`\n )\n .action(async (options) => {\n const { mcpCommand } = await import(\"./commands/mcp.js\");\n const transport = (options.transport as string).toLowerCase();\n if (transport !== \"stdio\" && transport !== \"http\") {\n throw new CLIError(`Invalid transport: ${transport}. Allowed values: stdio, http`, 1);\n }\n const port = parseInt(options.port as string, 10);\n if (!Number.isFinite(port) || port < 1 || port > 65535) {\n throw new CLIError(`Invalid port: ${options.port}. Must be a number between 1 and 65535`, 1);\n }\n await mcpCommand({\n regenerateKey: options.regenerateKey,\n transport: transport as \"stdio\" | \"http\",\n port,\n host: options.host as string,\n });\n });\n\n// AI Integration command\nprogram\n .command(\"chat [client] [withDanger]\")\n .description(\"Interactive chat with AI about the architecture model\")\n .addHelpText(\n \"after\",\n `\nArguments:\n client Optional AI client to use: \"claude-code\" or \"github-copilot\"\n withDanger Enable dangerous mode: \"with-danger\"\n\nExamples:\n $ dr chat # Auto-detect or use saved preference\n $ dr chat claude-code # Use Claude Code, save as preference\n $ dr chat github-copilot # Use GitHub Copilot, save as preference\n $ dr chat with-danger # Auto-detect with dangerous mode\n $ dr chat claude-code with-danger # Use Claude Code with dangerous mode\n $ dr chat github-copilot with-danger # Use GitHub Copilot with dangerous mode\n\nDefault mode (read-safe permissions) enables:\n - Running 'dr' CLI commands to query the architecture model\n - Reading the codebase\n - Reading the documentation-robotics/ model folder\n - Reading the .dr/ configuration folder\n\nDangerous mode (--with-danger) enables unrestricted access:\n - Claude Code: --dangerously-skip-permissions (full tool access)\n - GitHub Copilot: --allow-all-tools (full tool access)\n\nThis launches an interactive chat interface where you can ask AI questions\nabout your architecture model. Supports Claude Code CLI and GitHub Copilot CLI.\n\nInstall instructions:\n - Claude Code: https://claude.ai\n - GitHub Copilot: gh extension install github/gh-copilot`\n )\n .action(async (client?: string, withDangerArg?: string) => {\n // Parse arguments - handle both \"with-danger\" as first or second arg\n let selectedClient: string | undefined;\n let withDanger = false;\n\n if (client === \"with-danger\") {\n // Format: dr chat with-danger\n withDanger = true;\n selectedClient = undefined;\n } else if (withDangerArg === \"with-danger\") {\n // Format: dr chat <client> with-danger\n withDanger = true;\n selectedClient = client;\n } else {\n // Format: dr chat <client>\n selectedClient = client;\n }\n\n await chatCommand(selectedClient, withDanger);\n });\n\n// Advanced commands\nprogram\n .command(\"version\")\n .description(\"Show CLI and embedded spec version information\")\n .addHelpText(\n \"after\",\n `\nExamples:\n $ dr version`\n )\n .action(async () => {\n await versionCommand();\n });\n\nprogram\n .command(\"upgrade\")\n .description(\"Upgrade spec reference and migrate model to latest versions\")\n .option(\"-y, --yes\", \"Automatically upgrade without prompting\")\n .option(\"--dry-run\", \"Show what would be upgraded without making changes\")\n .option(\"--force\", \"Force all upgrades regardless of current versions; skips migration validation\")\n .addHelpText(\n \"after\",\n `\nExamples:\n $ dr upgrade # Scan, show plan, and prompt for upgrades\n $ dr upgrade --dry-run # Preview available upgrades\n $ dr upgrade --yes # Upgrade without prompting\n $ dr upgrade --force # Force all upgrades, ignoring version checks`\n )\n .action(async (options) => {\n await upgradeCommand({\n yes: options.yes,\n dryRun: options.dryRun,\n force: options.force,\n });\n });\n\nprogram\n .command(\"conformance\")\n .description(\"Check model conformance to layer specifications\")\n .option(\"--layers <layers...>\", \"Specific layers to check\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--verbose\", \"Verbose output\")\n .addHelpText(\n \"after\",\n `\nExamples:\n $ dr conformance\n $ dr conformance --layers business api application\n $ dr conformance --json\n $ dr conformance --verbose`\n )\n .action(async (options) => {\n await conformanceCommand({\n layers: options.layers,\n json: options.json ?? program.opts().json,\n verbose: options.verbose ?? program.opts().verbose,\n });\n });\n\n// Changeset subcommands\nchangesetCommands(program);\n\n// Farm subcommands\nfarmCommands(program);\n\n// Claude Code integration subcommands\nclaudeCommands(program);\n\n// GitHub Copilot integration subcommands\ncopilotCommands(program);\n\n// Analyzer integration subcommands\nanalyzerCommands(program);\n\n// Execute CLI with proper telemetry span wrapping\n// This creates a root span that all child spans will be linked to\n(async () => {\n let exitCode = 0;\n try {\n if (isTelemetryEnabled) {\n // Initialize telemetry before execution\n await initTelemetry();\n\n // Only install console interceptor for commands that need it\n const commandName = process.argv[2] || \"unknown\";\n if (CONSOLE_LOGGING_COMMANDS.has(commandName)) {\n await installConsoleInterceptor();\n }\n\n const args = process.argv.slice(3).join(\" \");\n\n // Wrap entire CLI execution in active span for proper context propagation\n await startActiveSpan(\n \"cli.execute\",\n async (span) => {\n // Attributes already set via options parameter - no duplicate setAttributes needed\n try {\n // Execute command - all child spans will now link to this root span\n await program.parseAsync(process.argv);\n\n // Set success status\n span.setStatus({ code: 0 }); // SpanStatusCode.OK\n } catch (error) {\n // Record exception and set error status\n // CommanderError with exitCode 0 is help text / unknown subcommand shown \u2014 not a real error\n if (error instanceof CommanderError) {\n if (error.exitCode === 0) {\n span.setStatus({ code: 0 }); // SpanStatusCode.OK\n } else {\n span.recordException(error as Error);\n span.setStatus({\n code: 2, // SpanStatusCode.ERROR\n message: error.message,\n });\n }\n } else {\n span.recordException(error as Error);\n span.setStatus({\n code: 2, // SpanStatusCode.ERROR\n message: getErrorMessage(error),\n });\n }\n\n // Print error message for CLIError instances\n // Skip CommanderError \u2014 Commander already printed its own output (e.g. help text, unknown command)\n const { CLIError } = await import(\"./utils/errors.js\");\n const { isJson } = await import(\"./utils/globals.js\");\n if (error instanceof CommanderError) {\n // Commander handled its own output; nothing to print\n } else if (error instanceof CLIError) {\n // In JSON mode, handleError already output structured JSON; skip text formatting\n if (!isJson()) {\n console.error(error.format());\n }\n } else if (error instanceof Error) {\n console.error(error.message);\n } else {\n console.error(String(error));\n }\n\n // Extract exit code from CLIError if available\n exitCode = await extractExitCode(error);\n // Don't throw - let telemetry shutdown complete\n }\n },\n {\n \"cli.command\": commandName,\n \"cli.args\": args,\n \"cli.cwd\": process.cwd(),\n \"cli.version\": cliVersion,\n }\n );\n\n // Shutdown telemetry after execution completes\n await shutdownTelemetry();\n\n // Exit with exit code (keepAlive disabled in exporters prevents hanging)\n process.exit(exitCode);\n } else {\n // No telemetry - just parse normally with error handling\n try {\n await program.parseAsync(process.argv);\n } catch (error) {\n // Extract exit code from CLIError if available\n // Skip CommanderError \u2014 Commander already printed its own output (e.g. help text, unknown command)\n const { CLIError } = await import(\"./utils/errors.js\");\n const { isJson } = await import(\"./utils/globals.js\");\n if (error instanceof CommanderError) {\n // Commander handled its own output; nothing to print\n } else if (error instanceof CLIError) {\n // In JSON mode, handleError already output structured JSON; skip text formatting\n if (!isJson()) {\n console.error(error.format());\n }\n } else {\n // Unexpected exceptions need to be printed\n if (error instanceof Error) {\n console.error(error.message);\n } else {\n console.error(String(error));\n }\n }\n const exitCodeFromError = await extractExitCode(error);\n process.exit(exitCodeFromError);\n }\n }\n } catch (error) {\n // Error during telemetry init or shutdown\n if (!isTelemetryEnabled) {\n // No telemetry - exit immediately with error\n process.exit(1);\n }\n // Telemetry enabled - try to shutdown before exit\n await shutdownTelemetry();\n process.exit(1);\n }\n})();\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["CLIError"]
|
|
7
7
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { existsSync } from "node:fs";
|
|
1
|
+
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
|
2
2
|
import { chmod, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
|
3
3
|
import { homedir, tmpdir } from "node:os";
|
|
4
|
-
import { join } from "node:path";
|
|
4
|
+
import { basename, dirname, join, resolve } from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
|
-
import {
|
|
6
|
+
import { parse as parseYaml } from "yaml";
|
|
7
7
|
import { CHANGESET_ONLY_ENV } from "../core/changeset-only-guard.js";
|
|
8
8
|
const DR_MCP_SERVER_NAME = "dr", DR_MCP_ROOT_PATH_ENV = "DR_MCP_ROOT_PATH", DR_CLI_ENTRY_ENV = "DR_CLI_ENTRY", DR_MCP_READ_TOOLS = Object.freeze([
|
|
9
9
|
"model_list",
|
|
@@ -23,7 +23,8 @@ const DR_MCP_SERVER_NAME = "dr", DR_MCP_ROOT_PATH_ENV = "DR_MCP_ROOT_PATH", DR_C
|
|
|
23
23
|
"spec_type",
|
|
24
24
|
"annotation_list",
|
|
25
25
|
"annotation_get",
|
|
26
|
-
"chat_status"
|
|
26
|
+
"chat_status",
|
|
27
|
+
"project_status"
|
|
27
28
|
]), DR_MCP_CHANGESET_TOOLS = Object.freeze([
|
|
28
29
|
"changeset_create",
|
|
29
30
|
"changeset_activate",
|
|
@@ -51,10 +52,7 @@ function resolveDrCommand(env = process.env, exists = existsSync) {
|
|
|
51
52
|
}
|
|
52
53
|
function buildDrMcpConfig(options) {
|
|
53
54
|
const env = {
|
|
54
|
-
|
|
55
|
-
[DR_MCP_ROOT_PATH_ENV]: options.rootPath,
|
|
56
|
-
// The key is already in this private config; don't print it into the client's MCP logs.
|
|
57
|
-
DR_MCP_QUIET_KEY: "1"
|
|
55
|
+
[DR_MCP_ROOT_PATH_ENV]: options.rootPath
|
|
58
56
|
};
|
|
59
57
|
return options.changesetOnly && (env[CHANGESET_ONLY_ENV] = "true"), {
|
|
60
58
|
mcpServers: {
|
|
@@ -68,9 +66,8 @@ function buildDrMcpConfig(options) {
|
|
|
68
66
|
};
|
|
69
67
|
}
|
|
70
68
|
async function prepareDrMcpLaunch(options) {
|
|
71
|
-
const
|
|
69
|
+
const config = buildDrMcpConfig({
|
|
72
70
|
drCommand: options.drCommand ?? resolveDrCommand(),
|
|
73
|
-
apiKey: key,
|
|
74
71
|
rootPath: options.rootPath,
|
|
75
72
|
changesetOnly: options.changesetOnly
|
|
76
73
|
}), dir = await mkdtemp(join(options.tempRoot ?? tmpdir(), "dr-drbot-mcp-"));
|
|
@@ -123,29 +120,127 @@ function parseAgentFrontmatterTools(markdown) {
|
|
|
123
120
|
}
|
|
124
121
|
return tools;
|
|
125
122
|
}
|
|
126
|
-
function
|
|
127
|
-
|
|
128
|
-
|
|
123
|
+
function agentDirectories(rootPath, options = {}) {
|
|
124
|
+
const configDir = (options.env ?? process.env).CLAUDE_CONFIG_DIR, userDir = configDir ? resolve(configDir, "agents") : join(options.homeDir ?? homedir(), ".claude", "agents"), dirs = [];
|
|
125
|
+
let dir = resolve(rootPath);
|
|
126
|
+
for (; ; ) {
|
|
127
|
+
const agents = join(dir, ".claude", "agents");
|
|
128
|
+
if (agents !== userDir && dirs.push({ dir: agents, source: "project" }), existsSync(join(dir, ".git")))
|
|
129
|
+
break;
|
|
130
|
+
const parent = dirname(dir);
|
|
131
|
+
if (parent === dir)
|
|
132
|
+
break;
|
|
133
|
+
dir = parent;
|
|
134
|
+
}
|
|
135
|
+
return dirs.push({ dir: userDir, source: "user" }), dirs;
|
|
136
|
+
}
|
|
137
|
+
function agentFileName(path) {
|
|
138
|
+
try {
|
|
139
|
+
const match = /^---\r?\n([\s\S]*?)\r?\n---/.exec(readFileSync(path, "utf8")), frontmatter = match ? parseYaml(match[1]) : null;
|
|
140
|
+
if (typeof frontmatter?.name == "string" && frontmatter.name.trim())
|
|
141
|
+
return frontmatter.name.trim();
|
|
142
|
+
} catch {
|
|
143
|
+
}
|
|
144
|
+
return basename(path, ".md");
|
|
145
|
+
}
|
|
146
|
+
function markdownFiles(dir) {
|
|
147
|
+
let entries;
|
|
148
|
+
try {
|
|
149
|
+
entries = readdirSync(dir, { withFileTypes: !0 });
|
|
150
|
+
} catch {
|
|
151
|
+
return [];
|
|
152
|
+
}
|
|
153
|
+
const files = [];
|
|
154
|
+
for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
|
|
155
|
+
const path = join(dir, entry.name);
|
|
156
|
+
entry.isDirectory() ? files.push(...markdownFiles(path)) : entry.name.endsWith(".md") && files.push(path);
|
|
157
|
+
}
|
|
158
|
+
return files;
|
|
159
|
+
}
|
|
160
|
+
function findInstalledAgentFile(rootPath, options = {}) {
|
|
161
|
+
for (const { dir, source } of agentDirectories(rootPath, options)) {
|
|
162
|
+
const path = markdownFiles(dir).find((file) => agentFileName(file) === DR_ARCHITECT_AGENT);
|
|
163
|
+
if (path)
|
|
164
|
+
return { path, source };
|
|
165
|
+
}
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
168
|
+
function bundledAgentFile(exists = existsSync) {
|
|
169
|
+
const relativePaths = [
|
|
170
|
+
`../integrations/claude_code/agents/${DR_ARCHITECT_AGENT}.md`,
|
|
171
|
+
`../../../integrations/claude_code/agents/${DR_ARCHITECT_AGENT}.md`
|
|
172
|
+
];
|
|
173
|
+
for (const relativePath of relativePaths) {
|
|
174
|
+
const candidate = fileURLToPath(new URL(relativePath, import.meta.url));
|
|
129
175
|
if (exists(candidate))
|
|
130
176
|
return candidate;
|
|
131
177
|
}
|
|
132
178
|
return null;
|
|
133
179
|
}
|
|
180
|
+
function resolveDrBotAgent(rootPath, options = {}) {
|
|
181
|
+
const installed = findInstalledAgentFile(rootPath, options);
|
|
182
|
+
if (installed)
|
|
183
|
+
return installed;
|
|
184
|
+
const bundledPath = options.bundledPath === void 0 ? bundledAgentFile() : options.bundledPath;
|
|
185
|
+
return bundledPath ? { path: bundledPath, source: "bundled" } : null;
|
|
186
|
+
}
|
|
187
|
+
function agentDefinitionFromMarkdown(markdown) {
|
|
188
|
+
const match = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/.exec(markdown);
|
|
189
|
+
if (!match)
|
|
190
|
+
throw new Error("agent file has no frontmatter");
|
|
191
|
+
const frontmatter = parseYaml(match[1]) ?? {};
|
|
192
|
+
if (typeof frontmatter.description != "string" || !frontmatter.description.trim())
|
|
193
|
+
throw new Error("agent file has no description");
|
|
194
|
+
const definition = {
|
|
195
|
+
description: frontmatter.description,
|
|
196
|
+
prompt: markdown.slice(match[0].length).trim()
|
|
197
|
+
}, tools = parseAgentFrontmatterTools(markdown);
|
|
198
|
+
return tools !== null && (definition.tools = tools), typeof frontmatter.model == "string" && (definition.model = frontmatter.model), definition;
|
|
199
|
+
}
|
|
200
|
+
async function drBotAgentArgs(agent) {
|
|
201
|
+
if (agent?.source !== "bundled")
|
|
202
|
+
return [];
|
|
203
|
+
const definition = agentDefinitionFromMarkdown(await readFile(agent.path, "utf8"));
|
|
204
|
+
return ["--agents", JSON.stringify({ [DR_ARCHITECT_AGENT]: definition })];
|
|
205
|
+
}
|
|
134
206
|
function drMcpToolsForMode(mode) {
|
|
135
207
|
return mode === "danger" ? [...DR_MCP_READ_TOOLS, ...DR_MCP_CHANGESET_TOOLS].map(drMcpToolRule) : drMcpAllowedTools(mode);
|
|
136
208
|
}
|
|
137
|
-
async function
|
|
138
|
-
|
|
139
|
-
if (!path)
|
|
209
|
+
async function checkAgentMcpTools(agent, mode) {
|
|
210
|
+
if (!agent)
|
|
140
211
|
return null;
|
|
141
|
-
const tools = parseAgentFrontmatterTools(await readFile(path, "utf8"));
|
|
212
|
+
const { path, source } = agent, tools = parseAgentFrontmatterTools(await readFile(path, "utf8"));
|
|
142
213
|
if (tools === null)
|
|
143
214
|
return null;
|
|
144
215
|
const listed = new Set(tools);
|
|
145
216
|
if (listed.has(`mcp__${DR_MCP_SERVER_NAME}`) || listed.has(`mcp__${DR_MCP_SERVER_NAME}__*`))
|
|
146
217
|
return null;
|
|
147
218
|
const required = drMcpToolsForMode(mode), missing = required.filter((rule) => !listed.has(rule));
|
|
148
|
-
return missing.length === 0 ? null : { path, missing, noneVisible: missing.length === required.length };
|
|
219
|
+
return missing.length === 0 ? null : { path, source, missing, noneVisible: missing.length === required.length };
|
|
220
|
+
}
|
|
221
|
+
async function checkInstalledAgentMcpTools(rootPath, mode, options = {}) {
|
|
222
|
+
return checkAgentMcpTools(resolveDrBotAgent(rootPath, options), mode);
|
|
223
|
+
}
|
|
224
|
+
async function prepareDrBotAgent(rootPath, mode, options = {}) {
|
|
225
|
+
const agent = resolveDrBotAgent(rootPath, options);
|
|
226
|
+
let args;
|
|
227
|
+
try {
|
|
228
|
+
args = await drBotAgentArgs(agent);
|
|
229
|
+
} catch (error) {
|
|
230
|
+
const missing = drMcpToolsForMode(mode);
|
|
231
|
+
return {
|
|
232
|
+
agent,
|
|
233
|
+
args: [],
|
|
234
|
+
check: {
|
|
235
|
+
path: agent.path,
|
|
236
|
+
source: "bundled",
|
|
237
|
+
missing,
|
|
238
|
+
noneVisible: !0,
|
|
239
|
+
error: error instanceof Error ? error.message : String(error)
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
return { agent, args, check: await checkAgentMcpTools(agent, mode) };
|
|
149
244
|
}
|
|
150
245
|
export {
|
|
151
246
|
DR_ARCHITECT_AGENT,
|
|
@@ -154,14 +249,21 @@ export {
|
|
|
154
249
|
DR_MCP_READ_TOOLS,
|
|
155
250
|
DR_MCP_ROOT_PATH_ENV,
|
|
156
251
|
DR_MCP_SERVER_NAME,
|
|
252
|
+
agentDefinitionFromMarkdown,
|
|
253
|
+
agentDirectories,
|
|
157
254
|
buildDrMcpConfig,
|
|
255
|
+
bundledAgentFile,
|
|
256
|
+
checkAgentMcpTools,
|
|
158
257
|
checkInstalledAgentMcpTools,
|
|
258
|
+
drBotAgentArgs,
|
|
159
259
|
drBotMcpPrompt,
|
|
160
260
|
drMcpAllowedTools,
|
|
161
261
|
drMcpToolRule,
|
|
162
262
|
findInstalledAgentFile,
|
|
163
263
|
parseAgentFrontmatterTools,
|
|
264
|
+
prepareDrBotAgent,
|
|
164
265
|
prepareDrMcpLaunch,
|
|
266
|
+
resolveDrBotAgent,
|
|
165
267
|
resolveDrCommand
|
|
166
268
|
};
|
|
167
269
|
//# sourceMappingURL=drbot-mcp.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/coding-agents/drbot-mcp.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * DrBot on MCP: connect the viewer's chat agent to the dr MCP server.\n *\n * `dr visualize` launches Claude Code as DrBot (server/server.ts). Rather than having the\n * agent shell out to `dr` through Bash, the launch hands Claude Code an MCP config that runs\n * this same dr installation's `dr mcp` over stdio, pointed at the served model, so DrBot plans\n * changes with the change-modeling tools (changeset_create, spec_type, model_add,\n * relationship_add, changeset_brief) the way any other agent does.\n *\n * Authentication: `dr mcp` over stdio requires DR_MCP_API_KEY to match the installation's\n * stored key (mcp/api-key-manager.ts). Over stdio the client supplies both the process and its\n * environment, so a key minted per launch would only be checked against itself; the launch\n * instead resolves the installation key (creating it on first use, as `dr mcp` does) and puts\n * it only in a private temp config file (0600, in a 0700 directory under the OS temp dir),\n * never in the repo, the model directory or the process arguments. The file is removed when the\n * agent process exits.\n *\n * Tolerance: if anything here fails (no key, no temp dir), the caller launches DrBot without\n * MCP and it falls back to the read-safe Bash rules; the failure is logged, not swallowed.\n */\n\nimport { existsSync } from \"node:fs\";\nimport { chmod, mkdtemp, readFile, rm, writeFile } from \"node:fs/promises\";\nimport { homedir, tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { ApiKeyManager } from \"../mcp/api-key-manager.js\";\nimport { CHANGESET_ONLY_ENV } from \"../core/changeset-only-guard.js\";\n\n/** Name the dr MCP server is registered under; Claude Code exposes its tools as mcp__dr__<tool>. */\nexport const DR_MCP_SERVER_NAME = \"dr\";\n\n/** Env var `dr mcp` honours to serve a model from a directory other than its cwd. */\nexport const DR_MCP_ROOT_PATH_ENV = \"DR_MCP_ROOT_PATH\";\n\n/** Env var that overrides the dr CLI entry script DrBot's MCP server runs (tests, custom installs). */\nexport const DR_CLI_ENTRY_ENV = \"DR_CLI_ENTRY\";\n\n/** Tools that only read: allowed in every DrBot mode. */\nexport const DR_MCP_READ_TOOLS: readonly string[] = Object.freeze([\n \"model_list\",\n \"model_show\",\n \"model_search\",\n \"model_stats\",\n \"model_info\",\n \"model_trace\",\n \"model_validate\",\n \"model_export\",\n \"model_reload\",\n \"changeset_list\",\n \"changeset_show\",\n \"changeset_impact\",\n \"changeset_brief\",\n \"changeset_verify\",\n \"spec_type\",\n \"annotation_list\",\n \"annotation_get\",\n \"chat_status\",\n]);\n\n/**\n * Tools added in changeset-only mode (`dr visualize --with-changesets`): open and work in a\n * changeset and stage element and relationship changes. The MCP server runs with\n * DR_CHANGESET_ONLY set, so any of these that would write the base model (no active changeset)\n * is refused there (mcp/changeset-only.ts). changeset_update and changeset_unstage revise the\n * plan. Commit and apply are not MCP tools at all, and changeset_discard (which deletes the\n * staged changes) stays out: abandoning a changeset is the user's call.\n * chat_launch (an agent launching another agent) and the annotation writers stay out.\n */\nexport const DR_MCP_CHANGESET_TOOLS: readonly string[] = Object.freeze([\n \"changeset_create\",\n \"changeset_activate\",\n \"changeset_deactivate\",\n \"model_add\",\n \"model_update\",\n \"model_delete\",\n \"relationship_add\",\n \"relationship_delete\",\n \"changeset_update\",\n \"changeset_unstage\",\n]);\n\nexport type DrBotMode = \"read-safe\" | \"changesets\" | \"danger\";\n\n/** Claude Code permission rule for one dr MCP tool. */\nexport function drMcpToolRule(tool: string): string {\n return `mcp__${DR_MCP_SERVER_NAME}__${tool}`;\n}\n\n/** The mcp__dr__* rules DrBot may use without prompting in a mode (danger mode skips permissions). */\nexport function drMcpAllowedTools(mode: DrBotMode): string[] {\n if (mode === \"danger\") return [];\n const tools = mode === \"changesets\" ? [...DR_MCP_READ_TOOLS, ...DR_MCP_CHANGESET_TOOLS] : [...DR_MCP_READ_TOOLS];\n return tools.map(drMcpToolRule);\n}\n\n/** How to run this dr installation: a runtime plus the CLI entry script, or `dr` from PATH. */\nexport interface DrCommand {\n command: string;\n args: string[];\n}\n\n/**\n * Resolves the command that runs this same dr installation. The built CLI lives next to this\n * module's parent (dist/coding-agents/ \u2192 dist/cli.js) and runs under whichever runtime is\n * running now; DR_CLI_ENTRY overrides the script. Falls back to `dr` on PATH.\n */\nexport function resolveDrCommand(\n env: NodeJS.ProcessEnv = process.env,\n exists: (path: string) => boolean = existsSync\n): DrCommand {\n const override = env[DR_CLI_ENTRY_ENV];\n if (override && exists(override)) {\n return { command: process.execPath, args: [override] };\n }\n const bundled = fileURLToPath(new URL(\"../cli.js\", import.meta.url));\n if (exists(bundled)) {\n return { command: process.execPath, args: [bundled] };\n }\n return { command: \"dr\", args: [] };\n}\n\nexport interface DrMcpConfigOptions {\n drCommand: DrCommand;\n apiKey: string;\n /** Project root of the served model. */\n rootPath: string;\n /** Run the server in changeset-only mode (DR_CHANGESET_ONLY=true). */\n changesetOnly: boolean;\n}\n\n/** The Claude Code MCP config (the --mcp-config file's content) for DrBot's dr server. */\nexport function buildDrMcpConfig(options: DrMcpConfigOptions): {\n mcpServers: Record<\n string,\n {\n type: \"stdio\";\n command: string;\n args: string[];\n env: Record<string, string>;\n }\n >;\n} {\n const env: Record<string, string> = {\n DR_MCP_API_KEY: options.apiKey,\n [DR_MCP_ROOT_PATH_ENV]: options.rootPath,\n // The key is already in this private config; don't print it into the client's MCP logs.\n DR_MCP_QUIET_KEY: \"1\",\n };\n if (options.changesetOnly) {\n env[CHANGESET_ONLY_ENV] = \"true\";\n }\n return {\n mcpServers: {\n [DR_MCP_SERVER_NAME]: {\n type: \"stdio\",\n command: options.drCommand.command,\n args: [...options.drCommand.args, \"mcp\"],\n env,\n },\n },\n };\n}\n\n/** A written MCP config and the function that removes it again (safe to call more than once). */\nexport interface DrMcpLaunch {\n configPath: string;\n cleanup: () => Promise<void>;\n}\n\nexport interface PrepareDrMcpLaunchOptions {\n rootPath: string;\n changesetOnly: boolean;\n keyManager?: Pick<ApiKeyManager, \"ensureKey\">;\n drCommand?: DrCommand;\n /** Parent directory for the private config directory; defaults to the OS temp dir. */\n tempRoot?: string;\n}\n\n/**\n * Writes DrBot's MCP config to a private temp file. Throws on failure; the caller decides to\n * launch without MCP.\n */\nexport async function prepareDrMcpLaunch(options: PrepareDrMcpLaunchOptions): Promise<DrMcpLaunch> {\n const keyManager = options.keyManager ?? new ApiKeyManager();\n // No prompt: the server is non-interactive, so a first-time key goes to the default path.\n const { key } = await keyManager.ensureKey();\n const config = buildDrMcpConfig({\n drCommand: options.drCommand ?? resolveDrCommand(),\n apiKey: key,\n rootPath: options.rootPath,\n changesetOnly: options.changesetOnly,\n });\n\n const dir = await mkdtemp(join(options.tempRoot ?? tmpdir(), \"dr-drbot-mcp-\"));\n let removed = false;\n const cleanup = async () => {\n if (removed) return;\n removed = true;\n try {\n await rm(dir, { recursive: true, force: true });\n } catch (error) {\n console.warn(`[DrBot] Could not remove MCP config directory ${dir}: ${(error as Error).message}`);\n }\n };\n\n try {\n await chmod(dir, 0o700);\n const configPath = join(dir, \"mcp.json\");\n await writeFile(configPath, JSON.stringify(config, null, 2), {\n mode: 0o600,\n });\n return { configPath, cleanup };\n } catch (error) {\n await cleanup();\n throw error;\n }\n}\n\n/** Appended to DrBot's system prompt when the dr MCP server is connected. */\nexport function drBotMcpPrompt(mode: DrBotMode): string {\n const lines = [\n `The Documentation Robotics MCP server \"${DR_MCP_SERVER_NAME}\" is connected for the model this session serves ` +\n `(tools named mcp__${DR_MCP_SERVER_NAME}__*). Prefer these tools to running dr through Bash: ` +\n \"model_search/model_show/model_list to look things up, spec_type to check what a type takes and which \" +\n \"relationships the catalog allows, changeset_impact and changeset_brief to pressure-test a change.\",\n ];\n if (mode === \"changesets\") {\n lines.push(\n \"This session may change the model only through a changeset. Call changeset_create first (it activates the \" +\n \"new changeset), then stage changes with model_add, model_update, model_delete, relationship_add and \" +\n \"relationship_delete, and review them with changeset_brief. Writes with no active changeset are refused. \" +\n \"Never commit or apply a changeset: the user reviews and commits it.\"\n );\n } else if (mode === \"read-safe\") {\n lines.push(\"This session is read-only: answer from the model, and do not try to change it.\");\n }\n return lines.join(\"\\n\\n\");\n}\n\n/** The Claude Code agent DrBot runs as (`claude --agent dr-architect`). */\nexport const DR_ARCHITECT_AGENT = \"dr-architect\";\n\n/**\n * The tool names in an agent file's frontmatter `tools:` field, or null when the file has no\n * `tools:` field (Claude Code then gives the agent every tool, MCP tools included). Accepts the\n * comma-separated form, a flow list (`[a, b]`) and a block list.\n */\nexport function parseAgentFrontmatterTools(markdown: string): string[] | null {\n const match = /^---\\r?\\n([\\s\\S]*?)\\r?\\n---/.exec(markdown);\n if (!match) return null;\n const lines = match[1].split(/\\r?\\n/);\n const index = lines.findIndex((line) => /^tools\\s*:/.test(line));\n if (index === -1) return null;\n const unquote = (value: string) =>\n value\n .trim()\n .replace(/^[\"']|[\"']$/g, \"\")\n .trim();\n const inline = lines[index].replace(/^tools\\s*:/, \"\").trim();\n if (inline) {\n return inline\n .replace(/^\\[|\\]$/g, \"\")\n .split(\",\")\n .map(unquote)\n .filter(Boolean);\n }\n const tools: string[] = [];\n for (const line of lines.slice(index + 1)) {\n const item = /^\\s+-\\s*(.+)$/.exec(line);\n if (!item) break;\n tools.push(unquote(item[1]));\n }\n return tools;\n}\n\n/**\n * The dr-architect agent file Claude Code loads for a session run in `rootPath`: the project's\n * .claude/agents copy wins over the user's ~/.claude/agents copy. Null when neither exists.\n */\nexport function findInstalledAgentFile(\n rootPath: string,\n homeDir: string = homedir(),\n exists: (path: string) => boolean = existsSync\n): string | null {\n for (const base of [rootPath, homeDir]) {\n const candidate = join(base, \".claude\", \"agents\", `${DR_ARCHITECT_AGENT}.md`);\n if (exists(candidate)) return candidate;\n }\n return null;\n}\n\n/** The dr MCP tools a mode uses that the installed dr-architect agent can't see. */\nexport interface AgentMcpToolCheck {\n /** The agent file that was checked. */\n path: string;\n /** The mcp__dr__* rules the mode uses that the agent's `tools:` field leaves out. */\n missing: string[];\n /** True when the agent can see none of them (a copy installed before DrBot used MCP). */\n noneVisible: boolean;\n}\n\n/** Every dr MCP tool DrBot can use in a mode (danger mode may use them all). */\nfunction drMcpToolsForMode(mode: DrBotMode): string[] {\n return mode === \"danger\"\n ? [...DR_MCP_READ_TOOLS, ...DR_MCP_CHANGESET_TOOLS].map(drMcpToolRule)\n : drMcpAllowedTools(mode);\n}\n\n/**\n * Checks that the installed dr-architect agent lists the dr MCP tools DrBot's mode uses. An\n * agent's `tools:` field limits what it can call, so a copy installed before DrBot moved to MCP\n * can't see the server at all, whatever --allowedTools says. Null when there's nothing to report:\n * no agent file found, no `tools:` field, a server-wide `mcp__dr` entry, or every tool listed.\n */\nexport async function checkInstalledAgentMcpTools(\n rootPath: string,\n mode: DrBotMode,\n homeDir: string = homedir()\n): Promise<AgentMcpToolCheck | null> {\n const path = findInstalledAgentFile(rootPath, homeDir);\n if (!path) return null;\n const tools = parseAgentFrontmatterTools(await readFile(path, \"utf8\"));\n if (tools === null) return null;\n const listed = new Set(tools);\n if (listed.has(`mcp__${DR_MCP_SERVER_NAME}`) || listed.has(`mcp__${DR_MCP_SERVER_NAME}__*`)) return null;\n const required = drMcpToolsForMode(mode);\n const missing = required.filter((rule) => !listed.has(rule));\n if (missing.length === 0) return null;\n return { path, missing, noneVisible: missing.length === required.length };\n}\n"],
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["/**\n * DrBot on MCP: connect the viewer's chat agent to the dr MCP server.\n *\n * `dr visualize` launches Claude Code as DrBot (server/server.ts). Rather than having the\n * agent shell out to `dr` through Bash, the launch hands Claude Code an MCP config that runs\n * this same dr installation's `dr mcp` over stdio, pointed at the served model, so DrBot plans\n * changes with the change-modeling tools (changeset_create, spec_type, model_add,\n * relationship_add, changeset_brief) the way any other agent does.\n *\n * `dr mcp` over stdio needs no API key (the client spawns it as the same user). The config goes\n * in a private temp file (0600, in a 0700 directory under the OS temp dir), never in the repo or\n * the model directory, and is removed when the agent process exits.\n *\n * Tolerance: if anything here fails (no temp dir), the caller launches DrBot without\n * MCP and it falls back to the read-safe Bash rules; the failure is logged, not swallowed.\n */\n\nimport { existsSync, readdirSync, readFileSync, type Dirent } from \"node:fs\";\nimport { chmod, mkdtemp, readFile, rm, writeFile } from \"node:fs/promises\";\nimport { homedir, tmpdir } from \"node:os\";\nimport { basename, dirname, join, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { parse as parseYaml } from \"yaml\";\nimport { CHANGESET_ONLY_ENV } from \"../core/changeset-only-guard.js\";\n\n/** Name the dr MCP server is registered under; Claude Code exposes its tools as mcp__dr__<tool>. */\nexport const DR_MCP_SERVER_NAME = \"dr\";\n\n/** Env var `dr mcp` honours to serve a model from a directory other than its cwd. */\nexport const DR_MCP_ROOT_PATH_ENV = \"DR_MCP_ROOT_PATH\";\n\n/** Env var that overrides the dr CLI entry script DrBot's MCP server runs (tests, custom installs). */\nexport const DR_CLI_ENTRY_ENV = \"DR_CLI_ENTRY\";\n\n/** Tools that only read: allowed in every DrBot mode. */\nexport const DR_MCP_READ_TOOLS: readonly string[] = Object.freeze([\n \"model_list\",\n \"model_show\",\n \"model_search\",\n \"model_stats\",\n \"model_info\",\n \"model_trace\",\n \"model_validate\",\n \"model_export\",\n \"model_reload\",\n \"changeset_list\",\n \"changeset_show\",\n \"changeset_impact\",\n \"changeset_brief\",\n \"changeset_verify\",\n \"spec_type\",\n \"annotation_list\",\n \"annotation_get\",\n \"chat_status\",\n \"project_status\",\n]);\n\n/**\n * Tools added in changeset-only mode (`dr visualize --with-changesets`): open and work in a\n * changeset and stage element and relationship changes. The MCP server runs with\n * DR_CHANGESET_ONLY set, so any of these that would write the base model (no active changeset)\n * is refused there (mcp/changeset-only.ts). changeset_update and changeset_unstage revise the\n * plan. Left out on purpose:\n * - changeset_commit: landing needs a person to confirm it, and the server refuses it in\n * changeset-only mode anyway. Apply is not an MCP tool.\n * - changeset_discard: it deletes the staged changes, and abandoning a changeset is the user's call.\n * - project_init and project_upgrade: they create or migrate the model outside any changeset.\n * - review_open: DrBot already lives in the viewer it would open.\n * - codebase_extract: it writes a changeset from the code, a run the user starts from their own\n * session. The server still allows it in changeset-only mode, since it only writes a changeset.\n * - chat_launch (an agent launching another agent) and the annotation writers.\n */\nexport const DR_MCP_CHANGESET_TOOLS: readonly string[] = Object.freeze([\n \"changeset_create\",\n \"changeset_activate\",\n \"changeset_deactivate\",\n \"model_add\",\n \"model_update\",\n \"model_delete\",\n \"relationship_add\",\n \"relationship_delete\",\n \"changeset_update\",\n \"changeset_unstage\",\n]);\n\nexport type DrBotMode = \"read-safe\" | \"changesets\" | \"danger\";\n\n/** Claude Code permission rule for one dr MCP tool. */\nexport function drMcpToolRule(tool: string): string {\n return `mcp__${DR_MCP_SERVER_NAME}__${tool}`;\n}\n\n/** The mcp__dr__* rules DrBot may use without prompting in a mode (danger mode skips permissions). */\nexport function drMcpAllowedTools(mode: DrBotMode): string[] {\n if (mode === \"danger\") return [];\n const tools = mode === \"changesets\" ? [...DR_MCP_READ_TOOLS, ...DR_MCP_CHANGESET_TOOLS] : [...DR_MCP_READ_TOOLS];\n return tools.map(drMcpToolRule);\n}\n\n/** How to run this dr installation: a runtime plus the CLI entry script, or `dr` from PATH. */\nexport interface DrCommand {\n command: string;\n args: string[];\n}\n\n/**\n * Resolves the command that runs this same dr installation. The built CLI lives next to this\n * module's parent (dist/coding-agents/ \u2192 dist/cli.js) and runs under whichever runtime is\n * running now; DR_CLI_ENTRY overrides the script. Falls back to `dr` on PATH.\n */\nexport function resolveDrCommand(\n env: NodeJS.ProcessEnv = process.env,\n exists: (path: string) => boolean = existsSync\n): DrCommand {\n const override = env[DR_CLI_ENTRY_ENV];\n if (override && exists(override)) {\n return { command: process.execPath, args: [override] };\n }\n const bundled = fileURLToPath(new URL(\"../cli.js\", import.meta.url));\n if (exists(bundled)) {\n return { command: process.execPath, args: [bundled] };\n }\n return { command: \"dr\", args: [] };\n}\n\nexport interface DrMcpConfigOptions {\n drCommand: DrCommand;\n /** Project root of the served model. */\n rootPath: string;\n /** Run the server in changeset-only mode (DR_CHANGESET_ONLY=true). */\n changesetOnly: boolean;\n}\n\n/** The Claude Code MCP config (the --mcp-config file's content) for DrBot's dr server. */\nexport function buildDrMcpConfig(options: DrMcpConfigOptions): {\n mcpServers: Record<\n string,\n {\n type: \"stdio\";\n command: string;\n args: string[];\n env: Record<string, string>;\n }\n >;\n} {\n const env: Record<string, string> = {\n [DR_MCP_ROOT_PATH_ENV]: options.rootPath,\n };\n if (options.changesetOnly) {\n env[CHANGESET_ONLY_ENV] = \"true\";\n }\n return {\n mcpServers: {\n [DR_MCP_SERVER_NAME]: {\n type: \"stdio\",\n command: options.drCommand.command,\n args: [...options.drCommand.args, \"mcp\"],\n env,\n },\n },\n };\n}\n\n/** A written MCP config and the function that removes it again (safe to call more than once). */\nexport interface DrMcpLaunch {\n configPath: string;\n cleanup: () => Promise<void>;\n}\n\nexport interface PrepareDrMcpLaunchOptions {\n rootPath: string;\n changesetOnly: boolean;\n drCommand?: DrCommand;\n /** Parent directory for the private config directory; defaults to the OS temp dir. */\n tempRoot?: string;\n}\n\n/**\n * Writes DrBot's MCP config to a private temp file. Throws on failure; the caller decides to\n * launch without MCP.\n */\nexport async function prepareDrMcpLaunch(options: PrepareDrMcpLaunchOptions): Promise<DrMcpLaunch> {\n const config = buildDrMcpConfig({\n drCommand: options.drCommand ?? resolveDrCommand(),\n rootPath: options.rootPath,\n changesetOnly: options.changesetOnly,\n });\n\n const dir = await mkdtemp(join(options.tempRoot ?? tmpdir(), \"dr-drbot-mcp-\"));\n let removed = false;\n const cleanup = async () => {\n if (removed) return;\n removed = true;\n try {\n await rm(dir, { recursive: true, force: true });\n } catch (error) {\n console.warn(`[DrBot] Could not remove MCP config directory ${dir}: ${(error as Error).message}`);\n }\n };\n\n try {\n await chmod(dir, 0o700);\n const configPath = join(dir, \"mcp.json\");\n await writeFile(configPath, JSON.stringify(config, null, 2), {\n mode: 0o600,\n });\n return { configPath, cleanup };\n } catch (error) {\n await cleanup();\n throw error;\n }\n}\n\n/** Appended to DrBot's system prompt when the dr MCP server is connected. */\nexport function drBotMcpPrompt(mode: DrBotMode): string {\n const lines = [\n `The Documentation Robotics MCP server \"${DR_MCP_SERVER_NAME}\" is connected for the model this session serves ` +\n `(tools named mcp__${DR_MCP_SERVER_NAME}__*). Prefer these tools to running dr through Bash: ` +\n \"model_search/model_show/model_list to look things up, spec_type to check what a type takes and which \" +\n \"relationships the catalog allows, changeset_impact and changeset_brief to pressure-test a change.\",\n ];\n if (mode === \"changesets\") {\n lines.push(\n \"This session may change the model only through a changeset. Call changeset_create first (it activates the \" +\n \"new changeset), then stage changes with model_add, model_update, model_delete, relationship_add and \" +\n \"relationship_delete, and review them with changeset_brief. Writes with no active changeset are refused. \" +\n \"Never commit or apply a changeset: the user reviews and commits it.\"\n );\n } else if (mode === \"read-safe\") {\n lines.push(\"This session is read-only: answer from the model, and do not try to change it.\");\n }\n return lines.join(\"\\n\\n\");\n}\n\n/** The Claude Code agent DrBot runs as (`claude --agent dr-architect`). */\nexport const DR_ARCHITECT_AGENT = \"dr-architect\";\n\n/**\n * The tool names in an agent file's frontmatter `tools:` field, or null when the file has no\n * `tools:` field (Claude Code then gives the agent every tool, MCP tools included). Accepts the\n * comma-separated form, a flow list (`[a, b]`) and a block list.\n */\nexport function parseAgentFrontmatterTools(markdown: string): string[] | null {\n const match = /^---\\r?\\n([\\s\\S]*?)\\r?\\n---/.exec(markdown);\n if (!match) return null;\n const lines = match[1].split(/\\r?\\n/);\n const index = lines.findIndex((line) => /^tools\\s*:/.test(line));\n if (index === -1) return null;\n const unquote = (value: string) =>\n value\n .trim()\n .replace(/^[\"']|[\"']$/g, \"\")\n .trim();\n const inline = lines[index].replace(/^tools\\s*:/, \"\").trim();\n if (inline) {\n return inline\n .replace(/^\\[|\\]$/g, \"\")\n .split(\",\")\n .map(unquote)\n .filter(Boolean);\n }\n const tools: string[] = [];\n for (const line of lines.slice(index + 1)) {\n const item = /^\\s+-\\s*(.+)$/.exec(line);\n if (!item) break;\n tools.push(unquote(item[1]));\n }\n return tools;\n}\n\n/**\n * Where Claude Code looks for a session's agents, and what DrBot passes it.\n *\n * Checked against claude 2.1.321 (#1044): a session started in a directory loads every `.md` under\n * `.claude/agents/` (subfolders included) of that directory and each parent, up to the git root\n * (or the filesystem root outside a repo), then the user folder (`$CLAUDE_CONFIG_DIR/agents`, or\n * `~/.claude/agents`), then plugins. An agent's name is its frontmatter `name:`, or the file name\n * without one. For `--agent dr-architect` the nearest folder wins; the dr plugin's own copy,\n * `dr:dr-architect`, comes last and names the plugin's server's tools (mcp__plugin_dr_dr__*),\n * which DrBot's MCP server (named `dr`) doesn't serve.\n */\nexport interface AgentLookupOptions {\n /** Home directory for `~/.claude/agents`; defaults to the OS home. */\n homeDir?: string;\n /** Environment for CLAUDE_CONFIG_DIR; defaults to process.env. */\n env?: NodeJS.ProcessEnv;\n /** The bundled dr-architect source; defaults to bundledAgentFile(). Null: there is none. */\n bundledPath?: string | null;\n}\n\n/** An agents folder Claude Code reads, and whether it counts as the project's or the user's. */\nexport interface AgentDirectory {\n dir: string;\n source: \"project\" | \"user\";\n}\n\n/** The agents folders a session started in `rootPath` reads, highest priority first. */\nexport function agentDirectories(rootPath: string, options: AgentLookupOptions = {}): AgentDirectory[] {\n const env = options.env ?? process.env;\n const configDir = env.CLAUDE_CONFIG_DIR;\n const userDir = configDir\n ? resolve(configDir, \"agents\")\n : join(options.homeDir ?? homedir(), \".claude\", \"agents\");\n const dirs: AgentDirectory[] = [];\n let dir = resolve(rootPath);\n for (;;) {\n const agents = join(dir, \".claude\", \"agents\");\n if (agents !== userDir) dirs.push({ dir: agents, source: \"project\" });\n if (existsSync(join(dir, \".git\"))) break;\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n dirs.push({ dir: userDir, source: \"user\" });\n return dirs;\n}\n\n/** The name Claude Code gives an agent file: frontmatter `name:`, else the file name. */\nfunction agentFileName(path: string): string {\n try {\n const match = /^---\\r?\\n([\\s\\S]*?)\\r?\\n---/.exec(readFileSync(path, \"utf8\"));\n const frontmatter = match ? (parseYaml(match[1]) as Record<string, unknown> | null) : null;\n if (typeof frontmatter?.name === \"string\" && frontmatter.name.trim()) return frontmatter.name.trim();\n } catch {\n // Unreadable or malformed frontmatter: Claude Code falls back to the file name too.\n }\n return basename(path, \".md\");\n}\n\n/** Every .md file under a folder, subfolders included, in a stable order. Empty when it doesn't exist. */\nfunction markdownFiles(dir: string): string[] {\n let entries: Dirent[];\n try {\n entries = readdirSync(dir, { withFileTypes: true });\n } catch {\n return [];\n }\n const files: string[] = [];\n for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {\n const path = join(dir, entry.name);\n if (entry.isDirectory()) files.push(...markdownFiles(path));\n else if (entry.name.endsWith(\".md\")) files.push(path);\n }\n return files;\n}\n\n/** An installed dr-architect Claude Code would load before the plugin's, or null. */\nexport function findInstalledAgentFile(\n rootPath: string,\n options: AgentLookupOptions = {}\n): { path: string; source: \"project\" | \"user\" } | null {\n for (const { dir, source } of agentDirectories(rootPath, options)) {\n const path = markdownFiles(dir).find((file) => agentFileName(file) === DR_ARCHITECT_AGENT);\n if (path) return { path, source };\n }\n return null;\n}\n\n/**\n * The dr-architect source shipped with this CLI (the file `dr claude install` copies), with its\n * mcp__dr__* tool names. Built CLI: dist/coding-agents/ \u2192 dist/integrations/; from source:\n * cli/src/coding-agents/ \u2192 integrations/. Null when neither exists.\n */\nexport function bundledAgentFile(exists: (path: string) => boolean = existsSync): string | null {\n const relativePaths = [\n `../integrations/claude_code/agents/${DR_ARCHITECT_AGENT}.md`,\n `../../../integrations/claude_code/agents/${DR_ARCHITECT_AGENT}.md`,\n ];\n for (const relativePath of relativePaths) {\n const candidate = fileURLToPath(new URL(relativePath, import.meta.url));\n if (exists(candidate)) return candidate;\n }\n return null;\n}\n\n/** The dr-architect copy DrBot runs, and where it comes from. */\nexport interface DrBotAgent {\n path: string;\n source: \"project\" | \"user\" | \"bundled\";\n}\n\n/**\n * The dr-architect copy DrBot runs in `rootPath`: an installed project or user copy, else the\n * bundled source (passed with --agents, which outranks the plugin's copy). Null when there is\n * none at all.\n */\nexport function resolveDrBotAgent(rootPath: string, options: AgentLookupOptions = {}): DrBotAgent | null {\n const installed = findInstalledAgentFile(rootPath, options);\n if (installed) return installed;\n const bundledPath = options.bundledPath === undefined ? bundledAgentFile() : options.bundledPath;\n return bundledPath ? { path: bundledPath, source: \"bundled\" } : null;\n}\n\n/** A Claude Code --agents entry: what an agent file's frontmatter and body say. */\nexport interface AgentDefinition {\n description: string;\n prompt: string;\n tools?: string[];\n model?: string;\n}\n\n/** Turns an agent markdown file into a --agents definition. Throws without frontmatter or a description. */\nexport function agentDefinitionFromMarkdown(markdown: string): AgentDefinition {\n const match = /^---\\r?\\n([\\s\\S]*?)\\r?\\n---\\r?\\n?/.exec(markdown);\n if (!match) throw new Error(\"agent file has no frontmatter\");\n const frontmatter = (parseYaml(match[1]) ?? {}) as Record<string, unknown>;\n if (typeof frontmatter.description !== \"string\" || !frontmatter.description.trim()) {\n throw new Error(\"agent file has no description\");\n }\n const definition: AgentDefinition = {\n description: frontmatter.description,\n prompt: markdown.slice(match[0].length).trim(),\n };\n const tools = parseAgentFrontmatterTools(markdown);\n if (tools !== null) definition.tools = tools;\n if (typeof frontmatter.model === \"string\") definition.model = frontmatter.model;\n return definition;\n}\n\n/**\n * Extra `claude` arguments that make `--agent dr-architect` run `agent`. Only the bundled copy\n * needs them: `--agents` outranks every installed agent, the plugin's included. Throws when the\n * bundled file can't be read or parsed.\n */\nexport async function drBotAgentArgs(agent: DrBotAgent | null): Promise<string[]> {\n if (agent?.source !== \"bundled\") return [];\n const definition = agentDefinitionFromMarkdown(await readFile(agent.path, \"utf8\"));\n return [\"--agents\", JSON.stringify({ [DR_ARCHITECT_AGENT]: definition })];\n}\n\n/** The dr MCP tools a mode uses that the dr-architect DrBot runs can't see. */\nexport interface AgentMcpToolCheck {\n /** The agent file that was checked. */\n path: string;\n /** Where that copy comes from. */\n source: DrBotAgent[\"source\"];\n /** The mcp__dr__* rules the mode uses that the agent's `tools:` field leaves out. */\n missing: string[];\n /** True when the agent can see none of them (a copy installed before DrBot used MCP). */\n noneVisible: boolean;\n /**\n * Set when the bundled copy couldn't be passed with --agents. Claude Code then runs whatever it\n * finds (the plugin's copy, say), so DrBot can't count on any dr tool: noneVisible is true.\n */\n error?: string;\n}\n\n/** Every dr MCP tool DrBot can use in a mode (danger mode may use them all). */\nfunction drMcpToolsForMode(mode: DrBotMode): string[] {\n return mode === \"danger\"\n ? [...DR_MCP_READ_TOOLS, ...DR_MCP_CHANGESET_TOOLS].map(drMcpToolRule)\n : drMcpAllowedTools(mode);\n}\n\n/**\n * Checks that an agent file lists the dr MCP tools DrBot's mode uses. An agent's `tools:` field\n * limits what it can call, so a copy installed before DrBot moved to MCP can't see the server at\n * all, whatever --allowedTools says. Null when there's nothing to report: no agent, no `tools:`\n * field, a server-wide `mcp__dr` entry, or every tool listed.\n */\nexport async function checkAgentMcpTools(\n agent: DrBotAgent | null,\n mode: DrBotMode\n): Promise<AgentMcpToolCheck | null> {\n if (!agent) return null;\n const { path, source } = agent;\n const tools = parseAgentFrontmatterTools(await readFile(path, \"utf8\"));\n if (tools === null) return null;\n const listed = new Set(tools);\n if (listed.has(`mcp__${DR_MCP_SERVER_NAME}`) || listed.has(`mcp__${DR_MCP_SERVER_NAME}__*`)) return null;\n const required = drMcpToolsForMode(mode);\n const missing = required.filter((rule) => !listed.has(rule));\n if (missing.length === 0) return null;\n return { path, source, missing, noneVisible: missing.length === required.length };\n}\n\n/** checkAgentMcpTools for the copy resolveDrBotAgent picks in `rootPath`. */\nexport async function checkInstalledAgentMcpTools(\n rootPath: string,\n mode: DrBotMode,\n options: AgentLookupOptions = {}\n): Promise<AgentMcpToolCheck | null> {\n return checkAgentMcpTools(resolveDrBotAgent(rootPath, options), mode);\n}\n\n/** The dr-architect DrBot runs: the extra claude arguments and the tool check, from one lookup. */\nexport interface DrBotAgentLaunch {\n agent: DrBotAgent | null;\n /** `--agents <json>` for the bundled copy, else empty. */\n args: string[];\n check: AgentMcpToolCheck | null;\n}\n\n/**\n * Resolves DrBot's dr-architect once and derives both the launch arguments and the tool check\n * from it. When the bundled copy can't be passed, the check reports that no dr tool is visible\n * (with `error`) rather than passing against a file claude won't run. Throws if an installed\n * copy can't be read.\n */\nexport async function prepareDrBotAgent(\n rootPath: string,\n mode: DrBotMode,\n options: AgentLookupOptions = {}\n): Promise<DrBotAgentLaunch> {\n const agent = resolveDrBotAgent(rootPath, options);\n let args: string[];\n try {\n args = await drBotAgentArgs(agent);\n } catch (error) {\n const missing = drMcpToolsForMode(mode);\n return {\n agent,\n args: [],\n check: {\n path: agent!.path,\n source: \"bundled\",\n missing,\n noneVisible: true,\n error: error instanceof Error ? error.message : String(error),\n },\n };\n }\n return { agent, args, check: await checkAgentMcpTools(agent, mode) };\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|