@stackwright-pro/mcp 0.2.0-alpha.53 ā 0.2.0-alpha.58
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/integrity.js +17 -5
- package/dist/integrity.js.map +1 -1
- package/dist/integrity.mjs +17 -5
- package/dist/integrity.mjs.map +1 -1
- package/dist/server.js +161 -18
- package/dist/server.js.map +1 -1
- package/dist/server.mjs +161 -18
- package/dist/server.mjs.map +1 -1
- package/package.json +3 -3
package/dist/server.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/server.ts","../src/tools/data-explorer.ts","../src/coerce.ts","../src/tools/security.ts","../src/tools/isr.ts","../src/tools/dashboard.ts","../src/tools/clarification.ts","../src/tools/packages.ts","../src/tools/questions.ts","../src/question-adapter.ts","../src/tools/orchestration.ts","../src/tools/pipeline.ts","../src/artifact-signing.ts","../src/tools/safe-write.ts","../src/tools/auth.ts","../src/integrity.ts","../src/tools/domain.ts","../src/tools/type-schemas.ts","../package.json"],"sourcesContent":["import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { registerDataExplorerTools } from './tools/data-explorer.js';\nimport { registerSecurityTools } from './tools/security.js';\nimport { registerIsrTools } from './tools/isr.js';\nimport { registerDashboardTools } from './tools/dashboard.js';\nimport { registerClarificationTools } from './tools/clarification.js';\nimport { registerPackageTools } from './tools/packages.js';\nimport { registerQuestionTools } from './tools/questions.js';\nimport { registerOrchestrationTools } from './tools/orchestration.js';\nimport { registerPipelineTools } from './tools/pipeline.js';\nimport { registerSafeWriteTools } from './tools/safe-write.js';\nimport { registerAuthTools } from './tools/auth.js';\nimport { registerIntegrityTools } from './integrity.js';\nimport { registerArtifactSigningTools } from './artifact-signing.js';\nimport { registerDomainTools } from './tools/domain.js';\nimport { registerTypeSchemasTool } from './tools/type-schemas.js';\nimport packageJson from '../package.json';\n\nconst server = new McpServer({\n name: 'stackwright-pro',\n version: packageJson.version,\n});\n\n// Register all Pro tools\nregisterDataExplorerTools(server); // stackwright_pro_list_entities, stackwright_pro_generate_filter\nregisterSecurityTools(server); // stackwright_pro_validate_spec, stackwright_pro_add_approved_spec, stackwright_pro_list_approved_specs\nregisterIsrTools(server); // stackwright_pro_configure_isr, stackwright_pro_configure_isr_batch\nregisterDashboardTools(server); // stackwright_pro_generate_dashboard, stackwright_pro_generate_detail_page\nregisterClarificationTools(server); // stackwright_pro_clarify, stackwright_pro_detect_conflict\nregisterPackageTools(server); // stackwright_pro_setup_packages\nregisterQuestionTools(server); // stackwright_pro_present_phase_questions\nregisterOrchestrationTools(server); // stackwright_pro_parse_otter_response, stackwright_pro_save_manifest, stackwright_pro_save_phase_answers, stackwright_pro_read_phase_answers, stackwright_pro_get_otter_name\nregisterPipelineTools(server); // stackwright_pro_get_pipeline_state, stackwright_pro_set_pipeline_state, stackwright_pro_check_execution_ready, stackwright_pro_list_artifacts, stackwright_pro_write_phase_questions, stackwright_pro_build_specialist_prompt, stackwright_pro_validate_artifact\nregisterSafeWriteTools(server); // stackwright_pro_safe_write\nregisterAuthTools(server); // stackwright_pro_configure_auth\nregisterIntegrityTools(server); // stackwright_pro_verify_otter_integrity\nregisterArtifactSigningTools(server); // stackwright_pro_verify_artifact_signatures\nregisterDomainTools(server); // stackwright_pro_list_collections, stackwright_pro_resolve_data_strategy, stackwright_pro_validate_workflow\nregisterTypeSchemasTool(server); // stackwright_pro_get_type_schemas\n\nasync function main() {\n const transport = new StdioServerTransport();\n await server.connect(transport);\n console.error('Stackwright Pro MCP server running on stdio');\n}\n\nmain().catch((err) => {\n console.error('Fatal:', err);\n process.exit(1);\n});\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { listEntities, generateFilter } from '@stackwright-pro/cli-data-explorer';\nimport { jsonCoerce } from '../coerce.js';\n\n/**\n * Register data-explorer MCP tools.\n * Tools for discovering API entities and generating endpoint filters.\n */\nexport function registerDataExplorerTools(server: McpServer): void {\n // Tool: List available entities\n server.tool(\n 'stackwright_pro_list_entities',\n 'List all available API entities from OpenAPI specs or generated Zod schemas. ' +\n 'Use this to discover what entities are available before generating endpoint filters. ' +\n 'Returns entity names, endpoints, and field counts. ' +\n 'Part of the Pro Otter Raft for building API-integrated Stackwright applications.',\n {\n specPath: z.string().optional().describe('Path to OpenAPI spec file (YAML or JSON)'),\n projectRoot: z\n .string()\n .optional()\n .describe('Project root directory (auto-detected if omitted)'),\n },\n async ({ specPath, projectRoot }) => {\n const result = listEntities({\n ...(specPath !== undefined && { specPath }),\n ...(projectRoot !== undefined && { projectRoot }),\n });\n\n if (!result.success) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Error discovering entities: ${(result.errors ?? []).join(', ')}`,\n },\n ],\n isError: true,\n };\n }\n\n const lines: string[] = [`š¦ Found ${result.entities.length} API Entities:\\n`];\n\n for (const entity of result.entities) {\n lines.push(`š¦ ${entity.name} (${entity.slug})`);\n lines.push(` Endpoint: ${entity.endpoint}`);\n lines.push(` Fields: ${entity.fieldCount}`);\n if (entity.fields.length > 0) {\n const fieldTypes = entity.fields\n .slice(0, 3)\n .map((f) => `${f.name}:${f.type}`)\n .join(', ');\n lines.push(` Types: ${fieldTypes}${entity.fields.length > 3 ? '...' : ''}`);\n }\n lines.push('');\n }\n\n lines.push(\n `\\nš” Use stackwright_pro_generate_filter with selected entity slugs to create endpoint filters.`\n );\n\n return {\n content: [\n {\n type: 'text' as const,\n text: lines.join('\\n'),\n },\n ],\n };\n }\n );\n\n // Tool: Generate endpoint filter\n server.tool(\n 'stackwright_pro_generate_filter',\n 'Generate endpoint filter configuration from selected entities. ' +\n 'Creates include/exclude patterns for stackwright.yml OpenAPI integration. ' +\n 'Use this after stackwright_pro_list_entities to select which API endpoints the application needs. ' +\n 'Only selected endpoints will generate client code, reducing bundle size and improving security.',\n {\n selectedEntities: jsonCoerce(z.array(z.string())).describe(\n 'Entity slugs to include (e.g., [\"equipment\", \"supplies\"])'\n ),\n excludePatterns: jsonCoerce(z.array(z.string()).optional()).describe(\n 'Glob patterns to exclude (e.g., [\"/admin/**\", \"/reports/**\"])'\n ),\n\n projectRoot: z.string().optional().describe('Project root directory'),\n },\n async ({ selectedEntities, excludePatterns, projectRoot }) => {\n const result = generateFilter({\n selectedEntities,\n ...(excludePatterns !== undefined && { excludePatterns }),\n projectRoot: projectRoot ?? process.cwd(),\n });\n\n if (!result.success) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Error generating filter: ${result.warnings?.join(', ')}`,\n },\n ],\n isError: true,\n };\n }\n\n const lines: string[] = ['š Generated Endpoint Filter:\\n'];\n lines.push('```yaml');\n lines.push('integrations:');\n lines.push(' - type: openapi');\n lines.push(' endpoints:');\n\n if (result.filter.include && result.filter.include.length > 0) {\n lines.push(' include:');\n for (const path of result.filter.include) {\n lines.push(` - ${path}`);\n }\n }\n\n if (result.filter.exclude && result.filter.exclude.length > 0) {\n lines.push(' exclude:');\n for (const pattern of result.filter.exclude) {\n lines.push(` - ${pattern}`);\n }\n }\n\n lines.push('```');\n\n if (result.warnings && result.warnings.length > 0) {\n lines.push('\\nā ļø Warnings:');\n for (const warning of result.warnings) {\n lines.push(` ${warning}`);\n }\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: lines.join('\\n'),\n },\n ],\n };\n }\n );\n}\n","/**\n * LLM Input Coercion Utilities ā \"Sinks Not Pipes\"\n *\n * LLMs frequently serialize complex values to JSON strings before passing them\n * as MCP tool arguments. These utilities wrap Zod schemas with z.preprocess\n * steps that coerce the common mis-serializations back to native types before\n * Zod validates them.\n *\n * Usage:\n * import { jsonCoerce, boolCoerce, numCoerce } from '../coerce.js';\n * // In a server.tool() schema:\n * myArray: jsonCoerce(z.array(z.string())).describe('...'),\n * myBool: boolCoerce(z.boolean().optional()).describe('...'),\n * myNum: numCoerce(z.number().optional()).describe('...'),\n *\n * Design note: z.preprocess uses the INNER schema for JSON Schema generation,\n * so the MCP tool's inputSchema still shows the correct native type to the LLM.\n * The coercion is invisible to the model ā it only fires when the model sends\n * the wrong type.\n */\nimport { z } from 'zod';\n\n/**\n * JSON-coerce: If the input is a string, attempt JSON.parse before validation.\n * Handles LLM string-serialization of arrays (`\"[...]\"`), objects (`\"{...}\"`),\n * and records. If JSON.parse fails, the original string is passed through and\n * Zod produces a clear type error.\n */\nexport function jsonCoerce<T extends z.ZodTypeAny>(schema: T) {\n return z.preprocess((v) => {\n if (typeof v === 'string') {\n try {\n return JSON.parse(v);\n } catch {\n return v; // Zod will reject it with a clear error\n }\n }\n return v;\n }, schema);\n}\n\n/**\n * Bool-coerce: Converts the strings \"true\" and \"false\" to their boolean\n * equivalents. Uses explicit string matching ā NOT JavaScript truthiness ā\n * so the string \"false\" correctly maps to boolean false.\n */\nexport function boolCoerce<T extends z.ZodTypeAny>(schema: T) {\n return z.preprocess((v) => (v === 'true' ? true : v === 'false' ? false : v), schema);\n}\n\n/**\n * Num-coerce: Converts pure numeric strings (\"42\", \"3.14\") to numbers.\n * Non-numeric strings pass through unchanged (Zod produces a clear error).\n */\nexport function numCoerce<T extends z.ZodTypeAny>(schema: T) {\n return z.preprocess((v) => {\n if (typeof v === 'string' && v.trim() !== '') {\n const n = Number(v);\n if (!Number.isNaN(n)) return n;\n }\n return v;\n }, schema);\n}\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { createHash } from 'crypto';\nimport fs from 'fs';\nimport path from 'path';\n\n/**\n * Register security-focused MCP tools.\n * Tools for validating specs against approved-specs and managing the allowlist.\n */\nexport function registerSecurityTools(server: McpServer): void {\n // Tool: Validate a spec against approved-specs\n server.tool(\n 'stackwright_pro_validate_spec',\n 'Validate an OpenAPI spec against the enterprise approved-specs configuration. ' +\n 'Checks if the spec URL is on the allowlist and verifies SHA-256 hash integrity. ' +\n 'Use this in enterprise environments where only pre-approved API specs are allowed. ' +\n 'Fails build if spec is not approved or has been modified.',\n {\n specPath: z.string().describe('URL or file path to the OpenAPI spec to validate'),\n configPath: z\n .string()\n .optional()\n .describe('Path to stackwright.yml with prebuild.security config'),\n },\n async ({ specPath, configPath }) => {\n // Try to load config from stackwright.yml\n let securityEnabled = false;\n const allowlist: Array<{ name: string; url: string; sha256: string }> = [];\n\n const configFile = configPath || path.join(process.cwd(), 'stackwright.yml');\n\n if (fs.existsSync(configFile)) {\n try {\n const content = fs.readFileSync(configFile, 'utf8');\n\n // Simple regex extraction for security config\n const securityMatch = content.match(\n /prebuild:\\s*\\n\\s*security:\\s*\\n\\s*enabled:\\s*(true|false)/\n );\n if (securityMatch && securityMatch[1] === 'true') {\n securityEnabled = true;\n // Extract allowlist entries\n const specMatches = content.matchAll(\n /- name:\\s*(.+?)\\n\\s+url:\\s*(.+?)\\n\\s+sha256:\\s*(.+?)(?:\\n|$)/g\n );\n for (const match of specMatches) {\n allowlist.push({\n name: match[1]!.trim(),\n url: match[2]!.trim(),\n sha256: match[3]!.trim(),\n });\n }\n }\n } catch {\n // Config exists but couldn't parse - continue without it\n }\n }\n\n // If no security config, just return success (security not enabled)\n if (!securityEnabled) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `ā
Spec validation skipped (security not enabled)\\n\\nTo enable approved-specs validation, add to stackwright.yml:\\n\\nprebuild:\\n security:\\n enabled: true\\n allowlist:\\n - name: My API\\n url: ${specPath}\\n sha256: <sha256-of-spec>`,\n },\n ],\n };\n }\n\n // Check if spec is in allowlist\n const matchingSpec = allowlist.find((s) => s.url === specPath);\n\n if (!matchingSpec) {\n return {\n content: [\n {\n type: 'text' as const,\n text:\n `ā Spec rejected!\\n\\nError Code: SPEC_NOT_IN_ALLOWLIST\\n\\nURL: ${specPath}\\n\\nThis spec is not on the approved-specs allowlist. ` +\n `Add it using stackwright_pro_add_approved_spec before proceeding.`,\n },\n ],\n isError: true,\n };\n }\n\n // For file-based specs, compute hash and validate\n if (!specPath.startsWith('http://') && !specPath.startsWith('https://')) {\n if (fs.existsSync(specPath)) {\n const specContent = fs.readFileSync(specPath, 'utf8');\n const sha256 = createHash('sha256').update(specContent).digest('hex');\n\n if (sha256 !== matchingSpec.sha256) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `ā Spec hash mismatch!\\n\\nError Code: SPEC_HASH_MISMATCH\\n\\nExpected: ${matchingSpec.sha256.substring(0, 16)}...\\nActual: ${sha256.substring(0, 16)}...\\n\\nThe spec has been modified since it was approved. Re-approve the spec to continue.`,\n },\n ],\n isError: true,\n };\n }\n }\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `ā
Spec approved!\\n\\nName: ${matchingSpec.name}\\nURL: ${specPath}\\nStatus: Valid (${allowlist.length} specs on allowlist)`,\n },\n ],\n };\n }\n );\n\n // Tool: Add approved spec to allowlist\n server.tool(\n 'stackwright_pro_add_approved_spec',\n 'Add an OpenAPI spec to the approved-specs allowlist in stackwright.yml. ' +\n 'Computes the SHA-256 hash of the spec and adds it to the security configuration. ' +\n 'Use this when onboarding a new API in enterprise environments.',\n {\n name: z.string().describe('Human-readable name for the spec'),\n url: z.string().describe('URL or file path to the OpenAPI spec'),\n configPath: z.string().optional().describe('Path to stackwright.yml'),\n },\n async ({ name, url, configPath }) => {\n const configFile = configPath || path.join(process.cwd(), 'stackwright.yml');\n\n // Compute SHA-256 of spec\n let sha256 = '<computed-at-build>';\n\n try {\n if (url.startsWith('http://') || url.startsWith('https://')) {\n // URL spec - hash computed at build time; initial value already set\n } else if (fs.existsSync(url)) {\n const specContent = fs.readFileSync(url, 'utf8');\n sha256 = createHash('sha256').update(specContent).digest('hex');\n } else {\n return {\n content: [\n {\n type: 'text' as const,\n text: `ā Spec file not found: ${url}`,\n },\n ],\n isError: true,\n };\n }\n } catch (e) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `ā Failed to read spec: ${e}`,\n },\n ],\n isError: true,\n };\n }\n\n const yamlSnippet = ` - name: ${name}\n url: ${url}\n sha256: ${sha256}`;\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `š Add this to stackwright.yml under prebuild.security.allowlist:\\n\\n${yamlSnippet}\\n\\nSHA-256 computed: ${sha256}`,\n },\n ],\n };\n }\n );\n\n // Tool: List approved specs\n server.tool(\n 'stackwright_pro_list_approved_specs',\n 'List all specs currently on the approved-specs allowlist. ' +\n 'Shows spec names, URLs, and hash prefixes. ' +\n 'Use this to audit what APIs are approved in the project.',\n {\n configPath: z.string().optional().describe('Path to stackwright.yml'),\n },\n async ({ configPath }) => {\n const configFile = configPath || path.join(process.cwd(), 'stackwright.yml');\n\n if (!fs.existsSync(configFile)) {\n return {\n content: [\n {\n type: 'text' as const,\n text: 'ā stackwright.yml not found in project root.',\n },\n ],\n isError: true,\n };\n }\n\n const content = fs.readFileSync(configFile, 'utf8');\n\n // Check if security is enabled\n const securityEnabled =\n content.includes('prebuild:') &&\n content.includes('security:') &&\n content.includes('enabled: true');\n\n if (!securityEnabled) {\n return {\n content: [\n {\n type: 'text' as const,\n text: 'ā¹ļø Approved-specs validation is not enabled.\\n\\nAdd to stackwright.yml to enable:\\n\\nprebuild:\\n security:\\n enabled: true\\n allowlist: []',\n },\n ],\n };\n }\n\n // Extract specs\n const specs: Array<{ name: string; url: string; sha256: string }> = [];\n const specMatches = content.matchAll(\n /- name:\\s*(.+?)\\n\\s+url:\\s*(.+?)\\n\\s+sha256:\\s*(.+?)(?:\\n|$)/g\n );\n\n for (const match of specMatches) {\n specs.push({\n name: match[1]!.trim(),\n url: match[2]!.trim(),\n sha256: match[3]!.trim().substring(0, 16) + '...',\n });\n }\n\n if (specs.length === 0) {\n return {\n content: [\n {\n type: 'text' as const,\n text: 'ā¹ļø Security enabled but no specs on allowlist.\\n\\nAdd specs using stackwright_pro_add_approved_spec.',\n },\n ],\n };\n }\n\n const lines = [`š Approved Specs (${specs.length}):\\n`];\n for (const spec of specs) {\n lines.push(`š¦ ${spec.name}`);\n lines.push(` URL: ${spec.url}`);\n lines.push(` Hash: ${spec.sha256}`);\n lines.push('');\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: lines.join('\\n'),\n },\n ],\n };\n }\n );\n}\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport fs from 'fs';\nimport path from 'path';\nimport { jsonCoerce, numCoerce } from '../coerce.js';\n\n/**\n * Register ISR configuration MCP tools.\n * Tools for configuring Incremental Static Regeneration for API-backed collections.\n */\nexport function registerIsrTools(server: McpServer): void {\n // Tool: Configure ISR for a collection\n server.tool(\n 'stackwright_pro_configure_isr',\n 'Configure Incremental Static Regeneration (ISR) for an API-backed collection. ' +\n 'ISR allows API data to be cached and refreshed on a schedule, providing real-time data ' +\n 'with the performance of static generation. ' +\n 'Use this after stackwright_pro_generate_filter to set revalidation intervals.',\n {\n collection: z.string().describe('Collection name (e.g., \"equipment\", \"supplies\")'),\n revalidateSeconds: numCoerce(z.number().optional()).describe(\n 'Revalidation interval in seconds (default: 60)'\n ),\n fallback: z\n .enum(['blocking', 'true', 'false'])\n .optional()\n .describe('Fallback behavior for new pages'),\n configPath: z.string().optional().describe('Path to stackwright.yml'),\n },\n async ({ collection, revalidateSeconds = 60, fallback = 'blocking', configPath }) => {\n const revalidate = revalidateSeconds;\n\n const yamlSnippet = `# Add to stackwright.yml under integrations:\n - type: openapi\n name: ${collection}\n # ... other config\n isr:\n revalidate: ${revalidate}\n fallback: ${fallback}`;\n\n let description: string;\n if (revalidate < 60) {\n description = 'ā” Very fresh data (revalidate every ' + revalidate + 's)';\n } else if (revalidate < 300) {\n description = 'š Fresh data (revalidate every ' + (revalidate / 60).toFixed(0) + ' min)';\n } else if (revalidate < 3600) {\n description = 'š¾ Cached data (revalidate every ' + (revalidate / 60).toFixed(0) + ' min)';\n } else {\n description =\n 'šļø Static data (revalidate every ' + (revalidate / 3600).toFixed(0) + ' hour)';\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `āļø ISR Configuration for \"${collection}\":\\n\\n${description}\\n\\nFallback: ${fallback === 'blocking' ? 'ā³ Show loading until cached' : fallback === 'true' ? 'š Generate on demand' : 'ā 404 for new pages'}\\n\\n\\`\\`\\`yaml\\n${yamlSnippet}\\n\\`\\`\\``,\n },\n ],\n };\n }\n );\n\n // Tool: Configure ISR for multiple collections\n server.tool(\n 'stackwright_pro_configure_isr_batch',\n 'Configure ISR for multiple collections at once. ' +\n 'More efficient than calling stackwright_pro_configure_isr multiple times. ' +\n 'Provide different revalidation intervals based on data freshness requirements.',\n {\n collections: jsonCoerce(\n z.array(\n z.object({\n name: z.string().describe('Collection name'),\n revalidateSeconds: numCoerce(z.number().optional()).describe('Revalidation interval'),\n })\n )\n ).describe('Array of collection configurations'),\n defaultFallback: z\n .enum(['blocking', 'true', 'false'])\n .optional()\n .describe('Default fallback behavior'),\n configPath: z.string().optional().describe('Path to stackwright.yml'),\n },\n async ({ collections, defaultFallback = 'blocking', configPath }) => {\n const lines = [`āļø Batch ISR Configuration:\\n`];\n\n for (const col of collections) {\n const rev = col.revalidateSeconds || 60;\n let freshness = 'š¾';\n if (rev < 60) freshness = 'ā”';\n else if (rev < 300) freshness = 'š';\n else if (rev >= 3600) freshness = 'šļø';\n\n lines.push(`${freshness} ${col.name}: revalidate=${rev}s`);\n }\n\n lines.push(`\\nFallback: ${defaultFallback}`);\n\n return {\n content: [\n {\n type: 'text' as const,\n text: lines.join('\\n'),\n },\n ],\n };\n }\n );\n}\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { listEntities } from '@stackwright-pro/cli-data-explorer';\nimport { jsonCoerce } from '../coerce.js';\n\n/**\n * Register dashboard generation MCP tools.\n * Tools for building pages that display live API data.\n */\nexport function registerDashboardTools(server: McpServer): void {\n // Tool: Generate dashboard page configuration\n server.tool(\n 'stackwright_pro_generate_dashboard',\n 'Generate a dashboard page configuration for displaying API data. ' +\n 'Creates YAML content for a Stackwright page with grid, metric_card, data_table, and collection_list content types. ' +\n 'Use this after stackwright_pro_generate_filter to create pages for your API collections.',\n {\n entities: jsonCoerce(z.array(z.string())).describe('Entity slugs to include in dashboard'),\n layout: z.enum(['grid', 'table', 'mixed']).optional().describe('Dashboard layout style'),\n pageTitle: z.string().optional().describe('Page title'),\n specPath: z.string().optional().describe('Path to OpenAPI spec for entity details'),\n },\n async ({ entities, layout = 'mixed', pageTitle, specPath }) => {\n // Get entity details if spec provided\n let entityDetails: any[] = [];\n if (specPath) {\n const result = listEntities({ specPath });\n if (result.success) {\n entityDetails = result.entities.filter((e) => entities.includes(e.slug));\n }\n }\n\n const title =\n pageTitle || entities.map((e) => e.charAt(0).toUpperCase() + e.slice(1)).join(' & ');\n\n const yamlLines = [\n '# Dashboard page configuration',\n '# Generated by Stackwright Pro MCP',\n '',\n 'content:',\n ' meta:',\n ` title: \"${title} | Dashboard\"`,\n ` description: \"Live data from API\"`,\n '',\n ' content_items:',\n ];\n\n // Add metric cards in a grid for each entity\n if (layout === 'grid' || layout === 'mixed') {\n for (const slug of entities) {\n yamlLines.push(` - type: grid`);\n yamlLines.push(` columns: 4`);\n yamlLines.push(` items:`);\n yamlLines.push(` - type: metric_card`);\n yamlLines.push(` label: \"Total\"`);\n yamlLines.push(` value: {{ ${slug}.count }}`);\n yamlLines.push(` icon: Database`);\n yamlLines.push(` - type: metric_card`);\n yamlLines.push(` label: \"Active\"`);\n yamlLines.push(` value: 0`);\n yamlLines.push(` icon: CheckCircle`);\n yamlLines.push('');\n }\n }\n\n // Add collection listing for each entity\n yamlLines.push(` - type: collection_list`);\n yamlLines.push(` label: ${entities[0]}-listing`);\n yamlLines.push(` collection: ${entities[0]}`);\n yamlLines.push(` showFilters: true`);\n yamlLines.push(` showSearch: true`);\n const defaultCols = ['id', 'name', 'status', 'created_at'];\n yamlLines.push(\n ` columns: ${\n entityDetails[0]?.fields\n ?.slice(0, 4)\n .map((f: any) => f.name)\n .join(', ') || defaultCols.join(', ')\n }`\n );\n yamlLines.push('');\n\n if (layout === 'table') {\n yamlLines.push(` - type: data_table`);\n yamlLines.push(` label: ${entities[0]}-table`);\n yamlLines.push(` collection: ${entities[0]}`);\n yamlLines.push(` columns:`);\n yamlLines.push(` - field: id`);\n yamlLines.push(` header: ID`);\n yamlLines.push(` sortable: true`);\n yamlLines.push(` - field: name`);\n yamlLines.push(` header: Name`);\n yamlLines.push(` sortable: true`);\n yamlLines.push(` - field: status`);\n yamlLines.push(` header: Status`);\n yamlLines.push(` type: badge`);\n }\n\n const yaml = yamlLines.join('\\n');\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `š Generated Dashboard for: ${entities.join(', ')}\\n\\nLayout: ${layout}\\n\\n\\`\\`\\`yaml\\n${yaml}\\n\\`\\`\\`\\n\\nš” Add this to pages/dashboard/content.yml and validate with stackwright_validate_pages.`,\n },\n ],\n };\n }\n );\n\n // Tool: Generate detail page\n server.tool(\n 'stackwright_pro_generate_detail_page',\n 'Generate a detail view page for a single API entity. ' +\n 'Creates YAML content for displaying all fields of an individual record. ' +\n 'Use this to create detail pages that complement collection listing pages.',\n {\n entity: z.string().describe('Entity slug (e.g., \"equipment\")'),\n slugField: z.string().optional().describe('Field to use as URL slug (default: \"id\")'),\n specPath: z.string().optional().describe('Path to OpenAPI spec for field details'),\n },\n async ({ entity, slugField = 'id', specPath }) => {\n // Get field details if spec provided\n let fields: any[] = [];\n if (specPath) {\n const result = listEntities({ specPath });\n if (result.success) {\n const ent = result.entities.find((e) => e.slug === entity);\n if (ent) {\n fields = ent.fields;\n }\n }\n }\n\n const entityName = entity.charAt(0).toUpperCase() + entity.slice(1);\n\n const yamlLines = [\n `# Detail page for ${entityName}`,\n '# Generated by Stackwright Pro MCP',\n '',\n 'content:',\n ' meta:',\n ` title: \"${entityName} Details | {{ ${entity}.${slugField} }}\"`,\n '',\n ' content_items:',\n ' - type: text_block',\n ' label: \"detail-header\"',\n ' heading:',\n ` text: \"{{ ${entity}.${slugField} }}\"`,\n ' textSize: \"h1\"',\n ' textBlocks:',\n ` - text: \"Details for this ${entity}\"`,\n ' textSize: \"body1\"',\n '',\n ' - type: grid',\n ' label: \"detail-fields\"',\n ' columns:',\n ];\n\n // Add field displays as text_block items within grid columns\n const displayFields =\n fields.length > 0\n ? fields.slice(0, 8)\n : [\n { name: slugField, type: 'string' },\n { name: 'created_at', type: 'datetime' },\n { name: 'updated_at', type: 'datetime' },\n ];\n\n // Split fields into two columns\n const mid = Math.ceil(displayFields.length / 2);\n const col1 = displayFields.slice(0, mid);\n const col2 = displayFields.slice(mid);\n\n for (const [colIndex, colFields] of [col1, col2].entries()) {\n yamlLines.push(' - width: 1');\n yamlLines.push(' content_items:');\n for (const field of colFields) {\n const label = field.name\n .replace(/_/g, ' ')\n .replace(/\\b\\w/g, (l: string) => l.toUpperCase());\n yamlLines.push(' - type: text_block');\n yamlLines.push(` label: \"${field.name}-field\"`);\n yamlLines.push(' heading:');\n yamlLines.push(` text: \"${label}\"`);\n yamlLines.push(' textSize: \"h4\"');\n yamlLines.push(' textBlocks:');\n yamlLines.push(` - text: \"{{ ${entity}.${field.name} }}\"`);\n yamlLines.push(' textSize: \"body1\"');\n }\n }\n\n // Back navigation\n yamlLines.push('');\n yamlLines.push(' - type: action_bar');\n yamlLines.push(' actions:');\n yamlLines.push(` - label: \"<- Back to ${entityName}\"`);\n yamlLines.push(' action: navigate');\n yamlLines.push(` href: \"/${entity}\"`);\n yamlLines.push(' style: secondary');\n\n const yaml = yamlLines.join('\\n');\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `š Generated Detail Page for: ${entity}\\n\\n\\`\\`\\`yaml\\n${yaml}\\n\\`\\`\\`\\n\\nš” Add this to pages/${entity}/[${slugField}]/content.yml and validate.`,\n },\n ],\n };\n }\n );\n}\n","/**\n * Clarification MCP Tools\n *\n * Provides human-in-the-loop clarification for otters that encounter\n * ambiguity during execution.\n *\n * Two tools:\n * 1. stackwright_pro_clarify ā mid-execution clarification (NOT upfront\n * question collection; that's the Question Manifest Protocol).\n * 2. stackwright_pro_detect_conflict ā pure-logic conflict detection between\n * stated preferences and actual selections.\n *\n * Handler functions are exported for direct testing ā no MCP server needed.\n */\n\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { jsonCoerce } from '../coerce.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface ClarificationRequest {\n context?: string | undefined;\n question_type: 'closed_choice' | 'open_text';\n question: string;\n choices?: string[] | undefined;\n priority: 'blocking' | 'preferred' | 'optional';\n target_field?: string | undefined;\n}\n\nexport interface ClarificationResponse {\n action: 'ask_user';\n adaptedQuestion?: AdaptedQuestion | undefined;\n prompt?: string | undefined;\n suggestedDefault?: string | undefined;\n targetField?: string | undefined;\n}\n\n/** Ready-to-pass shape for `ask_user_question`. */\ninterface AdaptedQuestion {\n question: string;\n header: string;\n options: Array<{ label: string; description?: string }>;\n}\n\nexport interface ConflictDetectionInput {\n stated_preference: string;\n selected_values: Record<string, string>;\n}\n\nexport interface ConflictDetectionResult {\n conflict: boolean;\n description?: string;\n resolution_options?: string[];\n}\n\n// ---------------------------------------------------------------------------\n// Contradiction patterns ā keyword matching against known opposites\n// ---------------------------------------------------------------------------\n\nconst CONTRADICTION_PATTERNS: Array<{\n keywords: string[];\n conflicts: string[];\n}> = [\n {\n keywords: ['minimal', 'clean', 'simple'],\n conflicts: ['vibrant', 'rich', 'content-heavy', 'playful'],\n },\n {\n keywords: ['dark', 'dark mode'],\n conflicts: ['light mode only', 'light'],\n },\n {\n keywords: ['enterprise', 'professional', 'corporate'],\n conflicts: ['playful', 'casual', 'fun'],\n },\n {\n keywords: ['accessible', 'wcag', 'section 508'],\n conflicts: ['compact', 'dense', 'small text'],\n },\n {\n keywords: ['government', 'defense', 'federal'],\n conflicts: ['public', 'no auth', 'consumer'],\n },\n];\n\n// ---------------------------------------------------------------------------\n// Handler: clarify\n// ---------------------------------------------------------------------------\n\nexport function handleClarify(input: ClarificationRequest): ClarificationResponse {\n const { question_type, question, choices, priority, target_field, context } = input;\n\n const base: ClarificationResponse = {\n action: 'ask_user',\n targetField: target_field,\n };\n\n if (question_type === 'closed_choice' && choices && choices.length > 0) {\n const header = truncateHeader(question);\n base.adaptedQuestion = {\n question,\n header,\n options: choices.map((c) => ({ label: c })),\n };\n } else {\n // open_text ā foreman should ask the user directly\n const contextPrefix = context ? `Context: ${context}\\n\\n` : '';\n base.prompt = `${contextPrefix}${question}`;\n }\n\n if (priority === 'optional') {\n base.suggestedDefault = inferDefault(question_type, choices);\n }\n\n return base;\n}\n\n// ---------------------------------------------------------------------------\n// Handler: detect conflict\n// ---------------------------------------------------------------------------\n\nexport function handleDetectConflict(input: ConflictDetectionInput): ConflictDetectionResult {\n const preferenceLower = input.stated_preference.toLowerCase();\n const valuesLower = Object.values(input.selected_values).map((v) => v.toLowerCase());\n\n for (const pattern of CONTRADICTION_PATTERNS) {\n const preferenceMatch = pattern.keywords.some((kw) => preferenceLower.includes(kw));\n if (!preferenceMatch) continue;\n\n const conflictingValues = valuesLower.filter((val) =>\n pattern.conflicts.some((c) => val.includes(c))\n );\n\n if (conflictingValues.length > 0) {\n const matchedKeywords = pattern.keywords.filter((kw) => preferenceLower.includes(kw));\n const primaryKeyword = matchedKeywords[0] ?? 'preference';\n return {\n conflict: true,\n description:\n `Stated preference includes \"${matchedKeywords.join(', ')}\" ` +\n `but selections contain \"${conflictingValues.join(', ')}\" ā these are contradictory.`,\n resolution_options: [\n `Align selections with the \"${primaryKeyword}\" preference`,\n `Revise stated preference to match current selections`,\n 'Ask user which direction they actually want',\n ],\n };\n }\n }\n\n return { conflict: false };\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Truncate to 50 chars (ask_user_question header limit). */\nfunction truncateHeader(text: string): string {\n const MAX = 50;\n if (text.length <= MAX) return text;\n return text.slice(0, MAX - 1) + 'ā¦';\n}\n\n/** Best-effort default suggestion for optional questions. */\nfunction inferDefault(\n questionType: ClarificationRequest['question_type'],\n choices?: string[]\n): string {\n if (questionType === 'closed_choice' && choices && choices.length > 0) {\n return choices[0] ?? '(first choice)';\n }\n return '(use sensible project default)';\n}\n\n// ---------------------------------------------------------------------------\n// MCP tool registration\n// ---------------------------------------------------------------------------\n\nexport function registerClarificationTools(server: McpServer): void {\n // -----------------------------------------------------------------------\n // 1. stackwright_pro_clarify\n // -----------------------------------------------------------------------\n server.tool(\n 'stackwright_pro_clarify',\n 'Ask the user for clarification when a specialist otter encounters ambiguity. ' +\n 'This is for MID-EXECUTION questions, NOT upfront question collection (use the Question Manifest Protocol for that). ' +\n 'Returns a structured response for the foreman to present to the user via ask_user_question (closed_choice) or directly (open_text).',\n {\n context: z.string().optional().describe('Context about what the otter is trying to do'),\n question_type: z\n .enum(['closed_choice', 'open_text'])\n .describe('Type of question being asked'),\n question: z.string().describe('The clarification question to ask the user'),\n choices: jsonCoerce(z.array(z.string()).optional()).describe(\n 'Options for closed_choice questions'\n ),\n priority: z\n .enum(['blocking', 'preferred', 'optional'])\n .optional()\n .default('preferred')\n .describe('How critical is this clarification? Default: preferred'),\n target_field: z.string().optional().describe('What field/config does this clarify?'),\n },\n async ({ context, question_type, question, choices, priority, target_field }) => {\n const result = handleClarify({\n context: context ?? undefined,\n question_type,\n question,\n choices: choices ?? undefined,\n priority: (priority ?? 'preferred') as ClarificationRequest['priority'],\n target_field: target_field ?? undefined,\n });\n\n return {\n content: [\n {\n type: 'text' as const,\n text:\n `𦦠Clarification needed${target_field ? ` for \"${target_field}\"` : ''}. ` +\n `Present the following to the user. ` +\n (result.adaptedQuestion\n ? 'Pass the adaptedQuestion to ask_user_question directly.'\n : 'Ask the user the prompt below.'),\n },\n {\n type: 'text' as const,\n text: JSON.stringify(result),\n },\n ],\n };\n }\n );\n\n // -----------------------------------------------------------------------\n // 2. stackwright_pro_detect_conflict\n // -----------------------------------------------------------------------\n server.tool(\n 'stackwright_pro_detect_conflict',\n \"Detect when a user's stated preference conflicts with their selected choices. \" +\n 'Uses keyword heuristics against known contradiction patterns (minimal vs vibrant, dark vs light, etc). ' +\n 'Returns conflict details and resolution options.',\n {\n stated_preference: z.string().describe('What the user said they wanted'),\n selected_values: jsonCoerce(z.record(z.string(), z.string())).describe(\n 'What the user actually selected (field ā value)'\n ),\n },\n async ({ stated_preference, selected_values }) => {\n const result = handleDetectConflict({ stated_preference, selected_values });\n\n if (result.conflict) {\n return {\n content: [\n {\n type: 'text' as const,\n text:\n `ā ļø CONFLICT DETECTED\\n\\n` +\n `User stated: \"${stated_preference}\"\\n` +\n `But selected: ${JSON.stringify(selected_values)}\\n\\n` +\n `${result.description}\\n\\n` +\n `Resolution options:\\n${result.resolution_options?.map((o) => ` ⢠${o}`).join('\\n')}\\n\\n` +\n `š” Consider asking the user to reconcile this conflict.`,\n },\n {\n type: 'text' as const,\n text: JSON.stringify(result),\n },\n ],\n };\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: 'ā
No conflict detected between stated preference and selections.',\n },\n {\n type: 'text' as const,\n text: JSON.stringify(result),\n },\n ],\n };\n }\n );\n}\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { readFileSync, writeFileSync, existsSync, realpathSync, lstatSync } from 'fs';\nimport { execSync } from 'child_process';\nimport path from 'path';\nimport { jsonCoerce, boolCoerce } from '../coerce.js';\n\n/**\n * stackwright_pro_setup_packages MCP tool\n *\n * Ensures pro packages are present in a project's package.json.\n * Used by the Pro Foreman Otter to bootstrap dependencies before\n * specialist otters run ā enabling the otter raft's IoC dependency\n * declaration pattern.\n *\n * Merge semantics: NEVER overwrites an existing version pin.\n * If a package is already declared at any version, it is skipped.\n * This preserves intentional version pinning by developers.\n */\n\ninterface PackageJson {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n scripts?: Record<string, string>;\n [key: string]: unknown;\n}\n\ninterface SetupPackagesResult {\n success: boolean;\n added: string[];\n skipped: string[];\n scriptsAdded: string[];\n installed: boolean;\n packageJsonPath: string;\n error?: string;\n installError?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Baseline dependencies moved from foreman prompt into version-controlled code\n// ---------------------------------------------------------------------------\n\nconst BASELINE_DEPS: Record<string, string> = {\n '@stackwright-pro/mcp': 'latest',\n '@stackwright-pro/otters': 'latest',\n '@stackwright-pro/openapi': 'latest',\n '@stackwright-pro/auth': 'latest',\n '@stackwright-pro/auth-nextjs': 'latest',\n zod: '^3.23.0',\n};\n\nconst BASELINE_DEV_DEPS: Record<string, string> = {\n '@stoplight/prism-cli': '^5.14.2',\n};\n\nexport function registerPackageTools(server: McpServer): void {\n server.tool(\n 'stackwright_pro_setup_packages',\n \"Ensures pro packages are present in a project's package.json. \" +\n 'Safe to call multiple times ā never overwrites existing version pins. ' +\n 'Use this to bootstrap dependencies before specialist otters run. ' +\n 'Pass includeBaseline: true to automatically include all required @stackwright-pro/* baseline dependencies. ' +\n 'Safe to call on existing projects ā never overwrites pinned versions.',\n {\n // FIX 3 (B-new-1): Zod v4 requires two-arg z.record(keySchema, valueSchema)\n packages: jsonCoerce(z.record(z.string(), z.string()).optional().default({})).describe(\n 'Dependencies to add. Record<packageName, version>. e.g. { \"@stackwright-pro/auth\": \"latest\" }. Omit or pass {} when using includeBaseline: true.'\n ),\n devPackages: jsonCoerce(z.record(z.string(), z.string()).optional()).describe(\n 'devDependencies to add. Same format as packages.'\n ),\n scripts: jsonCoerce(z.record(z.string(), z.string()).optional()).describe(\n 'npm scripts to add. Only adds if key does not already exist.'\n ),\n targetDir: z\n .string()\n .optional()\n .describe(\n 'Project directory containing package.json. Defaults to process.cwd(). Must be an absolute path within the current working directory.'\n ),\n runInstall: boolCoerce(z.boolean().optional().default(true)).describe(\n 'Run pnpm install after writing package.json. Defaults to true. Pass boolean true/false.'\n ),\n includeBaseline: boolCoerce(z.boolean().optional().default(false)).describe(\n 'When true, automatically merges BASELINE_DEPS and BASELINE_DEV_DEPS before applying packages/devPackages args. ' +\n 'Safe to call on existing projects ā never overwrites pinned versions. Pass boolean true/false.'\n ),\n },\n async ({ packages, devPackages, scripts, targetDir, runInstall, includeBaseline }) => {\n // Merge baseline deps when requested ā existing \"never overwrite\" semantics\n // in setupPackages mean this is safe to call on any project.\n const mergedPackages: Record<string, string> = includeBaseline\n ? { ...BASELINE_DEPS, ...packages }\n : { ...packages };\n\n const mergedDevPackages: Record<string, string> | undefined = includeBaseline\n ? { ...BASELINE_DEV_DEPS, ...(devPackages ?? {}) }\n : devPackages;\n\n // exactOptionalPropertyTypes: true means we cannot pass `undefined` explicitly\n // for optional fields ā conditionally spread them instead.\n const result = setupPackages({\n packages: mergedPackages,\n runInstall,\n ...(mergedDevPackages !== undefined ? { devPackages: mergedDevPackages } : {}),\n ...(scripts !== undefined ? { scripts } : {}),\n ...(targetDir !== undefined ? { targetDir } : {}),\n });\n\n const statusLine = result.success\n ? `ā
package.json updated: ${result.packageJsonPath}`\n : `ā Failed: ${result.error}`;\n\n const lines = [\n statusLine,\n '',\n result.added.length > 0\n ? `Added (${result.added.length}): ${result.added.join(', ')}`\n : 'Added: none',\n result.skipped.length > 0\n ? `Skipped/already present (${result.skipped.length}): ${result.skipped.join(', ')}`\n : 'Skipped: none',\n result.scriptsAdded.length > 0\n ? `Scripts added (${result.scriptsAdded.length}): ${result.scriptsAdded.join(', ')}`\n : 'Scripts added: none',\n `pnpm install: ${result.installed ? 'ran successfully' : result.success && runInstall ? 'failed (non-fatal)' : 'skipped'}`,\n ];\n\n return {\n content: [\n {\n type: 'text' as const,\n text: lines.join('\\n'),\n },\n {\n type: 'text' as const,\n text: JSON.stringify(result),\n },\n ],\n };\n }\n );\n}\n\n/**\n * Core implementation ā extracted so it can be tested directly without\n * going through the MCP server machinery. Keeping I/O at the edges.\n */\nexport function setupPackages(opts: {\n packages: Record<string, string>;\n devPackages?: Record<string, string>;\n scripts?: Record<string, string>;\n targetDir?: string;\n runInstall: boolean;\n}): SetupPackagesResult {\n const emptyResult: Omit<SetupPackagesResult, 'success' | 'error'> = {\n added: [],\n skipped: [],\n scriptsAdded: [],\n installed: false,\n packageJsonPath: '',\n };\n\n try {\n // -------------------------------------------------------------------------\n // Security: path traversal guard\n // -------------------------------------------------------------------------\n const cwd = process.cwd();\n const resolvedTarget = opts.targetDir ? path.resolve(opts.targetDir) : cwd;\n\n // Ensure resolved path stays within cwd ā no sneaky ../../etc tricks\n const cwdWithSep = cwd.endsWith(path.sep) ? cwd : cwd + path.sep;\n if (resolvedTarget !== cwd && !resolvedTarget.startsWith(cwdWithSep)) {\n return {\n success: false,\n added: [],\n skipped: [],\n scriptsAdded: [],\n installed: false,\n packageJsonPath: '',\n // FIX 5 (M-4): do not leak absolute paths in error messages\n error: `Path traversal rejected: target directory is outside the allowed working directory`,\n };\n }\n\n // -------------------------------------------------------------------------\n // Find package.json (existence check before symlink resolution)\n // -------------------------------------------------------------------------\n const preResolvePackageJsonPath = path.join(resolvedTarget, 'package.json');\n\n if (!existsSync(preResolvePackageJsonPath)) {\n return {\n success: false,\n ...emptyResult,\n error: `No package.json found in ${resolvedTarget}`,\n };\n }\n\n // -------------------------------------------------------------------------\n // Security: directory-level symlink bypass guard (B2)\n // -------------------------------------------------------------------------\n let realTarget: string;\n try {\n realTarget = realpathSync(resolvedTarget);\n } catch {\n return {\n success: false,\n added: [],\n skipped: [],\n scriptsAdded: [],\n installed: false,\n packageJsonPath: '',\n error: `Could not resolve real path of target directory`,\n };\n }\n\n const realCwd = realpathSync(cwd);\n const realCwdWithSep = realCwd.endsWith(path.sep) ? realCwd : realCwd + path.sep;\n if (realTarget !== realCwd && !realTarget.startsWith(realCwdWithSep)) {\n return {\n success: false,\n added: [],\n skipped: [],\n scriptsAdded: [],\n installed: false,\n packageJsonPath: '',\n // FIX 5 (M-4): do not leak absolute paths in error messages\n error: `Path traversal rejected: target directory resolved to a location outside the allowed working directory`,\n };\n }\n\n // -------------------------------------------------------------------------\n // Security: file-level symlink guard at package.json (C-1 / FIX 1)\n // -------------------------------------------------------------------------\n // Reconstruct package.json path from the symlink-resolved target directory.\n // This prevents readFileSync / writeFileSync from following a file-level\n // symlink planted at <targetDir>/package.json.\n const realPackageJsonPath = path.join(realTarget, 'package.json');\n\n const pkgStat = lstatSync(realPackageJsonPath);\n if (pkgStat.isSymbolicLink()) {\n return {\n ...emptyResult,\n success: false,\n error: `package.json is a symlink ā refusing to read or write`,\n };\n }\n\n // -------------------------------------------------------------------------\n // Security: package name validation (C-2C / L-1)\n // -------------------------------------------------------------------------\n // npm package name spec: optional @scope/, then lowercase alphanumeric + hyphens/dots/underscores\n const VALID_PKG_NAME_RE = /^(@[a-z0-9][a-z0-9\\-._~]*\\/)?[a-z0-9][a-z0-9\\-._~]*$/;\n const allPkgNames = [\n ...Object.keys(opts.packages ?? {}),\n ...Object.keys(opts.devPackages ?? {}),\n ];\n for (const pkg of allPkgNames) {\n if (!VALID_PKG_NAME_RE.test(pkg)) {\n return {\n ...emptyResult,\n success: false,\n error: `Invalid package name: '${pkg}' ā must match npm package name specification`,\n };\n }\n }\n\n // -------------------------------------------------------------------------\n // Security: version string allowlist (C-2B / FIX 2B)\n // -------------------------------------------------------------------------\n // Allows: semver ranges (^1.0.0, ~2.1, >=3, 1.x, *), workspace:*, latest/next/beta/alpha/canary/rc\n // Blocks: git+https://, file:, npm:evil@, http://, ssh://, etc.\n const SAFE_VERSION_RE =\n /^(workspace:[*^~]?|\\*|latest|next|beta|alpha|canary|rc|[~^><=*|, ]*[\\d.x*][\\d.x*\\-+a-zA-Z.~^><=*|, ]*)$/;\n const allVersionEntries = [\n ...Object.entries(opts.packages ?? {}),\n ...Object.entries(opts.devPackages ?? {}),\n ];\n for (const [pkg, version] of allVersionEntries) {\n if (!SAFE_VERSION_RE.test(version.trim())) {\n return {\n ...emptyResult,\n success: false,\n error: `Unsafe version specifier for '${pkg}': '${version}' ā only semver ranges, workspace:*, and dist-tags (latest/next/beta) are permitted`,\n };\n }\n }\n\n // -------------------------------------------------------------------------\n // Security: lifecycle script key blocklist (C-2A / FIX 2A)\n // -------------------------------------------------------------------------\n const BLOCKED_LIFECYCLE_KEYS = new Set([\n 'preinstall',\n 'install',\n 'postinstall',\n 'prepare',\n 'prepublish',\n 'prepublishOnly',\n 'prepack',\n 'postpack',\n 'dependencies', // pnpm hook key\n ]);\n if (opts.scripts) {\n for (const key of Object.keys(opts.scripts)) {\n if (BLOCKED_LIFECYCLE_KEYS.has(key)) {\n return {\n ...emptyResult,\n success: false,\n error: `Blocked lifecycle script key: '${key}' ā writing npm lifecycle hooks is not permitted`,\n };\n }\n }\n }\n\n // -------------------------------------------------------------------------\n // Read & parse\n // -------------------------------------------------------------------------\n const raw = readFileSync(realPackageJsonPath, 'utf8');\n\n // W2: Validate package.json structure with Zod before touching anything\n const PackageJsonSchema = z\n .object({\n // Zod v4: z.record(keySchema, valueSchema) ā two-arg form required\n dependencies: z.record(z.string(), z.string()).optional(),\n devDependencies: z.record(z.string(), z.string()).optional(),\n scripts: z.record(z.string(), z.string()).optional(),\n })\n .passthrough();\n\n const schemaResult = PackageJsonSchema.safeParse(JSON.parse(raw));\n if (!schemaResult.success) {\n return {\n ...emptyResult,\n success: false,\n error: `Invalid package.json structure: ${schemaResult.error.message}`,\n };\n }\n // FIX 4 (B-new-2): The schema has already validated the shape ā the cast is earned.\n // passthrough() + noUncheckedIndexedAccess would otherwise broaden field types to unknown.\n const parsed = schemaResult.data as PackageJson;\n\n // -------------------------------------------------------------------------\n // Merge dependencies ā NEVER overwrite existing version pins\n // -------------------------------------------------------------------------\n const added: string[] = [];\n const skipped: string[] = [];\n const scriptsAdded: string[] = [];\n\n // Live Set grows as packages are written ā prevents same pkg landing in both buckets (B4).\n // Uses `in` semantics (not falsy) so empty-string versions are treated as existing (B3).\n const claimedPkgs = new Set<string>([\n ...Object.keys(parsed.dependencies ?? {}),\n ...Object.keys(parsed.devDependencies ?? {}),\n ]);\n\n // Regular dependencies\n parsed.dependencies = parsed.dependencies ?? {};\n for (const [pkg, version] of Object.entries(opts.packages)) {\n if (claimedPkgs.has(pkg)) {\n skipped.push(pkg);\n } else {\n parsed.dependencies[pkg] = version;\n claimedPkgs.add(pkg);\n added.push(pkg);\n }\n }\n\n // Dev dependencies\n if (opts.devPackages && Object.keys(opts.devPackages).length > 0) {\n parsed.devDependencies = parsed.devDependencies ?? {};\n for (const [pkg, version] of Object.entries(opts.devPackages)) {\n if (claimedPkgs.has(pkg)) {\n skipped.push(pkg);\n } else {\n parsed.devDependencies[pkg] = version;\n claimedPkgs.add(pkg);\n added.push(pkg);\n }\n }\n }\n\n // Scripts ā same never-overwrite semantics\n if (opts.scripts && Object.keys(opts.scripts).length > 0) {\n parsed.scripts = parsed.scripts ?? {};\n for (const [key, value] of Object.entries(opts.scripts)) {\n if (parsed.scripts[key] === undefined) {\n parsed.scripts[key] = value;\n scriptsAdded.push(key);\n }\n }\n }\n\n // -------------------------------------------------------------------------\n // Write back ā use realPackageJsonPath (symlink-resolved) for all I/O\n // -------------------------------------------------------------------------\n writeFileSync(realPackageJsonPath, JSON.stringify(parsed, null, 2) + '\\n');\n\n // -------------------------------------------------------------------------\n // Run pnpm install (optional, non-fatal on failure)\n // -------------------------------------------------------------------------\n let installed = false;\n let installError: string | undefined;\n\n if (opts.runInstall) {\n try {\n execSync('pnpm install', { cwd: realTarget, stdio: 'pipe', timeout: 60_000 });\n installed = true;\n } catch (err) {\n // Don't blow up the whole tool ā install failure is recoverable.\n // The caller can re-run or handle manually.\n installed = false;\n const spawnErr = err as { stderr?: Buffer; message?: string };\n installError =\n spawnErr.stderr?.toString().trim() ||\n (err instanceof Error ? err.message : 'unknown error');\n }\n }\n\n return {\n success: true,\n added,\n skipped,\n scriptsAdded,\n installed,\n packageJsonPath: realPackageJsonPath,\n ...(installError !== undefined ? { installError } : {}),\n };\n } catch (err) {\n return {\n ...emptyResult,\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n}\n","/**\n * Question Presentation MCP Tool\n *\n * Wraps ask_user_question with safe question adaptation so the foreman otter\n * never has to construct the nested questions array itself ā which causes\n * consistent serialization failures where the LLM passes the array as a\n * JSON string instead of a native array.\n *\n * The tool accepts manifest-format questions (what specialist otters produce),\n * adapts them via the shared question-adapter, and calls ask_user_question\n * with a guaranteed-correct native array.\n *\n * When `questions` is omitted, the tool reads from\n * .stackwright/question-manifest.json automatically by phase name.\n */\n\nimport { readFile, writeFile } from 'node:fs/promises';\nimport { existsSync, lstatSync, mkdirSync, renameSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { adaptQuestions, type QuestionManifestQuestion } from '../question-adapter.js';\nimport { jsonCoerce } from '../coerce.js';\n\nconst ManifestQuestionSchema = z.object({\n id: z.string(),\n question: z.string(),\n type: z.enum(['text', 'select', 'multi-select', 'confirm']),\n required: z.boolean().optional(),\n options: z\n .array(\n z.object({\n label: z.string(),\n value: z.string(),\n })\n )\n .optional(),\n default: z.union([z.string(), z.boolean(), z.array(z.string())]).optional(),\n help: z.string().optional(),\n dependsOn: z\n .object({\n questionId: z.string(),\n value: z.union([z.string(), z.array(z.string())]),\n })\n .optional(),\n});\n\nexport function registerQuestionTools(server: McpServer): void {\n server.tool(\n 'stackwright_pro_present_phase_questions',\n 'Adapt manifest-format questions from a specialist otter and present them to the user via ask_user_question. ' +\n 'Pass only the phase name ā this tool reads questions from .stackwright/question-manifest.json automatically. ' +\n 'The questions parameter is optional and only needed if the manifest has not been written yet. ' +\n 'Use this instead of calling ask_user_question directly ā it handles label truncation (50-char limit), ' +\n 'header generation, confirm/text defaults, and correct array formatting automatically. ' +\n 'IMPORTANT: This is the ONLY approved way to prepare questions before calling ask_user_question. ' +\n 'Never call ask_user_question with raw manifest questions. ' +\n 'Never retry ask_user_question validation errors by calling it directly ā always re-call this tool.',\n {\n phase: z.string().describe('Phase name for display context, e.g. \"designer\", \"api\", \"auth\"'),\n questions: jsonCoerce(z.array(ManifestQuestionSchema).optional()).describe(\n 'Questions in Question Manifest format. If omitted, questions are read ' +\n 'from .stackwright/question-manifest.json using the phase name.'\n ),\n answers: jsonCoerce(\n z.record(z.string(), z.union([z.string(), z.array(z.string()), z.boolean()])).optional()\n ).describe('Previously collected answers used to resolve dependsOn conditions'),\n },\n async ({ phase, questions, answers }) => {\n // Resolution order:\n // 1. Use questions param if provided (explicit)\n // 2. Try per-phase file: .stackwright/questions/{phase}.json (new sink model)\n // 3. Fall back to monolithic manifest: .stackwright/question-manifest.json (legacy)\n let resolvedQuestions: QuestionManifestQuestion[];\n\n // Validate phase name ā prevent path traversal (CWE-22)\n const SAFE_PHASE = /^[a-z][a-z0-9-]{0,30}$/;\n if (!SAFE_PHASE.test(phase)) {\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify({\n error: `Invalid phase name: \"${phase.slice(0, 50)}\". Must be lowercase alphanumeric with hyphens, max 31 chars.`,\n }),\n },\n ],\n isError: true,\n };\n }\n\n if (questions && questions.length > 0) {\n resolvedQuestions = questions as QuestionManifestQuestion[];\n } else {\n // Try per-phase question file first (Sinks Not Pipes model)\n const phaseQuestionPath = join(process.cwd(), '.stackwright', 'questions', `${phase}.json`);\n try {\n const raw = await readFile(phaseQuestionPath, 'utf-8');\n const phaseData = JSON.parse(raw) as { questions: QuestionManifestQuestion[] };\n resolvedQuestions = (phaseData.questions ?? []) as QuestionManifestQuestion[];\n } catch {\n // Fall back to monolithic manifest (legacy path)\n try {\n const manifestPath = join(process.cwd(), '.stackwright', 'question-manifest.json');\n const raw = await readFile(manifestPath, 'utf-8');\n const manifest = JSON.parse(raw) as {\n phases: { phase: string; questions: QuestionManifestQuestion[] }[];\n };\n const phaseData = manifest.phases.find((p) => p.phase === phase);\n resolvedQuestions = (phaseData?.questions ?? []) as QuestionManifestQuestion[];\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify({\n error: `Could not read question manifest for phase \"${phase}\": ${msg}`,\n hint: 'Write the manifest first, or pass questions directly to this tool.',\n }),\n },\n ],\n isError: true,\n };\n }\n }\n }\n\n // Adapt from manifest format to ask_user_question format\n const adapted = adaptQuestions(resolvedQuestions, answers ?? {});\n\n // Post-adaptation guard: validate all option labels are ā¤50 chars.\n // adaptQuestions() truncates labels to 50 chars; this guard catches any\n // slip-through and surfaces a clear \"50 characters\" message instead of\n // the misleading \"50 items\" message that ask_user_question would produce.\n const labelSchema = z.string().max(50, 'Value should have at most 50 characters');\n for (const q of adapted) {\n for (const opt of q.options) {\n const check = labelSchema.safeParse(opt.label);\n if (!check.success) {\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify({\n error: `Option label for phase \"${phase}\" exceeds 50 characters: ${check.error.issues[0]?.message ?? 'label too long'}. Truncate option labels to ā¤50 characters before calling this tool.`,\n }),\n },\n ],\n isError: true,\n };\n }\n }\n }\n\n if (adapted.length === 0) {\n return {\n content: [\n {\n type: 'text' as const,\n text:\n `Phase \"${phase}\" has no questions to present. ` +\n `Do NOT call ask_user_question. ` +\n `Call stackwright_pro_save_phase_answers({ phase: \"${phase}\", rawAnswers: [] }) directly, then proceed to the execution step for this phase.`,\n },\n {\n type: 'text' as const,\n // Empty array ā second block always present so the foreman's two-block contract holds\n text: JSON.stringify([]),\n },\n ],\n isError: false,\n };\n }\n\n // Return the adapted questions for the foreman to pass to ask_user_question.\n // Two-block format: first block is the instruction, second block is the raw\n // JSON array. Splitting them removes the temptation for the LLM to\n // re-serialise the array when it reads the instruction text.\n return {\n content: [\n {\n type: 'text' as const,\n text:\n `Adapted ${adapted.length} questions for phase \"${phase}\". ` +\n `Pass the JSON array below DIRECTLY to ask_user_question as the \"questions\" parameter. ` +\n `Do NOT JSON.stringify() it. Do NOT wrap it in an object. Pass the parsed array value as-is.`,\n },\n {\n type: 'text' as const,\n text: JSON.stringify(adapted),\n },\n ],\n isError: false,\n };\n }\n );\n\n // ---------------------------------------------------------------------------\n // stackwright_pro_get_next_question\n // ---------------------------------------------------------------------------\n server.tool(\n 'stackwright_pro_get_next_question',\n 'Returns the next unanswered question for a phase as a plain JSON object ā one question at a time. ' +\n 'Returns { done: true } when all questions are answered or the phase has no questions. ' +\n 'Call this in a loop: present the question in plain chat, get user reply, call record_answer, repeat.',\n { phase: z.string().describe('Phase name e.g. \"designer\", \"api\", \"auth\"') },\n async ({ phase }) => {\n const SAFE_PHASE = /^[a-z][a-z0-9-]{0,30}$/;\n if (!SAFE_PHASE.test(phase)) {\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify({ error: `Invalid phase name: \"${phase.slice(0, 50)}\"` }),\n },\n ],\n isError: true,\n };\n }\n\n const cwd = process.cwd();\n\n // Read questions file\n const questionsPath = join(cwd, '.stackwright', 'questions', `${phase}.json`);\n let questions: Array<{\n id: string;\n question: string;\n type: string;\n options?: Array<{ label: string; value: string }>;\n help?: string;\n }> = [];\n try {\n const raw = await readFile(questionsPath, 'utf-8');\n const parsed = JSON.parse(raw) as { questions?: typeof questions };\n questions = parsed.questions ?? [];\n } catch {\n // File missing or malformed ā phase has no questions\n return { content: [{ type: 'text' as const, text: JSON.stringify({ done: true }) }] };\n }\n\n if (questions.length === 0) {\n return { content: [{ type: 'text' as const, text: JSON.stringify({ done: true }) }] };\n }\n\n // Read existing answers to build the answered-ID set\n const answersPath = join(cwd, '.stackwright', 'answers', `${phase}.json`);\n let answeredIds = new Set<string>();\n try {\n const raw = await readFile(answersPath, 'utf-8');\n const parsed = JSON.parse(raw) as { answers?: Record<string, unknown> };\n answeredIds = new Set(Object.keys(parsed.answers ?? {}));\n } catch {\n // File missing ā nothing answered yet\n }\n\n // First unanswered question\n const next = questions.find((q) => !answeredIds.has(q.id));\n if (!next) {\n return { content: [{ type: 'text' as const, text: JSON.stringify({ done: true }) }] };\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify({\n done: false,\n questionId: next.id,\n question: next.question,\n type: next.type,\n options: next.options ?? null,\n help: next.help ?? null,\n index: questions.indexOf(next) + 1,\n total: questions.length,\n }),\n },\n ],\n };\n }\n );\n\n // ---------------------------------------------------------------------------\n // stackwright_pro_record_answer\n // ---------------------------------------------------------------------------\n server.tool(\n 'stackwright_pro_record_answer',\n 'Records a single answer to a phase question. Appends to .stackwright/answers/{phase}.json incrementally. ' +\n 'Idempotent ā calling twice for the same questionId overwrites. ' +\n 'Call after receiving each user reply in the conversational question loop.',\n {\n phase: z.string().describe('Phase name e.g. \"designer\"'),\n questionId: z.string().describe('The question ID from get_next_question, e.g. \"designer-1\"'),\n answer: z.string().describe(\"The user's free-text answer\"),\n },\n async ({ phase, questionId, answer }) => {\n const SAFE_PHASE = /^[a-z][a-z0-9-]{0,30}$/;\n if (!SAFE_PHASE.test(phase)) {\n return {\n content: [\n { type: 'text' as const, text: JSON.stringify({ error: 'Invalid phase name' }) },\n ],\n isError: true,\n };\n }\n if (!/^[a-z0-9][a-z0-9-]{0,63}$/i.test(questionId)) {\n return {\n content: [\n { type: 'text' as const, text: JSON.stringify({ error: 'Invalid questionId' }) },\n ],\n isError: true,\n };\n }\n const safeAnswer = answer.slice(0, 2000);\n\n const cwd = process.cwd();\n const answersDir = join(cwd, '.stackwright', 'answers');\n const answersPath = join(answersDir, `${phase}.json`);\n\n // Symlink guard on directory\n if (existsSync(answersDir) && lstatSync(answersDir).isSymbolicLink()) {\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify({ error: 'answers dir is a symlink ā refusing to write' }),\n },\n ],\n isError: true,\n };\n }\n mkdirSync(answersDir, { recursive: true });\n\n // Read existing or start fresh\n let existing: {\n version: string;\n phase: string;\n answers: Record<string, string>;\n updatedAt?: string;\n } = {\n version: '1.0',\n phase,\n answers: {},\n };\n try {\n if (existsSync(answersPath)) {\n if (lstatSync(answersPath).isSymbolicLink()) {\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify({ error: 'answers file is a symlink ā refusing to write' }),\n },\n ],\n isError: true,\n };\n }\n const raw = await readFile(answersPath, 'utf-8');\n existing = JSON.parse(raw) as typeof existing;\n }\n } catch {\n // Malformed ā start fresh\n }\n\n // Upsert\n existing.answers[questionId] = safeAnswer;\n existing.updatedAt = new Date().toISOString();\n\n // Atomic write via tmp+rename\n const tmp = `${answersPath}.tmp`;\n await writeFile(tmp, JSON.stringify(existing, null, 2), 'utf-8');\n renameSync(tmp, answersPath);\n\n return {\n content: [\n { type: 'text' as const, text: JSON.stringify({ recorded: true, phase, questionId }) },\n ],\n };\n }\n );\n}\n","/**\n * Question Adapter - Converts between Question Manifest format and ask_user_question format\n *\n * The ask_user_question MCP tool requires:\n * - question: string (full text)\n * - header: string (max 12 chars, short label)\n * - multi_select: boolean\n * - options: {label, description}[] (REQUIRED, min 2)\n *\n * Our Question Manifest format has:\n * - id: string (e.g., \"api-1\")\n * - question: string\n * - type: 'text' | 'select' | 'multi-select' | 'confirm'\n * - options?: {label, value}[] (optional for text/confirm)\n * - required?: boolean\n * - default?: string | boolean | string[]\n * - dependsOn?: {questionId, value}\n */\n\nexport interface QuestionManifestQuestion {\n id: string;\n question: string;\n type: 'text' | 'select' | 'multi-select' | 'confirm';\n required?: boolean;\n options?: { label: string; value: string }[];\n default?: string | boolean | string[];\n help?: string;\n dependsOn?: {\n questionId: string;\n value: string | string[];\n };\n}\n\nexport interface AskUserQuestionOption {\n label: string;\n description?: string;\n}\n\nexport interface AskUserQuestion {\n question: string;\n header: string;\n multi_select: boolean;\n options: AskUserQuestionOption[];\n}\n\n/**\n * Truncate string to max length, adding ellipsis if needed\n */\nfunction truncate(str: string, maxLength: number): string {\n if (str.length <= maxLength) return str;\n return str.substring(0, maxLength - 1) + 'ā¦';\n}\n\n/**\n * Generate a valid header from a question ID\n * Headers must be max 12 chars, alphanumeric with hyphens\n */\nfunction generateHeader(id: string): string {\n // Remove numbers and prefix, keep meaningful part\n // e.g., \"api-1\" -> \"API-1\", \"auth-3\" -> \"AUTH-3\"\n const parts = id.split('-');\n if (parts.length >= 2) {\n const prefix = parts[0].toUpperCase().substring(0, 4);\n const num = parts[1];\n return truncate(`${prefix}-${num}`, 12);\n }\n return truncate(\n id\n .toUpperCase()\n .replace(/[^A-Z0-9]/g, '')\n .substring(0, 12),\n 12\n );\n}\n\n/**\n * Generate default options for question types that don't have options\n */\nfunction generateDefaultOptions(type: string): AskUserQuestionOption[] {\n switch (type) {\n case 'confirm':\n return [\n { label: 'Yes', description: 'Enable or confirm this option' },\n { label: 'No', description: 'Disable or decline this option' },\n ];\n case 'text':\n return [\n { label: 'Specify', description: 'I will provide a specific value' },\n { label: 'Skip', description: 'Use default or skip this question' },\n ];\n default:\n return [\n { label: 'Option 1', description: 'First option' },\n { label: 'Option 2', description: 'Second option' },\n ];\n }\n}\n\n/**\n * Convert a single QuestionManifest question to ask_user_question format\n */\nexport function adaptQuestion(q: QuestionManifestQuestion): AskUserQuestion {\n // Generate header from ID\n const header = generateHeader(q.id);\n\n // Determine multi_select\n const multiSelect = q.type === 'multi-select';\n\n // Handle options - use provided or generate defaults\n let options: AskUserQuestionOption[];\n\n if (q.options && q.options.length >= 2) {\n // Use provided options, adapt format\n options = q.options.map((opt) => ({\n label: truncate(opt.label, 50),\n description: opt.value !== opt.label ? opt.value : undefined,\n }));\n } else if (q.options && q.options.length === 1) {\n // Single option - add a default\n options = [\n ...q.options.map((opt) => ({ label: truncate(opt.label, 50), description: opt.value })),\n { label: 'Other', description: 'Specify a different value' },\n ];\n } else {\n // No options - generate defaults based on type\n options = generateDefaultOptions(q.type);\n }\n\n // Ensure minimum 2 options (MCP tool requirement)\n if (options.length < 2) {\n options.push({ label: 'Other', description: 'Alternative option' });\n }\n\n // Limit to 6 options (MCP tool max)\n options = options.slice(0, 6);\n\n return {\n question: q.question + (q.help ? `\\n\\n${q.help}` : ''),\n header,\n multi_select: multiSelect,\n options,\n };\n}\n\n/**\n * Adapt multiple questions, filtering by dependsOn\n *\n * @param questions - All questions from manifest\n * @param answers - Previously answered questions (for filtering conditionals)\n * @returns Questions adapted for ask_user_question, with conditionals resolved\n */\nexport function adaptQuestions(\n questions: QuestionManifestQuestion[],\n answers: Record<string, string | string[] | boolean> = {}\n): AskUserQuestion[] {\n const adapted: AskUserQuestion[] = [];\n\n for (const q of questions) {\n // Check dependsOn condition\n if (q.dependsOn) {\n const dependsAnswer = answers[q.dependsOn.questionId];\n if (dependsAnswer === undefined) {\n // Parent question not answered yet - skip this conditional question\n continue;\n }\n\n // Check if the answer matches the condition\n const expectedValues = Array.isArray(q.dependsOn.value)\n ? q.dependsOn.value\n : [q.dependsOn.value];\n\n const answerValue = Array.isArray(dependsAnswer) ? dependsAnswer[0] : dependsAnswer;\n\n if (!expectedValues.includes(answerValue as string)) {\n // Condition not met - skip this question\n continue;\n }\n }\n\n adapted.push(adaptQuestion(q));\n }\n\n return adapted;\n}\n\n/**\n * Parse JSON response from LLM (handles various formats)\n */\nexport function parseLLMQuestionsResponse(text: string): QuestionManifestQuestion[] {\n // Try to extract JSON from the response\n let jsonStr = text;\n\n // Remove markdown code blocks\n jsonStr = jsonStr.replace(/```(?:json|javascript)?\\s*/gi, '');\n jsonStr = jsonStr.replace(/```\\s*$/gm, '');\n\n // Find JSON object or array\n const firstBrace = jsonStr.indexOf('{');\n const firstBracket = jsonStr.indexOf('[');\n\n let start = -1;\n if (firstBrace !== -1 && firstBracket !== -1) {\n start = Math.min(firstBrace, firstBracket);\n } else if (firstBrace !== -1) {\n start = firstBrace;\n } else if (firstBracket !== -1) {\n start = firstBracket;\n }\n\n if (start === -1) {\n throw new Error('No JSON found in response');\n }\n\n jsonStr = jsonStr.substring(start);\n\n // Handle trailing text after JSON\n const lastBrace = jsonStr.lastIndexOf('}');\n const lastBracket = jsonStr.lastIndexOf(']');\n const end = Math.max(lastBrace, lastBracket);\n\n if (end === -1) {\n throw new Error('Invalid JSON structure');\n }\n\n jsonStr = jsonStr.substring(0, end + 1);\n\n // Fix common issues\n jsonStr = jsonStr.replace(/,(\\s*[}\\]])/g, '$1'); // Remove trailing commas\n jsonStr = jsonStr.replace(/'/g, '\"'); // Single quotes to double\n\n const parsed = JSON.parse(jsonStr);\n\n // Handle various JSON structures\n let questions: unknown[];\n\n if (Array.isArray(parsed)) {\n questions = parsed;\n } else if (parsed.questions && Array.isArray(parsed.questions)) {\n questions = parsed.questions;\n } else if (parsed.data && Array.isArray((parsed.data as Record<string, unknown>).questions)) {\n questions = (parsed.data as Record<string, unknown>).questions as unknown[];\n } else {\n throw new Error('No questions array found in response');\n }\n\n // Sanitize: strip __proto__, constructor, prototype keys recursively\n // to prevent prototype pollution attacks from malicious LLM output\n function sanitize(obj: Record<string, unknown>): Record<string, unknown> {\n const sanitized: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n if (key === '__proto__' || key === 'constructor' || key === 'prototype') {\n // Skip prototype pollution vectors ā they could affect downstream parsing\n continue;\n }\n const val = obj[key];\n if (val && typeof val === 'object' && !Array.isArray(val)) {\n sanitized[key] = sanitize(val as Record<string, unknown>);\n } else if (Array.isArray(val)) {\n sanitized[key] = val.map((item) =>\n item && typeof item === 'object' && !Array.isArray(item)\n ? sanitize(item as Record<string, unknown>)\n : item\n );\n } else {\n sanitized[key] = val;\n }\n }\n return sanitized;\n }\n\n // Apply sanitization to each question object\n questions = questions.map((q) => {\n if (q && typeof q === 'object') {\n return sanitize(q as Record<string, unknown>);\n }\n return q;\n }) as QuestionManifestQuestion[];\n\n return questions;\n}\n\n/**\n * Convert ask_user_question answers back to manifest format\n */\nexport function answersToManifestFormat(\n answers: { question_header: string; selected_options: string[]; other_text?: string | null }[],\n questions: QuestionManifestQuestion[]\n): Record<string, string | string[] | boolean> {\n const result: Record<string, string | string[] | boolean> = {};\n\n for (const answer of answers) {\n // Find matching question by header\n const headerLower = answer.question_header.toLowerCase();\n const question = questions.find((q) => {\n const qHeader = generateHeader(q.id).toLowerCase();\n return qHeader === headerLower || q.id.toLowerCase().includes(headerLower);\n });\n\n if (!question) {\n // Try to match by header prefix\n const matched = questions.find((q) => {\n const qHeader = generateHeader(q.id).toLowerCase();\n return qHeader.startsWith(headerLower.split('-')[0]);\n });\n if (matched) {\n result[matched.id] = answer.selected_options[0] || '';\n }\n continue;\n }\n\n // Handle multi-select vs single select\n if (question.type === 'multi-select' || answer.selected_options.length > 1) {\n result[question.id] = answer.selected_options;\n } else if (question.type === 'confirm') {\n result[question.id] = answer.selected_options[0] === 'Yes';\n } else {\n // For text or single select, use first option or other_text\n if (answer.other_text) {\n result[question.id] = answer.other_text;\n } else if (answer.selected_options.length > 0) {\n // Map label back to value if possible\n const option = question.options?.find((o) => o.label === answer.selected_options[0]);\n result[question.id] = option?.value ?? answer.selected_options[0];\n }\n }\n }\n\n return result;\n}\n","/**\n * Orchestration MCP Tools\n *\n * Moves mechanical Type B logic out of the foreman otter's system prompt\n * into tested TypeScript. Reduces foreman prompt from ~2,750 words to ~600 words,\n * enabling reliable operation on 7B parameter models for airgapped deployments.\n *\n * These tools replace pseudocode that was previously embedded in the foreman\n * prompt as inline helper functions and procedural instructions.\n */\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { jsonCoerce } from '../coerce.js';\nimport { readFileSync, writeFileSync, existsSync, mkdirSync, lstatSync } from 'fs';\nimport { join } from 'path';\nimport {\n parseLLMQuestionsResponse,\n answersToManifestFormat,\n type QuestionManifestQuestion,\n} from '../question-adapter.js';\n\n// ---------------------------------------------------------------------------\n// Constants ā version-controlled, not buried in a 2,750-word prompt\n// ---------------------------------------------------------------------------\n\n/**\n * Maps otter name substrings ā canonical phase name.\n * Order matters: more-specific entries first.\n */\nconst OTTER_NAME_TO_PHASE: Array<[string, string]> = [\n ['designer', 'designer'],\n ['theme', 'theme'],\n ['api', 'api'],\n ['auth', 'auth'],\n ['dashboard', 'dashboard'],\n ['data', 'data'],\n ['page', 'pages'],\n ['workflow', 'workflow'],\n];\n\nconst PHASE_TO_OTTER: Record<string, string> = {\n designer: 'stackwright-pro-designer-otter',\n theme: 'stackwright-pro-theme-otter',\n api: 'stackwright-pro-api-otter',\n auth: 'stackwright-pro-auth-otter',\n pages: 'stackwright-pro-page-otter',\n dashboard: 'stackwright-pro-dashboard-otter',\n data: 'stackwright-pro-data-otter',\n workflow: 'stackwright-pro-workflow-otter',\n};\n\n// ---------------------------------------------------------------------------\n// Phase detection\n// ---------------------------------------------------------------------------\n\nfunction detectPhase(otterName: string): string {\n const lower = otterName.toLowerCase();\n for (const [keyword, phase] of OTTER_NAME_TO_PHASE) {\n if (lower.includes(keyword)) return phase;\n }\n // Fallback: strip well-known wrapper and return whatever's left\n return lower.replace(/^stackwright-pro-/, '').replace(/-otter$/, '');\n}\n\n// ---------------------------------------------------------------------------\n// Handler functions (exported for direct testing ā no MCP server needed)\n// ---------------------------------------------------------------------------\n\nexport interface ParseOtterResponseInput {\n otterName: string;\n responseText: string;\n}\n\nexport interface ParseOtterResponseResult {\n phase: string;\n otter: string;\n questions: QuestionManifestQuestion[];\n error?: true;\n parseError?: string;\n}\n\nexport function handleParseOtterResponse(input: ParseOtterResponseInput): {\n result: ParseOtterResponseResult;\n isError: boolean;\n} {\n const phase = detectPhase(input.otterName);\n try {\n const questions = parseLLMQuestionsResponse(input.responseText);\n return {\n result: { phase, otter: input.otterName, questions },\n isError: false,\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n result: {\n error: true,\n otterName: input.otterName,\n phase,\n questions: [],\n parseError: message,\n } as unknown as ParseOtterResponseResult,\n isError: true,\n };\n }\n}\n\n// ---------------------------------------------------------------------------\n\nexport interface PhaseEntry {\n phase: string;\n otter: string;\n questions: unknown[];\n requiredPackages?: {\n dependencies?: Record<string, string>;\n devPackages?: Record<string, string>;\n };\n}\n\nexport interface SaveManifestInput {\n phases: PhaseEntry[];\n _cwd?: string; // injectable for tests\n}\n\nexport function handleSaveManifest(input: SaveManifestInput): { text: string; isError: boolean } {\n const cwd = input._cwd ?? process.cwd();\n const dir = join(cwd, '.stackwright');\n const filePath = join(dir, 'question-manifest.json');\n try {\n mkdirSync(dir, { recursive: true });\n\n // Symlink guard ā refuse to write through a symlink\n if (existsSync(filePath)) {\n const stat = lstatSync(filePath);\n if (stat.isSymbolicLink()) {\n const message = `Refusing to write to symlink: ${filePath}`;\n return {\n text: JSON.stringify({ success: false, error: message }),\n isError: true,\n };\n }\n }\n\n const manifest = {\n version: '1.0',\n createdAt: new Date().toISOString(),\n phases: input.phases,\n };\n writeFileSync(filePath, JSON.stringify(manifest, null, 2) + '\\n');\n return {\n text: JSON.stringify({ success: true, path: filePath, phaseCount: input.phases.length }),\n isError: false,\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n text: JSON.stringify({ success: false, error: message }),\n isError: true,\n };\n }\n}\n\n// ---------------------------------------------------------------------------\n\nexport interface RawAnswer {\n question_header: string;\n selected_options: string[];\n other_text?: string | null;\n}\n\nexport interface SavePhaseAnswersInput {\n phase: string;\n rawAnswers: RawAnswer[];\n questions?: QuestionManifestQuestion[];\n _cwd?: string; // injectable for tests\n}\n\nexport function handleSavePhaseAnswers(input: SavePhaseAnswersInput): {\n text: string;\n isError: boolean;\n} {\n const cwd = input._cwd ?? process.cwd();\n const dir = join(cwd, '.stackwright', 'answers');\n const filePath = join(dir, `${input.phase}.json`);\n try {\n mkdirSync(dir, { recursive: true });\n\n let answers: Record<string, unknown>;\n if (input.questions && input.questions.length > 0) {\n answers = answersToManifestFormat(input.rawAnswers, input.questions);\n } else {\n // Fallback: no manifest questions provided ā best-effort key extraction\n answers = Object.fromEntries(\n input.rawAnswers.map((a) => [a.question_header, a.selected_options[0] ?? ''])\n );\n }\n\n const payload = {\n version: '1.0',\n phase: input.phase,\n completedAt: new Date().toISOString(),\n answers,\n };\n\n // Symlink guard ā refuse to write through a symlink\n if (existsSync(filePath)) {\n const stat = lstatSync(filePath);\n if (stat.isSymbolicLink()) {\n const message = `Refusing to write to symlink: ${filePath}`;\n return {\n text: JSON.stringify({ success: false, error: message }),\n isError: true,\n };\n }\n }\n\n writeFileSync(filePath, JSON.stringify(payload, null, 2) + '\\n');\n return {\n text: JSON.stringify({\n success: true,\n path: filePath,\n answersCount: Object.keys(answers).length,\n }),\n isError: false,\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n text: JSON.stringify({ success: false, error: message }),\n isError: true,\n };\n }\n}\n\n// ---------------------------------------------------------------------------\n\nexport interface ReadPhaseAnswersInput {\n phase: string;\n _cwd?: string; // injectable for tests\n}\n\nexport function handleReadPhaseAnswers(input: ReadPhaseAnswersInput): {\n text: string;\n isError: boolean;\n} {\n const cwd = input._cwd ?? process.cwd();\n const filePath = join(cwd, '.stackwright', 'answers', `${input.phase}.json`);\n if (!existsSync(filePath)) {\n return {\n text: JSON.stringify({ missing: true, phase: input.phase }),\n isError: false,\n };\n }\n try {\n const raw = readFileSync(filePath, 'utf8');\n const parsed = JSON.parse(raw);\n return { text: JSON.stringify(parsed), isError: false };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n text: JSON.stringify({ error: true, phase: input.phase, readError: message }),\n isError: true,\n };\n }\n}\n\n// ---------------------------------------------------------------------------\n\nexport interface GetOtterNameInput {\n phase: string;\n}\n\nexport function handleGetOtterName(input: GetOtterNameInput): { text: string; isError: boolean } {\n const normalised = input.phase.toLowerCase().trim();\n const otterName = PHASE_TO_OTTER[normalised];\n if (!otterName) {\n return {\n text: JSON.stringify({ error: true, message: `Unknown phase: ${input.phase}` }),\n isError: true,\n };\n }\n return {\n text: JSON.stringify({ phase: normalised, otterName }),\n isError: false,\n };\n}\n\n// ---------------------------------------------------------------------------\n\nexport interface SaveBuildContextInput {\n buildContext: string;\n _cwd?: string;\n}\n\nexport function handleSaveBuildContext(input: SaveBuildContextInput): {\n text: string;\n isError: boolean;\n} {\n const cwd = input._cwd ?? process.cwd();\n const dir = join(cwd, '.stackwright');\n const filePath = join(dir, 'build-context.json');\n try {\n mkdirSync(dir, { recursive: true });\n\n // Symlink guard\n if (existsSync(filePath)) {\n const stat = lstatSync(filePath);\n if (stat.isSymbolicLink()) {\n return {\n text: JSON.stringify({\n success: false,\n error: `Refusing to write to symlink: ${filePath}`,\n }),\n isError: true,\n };\n }\n }\n\n const payload = {\n version: '1.0',\n savedAt: new Date().toISOString(),\n buildContext: input.buildContext,\n };\n writeFileSync(filePath, JSON.stringify(payload, null, 2) + '\\n');\n return {\n text: JSON.stringify({ success: true, path: filePath }),\n isError: false,\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n text: JSON.stringify({ success: false, error: message }),\n isError: true,\n };\n }\n}\n\n// ---------------------------------------------------------------------------\n// MCP tool registration\n// ---------------------------------------------------------------------------\n\nexport function registerOrchestrationTools(server: McpServer): void {\n // -------------------------------------------------------------------------\n // 0. stackwright_pro_save_build_context\n // -------------------------------------------------------------------------\n server.tool(\n 'stackwright_pro_save_build_context',\n \"Save the user's initial build description to .stackwright/build-context.json. \" +\n 'Call this once at startup after the user answers the opening \"what are you building\" question. ' +\n 'The saved context is automatically prepended to specialist prompts by stackwright_pro_build_specialist_prompt.',\n {\n buildContext: z.string().describe('Free-text description of what the user wants to build'),\n },\n async ({ buildContext }) => {\n const { text, isError } = handleSaveBuildContext({ buildContext });\n return {\n content: [{ type: 'text' as const, text }],\n isError,\n };\n }\n );\n\n // -------------------------------------------------------------------------\n // 1. stackwright_pro_parse_otter_response\n // -------------------------------------------------------------------------\n server.tool(\n 'stackwright_pro_parse_otter_response',\n \"Parse and validate a specialist otter's QUESTION_COLLECTION_MODE JSON response. \" +\n 'Handles JSON extraction from LLM responses (strips markdown, fixes single quotes, trailing commas). ' +\n 'Detects the phase from the otter name. ' +\n 'Use this immediately after invoke_agent() to get a validated manifest phase object.',\n {\n otterName: z.string().describe('The agent name, e.g. \"stackwright-pro-api-otter\"'),\n responseText: z\n .string()\n .describe(\"Raw text response from the otter's QUESTION_COLLECTION_MODE invocation\"),\n },\n async ({ otterName, responseText }) => {\n const { result, isError } = handleParseOtterResponse({ otterName, responseText });\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(result) }],\n isError,\n };\n }\n );\n\n // -------------------------------------------------------------------------\n // 2. stackwright_pro_save_manifest\n // -------------------------------------------------------------------------\n server.tool(\n 'stackwright_pro_save_manifest',\n 'Write the question manifest to .stackwright/question-manifest.json. ' +\n 'Call this after collecting and parsing questions from all otters via stackwright_pro_parse_otter_response.',\n {\n phases: jsonCoerce(\n z.array(\n z.object({\n phase: z.string(),\n otter: z.string(),\n questions: z.array(z.any()),\n requiredPackages: z\n .object({\n dependencies: z.record(z.string(), z.string()).optional(),\n devPackages: z.record(z.string(), z.string()).optional(),\n })\n .optional(),\n })\n )\n ).describe('Array of parsed phase objects from stackwright_pro_parse_otter_response'),\n },\n async ({ phases }) => {\n const { text, isError } = handleSaveManifest({ phases });\n return {\n content: [{ type: 'text' as const, text }],\n isError,\n };\n }\n );\n\n // -------------------------------------------------------------------------\n // 3. stackwright_pro_save_phase_answers\n // -------------------------------------------------------------------------\n server.tool(\n 'stackwright_pro_save_phase_answers',\n 'Save user answers for a phase to .stackwright/answers/{phase}.json. ' +\n 'Pass rawAnswers directly from ask_user_question and the original manifest questions for label-to-value reverse mapping.',\n {\n phase: z.string().describe('Phase name, e.g. \"designer\"'),\n rawAnswers: jsonCoerce(\n z.array(\n z.object({\n question_header: z.string(),\n selected_options: z.array(z.string()),\n other_text: z.string().nullable().optional(),\n })\n )\n ).describe(\n 'Answers as returned by ask_user_question ā pass the native array, not a JSON string'\n ),\n questions: jsonCoerce(z.array(z.any()).optional()).describe(\n 'Original manifest questions for labelāvalue reverse-mapping ā pass the native array, not a JSON string'\n ),\n },\n async ({ phase, rawAnswers, questions }) => {\n const { text, isError } = handleSavePhaseAnswers({\n phase,\n rawAnswers,\n ...(questions && questions.length > 0\n ? { questions: questions as QuestionManifestQuestion[] }\n : {}),\n });\n return {\n content: [{ type: 'text' as const, text }],\n isError,\n };\n }\n );\n\n // -------------------------------------------------------------------------\n // 4. stackwright_pro_read_phase_answers\n // -------------------------------------------------------------------------\n server.tool(\n 'stackwright_pro_read_phase_answers',\n 'Read saved answers for a phase from .stackwright/answers/{phase}.json. ' +\n 'Returns { missing: true } when no answers exist yet ā use this to skip phases safely in the execution loop.',\n {\n phase: z.string().describe('Phase name, e.g. \"designer\"'),\n },\n async ({ phase }) => {\n const { text, isError } = handleReadPhaseAnswers({ phase });\n return {\n content: [{ type: 'text' as const, text }],\n isError,\n };\n }\n );\n\n // -------------------------------------------------------------------------\n // 5. stackwright_pro_get_otter_name\n // -------------------------------------------------------------------------\n server.tool(\n 'stackwright_pro_get_otter_name',\n \"Get the agent name for a phase (e.g. 'designer' ā 'stackwright-pro-designer-otter'). \" +\n 'Use this in the execution loop to invoke the correct specialist otter without hardcoding names in the prompt.',\n {\n phase: z.string().describe('Phase name, e.g. \"designer\", \"api\", \"pages\"'),\n },\n async ({ phase }) => {\n const { text, isError } = handleGetOtterName({ phase });\n return {\n content: [{ type: 'text' as const, text }],\n isError,\n };\n }\n );\n}\n","/**\n * Pipeline State & Artifact Management Tools ā \"Sinks Not Pipes\"\n *\n * The filesystem IS the state machine. Every tool reads/writes to `.stackwright/`.\n * Specialists produce artifacts ā validated here. Retry logic lives HERE.\n */\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { readFileSync, writeFileSync, existsSync, mkdirSync, lstatSync } from 'fs';\nimport { join } from 'path';\nimport { parseLLMQuestionsResponse } from '../question-adapter.js';\nimport { boolCoerce, jsonCoerce } from '../coerce.js';\nimport { createHash } from 'crypto';\nimport {\n initPipelineKeys,\n loadPipelineKeys,\n signArtifact,\n verifyArtifact,\n getArtifactSignature,\n saveArtifactSignature,\n emitSignatureAuditEvent,\n loadSignatureManifest,\n} from '../artifact-signing.js';\n\n// āāā Canonical pro type schemas for artifact validation āāāāāāāāāāāāāāāāāāāāā\nimport { WorkflowFileSchema, authConfigSchema } from '@stackwright-pro/types';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n/** Canonical phase execution order */\nconst PHASE_ORDER = [\n 'designer',\n 'theme',\n 'api',\n 'data',\n 'workflow',\n 'pages',\n 'dashboard',\n 'auth',\n] as const;\ntype Phase = (typeof PHASE_ORDER)[number];\n\n/** Phase dependency graph: what upstream artifacts each phase needs */\nconst PHASE_DEPENDENCIES: Record<Phase, readonly Phase[]> = {\n designer: [],\n theme: ['designer'],\n api: [],\n data: ['api'],\n // workflow: no hard deps ā uses service: references with Prism mock fallback\n // when API artifacts aren't available; roles come from user answers\n workflow: [],\n // pages: 'api' is transitive through 'data'; auth removed ā page-otter has\n // graceful fallback and reads role names from workflow artifacts instead\n pages: ['designer', 'theme', 'data'],\n dashboard: ['designer', 'theme', 'data'],\n // auth is the terminal phase ā reads all available artifacts at runtime;\n // no hard upstream requirements so it always runs and never gets skipped\n auth: [],\n};\n\n/** Maps phase ā expected artifact filename */\nconst PHASE_ARTIFACT: Record<Phase, string> = {\n designer: 'design-language.json',\n theme: 'theme-tokens.json',\n api: 'api-config.json',\n auth: 'auth-config.json',\n data: 'data-config.json',\n pages: 'pages-manifest.json',\n dashboard: 'dashboard-manifest.json',\n workflow: 'workflow-config.json',\n};\n\n/** Maps phase ā otter agent name */\nconst PHASE_TO_OTTER: Record<Phase, string> = {\n designer: 'stackwright-pro-designer-otter',\n theme: 'stackwright-pro-theme-otter',\n api: 'stackwright-pro-api-otter',\n auth: 'stackwright-pro-auth-otter',\n data: 'stackwright-pro-data-otter',\n pages: 'stackwright-pro-page-otter',\n dashboard: 'stackwright-pro-dashboard-otter',\n workflow: 'stackwright-pro-workflow-otter',\n};\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface PhaseStatus {\n questionsCollected: boolean;\n answered: boolean;\n executed: boolean;\n artifactWritten: boolean;\n retryCount: number;\n}\n\nexport interface PipelineState {\n version: '1.0';\n currentPhase: string;\n status: 'setup' | 'questions' | 'execution' | 'done';\n phases: Record<string, PhaseStatus>;\n startedAt: string;\n updatedAt: string;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction isValidPhase(phase: string): phase is Phase {\n return (PHASE_ORDER as readonly string[]).includes(phase);\n}\n\nfunction defaultPhaseStatus(): PhaseStatus {\n return {\n questionsCollected: false,\n answered: false,\n executed: false,\n artifactWritten: false,\n retryCount: 0,\n };\n}\n\nfunction createDefaultState(): PipelineState {\n const now = new Date().toISOString();\n const phases: Record<string, PhaseStatus> = {};\n for (const p of PHASE_ORDER) {\n phases[p] = defaultPhaseStatus();\n }\n return {\n version: '1.0',\n currentPhase: PHASE_ORDER[0],\n status: 'setup',\n phases,\n startedAt: now,\n updatedAt: now,\n };\n}\n\nfunction statePath(cwd: string): string {\n return join(cwd, '.stackwright', 'pipeline-state.json');\n}\n\nfunction readState(cwd: string): PipelineState {\n const p = statePath(cwd);\n if (!existsSync(p)) return createDefaultState();\n const raw = JSON.parse(safeReadSync(p));\n // Minimal schema validation ā reject corrupted state files\n if (typeof raw !== 'object' || raw === null || raw.version !== '1.0') {\n return createDefaultState();\n }\n return raw as PipelineState;\n}\n\n/**\n * Safely write to a path, rejecting symlinks.\n * Used by all pipeline write operations.\n */\nfunction safeWriteSync(filePath: string, content: string): void {\n if (existsSync(filePath)) {\n const stat = lstatSync(filePath);\n if (stat.isSymbolicLink()) {\n throw new Error(`Refusing to write to symlink: ${filePath}`);\n }\n }\n writeFileSync(filePath, content);\n}\n\n/**\n * Safely read from a path, rejecting symlinks.\n * Used by all pipeline read operations to prevent TOCTOU-based symlink attacks.\n */\nfunction safeReadSync(filePath: string): string {\n if (existsSync(filePath)) {\n const stat = lstatSync(filePath);\n if (stat.isSymbolicLink()) {\n throw new Error(`Refusing to read symlink: ${filePath}`);\n }\n }\n return readFileSync(filePath, 'utf-8');\n}\n\nfunction writeState(cwd: string, state: PipelineState): void {\n const dir = join(cwd, '.stackwright');\n mkdirSync(dir, { recursive: true });\n state.updatedAt = new Date().toISOString();\n safeWriteSync(statePath(cwd), JSON.stringify(state, null, 2) + '\\n');\n}\n\n/** Extract JSON from messy LLM output ā handles markdown fences, leading prose */\nfunction extractJsonFromResponse(text: string): unknown {\n let cleaned = text;\n // Strip markdown code fences (```json ... ``` or ``` ... ```)\n cleaned = cleaned.replace(/```(?:json)?\\s*/gi, '');\n cleaned = cleaned.replace(/```\\s*$/gm, '');\n\n // Find the outermost JSON object\n const firstBrace = cleaned.indexOf('{');\n if (firstBrace === -1) throw new Error('No JSON object found in response');\n cleaned = cleaned.substring(firstBrace);\n\n const lastBrace = cleaned.lastIndexOf('}');\n if (lastBrace === -1) throw new Error('Unclosed JSON object in response');\n cleaned = cleaned.substring(0, lastBrace + 1);\n\n // Fix common LLM JSON quirks\n cleaned = cleaned.replace(/,(\\s*[}\\]])/g, '$1'); // trailing commas\n return JSON.parse(cleaned);\n}\n\n// ---------------------------------------------------------------------------\n// Handler functions (exported for direct testing ā no MCP server needed)\n// ---------------------------------------------------------------------------\n\nexport function handleGetPipelineState(_cwd?: string): { text: string; isError: boolean } {\n const cwd = _cwd ?? process.cwd();\n try {\n const state = readState(cwd);\n\n // Auto-initialize signing keys on first access (lazy init)\n const keyPath = join(cwd, '.stackwright', 'pipeline-keys.json');\n if (!existsSync(keyPath)) {\n try {\n const { fingerprint } = initPipelineKeys(cwd);\n // Record key fingerprint in pipeline state for audit trail\n (state as unknown as Record<string, unknown>)['signingKeyFingerprint'] = fingerprint;\n writeState(cwd, state);\n } catch {\n // Non-blocking ā signing is defense-in-depth, not a hard gate at init\n }\n }\n\n return { text: JSON.stringify(state), isError: false };\n } catch (err) {\n return { text: JSON.stringify({ error: true, message: String(err) }), isError: true };\n }\n}\n\nexport interface SetPipelineStateInput {\n phase?: string;\n field?: 'questionsCollected' | 'answered' | 'executed' | 'artifactWritten';\n value?: boolean;\n status?: 'setup' | 'questions' | 'execution' | 'done';\n incrementRetry?: boolean;\n _cwd?: string;\n}\n\nexport function handleSetPipelineState(input: SetPipelineStateInput): {\n text: string;\n isError: boolean;\n} {\n const cwd = input._cwd ?? process.cwd();\n\n // Validate phase name if provided\n if (input.phase && !isValidPhase(input.phase)) {\n return {\n text: JSON.stringify({\n error: true,\n message: `Invalid phase: ${input.phase}. Valid phases are: ${PHASE_ORDER.join(', ')}`,\n }),\n isError: true,\n };\n }\n\n // Validate field name if provided\n const VALID_FIELDS = ['questionsCollected', 'answered', 'executed', 'artifactWritten'] as const;\n if (input.field && !VALID_FIELDS.includes(input.field as (typeof VALID_FIELDS)[number])) {\n return {\n text: JSON.stringify({\n error: true,\n message: `Invalid field: ${input.field}. Valid fields are: ${VALID_FIELDS.join(', ')}`,\n }),\n isError: true,\n };\n }\n\n try {\n const state = readState(cwd);\n\n // Update top-level status if provided\n if (input.status) {\n state.status = input.status;\n }\n\n // Update phase-level fields\n if (input.phase) {\n const phase = input.phase;\n if (!state.phases[phase]) {\n state.phases[phase] = defaultPhaseStatus();\n }\n const phaseState = state.phases[phase];\n\n if (input.field && input.value !== undefined) {\n phaseState[input.field] = input.value;\n }\n\n if (input.incrementRetry) {\n phaseState.retryCount += 1;\n }\n\n state.currentPhase = phase;\n }\n\n writeState(cwd, state);\n return { text: JSON.stringify(state), isError: false };\n } catch (err) {\n return { text: JSON.stringify({ error: true, message: String(err) }), isError: true };\n }\n}\n\nexport function handleCheckExecutionReady(\n _cwd?: string,\n phase?: string\n): { text: string; isError: boolean } {\n const cwd = _cwd ?? process.cwd();\n\n if (phase) {\n if (!isValidPhase(phase)) {\n return {\n text: JSON.stringify({\n error: true,\n message: `Invalid phase: ${phase}. Valid phases are: ${PHASE_ORDER.join(', ')}`,\n }),\n isError: true,\n };\n }\n const answerFile = join(cwd, '.stackwright', 'answers', `${phase}.json`);\n if (!existsSync(answerFile)) {\n return {\n text: JSON.stringify({ ready: false, phase, reason: 'Answer file not found' }),\n isError: false,\n };\n }\n try {\n const raw = safeReadSync(answerFile);\n const parsed = JSON.parse(raw) as Record<string, unknown>;\n if (\n typeof parsed['version'] !== 'string' ||\n typeof parsed['phase'] !== 'string' ||\n typeof parsed['answers'] !== 'object' ||\n parsed['answers'] === null\n ) {\n return {\n text: JSON.stringify({ ready: false, phase, reason: 'Answer file is malformed' }),\n isError: false,\n };\n }\n return { text: JSON.stringify({ ready: true, phase }), isError: false };\n } catch {\n return {\n text: JSON.stringify({ ready: false, phase, reason: 'Answer file could not be parsed' }),\n isError: false,\n };\n }\n }\n\n try {\n const answersDir = join(cwd, '.stackwright', 'answers');\n const answeredPhases: string[] = [];\n const missingPhases: string[] = [];\n\n for (const phase of PHASE_ORDER) {\n const answerFile = join(answersDir, `${phase}.json`);\n if (existsSync(answerFile)) {\n // Validate: file must be parseable JSON with required fields\n try {\n const raw = safeReadSync(answerFile);\n const parsed = JSON.parse(raw) as Record<string, unknown>;\n\n // Must have version, phase, and answers keys\n if (\n typeof parsed['version'] !== 'string' ||\n typeof parsed['phase'] !== 'string' ||\n typeof parsed['answers'] !== 'object' ||\n parsed['answers'] === null\n ) {\n // File exists but is malformed ā treat as missing\n missingPhases.push(phase);\n continue;\n }\n\n answeredPhases.push(phase);\n } catch {\n // Can't parse ā treat as missing\n missingPhases.push(phase);\n }\n } else {\n missingPhases.push(phase);\n }\n }\n\n return {\n text: JSON.stringify({\n ready: missingPhases.length === 0,\n answeredPhases,\n missingPhases,\n totalPhases: PHASE_ORDER.length,\n }),\n isError: false,\n };\n } catch (err) {\n return { text: JSON.stringify({ error: true, message: String(err) }), isError: true };\n }\n}\n\nexport function handleListArtifacts(_cwd?: string): { text: string; isError: boolean } {\n const cwd = _cwd ?? process.cwd();\n try {\n const artifactsDir = join(cwd, '.stackwright', 'artifacts');\n\n // Load signature manifest (non-blocking if missing)\n let manifest: ReturnType<typeof loadSignatureManifest> | null = null;\n try {\n manifest = loadSignatureManifest(cwd);\n } catch {\n // No signature manifest ā report unsigned\n }\n\n const artifacts: Array<{\n phase: string;\n expectedFile: string;\n exists: boolean;\n path: string;\n signed: boolean;\n signatureValid: boolean | null;\n }> = [];\n let completedCount = 0;\n\n for (const phase of PHASE_ORDER) {\n const expectedFile = PHASE_ARTIFACT[phase];\n const fullPath = join(artifactsDir, expectedFile);\n const exists = existsSync(fullPath);\n if (exists) completedCount++;\n\n // Check signature status\n let signed = false;\n let signatureValid: boolean | null = null;\n\n if (exists && manifest) {\n const entry = manifest.signatures[expectedFile];\n if (entry) {\n signed = true;\n // Verify if keys are available\n try {\n const rawBytes = Buffer.from(safeReadSync(fullPath), 'utf-8');\n const { publicKey } = loadPipelineKeys(cwd);\n signatureValid = verifyArtifact(rawBytes, entry, publicKey);\n } catch {\n signatureValid = null; // Can't verify ā keys unavailable\n }\n }\n }\n\n artifacts.push({ phase, expectedFile, exists, path: fullPath, signed, signatureValid });\n }\n\n return {\n text: JSON.stringify({ artifacts, completedCount, totalCount: PHASE_ORDER.length }),\n isError: false,\n };\n } catch (err) {\n return { text: JSON.stringify({ error: true, message: String(err) }), isError: true };\n }\n}\n\nexport interface WritePhaseQuestionsInput {\n phase: string;\n responseText: string;\n _cwd?: string;\n}\n\nexport function handleWritePhaseQuestions(input: WritePhaseQuestionsInput): {\n text: string;\n isError: boolean;\n} {\n const cwd = input._cwd ?? process.cwd();\n const { phase, responseText } = input;\n\n if (!isValidPhase(phase)) {\n return {\n text: JSON.stringify({ error: true, message: `Unknown phase: ${phase}` }),\n isError: true,\n };\n }\n\n try {\n const questions = parseLLMQuestionsResponse(responseText);\n\n // Extract requiredPackages if present in the raw response\n let requiredPackages: {\n dependencies: Record<string, string>;\n devPackages: Record<string, string>;\n } = {\n dependencies: {},\n devPackages: {},\n };\n try {\n const fullParsed = extractJsonFromResponse(responseText) as Record<string, unknown>;\n if (fullParsed.requiredPackages && typeof fullParsed.requiredPackages === 'object') {\n const rp = fullParsed.requiredPackages as Record<string, unknown>;\n requiredPackages = {\n dependencies: (rp.dependencies as Record<string, string>) ?? {},\n devPackages: (rp.devPackages as Record<string, string>) ?? {},\n };\n }\n } catch {\n // extractJsonFromResponse may fail if the response is a bare array ā that's fine\n }\n\n const questionsDir = join(cwd, '.stackwright', 'questions');\n mkdirSync(questionsDir, { recursive: true });\n const filePath = join(questionsDir, `${phase}.json`);\n\n const payload = {\n version: '1.0',\n phase,\n otter: PHASE_TO_OTTER[phase],\n collectedAt: new Date().toISOString(),\n questions,\n requiredPackages,\n };\n\n safeWriteSync(filePath, JSON.stringify(payload, null, 2) + '\\n');\n\n // Update pipeline state\n const state = readState(cwd);\n if (!state.phases[phase]) state.phases[phase] = defaultPhaseStatus();\n const ps = state.phases[phase]!; // guaranteed by line above\n ps.questionsCollected = true;\n writeState(cwd, state);\n\n return {\n text: JSON.stringify({\n success: true,\n phase,\n questionCount: questions.length,\n requiredPackages,\n path: filePath,\n }),\n isError: false,\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return { text: JSON.stringify({ error: true, phase, message }), isError: true };\n }\n}\n\nexport interface BuildSpecialistPromptInput {\n phase: string;\n _cwd?: string;\n}\n\nexport function handleBuildSpecialistPrompt(input: BuildSpecialistPromptInput): {\n text: string;\n isError: boolean;\n} {\n const cwd = input._cwd ?? process.cwd();\n const { phase } = input;\n\n if (!isValidPhase(phase)) {\n return {\n text: JSON.stringify({ error: true, message: `Unknown phase: ${phase}` }),\n isError: true,\n };\n }\n\n try {\n // 1. Read answers for this phase\n const answersPath = join(cwd, '.stackwright', 'answers', `${phase}.json`);\n let answers: unknown = {};\n if (existsSync(answersPath)) {\n answers = JSON.parse(safeReadSync(answersPath));\n }\n\n // 1b. Read build context (optional ā non-blocking if missing or malformed)\n let buildContextText = '';\n const buildContextPath = join(cwd, '.stackwright', 'build-context.json');\n if (existsSync(buildContextPath)) {\n try {\n const bcRaw = JSON.parse(safeReadSync(buildContextPath)) as { buildContext?: string };\n if (typeof bcRaw.buildContext === 'string' && bcRaw.buildContext.trim().length > 0) {\n buildContextText = bcRaw.buildContext.trim();\n }\n } catch {\n // Non-blocking ā missing or malformed build context does not block execution\n }\n }\n\n // 2. Read upstream dependency artifacts\n const deps = PHASE_DEPENDENCIES[phase];\n const artifactSections: string[] = [];\n const missingDependencies: string[] = [];\n\n for (const dep of deps) {\n const artifactFile = PHASE_ARTIFACT[dep];\n const artifactPath = join(cwd, '.stackwright', 'artifacts', artifactFile);\n if (existsSync(artifactPath)) {\n const rawContent = safeReadSync(artifactPath);\n const rawBytes = Buffer.from(rawContent, 'utf-8');\n const content = JSON.parse(rawContent) as Record<string, unknown>;\n\n // āā Cryptographic signature verification (primary integrity check) āā\n // If signing keys exist, verify the ECDSA P-384 signature before trusting\n // the artifact. Falls back to generatedBy check if unsigned (backwards compat).\n let signatureVerified = false;\n let signatureAvailable = false;\n\n try {\n const sig = getArtifactSignature(cwd, artifactFile);\n if (sig) {\n signatureAvailable = true;\n const { publicKey } = loadPipelineKeys(cwd);\n signatureVerified = verifyArtifact(rawBytes, sig, publicKey);\n\n if (!signatureVerified) {\n // Emit audit event for SOC2/FedRAMP compliance\n const actualDigest = createHash('sha384').update(rawBytes).digest('hex');\n emitSignatureAuditEvent({\n artifactFilename: artifactFile,\n expectedDigest: sig.digest,\n actualDigest,\n phase: dep,\n timestamp: new Date().toISOString(),\n source: 'stackwright_pro_build_specialist_prompt',\n });\n\n missingDependencies.push(dep);\n artifactSections.push(\n `[${artifactFile}]:\\n(integrity check failed: ECDSA-P384 signature verification failed ā artifact may have been tampered with)`\n );\n continue;\n }\n }\n } catch {\n // Key loading failed ā fall through to generatedBy check\n }\n\n // āā Secondary check: generatedBy field cross-validation āā\n // Even with valid signatures, verify the generatedBy field matches expectations.\n // Without signatures (unsigned pipeline), this is the primary check.\n const expectedOtter = PHASE_TO_OTTER[dep];\n const artifactOtter = content['generatedBy'] as string | undefined;\n const normalizedOtter = artifactOtter?.replace(/-[a-f0-9]{6}$/, '');\n\n if (!artifactOtter) {\n missingDependencies.push(dep);\n artifactSections.push(\n `[${artifactFile}]:\\n(integrity check failed: missing generatedBy field)`\n );\n } else if (normalizedOtter !== expectedOtter) {\n missingDependencies.push(dep);\n artifactSections.push(\n `[${artifactFile}]:\\n(integrity check failed: artifact claims generatedBy=\"${artifactOtter}\" but expected=\"${expectedOtter}\")`\n );\n } else {\n const sigStatus = signatureAvailable\n ? signatureVerified\n ? ' [signature verified]'\n : ' [signature check skipped]'\n : ' [unsigned]';\n artifactSections.push(\n `[${artifactFile}]${sigStatus}:\\n${JSON.stringify(content, null, 2)}`\n );\n }\n } else {\n missingDependencies.push(dep);\n artifactSections.push(`[${artifactFile}]:\\n(not yet available)`);\n }\n }\n\n // 3. Assemble the prompt\n const parts: string[] = [];\n\n if (buildContextText) {\n parts.push('BUILD_CONTEXT:', buildContextText, '');\n }\n\n parts.push('ANSWERS:', JSON.stringify(answers, null, 2));\n\n if (artifactSections.length > 0) {\n parts.push('', 'UPSTREAM ARTIFACTS:', '', ...artifactSections);\n }\n\n // Inject the canonical artifact schema so specialists always build against\n // the current contract ā not hardcoded examples in their JSON files.\n const artifactSchema = PHASE_ARTIFACT_SCHEMA[phase];\n parts.push('', 'REQUIRED_ARTIFACT_SCHEMA:');\n parts.push(artifactSchema);\n\n parts.push('', 'Execute using these answers and the upstream artifacts provided.');\n\n const prompt = parts.join('\\n');\n const dependenciesSatisfied = missingDependencies.length === 0;\n\n return {\n text: JSON.stringify({\n otterName: PHASE_TO_OTTER[phase],\n phase,\n prompt,\n dependenciesSatisfied,\n missingDependencies,\n }),\n isError: false,\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return { text: JSON.stringify({ error: true, phase, message }), isError: true };\n }\n}\n\nexport interface ValidateArtifactInput {\n phase: string;\n responseText?: string;\n artifact?: Record<string, unknown>;\n _cwd?: string;\n}\n\nconst OFF_SCRIPT_PATTERNS: Array<{ pattern: RegExp; label: string }> = [\n {\n pattern: /```(?:ts|tsx|js|jsx|python|bash|sh|sql|ruby|go|rust|java|csharp|c\\+\\+)\\b/,\n label: 'code fence',\n },\n { pattern: /\\bimport\\s+[\\w{]/, label: 'import statement' },\n { pattern: /\\bexport\\s+(?:const|function|default|class)\\b/, label: 'export statement' },\n { pattern: /\\brequire\\s*\\(/, label: 'require() call' },\n { pattern: /\\beval\\s*\\(/, label: 'eval() call' },\n { pattern: /^#!/m, label: 'shebang' },\n { pattern: /<script[\\s>]/i, label: 'script tag' },\n { pattern: /\\.(ts|tsx|js|jsx)\\b.*\\bfile\\b/i, label: 'code file reference' },\n];\n\ninterface ValidArtifactResult {\n valid: true;\n phase: string;\n artifactPath: string;\n summary: string;\n}\n\ninterface InvalidArtifactResult {\n valid: false;\n phase: string;\n violation: 'off-script' | 'invalid-json' | 'missing-fields' | 'schema-mismatch';\n retryPrompt: string;\n}\n\nconst PHASE_REQUIRED_KEYS: Record<Phase, string[]> = {\n designer: ['designLanguage', 'themeTokenSeeds'],\n theme: ['tokens'],\n api: ['entities', 'version', 'generatedBy'],\n auth: ['version', 'generatedBy'],\n data: ['version', 'generatedBy', 'strategy', 'collections'],\n pages: ['version', 'generatedBy'],\n dashboard: ['version', 'generatedBy'],\n workflow: ['version', 'generatedBy'],\n};\n\n/**\n * Canonical artifact schema examples for each phase.\n *\n * SINGLE SOURCE OF TRUTH ā injected into specialist prompts at invocation time\n * via handleBuildSpecialistPrompt. Both validate_artifact (enforcement) and\n * build_specialist_prompt (guidance) derive from the same constant here.\n *\n * Schema changes happen in THIS file only. Zero drift possible.\n */\nconst PHASE_ARTIFACT_SCHEMA: Record<Phase, string> = {\n designer: JSON.stringify(\n {\n version: '1.0',\n generatedBy: 'stackwright-pro-designer-otter',\n application: {\n type: '<operational|data-explorer|admin|logistics|general>',\n environment: '<workstation|field|control-room|mixed>',\n density: '<compact|balanced|spacious>',\n accessibility: '<wcag-aa|section-508|none>',\n colorScheme: '<light|dark|both>',\n },\n designLanguage: {\n rationale: '<design rationale>',\n spacingScale: { base: 8, scale: [0, 4, 8, 16, 24, 32, 48, 64] },\n colorSemantics: { primary: '#1a365d', accent: '#e53e3e' },\n typography: {\n dataFont: 'Inter',\n headingFont: 'Inter',\n monoFont: 'monospace',\n dataSizePx: 12,\n bodySizePx: 14,\n },\n contrastRatio: '4.5',\n borderRadius: '4',\n shadowElevation: 'standard',\n },\n themeTokenSeeds: {\n light: {\n background: '#ffffff',\n foreground: '#1a1a1a',\n primary: '#1a365d',\n surface: '#f7f7f7',\n border: '#e2e8f0',\n },\n dark: {\n background: '#1a1a1a',\n foreground: '#ffffff',\n primary: '#90cdf4',\n surface: '#2d2d2d',\n border: '#4a5568',\n },\n },\n conformsTo: null,\n operationalNotes: [],\n },\n null,\n 2\n ),\n\n theme: JSON.stringify(\n {\n version: '1.0',\n generatedBy: 'stackwright-pro-theme-otter',\n componentLibrary: 'shadcn',\n colorScheme: '<light|dark|both>',\n tokens: {\n colors: { 'primary-500': '#1a365d', background: '#ffffff' },\n spacing: { 'spacing-1': '8px', 'spacing-2': '16px' },\n typography: { 'font-data': 'Inter', 'text-sm': '12px' },\n shape: { 'radius-sm': '4px', 'radius-md': '8px' },\n shadows: { 'shadow-sm': '0 1px 2px rgba(0,0,0,0.08)' },\n },\n cssVariables: {\n '--background': '0 0% 100%',\n '--foreground': '222.2 84% 4.9%',\n '--primary': '222.2 47.4% 11.2%',\n '--primary-foreground': '210 40% 98%',\n '--surface': '210 40% 98%',\n '--border': '214.3 31.8% 91.4%',\n },\n dark: { '--background': '222.2 84% 4.9%', '--foreground': '210 40% 98%' },\n },\n null,\n 2\n ),\n\n api: JSON.stringify(\n {\n version: '1.0',\n generatedBy: 'stackwright-pro-api-otter',\n entities: [\n {\n name: 'Shipment',\n endpoint: '/shipments',\n method: 'GET',\n revalidate: 60,\n mutationType: null,\n },\n ],\n auth: { type: 'bearer', header: 'Authorization', envVar: 'API_TOKEN' },\n baseUrl: 'https://api.example.mil/v2',\n specPath: './specs/api.yaml',\n },\n null,\n 2\n ),\n\n data: JSON.stringify(\n {\n version: '1.0',\n generatedBy: 'stackwright-pro-data-otter',\n strategy: '<pulse-fast|isr-fast|isr-standard|isr-slow>',\n pulseMode: false,\n collections: [{ name: 'equipment', revalidate: 60, pulse: false }],\n endpoints: { included: ['/equipment/**'], excluded: ['/admin/**'] },\n requiredPackages: { dependencies: {}, devPackages: {} },\n },\n null,\n 2\n ),\n\n workflow: JSON.stringify(\n {\n version: '1.0',\n generatedBy: 'stackwright-pro-workflow-otter',\n workflowConfig: {\n id: 'procurement-approval',\n route: '/procurement',\n files: ['workflows/procurement-approval.yml'],\n serviceDependencies: ['service:workflow-state'],\n warnings: [],\n },\n },\n null,\n 2\n ),\n\n pages: JSON.stringify(\n {\n version: '1.0',\n generatedBy: 'stackwright-pro-page-otter',\n pages: [\n {\n slug: 'catalog',\n type: 'collection_listing',\n collection: 'products',\n themeApplied: true,\n authRequired: false,\n },\n {\n slug: 'admin',\n type: 'protected',\n collection: null,\n themeApplied: true,\n authRequired: true,\n },\n ],\n },\n null,\n 2\n ),\n\n dashboard: JSON.stringify(\n {\n version: '1.0',\n generatedBy: 'stackwright-pro-dashboard-otter',\n pages: [\n {\n slug: 'dashboard',\n layout: '<grid|table|mixed>',\n collections: ['equipment', 'supplies'],\n mode: '<ISR|Pulse>',\n },\n ],\n },\n null,\n 2\n ),\n\n auth: JSON.stringify(\n {\n version: '1.0',\n generatedBy: 'stackwright-pro-auth-otter',\n authConfig: {\n method: '<cac|oidc|oauth2|none>',\n provider: '<azure-ad|okta|ping|cognito ā if OIDC, else null>',\n rbacRoles: ['ADMIN', 'ANALYST'],\n rbacDefaultRole: 'ANALYST',\n protectedRoutes: ['/dashboard/:path*', '/procurement/:path*'],\n auditEnabled: true,\n auditRetentionDays: 90,\n },\n },\n null,\n 2\n ),\n};\n\nexport function handleValidateArtifact(input: ValidateArtifactInput): {\n text: string;\n isError: boolean;\n} {\n const cwd = input._cwd ?? process.cwd();\n const { phase, responseText, artifact: directArtifact } = input;\n\n if (!isValidPhase(phase)) {\n return {\n text: JSON.stringify({ error: true, message: `Unknown phase: ${phase}` }),\n isError: true,\n };\n }\n\n let artifact: Record<string, unknown>;\n\n if (directArtifact) {\n // Direct artifact path (specialist calling with artifact object):\n // Skip off-script detection and JSON string parsing ā already an object.\n artifact = directArtifact;\n } else {\n // Legacy responseText path (Foreman-mediated):\n const text = responseText ?? '';\n\n // 1. Off-script detection ā check the RAW response before trying to parse\n for (const { pattern, label } of OFF_SCRIPT_PATTERNS) {\n if (pattern.test(text)) {\n const result: InvalidArtifactResult = {\n valid: false,\n phase,\n violation: 'off-script',\n retryPrompt: `You returned code output (detected: ${label}). Return ONLY a JSON artifact ā no code, no files.`,\n };\n return { text: JSON.stringify(result), isError: false };\n }\n }\n\n // 2. JSON extraction\n try {\n artifact = extractJsonFromResponse(text) as Record<string, unknown>;\n } catch {\n const result: InvalidArtifactResult = {\n valid: false,\n phase,\n violation: 'invalid-json',\n retryPrompt:\n 'Your response did not contain valid JSON. Return a single JSON object with no surrounding text.',\n };\n return { text: JSON.stringify(result), isError: false };\n }\n }\n\n // 3. Required universal fields\n if (!artifact.version || !artifact.generatedBy) {\n const result: InvalidArtifactResult = {\n valid: false,\n phase,\n violation: 'missing-fields',\n retryPrompt:\n 'Your JSON artifact is missing required fields. Every artifact MUST include \"version\" and \"generatedBy\" at the top level.',\n };\n return { text: JSON.stringify(result), isError: false };\n }\n\n // 4. Phase-specific key checks\n const requiredKeys = PHASE_REQUIRED_KEYS[phase];\n const missingKeys = requiredKeys.filter((k) => !(k in artifact));\n if (missingKeys.length > 0) {\n const result: InvalidArtifactResult = {\n valid: false,\n phase,\n violation: 'schema-mismatch',\n retryPrompt: `Your ${phase} artifact is missing required keys: ${missingKeys.join(', ')}. Include them and try again.`,\n };\n return { text: JSON.stringify(result), isError: false };\n }\n\n // 5. Zod schema validation (where canonical schemas are available)\n // Provides richer error messages than key-presence checks alone.\n const PHASE_ZOD_VALIDATORS: Partial<\n Record<\n Phase,\n (artifact: Record<string, unknown>) => { success: boolean; error?: { message: string } }\n >\n > = {\n workflow: (artifact) => {\n // The workflow otter produces { version, generatedBy, workflowConfig: { workflow: {...} } }\n // Validate the nested workflowConfig if present\n const workflowConfig = artifact['workflowConfig'];\n if (!workflowConfig) return { success: true }; // skip if not present (caught by key check)\n const result = WorkflowFileSchema.safeParse(workflowConfig);\n if (!result.success) {\n const issues = result.error.issues\n .slice(0, 3)\n .map((i) => `${i.path.join('.')}: ${i.message}`)\n .join('; ');\n return { success: false, error: { message: issues } };\n }\n return { success: true };\n },\n auth: (artifact) => {\n // The auth otter produces { version, generatedBy, authConfig: { type: 'oidc'|'pki', ... } }\n const authConfig = artifact['authConfig'];\n if (!authConfig) return { success: true }; // skip if not present\n const result = authConfigSchema.safeParse(authConfig);\n if (!result.success) {\n const issues = result.error.issues\n .slice(0, 3)\n .map((i) => `${i.path.join('.')}: ${i.message}`)\n .join('; ');\n return { success: false, error: { message: issues } };\n }\n return { success: true };\n },\n };\n\n const zodValidator = PHASE_ZOD_VALIDATORS[phase];\n if (zodValidator) {\n const zodResult = zodValidator(artifact);\n if (!zodResult.success) {\n const result: InvalidArtifactResult = {\n valid: false,\n phase,\n violation: 'schema-mismatch',\n retryPrompt: `Your artifact failed schema validation: ${zodResult.error?.message}. Fix these fields and return the corrected JSON artifact.`,\n };\n return { text: JSON.stringify(result), isError: false };\n }\n }\n\n // 6. All good ā write it and sign it\n try {\n const artifactsDir = join(cwd, '.stackwright', 'artifacts');\n mkdirSync(artifactsDir, { recursive: true });\n const artifactFile = PHASE_ARTIFACT[phase];\n const artifactPath = join(artifactsDir, artifactFile);\n\n // Serialize once ā sign and write the same bytes (zero TOCTOU window)\n const serialized = JSON.stringify(artifact, null, 2) + '\\n';\n const artifactBytes = Buffer.from(serialized, 'utf-8');\n safeWriteSync(artifactPath, serialized);\n\n // Sign the artifact (non-blocking ā signing failure doesn't prevent write)\n let signed = false;\n try {\n const { privateKey } = loadPipelineKeys(cwd);\n const sig = signArtifact(artifactBytes, privateKey);\n const signerOtter = PHASE_TO_OTTER[phase];\n saveArtifactSignature(cwd, artifactFile, sig, signerOtter);\n signed = true;\n } catch {\n // Signing is defense-in-depth ā pipeline continues without signatures\n // if keys haven't been initialized (e.g., backwards-compat with old pipelines)\n }\n\n // Update pipeline state\n const state = readState(cwd);\n if (!state.phases[phase]) state.phases[phase] = defaultPhaseStatus();\n const ps = state.phases[phase]!; // guaranteed by line above\n ps.artifactWritten = true;\n writeState(cwd, state);\n\n const topKeys = Object.keys(artifact).slice(0, 5).join(', ');\n const result: ValidArtifactResult = {\n valid: true,\n phase,\n artifactPath,\n summary: `Wrote ${artifactFile} (keys: ${topKeys}${Object.keys(artifact).length > 5 ? ', ...' : ''})${signed ? ' [signed]' : ''}`,\n };\n return { text: JSON.stringify(result), isError: false };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return { text: JSON.stringify({ error: true, phase, message }), isError: true };\n }\n}\n\n// ---------------------------------------------------------------------------\n// MCP tool registration\n// ---------------------------------------------------------------------------\n\nexport function registerPipelineTools(server: McpServer): void {\n const DESC = 'Writes state to .stackwright/ ā the filesystem is the state machine.';\n const res = (r: { text: string; isError: boolean }) => ({\n content: [{ type: 'text' as const, text: r.text }],\n isError: r.isError,\n });\n\n server.tool(\n 'stackwright_pro_get_pipeline_state',\n `Read pipeline state from .stackwright/pipeline-state.json. ${DESC}`,\n {},\n async () => res(handleGetPipelineState())\n );\n\n server.tool(\n 'stackwright_pro_set_pipeline_state',\n `Atomic readāmodifyāwrite pipeline state. ${DESC}`,\n {\n phase: z.string().optional().describe('Phase to update, e.g. \"designer\"'),\n field: z\n .enum(['questionsCollected', 'answered', 'executed', 'artifactWritten'])\n .optional()\n .describe('Boolean field to set'),\n value: boolCoerce(z.boolean().optional()).describe(\n 'Value for the field ā must be a JSON boolean (true/false), NOT the string \"true\"/\"false\"'\n ),\n status: z\n .enum(['setup', 'questions', 'execution', 'done'])\n .optional()\n .describe('Top-level status override'),\n incrementRetry: boolCoerce(z.boolean().optional()).describe(\n 'Bump retryCount by 1 ā must be a JSON boolean'\n ),\n },\n async (args) =>\n res(\n handleSetPipelineState({\n ...(args.phase != null ? { phase: args.phase } : {}),\n ...(args.field != null ? { field: args.field } : {}),\n ...(args.value != null ? { value: args.value } : {}),\n ...(args.status != null ? { status: args.status } : {}),\n ...(args.incrementRetry != null ? { incrementRetry: args.incrementRetry } : {}),\n })\n )\n );\n\n server.tool(\n 'stackwright_pro_check_execution_ready',\n `Check all phases have answer files in .stackwright/answers/. If phase is provided, check only that phase. ${DESC}`,\n {\n phase: z\n .string()\n .optional()\n .describe(\"If provided, check only this phase's readiness. Omit to check all phases.\"),\n },\n async ({ phase }) => res(handleCheckExecutionReady(undefined, phase))\n );\n\n server.tool(\n 'stackwright_pro_list_artifacts',\n `List phase artifacts in .stackwright/artifacts/ with completedCount/totalCount. ${DESC}`,\n {},\n async () => res(handleListArtifacts())\n );\n\n server.tool(\n 'stackwright_pro_write_phase_questions',\n `Parse otter question-collection response ā .stackwright/questions/{phase}.json. Specialists may also call this directly with a parsed questions array. ${DESC}`,\n {\n phase: z\n .string()\n .optional()\n .describe('Phase name, e.g. \"designer\" (required for direct write)'),\n responseText: z\n .string()\n .optional()\n .describe('Raw LLM response from QUESTION_COLLECTION_MODE'),\n questions: jsonCoerce(z.array(z.any()).optional()).describe(\n 'Questions array for direct specialist write'\n ),\n },\n async ({ phase, responseText, questions }) => {\n // Direct write path: specialist calls with parsed array (no responseText parsing)\n if (phase && questions && Array.isArray(questions)) {\n const SAFE_PHASE = /^[a-z][a-z0-9-]{0,30}$/;\n if (!SAFE_PHASE.test(phase)) {\n return {\n content: [\n { type: 'text' as const, text: JSON.stringify({ error: `Invalid phase name` }) },\n ],\n isError: true,\n };\n }\n const questionsDir = join(process.cwd(), '.stackwright', 'questions');\n mkdirSync(questionsDir, { recursive: true });\n const outPath = join(questionsDir, `${phase}.json`);\n writeFileSync(\n outPath,\n JSON.stringify({ phase, questions, writtenAt: new Date().toISOString() }, null, 2)\n );\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify({\n written: true,\n phase,\n count: (questions as unknown[]).length,\n }),\n },\n ],\n };\n }\n // Fallback: parse from raw LLM responseText\n return res(\n handleWritePhaseQuestions({ phase: phase ?? '', responseText: responseText ?? '' })\n );\n }\n );\n\n server.tool(\n 'stackwright_pro_build_specialist_prompt',\n `Assemble execution prompt from answers + upstream artifacts. Foreman passes verbatim. ${DESC}`,\n { phase: z.string().describe('Phase to build prompt for, e.g. \"pages\"') },\n async ({ phase }) => res(handleBuildSpecialistPrompt({ phase }))\n );\n\n server.tool(\n 'stackwright_pro_validate_artifact',\n `Validate and write artifact to .stackwright/artifacts/. Returns retryPrompt on failure. ${DESC}`,\n {\n phase: z.string().describe('Phase that produced this artifact, e.g. \"designer\"'),\n responseText: z\n .string()\n .optional()\n .describe('Raw response text from the specialist otter (Foreman-mediated path, legacy)'),\n artifact: jsonCoerce(z.record(z.string(), z.unknown()).optional()).describe(\n 'Artifact object to validate and write directly (specialist direct path ā skips off-script detection and JSON parsing)'\n ),\n },\n async ({ phase, responseText, artifact }) => {\n if (artifact) {\n return res(\n handleValidateArtifact({ phase, artifact: artifact as Record<string, unknown> })\n );\n }\n return res(handleValidateArtifact({ phase, responseText: responseText ?? '' }));\n }\n );\n}\n","/**\n * Artifact Signing ā Cryptographic Pipeline Artifact Protection\n * ==============================================================\n * Closes the mid-pipeline TOCTOU gap where artifacts written by one otter\n * can be tampered with before the next otter reads them.\n *\n * integrity.ts handles SHA-256 pinning of otter *definition* files at startup.\n * This module protects pipeline *artifacts* (`.stackwright/artifacts/`) with\n * ECDSA P-384 signatures. Ephemeral key pairs are per-pipeline-run, destroyed\n * after completion.\n */\nimport {\n createHash,\n generateKeyPairSync,\n createPublicKey,\n createPrivateKey,\n sign,\n verify,\n timingSafeEqual,\n KeyObject,\n} from 'crypto';\nimport {\n readFileSync,\n writeFileSync,\n existsSync,\n mkdirSync,\n lstatSync,\n unlinkSync,\n readdirSync,\n} from 'fs';\nimport { join } from 'path';\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst ALGORITHM = 'ECDSA-P384-SHA384' as const;\nconst KEY_FILE = 'pipeline-keys.json';\nconst KEY_DIR = '.stackwright';\nconst SIGNATURE_MANIFEST = 'signatures.json';\nconst ARTIFACTS_DIR = '.stackwright/artifacts';\n\n// ---------------------------------------------------------------------------\n// Exported types & interfaces\n// ---------------------------------------------------------------------------\n\n/** Signature record for a single artifact. */\nexport interface ArtifactSignature {\n digest: string;\n signature: string;\n algorithm: typeof ALGORITHM;\n signedAt: string;\n}\n\n/** Manifest entry ā extends ArtifactSignature with signer identity. */\nexport interface ManifestEntry extends ArtifactSignature {\n signedBy: string;\n}\n\n/** On-disk shape of `.stackwright/artifacts/signatures.json`. */\nexport interface SignatureManifest {\n version: '1.0';\n algorithm: typeof ALGORITHM;\n signatures: Record<string, ManifestEntry>;\n}\n\n/** On-disk shape of `.stackwright/pipeline-keys.json`. */\nexport interface PipelineKeyFile {\n version: '1.0';\n algorithm: typeof ALGORITHM;\n createdAt: string;\n publicKeyPem: string;\n privateKeyPem: string;\n}\n\n/** Structured audit event for a signature failure. */\nexport interface SignatureAuditEvent {\n artifactFilename: string;\n expectedDigest: string;\n actualDigest: string;\n phase: string;\n timestamp: string;\n source: string;\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\n/** Reject symlinks at a given path. No-op if path doesn't exist. */\nfunction rejectSymlink(filePath: string, context: string): void {\n if (!existsSync(filePath)) return;\n const stat = lstatSync(filePath);\n if (stat.isSymbolicLink()) {\n throw new Error(`Security: refusing to follow symlink at ${context}: ${filePath}`);\n }\n}\n\n/** Hex-encoded SHA-384 digest of raw bytes. Pure, no I/O. */\nfunction computeSha384(data: Buffer): string {\n return createHash('sha384').update(data).digest('hex');\n}\n\n/** Constant-time comparison of two hex digest strings. */\nfunction safeDigestEqual(a: string, b: string): boolean {\n if (a.length !== b.length) return false;\n return timingSafeEqual(Buffer.from(a, 'utf8'), Buffer.from(b, 'utf8'));\n}\n\n/** Build an empty manifest with the correct shape. */\nfunction emptyManifest(): SignatureManifest {\n return {\n version: '1.0',\n algorithm: ALGORITHM,\n signatures: {},\n };\n}\n\n// ---------------------------------------------------------------------------\n// 1. Ephemeral Key Pair Management (ECDSA P-384)\n// ---------------------------------------------------------------------------\n\n/** Generate an ECDSA P-384 key pair, write to `.stackwright/pipeline-keys.json`. */\nexport function initPipelineKeys(cwd: string): { publicKeyPem: string; fingerprint: string } {\n const keyDir = join(cwd, KEY_DIR);\n const keyPath = join(keyDir, KEY_FILE);\n\n // Reject symlinks on the key file path\n rejectSymlink(keyPath, 'pipeline-keys.json');\n\n // Ensure directory exists\n mkdirSync(keyDir, { recursive: true });\n\n // Generate ECDSA P-384 key pair\n const { publicKey, privateKey } = generateKeyPairSync('ec', {\n namedCurve: 'P-384',\n });\n\n const publicKeyPem = publicKey.export({ type: 'spki', format: 'pem' }) as string;\n const privateKeyPem = privateKey.export({ type: 'pkcs8', format: 'pem' }) as string;\n\n // SHA-256 fingerprint of the public key PEM\n const fingerprint = createHash('sha256').update(publicKeyPem).digest('hex');\n\n const keyFile: PipelineKeyFile = {\n version: '1.0',\n algorithm: ALGORITHM,\n createdAt: new Date().toISOString(),\n publicKeyPem,\n privateKeyPem,\n };\n\n writeFileSync(keyPath, JSON.stringify(keyFile, null, 2), { encoding: 'utf-8' });\n\n return { publicKeyPem, fingerprint };\n}\n\n/** Load pipeline key pair from disk. Validates PEM, rejects symlinks. */\nexport function loadPipelineKeys(cwd: string): { privateKey: KeyObject; publicKey: KeyObject } {\n const keyPath = join(cwd, KEY_DIR, KEY_FILE);\n\n // Reject symlinks\n rejectSymlink(keyPath, 'pipeline-keys.json');\n\n if (!existsSync(keyPath)) {\n throw new Error('Pipeline keys not found ā call initPipelineKeys() first');\n }\n\n let raw: string;\n try {\n raw = readFileSync(keyPath, 'utf-8');\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n throw new Error(`Cannot read pipeline keys: ${msg}`, { cause: err });\n }\n\n let parsed: PipelineKeyFile;\n try {\n parsed = JSON.parse(raw) as PipelineKeyFile;\n } catch {\n throw new Error('Pipeline keys file is not valid JSON');\n }\n\n // Basic PEM format validation\n if (\n typeof parsed.publicKeyPem !== 'string' ||\n !parsed.publicKeyPem.includes('-----BEGIN PUBLIC KEY-----')\n ) {\n throw new Error('Invalid public key PEM in pipeline keys file');\n }\n if (typeof parsed.privateKeyPem !== 'string' || !parsed.privateKeyPem.includes('-----BEGIN')) {\n throw new Error('Invalid private key PEM in pipeline keys file');\n }\n\n const publicKey = createPublicKey(parsed.publicKeyPem);\n const privateKey = createPrivateKey(parsed.privateKeyPem);\n\n return { privateKey, publicKey };\n}\n\n/** Overwrite private key material with zeros then delete. Idempotent. */\nexport function destroyPipelineKeys(cwd: string): void {\n const keyPath = join(cwd, KEY_DIR, KEY_FILE);\n\n if (!existsSync(keyPath)) return;\n\n // Reject symlinks even during destruction\n rejectSymlink(keyPath, 'pipeline-keys.json (destroy)');\n\n // Read ā overwrite private key material with zeros ā delete\n try {\n const raw = readFileSync(keyPath, 'utf-8');\n const parsed = JSON.parse(raw) as PipelineKeyFile;\n parsed.privateKeyPem = '0'.repeat(parsed.privateKeyPem.length);\n parsed.publicKeyPem = '0'.repeat(parsed.publicKeyPem.length);\n writeFileSync(keyPath, JSON.stringify(parsed, null, 2), { encoding: 'utf-8' });\n } catch {\n // Best-effort overwrite ā proceed to delete regardless\n }\n\n try {\n unlinkSync(keyPath);\n } catch {\n // Already gone ā idempotent\n }\n}\n\n// ---------------------------------------------------------------------------\n// 2. Artifact Signing\n// ---------------------------------------------------------------------------\n\n/** Sign artifact bytes with ECDSA P-384. Returns structured signature record. */\nexport function signArtifact(artifactBytes: Buffer, privateKey: KeyObject): ArtifactSignature {\n const digest = computeSha384(artifactBytes);\n const sig = sign('SHA384', artifactBytes, privateKey);\n\n return {\n digest,\n signature: sig.toString('base64'),\n algorithm: ALGORITHM,\n signedAt: new Date().toISOString(),\n };\n}\n\n// ---------------------------------------------------------------------------\n// 3. Artifact Verification\n// ---------------------------------------------------------------------------\n\n/** Verify ECDSA signature AND constant-time SHA-384 digest. Both must pass. */\nexport function verifyArtifact(\n artifactBytes: Buffer,\n signature: ArtifactSignature,\n publicKey: KeyObject\n): boolean {\n // Layer 1: ECDSA signature verification\n const sigValid = verify(\n 'SHA384',\n artifactBytes,\n publicKey,\n Buffer.from(signature.signature, 'base64')\n );\n\n if (!sigValid) return false;\n\n // Layer 2: Constant-time digest comparison\n const actualDigest = computeSha384(artifactBytes);\n return safeDigestEqual(actualDigest, signature.digest);\n}\n\n// ---------------------------------------------------------------------------\n// 4. Signature Manifest Management\n// ---------------------------------------------------------------------------\n\n/** Load signature manifest. Returns empty manifest if file doesn't exist. */\nexport function loadSignatureManifest(cwd: string): SignatureManifest {\n const manifestPath = join(cwd, ARTIFACTS_DIR, SIGNATURE_MANIFEST);\n\n rejectSymlink(manifestPath, 'signatures.json');\n\n if (!existsSync(manifestPath)) return emptyManifest();\n\n let raw: string;\n try {\n raw = readFileSync(manifestPath, 'utf-8');\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n throw new Error(`Cannot read signature manifest: ${msg}`, { cause: err });\n }\n\n try {\n const parsed = JSON.parse(raw) as SignatureManifest;\n // Basic shape validation ā don't trust what's on disk blindly\n if (parsed.version !== '1.0' || typeof parsed.signatures !== 'object') {\n throw new Error('Malformed signature manifest: invalid version or missing signatures object');\n }\n return parsed;\n } catch (err) {\n if (err instanceof Error && err.message.startsWith('Malformed')) throw err;\n throw new Error('Signature manifest is not valid JSON', { cause: err });\n }\n}\n\n/** Save a signature entry for a specific artifact. Read-modify-write. */\nexport function saveArtifactSignature(\n cwd: string,\n artifactFilename: string,\n sig: ArtifactSignature,\n signerOtter: string\n): void {\n const artifactsDir = join(cwd, ARTIFACTS_DIR);\n const manifestPath = join(artifactsDir, SIGNATURE_MANIFEST);\n\n rejectSymlink(manifestPath, 'signatures.json (save)');\n\n // Ensure artifacts directory exists\n mkdirSync(artifactsDir, { recursive: true });\n\n const manifest = loadSignatureManifest(cwd);\n\n manifest.signatures[artifactFilename] = {\n ...sig,\n signedBy: signerOtter,\n };\n\n writeFileSync(manifestPath, JSON.stringify(manifest, null, 2), { encoding: 'utf-8' });\n}\n\n/** Retrieve signature for a specific artifact, or null if absent. */\nexport function getArtifactSignature(\n cwd: string,\n artifactFilename: string\n): ArtifactSignature | null {\n const manifest = loadSignatureManifest(cwd);\n const entry = manifest.signatures[artifactFilename];\n if (!entry) return null;\n\n // Return just the ArtifactSignature fields (strip signedBy)\n return {\n digest: entry.digest,\n signature: entry.signature,\n algorithm: entry.algorithm,\n signedAt: entry.signedAt,\n };\n}\n\n// ---------------------------------------------------------------------------\n// 5. Audit Events ā SOC2 / FedRAMP / DoD ATO compliance\n// ---------------------------------------------------------------------------\n\n/**\n * Emit a structured ARTIFACT_SIGNATURE_FAIL audit event to stderr.\n *\n * Line prefix allows log shippers (FluentBit, syslog, CloudWatch, Splunk)\n * to route events via simple string filter before JSON parsing.\n */\nexport function emitSignatureAuditEvent(params: SignatureAuditEvent): void {\n const record = JSON.stringify({\n level: 'AUDIT',\n event: 'ARTIFACT_SIGNATURE_FAIL',\n timestamp: params.timestamp,\n source: params.source,\n artifactFilename: params.artifactFilename,\n expectedDigest: params.expectedDigest,\n actualDigest: params.actualDigest,\n phase: params.phase,\n });\n process.stderr.write(`ARTIFACT_SIGNATURE_FAIL ${record}\\n`);\n}\n\n// ---------------------------------------------------------------------------\n// 6. MCP Tool Registration\n// ---------------------------------------------------------------------------\n\n/** Per-artifact verification result returned by the MCP tool. */\nexport interface ArtifactVerificationResult {\n filename: string;\n verified: boolean;\n error?: string;\n signedBy?: string;\n signedAt?: string;\n}\n\n/** Register artifact signing verification tool on the MCP server. */\nexport function registerArtifactSigningTools(server: McpServer): void {\n server.tool(\n 'stackwright_pro_verify_artifact_signatures',\n 'Verify ECDSA P-384 signatures for all pipeline artifacts in .stackwright/artifacts/. ' +\n 'Auto-discovers keys from .stackwright/pipeline-keys.json. ' +\n 'Returns per-artifact verification status.',\n {\n cwd: z.string().optional().describe('Project root directory. Defaults to process.cwd().'),\n },\n async ({ cwd: cwdParam }) => {\n const cwd = cwdParam ?? process.cwd();\n\n // 1. Load pipeline keys\n let publicKey: KeyObject;\n try {\n const keys = loadPipelineKeys(cwd);\n publicKey = keys.publicKey;\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify({\n error: true,\n message: `Cannot load pipeline keys: ${msg}`,\n }),\n },\n ],\n isError: true,\n };\n }\n\n // 2. Load signature manifest\n let manifest: SignatureManifest;\n try {\n manifest = loadSignatureManifest(cwd);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify({\n error: true,\n message: `Cannot load signature manifest: ${msg}`,\n }),\n },\n ],\n isError: true,\n };\n }\n\n // 3. Discover artifact files on disk\n const artifactsPath = join(cwd, ARTIFACTS_DIR);\n let artifactFiles: string[] = [];\n try {\n if (existsSync(artifactsPath)) {\n artifactFiles = readdirSync(artifactsPath).filter(\n (f) => f.endsWith('.json') && f !== SIGNATURE_MANIFEST\n );\n }\n } catch {\n // If we can't read the directory, we'll report zero artifacts\n }\n\n // 4. Verify each artifact\n const results: ArtifactVerificationResult[] = [];\n let hasFailure = false;\n\n for (const filename of artifactFiles) {\n const filePath = join(artifactsPath, filename);\n\n // Symlink guard\n try {\n rejectSymlink(filePath, `artifact ${filename}`);\n } catch {\n results.push({\n filename,\n verified: false,\n error: 'Refusing to verify symlink',\n });\n hasFailure = true;\n continue;\n }\n\n // Read artifact bytes\n let artifactBytes: Buffer;\n try {\n artifactBytes = readFileSync(filePath);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n results.push({\n filename,\n verified: false,\n error: `Cannot read artifact: ${msg}`,\n });\n hasFailure = true;\n continue;\n }\n\n // Look up signature in manifest\n const entry = manifest.signatures[filename];\n if (!entry) {\n results.push({\n filename,\n verified: false,\n error: 'No signature found in manifest',\n });\n hasFailure = true;\n continue;\n }\n\n // Verify\n const sig: ArtifactSignature = {\n digest: entry.digest,\n signature: entry.signature,\n algorithm: entry.algorithm,\n signedAt: entry.signedAt,\n };\n\n const verified = verifyArtifact(artifactBytes, sig, publicKey);\n\n if (!verified) {\n const actualDigest = computeSha384(artifactBytes);\n emitSignatureAuditEvent({\n artifactFilename: filename,\n expectedDigest: sig.digest,\n actualDigest,\n phase: entry.signedBy ?? 'unknown',\n timestamp: new Date().toISOString(),\n source: 'stackwright_pro_verify_artifact_signatures',\n });\n\n results.push({\n filename,\n verified: false,\n error: `Signature verification failed ā artifact may have been tampered with`,\n signedBy: entry.signedBy,\n signedAt: entry.signedAt,\n });\n hasFailure = true;\n } else {\n results.push({\n filename,\n verified: true,\n signedBy: entry.signedBy,\n signedAt: entry.signedAt,\n });\n }\n }\n\n // 5. Report artifacts in manifest that are missing from disk\n for (const manifestFilename of Object.keys(manifest.signatures)) {\n if (!artifactFiles.includes(manifestFilename)) {\n results.push({\n filename: manifestFilename,\n verified: false,\n error: 'Artifact referenced in manifest but missing from disk',\n });\n hasFailure = true;\n }\n }\n\n const verifiedCount = results.filter((r) => r.verified).length;\n const failedCount = results.filter((r) => !r.verified).length;\n\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify({\n totalArtifacts: artifactFiles.length,\n verifiedCount,\n failedCount,\n results,\n ...(hasFailure\n ? {\n error:\n 'SIGNATURE VERIFICATION FAILED: One or more artifact signatures are invalid. ' +\n 'Do not proceed ā artifacts may have been tampered with.',\n }\n : {}),\n }),\n },\n ],\n isError: hasFailure,\n };\n }\n );\n}\n","/**\n * Safe Write ā Deterministic File-Write Guard\n *\n * The controlled I/O chokepoint for ALL file writes from specialist otters.\n * Every write goes through per-otter path allowlists. The LLM cannot write\n * to arbitrary filesystem paths.\n *\n * Why this matters: defense/regulated industry customers need guarantees that\n * \"the LLM cannot decide what to read and write from anywhere on your filesystem.\"\n */\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { boolCoerce } from '../coerce.js';\nimport { writeFileSync, existsSync, mkdirSync, lstatSync } from 'fs';\nimport { normalize, isAbsolute, dirname, join } from 'path';\n\n// ---------------------------------------------------------------------------\n// Per-otter path allowlists\n// ---------------------------------------------------------------------------\n\n/**\n * Allowlists define which file patterns each otter is permitted to write.\n * Paths are relative to the project root (cwd).\n * Patterns use simple prefix + suffix matching (no regex ā deterministic and auditable).\n */\ninterface PathAllowRule {\n /** Path prefix the file must start with (relative to project root) */\n prefix: string;\n /** File suffix/extension the file must end with */\n suffix: string;\n /** Human-readable description for audit logs */\n description: string;\n}\n\nconst OTTER_WRITE_ALLOWLISTS: Record<string, PathAllowRule[]> = {\n 'stackwright-pro-designer-otter': [\n { prefix: '.stackwright/artifacts/', suffix: '.json', description: 'Design language artifact' },\n ],\n 'stackwright-pro-theme-otter': [\n { prefix: '.stackwright/artifacts/', suffix: '.json', description: 'Theme tokens artifact' },\n ],\n 'stackwright-pro-auth-otter': [\n { prefix: '.stackwright/artifacts/', suffix: '.json', description: 'Auth config artifact' },\n { prefix: 'config/', suffix: '.yml', description: 'Auth YAML config' },\n { prefix: 'config/', suffix: '.yaml', description: 'Auth YAML config' },\n {\n prefix: '.env',\n suffix: '',\n description: 'Dotenv files (.env, .env.local, .env.production, etc.)',\n },\n ],\n 'stackwright-pro-data-otter': [\n { prefix: '.stackwright/artifacts/', suffix: '.json', description: 'Data config artifact' },\n { prefix: 'stackwright.yml', suffix: '', description: 'Stackwright config' },\n ],\n 'stackwright-pro-page-otter': [\n { prefix: 'pages/', suffix: '/content.yml', description: 'Page content YAML' },\n { prefix: 'pages/', suffix: '/content.yaml', description: 'Page content YAML' },\n { prefix: '.stackwright/artifacts/', suffix: '.json', description: 'Pages manifest' },\n ],\n 'stackwright-pro-dashboard-otter': [\n { prefix: 'pages/', suffix: '/content.yml', description: 'Dashboard content YAML' },\n { prefix: 'pages/', suffix: '/content.yaml', description: 'Dashboard content YAML' },\n { prefix: '.stackwright/artifacts/', suffix: '.json', description: 'Dashboard manifest' },\n ],\n 'stackwright-pro-workflow-otter': [\n { prefix: 'workflows/', suffix: '.yml', description: 'Workflow definition' },\n { prefix: 'workflows/', suffix: '.yaml', description: 'Workflow definition' },\n { prefix: '.stackwright/artifacts/', suffix: '.json', description: 'Workflow config' },\n ],\n 'stackwright-pro-api-otter': [\n { prefix: '.stackwright/artifacts/', suffix: '.json', description: 'API config artifact' },\n ],\n};\n\n// ---------------------------------------------------------------------------\n// Protected paths ā managed by other sink tools, never written here\n// ---------------------------------------------------------------------------\n\nconst PROTECTED_PATH_PREFIXES = [\n '.stackwright/pipeline-state.json',\n '.stackwright/pipeline-keys.json', // ephemeral signing keys\n '.stackwright/artifacts/signatures.json', // artifact signature manifest\n '.stackwright/questions/',\n '.stackwright/answers/',\n];\n\n// ---------------------------------------------------------------------------\n// Per-file-type content size limits (defense-in-depth: disk exhaustion vector)\n// Mirrors MAX_OTTER_BYTES in integrity.ts ā different thresholds per content type.\n// Exported for test assertions; callers cannot negotiate around these limits.\n// ---------------------------------------------------------------------------\n\n/** 512 KB ā JSON artifacts (.stackwright/artifacts/*.json) */\nexport const MAX_SAFE_WRITE_BYTES_JSON = 512 * 1024;\n\n/** 256 KB ā YAML content files (pages, workflows, config) */\nexport const MAX_SAFE_WRITE_BYTES_YAML = 256 * 1024;\n\n/** 4 KB ā dotenv files (.env, .env.local, .env.production) */\nexport const MAX_SAFE_WRITE_BYTES_ENV = 4 * 1024;\n\n/** 256 KB ā fallback for any unrecognized extension */\nexport const MAX_SAFE_WRITE_BYTES_DEFAULT = 256 * 1024;\n\n/**\n * Resolve the maximum allowed byte size for a given file path.\n * Exported for testing ā not for callers to negotiate around.\n */\nexport function getMaxBytesForPath(filePath: string): { limit: number; label: string } {\n if (filePath.endsWith('.json')) return { limit: MAX_SAFE_WRITE_BYTES_JSON, label: 'JSON' };\n if (filePath.endsWith('.yml') || filePath.endsWith('.yaml'))\n return { limit: MAX_SAFE_WRITE_BYTES_YAML, label: 'YAML' };\n if (filePath === '.env' || /^\\.env\\.[a-zA-Z0-9]+/.test(filePath))\n return { limit: MAX_SAFE_WRITE_BYTES_ENV, label: 'env' };\n return { limit: MAX_SAFE_WRITE_BYTES_DEFAULT, label: 'default' };\n}\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface SafeWriteInput {\n callerOtter: string;\n filePath: string;\n content: string;\n createDirectories?: boolean;\n _cwd?: string;\n}\n\ninterface SafeWriteSuccess {\n success: true;\n path: string;\n bytesWritten: number;\n allowRule: string;\n}\n\ninterface SafeWriteRejection {\n success: false;\n error: string;\n callerOtter: string;\n attemptedPath: string;\n allowedPaths: string[];\n}\n\n// ---------------------------------------------------------------------------\n// Core security logic ā exported for testing\n// ---------------------------------------------------------------------------\n\nexport function checkPathAllowed(\n callerOtter: string,\n filePath: string\n): { allowed: boolean; rule?: string; error?: string } {\n // 1. Normalize the path ā reject path traversal\n const normalized = normalize(filePath);\n if (normalized.includes('..')) {\n return { allowed: false, error: 'Path traversal detected: \"..\" segments are not allowed' };\n }\n\n // 2. Reject absolute paths\n if (isAbsolute(normalized)) {\n return {\n allowed: false,\n error: 'Absolute paths are not allowed ā use paths relative to project root',\n };\n }\n\n // 3. Foreman never writes directly\n if (callerOtter === 'stackwright-pro-foreman-otter') {\n return {\n allowed: false,\n error: 'The foreman otter coordinates ā it does not write files directly',\n };\n }\n\n // 4. Check caller is known\n const allowlist = OTTER_WRITE_ALLOWLISTS[callerOtter];\n if (!allowlist) {\n return {\n allowed: false,\n error: `Unknown otter: \"${callerOtter}\" is not in the write allowlist`,\n };\n }\n\n // 5. Reject protected paths (managed by other sink tools)\n for (const protectedPrefix of PROTECTED_PATH_PREFIXES) {\n if (normalized === protectedPrefix || normalized.startsWith(protectedPrefix)) {\n return {\n allowed: false,\n error: `Path \"${normalized}\" is managed by dedicated sink tools, not safe_write`,\n };\n }\n }\n\n // 6. Check path matches at least one allowlist rule\n for (const rule of allowlist) {\n const prefixMatch = normalized.startsWith(rule.prefix);\n const suffixMatch = rule.suffix === '' || normalized.endsWith(rule.suffix);\n if (prefixMatch && suffixMatch) {\n // For .env rules, enforce strict dotenv filename pattern\n // Only allow: .env, .env.local, .env.development, .env.production, .env.test, etc.\n // Reject: .envrc, .env.sh, .environment/, .envoy.yaml\n if (rule.prefix === '.env' && rule.suffix === '') {\n if (!/^\\.env(\\.[a-zA-Z0-9]{3,})*$/.test(normalized)) {\n continue; // this rule doesn't match, try next\n }\n }\n return { allowed: true, rule: rule.description };\n }\n }\n\n return {\n allowed: false,\n error: `Path \"${normalized}\" does not match any allowed write pattern for ${callerOtter}`,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Content validation helpers\n// ---------------------------------------------------------------------------\n\nfunction validateJsonContent(content: string): string | null {\n try {\n JSON.parse(content);\n return null;\n } catch (err) {\n return `Invalid JSON: ${err instanceof Error ? err.message : String(err)}`;\n }\n}\n\nfunction validateYamlContent(content: string): string | null {\n const trimmed = content.trimStart();\n\n // Entity expansion DoS check ā reject deeply nested anchor references\n // Pattern: &anchor followed by [*anchor] repeated many times\n // 20+ occurrences of any [*name] pattern indicates potential entity expansion attack\n const anchorRefPattern = /\\[(\\*[\\w]+)\\]/g;\n const matches = [...content.matchAll(anchorRefPattern)];\n if (matches.length >= 20) {\n return 'YAML entity expansion pattern detected ā too many anchor references';\n }\n\n // Also check for repeated identical anchor refs (exponential expansion)\n const anchorDefPattern = /&([\\w]+)/g;\n const defs = [...content.matchAll(anchorDefPattern)];\n if (defs.length >= 10) {\n // Check for exponential pattern: &a [*a *a *a...]\n const anchorNameCounts = new Map<string, number>();\n for (const [, name] of defs) {\n const count = (anchorNameCounts.get(name) ?? 0) + 1;\n anchorNameCounts.set(name, count);\n if (count >= 10) {\n return 'YAML entity expansion: repeated anchor definitions detected';\n }\n }\n }\n\n if (trimmed.startsWith('import ') || trimmed.startsWith('import{')) {\n return 'Content starts with \"import\" ā this looks like code, not YAML';\n }\n if (trimmed.startsWith('export ') || trimmed.startsWith('export{')) {\n return 'Content starts with \"export\" ā this looks like code, not YAML';\n }\n if (trimmed.startsWith('#!'))\n return 'Content starts with shebang ā this looks like a script, not YAML';\n if (/!!(?:python|ruby|perl|js|java)/i.test(content))\n return 'YAML deserialization attack tags detected';\n if (trimmed.startsWith('<') && !trimmed.startsWith('<<'))\n return 'Content looks like markup, not YAML';\n return null;\n}\n\nfunction validateEnvContent(content: string): string | null {\n const lines = content.split('\\n');\n for (let i = 0; i < lines.length; i++) {\n const raw = lines[i];\n if (raw === undefined) continue;\n const line = raw.trim();\n // Allow empty lines, comments, and key=value pairs\n if (line === '' || line.startsWith('#')) continue;\n if (!/^[A-Za-z_][A-Za-z0-9_]*=/.test(line)) {\n return `Line ${i + 1} is not a valid env entry (expected KEY=value): \"${line}\"`;\n }\n }\n return null;\n}\n\nfunction validateContent(filePath: string, content: string): string | null {\n if (filePath.endsWith('.json')) return validateJsonContent(content);\n if (filePath.endsWith('.yml') || filePath.endsWith('.yaml')) return validateYamlContent(content);\n if (filePath === '.env' || filePath.startsWith('.env')) return validateEnvContent(content);\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Handler (exported for direct testing ā no MCP server needed)\n// ---------------------------------------------------------------------------\n\nexport function handleSafeWrite(input: SafeWriteInput): { text: string; isError: boolean } {\n const cwd = input._cwd ?? process.cwd();\n const { callerOtter, filePath, content, createDirectories = true } = input;\n\n // 1. Path allowlist check\n const check = checkPathAllowed(callerOtter, filePath);\n if (!check.allowed) {\n const allowlist = OTTER_WRITE_ALLOWLISTS[callerOtter] ?? [];\n const allowedPaths = allowlist.map((r) => `${r.prefix}*${r.suffix} (${r.description})`);\n const result: SafeWriteRejection = {\n success: false,\n error: check.error ?? 'Path not allowed',\n callerOtter,\n attemptedPath: filePath,\n allowedPaths,\n };\n return { text: JSON.stringify(result), isError: true };\n }\n\n // 2. Content size limit check (defense-in-depth: disk exhaustion vector)\n const contentBytes = Buffer.byteLength(content, 'utf-8');\n const { limit: maxBytes, label: fileTypeLabel } = getMaxBytesForPath(filePath);\n if (contentBytes > maxBytes) {\n const result: SafeWriteRejection = {\n success: false,\n error: `Content size ${contentBytes} bytes exceeds ${fileTypeLabel} limit of ${maxBytes} bytes (${maxBytes / 1024} KB)`,\n callerOtter,\n attemptedPath: filePath,\n allowedPaths: [],\n };\n return { text: JSON.stringify(result), isError: true };\n }\n\n const normalized = normalize(filePath);\n const fullPath = join(cwd, normalized);\n\n // 3. Reject symlinks at target\n if (existsSync(fullPath)) {\n try {\n const stat = lstatSync(fullPath);\n if (stat.isSymbolicLink()) {\n const result: SafeWriteRejection = {\n success: false,\n error: 'Target path is a symlink ā refusing to write through symlinks for security',\n callerOtter,\n attemptedPath: filePath,\n allowedPaths: [],\n };\n return { text: JSON.stringify(result), isError: true };\n }\n } catch {\n // lstat failed ā file might have been removed between exists check and lstat, proceed\n }\n }\n\n // 4. Content validation\n const contentError = validateContent(normalized, content);\n if (contentError) {\n const result: SafeWriteRejection = {\n success: false,\n error: `Content validation failed: ${contentError}`,\n callerOtter,\n attemptedPath: filePath,\n allowedPaths: [],\n };\n return { text: JSON.stringify(result), isError: true };\n }\n\n // 5. Write the file\n try {\n if (createDirectories) {\n mkdirSync(dirname(fullPath), { recursive: true });\n }\n\n writeFileSync(fullPath, content, { encoding: 'utf-8' });\n\n const result: SafeWriteSuccess = {\n success: true,\n path: normalized,\n bytesWritten: Buffer.byteLength(content, 'utf-8'),\n allowRule: check.rule ?? 'unknown',\n };\n return { text: JSON.stringify(result), isError: false };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n const result: SafeWriteRejection = {\n success: false,\n error: `Write failed: ${message}`,\n callerOtter,\n attemptedPath: filePath,\n allowedPaths: [],\n };\n return { text: JSON.stringify(result), isError: true };\n }\n}\n\n// ---------------------------------------------------------------------------\n// MCP tool registration\n// ---------------------------------------------------------------------------\n\nexport function registerSafeWriteTools(server: McpServer): void {\n const DESC =\n 'Controlled file-write chokepoint. Every write from specialist otters goes through this tool with per-otter path allowlists. The LLM cannot write to arbitrary filesystem paths.';\n\n server.tool(\n 'stackwright_pro_safe_write',\n DESC,\n {\n callerOtter: z\n .string()\n .describe('The otter agent name requesting the write, e.g. \"stackwright-pro-page-otter\"'),\n filePath: z\n .string()\n .describe('Relative path from project root, e.g. \"pages/dashboard/content.yml\"'),\n content: z.string().describe('File content to write'),\n createDirectories: boolCoerce(z.boolean().optional().default(true)).describe(\n \"Create parent directories if they don't exist. Default: true\"\n ),\n },\n async ({ callerOtter, filePath, content, createDirectories }) => {\n const result = handleSafeWrite({\n callerOtter,\n filePath,\n content,\n ...(createDirectories != null ? { createDirectories } : {}),\n });\n return { content: [{ type: 'text' as const, text: result.text }], isError: result.isError };\n }\n );\n}\n","/**\n * Auth MCP Tools\n *\n * Implements stackwright_pro_configure_auth ā the tool that the auth-otter\n * has referenced since day one but that was never built. Its absence meant the\n * auth-otter would fall back to writing middleware.ts directly, bypassing the\n * TOOL GUARD that was supposed to prevent exactly that.\n *\n * For CAC/PKI: generated middleware.ts carries an explicit SECURITY REVIEW\n * REQUIRED comment. Certificate chain validation must be verified by a\n * security officer before production deployment on DoD systems.\n */\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { readFileSync, writeFileSync, existsSync } from 'fs';\nimport { join } from 'path';\nimport { jsonCoerce, boolCoerce, numCoerce } from '../coerce.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface ConfigureAuthParams {\n method: 'cac' | 'oidc' | 'oauth2' | 'none';\n provider?: 'azure-ad' | 'okta' | 'ping' | 'cognito' | 'custom';\n // CAC\n cacCaBundle?: string;\n cacEdipiLookup?: string;\n cacOcspEndpoint?: string;\n cacCertHeader?: string;\n // OIDC\n oidcDiscoveryUrl?: string;\n oidcClientId?: string;\n oidcClientSecret?: string;\n oidcScopes?: string;\n oidcRoleClaim?: string;\n // OAuth2\n oauth2AuthUrl?: string;\n oauth2TokenUrl?: string;\n oauth2ClientId?: string;\n oauth2ClientSecret?: string;\n oauth2Scopes?: string;\n // RBAC\n rbacRoles?: string[];\n rbacDefaultRole?: string;\n // Audit\n auditEnabled?: boolean;\n auditRetentionDays?: number;\n // Routes\n protectedRoutes?: string[];\n // Injection for tests\n _cwd?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction buildHierarchy(roles: string[]): Record<string, string[]> {\n const h: Record<string, string[]> = {};\n for (let i = 0; i < roles.length - 1; i++) {\n h[roles[i]!] = roles.slice(i + 1);\n }\n return h;\n}\n\nfunction hierarchyToYaml(hierarchy: Record<string, string[]>, indent: string): string {\n const entries = Object.entries(hierarchy);\n if (entries.length === 0) return `${indent}{}`;\n return entries.map(([role, subs]) => `${indent}${role}: [${subs.join(', ')}]`).join('\\n');\n}\n\nfunction rolesToYaml(roles: string[], indent: string): string {\n return roles.map((r) => `${indent}- ${r}`).join('\\n');\n}\n\nfunction routesToYaml(routes: string[], defaultRole: string, indent: string): string {\n return routes\n .map((r) => `${indent}- pattern: ${r}\\n${indent} requiredRole: ${defaultRole}`)\n .join('\\n');\n}\n\n/** Replace or append the auth: block in existing YAML content. */\nfunction upsertAuthBlock(existing: string, authYaml: string): string {\n const lines = existing.split('\\n');\n let authStart = -1;\n let authEnd = lines.length;\n\n for (let i = 0; i < lines.length; i++) {\n if (/^auth:/.test(lines[i]!)) {\n authStart = i;\n } else if (\n authStart >= 0 &&\n i > authStart &&\n /^\\S/.test(lines[i]!) &&\n lines[i]!.trim() !== ''\n ) {\n authEnd = i;\n break;\n }\n }\n\n if (authStart < 0) {\n // No existing auth block ā append\n return existing.trimEnd() + '\\n' + authYaml + '\\n';\n }\n\n // Replace auth block\n const before = lines.slice(0, authStart);\n const after = lines.slice(authEnd);\n return [...before, ...authYaml.trimEnd().split('\\n'), ...(after.length ? after : [])].join('\\n');\n}\n\n// ---------------------------------------------------------------------------\n// Content generators\n// ---------------------------------------------------------------------------\n\nfunction generateMiddlewareContent(\n method: string,\n params: ConfigureAuthParams,\n roles: string[],\n defaultRole: string,\n hierarchy: Record<string, string[]>,\n auditEnabled: boolean,\n auditRetentionDays: number,\n protectedRoutes: string[]\n): string {\n const rbacBlock = ` rbac: {\n roles: ${JSON.stringify(roles)},\n defaultRole: '${defaultRole}',\n hierarchy: ${JSON.stringify(hierarchy, null, 4)},\n },`;\n const auditBlock = ` audit: {\n enabled: ${auditEnabled},\n retentionDays: ${auditRetentionDays},\n },`;\n const routesBlock = ` protectedRoutes: ${JSON.stringify(protectedRoutes)},`;\n const configBlock = `export const config = {\n matcher: ${JSON.stringify(protectedRoutes)},\n};`;\n\n if (method === 'cac') {\n const caBundle = params.cacCaBundle ?? './certs/dod-ca-bundle.pem';\n const edipiLookup = params.cacEdipiLookup ?? './config/edipi-lookup.json';\n const ocspEndpoint = params.cacOcspEndpoint ?? 'https://ocsp.disa.mil';\n const certHeader = params.cacCertHeader ?? 'X-SSL-Client-Cert';\n return `// middleware.ts ā generated by @stackwright-pro/auth\n// ā ļø SECURITY REVIEW REQUIRED ā CAC/PKI certificate validation\n// DoD security officer review required before production deployment.\n// Verify: CA bundle completeness, EDIPI lookup endpoint, OCSP accessibility.\nimport { createProMiddleware } from '@stackwright-pro/auth-nextjs';\n\nexport const middleware = createProMiddleware({\n method: 'cac',\n cac: {\n caBundle: process.env.CAC_CA_BUNDLE ?? '${caBundle}',\n edipiLookup: '${edipiLookup}',\n ocspEndpoint: process.env.CAC_OCSP_ENDPOINT ?? '${ocspEndpoint}',\n certHeader: '${certHeader}',\n },\n${rbacBlock}\n${auditBlock}\n${routesBlock}\n});\n\n${configBlock}\n`;\n }\n\n if (method === 'oidc') {\n const scopes = params.oidcScopes ?? 'openid profile email';\n const roleClaim = params.oidcRoleClaim ?? 'roles';\n return `// middleware.ts ā generated by @stackwright-pro/auth-nextjs\nimport { createProMiddleware } from '@stackwright-pro/auth-nextjs';\n\nexport const middleware = createProMiddleware({\n method: 'oidc',\n oidc: {\n discoveryUrl: process.env.OIDC_DISCOVERY_URL!,\n clientId: process.env.OIDC_CLIENT_ID!,\n clientSecret: process.env.OIDC_CLIENT_SECRET!,\n scopes: '${scopes}',\n roleClaim: '${roleClaim}',\n },\n${rbacBlock}\n${auditBlock}\n${routesBlock}\n});\n\n${configBlock}\n`;\n }\n\n // oauth2\n const scopes = params.oauth2Scopes ?? 'read write';\n return `// middleware.ts ā generated by @stackwright-pro/auth-nextjs\nimport { createProMiddleware } from '@stackwright-pro/auth-nextjs';\n\nexport const middleware = createProMiddleware({\n method: 'oauth2',\n oauth2: {\n authorizationUrl: process.env.OAUTH2_AUTH_URL!,\n tokenUrl: process.env.OAUTH2_TOKEN_URL!,\n clientId: process.env.OAUTH2_CLIENT_ID!,\n clientSecret: process.env.OAUTH2_CLIENT_SECRET!,\n scopes: '${scopes}',\n },\n${rbacBlock}\n${auditBlock}\n${routesBlock}\n});\n\n${configBlock}\n`;\n}\n\nfunction generateEnvBlock(method: string, params: ConfigureAuthParams): string {\n if (method === 'cac') {\n return `# Authentication (CAC/PKI ā DoD)\n# ā ļø SECURITY REVIEW REQUIRED before production deployment\nCAC_CA_BUNDLE=./certs/dod-ca-bundle.pem\nCAC_OCSP_ENDPOINT=https://ocsp.disa.mil\n`;\n }\n\n if (method === 'oidc') {\n const label = params.provider ?? 'OIDC';\n const discoveryUrl =\n params.oidcDiscoveryUrl ?? 'https://your-provider/.well-known/openid-configuration';\n return `# Authentication (OIDC ā ${label})\nOIDC_DISCOVERY_URL=${discoveryUrl}\nOIDC_CLIENT_ID=your-client-id\nOIDC_CLIENT_SECRET=your-client-secret\n`;\n }\n\n // oauth2\n const authUrl = params.oauth2AuthUrl ?? 'https://your-auth-server/authorize';\n const tokenUrl = params.oauth2TokenUrl ?? 'https://your-auth-server/token';\n return `# Authentication (OAuth2)\nOAUTH2_AUTH_URL=${authUrl}\nOAUTH2_TOKEN_URL=${tokenUrl}\nOAUTH2_CLIENT_ID=your-client-id\nOAUTH2_CLIENT_SECRET=your-client-secret\n`;\n}\n\nfunction generateYamlBlock(\n method: string,\n params: ConfigureAuthParams,\n roles: string[],\n defaultRole: string,\n hierarchy: Record<string, string[]>,\n auditEnabled: boolean,\n auditRetentionDays: number,\n protectedRoutes: string[]\n): string {\n const rbacSection = ` rbac:\n roles:\n${rolesToYaml(roles, ' ')}\n defaultRole: ${defaultRole}\n hierarchy:\n${hierarchyToYaml(hierarchy, ' ')}`;\n\n const auditSection = ` audit:\n enabled: ${auditEnabled}\n retentionDays: ${auditRetentionDays}`;\n\n const routesSection = ` protectedRoutes:\n${routesToYaml(protectedRoutes, ' ', defaultRole)}`.replace(/\\n\\s+,/g, '');\n\n // Re-do routesSection cleanly:\n const routeLines = protectedRoutes\n .map((r) => ` - pattern: ${r}\\n requiredRole: ${defaultRole}`)\n .join('\\n');\n\n const providerLine = params.provider ? ` provider: ${params.provider}\\n` : '';\n\n if (method === 'cac') {\n const caBundle = params.cacCaBundle ?? './certs/dod-ca-bundle.pem';\n const edipiLookup = params.cacEdipiLookup ?? './config/edipi-lookup.json';\n const ocspEndpoint = params.cacOcspEndpoint ?? 'https://ocsp.disa.mil';\n const certHeader = params.cacCertHeader ?? 'X-SSL-Client-Cert';\n return `auth:\n method: cac\n${providerLine} middleware: ./middleware.ts\n cac:\n caBundle: \\${CAC_CA_BUNDLE}\n edipiLookup: ${edipiLookup}\n ocspEndpoint: \\${CAC_OCSP_ENDPOINT}\n certHeader: ${certHeader}\n${rbacSection}\n protectedRoutes:\n${routeLines}\n${auditSection}\n`;\n }\n\n if (method === 'oidc') {\n const scopes = params.oidcScopes ?? 'openid profile email';\n const roleClaim = params.oidcRoleClaim ?? 'roles';\n return `auth:\n method: oidc\n${providerLine} middleware: ./middleware.ts\n oidc:\n discoveryUrl: \\${OIDC_DISCOVERY_URL}\n clientId: \\${OIDC_CLIENT_ID}\n clientSecret: \\${OIDC_CLIENT_SECRET}\n scopes: ${scopes}\n roleClaim: ${roleClaim}\n${rbacSection}\n protectedRoutes:\n${routeLines}\n${auditSection}\n`;\n }\n\n // oauth2\n const scopes = params.oauth2Scopes ?? 'read write';\n return `auth:\n method: oauth2\n${providerLine} middleware: ./middleware.ts\n oauth2:\n authorizationUrl: \\${OAUTH2_AUTH_URL}\n tokenUrl: \\${OAUTH2_TOKEN_URL}\n clientId: \\${OAUTH2_CLIENT_ID}\n clientSecret: \\${OAUTH2_CLIENT_SECRET}\n scopes: ${scopes}\n${rbacSection}\n protectedRoutes:\n${routeLines}\n${auditSection}\n`;\n}\n\n// ---------------------------------------------------------------------------\n// Exported handler (called directly in tests ā no MCP server spin-up needed)\n// ---------------------------------------------------------------------------\n\nexport async function configureAuthHandler(\n params: ConfigureAuthParams,\n cwd: string\n): Promise<{ content: Array<{ type: 'text'; text: string }>; isError?: boolean }> {\n const {\n method,\n provider,\n rbacRoles = ['SUPER_ADMIN', 'ADMIN', 'ANALYST'],\n auditEnabled = true,\n auditRetentionDays = 90,\n protectedRoutes = ['/dashboard/:path*'],\n } = params;\n\n const roles = rbacRoles;\n const defaultRole = params.rbacDefaultRole ?? roles[roles.length - 1]!;\n const hierarchy = buildHierarchy(roles);\n\n // āā Short-circuit for method: none āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n if (method === 'none') {\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify({\n success: true,\n method: 'none',\n provider: null,\n rbacRoles: roles,\n rbacDefaultRole: defaultRole,\n protectedRoutesCount: protectedRoutes.length,\n filesWritten: [],\n securityWarning: null,\n }),\n },\n ],\n };\n }\n\n const filesWritten: string[] = [];\n\n try {\n // āā Step 2 ā middleware.ts āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n const middlewareContent = generateMiddlewareContent(\n method,\n params,\n roles,\n defaultRole,\n hierarchy,\n auditEnabled,\n auditRetentionDays,\n protectedRoutes\n );\n writeFileSync(join(cwd, 'middleware.ts'), middlewareContent, 'utf8');\n filesWritten.push('middleware.ts');\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify({ success: false, error: `Failed writing middleware.ts: ${msg}` }),\n },\n ],\n isError: true,\n };\n }\n\n try {\n // āā Step 3 ā .env.example āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n const envBlock = generateEnvBlock(method, params);\n const envPath = join(cwd, '.env.example');\n if (existsSync(envPath)) {\n const existing = readFileSync(envPath, 'utf8');\n writeFileSync(envPath, existing.trimEnd() + '\\n\\n' + envBlock, 'utf8');\n } else {\n writeFileSync(envPath, envBlock, 'utf8');\n }\n filesWritten.push('.env.example');\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify({ success: false, error: `Failed writing .env.example: ${msg}` }),\n },\n ],\n isError: true,\n };\n }\n\n try {\n // āā Step 4 ā stackwright.yml āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n const authYaml = generateYamlBlock(\n method,\n params,\n roles,\n defaultRole,\n hierarchy,\n auditEnabled,\n auditRetentionDays,\n protectedRoutes\n );\n const ymlPath = join(cwd, 'stackwright.yml');\n if (!existsSync(ymlPath)) {\n writeFileSync(ymlPath, authYaml, 'utf8');\n } else {\n const existing = readFileSync(ymlPath, 'utf8');\n writeFileSync(ymlPath, upsertAuthBlock(existing, authYaml), 'utf8');\n }\n filesWritten.push('stackwright.yml');\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify({ success: false, error: `Failed writing stackwright.yml: ${msg}` }),\n },\n ],\n isError: true,\n };\n }\n\n // āā Step 5 ā Return summary āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n const securityWarning =\n method === 'cac'\n ? 'SECURITY REVIEW REQUIRED ā CAC certificate chain must be verified before production deployment'\n : null;\n\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify({\n success: true,\n method,\n provider: provider ?? null,\n rbacRoles: roles,\n rbacDefaultRole: defaultRole,\n protectedRoutesCount: protectedRoutes.length,\n filesWritten,\n securityWarning,\n }),\n },\n ],\n };\n}\n\n// ---------------------------------------------------------------------------\n// MCP tool registration\n// ---------------------------------------------------------------------------\n\nexport function registerAuthTools(server: McpServer): void {\n server.tool(\n 'stackwright_pro_configure_auth',\n 'Generate authentication middleware and configuration for a Next.js Stackwright application. ' +\n 'Writes `middleware.ts` from a secure template, appends/updates the `auth:` section in `stackwright.yml`, ' +\n 'and generates `.env.example` with required environment variables. ' +\n 'ā ļø For CAC/PKI: generated `middleware.ts` carries a SECURITY REVIEW REQUIRED comment ā ' +\n 'certificate chain validation must be verified by a DoD security officer before production deployment. ' +\n 'This is the ONLY approved path to generating `middleware.ts`. Never write TypeScript auth files directly.',\n {\n method: z.enum(['cac', 'oidc', 'oauth2', 'none']),\n provider: z.enum(['azure-ad', 'okta', 'ping', 'cognito', 'custom']).optional(),\n // CAC\n cacCaBundle: z.string().optional(),\n cacEdipiLookup: z.string().optional(),\n cacOcspEndpoint: z.string().optional(),\n cacCertHeader: z.string().optional(),\n // OIDC\n oidcDiscoveryUrl: z.string().optional(),\n oidcClientId: z.string().optional(),\n oidcClientSecret: z.string().optional(),\n oidcScopes: z.string().optional(),\n oidcRoleClaim: z.string().optional(),\n // OAuth2\n oauth2AuthUrl: z.string().optional(),\n oauth2TokenUrl: z.string().optional(),\n oauth2ClientId: z.string().optional(),\n oauth2ClientSecret: z.string().optional(),\n oauth2Scopes: z.string().optional(),\n // RBAC\n rbacRoles: jsonCoerce(z.array(z.string()).optional()),\n rbacDefaultRole: z.string().optional(),\n // Audit\n auditEnabled: boolCoerce(z.boolean().optional()),\n auditRetentionDays: numCoerce(z.number().int().positive().optional()),\n // Routes\n protectedRoutes: jsonCoerce(z.array(z.string()).optional()),\n // Injection for tests\n _cwd: z.string().optional(),\n },\n async (params) => {\n const cwd = params._cwd ?? process.cwd();\n return configureAuthHandler(params, cwd);\n }\n );\n}\n","/**\n * Otter Integrity Verification\n * ============================\n * Protects the Pro Otter Raft from disk-based prompt injection / jailbreak attacks.\n *\n * TypeScript port of python/src/stackwright_pro/raft/integrity.py ā this lets\n * the MCP package verify otter files without a Python dependency.\n *\n * Certificate-pinned canonical checksums ā hardcoded in the MCP package.\n *\n * These are NOT read from disk. An attacker who modifies otter JSON files\n * in @stackwright-pro/otters cannot also modify these constants without\n * compromising the separately-published @stackwright-pro/mcp package.\n *\n * To update: node scripts/sync-mcp-checksums.cjs\n * (reads from packages/otters/src/checksums.json, writes this file)\n */\nimport { createHash, timingSafeEqual } from 'crypto';\nimport { readFileSync, readdirSync, lstatSync } from 'fs';\nimport { join, basename } from 'path';\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\n\n// ---------------------------------------------------------------------------\n// Certificate-pinned canonical checksums ā frozen Map, immutable by design.\n// DO NOT read these from disk ā that would defeat the entire purpose.\n// Object.freeze prevents property mutation at runtime; ReadonlyMap prevents\n// .set() / .delete() at compile time (belt-and-suspenders).\n// ---------------------------------------------------------------------------\n\nconst _checksums = new Map<string, string>([\n [\n 'stackwright-pro-api-otter.json',\n '9fbaed0ce6116b82d0289f24432037d04637c89b8e73062ed946e5d49b294734',\n ],\n [\n 'stackwright-pro-auth-otter.json',\n 'bf0e66e35d15ba818ba6ff1a007df34975565bacbb35cc0c80151fb1da13e573',\n ],\n [\n 'stackwright-pro-dashboard-otter.json',\n '89e81ac161147ab532034b40e4f7863dcd7d03ef33fd94c97d19c3e56fb91a9e',\n ],\n [\n 'stackwright-pro-data-otter.json',\n '3afe5acf749d41788803ceb41a2a1f1c7bc73350e9199d10be88dede0677804e',\n ],\n [\n 'stackwright-pro-designer-otter.json',\n 'af09ac8f06385bdbac63e2820daa2ff7d38b8ff1ff383c161f07e3fb9d9359c5',\n ],\n [\n 'stackwright-pro-foreman-otter.json',\n '582a26766a5bc80ef9f3aef53e82794c7f47f618bd28e4e70583bfc2b569398c',\n ],\n [\n 'stackwright-pro-page-otter.json',\n 'd971e1c76e05fc747ec59217832e1247b12c1824edac3adc0f3d125c59da9135',\n ],\n [\n 'stackwright-pro-theme-otter.json',\n 'cc9af32df65a049b27de41a6d25f66cd738201fcb8c5d08a312cdb868ba17cd7',\n ],\n [\n 'stackwright-pro-workflow-otter.json',\n 'c90d6773b2287aa9a640c2715ca0e75f44c13e99fddcfb89ced36603f38930ce',\n ],\n]);\nObject.freeze(_checksums);\nconst CANONICAL_CHECKSUMS: ReadonlyMap<string, string> = _checksums;\n\n// ---------------------------------------------------------------------------\n// Import-time format validation ā malformed constants are a packaging bug,\n// not a runtime surprise. Fail fast, fail loud.\n// ---------------------------------------------------------------------------\n\nconst SHA256_HEX_RE = /^[0-9a-f]{64}$/;\n\nfor (const [name, digest] of CANONICAL_CHECKSUMS) {\n if (!SHA256_HEX_RE.test(digest)) {\n throw new Error(\n `Malformed SHA-256 in CANONICAL_CHECKSUMS for \"${name}\": ` +\n `expected 64 hex chars, got ${digest.length}: \"${digest}\"`\n );\n }\n}\n\n// 1 MB ā generous headroom for agent definitions; anything larger is suspicious.\nconst MAX_OTTER_BYTES = 1 * 1024 * 1024;\n\n// ---------------------------------------------------------------------------\n// Core functions (exported for direct testing ā no MCP server needed)\n// ---------------------------------------------------------------------------\n\n/** Compute the hex-encoded SHA-256 digest of raw bytes. Pure, no I/O. */\nexport function computeSha256(data: Buffer): string {\n return createHash('sha256').update(data).digest('hex');\n}\n\n/** Constant-time comparison of two hex digest strings. */\nfunction safeEqual(a: string, b: string): boolean {\n if (a.length !== b.length) return false;\n return timingSafeEqual(Buffer.from(a, 'utf8'), Buffer.from(b, 'utf8'));\n}\n\n// ---------------------------------------------------------------------------\n// Single-file verification\n// ---------------------------------------------------------------------------\n\nexport interface VerifyOtterFileResult {\n verified: boolean;\n filename: string;\n error?: string;\n}\n\n/**\n * Read a single otter JSON file, check its size, compute its SHA-256,\n * and constant-time compare against the canonical checksum.\n *\n * Single read ā hash ā decode. No TOCTOU window.\n */\nexport function verifyOtterFile(filePath: string): VerifyOtterFileResult {\n const filename = basename(filePath);\n\n // Fast-fail on unknown filenames before any I/O\n const expected = CANONICAL_CHECKSUMS.get(filename);\n if (expected === undefined) {\n return { verified: false, filename, error: `Unknown otter file: not in canonical set` };\n }\n\n // Symlink guard ā refuse to follow symlinks (prevents symlink-based swaps)\n let stat: ReturnType<typeof lstatSync>;\n try {\n stat = lstatSync(filePath);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n return { verified: false, filename, error: `Cannot stat file: ${msg}` };\n }\n\n if (stat.isSymbolicLink()) {\n return { verified: false, filename, error: 'Refusing to verify symlink' };\n }\n\n // Stat-based size pre-check ā don't materialise oversized payloads\n const size = stat.size;\n\n if (size > MAX_OTTER_BYTES) {\n return {\n verified: false,\n filename,\n error: `File exceeds size limit (${MAX_OTTER_BYTES.toLocaleString()} bytes, got ${size.toLocaleString()})`,\n };\n }\n\n // Single read ā used for hashing and UTF-8 validation (zero TOCTOU window)\n let raw: Buffer;\n try {\n raw = readFileSync(filePath);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n return { verified: false, filename, error: `Cannot read file: ${msg}` };\n }\n\n // Belt-and-suspenders: re-check length after read in case of a race\n if (raw.length > MAX_OTTER_BYTES) {\n return {\n verified: false,\n filename,\n error: `File exceeds size limit after read (${MAX_OTTER_BYTES.toLocaleString()} bytes, got ${raw.length.toLocaleString()})`,\n };\n }\n\n // Hash the raw bytes\n const actual = computeSha256(raw);\n\n // Constant-time comparison prevents timing-oracle attacks\n if (!safeEqual(actual, expected)) {\n return {\n verified: false,\n filename,\n error: `SHA-256 mismatch: expected ${expected.substring(0, 8)}ā¦, got ${actual.substring(0, 8)}ā¦`,\n };\n }\n\n // UTF-8 validation ā binary injection guard\n try {\n const decoder = new TextDecoder('utf-8', { fatal: true });\n decoder.decode(raw);\n } catch {\n return {\n verified: false,\n filename,\n error: 'File is not valid UTF-8 ā may be corrupted or contain binary injection',\n };\n }\n\n return { verified: true, filename };\n}\n\n// ---------------------------------------------------------------------------\n// Directory-level verification\n// ---------------------------------------------------------------------------\n\nexport interface VerifyAllOttersResult {\n verified: string[];\n failed: Array<{ filename: string; error: string }>;\n unknown: string[];\n}\n\n/**\n * Scan a directory for `*-otter.json` files, verify each one against\n * canonical checksums. Returns lists of verified, failed, and unknown files.\n */\nexport function verifyAllOtters(otterDir: string): VerifyAllOttersResult {\n // ---------------------------------------------------------------------------\n // Path traversal guard ā reject any input containing \"..\" sequences before\n // any I/O. An attacker controlling this parameter could otherwise scan\n // directories outside the expected otter install locations.\n // ---------------------------------------------------------------------------\n if (/(?:^|[/\\\\])\\.\\.(?:[/\\\\]|$)/.test(otterDir) || otterDir.includes('..')) {\n return {\n verified: [],\n failed: [\n {\n filename: '<directory>',\n error: `Security: path traversal sequence detected in otter directory parameter`,\n },\n ],\n unknown: [],\n };\n }\n\n const verified: string[] = [];\n const failed: Array<{ filename: string; error: string }> = [];\n const unknown: string[] = [];\n\n let entries: string[];\n try {\n entries = readdirSync(otterDir);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n return {\n verified: [],\n failed: [{ filename: '<directory>', error: `Cannot read directory: ${msg}` }],\n unknown: [],\n };\n }\n\n const otterFiles = entries.filter((f) => f.endsWith('-otter.json'));\n\n for (const filename of otterFiles) {\n const filePath = join(otterDir, filename);\n\n // Skip symlinks at the directory-scan level too\n try {\n if (lstatSync(filePath).isSymbolicLink()) {\n failed.push({ filename, error: 'Skipped: symlink' });\n continue;\n }\n } catch {\n // verifyOtterFile will handle stat errors\n }\n\n const result = verifyOtterFile(filePath);\n\n if (result.verified) {\n verified.push(result.filename);\n } else if (result.error?.startsWith('Unknown otter file')) {\n unknown.push(result.filename);\n } else {\n failed.push({ filename: result.filename, error: result.error ?? 'Unknown error' });\n }\n }\n\n // Check for missing canonical files ā ones we expect but didn't find on disk\n for (const canonicalName of CANONICAL_CHECKSUMS.keys()) {\n if (!otterFiles.includes(canonicalName)) {\n failed.push({ filename: canonicalName, error: 'Missing from directory' });\n }\n }\n\n return { verified, failed, unknown };\n}\n\n// ---------------------------------------------------------------------------\n// Otter directory resolution\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_SEARCH_PATHS = ['node_modules/@stackwright-pro/otters/src/', 'packages/otters/src/'];\n\nfunction resolveOtterDir(): string | null {\n const cwd = process.cwd();\n for (const relative of DEFAULT_SEARCH_PATHS) {\n const candidate = join(cwd, relative);\n try {\n lstatSync(candidate);\n return candidate;\n } catch {\n // Not found, try next\n }\n }\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Audit stream ā SOC2 / FedRAMP / DoD ATO compliance\n// ---------------------------------------------------------------------------\n\n/**\n * Structured audit event parameters for an integrity failure.\n * Kept as a plain interface so callers can pass partial results without\n * constructing the full VerifyAllOttersResult.\n */\nexport interface IntegrityAuditEvent {\n otterDir: string;\n failed: Array<{ filename: string; error: string }>;\n unknown: string[];\n}\n\n/**\n * Emit a structured INTEGRITY_FAIL audit event to stderr.\n *\n * Writes a single line to process.stderr in the format:\n * INTEGRITY_FAIL {\"level\":\"AUDIT\",\"event\":\"INTEGRITY_FAIL\",...}\n *\n * The line prefix \"INTEGRITY_FAIL\" (without JSON) allows log shippers\n * (FluentBit, syslog, CloudWatch Logs, Splunk) to match and route the\n * event to a dedicated audit stream using a simple string filter, even\n * before attempting JSON parsing.\n *\n * Exported for unit testing. Do not call directly in production code ā\n * use registerIntegrityTools() which calls this automatically.\n */\nexport function emitIntegrityAuditEvent(params: IntegrityAuditEvent): void {\n const record = JSON.stringify({\n level: 'AUDIT',\n event: 'INTEGRITY_FAIL',\n timestamp: new Date().toISOString(),\n source: 'stackwright_pro_verify_otter_integrity',\n otterDir: params.otterDir,\n failedCount: params.failed.length,\n unknownCount: params.unknown.length,\n failures: params.failed,\n unknown: params.unknown,\n });\n process.stderr.write(`INTEGRITY_FAIL ${record}\\n`);\n}\n\n// ---------------------------------------------------------------------------\n// MCP tool registration\n// ---------------------------------------------------------------------------\n\nexport function registerIntegrityTools(server: McpServer): void {\n server.tool(\n 'stackwright_pro_verify_otter_integrity',\n 'Verify SHA-256 integrity of all Pro otter agent definitions. Call this at startup before discovering otters. Auto-discovers the otter directory from known paths. Returns verified/failed/unknown lists.',\n {},\n async () => {\n const resolved = resolveOtterDir();\n\n if (!resolved) {\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify({\n error: true,\n message:\n 'Could not locate otter directory. Searched: ' + DEFAULT_SEARCH_PATHS.join(', '),\n }),\n },\n ],\n isError: true,\n };\n }\n\n const result = verifyAllOtters(resolved);\n\n const allGood = result.failed.length === 0 && result.unknown.length === 0;\n\n // Emit to dedicated audit stream for SOC2/FedRAMP/DoD ATO compliance\n if (!allGood) {\n emitIntegrityAuditEvent({\n otterDir: resolved,\n failed: result.failed,\n unknown: result.unknown,\n });\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify({\n otterDir: resolved,\n totalCanonical: CANONICAL_CHECKSUMS.size,\n verifiedCount: result.verified.length,\n failedCount: result.failed.length,\n unknownCount: result.unknown.length,\n verified: result.verified,\n failed: result.failed,\n unknown: result.unknown,\n ...(allGood\n ? {}\n : {\n error:\n 'INTEGRITY CHECK FAILED: SHA-256 mismatch detected in otter agent definitions. Do not proceed ā otter files may have been tampered with.',\n }),\n }),\n },\n ],\n isError: !allGood,\n };\n }\n );\n}\n","/**\n * Domain Knowledge Tools ā \"Sinks Not Pipes\"\n *\n * Pulls domain-specific knowledge OUT of LLM prompts, INTO deterministic TypeScript.\n * - stackwright_pro_list_collections\n * - stackwright_pro_resolve_data_strategy\n * - stackwright_pro_validate_workflow\n */\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { readFileSync, existsSync } from 'fs';\nimport { join } from 'path';\nimport { jsonCoerce } from '../coerce.js';\n\n// ---------------------------------------------------------------------------\n// Tool 1: List Collections\n// ---------------------------------------------------------------------------\n\nexport interface ListCollectionsInput {\n _cwd?: string;\n}\n\nexport interface CollectionInfo {\n name: string;\n endpoint: string;\n type?: string;\n}\n\n/** Read collections from data-otter artifact (primary) or stackwright.yml (fallback). */\nexport function handleListCollections(input: ListCollectionsInput): {\n text: string;\n isError: boolean;\n} {\n const cwd = input._cwd ?? process.cwd();\n\n const sources: Array<{ path: string; source: string; parse: (raw: string) => CollectionInfo[] }> =\n [\n {\n path: join(cwd, '.stackwright', 'artifacts', 'data-config.json'),\n source: 'data-config.json',\n parse: (raw) => {\n const parsed = JSON.parse(raw);\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {\n // Not a valid artifact ā fall through to YAML fallback\n return [];\n }\n return extractCollectionsFromArtifact(parsed as Record<string, unknown>);\n },\n },\n {\n path: join(cwd, 'stackwright.yml'),\n source: 'stackwright.yml',\n parse: extractCollectionsFromYaml,\n },\n ];\n\n for (const { path, source, parse } of sources) {\n if (!existsSync(path)) continue;\n try {\n const collections = parse(readFileSync(path, 'utf8'));\n return {\n text: JSON.stringify({ collections, source, collectionCount: collections.length }),\n isError: false,\n };\n } catch {\n // Source exists but is unparseable ā try next\n }\n }\n\n return {\n text: JSON.stringify({\n collections: [],\n source: 'none',\n collectionCount: 0,\n hint: 'Run API Otter and Data Otter first',\n }),\n isError: false,\n };\n}\n\n/** Pull collections from the data-otter's JSON artifact. */\nfunction extractCollectionsFromArtifact(raw: Record<string, unknown>): CollectionInfo[] {\n const collections: CollectionInfo[] = [];\n const integrations = raw.integrations ?? raw.collections ?? [];\n if (!Array.isArray(integrations)) return collections;\n\n for (const item of integrations) {\n if (!item || typeof item !== 'object') continue;\n const obj = item as Record<string, unknown>;\n\n // Direct collection entry\n if (typeof obj.name === 'string' && typeof obj.endpoint === 'string') {\n collections.push(makeCollectionInfo(obj.name, obj.endpoint, obj.type));\n continue;\n }\n\n // Nested collections inside integration entry\n if (!Array.isArray(obj.collections)) continue;\n for (const col of obj.collections) {\n if (!col || typeof col !== 'object') continue;\n const c = col as Record<string, unknown>;\n if (typeof c.name === 'string' && typeof c.endpoint === 'string') {\n collections.push(makeCollectionInfo(c.name, c.endpoint, c.type ?? obj.type));\n }\n }\n }\n return collections;\n}\n\nfunction makeCollectionInfo(name: string, endpoint: string, type: unknown): CollectionInfo {\n return { name, endpoint, ...(typeof type === 'string' ? { type } : {}) };\n}\n\n/** Best-effort regex extraction from stackwright.yml integrations block. */\nfunction extractCollectionsFromYaml(yamlText: string): CollectionInfo[] {\n const collections: CollectionInfo[] = [];\n const lines = yamlText.split('\\n');\n\n let inIntegrations = false;\n let currentName: string | null = null;\n let currentEndpoint: string | null = null;\n let currentType: string | null = null;\n\n for (const line of lines) {\n if (line.length > 1000) continue; // Defense against ReDoS on pathological lines\n if (/^integrations:\\s*$/.test(line)) {\n inIntegrations = true;\n continue;\n }\n if (inIntegrations && /^[a-z]/.test(line) && !line.startsWith(' ')) {\n inIntegrations = false;\n }\n if (!inIntegrations) continue;\n\n const stripQuotes = (s: string) => s.trim().replace(/^['\"]|['\"]$/g, '');\n\n const typeMatch = line.match(/^\\s+type:\\s*(.+)$/);\n if (typeMatch?.[1]) currentType = stripQuotes(typeMatch[1]);\n\n const nameMatch = line.match(/^[\\s-]+name:\\s*(.+)$/);\n if (nameMatch?.[1]) {\n if (currentName && currentEndpoint) {\n collections.push(makeCollectionInfo(currentName, currentEndpoint, currentType));\n }\n currentName = stripQuotes(nameMatch[1]);\n currentEndpoint = null;\n }\n\n const endpointMatch = line.match(/^\\s+endpoint:\\s*(.+)$/);\n if (endpointMatch?.[1]) currentEndpoint = stripQuotes(endpointMatch[1]);\n }\n\n if (currentName && currentEndpoint) {\n collections.push(makeCollectionInfo(currentName, currentEndpoint, currentType));\n }\n return collections;\n}\n\n// ---------------------------------------------------------------------------\n// Tool 2: Resolve Data Strategy\n// ---------------------------------------------------------------------------\n\nexport interface DataStrategy {\n strategy: string;\n mechanism: string;\n mechanismPackage?: string;\n revalidateSeconds?: number;\n pulse: boolean;\n requiredPackages: Record<string, string>;\n handoffFlags: string[];\n description: string;\n}\n\nconst DATA_STRATEGIES: Record<string, DataStrategy> = {\n 'pulse-fast': {\n strategy: 'pulse-fast',\n mechanism: 'Client-side polling via @stackwright-pro/pulse',\n mechanismPackage: '@stackwright-pro/pulse',\n pulse: true,\n requiredPackages: { '@stackwright-pro/pulse': 'latest', '@tanstack/react-query': '^5.0.0' },\n handoffFlags: ['PULSE_MODE=true'],\n description:\n 'Real-time updates every few seconds. Uses client-side polling. Dashboard Otter should use *_pulse component variants.',\n },\n 'isr-fast': {\n strategy: 'isr-fast',\n mechanism: 'Next.js ISR',\n revalidateSeconds: 60,\n pulse: false,\n requiredPackages: {},\n handoffFlags: [],\n description:\n 'Near real-time with 60-second ISR revalidation. Good for dashboards that need minute-level freshness.',\n },\n 'isr-standard': {\n strategy: 'isr-standard',\n mechanism: 'Next.js ISR',\n revalidateSeconds: 3600,\n pulse: false,\n requiredPackages: {},\n handoffFlags: [],\n description: 'Standard hourly revalidation. Good for most API-backed pages.',\n },\n 'isr-slow': {\n strategy: 'isr-slow',\n mechanism: 'Next.js ISR',\n revalidateSeconds: 86400,\n pulse: false,\n requiredPackages: {},\n handoffFlags: [],\n description: 'Daily revalidation. Good for infrequently changing data.',\n },\n};\n\nexport interface ResolveDataStrategyInput {\n strategy: string;\n}\n\n/** Look up the data freshness strategy. Replaces the markdown table in the data-otter prompt. */\nexport function handleResolveDataStrategy(input: ResolveDataStrategyInput): {\n text: string;\n isError: boolean;\n} {\n const key = input.strategy.trim().toLowerCase();\n const match = DATA_STRATEGIES[key];\n\n if (!match) {\n const validKeys = Object.keys(DATA_STRATEGIES).join(', ');\n return {\n text: JSON.stringify({\n error: true,\n message: `Unknown strategy: \"${input.strategy}\". Valid strategies: ${validKeys}`,\n validStrategies: Object.keys(DATA_STRATEGIES),\n }),\n isError: true,\n };\n }\n\n // Hint: the exact tool call the otter should make next\n const configureIsrCall = match.pulse\n ? null\n : {\n tool: 'stackwright_pro_configure_isr_batch',\n args: {\n collections: [{ name: '$COLLECTION', revalidateSeconds: match.revalidateSeconds }],\n },\n };\n\n return {\n text: JSON.stringify({ ...match, configureIsrCall }),\n isError: false,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Tool 3: Validate Workflow\n// ---------------------------------------------------------------------------\n\nexport interface WorkflowValidationIssue {\n code: string;\n message: string;\n path?: string;\n}\n\nexport interface ValidateWorkflowInput {\n workflow?: Record<string, unknown>;\n _cwd?: string;\n}\n\n/** Shorthand for returning a validation failure. */\nfunction fail(errors: WorkflowValidationIssue[]): { text: string; isError: boolean } {\n return { text: JSON.stringify({ valid: false, errors, warnings: [] }), isError: true };\n}\n\n/**\n * Inline workflow validation (Approach B) ā no cross-package import.\n * CLAUDE.md invariant 1 forbids runtime imports from @stackwright-pro/workflow.\n */\nexport function handleValidateWorkflow(input: ValidateWorkflowInput): {\n text: string;\n isError: boolean;\n} {\n const cwd = input._cwd ?? process.cwd();\n let raw: Record<string, unknown>;\n\n // Resolve: explicit object > artifact file\n if (input.workflow && Object.keys(input.workflow).length > 0) {\n raw = input.workflow;\n } else {\n const artifactPath = join(cwd, '.stackwright', 'artifacts', 'workflow-config.json');\n if (!existsSync(artifactPath)) {\n return fail([\n {\n code: 'NO_WORKFLOW',\n message:\n 'No workflow provided and .stackwright/artifacts/workflow-config.json not found. Pass a workflow object or run the workflow otter first.',\n },\n ]);\n }\n try {\n raw = JSON.parse(readFileSync(artifactPath, 'utf8'));\n } catch (err) {\n return fail([{ code: 'INVALID_JSON', message: `Failed to parse workflow artifact: ${err}` }]);\n }\n }\n\n // Unwrap { workflow: { ... } } envelope if present\n const workflow = (\n raw.workflow && typeof raw.workflow === 'object' ? raw.workflow : raw\n ) as Record<string, unknown>;\n\n const errors: WorkflowValidationIssue[] = [];\n const warnings: WorkflowValidationIssue[] = [];\n\n // Rule 1: workflow.id\n if (typeof workflow.id !== 'string' || !workflow.id) {\n errors.push({ code: 'MISSING_ID', message: 'workflow.id is required', path: 'workflow.id' });\n } else if (!/^[a-z0-9-]+$/.test(workflow.id)) {\n errors.push({\n code: 'INVALID_ID',\n message: `workflow.id \"${workflow.id}\" must match ^[a-z0-9-]+$`,\n path: 'workflow.id',\n });\n }\n\n // Rule 2: workflow.label\n if (typeof workflow.label !== 'string' || !workflow.label) {\n errors.push({\n code: 'MISSING_LABEL',\n message: 'workflow.label is required',\n path: 'workflow.label',\n });\n }\n\n // Rule 3: steps array\n const steps = workflow.steps;\n if (!Array.isArray(steps)) {\n errors.push({\n code: 'MISSING_STEPS',\n message: 'workflow.steps must be an array',\n path: 'workflow.steps',\n });\n return { text: JSON.stringify({ valid: false, errors, warnings }), isError: false };\n }\n\n if (steps.length < 2) {\n errors.push({\n code: 'TOO_FEW_STEPS',\n message: 'A workflow must have at least 2 steps',\n path: 'workflow.steps',\n });\n }\n\n // Build step ID index\n const stepIds = new Set<string>();\n const duplicateIds: string[] = [];\n\n for (const step of steps) {\n if (!step || typeof step !== 'object') continue;\n const id = (step as Record<string, unknown>).id;\n if (typeof id !== 'string' || !id) {\n errors.push({\n code: 'MISSING_STEP_ID',\n message: 'Every step must have an id',\n path: 'workflow.steps',\n });\n continue;\n }\n if (!/^[a-z0-9_]+$/.test(id)) {\n errors.push({\n code: 'INVALID_STEP_ID',\n message: `Step ID \"${id}\" must match ^[a-z0-9_]+$`,\n path: `workflow.steps[${id}].id`,\n });\n }\n if (stepIds.has(id)) duplicateIds.push(id);\n stepIds.add(id);\n }\n\n if (duplicateIds.length > 0) {\n errors.push({\n code: 'DUPLICATE_STEP_IDS',\n message: `Duplicate step IDs: ${duplicateIds.join(', ')}`,\n path: 'workflow.steps',\n });\n }\n\n // Rule 4: initial_step references existing step\n const initialStep = workflow.initial_step;\n if (typeof initialStep !== 'string' || !initialStep) {\n errors.push({\n code: 'MISSING_INITIAL_STEP',\n message: 'workflow.initial_step is required',\n path: 'workflow.initial_step',\n });\n } else if (!stepIds.has(initialStep)) {\n errors.push({\n code: 'INVALID_INITIAL_STEP',\n message: `initial_step \"${initialStep}\" does not reference an existing step. Valid: ${[...stepIds].join(', ')}`,\n path: 'workflow.initial_step',\n });\n }\n\n // Rules 5+6: transition targets + service: warnings\n for (const step of steps) {\n if (!step || typeof step !== 'object') continue;\n const s = step as Record<string, unknown>;\n const stepId = String(s.id ?? '??');\n validateTransitionTargets(s, stepId, stepIds, errors);\n collectServiceWarnings(s, stepId, warnings);\n }\n\n // Workflow-level persistence service check\n if (typeof workflow.persistence === 'string' && workflow.persistence.startsWith('service:')) {\n warnings.push({\n code: 'WARN_SERVICE_REFERENCE',\n message:\n 'service: reference at \"workflow.persistence\" requires @stackwright-pro/services. Prism mock fallback will be used until services layer is configured.',\n path: 'workflow.persistence',\n });\n }\n\n // Rule 7: at least one terminal step\n const hasTerminal = steps.some((step: unknown) => {\n if (!step || typeof step !== 'object') return false;\n return (step as Record<string, unknown>).type === 'terminal';\n });\n if (!hasTerminal) {\n errors.push({\n code: 'NO_TERMINAL_STATE',\n message: 'Workflow must have at least one step with type: terminal',\n path: 'workflow.steps',\n });\n }\n\n return { text: JSON.stringify({ valid: errors.length === 0, errors, warnings }), isError: false };\n}\n\n/** Check all transition targets within a step reference real step IDs. */\nfunction validateTransitionTargets(\n step: Record<string, unknown>,\n stepId: string,\n stepIds: Set<string>,\n errors: WorkflowValidationIssue[]\n): void {\n const check = (target: unknown, path: string) => {\n if (typeof target === 'string' && !stepIds.has(target)) {\n errors.push({\n code: 'ORPHANED_TRANSITION',\n message: `Step \"${stepId}\" transitions to \"${target}\" which does not exist`,\n path,\n });\n }\n };\n\n // on_submit.transition\n const onSubmit = step.on_submit as Record<string, unknown> | undefined;\n if (onSubmit && typeof onSubmit === 'object') {\n check(onSubmit.transition, `workflow.steps[${stepId}].on_submit.transition`);\n }\n\n // actions[].transition\n if (Array.isArray(step.actions)) {\n for (const action of step.actions) {\n if (!action || typeof action !== 'object') continue;\n const a = action as Record<string, unknown>;\n check(a.transition, `workflow.steps[${stepId}].actions[${a.id ?? '??'}].transition`);\n }\n }\n\n // conditions[].then.transition\n if (Array.isArray(step.conditions)) {\n for (const cond of step.conditions) {\n if (!cond || typeof cond !== 'object') continue;\n const then = (cond as Record<string, unknown>).then as Record<string, unknown> | undefined;\n if (then && typeof then === 'object') {\n check(then.transition, `workflow.steps[${stepId}].conditions`);\n }\n }\n }\n\n // show_fields_from\n if (Array.isArray(step.show_fields_from)) {\n for (const ref of step.show_fields_from)\n check(ref, `workflow.steps[${stepId}].show_fields_from`);\n }\n\n // display.source_step / display.source_steps\n const display = step.display as Record<string, unknown> | undefined;\n if (display && typeof display === 'object') {\n check(display.source_step, `workflow.steps[${stepId}].display.source_step`);\n if (Array.isArray(display.source_steps)) {\n for (const ref of display.source_steps)\n check(ref, `workflow.steps[${stepId}].display.source_steps`);\n }\n }\n}\n\n/** Collect service: references as warnings (non-blocking). */\nfunction collectServiceWarnings(\n step: Record<string, unknown>,\n stepId: string,\n warnings: WorkflowValidationIssue[]\n): void {\n const isService = (val: unknown): val is string =>\n typeof val === 'string' && val.startsWith('service:');\n\n const warn = (path: string) => {\n warnings.push({\n code: 'WARN_SERVICE_REFERENCE',\n message: `service: reference at \"${path}\" requires @stackwright-pro/services. Prism mock fallback will be used until services layer is configured.`,\n path,\n });\n };\n\n const onSubmit = step.on_submit as Record<string, unknown> | undefined;\n if (onSubmit && typeof onSubmit === 'object' && isService(onSubmit.action))\n warn(`${stepId}.on_submit.action`);\n\n const onEnter = step.on_enter as Record<string, unknown> | undefined;\n if (onEnter && typeof onEnter === 'object' && isService(onEnter.action))\n warn(`${stepId}.on_enter.action`);\n\n if (Array.isArray(step.actions)) {\n for (const action of step.actions) {\n if (!action || typeof action !== 'object') continue;\n const a = action as Record<string, unknown>;\n if (isService(a.action)) warn(`${stepId}.actions.${a.id ?? '??'}.action`);\n }\n }\n\n if (Array.isArray(step.fields)) {\n for (const field of step.fields) {\n if (!field || typeof field !== 'object') continue;\n const f = field as Record<string, unknown>;\n if (isService(f.data_source)) warn(`${stepId}.fields.${f.name ?? '??'}.data_source`);\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// MCP Tool Registration\n// ---------------------------------------------------------------------------\n\nexport function registerDomainTools(server: McpServer): void {\n const res = (r: { text: string; isError: boolean }) => ({\n content: [{ type: 'text' as const, text: r.text }],\n isError: r.isError,\n });\n\n server.tool(\n 'stackwright_pro_list_collections',\n 'List API-backed collections available for page generation. ' +\n 'Reads from Data Otter artifact (.stackwright/artifacts/data-config.json) or stackwright.yml. ' +\n 'Call this before generating pages that bind to data.',\n {},\n async () => res(handleListCollections({}))\n );\n\n server.tool(\n 'stackwright_pro_resolve_data_strategy',\n \"Look up the data freshness strategy configuration from the user's answer. \" +\n 'Returns mechanism, revalidation seconds, required packages, and the exact MCP tool call to make. ' +\n 'Replaces the strategy table in the data-otter prompt.',\n {\n strategy: z\n .string()\n .describe(\n 'The data-1 answer value: \"pulse-fast\", \"isr-fast\", \"isr-standard\", or \"isr-slow\"'\n ),\n },\n async ({ strategy }) => res(handleResolveDataStrategy({ strategy }))\n );\n\n server.tool(\n 'stackwright_pro_validate_workflow',\n 'Validate a workflow definition against the Stackwright workflow schema. ' +\n 'Checks step ID uniqueness, transition targets, terminal state existence, and service references. ' +\n 'Call this after the workflow otter produces output.',\n {\n workflow: jsonCoerce(z.record(z.string(), z.unknown()).optional()).describe(\n 'Parsed workflow object. If omitted, reads from .stackwright/artifacts/workflow-config.json'\n ),\n },\n async ({ workflow }) => res(handleValidateWorkflow(workflow ? { workflow } : {}))\n );\n}\n","/**\n * Type Schemas Tool ā \"Sinks Not Pipes\"\n *\n * Exposes a human-readable summary of available @stackwright-pro/types schemas.\n * The foreman uses this for schema-based routing: \"which otter owns this domain?\"\n * instead of hardcoded capability descriptions in the prompt.\n */\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\n\n/**\n * Schema summary returned by the tool and written to .stackwright/type-schemas.json\n */\nexport interface TypeSchemaSummary {\n version: '1.0';\n generatedAt: string;\n domains: {\n workflow: {\n description: string;\n schemas: string[];\n otter: string;\n artifactKey: string;\n };\n auth: {\n description: string;\n schemas: string[];\n otter: string;\n artifactKey: string;\n };\n openapi: {\n description: string;\n interfaces: string[];\n otter: string;\n artifactKey: string;\n };\n pulse: {\n description: string;\n interfaces: string[];\n note: string;\n };\n enterprise: {\n description: string;\n interfaces: string[];\n note: string;\n };\n };\n}\n\nexport function buildTypeSchemaSummary(): TypeSchemaSummary {\n return {\n version: '1.0',\n generatedAt: new Date().toISOString(),\n domains: {\n workflow: {\n description: 'Workflow DSL ā step definitions, auth blocks, field types, conditions',\n schemas: [\n 'WorkflowFileSchema',\n 'WorkflowDefinitionSchema',\n 'WorkflowStepSchema',\n 'WorkflowStepTypeSchema',\n 'WorkflowFieldSchema',\n 'WorkflowActionSchema',\n 'WorkflowAuthSchema',\n 'WorkflowThemeSchema',\n 'TransitionConditionSchema',\n 'PersistenceSchema',\n ],\n otter: 'stackwright-pro-workflow-otter',\n artifactKey: 'workflowConfig',\n },\n auth: {\n description: 'Authentication providers ā PKI/CAC, OIDC, RBAC configuration',\n schemas: [\n 'authConfigSchema',\n 'pkiConfigSchema',\n 'oidcConfigSchema',\n 'rbacConfigSchema',\n 'componentAuthSchema',\n 'authUserSchema',\n 'authSessionSchema',\n ],\n otter: 'stackwright-pro-auth-otter',\n artifactKey: 'authConfig',\n },\n openapi: {\n description: 'OpenAPI spec integration ā collection config, endpoint filters, actions',\n interfaces: [\n 'OpenAPIConfig',\n 'ActionConfig',\n 'EndpointFilter',\n 'ApprovedSpec',\n 'PrebuildSecurityConfig',\n 'SiteConfig',\n 'ValidationResult',\n ],\n otter: 'stackwright-pro-api-otter',\n artifactKey: 'apiConfig',\n },\n pulse: {\n description: 'Real-time data polling ā source-agnostic polling options and states',\n interfaces: ['PulseOptions', 'PulseMeta', 'PulseState'],\n note: 'React-bound types (PulseProps, PulseIndicatorProps) remain in @stackwright-pro/pulse',\n },\n enterprise: {\n description: 'Enterprise collection access ā multi-tenant provider extension',\n interfaces: [\n 'EnterpriseCollectionProvider',\n 'CollectionProvider',\n 'CollectionEntry',\n 'CollectionListOptions',\n 'CollectionListResult',\n 'TenantFilter',\n 'Collection',\n ],\n note: 'CollectionProvider, CollectionEntry, CollectionListOptions, and CollectionListResult are re-exported from @stackwright/types (^1.5.0). EnterpriseCollectionProvider, TenantFilter, and Collection are Pro-only extensions.',\n },\n },\n };\n}\n\nexport function registerTypeSchemasTool(server: McpServer): void {\n server.tool(\n 'stackwright_pro_get_type_schemas',\n 'Returns a structured summary of all canonical @stackwright-pro/types schemas, organized by domain. Use this to determine which otter owns a given schema and what artifact key to expect.',\n {\n format: z\n .enum(['full', 'domains-only'])\n .optional()\n .default('full')\n .describe('full = complete summary with all fields; domains-only = just domain names'),\n },\n async ({ format }) => {\n const summary = buildTypeSchemaSummary();\n const output = format === 'domains-only' ? Object.keys(summary.domains) : summary;\n return {\n content: [{ type: 'text', text: JSON.stringify(output, null, 2) }],\n };\n }\n );\n}\n","{\n \"dependencies\": {\n \"@stackwright-pro/types\": \"workspace:*\",\n \"@modelcontextprotocol/sdk\": \"^1.10.0\",\n \"@stackwright-pro/cli-data-explorer\": \"workspace:*\",\n \"zod\": \"^4.4.3\"\n },\n \"devDependencies\": {\n \"@types/node\": \"catalog:\",\n \"tsup\": \"catalog:\",\n \"typescript\": \"catalog:\",\n \"vitest\": \"catalog:\"\n },\n \"scripts\": {\n \"prepublishOnly\": \"node scripts/verify-integrity-sync.js\",\n \"build\": \"tsup\",\n \"dev\": \"tsup --watch\",\n \"start\": \"node dist/server.js\",\n \"test\": \"vitest run\",\n \"test:coverage\": \"vitest run --coverage\"\n },\n \"name\": \"@stackwright-pro/mcp\",\n \"version\": \"0.2.0-alpha.52\",\n \"description\": \"MCP tools for Stackwright Pro - Data Explorer, Security, ISR, and Dashboard generation\",\n \"license\": \"SEE LICENSE IN LICENSE\",\n \"main\": \"./dist/server.js\",\n \"bin\": {\n \"stackwright-pro-mcp\": \"./dist/server.js\"\n },\n \"module\": \"./dist/server.mjs\",\n \"types\": \"./dist/server.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/server.d.ts\",\n \"import\": \"./dist/server.mjs\",\n \"require\": \"./dist/server.js\"\n },\n \"./integrity\": {\n \"types\": \"./dist/integrity.d.ts\",\n \"import\": \"./dist/integrity.mjs\",\n \"require\": \"./dist/integrity.js\"\n },\n \"./type-schemas\": {\n \"types\": \"./dist/tools/type-schemas.d.ts\",\n \"import\": \"./dist/tools/type-schemas.mjs\",\n \"require\": \"./dist/tools/type-schemas.js\"\n }\n },\n \"files\": [\n \"dist\"\n ],\n \"publishConfig\": {\n \"access\": \"public\"\n }\n}\n"],"mappings":"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","names":["z","server","z","path","z","server","z","server","z","z","listEntities","server","z","listEntities","z","server","z","z","path","server","z","path","existsSync","lstatSync","z","z","server","existsSync","lstatSync","z","readFileSync","writeFileSync","existsSync","mkdirSync","lstatSync","join","join","mkdirSync","existsSync","lstatSync","writeFileSync","readFileSync","server","z","z","readFileSync","writeFileSync","existsSync","mkdirSync","lstatSync","join","createHash","createHash","readFileSync","writeFileSync","existsSync","mkdirSync","lstatSync","join","z","join","existsSync","readFileSync","mkdirSync","writeFileSync","server","z","PHASE_TO_OTTER","join","existsSync","lstatSync","writeFileSync","readFileSync","mkdirSync","phase","createHash","artifact","server","z","z","writeFileSync","existsSync","mkdirSync","lstatSync","join","server","z","z","readFileSync","writeFileSync","existsSync","join","scopes","writeFileSync","join","existsSync","readFileSync","server","z","createHash","timingSafeEqual","readFileSync","readdirSync","lstatSync","join","server","z","readFileSync","existsSync","join","join","path","existsSync","readFileSync","server","z","z","server"]}
|
|
1
|
+
{"version":3,"sources":["../src/server.ts","../src/tools/data-explorer.ts","../src/coerce.ts","../src/tools/security.ts","../src/tools/isr.ts","../src/tools/dashboard.ts","../src/tools/clarification.ts","../src/tools/packages.ts","../src/tools/questions.ts","../src/question-adapter.ts","../src/tools/orchestration.ts","../src/tools/pipeline.ts","../src/artifact-signing.ts","../src/tools/safe-write.ts","../src/tools/auth.ts","../src/integrity.ts","../src/tools/domain.ts","../src/tools/type-schemas.ts","../package.json"],"sourcesContent":["import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { registerDataExplorerTools } from './tools/data-explorer.js';\nimport { registerSecurityTools } from './tools/security.js';\nimport { registerIsrTools } from './tools/isr.js';\nimport { registerDashboardTools } from './tools/dashboard.js';\nimport { registerClarificationTools } from './tools/clarification.js';\nimport { registerPackageTools } from './tools/packages.js';\nimport { registerQuestionTools } from './tools/questions.js';\nimport { registerOrchestrationTools } from './tools/orchestration.js';\nimport { registerPipelineTools } from './tools/pipeline.js';\nimport { registerSafeWriteTools } from './tools/safe-write.js';\nimport { registerAuthTools } from './tools/auth.js';\nimport { registerIntegrityTools } from './integrity.js';\nimport { registerArtifactSigningTools } from './artifact-signing.js';\nimport { registerDomainTools } from './tools/domain.js';\nimport { registerTypeSchemasTool } from './tools/type-schemas.js';\nimport packageJson from '../package.json';\n\nconst server = new McpServer({\n name: 'stackwright-pro',\n version: packageJson.version,\n});\n\n// Register all Pro tools\nregisterDataExplorerTools(server); // stackwright_pro_list_entities, stackwright_pro_generate_filter\nregisterSecurityTools(server); // stackwright_pro_validate_spec, stackwright_pro_add_approved_spec, stackwright_pro_list_approved_specs\nregisterIsrTools(server); // stackwright_pro_configure_isr, stackwright_pro_configure_isr_batch\nregisterDashboardTools(server); // stackwright_pro_generate_dashboard, stackwright_pro_generate_detail_page\nregisterClarificationTools(server); // stackwright_pro_clarify, stackwright_pro_detect_conflict\nregisterPackageTools(server); // stackwright_pro_setup_packages\nregisterQuestionTools(server); // stackwright_pro_present_phase_questions\nregisterOrchestrationTools(server); // stackwright_pro_parse_otter_response, stackwright_pro_save_manifest, stackwright_pro_save_phase_answers, stackwright_pro_read_phase_answers, stackwright_pro_get_otter_name\nregisterPipelineTools(server); // stackwright_pro_get_pipeline_state, stackwright_pro_set_pipeline_state, stackwright_pro_check_execution_ready, stackwright_pro_list_artifacts, stackwright_pro_write_phase_questions, stackwright_pro_build_specialist_prompt, stackwright_pro_validate_artifact\nregisterSafeWriteTools(server); // stackwright_pro_safe_write\nregisterAuthTools(server); // stackwright_pro_configure_auth\nregisterIntegrityTools(server); // stackwright_pro_verify_otter_integrity\nregisterArtifactSigningTools(server); // stackwright_pro_verify_artifact_signatures\nregisterDomainTools(server); // stackwright_pro_list_collections, stackwright_pro_resolve_data_strategy, stackwright_pro_validate_workflow\nregisterTypeSchemasTool(server); // stackwright_pro_get_type_schemas\n\nasync function main() {\n const transport = new StdioServerTransport();\n await server.connect(transport);\n console.error('Stackwright Pro MCP server running on stdio');\n}\n\nmain().catch((err) => {\n console.error('Fatal:', err);\n process.exit(1);\n});\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { listEntities, generateFilter } from '@stackwright-pro/cli-data-explorer';\nimport { jsonCoerce } from '../coerce.js';\n\n/**\n * Register data-explorer MCP tools.\n * Tools for discovering API entities and generating endpoint filters.\n */\nexport function registerDataExplorerTools(server: McpServer): void {\n // Tool: List available entities\n server.tool(\n 'stackwright_pro_list_entities',\n 'List all available API entities from OpenAPI specs or generated Zod schemas. ' +\n 'Use this to discover what entities are available before generating endpoint filters. ' +\n 'Returns entity names, endpoints, and field counts. ' +\n 'Part of the Pro Otter Raft for building API-integrated Stackwright applications.',\n {\n specPath: z.string().optional().describe('Path to OpenAPI spec file (YAML or JSON)'),\n projectRoot: z\n .string()\n .optional()\n .describe('Project root directory (auto-detected if omitted)'),\n },\n async ({ specPath, projectRoot }) => {\n const result = listEntities({\n ...(specPath !== undefined && { specPath }),\n ...(projectRoot !== undefined && { projectRoot }),\n });\n\n if (!result.success) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Error discovering entities: ${(result.errors ?? []).join(', ')}`,\n },\n ],\n isError: true,\n };\n }\n\n const lines: string[] = [`š¦ Found ${result.entities.length} API Entities:\\n`];\n\n for (const entity of result.entities) {\n lines.push(`š¦ ${entity.name} (${entity.slug})`);\n lines.push(` Endpoint: ${entity.endpoint}`);\n lines.push(` Fields: ${entity.fieldCount}`);\n if (entity.fields.length > 0) {\n const fieldTypes = entity.fields\n .slice(0, 3)\n .map((f) => `${f.name}:${f.type}`)\n .join(', ');\n lines.push(` Types: ${fieldTypes}${entity.fields.length > 3 ? '...' : ''}`);\n }\n lines.push('');\n }\n\n lines.push(\n `\\nš” Use stackwright_pro_generate_filter with selected entity slugs to create endpoint filters.`\n );\n\n return {\n content: [\n {\n type: 'text' as const,\n text: lines.join('\\n'),\n },\n ],\n };\n }\n );\n\n // Tool: Generate endpoint filter\n server.tool(\n 'stackwright_pro_generate_filter',\n 'Generate endpoint filter configuration from selected entities. ' +\n 'Creates include/exclude patterns for stackwright.yml OpenAPI integration. ' +\n 'Use this after stackwright_pro_list_entities to select which API endpoints the application needs. ' +\n 'Only selected endpoints will generate client code, reducing bundle size and improving security.',\n {\n selectedEntities: jsonCoerce(z.array(z.string())).describe(\n 'Entity slugs to include (e.g., [\"equipment\", \"supplies\"])'\n ),\n excludePatterns: jsonCoerce(z.array(z.string()).optional()).describe(\n 'Glob patterns to exclude (e.g., [\"/admin/**\", \"/reports/**\"])'\n ),\n\n projectRoot: z.string().optional().describe('Project root directory'),\n },\n async ({ selectedEntities, excludePatterns, projectRoot }) => {\n const result = generateFilter({\n selectedEntities,\n ...(excludePatterns !== undefined && { excludePatterns }),\n projectRoot: projectRoot ?? process.cwd(),\n });\n\n if (!result.success) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Error generating filter: ${result.warnings?.join(', ')}`,\n },\n ],\n isError: true,\n };\n }\n\n const lines: string[] = ['š Generated Endpoint Filter:\\n'];\n lines.push('```yaml');\n lines.push('integrations:');\n lines.push(' - type: openapi');\n lines.push(' endpoints:');\n\n if (result.filter.include && result.filter.include.length > 0) {\n lines.push(' include:');\n for (const path of result.filter.include) {\n lines.push(` - ${path}`);\n }\n }\n\n if (result.filter.exclude && result.filter.exclude.length > 0) {\n lines.push(' exclude:');\n for (const pattern of result.filter.exclude) {\n lines.push(` - ${pattern}`);\n }\n }\n\n lines.push('```');\n\n if (result.warnings && result.warnings.length > 0) {\n lines.push('\\nā ļø Warnings:');\n for (const warning of result.warnings) {\n lines.push(` ${warning}`);\n }\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: lines.join('\\n'),\n },\n ],\n };\n }\n );\n}\n","/**\n * LLM Input Coercion Utilities ā \"Sinks Not Pipes\"\n *\n * LLMs frequently serialize complex values to JSON strings before passing them\n * as MCP tool arguments. These utilities wrap Zod schemas with z.preprocess\n * steps that coerce the common mis-serializations back to native types before\n * Zod validates them.\n *\n * Usage:\n * import { jsonCoerce, boolCoerce, numCoerce } from '../coerce.js';\n * // In a server.tool() schema:\n * myArray: jsonCoerce(z.array(z.string())).describe('...'),\n * myBool: boolCoerce(z.boolean().optional()).describe('...'),\n * myNum: numCoerce(z.number().optional()).describe('...'),\n *\n * Design note: z.preprocess uses the INNER schema for JSON Schema generation,\n * so the MCP tool's inputSchema still shows the correct native type to the LLM.\n * The coercion is invisible to the model ā it only fires when the model sends\n * the wrong type.\n */\nimport { z } from 'zod';\n\n/**\n * JSON-coerce: If the input is a string, attempt JSON.parse before validation.\n * Handles LLM string-serialization of arrays (`\"[...]\"`), objects (`\"{...}\"`),\n * and records. If JSON.parse fails, the original string is passed through and\n * Zod produces a clear type error.\n */\nexport function jsonCoerce<T extends z.ZodTypeAny>(schema: T) {\n return z.preprocess((v) => {\n if (typeof v === 'string') {\n try {\n return JSON.parse(v);\n } catch {\n return v; // Zod will reject it with a clear error\n }\n }\n return v;\n }, schema);\n}\n\n/**\n * Bool-coerce: Converts the strings \"true\" and \"false\" to their boolean\n * equivalents. Uses explicit string matching ā NOT JavaScript truthiness ā\n * so the string \"false\" correctly maps to boolean false.\n */\nexport function boolCoerce<T extends z.ZodTypeAny>(schema: T) {\n return z.preprocess((v) => (v === 'true' ? true : v === 'false' ? false : v), schema);\n}\n\n/**\n * Num-coerce: Converts pure numeric strings (\"42\", \"3.14\") to numbers.\n * Non-numeric strings pass through unchanged (Zod produces a clear error).\n */\nexport function numCoerce<T extends z.ZodTypeAny>(schema: T) {\n return z.preprocess((v) => {\n if (typeof v === 'string' && v.trim() !== '') {\n const n = Number(v);\n if (!Number.isNaN(n)) return n;\n }\n return v;\n }, schema);\n}\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { createHash } from 'crypto';\nimport fs from 'fs';\nimport path from 'path';\n\n/**\n * Register security-focused MCP tools.\n * Tools for validating specs against approved-specs and managing the allowlist.\n */\nexport function registerSecurityTools(server: McpServer): void {\n // Tool: Validate a spec against approved-specs\n server.tool(\n 'stackwright_pro_validate_spec',\n 'Validate an OpenAPI spec against the enterprise approved-specs configuration. ' +\n 'Checks if the spec URL is on the allowlist and verifies SHA-256 hash integrity. ' +\n 'Use this in enterprise environments where only pre-approved API specs are allowed. ' +\n 'Fails build if spec is not approved or has been modified.',\n {\n specPath: z.string().describe('URL or file path to the OpenAPI spec to validate'),\n configPath: z\n .string()\n .optional()\n .describe('Path to stackwright.yml with prebuild.security config'),\n },\n async ({ specPath, configPath }) => {\n // Try to load config from stackwright.yml\n let securityEnabled = false;\n const allowlist: Array<{ name: string; url: string; sha256: string }> = [];\n\n const configFile = configPath || path.join(process.cwd(), 'stackwright.yml');\n\n if (fs.existsSync(configFile)) {\n try {\n const content = fs.readFileSync(configFile, 'utf8');\n\n // Simple regex extraction for security config\n const securityMatch = content.match(\n /prebuild:\\s*\\n\\s*security:\\s*\\n\\s*enabled:\\s*(true|false)/\n );\n if (securityMatch && securityMatch[1] === 'true') {\n securityEnabled = true;\n // Extract allowlist entries\n const specMatches = content.matchAll(\n /- name:\\s*(.+?)\\n\\s+url:\\s*(.+?)\\n\\s+sha256:\\s*(.+?)(?:\\n|$)/g\n );\n for (const match of specMatches) {\n allowlist.push({\n name: match[1]!.trim(),\n url: match[2]!.trim(),\n sha256: match[3]!.trim(),\n });\n }\n }\n } catch {\n // Config exists but couldn't parse - continue without it\n }\n }\n\n // If no security config, just return success (security not enabled)\n if (!securityEnabled) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `ā
Spec validation skipped (security not enabled)\\n\\nTo enable approved-specs validation, add to stackwright.yml:\\n\\nprebuild:\\n security:\\n enabled: true\\n allowlist:\\n - name: My API\\n url: ${specPath}\\n sha256: <sha256-of-spec>`,\n },\n ],\n };\n }\n\n // Check if spec is in allowlist\n const matchingSpec = allowlist.find((s) => s.url === specPath);\n\n if (!matchingSpec) {\n return {\n content: [\n {\n type: 'text' as const,\n text:\n `ā Spec rejected!\\n\\nError Code: SPEC_NOT_IN_ALLOWLIST\\n\\nURL: ${specPath}\\n\\nThis spec is not on the approved-specs allowlist. ` +\n `Add it using stackwright_pro_add_approved_spec before proceeding.`,\n },\n ],\n isError: true,\n };\n }\n\n // For file-based specs, compute hash and validate\n if (!specPath.startsWith('http://') && !specPath.startsWith('https://')) {\n if (fs.existsSync(specPath)) {\n const specContent = fs.readFileSync(specPath, 'utf8');\n const sha256 = createHash('sha256').update(specContent).digest('hex');\n\n if (sha256 !== matchingSpec.sha256) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `ā Spec hash mismatch!\\n\\nError Code: SPEC_HASH_MISMATCH\\n\\nExpected: ${matchingSpec.sha256.substring(0, 16)}...\\nActual: ${sha256.substring(0, 16)}...\\n\\nThe spec has been modified since it was approved. Re-approve the spec to continue.`,\n },\n ],\n isError: true,\n };\n }\n }\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `ā
Spec approved!\\n\\nName: ${matchingSpec.name}\\nURL: ${specPath}\\nStatus: Valid (${allowlist.length} specs on allowlist)`,\n },\n ],\n };\n }\n );\n\n // Tool: Add approved spec to allowlist\n server.tool(\n 'stackwright_pro_add_approved_spec',\n 'Add an OpenAPI spec to the approved-specs allowlist in stackwright.yml. ' +\n 'Computes the SHA-256 hash of the spec and adds it to the security configuration. ' +\n 'Use this when onboarding a new API in enterprise environments.',\n {\n name: z.string().describe('Human-readable name for the spec'),\n url: z.string().describe('URL or file path to the OpenAPI spec'),\n configPath: z.string().optional().describe('Path to stackwright.yml'),\n },\n async ({ name, url, configPath }) => {\n const configFile = configPath || path.join(process.cwd(), 'stackwright.yml');\n\n // Compute SHA-256 of spec\n let sha256 = '<computed-at-build>';\n\n try {\n if (url.startsWith('http://') || url.startsWith('https://')) {\n // URL spec - hash computed at build time; initial value already set\n } else if (fs.existsSync(url)) {\n const specContent = fs.readFileSync(url, 'utf8');\n sha256 = createHash('sha256').update(specContent).digest('hex');\n } else {\n return {\n content: [\n {\n type: 'text' as const,\n text: `ā Spec file not found: ${url}`,\n },\n ],\n isError: true,\n };\n }\n } catch (e) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `ā Failed to read spec: ${e}`,\n },\n ],\n isError: true,\n };\n }\n\n const yamlSnippet = ` - name: ${name}\n url: ${url}\n sha256: ${sha256}`;\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `š Add this to stackwright.yml under prebuild.security.allowlist:\\n\\n${yamlSnippet}\\n\\nSHA-256 computed: ${sha256}`,\n },\n ],\n };\n }\n );\n\n // Tool: List approved specs\n server.tool(\n 'stackwright_pro_list_approved_specs',\n 'List all specs currently on the approved-specs allowlist. ' +\n 'Shows spec names, URLs, and hash prefixes. ' +\n 'Use this to audit what APIs are approved in the project.',\n {\n configPath: z.string().optional().describe('Path to stackwright.yml'),\n },\n async ({ configPath }) => {\n const configFile = configPath || path.join(process.cwd(), 'stackwright.yml');\n\n if (!fs.existsSync(configFile)) {\n return {\n content: [\n {\n type: 'text' as const,\n text: 'ā stackwright.yml not found in project root.',\n },\n ],\n isError: true,\n };\n }\n\n const content = fs.readFileSync(configFile, 'utf8');\n\n // Check if security is enabled\n const securityEnabled =\n content.includes('prebuild:') &&\n content.includes('security:') &&\n content.includes('enabled: true');\n\n if (!securityEnabled) {\n return {\n content: [\n {\n type: 'text' as const,\n text: 'ā¹ļø Approved-specs validation is not enabled.\\n\\nAdd to stackwright.yml to enable:\\n\\nprebuild:\\n security:\\n enabled: true\\n allowlist: []',\n },\n ],\n };\n }\n\n // Extract specs\n const specs: Array<{ name: string; url: string; sha256: string }> = [];\n const specMatches = content.matchAll(\n /- name:\\s*(.+?)\\n\\s+url:\\s*(.+?)\\n\\s+sha256:\\s*(.+?)(?:\\n|$)/g\n );\n\n for (const match of specMatches) {\n specs.push({\n name: match[1]!.trim(),\n url: match[2]!.trim(),\n sha256: match[3]!.trim().substring(0, 16) + '...',\n });\n }\n\n if (specs.length === 0) {\n return {\n content: [\n {\n type: 'text' as const,\n text: 'ā¹ļø Security enabled but no specs on allowlist.\\n\\nAdd specs using stackwright_pro_add_approved_spec.',\n },\n ],\n };\n }\n\n const lines = [`š Approved Specs (${specs.length}):\\n`];\n for (const spec of specs) {\n lines.push(`š¦ ${spec.name}`);\n lines.push(` URL: ${spec.url}`);\n lines.push(` Hash: ${spec.sha256}`);\n lines.push('');\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: lines.join('\\n'),\n },\n ],\n };\n }\n );\n}\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport fs from 'fs';\nimport path from 'path';\nimport { jsonCoerce, numCoerce } from '../coerce.js';\n\n/**\n * Register ISR configuration MCP tools.\n * Tools for configuring Incremental Static Regeneration for API-backed collections.\n */\nexport function registerIsrTools(server: McpServer): void {\n // Tool: Configure ISR for a collection\n server.tool(\n 'stackwright_pro_configure_isr',\n 'Configure Incremental Static Regeneration (ISR) for an API-backed collection. ' +\n 'ISR allows API data to be cached and refreshed on a schedule, providing real-time data ' +\n 'with the performance of static generation. ' +\n 'Use this after stackwright_pro_generate_filter to set revalidation intervals.',\n {\n collection: z.string().describe('Collection name (e.g., \"equipment\", \"supplies\")'),\n revalidateSeconds: numCoerce(z.number().optional()).describe(\n 'Revalidation interval in seconds (default: 60)'\n ),\n fallback: z\n .enum(['blocking', 'true', 'false'])\n .optional()\n .describe('Fallback behavior for new pages'),\n configPath: z.string().optional().describe('Path to stackwright.yml'),\n },\n async ({ collection, revalidateSeconds = 60, fallback = 'blocking', configPath }) => {\n const revalidate = revalidateSeconds;\n\n const yamlSnippet = `# Add to stackwright.yml under integrations:\n - type: openapi\n name: ${collection}\n # ... other config\n isr:\n revalidate: ${revalidate}\n fallback: ${fallback}`;\n\n let description: string;\n if (revalidate < 60) {\n description = 'ā” Very fresh data (revalidate every ' + revalidate + 's)';\n } else if (revalidate < 300) {\n description = 'š Fresh data (revalidate every ' + (revalidate / 60).toFixed(0) + ' min)';\n } else if (revalidate < 3600) {\n description = 'š¾ Cached data (revalidate every ' + (revalidate / 60).toFixed(0) + ' min)';\n } else {\n description =\n 'šļø Static data (revalidate every ' + (revalidate / 3600).toFixed(0) + ' hour)';\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `āļø ISR Configuration for \"${collection}\":\\n\\n${description}\\n\\nFallback: ${fallback === 'blocking' ? 'ā³ Show loading until cached' : fallback === 'true' ? 'š Generate on demand' : 'ā 404 for new pages'}\\n\\n\\`\\`\\`yaml\\n${yamlSnippet}\\n\\`\\`\\``,\n },\n ],\n };\n }\n );\n\n // Tool: Configure ISR for multiple collections\n server.tool(\n 'stackwright_pro_configure_isr_batch',\n 'Configure ISR for multiple collections at once. ' +\n 'More efficient than calling stackwright_pro_configure_isr multiple times. ' +\n 'Provide different revalidation intervals based on data freshness requirements.',\n {\n collections: jsonCoerce(\n z.array(\n z.object({\n name: z.string().describe('Collection name'),\n revalidateSeconds: numCoerce(z.number().optional()).describe('Revalidation interval'),\n })\n )\n ).describe('Array of collection configurations'),\n defaultFallback: z\n .enum(['blocking', 'true', 'false'])\n .optional()\n .describe('Default fallback behavior'),\n configPath: z.string().optional().describe('Path to stackwright.yml'),\n },\n async ({ collections, defaultFallback = 'blocking', configPath }) => {\n const lines = [`āļø Batch ISR Configuration:\\n`];\n\n for (const col of collections) {\n const rev = col.revalidateSeconds || 60;\n let freshness = 'š¾';\n if (rev < 60) freshness = 'ā”';\n else if (rev < 300) freshness = 'š';\n else if (rev >= 3600) freshness = 'šļø';\n\n lines.push(`${freshness} ${col.name}: revalidate=${rev}s`);\n }\n\n lines.push(`\\nFallback: ${defaultFallback}`);\n\n return {\n content: [\n {\n type: 'text' as const,\n text: lines.join('\\n'),\n },\n ],\n };\n }\n );\n}\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { listEntities } from '@stackwright-pro/cli-data-explorer';\nimport { jsonCoerce } from '../coerce.js';\n\n/**\n * Register dashboard generation MCP tools.\n * Tools for building pages that display live API data.\n */\nexport function registerDashboardTools(server: McpServer): void {\n // Tool: Generate dashboard page configuration\n server.tool(\n 'stackwright_pro_generate_dashboard',\n 'Generate a dashboard page configuration for displaying API data. ' +\n 'Creates YAML content for a Stackwright page with grid, metric_card, data_table, and collection_list content types. ' +\n 'Use this after stackwright_pro_generate_filter to create pages for your API collections.',\n {\n entities: jsonCoerce(z.array(z.string())).describe('Entity slugs to include in dashboard'),\n layout: z.enum(['grid', 'table', 'mixed']).optional().describe('Dashboard layout style'),\n pageTitle: z.string().optional().describe('Page title'),\n specPath: z.string().optional().describe('Path to OpenAPI spec for entity details'),\n },\n async ({ entities, layout = 'mixed', pageTitle, specPath }) => {\n // Get entity details if spec provided\n let entityDetails: any[] = [];\n if (specPath) {\n const result = listEntities({ specPath });\n if (result.success) {\n entityDetails = result.entities.filter((e) => entities.includes(e.slug));\n }\n }\n\n const title =\n pageTitle || entities.map((e) => e.charAt(0).toUpperCase() + e.slice(1)).join(' & ');\n\n const yamlLines = [\n '# Dashboard page configuration',\n '# Generated by Stackwright Pro MCP',\n '',\n 'content:',\n ' meta:',\n ` title: \"${title} | Dashboard\"`,\n ` description: \"Live data from API\"`,\n '',\n ' content_items:',\n ];\n\n // Add metric cards in a grid for each entity\n if (layout === 'grid' || layout === 'mixed') {\n for (const slug of entities) {\n yamlLines.push(` - type: grid`);\n yamlLines.push(` columns: 4`);\n yamlLines.push(` items:`);\n yamlLines.push(` - type: metric_card`);\n yamlLines.push(` label: \"Total\"`);\n yamlLines.push(` value: {{ ${slug}.count }}`);\n yamlLines.push(` icon: Database`);\n yamlLines.push(` - type: metric_card`);\n yamlLines.push(` label: \"Active\"`);\n yamlLines.push(` value: 0`);\n yamlLines.push(` icon: CheckCircle`);\n yamlLines.push('');\n }\n }\n\n // Add collection listing for each entity\n yamlLines.push(` - type: collection_list`);\n yamlLines.push(` label: ${entities[0]}-listing`);\n yamlLines.push(` collection: ${entities[0]}`);\n yamlLines.push(` showFilters: true`);\n yamlLines.push(` showSearch: true`);\n const defaultCols = ['id', 'name', 'status', 'created_at'];\n yamlLines.push(\n ` columns: ${\n entityDetails[0]?.fields\n ?.slice(0, 4)\n .map((f: any) => f.name)\n .join(', ') || defaultCols.join(', ')\n }`\n );\n yamlLines.push('');\n\n if (layout === 'table') {\n yamlLines.push(` - type: data_table`);\n yamlLines.push(` label: ${entities[0]}-table`);\n yamlLines.push(` collection: ${entities[0]}`);\n yamlLines.push(` columns:`);\n yamlLines.push(` - field: id`);\n yamlLines.push(` header: ID`);\n yamlLines.push(` sortable: true`);\n yamlLines.push(` - field: name`);\n yamlLines.push(` header: Name`);\n yamlLines.push(` sortable: true`);\n yamlLines.push(` - field: status`);\n yamlLines.push(` header: Status`);\n yamlLines.push(` type: badge`);\n }\n\n const yaml = yamlLines.join('\\n');\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `š Generated Dashboard for: ${entities.join(', ')}\\n\\nLayout: ${layout}\\n\\n\\`\\`\\`yaml\\n${yaml}\\n\\`\\`\\`\\n\\nš” Add this to pages/dashboard/content.yml and validate with stackwright_validate_pages.`,\n },\n ],\n };\n }\n );\n\n // Tool: Generate detail page\n server.tool(\n 'stackwright_pro_generate_detail_page',\n 'Generate a detail view page for a single API entity. ' +\n 'Creates YAML content for displaying all fields of an individual record. ' +\n 'Use this to create detail pages that complement collection listing pages.',\n {\n entity: z.string().describe('Entity slug (e.g., \"equipment\")'),\n slugField: z.string().optional().describe('Field to use as URL slug (default: \"id\")'),\n specPath: z.string().optional().describe('Path to OpenAPI spec for field details'),\n },\n async ({ entity, slugField = 'id', specPath }) => {\n // Get field details if spec provided\n let fields: any[] = [];\n if (specPath) {\n const result = listEntities({ specPath });\n if (result.success) {\n const ent = result.entities.find((e) => e.slug === entity);\n if (ent) {\n fields = ent.fields;\n }\n }\n }\n\n const entityName = entity.charAt(0).toUpperCase() + entity.slice(1);\n\n const yamlLines = [\n `# Detail page for ${entityName}`,\n '# Generated by Stackwright Pro MCP',\n '',\n 'content:',\n ' meta:',\n ` title: \"${entityName} Details | {{ ${entity}.${slugField} }}\"`,\n '',\n ' content_items:',\n ' - type: text_block',\n ' label: \"detail-header\"',\n ' heading:',\n ` text: \"{{ ${entity}.${slugField} }}\"`,\n ' textSize: \"h1\"',\n ' textBlocks:',\n ` - text: \"Details for this ${entity}\"`,\n ' textSize: \"body1\"',\n '',\n ' - type: grid',\n ' label: \"detail-fields\"',\n ' columns:',\n ];\n\n // Add field displays as text_block items within grid columns\n const displayFields =\n fields.length > 0\n ? fields.slice(0, 8)\n : [\n { name: slugField, type: 'string' },\n { name: 'created_at', type: 'datetime' },\n { name: 'updated_at', type: 'datetime' },\n ];\n\n // Split fields into two columns\n const mid = Math.ceil(displayFields.length / 2);\n const col1 = displayFields.slice(0, mid);\n const col2 = displayFields.slice(mid);\n\n for (const [colIndex, colFields] of [col1, col2].entries()) {\n yamlLines.push(' - width: 1');\n yamlLines.push(' content_items:');\n for (const field of colFields) {\n const label = field.name\n .replace(/_/g, ' ')\n .replace(/\\b\\w/g, (l: string) => l.toUpperCase());\n yamlLines.push(' - type: text_block');\n yamlLines.push(` label: \"${field.name}-field\"`);\n yamlLines.push(' heading:');\n yamlLines.push(` text: \"${label}\"`);\n yamlLines.push(' textSize: \"h4\"');\n yamlLines.push(' textBlocks:');\n yamlLines.push(` - text: \"{{ ${entity}.${field.name} }}\"`);\n yamlLines.push(' textSize: \"body1\"');\n }\n }\n\n // Back navigation\n yamlLines.push('');\n yamlLines.push(' - type: action_bar');\n yamlLines.push(' actions:');\n yamlLines.push(` - label: \"<- Back to ${entityName}\"`);\n yamlLines.push(' action: navigate');\n yamlLines.push(` href: \"/${entity}\"`);\n yamlLines.push(' style: secondary');\n\n const yaml = yamlLines.join('\\n');\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `š Generated Detail Page for: ${entity}\\n\\n\\`\\`\\`yaml\\n${yaml}\\n\\`\\`\\`\\n\\nš” Add this to pages/${entity}/[${slugField}]/content.yml and validate.`,\n },\n ],\n };\n }\n );\n}\n","/**\n * Clarification MCP Tools\n *\n * Provides human-in-the-loop clarification for otters that encounter\n * ambiguity during execution.\n *\n * Two tools:\n * 1. stackwright_pro_clarify ā mid-execution clarification (NOT upfront\n * question collection; that's the Question Manifest Protocol).\n * 2. stackwright_pro_detect_conflict ā pure-logic conflict detection between\n * stated preferences and actual selections.\n *\n * Handler functions are exported for direct testing ā no MCP server needed.\n */\n\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { jsonCoerce } from '../coerce.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface ClarificationRequest {\n context?: string | undefined;\n question_type: 'closed_choice' | 'open_text';\n question: string;\n choices?: string[] | undefined;\n priority: 'blocking' | 'preferred' | 'optional';\n target_field?: string | undefined;\n}\n\nexport interface ClarificationResponse {\n action: 'ask_user';\n adaptedQuestion?: AdaptedQuestion | undefined;\n prompt?: string | undefined;\n suggestedDefault?: string | undefined;\n targetField?: string | undefined;\n}\n\n/** Ready-to-pass shape for `ask_user_question`. */\ninterface AdaptedQuestion {\n question: string;\n header: string;\n options: Array<{ label: string; description?: string }>;\n}\n\nexport interface ConflictDetectionInput {\n stated_preference: string;\n selected_values: Record<string, string>;\n}\n\nexport interface ConflictDetectionResult {\n conflict: boolean;\n description?: string;\n resolution_options?: string[];\n}\n\n// ---------------------------------------------------------------------------\n// Contradiction patterns ā keyword matching against known opposites\n// ---------------------------------------------------------------------------\n\nconst CONTRADICTION_PATTERNS: Array<{\n keywords: string[];\n conflicts: string[];\n}> = [\n {\n keywords: ['minimal', 'clean', 'simple'],\n conflicts: ['vibrant', 'rich', 'content-heavy', 'playful'],\n },\n {\n keywords: ['dark', 'dark mode'],\n conflicts: ['light mode only', 'light'],\n },\n {\n keywords: ['enterprise', 'professional', 'corporate'],\n conflicts: ['playful', 'casual', 'fun'],\n },\n {\n keywords: ['accessible', 'wcag', 'section 508'],\n conflicts: ['compact', 'dense', 'small text'],\n },\n {\n keywords: ['government', 'defense', 'federal'],\n conflicts: ['public', 'no auth', 'consumer'],\n },\n];\n\n// ---------------------------------------------------------------------------\n// Handler: clarify\n// ---------------------------------------------------------------------------\n\nexport function handleClarify(input: ClarificationRequest): ClarificationResponse {\n const { question_type, question, choices, priority, target_field, context } = input;\n\n const base: ClarificationResponse = {\n action: 'ask_user',\n targetField: target_field,\n };\n\n if (question_type === 'closed_choice' && choices && choices.length > 0) {\n const header = truncateHeader(question);\n base.adaptedQuestion = {\n question,\n header,\n options: choices.map((c) => ({ label: c })),\n };\n } else {\n // open_text ā foreman should ask the user directly\n const contextPrefix = context ? `Context: ${context}\\n\\n` : '';\n base.prompt = `${contextPrefix}${question}`;\n }\n\n if (priority === 'optional') {\n base.suggestedDefault = inferDefault(question_type, choices);\n }\n\n return base;\n}\n\n// ---------------------------------------------------------------------------\n// Handler: detect conflict\n// ---------------------------------------------------------------------------\n\nexport function handleDetectConflict(input: ConflictDetectionInput): ConflictDetectionResult {\n const preferenceLower = input.stated_preference.toLowerCase();\n const valuesLower = Object.values(input.selected_values).map((v) => v.toLowerCase());\n\n for (const pattern of CONTRADICTION_PATTERNS) {\n const preferenceMatch = pattern.keywords.some((kw) => preferenceLower.includes(kw));\n if (!preferenceMatch) continue;\n\n const conflictingValues = valuesLower.filter((val) =>\n pattern.conflicts.some((c) => val.includes(c))\n );\n\n if (conflictingValues.length > 0) {\n const matchedKeywords = pattern.keywords.filter((kw) => preferenceLower.includes(kw));\n const primaryKeyword = matchedKeywords[0] ?? 'preference';\n return {\n conflict: true,\n description:\n `Stated preference includes \"${matchedKeywords.join(', ')}\" ` +\n `but selections contain \"${conflictingValues.join(', ')}\" ā these are contradictory.`,\n resolution_options: [\n `Align selections with the \"${primaryKeyword}\" preference`,\n `Revise stated preference to match current selections`,\n 'Ask user which direction they actually want',\n ],\n };\n }\n }\n\n return { conflict: false };\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Truncate to 50 chars (ask_user_question header limit). */\nfunction truncateHeader(text: string): string {\n const MAX = 50;\n if (text.length <= MAX) return text;\n return text.slice(0, MAX - 1) + 'ā¦';\n}\n\n/** Best-effort default suggestion for optional questions. */\nfunction inferDefault(\n questionType: ClarificationRequest['question_type'],\n choices?: string[]\n): string {\n if (questionType === 'closed_choice' && choices && choices.length > 0) {\n return choices[0] ?? '(first choice)';\n }\n return '(use sensible project default)';\n}\n\n// ---------------------------------------------------------------------------\n// MCP tool registration\n// ---------------------------------------------------------------------------\n\nexport function registerClarificationTools(server: McpServer): void {\n // -----------------------------------------------------------------------\n // 1. stackwright_pro_clarify\n // -----------------------------------------------------------------------\n server.tool(\n 'stackwright_pro_clarify',\n 'Ask the user for clarification when a specialist otter encounters ambiguity. ' +\n 'This is for MID-EXECUTION questions, NOT upfront question collection (use the Question Manifest Protocol for that). ' +\n 'Returns a structured response for the foreman to present to the user via ask_user_question (closed_choice) or directly (open_text).',\n {\n context: z.string().optional().describe('Context about what the otter is trying to do'),\n question_type: z\n .enum(['closed_choice', 'open_text'])\n .describe('Type of question being asked'),\n question: z.string().describe('The clarification question to ask the user'),\n choices: jsonCoerce(z.array(z.string()).optional()).describe(\n 'Options for closed_choice questions'\n ),\n priority: z\n .enum(['blocking', 'preferred', 'optional'])\n .optional()\n .default('preferred')\n .describe('How critical is this clarification? Default: preferred'),\n target_field: z.string().optional().describe('What field/config does this clarify?'),\n },\n async ({ context, question_type, question, choices, priority, target_field }) => {\n const result = handleClarify({\n context: context ?? undefined,\n question_type,\n question,\n choices: choices ?? undefined,\n priority: (priority ?? 'preferred') as ClarificationRequest['priority'],\n target_field: target_field ?? undefined,\n });\n\n return {\n content: [\n {\n type: 'text' as const,\n text:\n `𦦠Clarification needed${target_field ? ` for \"${target_field}\"` : ''}. ` +\n `Present the following to the user. ` +\n (result.adaptedQuestion\n ? 'Pass the adaptedQuestion to ask_user_question directly.'\n : 'Ask the user the prompt below.'),\n },\n {\n type: 'text' as const,\n text: JSON.stringify(result),\n },\n ],\n };\n }\n );\n\n // -----------------------------------------------------------------------\n // 2. stackwright_pro_detect_conflict\n // -----------------------------------------------------------------------\n server.tool(\n 'stackwright_pro_detect_conflict',\n \"Detect when a user's stated preference conflicts with their selected choices. \" +\n 'Uses keyword heuristics against known contradiction patterns (minimal vs vibrant, dark vs light, etc). ' +\n 'Returns conflict details and resolution options.',\n {\n stated_preference: z.string().describe('What the user said they wanted'),\n selected_values: jsonCoerce(z.record(z.string(), z.string())).describe(\n 'What the user actually selected (field ā value)'\n ),\n },\n async ({ stated_preference, selected_values }) => {\n const result = handleDetectConflict({ stated_preference, selected_values });\n\n if (result.conflict) {\n return {\n content: [\n {\n type: 'text' as const,\n text:\n `ā ļø CONFLICT DETECTED\\n\\n` +\n `User stated: \"${stated_preference}\"\\n` +\n `But selected: ${JSON.stringify(selected_values)}\\n\\n` +\n `${result.description}\\n\\n` +\n `Resolution options:\\n${result.resolution_options?.map((o) => ` ⢠${o}`).join('\\n')}\\n\\n` +\n `š” Consider asking the user to reconcile this conflict.`,\n },\n {\n type: 'text' as const,\n text: JSON.stringify(result),\n },\n ],\n };\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: 'ā
No conflict detected between stated preference and selections.',\n },\n {\n type: 'text' as const,\n text: JSON.stringify(result),\n },\n ],\n };\n }\n );\n}\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { readFileSync, writeFileSync, existsSync, realpathSync, lstatSync } from 'fs';\nimport { execSync } from 'child_process';\nimport path from 'path';\nimport { jsonCoerce, boolCoerce } from '../coerce.js';\n\n/**\n * stackwright_pro_setup_packages MCP tool\n *\n * Ensures pro packages are present in a project's package.json.\n * Used by the Pro Foreman Otter to bootstrap dependencies before\n * specialist otters run ā enabling the otter raft's IoC dependency\n * declaration pattern.\n *\n * Merge semantics: NEVER overwrites an existing version pin.\n * If a package is already declared at any version, it is skipped.\n * This preserves intentional version pinning by developers.\n */\n\ninterface PackageJson {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n scripts?: Record<string, string>;\n [key: string]: unknown;\n}\n\ninterface SetupPackagesResult {\n success: boolean;\n added: string[];\n skipped: string[];\n scriptsAdded: string[];\n installed: boolean;\n packageJsonPath: string;\n error?: string;\n installError?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Baseline dependencies moved from foreman prompt into version-controlled code\n// ---------------------------------------------------------------------------\n\nconst BASELINE_DEPS: Record<string, string> = {\n '@stackwright-pro/mcp': 'latest',\n '@stackwright-pro/otters': 'latest',\n '@stackwright-pro/openapi': 'latest',\n '@stackwright-pro/auth': 'latest',\n '@stackwright-pro/auth-nextjs': 'latest',\n zod: '^3.23.0',\n};\n\nconst BASELINE_DEV_DEPS: Record<string, string> = {\n '@stoplight/prism-cli': '^5.14.2',\n};\n\nexport function registerPackageTools(server: McpServer): void {\n server.tool(\n 'stackwright_pro_setup_packages',\n \"Ensures pro packages are present in a project's package.json. \" +\n 'Safe to call multiple times ā never overwrites existing version pins. ' +\n 'Use this to bootstrap dependencies before specialist otters run. ' +\n 'Pass includeBaseline: true to automatically include all required @stackwright-pro/* baseline dependencies. ' +\n 'Safe to call on existing projects ā never overwrites pinned versions.',\n {\n // FIX 3 (B-new-1): Zod v4 requires two-arg z.record(keySchema, valueSchema)\n packages: jsonCoerce(z.record(z.string(), z.string()).optional().default({})).describe(\n 'Dependencies to add. Record<packageName, version>. e.g. { \"@stackwright-pro/auth\": \"latest\" }. Omit or pass {} when using includeBaseline: true.'\n ),\n devPackages: jsonCoerce(z.record(z.string(), z.string()).optional()).describe(\n 'devDependencies to add. Same format as packages.'\n ),\n scripts: jsonCoerce(z.record(z.string(), z.string()).optional()).describe(\n 'npm scripts to add. Only adds if key does not already exist.'\n ),\n targetDir: z\n .string()\n .optional()\n .describe(\n 'Project directory containing package.json. Defaults to process.cwd(). Must be an absolute path within the current working directory.'\n ),\n runInstall: boolCoerce(z.boolean().optional().default(true)).describe(\n 'Run pnpm install after writing package.json. Defaults to true. Pass boolean true/false.'\n ),\n includeBaseline: boolCoerce(z.boolean().optional().default(false)).describe(\n 'When true, automatically merges BASELINE_DEPS and BASELINE_DEV_DEPS before applying packages/devPackages args. ' +\n 'Safe to call on existing projects ā never overwrites pinned versions. Pass boolean true/false.'\n ),\n },\n async ({ packages, devPackages, scripts, targetDir, runInstall, includeBaseline }) => {\n // Merge baseline deps when requested ā existing \"never overwrite\" semantics\n // in setupPackages mean this is safe to call on any project.\n const mergedPackages: Record<string, string> = includeBaseline\n ? { ...BASELINE_DEPS, ...packages }\n : { ...packages };\n\n const mergedDevPackages: Record<string, string> | undefined = includeBaseline\n ? { ...BASELINE_DEV_DEPS, ...(devPackages ?? {}) }\n : devPackages;\n\n // exactOptionalPropertyTypes: true means we cannot pass `undefined` explicitly\n // for optional fields ā conditionally spread them instead.\n const result = setupPackages({\n packages: mergedPackages,\n runInstall,\n ...(mergedDevPackages !== undefined ? { devPackages: mergedDevPackages } : {}),\n ...(scripts !== undefined ? { scripts } : {}),\n ...(targetDir !== undefined ? { targetDir } : {}),\n });\n\n const statusLine = result.success\n ? `ā
package.json updated: ${result.packageJsonPath}`\n : `ā Failed: ${result.error}`;\n\n const lines = [\n statusLine,\n '',\n result.added.length > 0\n ? `Added (${result.added.length}): ${result.added.join(', ')}`\n : 'Added: none',\n result.skipped.length > 0\n ? `Skipped/already present (${result.skipped.length}): ${result.skipped.join(', ')}`\n : 'Skipped: none',\n result.scriptsAdded.length > 0\n ? `Scripts added (${result.scriptsAdded.length}): ${result.scriptsAdded.join(', ')}`\n : 'Scripts added: none',\n `pnpm install: ${result.installed ? 'ran successfully' : result.success && runInstall ? 'failed (non-fatal)' : 'skipped'}`,\n ];\n\n return {\n content: [\n {\n type: 'text' as const,\n text: lines.join('\\n'),\n },\n {\n type: 'text' as const,\n text: JSON.stringify(result),\n },\n ],\n };\n }\n );\n}\n\n/**\n * Core implementation ā extracted so it can be tested directly without\n * going through the MCP server machinery. Keeping I/O at the edges.\n */\nexport function setupPackages(opts: {\n packages: Record<string, string>;\n devPackages?: Record<string, string>;\n scripts?: Record<string, string>;\n targetDir?: string;\n runInstall: boolean;\n}): SetupPackagesResult {\n const emptyResult: Omit<SetupPackagesResult, 'success' | 'error'> = {\n added: [],\n skipped: [],\n scriptsAdded: [],\n installed: false,\n packageJsonPath: '',\n };\n\n try {\n // -------------------------------------------------------------------------\n // Security: path traversal guard\n // -------------------------------------------------------------------------\n const cwd = process.cwd();\n const resolvedTarget = opts.targetDir ? path.resolve(opts.targetDir) : cwd;\n\n // Ensure resolved path stays within cwd ā no sneaky ../../etc tricks\n const cwdWithSep = cwd.endsWith(path.sep) ? cwd : cwd + path.sep;\n if (resolvedTarget !== cwd && !resolvedTarget.startsWith(cwdWithSep)) {\n return {\n success: false,\n added: [],\n skipped: [],\n scriptsAdded: [],\n installed: false,\n packageJsonPath: '',\n // FIX 5 (M-4): do not leak absolute paths in error messages\n error: `Path traversal rejected: target directory is outside the allowed working directory`,\n };\n }\n\n // -------------------------------------------------------------------------\n // Find package.json (existence check before symlink resolution)\n // -------------------------------------------------------------------------\n const preResolvePackageJsonPath = path.join(resolvedTarget, 'package.json');\n\n if (!existsSync(preResolvePackageJsonPath)) {\n return {\n success: false,\n ...emptyResult,\n error: `No package.json found in ${resolvedTarget}`,\n };\n }\n\n // -------------------------------------------------------------------------\n // Security: directory-level symlink bypass guard (B2)\n // -------------------------------------------------------------------------\n let realTarget: string;\n try {\n realTarget = realpathSync(resolvedTarget);\n } catch {\n return {\n success: false,\n added: [],\n skipped: [],\n scriptsAdded: [],\n installed: false,\n packageJsonPath: '',\n error: `Could not resolve real path of target directory`,\n };\n }\n\n const realCwd = realpathSync(cwd);\n const realCwdWithSep = realCwd.endsWith(path.sep) ? realCwd : realCwd + path.sep;\n if (realTarget !== realCwd && !realTarget.startsWith(realCwdWithSep)) {\n return {\n success: false,\n added: [],\n skipped: [],\n scriptsAdded: [],\n installed: false,\n packageJsonPath: '',\n // FIX 5 (M-4): do not leak absolute paths in error messages\n error: `Path traversal rejected: target directory resolved to a location outside the allowed working directory`,\n };\n }\n\n // -------------------------------------------------------------------------\n // Security: file-level symlink guard at package.json (C-1 / FIX 1)\n // -------------------------------------------------------------------------\n // Reconstruct package.json path from the symlink-resolved target directory.\n // This prevents readFileSync / writeFileSync from following a file-level\n // symlink planted at <targetDir>/package.json.\n const realPackageJsonPath = path.join(realTarget, 'package.json');\n\n const pkgStat = lstatSync(realPackageJsonPath);\n if (pkgStat.isSymbolicLink()) {\n return {\n ...emptyResult,\n success: false,\n error: `package.json is a symlink ā refusing to read or write`,\n };\n }\n\n // -------------------------------------------------------------------------\n // Security: package name validation (C-2C / L-1)\n // -------------------------------------------------------------------------\n // npm package name spec: optional @scope/, then lowercase alphanumeric + hyphens/dots/underscores\n const VALID_PKG_NAME_RE = /^(@[a-z0-9][a-z0-9\\-._~]*\\/)?[a-z0-9][a-z0-9\\-._~]*$/;\n const allPkgNames = [\n ...Object.keys(opts.packages ?? {}),\n ...Object.keys(opts.devPackages ?? {}),\n ];\n for (const pkg of allPkgNames) {\n if (!VALID_PKG_NAME_RE.test(pkg)) {\n return {\n ...emptyResult,\n success: false,\n error: `Invalid package name: '${pkg}' ā must match npm package name specification`,\n };\n }\n }\n\n // -------------------------------------------------------------------------\n // Security: version string allowlist (C-2B / FIX 2B)\n // -------------------------------------------------------------------------\n // Allows: semver ranges (^1.0.0, ~2.1, >=3, 1.x, *), workspace:*, latest/next/beta/alpha/canary/rc\n // Blocks: git+https://, file:, npm:evil@, http://, ssh://, etc.\n const SAFE_VERSION_RE =\n /^(workspace:[*^~]?|\\*|latest|next|beta|alpha|canary|rc|[~^><=*|, ]*[\\d.x*][\\d.x*\\-+a-zA-Z.~^><=*|, ]*)$/;\n const allVersionEntries = [\n ...Object.entries(opts.packages ?? {}),\n ...Object.entries(opts.devPackages ?? {}),\n ];\n for (const [pkg, version] of allVersionEntries) {\n if (!SAFE_VERSION_RE.test(version.trim())) {\n return {\n ...emptyResult,\n success: false,\n error: `Unsafe version specifier for '${pkg}': '${version}' ā only semver ranges, workspace:*, and dist-tags (latest/next/beta) are permitted`,\n };\n }\n }\n\n // -------------------------------------------------------------------------\n // Security: lifecycle script key blocklist (C-2A / FIX 2A)\n // -------------------------------------------------------------------------\n const BLOCKED_LIFECYCLE_KEYS = new Set([\n 'preinstall',\n 'install',\n 'postinstall',\n 'prepare',\n 'prepublish',\n 'prepublishOnly',\n 'prepack',\n 'postpack',\n 'dependencies', // pnpm hook key\n ]);\n if (opts.scripts) {\n for (const key of Object.keys(opts.scripts)) {\n if (BLOCKED_LIFECYCLE_KEYS.has(key)) {\n return {\n ...emptyResult,\n success: false,\n error: `Blocked lifecycle script key: '${key}' ā writing npm lifecycle hooks is not permitted`,\n };\n }\n }\n }\n\n // -------------------------------------------------------------------------\n // Read & parse\n // -------------------------------------------------------------------------\n const raw = readFileSync(realPackageJsonPath, 'utf8');\n\n // W2: Validate package.json structure with Zod before touching anything\n const PackageJsonSchema = z\n .object({\n // Zod v4: z.record(keySchema, valueSchema) ā two-arg form required\n dependencies: z.record(z.string(), z.string()).optional(),\n devDependencies: z.record(z.string(), z.string()).optional(),\n scripts: z.record(z.string(), z.string()).optional(),\n })\n .passthrough();\n\n const schemaResult = PackageJsonSchema.safeParse(JSON.parse(raw));\n if (!schemaResult.success) {\n return {\n ...emptyResult,\n success: false,\n error: `Invalid package.json structure: ${schemaResult.error.message}`,\n };\n }\n // FIX 4 (B-new-2): The schema has already validated the shape ā the cast is earned.\n // passthrough() + noUncheckedIndexedAccess would otherwise broaden field types to unknown.\n const parsed = schemaResult.data as PackageJson;\n\n // -------------------------------------------------------------------------\n // Merge dependencies ā NEVER overwrite existing version pins\n // -------------------------------------------------------------------------\n const added: string[] = [];\n const skipped: string[] = [];\n const scriptsAdded: string[] = [];\n\n // Live Set grows as packages are written ā prevents same pkg landing in both buckets (B4).\n // Uses `in` semantics (not falsy) so empty-string versions are treated as existing (B3).\n const claimedPkgs = new Set<string>([\n ...Object.keys(parsed.dependencies ?? {}),\n ...Object.keys(parsed.devDependencies ?? {}),\n ]);\n\n // Regular dependencies\n parsed.dependencies = parsed.dependencies ?? {};\n for (const [pkg, version] of Object.entries(opts.packages)) {\n if (claimedPkgs.has(pkg)) {\n skipped.push(pkg);\n } else {\n parsed.dependencies[pkg] = version;\n claimedPkgs.add(pkg);\n added.push(pkg);\n }\n }\n\n // Dev dependencies\n if (opts.devPackages && Object.keys(opts.devPackages).length > 0) {\n parsed.devDependencies = parsed.devDependencies ?? {};\n for (const [pkg, version] of Object.entries(opts.devPackages)) {\n if (claimedPkgs.has(pkg)) {\n skipped.push(pkg);\n } else {\n parsed.devDependencies[pkg] = version;\n claimedPkgs.add(pkg);\n added.push(pkg);\n }\n }\n }\n\n // Scripts ā same never-overwrite semantics\n if (opts.scripts && Object.keys(opts.scripts).length > 0) {\n parsed.scripts = parsed.scripts ?? {};\n for (const [key, value] of Object.entries(opts.scripts)) {\n if (parsed.scripts[key] === undefined) {\n parsed.scripts[key] = value;\n scriptsAdded.push(key);\n }\n }\n }\n\n // -------------------------------------------------------------------------\n // Write back ā use realPackageJsonPath (symlink-resolved) for all I/O\n // -------------------------------------------------------------------------\n writeFileSync(realPackageJsonPath, JSON.stringify(parsed, null, 2) + '\\n');\n\n // -------------------------------------------------------------------------\n // Run pnpm install (optional, non-fatal on failure)\n // -------------------------------------------------------------------------\n let installed = false;\n let installError: string | undefined;\n\n if (opts.runInstall) {\n try {\n execSync('pnpm install', { cwd: realTarget, stdio: 'pipe', timeout: 60_000 });\n installed = true;\n } catch (err) {\n // Don't blow up the whole tool ā install failure is recoverable.\n // The caller can re-run or handle manually.\n installed = false;\n const spawnErr = err as { stderr?: Buffer; message?: string };\n installError =\n spawnErr.stderr?.toString().trim() ||\n (err instanceof Error ? err.message : 'unknown error');\n }\n }\n\n return {\n success: true,\n added,\n skipped,\n scriptsAdded,\n installed,\n packageJsonPath: realPackageJsonPath,\n ...(installError !== undefined ? { installError } : {}),\n };\n } catch (err) {\n return {\n ...emptyResult,\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n}\n","/**\n * Question Presentation MCP Tool\n *\n * Wraps ask_user_question with safe question adaptation so the foreman otter\n * never has to construct the nested questions array itself ā which causes\n * consistent serialization failures where the LLM passes the array as a\n * JSON string instead of a native array.\n *\n * The tool accepts manifest-format questions (what specialist otters produce),\n * adapts them via the shared question-adapter, and calls ask_user_question\n * with a guaranteed-correct native array.\n *\n * When `questions` is omitted, the tool reads from\n * .stackwright/question-manifest.json automatically by phase name.\n */\n\nimport { readFile, writeFile } from 'node:fs/promises';\nimport { existsSync, lstatSync, mkdirSync, renameSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { adaptQuestions, type QuestionManifestQuestion } from '../question-adapter.js';\nimport { jsonCoerce } from '../coerce.js';\n\nconst ManifestQuestionSchema = z.object({\n id: z.string(),\n question: z.string(),\n type: z.enum(['text', 'select', 'multi-select', 'confirm']),\n required: z.boolean().optional(),\n options: z\n .array(\n z.object({\n label: z.string(),\n value: z.string(),\n })\n )\n .optional(),\n default: z.union([z.string(), z.boolean(), z.array(z.string())]).optional(),\n help: z.string().optional(),\n dependsOn: z\n .object({\n questionId: z.string(),\n value: z.union([z.string(), z.array(z.string())]),\n })\n .optional(),\n});\n\nexport function registerQuestionTools(server: McpServer): void {\n server.tool(\n 'stackwright_pro_present_phase_questions',\n 'Adapt manifest-format questions from a specialist otter and present them to the user via ask_user_question. ' +\n 'Pass only the phase name ā this tool reads questions from .stackwright/question-manifest.json automatically. ' +\n 'The questions parameter is optional and only needed if the manifest has not been written yet. ' +\n 'Use this instead of calling ask_user_question directly ā it handles label truncation (50-char limit), ' +\n 'header generation, confirm/text defaults, and correct array formatting automatically. ' +\n 'IMPORTANT: This is the ONLY approved way to prepare questions before calling ask_user_question. ' +\n 'Never call ask_user_question with raw manifest questions. ' +\n 'Never retry ask_user_question validation errors by calling it directly ā always re-call this tool.',\n {\n phase: z.string().describe('Phase name for display context, e.g. \"designer\", \"api\", \"auth\"'),\n questions: jsonCoerce(z.array(ManifestQuestionSchema).optional()).describe(\n 'Questions in Question Manifest format. If omitted, questions are read ' +\n 'from .stackwright/question-manifest.json using the phase name.'\n ),\n answers: jsonCoerce(\n z.record(z.string(), z.union([z.string(), z.array(z.string()), z.boolean()])).optional()\n ).describe('Previously collected answers used to resolve dependsOn conditions'),\n },\n async ({ phase, questions, answers }) => {\n // Resolution order:\n // 1. Use questions param if provided (explicit)\n // 2. Try per-phase file: .stackwright/questions/{phase}.json (new sink model)\n // 3. Fall back to monolithic manifest: .stackwright/question-manifest.json (legacy)\n let resolvedQuestions: QuestionManifestQuestion[];\n\n // Validate phase name ā prevent path traversal (CWE-22)\n const SAFE_PHASE = /^[a-z][a-z0-9-]{0,30}$/;\n if (!SAFE_PHASE.test(phase)) {\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify({\n error: `Invalid phase name: \"${phase.slice(0, 50)}\". Must be lowercase alphanumeric with hyphens, max 31 chars.`,\n }),\n },\n ],\n isError: true,\n };\n }\n\n if (questions && questions.length > 0) {\n resolvedQuestions = questions as QuestionManifestQuestion[];\n } else {\n // Try per-phase question file first (Sinks Not Pipes model)\n const phaseQuestionPath = join(process.cwd(), '.stackwright', 'questions', `${phase}.json`);\n try {\n const raw = await readFile(phaseQuestionPath, 'utf-8');\n const phaseData = JSON.parse(raw) as { questions: QuestionManifestQuestion[] };\n resolvedQuestions = (phaseData.questions ?? []) as QuestionManifestQuestion[];\n } catch {\n // Fall back to monolithic manifest (legacy path)\n try {\n const manifestPath = join(process.cwd(), '.stackwright', 'question-manifest.json');\n const raw = await readFile(manifestPath, 'utf-8');\n const manifest = JSON.parse(raw) as {\n phases: { phase: string; questions: QuestionManifestQuestion[] }[];\n };\n const phaseData = manifest.phases.find((p) => p.phase === phase);\n resolvedQuestions = (phaseData?.questions ?? []) as QuestionManifestQuestion[];\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify({\n error: `Could not read question manifest for phase \"${phase}\": ${msg}`,\n hint: 'Write the manifest first, or pass questions directly to this tool.',\n }),\n },\n ],\n isError: true,\n };\n }\n }\n }\n\n // Adapt from manifest format to ask_user_question format\n const adapted = adaptQuestions(resolvedQuestions, answers ?? {});\n\n // Post-adaptation guard: validate all option labels are ā¤50 chars.\n // adaptQuestions() truncates labels to 50 chars; this guard catches any\n // slip-through and surfaces a clear \"50 characters\" message instead of\n // the misleading \"50 items\" message that ask_user_question would produce.\n const labelSchema = z.string().max(50, 'Value should have at most 50 characters');\n for (const q of adapted) {\n for (const opt of q.options) {\n const check = labelSchema.safeParse(opt.label);\n if (!check.success) {\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify({\n error: `Option label for phase \"${phase}\" exceeds 50 characters: ${check.error.issues[0]?.message ?? 'label too long'}. Truncate option labels to ā¤50 characters before calling this tool.`,\n }),\n },\n ],\n isError: true,\n };\n }\n }\n }\n\n if (adapted.length === 0) {\n return {\n content: [\n {\n type: 'text' as const,\n text:\n `Phase \"${phase}\" has no questions to present. ` +\n `Do NOT call ask_user_question. ` +\n `Call stackwright_pro_save_phase_answers({ phase: \"${phase}\", rawAnswers: [] }) directly, then proceed to the execution step for this phase.`,\n },\n {\n type: 'text' as const,\n // Empty array ā second block always present so the foreman's two-block contract holds\n text: JSON.stringify([]),\n },\n ],\n isError: false,\n };\n }\n\n // Return the adapted questions for the foreman to pass to ask_user_question.\n // Two-block format: first block is the instruction, second block is the raw\n // JSON array. Splitting them removes the temptation for the LLM to\n // re-serialise the array when it reads the instruction text.\n return {\n content: [\n {\n type: 'text' as const,\n text:\n `Adapted ${adapted.length} questions for phase \"${phase}\". ` +\n `Pass the JSON array below DIRECTLY to ask_user_question as the \"questions\" parameter. ` +\n `Do NOT JSON.stringify() it. Do NOT wrap it in an object. Pass the parsed array value as-is.`,\n },\n {\n type: 'text' as const,\n text: JSON.stringify(adapted),\n },\n ],\n isError: false,\n };\n }\n );\n\n // ---------------------------------------------------------------------------\n // stackwright_pro_get_next_question\n // ---------------------------------------------------------------------------\n server.tool(\n 'stackwright_pro_get_next_question',\n 'Returns the next unanswered question for a phase as a plain JSON object ā one question at a time. ' +\n 'Returns { done: true } when all questions are answered or the phase has no questions. ' +\n 'Call this in a loop: present the question in plain chat, get user reply, call record_answer, repeat.',\n { phase: z.string().describe('Phase name e.g. \"designer\", \"api\", \"auth\"') },\n async ({ phase }) => {\n const SAFE_PHASE = /^[a-z][a-z0-9-]{0,30}$/;\n if (!SAFE_PHASE.test(phase)) {\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify({ error: `Invalid phase name: \"${phase.slice(0, 50)}\"` }),\n },\n ],\n isError: true,\n };\n }\n\n const cwd = process.cwd();\n\n // Read questions file\n const questionsPath = join(cwd, '.stackwright', 'questions', `${phase}.json`);\n let questions: Array<{\n id: string;\n question: string;\n type: string;\n options?: Array<{ label: string; value: string }>;\n help?: string;\n }> = [];\n try {\n const raw = await readFile(questionsPath, 'utf-8');\n const parsed = JSON.parse(raw) as { questions?: typeof questions };\n questions = parsed.questions ?? [];\n } catch {\n // File missing or malformed ā phase has no questions\n return { content: [{ type: 'text' as const, text: JSON.stringify({ done: true }) }] };\n }\n\n if (questions.length === 0) {\n return { content: [{ type: 'text' as const, text: JSON.stringify({ done: true }) }] };\n }\n\n // Read existing answers to build the answered-ID set\n const answersPath = join(cwd, '.stackwright', 'answers', `${phase}.json`);\n let answeredIds = new Set<string>();\n try {\n const raw = await readFile(answersPath, 'utf-8');\n const parsed = JSON.parse(raw) as { answers?: Record<string, unknown> };\n answeredIds = new Set(Object.keys(parsed.answers ?? {}));\n } catch {\n // File missing ā nothing answered yet\n }\n\n // First unanswered question\n const next = questions.find((q) => !answeredIds.has(q.id));\n if (!next) {\n return { content: [{ type: 'text' as const, text: JSON.stringify({ done: true }) }] };\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify({\n done: false,\n questionId: next.id,\n question: next.question,\n type: next.type,\n options: next.options ?? null,\n help: next.help ?? null,\n index: questions.indexOf(next) + 1,\n total: questions.length,\n }),\n },\n ],\n };\n }\n );\n\n // ---------------------------------------------------------------------------\n // stackwright_pro_record_answer\n // ---------------------------------------------------------------------------\n server.tool(\n 'stackwright_pro_record_answer',\n 'Records a single answer to a phase question. Appends to .stackwright/answers/{phase}.json incrementally. ' +\n 'Idempotent ā calling twice for the same questionId overwrites. ' +\n 'Call after receiving each user reply in the conversational question loop.',\n {\n phase: z.string().describe('Phase name e.g. \"designer\"'),\n questionId: z.string().describe('The question ID from get_next_question, e.g. \"designer-1\"'),\n answer: z.string().describe(\"The user's free-text answer\"),\n },\n async ({ phase, questionId, answer }) => {\n const SAFE_PHASE = /^[a-z][a-z0-9-]{0,30}$/;\n if (!SAFE_PHASE.test(phase)) {\n return {\n content: [\n { type: 'text' as const, text: JSON.stringify({ error: 'Invalid phase name' }) },\n ],\n isError: true,\n };\n }\n if (!/^[a-z0-9][a-z0-9-]{0,63}$/i.test(questionId)) {\n return {\n content: [\n { type: 'text' as const, text: JSON.stringify({ error: 'Invalid questionId' }) },\n ],\n isError: true,\n };\n }\n const safeAnswer = answer.slice(0, 2000);\n\n const cwd = process.cwd();\n const answersDir = join(cwd, '.stackwright', 'answers');\n const answersPath = join(answersDir, `${phase}.json`);\n\n // Symlink guard on directory\n if (existsSync(answersDir) && lstatSync(answersDir).isSymbolicLink()) {\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify({ error: 'answers dir is a symlink ā refusing to write' }),\n },\n ],\n isError: true,\n };\n }\n mkdirSync(answersDir, { recursive: true });\n\n // Read existing or start fresh\n let existing: {\n version: string;\n phase: string;\n answers: Record<string, string>;\n updatedAt?: string;\n } = {\n version: '1.0',\n phase,\n answers: {},\n };\n try {\n if (existsSync(answersPath)) {\n if (lstatSync(answersPath).isSymbolicLink()) {\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify({ error: 'answers file is a symlink ā refusing to write' }),\n },\n ],\n isError: true,\n };\n }\n const raw = await readFile(answersPath, 'utf-8');\n existing = JSON.parse(raw) as typeof existing;\n }\n } catch {\n // Malformed ā start fresh\n }\n\n // Upsert\n existing.answers[questionId] = safeAnswer;\n existing.updatedAt = new Date().toISOString();\n\n // Atomic write via tmp+rename\n const tmp = `${answersPath}.tmp`;\n await writeFile(tmp, JSON.stringify(existing, null, 2), 'utf-8');\n renameSync(tmp, answersPath);\n\n return {\n content: [\n { type: 'text' as const, text: JSON.stringify({ recorded: true, phase, questionId }) },\n ],\n };\n }\n );\n}\n","/**\n * Question Adapter - Converts between Question Manifest format and ask_user_question format\n *\n * The ask_user_question MCP tool requires:\n * - question: string (full text)\n * - header: string (max 12 chars, short label)\n * - multi_select: boolean\n * - options: {label, description}[] (REQUIRED, min 2)\n *\n * Our Question Manifest format has:\n * - id: string (e.g., \"api-1\")\n * - question: string\n * - type: 'text' | 'select' | 'multi-select' | 'confirm'\n * - options?: {label, value}[] (optional for text/confirm)\n * - required?: boolean\n * - default?: string | boolean | string[]\n * - dependsOn?: {questionId, value}\n */\n\nexport interface QuestionManifestQuestion {\n id: string;\n question: string;\n type: 'text' | 'select' | 'multi-select' | 'confirm';\n required?: boolean;\n options?: { label: string; value: string }[];\n default?: string | boolean | string[];\n help?: string;\n dependsOn?: {\n questionId: string;\n value: string | string[];\n };\n}\n\nexport interface AskUserQuestionOption {\n label: string;\n description?: string;\n}\n\nexport interface AskUserQuestion {\n question: string;\n header: string;\n multi_select: boolean;\n options: AskUserQuestionOption[];\n}\n\n/**\n * Truncate string to max length, adding ellipsis if needed\n */\nfunction truncate(str: string, maxLength: number): string {\n if (str.length <= maxLength) return str;\n return str.substring(0, maxLength - 1) + 'ā¦';\n}\n\n/**\n * Generate a valid header from a question ID\n * Headers must be max 12 chars, alphanumeric with hyphens\n */\nfunction generateHeader(id: string): string {\n // Remove numbers and prefix, keep meaningful part\n // e.g., \"api-1\" -> \"API-1\", \"auth-3\" -> \"AUTH-3\"\n const parts = id.split('-');\n if (parts.length >= 2) {\n const prefix = parts[0].toUpperCase().substring(0, 4);\n const num = parts[1];\n return truncate(`${prefix}-${num}`, 12);\n }\n return truncate(\n id\n .toUpperCase()\n .replace(/[^A-Z0-9]/g, '')\n .substring(0, 12),\n 12\n );\n}\n\n/**\n * Generate default options for question types that don't have options\n */\nfunction generateDefaultOptions(type: string): AskUserQuestionOption[] {\n switch (type) {\n case 'confirm':\n return [\n { label: 'Yes', description: 'Enable or confirm this option' },\n { label: 'No', description: 'Disable or decline this option' },\n ];\n case 'text':\n return [\n { label: 'Specify', description: 'I will provide a specific value' },\n { label: 'Skip', description: 'Use default or skip this question' },\n ];\n default:\n return [\n { label: 'Option 1', description: 'First option' },\n { label: 'Option 2', description: 'Second option' },\n ];\n }\n}\n\n/**\n * Convert a single QuestionManifest question to ask_user_question format\n */\nexport function adaptQuestion(q: QuestionManifestQuestion): AskUserQuestion {\n // Generate header from ID\n const header = generateHeader(q.id);\n\n // Determine multi_select\n const multiSelect = q.type === 'multi-select';\n\n // Handle options - use provided or generate defaults\n let options: AskUserQuestionOption[];\n\n if (q.options && q.options.length >= 2) {\n // Use provided options, adapt format\n options = q.options.map((opt) => ({\n label: truncate(opt.label, 50),\n description: opt.value !== opt.label ? opt.value : undefined,\n }));\n } else if (q.options && q.options.length === 1) {\n // Single option - add a default\n options = [\n ...q.options.map((opt) => ({ label: truncate(opt.label, 50), description: opt.value })),\n { label: 'Other', description: 'Specify a different value' },\n ];\n } else {\n // No options - generate defaults based on type\n options = generateDefaultOptions(q.type);\n }\n\n // Ensure minimum 2 options (MCP tool requirement)\n if (options.length < 2) {\n options.push({ label: 'Other', description: 'Alternative option' });\n }\n\n // Limit to 6 options (MCP tool max)\n options = options.slice(0, 6);\n\n return {\n question: q.question + (q.help ? `\\n\\n${q.help}` : ''),\n header,\n multi_select: multiSelect,\n options,\n };\n}\n\n/**\n * Adapt multiple questions, filtering by dependsOn\n *\n * @param questions - All questions from manifest\n * @param answers - Previously answered questions (for filtering conditionals)\n * @returns Questions adapted for ask_user_question, with conditionals resolved\n */\nexport function adaptQuestions(\n questions: QuestionManifestQuestion[],\n answers: Record<string, string | string[] | boolean> = {}\n): AskUserQuestion[] {\n const adapted: AskUserQuestion[] = [];\n\n for (const q of questions) {\n // Check dependsOn condition\n if (q.dependsOn) {\n const dependsAnswer = answers[q.dependsOn.questionId];\n if (dependsAnswer === undefined) {\n // Parent question not answered yet - skip this conditional question\n continue;\n }\n\n // Check if the answer matches the condition\n const expectedValues = Array.isArray(q.dependsOn.value)\n ? q.dependsOn.value\n : [q.dependsOn.value];\n\n const answerValue = Array.isArray(dependsAnswer) ? dependsAnswer[0] : dependsAnswer;\n\n if (!expectedValues.includes(answerValue as string)) {\n // Condition not met - skip this question\n continue;\n }\n }\n\n adapted.push(adaptQuestion(q));\n }\n\n return adapted;\n}\n\n/**\n * Parse JSON response from LLM (handles various formats)\n */\nexport function parseLLMQuestionsResponse(text: string): QuestionManifestQuestion[] {\n // Try to extract JSON from the response\n let jsonStr = text;\n\n // Remove markdown code blocks\n jsonStr = jsonStr.replace(/```(?:json|javascript)?\\s*/gi, '');\n jsonStr = jsonStr.replace(/```\\s*$/gm, '');\n\n // Find JSON object or array\n const firstBrace = jsonStr.indexOf('{');\n const firstBracket = jsonStr.indexOf('[');\n\n let start = -1;\n if (firstBrace !== -1 && firstBracket !== -1) {\n start = Math.min(firstBrace, firstBracket);\n } else if (firstBrace !== -1) {\n start = firstBrace;\n } else if (firstBracket !== -1) {\n start = firstBracket;\n }\n\n if (start === -1) {\n throw new Error('No JSON found in response');\n }\n\n jsonStr = jsonStr.substring(start);\n\n // Handle trailing text after JSON\n const lastBrace = jsonStr.lastIndexOf('}');\n const lastBracket = jsonStr.lastIndexOf(']');\n const end = Math.max(lastBrace, lastBracket);\n\n if (end === -1) {\n throw new Error('Invalid JSON structure');\n }\n\n jsonStr = jsonStr.substring(0, end + 1);\n\n // Fix common issues\n jsonStr = jsonStr.replace(/,(\\s*[}\\]])/g, '$1'); // Remove trailing commas\n jsonStr = jsonStr.replace(/'/g, '\"'); // Single quotes to double\n\n const parsed = JSON.parse(jsonStr);\n\n // Handle various JSON structures\n let questions: unknown[];\n\n if (Array.isArray(parsed)) {\n questions = parsed;\n } else if (parsed.questions && Array.isArray(parsed.questions)) {\n questions = parsed.questions;\n } else if (parsed.data && Array.isArray((parsed.data as Record<string, unknown>).questions)) {\n questions = (parsed.data as Record<string, unknown>).questions as unknown[];\n } else {\n throw new Error('No questions array found in response');\n }\n\n // Sanitize: strip __proto__, constructor, prototype keys recursively\n // to prevent prototype pollution attacks from malicious LLM output\n function sanitize(obj: Record<string, unknown>): Record<string, unknown> {\n const sanitized: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n if (key === '__proto__' || key === 'constructor' || key === 'prototype') {\n // Skip prototype pollution vectors ā they could affect downstream parsing\n continue;\n }\n const val = obj[key];\n if (val && typeof val === 'object' && !Array.isArray(val)) {\n sanitized[key] = sanitize(val as Record<string, unknown>);\n } else if (Array.isArray(val)) {\n sanitized[key] = val.map((item) =>\n item && typeof item === 'object' && !Array.isArray(item)\n ? sanitize(item as Record<string, unknown>)\n : item\n );\n } else {\n sanitized[key] = val;\n }\n }\n return sanitized;\n }\n\n // Apply sanitization to each question object\n questions = questions.map((q) => {\n if (q && typeof q === 'object') {\n return sanitize(q as Record<string, unknown>);\n }\n return q;\n }) as QuestionManifestQuestion[];\n\n return questions;\n}\n\n/**\n * Convert ask_user_question answers back to manifest format\n */\nexport function answersToManifestFormat(\n answers: { question_header: string; selected_options: string[]; other_text?: string | null }[],\n questions: QuestionManifestQuestion[]\n): Record<string, string | string[] | boolean> {\n const result: Record<string, string | string[] | boolean> = {};\n\n for (const answer of answers) {\n // Find matching question by header\n const headerLower = answer.question_header.toLowerCase();\n const question = questions.find((q) => {\n const qHeader = generateHeader(q.id).toLowerCase();\n return qHeader === headerLower || q.id.toLowerCase().includes(headerLower);\n });\n\n if (!question) {\n // Try to match by header prefix\n const matched = questions.find((q) => {\n const qHeader = generateHeader(q.id).toLowerCase();\n return qHeader.startsWith(headerLower.split('-')[0]);\n });\n if (matched) {\n result[matched.id] = answer.selected_options[0] || '';\n }\n continue;\n }\n\n // Handle multi-select vs single select\n if (question.type === 'multi-select' || answer.selected_options.length > 1) {\n result[question.id] = answer.selected_options;\n } else if (question.type === 'confirm') {\n result[question.id] = answer.selected_options[0] === 'Yes';\n } else {\n // For text or single select, use first option or other_text\n if (answer.other_text) {\n result[question.id] = answer.other_text;\n } else if (answer.selected_options.length > 0) {\n // Map label back to value if possible\n const option = question.options?.find((o) => o.label === answer.selected_options[0]);\n result[question.id] = option?.value ?? answer.selected_options[0];\n }\n }\n }\n\n return result;\n}\n","/**\n * Orchestration MCP Tools\n *\n * Moves mechanical Type B logic out of the foreman otter's system prompt\n * into tested TypeScript. Reduces foreman prompt from ~2,750 words to ~600 words,\n * enabling reliable operation on 7B parameter models for airgapped deployments.\n *\n * These tools replace pseudocode that was previously embedded in the foreman\n * prompt as inline helper functions and procedural instructions.\n */\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { jsonCoerce } from '../coerce.js';\nimport { readFileSync, writeFileSync, existsSync, mkdirSync, lstatSync } from 'fs';\nimport { join } from 'path';\nimport {\n parseLLMQuestionsResponse,\n answersToManifestFormat,\n type QuestionManifestQuestion,\n} from '../question-adapter.js';\n\n// ---------------------------------------------------------------------------\n// Constants ā version-controlled, not buried in a 2,750-word prompt\n// ---------------------------------------------------------------------------\n\n/**\n * Maps otter name substrings ā canonical phase name.\n * Order matters: more-specific entries first.\n */\nconst OTTER_NAME_TO_PHASE: Array<[string, string]> = [\n ['designer', 'designer'],\n ['theme', 'theme'],\n ['api', 'api'],\n ['auth', 'auth'],\n ['dashboard', 'dashboard'],\n ['data', 'data'],\n ['page', 'pages'],\n ['workflow', 'workflow'],\n ['polish', 'polish'],\n ['geo', 'geo'],\n];\n\nconst PHASE_TO_OTTER: Record<string, string> = {\n designer: 'stackwright-pro-designer-otter',\n theme: 'stackwright-pro-theme-otter',\n api: 'stackwright-pro-api-otter',\n auth: 'stackwright-pro-auth-otter',\n pages: 'stackwright-pro-page-otter',\n dashboard: 'stackwright-pro-dashboard-otter',\n data: 'stackwright-pro-data-otter',\n workflow: 'stackwright-pro-workflow-otter',\n polish: 'stackwright-pro-polish-otter',\n geo: 'stackwright-pro-geo-otter',\n};\n\n// ---------------------------------------------------------------------------\n// Phase detection\n// ---------------------------------------------------------------------------\n\nfunction detectPhase(otterName: string): string {\n const lower = otterName.toLowerCase();\n for (const [keyword, phase] of OTTER_NAME_TO_PHASE) {\n if (lower.includes(keyword)) return phase;\n }\n // Fallback: strip well-known wrapper and return whatever's left\n return lower.replace(/^stackwright-pro-/, '').replace(/-otter$/, '');\n}\n\n// ---------------------------------------------------------------------------\n// Handler functions (exported for direct testing ā no MCP server needed)\n// ---------------------------------------------------------------------------\n\nexport interface ParseOtterResponseInput {\n otterName: string;\n responseText: string;\n}\n\nexport interface ParseOtterResponseResult {\n phase: string;\n otter: string;\n questions: QuestionManifestQuestion[];\n error?: true;\n parseError?: string;\n}\n\nexport function handleParseOtterResponse(input: ParseOtterResponseInput): {\n result: ParseOtterResponseResult;\n isError: boolean;\n} {\n const phase = detectPhase(input.otterName);\n try {\n const questions = parseLLMQuestionsResponse(input.responseText);\n return {\n result: { phase, otter: input.otterName, questions },\n isError: false,\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n result: {\n error: true,\n otterName: input.otterName,\n phase,\n questions: [],\n parseError: message,\n } as unknown as ParseOtterResponseResult,\n isError: true,\n };\n }\n}\n\n// ---------------------------------------------------------------------------\n\nexport interface PhaseEntry {\n phase: string;\n otter: string;\n questions: unknown[];\n requiredPackages?: {\n dependencies?: Record<string, string>;\n devPackages?: Record<string, string>;\n };\n}\n\nexport interface SaveManifestInput {\n phases: PhaseEntry[];\n _cwd?: string; // injectable for tests\n}\n\nexport function handleSaveManifest(input: SaveManifestInput): { text: string; isError: boolean } {\n const cwd = input._cwd ?? process.cwd();\n const dir = join(cwd, '.stackwright');\n const filePath = join(dir, 'question-manifest.json');\n try {\n mkdirSync(dir, { recursive: true });\n\n // Symlink guard ā refuse to write through a symlink\n if (existsSync(filePath)) {\n const stat = lstatSync(filePath);\n if (stat.isSymbolicLink()) {\n const message = `Refusing to write to symlink: ${filePath}`;\n return {\n text: JSON.stringify({ success: false, error: message }),\n isError: true,\n };\n }\n }\n\n const manifest = {\n version: '1.0',\n createdAt: new Date().toISOString(),\n phases: input.phases,\n };\n writeFileSync(filePath, JSON.stringify(manifest, null, 2) + '\\n');\n return {\n text: JSON.stringify({ success: true, path: filePath, phaseCount: input.phases.length }),\n isError: false,\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n text: JSON.stringify({ success: false, error: message }),\n isError: true,\n };\n }\n}\n\n// ---------------------------------------------------------------------------\n\nexport interface RawAnswer {\n question_header: string;\n selected_options: string[];\n other_text?: string | null;\n}\n\nexport interface SavePhaseAnswersInput {\n phase: string;\n rawAnswers: RawAnswer[];\n questions?: QuestionManifestQuestion[];\n _cwd?: string; // injectable for tests\n}\n\nexport function handleSavePhaseAnswers(input: SavePhaseAnswersInput): {\n text: string;\n isError: boolean;\n} {\n const cwd = input._cwd ?? process.cwd();\n const dir = join(cwd, '.stackwright', 'answers');\n const filePath = join(dir, `${input.phase}.json`);\n try {\n mkdirSync(dir, { recursive: true });\n\n let answers: Record<string, unknown>;\n if (input.questions && input.questions.length > 0) {\n answers = answersToManifestFormat(input.rawAnswers, input.questions);\n } else {\n // Fallback: no manifest questions provided ā best-effort key extraction\n answers = Object.fromEntries(\n input.rawAnswers.map((a) => [a.question_header, a.selected_options[0] ?? ''])\n );\n }\n\n const payload = {\n version: '1.0',\n phase: input.phase,\n completedAt: new Date().toISOString(),\n answers,\n };\n\n // Symlink guard ā refuse to write through a symlink\n if (existsSync(filePath)) {\n const stat = lstatSync(filePath);\n if (stat.isSymbolicLink()) {\n const message = `Refusing to write to symlink: ${filePath}`;\n return {\n text: JSON.stringify({ success: false, error: message }),\n isError: true,\n };\n }\n }\n\n writeFileSync(filePath, JSON.stringify(payload, null, 2) + '\\n');\n return {\n text: JSON.stringify({\n success: true,\n path: filePath,\n answersCount: Object.keys(answers).length,\n }),\n isError: false,\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n text: JSON.stringify({ success: false, error: message }),\n isError: true,\n };\n }\n}\n\n// ---------------------------------------------------------------------------\n\nexport interface ReadPhaseAnswersInput {\n phase: string;\n _cwd?: string; // injectable for tests\n}\n\nexport function handleReadPhaseAnswers(input: ReadPhaseAnswersInput): {\n text: string;\n isError: boolean;\n} {\n const cwd = input._cwd ?? process.cwd();\n const filePath = join(cwd, '.stackwright', 'answers', `${input.phase}.json`);\n if (!existsSync(filePath)) {\n return {\n text: JSON.stringify({ missing: true, phase: input.phase }),\n isError: false,\n };\n }\n try {\n const raw = readFileSync(filePath, 'utf8');\n const parsed = JSON.parse(raw);\n return { text: JSON.stringify(parsed), isError: false };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n text: JSON.stringify({ error: true, phase: input.phase, readError: message }),\n isError: true,\n };\n }\n}\n\n// ---------------------------------------------------------------------------\n\nexport interface GetOtterNameInput {\n phase: string;\n}\n\nexport function handleGetOtterName(input: GetOtterNameInput): { text: string; isError: boolean } {\n const normalised = input.phase.toLowerCase().trim();\n const otterName = PHASE_TO_OTTER[normalised];\n if (!otterName) {\n return {\n text: JSON.stringify({ error: true, message: `Unknown phase: ${input.phase}` }),\n isError: true,\n };\n }\n return {\n text: JSON.stringify({ phase: normalised, otterName }),\n isError: false,\n };\n}\n\n// ---------------------------------------------------------------------------\n\nexport interface SaveBuildContextInput {\n buildContext: string;\n _cwd?: string;\n}\n\nexport function handleSaveBuildContext(input: SaveBuildContextInput): {\n text: string;\n isError: boolean;\n} {\n const cwd = input._cwd ?? process.cwd();\n const dir = join(cwd, '.stackwright');\n const filePath = join(dir, 'build-context.json');\n try {\n mkdirSync(dir, { recursive: true });\n\n // Symlink guard\n if (existsSync(filePath)) {\n const stat = lstatSync(filePath);\n if (stat.isSymbolicLink()) {\n return {\n text: JSON.stringify({\n success: false,\n error: `Refusing to write to symlink: ${filePath}`,\n }),\n isError: true,\n };\n }\n }\n\n const payload = {\n version: '1.0',\n savedAt: new Date().toISOString(),\n buildContext: input.buildContext,\n };\n writeFileSync(filePath, JSON.stringify(payload, null, 2) + '\\n');\n return {\n text: JSON.stringify({ success: true, path: filePath }),\n isError: false,\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n text: JSON.stringify({ success: false, error: message }),\n isError: true,\n };\n }\n}\n\n// ---------------------------------------------------------------------------\n// MCP tool registration\n// ---------------------------------------------------------------------------\n\nexport function registerOrchestrationTools(server: McpServer): void {\n // -------------------------------------------------------------------------\n // 0. stackwright_pro_save_build_context\n // -------------------------------------------------------------------------\n server.tool(\n 'stackwright_pro_save_build_context',\n \"Save the user's initial build description to .stackwright/build-context.json. \" +\n 'Call this once at startup after the user answers the opening \"what are you building\" question. ' +\n 'The saved context is automatically prepended to specialist prompts by stackwright_pro_build_specialist_prompt.',\n {\n buildContext: z.string().describe('Free-text description of what the user wants to build'),\n },\n async ({ buildContext }) => {\n const { text, isError } = handleSaveBuildContext({ buildContext });\n return {\n content: [{ type: 'text' as const, text }],\n isError,\n };\n }\n );\n\n // -------------------------------------------------------------------------\n // 1. stackwright_pro_parse_otter_response\n // -------------------------------------------------------------------------\n server.tool(\n 'stackwright_pro_parse_otter_response',\n \"Parse and validate a specialist otter's QUESTION_COLLECTION_MODE JSON response. \" +\n 'Handles JSON extraction from LLM responses (strips markdown, fixes single quotes, trailing commas). ' +\n 'Detects the phase from the otter name. ' +\n 'Use this immediately after invoke_agent() to get a validated manifest phase object.',\n {\n otterName: z.string().describe('The agent name, e.g. \"stackwright-pro-api-otter\"'),\n responseText: z\n .string()\n .describe(\"Raw text response from the otter's QUESTION_COLLECTION_MODE invocation\"),\n },\n async ({ otterName, responseText }) => {\n const { result, isError } = handleParseOtterResponse({ otterName, responseText });\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(result) }],\n isError,\n };\n }\n );\n\n // -------------------------------------------------------------------------\n // 2. stackwright_pro_save_manifest\n // -------------------------------------------------------------------------\n server.tool(\n 'stackwright_pro_save_manifest',\n 'Write the question manifest to .stackwright/question-manifest.json. ' +\n 'Call this after collecting and parsing questions from all otters via stackwright_pro_parse_otter_response.',\n {\n phases: jsonCoerce(\n z.array(\n z.object({\n phase: z.string(),\n otter: z.string(),\n questions: z.array(z.any()),\n requiredPackages: z\n .object({\n dependencies: z.record(z.string(), z.string()).optional(),\n devPackages: z.record(z.string(), z.string()).optional(),\n })\n .optional(),\n })\n )\n ).describe('Array of parsed phase objects from stackwright_pro_parse_otter_response'),\n },\n async ({ phases }) => {\n const { text, isError } = handleSaveManifest({ phases });\n return {\n content: [{ type: 'text' as const, text }],\n isError,\n };\n }\n );\n\n // -------------------------------------------------------------------------\n // 3. stackwright_pro_save_phase_answers\n // -------------------------------------------------------------------------\n server.tool(\n 'stackwright_pro_save_phase_answers',\n 'Save user answers for a phase to .stackwright/answers/{phase}.json. ' +\n 'Pass rawAnswers directly from ask_user_question and the original manifest questions for label-to-value reverse mapping.',\n {\n phase: z.string().describe('Phase name, e.g. \"designer\"'),\n rawAnswers: jsonCoerce(\n z.array(\n z.object({\n question_header: z.string(),\n selected_options: z.array(z.string()),\n other_text: z.string().nullable().optional(),\n })\n )\n ).describe(\n 'Answers as returned by ask_user_question ā pass the native array, not a JSON string'\n ),\n questions: jsonCoerce(z.array(z.any()).optional()).describe(\n 'Original manifest questions for labelāvalue reverse-mapping ā pass the native array, not a JSON string'\n ),\n },\n async ({ phase, rawAnswers, questions }) => {\n const { text, isError } = handleSavePhaseAnswers({\n phase,\n rawAnswers,\n ...(questions && questions.length > 0\n ? { questions: questions as QuestionManifestQuestion[] }\n : {}),\n });\n return {\n content: [{ type: 'text' as const, text }],\n isError,\n };\n }\n );\n\n // -------------------------------------------------------------------------\n // 4. stackwright_pro_read_phase_answers\n // -------------------------------------------------------------------------\n server.tool(\n 'stackwright_pro_read_phase_answers',\n 'Read saved answers for a phase from .stackwright/answers/{phase}.json. ' +\n 'Returns { missing: true } when no answers exist yet ā use this to skip phases safely in the execution loop.',\n {\n phase: z.string().describe('Phase name, e.g. \"designer\"'),\n },\n async ({ phase }) => {\n const { text, isError } = handleReadPhaseAnswers({ phase });\n return {\n content: [{ type: 'text' as const, text }],\n isError,\n };\n }\n );\n\n // -------------------------------------------------------------------------\n // 5. stackwright_pro_get_otter_name\n // -------------------------------------------------------------------------\n server.tool(\n 'stackwright_pro_get_otter_name',\n \"Get the agent name for a phase (e.g. 'designer' ā 'stackwright-pro-designer-otter'). \" +\n 'Use this in the execution loop to invoke the correct specialist otter without hardcoding names in the prompt.',\n {\n phase: z.string().describe('Phase name, e.g. \"designer\", \"api\", \"pages\"'),\n },\n async ({ phase }) => {\n const { text, isError } = handleGetOtterName({ phase });\n return {\n content: [{ type: 'text' as const, text }],\n isError,\n };\n }\n );\n}\n","/**\n * Pipeline State & Artifact Management Tools ā \"Sinks Not Pipes\"\n *\n * The filesystem IS the state machine. Every tool reads/writes to `.stackwright/`.\n * Specialists produce artifacts ā validated here. Retry logic lives HERE.\n */\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { readFileSync, writeFileSync, existsSync, mkdirSync, lstatSync } from 'fs';\nimport { join } from 'path';\nimport { parseLLMQuestionsResponse } from '../question-adapter.js';\nimport { boolCoerce, jsonCoerce } from '../coerce.js';\nimport { createHash } from 'crypto';\nimport {\n initPipelineKeys,\n loadPipelineKeys,\n signArtifact,\n verifyArtifact,\n getArtifactSignature,\n saveArtifactSignature,\n emitSignatureAuditEvent,\n loadSignatureManifest,\n} from '../artifact-signing.js';\n\n// āāā Canonical pro type schemas for artifact validation āāāāāāāāāāāāāāāāāāāāā\nimport { WorkflowFileSchema, authConfigSchema } from '@stackwright-pro/types';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n/** Canonical phase execution order */\nconst PHASE_ORDER = [\n 'designer',\n 'theme',\n 'api',\n 'data',\n 'geo',\n 'workflow',\n 'services',\n 'pages',\n 'dashboard',\n 'auth',\n 'polish',\n] as const;\ntype Phase = (typeof PHASE_ORDER)[number];\n\n/** Phase dependency graph: what upstream artifacts each phase needs */\nconst PHASE_DEPENDENCIES: Record<Phase, readonly Phase[]> = {\n designer: [],\n theme: ['designer'],\n api: [],\n data: ['api'],\n geo: ['data'],\n // workflow: no hard deps ā uses service: references with Prism mock fallback\n // when API artifacts aren't available; roles come from user answers\n workflow: [],\n // services: needs API endpoints to know what to wire, and optionally\n // workflow states as trigger sources. Produces OpenAPI specs consumed\n // by pages and dashboard for typed data wiring.\n services: ['api', 'workflow'],\n // pages/dashboard: now also depend on services for typed endpoint wiring\n // via the OpenAPI specs that services produces.\n // 'api' is still transitive through 'data'; auth removed ā page-otter has\n // graceful fallback and reads role names from workflow artifacts instead\n pages: ['designer', 'theme', 'data', 'services'],\n dashboard: ['designer', 'theme', 'data', 'services'],\n // auth is the penultimate phase ā runs after all content-producing phases\n // so it can read pages, dashboard, workflow, and geo artifacts for route\n // protection and RBAC wiring. Skipped upstream phases still satisfy deps\n // (the foreman marks them executed=true), so auth always runs.\n auth: ['pages', 'dashboard', 'workflow', 'geo'],\n // polish is the terminal phase ā runs after auth so the landing page and\n // nav reflect the final set of protected routes and all generated pages.\n polish: ['auth'],\n};\n\n/** Maps phase ā expected artifact filename */\nconst PHASE_ARTIFACT: Record<Phase, string> = {\n designer: 'design-language.json',\n theme: 'theme-tokens.json',\n api: 'api-config.json',\n auth: 'auth-config.json',\n data: 'data-config.json',\n pages: 'pages-manifest.json',\n dashboard: 'dashboard-manifest.json',\n workflow: 'workflow-config.json',\n services: 'services-config.json',\n polish: 'polish-manifest.json',\n geo: 'geo-manifest.json',\n};\n\n/** Maps phase ā otter agent name */\nconst PHASE_TO_OTTER: Record<Phase, string> = {\n designer: 'stackwright-pro-designer-otter',\n theme: 'stackwright-pro-theme-otter',\n api: 'stackwright-pro-api-otter',\n auth: 'stackwright-pro-auth-otter',\n data: 'stackwright-pro-data-otter',\n pages: 'stackwright-pro-page-otter',\n dashboard: 'stackwright-pro-dashboard-otter',\n workflow: 'stackwright-pro-workflow-otter',\n services: 'stackwright-services-otter',\n polish: 'stackwright-pro-polish-otter',\n geo: 'stackwright-pro-geo-otter',\n};\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface PhaseStatus {\n questionsCollected: boolean;\n answered: boolean;\n executed: boolean;\n artifactWritten: boolean;\n retryCount: number;\n}\n\nexport interface PipelineState {\n version: '1.0';\n currentPhase: string;\n status: 'setup' | 'questions' | 'execution' | 'done';\n phases: Record<string, PhaseStatus>;\n startedAt: string;\n updatedAt: string;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction isValidPhase(phase: string): phase is Phase {\n return (PHASE_ORDER as readonly string[]).includes(phase);\n}\n\nfunction defaultPhaseStatus(): PhaseStatus {\n return {\n questionsCollected: false,\n answered: false,\n executed: false,\n artifactWritten: false,\n retryCount: 0,\n };\n}\n\nfunction createDefaultState(): PipelineState {\n const now = new Date().toISOString();\n const phases: Record<string, PhaseStatus> = {};\n for (const p of PHASE_ORDER) {\n phases[p] = defaultPhaseStatus();\n }\n return {\n version: '1.0',\n currentPhase: PHASE_ORDER[0],\n status: 'setup',\n phases,\n startedAt: now,\n updatedAt: now,\n };\n}\n\nfunction statePath(cwd: string): string {\n return join(cwd, '.stackwright', 'pipeline-state.json');\n}\n\nfunction readState(cwd: string): PipelineState {\n const p = statePath(cwd);\n if (!existsSync(p)) return createDefaultState();\n const raw = JSON.parse(safeReadSync(p));\n // Minimal schema validation ā reject corrupted state files\n if (typeof raw !== 'object' || raw === null || raw.version !== '1.0') {\n return createDefaultState();\n }\n return raw as PipelineState;\n}\n\n/**\n * Safely write to a path, rejecting symlinks.\n * Used by all pipeline write operations.\n */\nfunction safeWriteSync(filePath: string, content: string): void {\n if (existsSync(filePath)) {\n const stat = lstatSync(filePath);\n if (stat.isSymbolicLink()) {\n throw new Error(`Refusing to write to symlink: ${filePath}`);\n }\n }\n writeFileSync(filePath, content);\n}\n\n/**\n * Safely read from a path, rejecting symlinks.\n * Used by all pipeline read operations to prevent TOCTOU-based symlink attacks.\n */\nfunction safeReadSync(filePath: string): string {\n if (existsSync(filePath)) {\n const stat = lstatSync(filePath);\n if (stat.isSymbolicLink()) {\n throw new Error(`Refusing to read symlink: ${filePath}`);\n }\n }\n return readFileSync(filePath, 'utf-8');\n}\n\nfunction writeState(cwd: string, state: PipelineState): void {\n const dir = join(cwd, '.stackwright');\n mkdirSync(dir, { recursive: true });\n state.updatedAt = new Date().toISOString();\n safeWriteSync(statePath(cwd), JSON.stringify(state, null, 2) + '\\n');\n}\n\n/** Extract JSON from messy LLM output ā handles markdown fences, leading prose */\nfunction extractJsonFromResponse(text: string): unknown {\n let cleaned = text;\n // Strip markdown code fences (```json ... ``` or ``` ... ```)\n cleaned = cleaned.replace(/```(?:json)?\\s*/gi, '');\n cleaned = cleaned.replace(/```\\s*$/gm, '');\n\n // Find the outermost JSON object\n const firstBrace = cleaned.indexOf('{');\n if (firstBrace === -1) throw new Error('No JSON object found in response');\n cleaned = cleaned.substring(firstBrace);\n\n const lastBrace = cleaned.lastIndexOf('}');\n if (lastBrace === -1) throw new Error('Unclosed JSON object in response');\n cleaned = cleaned.substring(0, lastBrace + 1);\n\n // Fix common LLM JSON quirks\n cleaned = cleaned.replace(/,(\\s*[}\\]])/g, '$1'); // trailing commas\n return JSON.parse(cleaned);\n}\n\n// ---------------------------------------------------------------------------\n// Handler functions (exported for direct testing ā no MCP server needed)\n// ---------------------------------------------------------------------------\n\nexport function handleGetPipelineState(_cwd?: string): { text: string; isError: boolean } {\n const cwd = _cwd ?? process.cwd();\n try {\n const state = readState(cwd);\n\n // Auto-initialize signing keys on first access (lazy init)\n const keyPath = join(cwd, '.stackwright', 'pipeline-keys.json');\n if (!existsSync(keyPath)) {\n try {\n const { fingerprint } = initPipelineKeys(cwd);\n // Record key fingerprint in pipeline state for audit trail\n (state as unknown as Record<string, unknown>)['signingKeyFingerprint'] = fingerprint;\n writeState(cwd, state);\n } catch {\n // Non-blocking ā signing is defense-in-depth, not a hard gate at init\n }\n }\n\n return { text: JSON.stringify(state), isError: false };\n } catch (err) {\n return { text: JSON.stringify({ error: true, message: String(err) }), isError: true };\n }\n}\n\nexport interface SetPipelineStateInput {\n phase?: string;\n field?: 'questionsCollected' | 'answered' | 'executed' | 'artifactWritten';\n value?: boolean;\n status?: 'setup' | 'questions' | 'execution' | 'done';\n incrementRetry?: boolean;\n _cwd?: string;\n}\n\nexport function handleSetPipelineState(input: SetPipelineStateInput): {\n text: string;\n isError: boolean;\n} {\n const cwd = input._cwd ?? process.cwd();\n\n // Validate phase name if provided\n if (input.phase && !isValidPhase(input.phase)) {\n return {\n text: JSON.stringify({\n error: true,\n message: `Invalid phase: ${input.phase}. Valid phases are: ${PHASE_ORDER.join(', ')}`,\n }),\n isError: true,\n };\n }\n\n // Validate field name if provided\n const VALID_FIELDS = ['questionsCollected', 'answered', 'executed', 'artifactWritten'] as const;\n if (input.field && !VALID_FIELDS.includes(input.field as (typeof VALID_FIELDS)[number])) {\n return {\n text: JSON.stringify({\n error: true,\n message: `Invalid field: ${input.field}. Valid fields are: ${VALID_FIELDS.join(', ')}`,\n }),\n isError: true,\n };\n }\n\n try {\n const state = readState(cwd);\n\n // Update top-level status if provided\n if (input.status) {\n state.status = input.status;\n }\n\n // Update phase-level fields\n if (input.phase) {\n const phase = input.phase;\n if (!state.phases[phase]) {\n state.phases[phase] = defaultPhaseStatus();\n }\n const phaseState = state.phases[phase];\n\n if (input.field && input.value !== undefined) {\n phaseState[input.field] = input.value;\n }\n\n if (input.incrementRetry) {\n phaseState.retryCount += 1;\n }\n\n state.currentPhase = phase;\n }\n\n writeState(cwd, state);\n return { text: JSON.stringify(state), isError: false };\n } catch (err) {\n return { text: JSON.stringify({ error: true, message: String(err) }), isError: true };\n }\n}\n\nexport function handleCheckExecutionReady(\n _cwd?: string,\n phase?: string\n): { text: string; isError: boolean } {\n const cwd = _cwd ?? process.cwd();\n\n if (phase) {\n if (!isValidPhase(phase)) {\n return {\n text: JSON.stringify({\n error: true,\n message: `Invalid phase: ${phase}. Valid phases are: ${PHASE_ORDER.join(', ')}`,\n }),\n isError: true,\n };\n }\n const answerFile = join(cwd, '.stackwright', 'answers', `${phase}.json`);\n if (!existsSync(answerFile)) {\n return {\n text: JSON.stringify({ ready: false, phase, reason: 'Answer file not found' }),\n isError: false,\n };\n }\n try {\n const raw = safeReadSync(answerFile);\n const parsed = JSON.parse(raw) as Record<string, unknown>;\n if (\n typeof parsed['version'] !== 'string' ||\n typeof parsed['phase'] !== 'string' ||\n typeof parsed['answers'] !== 'object' ||\n parsed['answers'] === null\n ) {\n return {\n text: JSON.stringify({ ready: false, phase, reason: 'Answer file is malformed' }),\n isError: false,\n };\n }\n return { text: JSON.stringify({ ready: true, phase }), isError: false };\n } catch {\n return {\n text: JSON.stringify({ ready: false, phase, reason: 'Answer file could not be parsed' }),\n isError: false,\n };\n }\n }\n\n try {\n const answersDir = join(cwd, '.stackwright', 'answers');\n const answeredPhases: string[] = [];\n const missingPhases: string[] = [];\n\n for (const phase of PHASE_ORDER) {\n const answerFile = join(answersDir, `${phase}.json`);\n if (existsSync(answerFile)) {\n // Validate: file must be parseable JSON with required fields\n try {\n const raw = safeReadSync(answerFile);\n const parsed = JSON.parse(raw) as Record<string, unknown>;\n\n // Must have version, phase, and answers keys\n if (\n typeof parsed['version'] !== 'string' ||\n typeof parsed['phase'] !== 'string' ||\n typeof parsed['answers'] !== 'object' ||\n parsed['answers'] === null\n ) {\n // File exists but is malformed ā treat as missing\n missingPhases.push(phase);\n continue;\n }\n\n answeredPhases.push(phase);\n } catch {\n // Can't parse ā treat as missing\n missingPhases.push(phase);\n }\n } else {\n missingPhases.push(phase);\n }\n }\n\n return {\n text: JSON.stringify({\n ready: missingPhases.length === 0,\n answeredPhases,\n missingPhases,\n totalPhases: PHASE_ORDER.length,\n }),\n isError: false,\n };\n } catch (err) {\n return { text: JSON.stringify({ error: true, message: String(err) }), isError: true };\n }\n}\n\n/**\n * Return phases whose dependencies are all satisfied (executed === true in\n * pipeline state). The foreman calls this in a loop to discover which phases\n * can run next ā enabling wave-based execution instead of strict serial order.\n *\n * Wave decomposition (with the current DAG):\n * Wave 1: designer, api, workflow (3 parallel ā zero deps)\n * Wave 2: theme, data (2 parallel)\n * Wave 3: geo\n * Wave 4: pages, dashboard (2 parallel)\n * Wave 5: auth\n * Wave 6: polish\n */\nexport function handleGetReadyPhases(_cwd?: string): { text: string; isError: boolean } {\n const cwd = _cwd ?? process.cwd();\n try {\n const state = readState(cwd);\n\n const completed: string[] = [];\n const ready: string[] = [];\n const blocked: string[] = [];\n\n for (const phase of PHASE_ORDER) {\n const ps = state.phases[phase];\n if (ps?.executed) {\n completed.push(phase);\n continue;\n }\n // Phase is ready if every dependency is executed\n const deps = PHASE_DEPENDENCIES[phase];\n const unmetDeps = deps.filter((dep) => !state.phases[dep]?.executed);\n if (unmetDeps.length === 0) {\n ready.push(phase);\n } else {\n blocked.push(phase);\n }\n }\n\n return {\n text: JSON.stringify({\n readyPhases: ready,\n completedPhases: completed,\n blockedPhases: blocked,\n waveSize: ready.length,\n allComplete: ready.length === 0 && blocked.length === 0,\n }),\n isError: false,\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return { text: JSON.stringify({ error: true, message }), isError: true };\n }\n}\n\nexport function handleListArtifacts(_cwd?: string): { text: string; isError: boolean } {\n const cwd = _cwd ?? process.cwd();\n try {\n const artifactsDir = join(cwd, '.stackwright', 'artifacts');\n\n // Load signature manifest (non-blocking if missing)\n let manifest: ReturnType<typeof loadSignatureManifest> | null = null;\n try {\n manifest = loadSignatureManifest(cwd);\n } catch {\n // No signature manifest ā report unsigned\n }\n\n const artifacts: Array<{\n phase: string;\n expectedFile: string;\n exists: boolean;\n path: string;\n signed: boolean;\n signatureValid: boolean | null;\n }> = [];\n let completedCount = 0;\n\n for (const phase of PHASE_ORDER) {\n const expectedFile = PHASE_ARTIFACT[phase];\n const fullPath = join(artifactsDir, expectedFile);\n const exists = existsSync(fullPath);\n if (exists) completedCount++;\n\n // Check signature status\n let signed = false;\n let signatureValid: boolean | null = null;\n\n if (exists && manifest) {\n const entry = manifest.signatures[expectedFile];\n if (entry) {\n signed = true;\n // Verify if keys are available\n try {\n const rawBytes = Buffer.from(safeReadSync(fullPath), 'utf-8');\n const { publicKey } = loadPipelineKeys(cwd);\n signatureValid = verifyArtifact(rawBytes, entry, publicKey);\n } catch {\n signatureValid = null; // Can't verify ā keys unavailable\n }\n }\n }\n\n artifacts.push({ phase, expectedFile, exists, path: fullPath, signed, signatureValid });\n }\n\n return {\n text: JSON.stringify({ artifacts, completedCount, totalCount: PHASE_ORDER.length }),\n isError: false,\n };\n } catch (err) {\n return { text: JSON.stringify({ error: true, message: String(err) }), isError: true };\n }\n}\n\nexport interface WritePhaseQuestionsInput {\n phase: string;\n responseText: string;\n _cwd?: string;\n}\n\nexport function handleWritePhaseQuestions(input: WritePhaseQuestionsInput): {\n text: string;\n isError: boolean;\n} {\n const cwd = input._cwd ?? process.cwd();\n const { phase, responseText } = input;\n\n if (!isValidPhase(phase)) {\n return {\n text: JSON.stringify({ error: true, message: `Unknown phase: ${phase}` }),\n isError: true,\n };\n }\n\n try {\n const questions = parseLLMQuestionsResponse(responseText);\n\n // Extract requiredPackages if present in the raw response\n let requiredPackages: {\n dependencies: Record<string, string>;\n devPackages: Record<string, string>;\n } = {\n dependencies: {},\n devPackages: {},\n };\n try {\n const fullParsed = extractJsonFromResponse(responseText) as Record<string, unknown>;\n if (fullParsed.requiredPackages && typeof fullParsed.requiredPackages === 'object') {\n const rp = fullParsed.requiredPackages as Record<string, unknown>;\n requiredPackages = {\n dependencies: (rp.dependencies as Record<string, string>) ?? {},\n devPackages: (rp.devPackages as Record<string, string>) ?? {},\n };\n }\n } catch {\n // extractJsonFromResponse may fail if the response is a bare array ā that's fine\n }\n\n const questionsDir = join(cwd, '.stackwright', 'questions');\n mkdirSync(questionsDir, { recursive: true });\n const filePath = join(questionsDir, `${phase}.json`);\n\n const payload = {\n version: '1.0',\n phase,\n otter: PHASE_TO_OTTER[phase],\n collectedAt: new Date().toISOString(),\n questions,\n requiredPackages,\n };\n\n safeWriteSync(filePath, JSON.stringify(payload, null, 2) + '\\n');\n\n // Update pipeline state\n const state = readState(cwd);\n if (!state.phases[phase]) state.phases[phase] = defaultPhaseStatus();\n const ps = state.phases[phase]!; // guaranteed by line above\n ps.questionsCollected = true;\n writeState(cwd, state);\n\n return {\n text: JSON.stringify({\n success: true,\n phase,\n questionCount: questions.length,\n requiredPackages,\n path: filePath,\n }),\n isError: false,\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return { text: JSON.stringify({ error: true, phase, message }), isError: true };\n }\n}\n\nexport interface BuildSpecialistPromptInput {\n phase: string;\n _cwd?: string;\n}\n\nexport function handleBuildSpecialistPrompt(input: BuildSpecialistPromptInput): {\n text: string;\n isError: boolean;\n} {\n const cwd = input._cwd ?? process.cwd();\n const { phase } = input;\n\n if (!isValidPhase(phase)) {\n return {\n text: JSON.stringify({ error: true, message: `Unknown phase: ${phase}` }),\n isError: true,\n };\n }\n\n try {\n // 1. Read answers for this phase\n const answersPath = join(cwd, '.stackwright', 'answers', `${phase}.json`);\n let answers: unknown = {};\n if (existsSync(answersPath)) {\n answers = JSON.parse(safeReadSync(answersPath));\n }\n\n // 1b. Read build context (optional ā non-blocking if missing or malformed)\n let buildContextText = '';\n const buildContextPath = join(cwd, '.stackwright', 'build-context.json');\n if (existsSync(buildContextPath)) {\n try {\n const bcRaw = JSON.parse(safeReadSync(buildContextPath)) as { buildContext?: string };\n if (typeof bcRaw.buildContext === 'string' && bcRaw.buildContext.trim().length > 0) {\n buildContextText = bcRaw.buildContext.trim();\n }\n } catch {\n // Non-blocking ā missing or malformed build context does not block execution\n }\n }\n\n // 2. Read upstream dependency artifacts\n const deps = PHASE_DEPENDENCIES[phase];\n const artifactSections: string[] = [];\n const missingDependencies: string[] = [];\n\n for (const dep of deps) {\n const artifactFile = PHASE_ARTIFACT[dep];\n const artifactPath = join(cwd, '.stackwright', 'artifacts', artifactFile);\n if (existsSync(artifactPath)) {\n const rawContent = safeReadSync(artifactPath);\n const rawBytes = Buffer.from(rawContent, 'utf-8');\n const content = JSON.parse(rawContent) as Record<string, unknown>;\n\n // āā Cryptographic signature verification (primary integrity check) āā\n // If signing keys exist, verify the ECDSA P-384 signature before trusting\n // the artifact. Falls back to generatedBy check if unsigned (backwards compat).\n let signatureVerified = false;\n let signatureAvailable = false;\n\n try {\n const sig = getArtifactSignature(cwd, artifactFile);\n if (sig) {\n signatureAvailable = true;\n const { publicKey } = loadPipelineKeys(cwd);\n signatureVerified = verifyArtifact(rawBytes, sig, publicKey);\n\n if (!signatureVerified) {\n // Emit audit event for SOC2/FedRAMP compliance\n const actualDigest = createHash('sha384').update(rawBytes).digest('hex');\n emitSignatureAuditEvent({\n artifactFilename: artifactFile,\n expectedDigest: sig.digest,\n actualDigest,\n phase: dep,\n timestamp: new Date().toISOString(),\n source: 'stackwright_pro_build_specialist_prompt',\n });\n\n missingDependencies.push(dep);\n artifactSections.push(\n `[${artifactFile}]:\\n(integrity check failed: ECDSA-P384 signature verification failed ā artifact may have been tampered with)`\n );\n continue;\n }\n }\n } catch {\n // Key loading failed ā fall through to generatedBy check\n }\n\n // āā Secondary check: generatedBy field cross-validation āā\n // Even with valid signatures, verify the generatedBy field matches expectations.\n // Without signatures (unsigned pipeline), this is the primary check.\n const expectedOtter = PHASE_TO_OTTER[dep];\n const artifactOtter = content['generatedBy'] as string | undefined;\n const normalizedOtter = artifactOtter?.replace(/-[a-f0-9]{6}$/, '');\n\n if (!artifactOtter) {\n missingDependencies.push(dep);\n artifactSections.push(\n `[${artifactFile}]:\\n(integrity check failed: missing generatedBy field)`\n );\n } else if (normalizedOtter !== expectedOtter) {\n missingDependencies.push(dep);\n artifactSections.push(\n `[${artifactFile}]:\\n(integrity check failed: artifact claims generatedBy=\"${artifactOtter}\" but expected=\"${expectedOtter}\")`\n );\n } else {\n const sigStatus = signatureAvailable\n ? signatureVerified\n ? ' [signature verified]'\n : ' [signature check skipped]'\n : ' [unsigned]';\n artifactSections.push(\n `[${artifactFile}]${sigStatus}:\\n${JSON.stringify(content, null, 2)}`\n );\n }\n } else {\n missingDependencies.push(dep);\n artifactSections.push(`[${artifactFile}]:\\n(not yet available)`);\n }\n }\n\n // 3. Assemble the prompt\n const parts: string[] = [];\n\n if (buildContextText) {\n parts.push('BUILD_CONTEXT:', buildContextText, '');\n }\n\n parts.push('ANSWERS:', JSON.stringify(answers, null, 2));\n\n if (artifactSections.length > 0) {\n parts.push('', 'UPSTREAM ARTIFACTS:', '', ...artifactSections);\n }\n\n // Inject the canonical artifact schema so specialists always build against\n // the current contract ā not hardcoded examples in their JSON files.\n const artifactSchema = PHASE_ARTIFACT_SCHEMA[phase];\n parts.push('', 'REQUIRED_ARTIFACT_SCHEMA:');\n parts.push(artifactSchema);\n\n parts.push('', 'Execute using these answers and the upstream artifacts provided.');\n\n const prompt = parts.join('\\n');\n const dependenciesSatisfied = missingDependencies.length === 0;\n\n return {\n text: JSON.stringify({\n otterName: PHASE_TO_OTTER[phase],\n phase,\n prompt,\n dependenciesSatisfied,\n missingDependencies,\n }),\n isError: false,\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return { text: JSON.stringify({ error: true, phase, message }), isError: true };\n }\n}\n\nexport interface ValidateArtifactInput {\n phase: string;\n responseText?: string;\n artifact?: Record<string, unknown>;\n _cwd?: string;\n}\n\nconst OFF_SCRIPT_PATTERNS: Array<{ pattern: RegExp; label: string }> = [\n {\n pattern: /```(?:ts|tsx|js|jsx|python|bash|sh|sql|ruby|go|rust|java|csharp|c\\+\\+)\\b/,\n label: 'code fence',\n },\n { pattern: /\\bimport\\s+[\\w{]/, label: 'import statement' },\n { pattern: /\\bexport\\s+(?:const|function|default|class)\\b/, label: 'export statement' },\n { pattern: /\\brequire\\s*\\(/, label: 'require() call' },\n { pattern: /\\beval\\s*\\(/, label: 'eval() call' },\n { pattern: /^#!/m, label: 'shebang' },\n { pattern: /<script[\\s>]/i, label: 'script tag' },\n { pattern: /\\.(ts|tsx|js|jsx)\\b.*\\bfile\\b/i, label: 'code file reference' },\n];\n\ninterface ValidArtifactResult {\n valid: true;\n phase: string;\n artifactPath: string;\n summary: string;\n}\n\ninterface InvalidArtifactResult {\n valid: false;\n phase: string;\n violation: 'off-script' | 'invalid-json' | 'missing-fields' | 'schema-mismatch';\n retryPrompt: string;\n}\n\nconst PHASE_REQUIRED_KEYS: Record<Phase, string[]> = {\n designer: ['designLanguage', 'themeTokenSeeds'],\n theme: ['tokens'],\n api: ['entities', 'version', 'generatedBy'],\n auth: ['version', 'generatedBy'],\n data: ['version', 'generatedBy', 'strategy', 'collections'],\n pages: ['version', 'generatedBy'],\n dashboard: ['version', 'generatedBy'],\n workflow: ['version', 'generatedBy'],\n services: ['version', 'generatedBy', 'flows'],\n polish: ['version', 'generatedBy'],\n geo: ['version', 'generatedBy', 'geoCollections'],\n};\n\n/**\n * Canonical artifact schema examples for each phase.\n *\n * SINGLE SOURCE OF TRUTH ā injected into specialist prompts at invocation time\n * via handleBuildSpecialistPrompt. Both validate_artifact (enforcement) and\n * build_specialist_prompt (guidance) derive from the same constant here.\n *\n * Schema changes happen in THIS file only. Zero drift possible.\n */\nconst PHASE_ARTIFACT_SCHEMA: Record<Phase, string> = {\n designer: JSON.stringify(\n {\n version: '1.0',\n generatedBy: 'stackwright-pro-designer-otter',\n application: {\n type: '<operational|data-explorer|admin|logistics|general>',\n environment: '<workstation|field|control-room|mixed>',\n density: '<compact|balanced|spacious>',\n accessibility: '<wcag-aa|section-508|none>',\n colorScheme: '<light|dark|both>',\n },\n designLanguage: {\n rationale: '<design rationale>',\n spacingScale: { base: 8, scale: [0, 4, 8, 16, 24, 32, 48, 64] },\n colorSemantics: { primary: '#1a365d', accent: '#e53e3e' },\n typography: {\n dataFont: 'Inter',\n headingFont: 'Inter',\n monoFont: 'monospace',\n dataSizePx: 12,\n bodySizePx: 14,\n },\n contrastRatio: '4.5',\n borderRadius: '4',\n shadowElevation: 'standard',\n },\n themeTokenSeeds: {\n light: {\n background: '#ffffff',\n foreground: '#1a1a1a',\n primary: '#1a365d',\n surface: '#f7f7f7',\n border: '#e2e8f0',\n },\n dark: {\n background: '#1a1a1a',\n foreground: '#ffffff',\n primary: '#90cdf4',\n surface: '#2d2d2d',\n border: '#4a5568',\n },\n },\n conformsTo: null,\n operationalNotes: [],\n },\n null,\n 2\n ),\n\n theme: JSON.stringify(\n {\n version: '1.0',\n generatedBy: 'stackwright-pro-theme-otter',\n componentLibrary: 'shadcn',\n colorScheme: '<light|dark|both>',\n tokens: {\n colors: { 'primary-500': '#1a365d', background: '#ffffff' },\n spacing: { 'spacing-1': '8px', 'spacing-2': '16px' },\n typography: { 'font-data': 'Inter', 'text-sm': '12px' },\n shape: { 'radius-sm': '4px', 'radius-md': '8px' },\n shadows: { 'shadow-sm': '0 1px 2px rgba(0,0,0,0.08)' },\n },\n cssVariables: {\n '--background': '0 0% 100%',\n '--foreground': '222.2 84% 4.9%',\n '--primary': '222.2 47.4% 11.2%',\n '--primary-foreground': '210 40% 98%',\n '--surface': '210 40% 98%',\n '--border': '214.3 31.8% 91.4%',\n },\n dark: { '--background': '222.2 84% 4.9%', '--foreground': '210 40% 98%' },\n },\n null,\n 2\n ),\n\n api: JSON.stringify(\n {\n version: '1.0',\n generatedBy: 'stackwright-pro-api-otter',\n entities: [\n {\n name: 'Shipment',\n endpoint: '/shipments',\n method: 'GET',\n revalidate: 60,\n mutationType: null,\n },\n ],\n auth: { type: 'bearer', header: 'Authorization', envVar: 'API_TOKEN' },\n baseUrl: 'https://api.example.mil/v2',\n specPath: './specs/api.yaml',\n },\n null,\n 2\n ),\n\n data: JSON.stringify(\n {\n version: '1.0',\n generatedBy: 'stackwright-pro-data-otter',\n strategy: '<pulse-fast|isr-fast|isr-standard|isr-slow>',\n pulseMode: false,\n collections: [{ name: 'equipment', revalidate: 60, pulse: false }],\n endpoints: { included: ['/equipment/**'], excluded: ['/admin/**'] },\n requiredPackages: { dependencies: {}, devPackages: {} },\n },\n null,\n 2\n ),\n\n geo: JSON.stringify(\n {\n version: '1.0',\n generatedBy: 'stackwright-pro-geo-otter',\n geoCollections: [\n {\n collection: 'vessels',\n latField: 'latitude',\n lngField: 'longitude',\n labelField: 'vesselName',\n colorField: 'navigationStatus',\n },\n ],\n pages: [\n {\n slug: 'fleet-tracker',\n type: '<tracker|zone|route|combined>',\n collections: ['vessels'],\n hasLayers: false,\n },\n ],\n },\n null,\n 2\n ),\n\n workflow: JSON.stringify(\n {\n version: '1.0',\n generatedBy: 'stackwright-pro-workflow-otter',\n workflowConfig: {\n id: 'procurement-approval',\n route: '/procurement',\n files: ['workflows/procurement-approval.yml'],\n serviceDependencies: ['service:workflow-state'],\n warnings: [],\n },\n },\n null,\n 2\n ),\n\n services: JSON.stringify(\n {\n version: '1.0',\n generatedBy: 'stackwright-services-otter',\n flows: [\n {\n name: 'at-risk-patients',\n trigger: '<http|event|schedule|queue>',\n steps: 3,\n outputSpec: 'at-risk-patients.openapi.json',\n },\n ],\n workflows: [\n {\n name: 'evacuation-coordination',\n states: 4,\n transitions: 5,\n },\n ],\n openApiSpecs: ['at-risk-patients.openapi.json'],\n capabilitiesUsed: ['service.call', 'collection.join', 'collection.filter'],\n },\n null,\n 2\n ),\n\n pages: JSON.stringify(\n {\n version: '1.0',\n generatedBy: 'stackwright-pro-page-otter',\n pages: [\n {\n slug: 'catalog',\n type: 'collection_listing',\n collection: 'products',\n themeApplied: true,\n authRequired: false,\n },\n {\n slug: 'admin',\n type: 'protected',\n collection: null,\n themeApplied: true,\n authRequired: true,\n },\n ],\n },\n null,\n 2\n ),\n\n dashboard: JSON.stringify(\n {\n version: '1.0',\n generatedBy: 'stackwright-pro-dashboard-otter',\n pages: [\n {\n slug: 'dashboard',\n layout: '<grid|table|mixed>',\n collections: ['equipment', 'supplies'],\n mode: '<ISR|Pulse>',\n },\n ],\n },\n null,\n 2\n ),\n\n auth: JSON.stringify(\n {\n version: '1.0',\n generatedBy: 'stackwright-pro-auth-otter',\n authConfig: {\n method: '<cac|oidc|oauth2|none>',\n provider: '<azure-ad|okta|ping|cognito ā if OIDC, else null>',\n rbacRoles: ['ADMIN', 'ANALYST'],\n rbacDefaultRole: 'ANALYST',\n protectedRoutes: ['/dashboard/:path*', '/procurement/:path*'],\n auditEnabled: true,\n auditRetentionDays: 90,\n },\n },\n null,\n 2\n ),\n\n polish: JSON.stringify(\n {\n version: '1.0',\n generatedBy: 'stackwright-pro-polish-otter',\n landingPage: { slug: '', rewritten: true },\n navigation: { itemCount: 5, items: ['/dashboard', '/equipment', '/workflows'] },\n gettingStarted: '<rewritten|redirected|not-found>',\n },\n null,\n 2\n ),\n};\n\nexport function handleValidateArtifact(input: ValidateArtifactInput): {\n text: string;\n isError: boolean;\n} {\n const cwd = input._cwd ?? process.cwd();\n const { phase, responseText, artifact: directArtifact } = input;\n\n if (!isValidPhase(phase)) {\n return {\n text: JSON.stringify({ error: true, message: `Unknown phase: ${phase}` }),\n isError: true,\n };\n }\n\n let artifact: Record<string, unknown>;\n\n if (directArtifact) {\n // Direct artifact path (specialist calling with artifact object):\n // Skip off-script detection and JSON string parsing ā already an object.\n artifact = directArtifact;\n } else {\n // Legacy responseText path (Foreman-mediated):\n const text = responseText ?? '';\n\n // 1. Off-script detection ā check the RAW response before trying to parse\n for (const { pattern, label } of OFF_SCRIPT_PATTERNS) {\n if (pattern.test(text)) {\n const result: InvalidArtifactResult = {\n valid: false,\n phase,\n violation: 'off-script',\n retryPrompt: `You returned code output (detected: ${label}). Return ONLY a JSON artifact ā no code, no files.`,\n };\n return { text: JSON.stringify(result), isError: false };\n }\n }\n\n // 2. JSON extraction\n try {\n artifact = extractJsonFromResponse(text) as Record<string, unknown>;\n } catch {\n const result: InvalidArtifactResult = {\n valid: false,\n phase,\n violation: 'invalid-json',\n retryPrompt:\n 'Your response did not contain valid JSON. Return a single JSON object with no surrounding text.',\n };\n return { text: JSON.stringify(result), isError: false };\n }\n }\n\n // 3. Required universal fields\n if (!artifact.version || !artifact.generatedBy) {\n const result: InvalidArtifactResult = {\n valid: false,\n phase,\n violation: 'missing-fields',\n retryPrompt:\n 'Your JSON artifact is missing required fields. Every artifact MUST include \"version\" and \"generatedBy\" at the top level.',\n };\n return { text: JSON.stringify(result), isError: false };\n }\n\n // 4. Phase-specific key checks\n const requiredKeys = PHASE_REQUIRED_KEYS[phase];\n const missingKeys = requiredKeys.filter((k) => !(k in artifact));\n if (missingKeys.length > 0) {\n const result: InvalidArtifactResult = {\n valid: false,\n phase,\n violation: 'schema-mismatch',\n retryPrompt: `Your ${phase} artifact is missing required keys: ${missingKeys.join(', ')}. Include them and try again.`,\n };\n return { text: JSON.stringify(result), isError: false };\n }\n\n // 5. Zod schema validation (where canonical schemas are available)\n // Provides richer error messages than key-presence checks alone.\n const PHASE_ZOD_VALIDATORS: Partial<\n Record<\n Phase,\n (artifact: Record<string, unknown>) => { success: boolean; error?: { message: string } }\n >\n > = {\n workflow: (artifact) => {\n // The workflow otter produces { version, generatedBy, workflowConfig: { workflow: {...} } }\n // Validate the nested workflowConfig if present\n const workflowConfig = artifact['workflowConfig'];\n if (!workflowConfig) return { success: true }; // skip if not present (caught by key check)\n const result = WorkflowFileSchema.safeParse(workflowConfig);\n if (!result.success) {\n const issues = result.error.issues\n .slice(0, 3)\n .map((i) => `${i.path.join('.')}: ${i.message}`)\n .join('; ');\n return { success: false, error: { message: issues } };\n }\n return { success: true };\n },\n auth: (artifact) => {\n // The auth otter produces { version, generatedBy, authConfig: { type: 'oidc'|'pki', ... } }\n const authConfig = artifact['authConfig'];\n if (!authConfig) return { success: true }; // skip if not present\n const result = authConfigSchema.safeParse(authConfig);\n if (!result.success) {\n const issues = result.error.issues\n .slice(0, 3)\n .map((i) => `${i.path.join('.')}: ${i.message}`)\n .join('; ');\n return { success: false, error: { message: issues } };\n }\n return { success: true };\n },\n };\n\n const zodValidator = PHASE_ZOD_VALIDATORS[phase];\n if (zodValidator) {\n const zodResult = zodValidator(artifact);\n if (!zodResult.success) {\n const result: InvalidArtifactResult = {\n valid: false,\n phase,\n violation: 'schema-mismatch',\n retryPrompt: `Your artifact failed schema validation: ${zodResult.error?.message}. Fix these fields and return the corrected JSON artifact.`,\n };\n return { text: JSON.stringify(result), isError: false };\n }\n }\n\n // 6. All good ā write it and sign it\n try {\n const artifactsDir = join(cwd, '.stackwright', 'artifacts');\n mkdirSync(artifactsDir, { recursive: true });\n const artifactFile = PHASE_ARTIFACT[phase];\n const artifactPath = join(artifactsDir, artifactFile);\n\n // Serialize once ā sign and write the same bytes (zero TOCTOU window)\n const serialized = JSON.stringify(artifact, null, 2) + '\\n';\n const artifactBytes = Buffer.from(serialized, 'utf-8');\n safeWriteSync(artifactPath, serialized);\n\n // Sign the artifact (non-blocking ā signing failure doesn't prevent write)\n let signed = false;\n try {\n const { privateKey } = loadPipelineKeys(cwd);\n const sig = signArtifact(artifactBytes, privateKey);\n const signerOtter = PHASE_TO_OTTER[phase];\n saveArtifactSignature(cwd, artifactFile, sig, signerOtter);\n signed = true;\n } catch {\n // Signing is defense-in-depth ā pipeline continues without signatures\n // if keys haven't been initialized (e.g., backwards-compat with old pipelines)\n }\n\n // Update pipeline state\n const state = readState(cwd);\n if (!state.phases[phase]) state.phases[phase] = defaultPhaseStatus();\n const ps = state.phases[phase]!; // guaranteed by line above\n ps.artifactWritten = true;\n writeState(cwd, state);\n\n const topKeys = Object.keys(artifact).slice(0, 5).join(', ');\n const result: ValidArtifactResult = {\n valid: true,\n phase,\n artifactPath,\n summary: `Wrote ${artifactFile} (keys: ${topKeys}${Object.keys(artifact).length > 5 ? ', ...' : ''})${signed ? ' [signed]' : ''}`,\n };\n return { text: JSON.stringify(result), isError: false };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return { text: JSON.stringify({ error: true, phase, message }), isError: true };\n }\n}\n\n// ---------------------------------------------------------------------------\n// MCP tool registration\n// ---------------------------------------------------------------------------\n\nexport function registerPipelineTools(server: McpServer): void {\n const DESC = 'Writes state to .stackwright/ ā the filesystem is the state machine.';\n const res = (r: { text: string; isError: boolean }) => ({\n content: [{ type: 'text' as const, text: r.text }],\n isError: r.isError,\n });\n\n server.tool(\n 'stackwright_pro_get_pipeline_state',\n `Read pipeline state from .stackwright/pipeline-state.json. ${DESC}`,\n {},\n async () => res(handleGetPipelineState())\n );\n\n server.tool(\n 'stackwright_pro_set_pipeline_state',\n `Atomic readāmodifyāwrite pipeline state. ${DESC}`,\n {\n phase: z.string().optional().describe('Phase to update, e.g. \"designer\"'),\n field: z\n .enum(['questionsCollected', 'answered', 'executed', 'artifactWritten'])\n .optional()\n .describe('Boolean field to set'),\n value: boolCoerce(z.boolean().optional()).describe(\n 'Value for the field ā must be a JSON boolean (true/false), NOT the string \"true\"/\"false\"'\n ),\n status: z\n .enum(['setup', 'questions', 'execution', 'done'])\n .optional()\n .describe('Top-level status override'),\n incrementRetry: boolCoerce(z.boolean().optional()).describe(\n 'Bump retryCount by 1 ā must be a JSON boolean'\n ),\n },\n async (args) =>\n res(\n handleSetPipelineState({\n ...(args.phase != null ? { phase: args.phase } : {}),\n ...(args.field != null ? { field: args.field } : {}),\n ...(args.value != null ? { value: args.value } : {}),\n ...(args.status != null ? { status: args.status } : {}),\n ...(args.incrementRetry != null ? { incrementRetry: args.incrementRetry } : {}),\n })\n )\n );\n\n server.tool(\n 'stackwright_pro_check_execution_ready',\n `Check all phases have answer files in .stackwright/answers/. If phase is provided, check only that phase. ${DESC}`,\n {\n phase: z\n .string()\n .optional()\n .describe(\"If provided, check only this phase's readiness. Omit to check all phases.\"),\n },\n async ({ phase }) => res(handleCheckExecutionReady(undefined, phase))\n );\n\n server.tool(\n 'stackwright_pro_get_ready_phases',\n `Return phases whose dependencies are all satisfied (executed=true). Use to determine which phases can run next ā enables wave-based execution. ${DESC}`,\n {},\n async () => res(handleGetReadyPhases())\n );\n\n server.tool(\n 'stackwright_pro_list_artifacts',\n `List phase artifacts in .stackwright/artifacts/ with completedCount/totalCount. ${DESC}`,\n {},\n async () => res(handleListArtifacts())\n );\n\n server.tool(\n 'stackwright_pro_write_phase_questions',\n `Parse otter question-collection response ā .stackwright/questions/{phase}.json. Specialists may also call this directly with a parsed questions array. ${DESC}`,\n {\n phase: z\n .string()\n .optional()\n .describe('Phase name, e.g. \"designer\" (required for direct write)'),\n responseText: z\n .string()\n .optional()\n .describe('Raw LLM response from QUESTION_COLLECTION_MODE'),\n questions: jsonCoerce(z.array(z.any()).optional()).describe(\n 'Questions array for direct specialist write'\n ),\n },\n async ({ phase, responseText, questions }) => {\n // Direct write path: specialist calls with parsed array (no responseText parsing)\n if (phase && questions && Array.isArray(questions)) {\n const SAFE_PHASE = /^[a-z][a-z0-9-]{0,30}$/;\n if (!SAFE_PHASE.test(phase)) {\n return {\n content: [\n { type: 'text' as const, text: JSON.stringify({ error: `Invalid phase name` }) },\n ],\n isError: true,\n };\n }\n const questionsDir = join(process.cwd(), '.stackwright', 'questions');\n mkdirSync(questionsDir, { recursive: true });\n const outPath = join(questionsDir, `${phase}.json`);\n writeFileSync(\n outPath,\n JSON.stringify({ phase, questions, writtenAt: new Date().toISOString() }, null, 2)\n );\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify({\n written: true,\n phase,\n count: (questions as unknown[]).length,\n }),\n },\n ],\n };\n }\n // Fallback: parse from raw LLM responseText\n return res(\n handleWritePhaseQuestions({ phase: phase ?? '', responseText: responseText ?? '' })\n );\n }\n );\n\n server.tool(\n 'stackwright_pro_build_specialist_prompt',\n `Assemble execution prompt from answers + upstream artifacts. Foreman passes verbatim. ${DESC}`,\n { phase: z.string().describe('Phase to build prompt for, e.g. \"pages\"') },\n async ({ phase }) => res(handleBuildSpecialistPrompt({ phase }))\n );\n\n server.tool(\n 'stackwright_pro_validate_artifact',\n `Validate and write artifact to .stackwright/artifacts/. Returns retryPrompt on failure. ${DESC}`,\n {\n phase: z.string().describe('Phase that produced this artifact, e.g. \"designer\"'),\n responseText: z\n .string()\n .optional()\n .describe('Raw response text from the specialist otter (Foreman-mediated path, legacy)'),\n artifact: jsonCoerce(z.record(z.string(), z.unknown()).optional()).describe(\n 'Artifact object to validate and write directly (specialist direct path ā skips off-script detection and JSON parsing)'\n ),\n },\n async ({ phase, responseText, artifact }) => {\n if (artifact) {\n return res(\n handleValidateArtifact({ phase, artifact: artifact as Record<string, unknown> })\n );\n }\n return res(handleValidateArtifact({ phase, responseText: responseText ?? '' }));\n }\n );\n}\n","/**\n * Artifact Signing ā Cryptographic Pipeline Artifact Protection\n * ==============================================================\n * Closes the mid-pipeline TOCTOU gap where artifacts written by one otter\n * can be tampered with before the next otter reads them.\n *\n * integrity.ts handles SHA-256 pinning of otter *definition* files at startup.\n * This module protects pipeline *artifacts* (`.stackwright/artifacts/`) with\n * ECDSA P-384 signatures. Ephemeral key pairs are per-pipeline-run, destroyed\n * after completion.\n */\nimport {\n createHash,\n generateKeyPairSync,\n createPublicKey,\n createPrivateKey,\n sign,\n verify,\n timingSafeEqual,\n KeyObject,\n} from 'crypto';\nimport {\n readFileSync,\n writeFileSync,\n existsSync,\n mkdirSync,\n lstatSync,\n unlinkSync,\n readdirSync,\n} from 'fs';\nimport { join } from 'path';\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst ALGORITHM = 'ECDSA-P384-SHA384' as const;\nconst KEY_FILE = 'pipeline-keys.json';\nconst KEY_DIR = '.stackwright';\nconst SIGNATURE_MANIFEST = 'signatures.json';\nconst ARTIFACTS_DIR = '.stackwright/artifacts';\n\n// ---------------------------------------------------------------------------\n// Exported types & interfaces\n// ---------------------------------------------------------------------------\n\n/** Signature record for a single artifact. */\nexport interface ArtifactSignature {\n digest: string;\n signature: string;\n algorithm: typeof ALGORITHM;\n signedAt: string;\n}\n\n/** Manifest entry ā extends ArtifactSignature with signer identity. */\nexport interface ManifestEntry extends ArtifactSignature {\n signedBy: string;\n}\n\n/** On-disk shape of `.stackwright/artifacts/signatures.json`. */\nexport interface SignatureManifest {\n version: '1.0';\n algorithm: typeof ALGORITHM;\n signatures: Record<string, ManifestEntry>;\n}\n\n/** On-disk shape of `.stackwright/pipeline-keys.json`. */\nexport interface PipelineKeyFile {\n version: '1.0';\n algorithm: typeof ALGORITHM;\n createdAt: string;\n publicKeyPem: string;\n privateKeyPem: string;\n}\n\n/** Structured audit event for a signature failure. */\nexport interface SignatureAuditEvent {\n artifactFilename: string;\n expectedDigest: string;\n actualDigest: string;\n phase: string;\n timestamp: string;\n source: string;\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\n/** Reject symlinks at a given path. No-op if path doesn't exist. */\nfunction rejectSymlink(filePath: string, context: string): void {\n if (!existsSync(filePath)) return;\n const stat = lstatSync(filePath);\n if (stat.isSymbolicLink()) {\n throw new Error(`Security: refusing to follow symlink at ${context}: ${filePath}`);\n }\n}\n\n/** Hex-encoded SHA-384 digest of raw bytes. Pure, no I/O. */\nfunction computeSha384(data: Buffer): string {\n return createHash('sha384').update(data).digest('hex');\n}\n\n/** Constant-time comparison of two hex digest strings. */\nfunction safeDigestEqual(a: string, b: string): boolean {\n if (a.length !== b.length) return false;\n return timingSafeEqual(Buffer.from(a, 'utf8'), Buffer.from(b, 'utf8'));\n}\n\n/** Build an empty manifest with the correct shape. */\nfunction emptyManifest(): SignatureManifest {\n return {\n version: '1.0',\n algorithm: ALGORITHM,\n signatures: {},\n };\n}\n\n// ---------------------------------------------------------------------------\n// 1. Ephemeral Key Pair Management (ECDSA P-384)\n// ---------------------------------------------------------------------------\n\n/** Generate an ECDSA P-384 key pair, write to `.stackwright/pipeline-keys.json`. */\nexport function initPipelineKeys(cwd: string): { publicKeyPem: string; fingerprint: string } {\n const keyDir = join(cwd, KEY_DIR);\n const keyPath = join(keyDir, KEY_FILE);\n\n // Reject symlinks on the key file path\n rejectSymlink(keyPath, 'pipeline-keys.json');\n\n // Ensure directory exists\n mkdirSync(keyDir, { recursive: true });\n\n // Generate ECDSA P-384 key pair\n const { publicKey, privateKey } = generateKeyPairSync('ec', {\n namedCurve: 'P-384',\n });\n\n const publicKeyPem = publicKey.export({ type: 'spki', format: 'pem' }) as string;\n const privateKeyPem = privateKey.export({ type: 'pkcs8', format: 'pem' }) as string;\n\n // SHA-256 fingerprint of the public key PEM\n const fingerprint = createHash('sha256').update(publicKeyPem).digest('hex');\n\n const keyFile: PipelineKeyFile = {\n version: '1.0',\n algorithm: ALGORITHM,\n createdAt: new Date().toISOString(),\n publicKeyPem,\n privateKeyPem,\n };\n\n writeFileSync(keyPath, JSON.stringify(keyFile, null, 2), { encoding: 'utf-8' });\n\n return { publicKeyPem, fingerprint };\n}\n\n/** Load pipeline key pair from disk. Validates PEM, rejects symlinks. */\nexport function loadPipelineKeys(cwd: string): { privateKey: KeyObject; publicKey: KeyObject } {\n const keyPath = join(cwd, KEY_DIR, KEY_FILE);\n\n // Reject symlinks\n rejectSymlink(keyPath, 'pipeline-keys.json');\n\n if (!existsSync(keyPath)) {\n throw new Error('Pipeline keys not found ā call initPipelineKeys() first');\n }\n\n let raw: string;\n try {\n raw = readFileSync(keyPath, 'utf-8');\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n throw new Error(`Cannot read pipeline keys: ${msg}`, { cause: err });\n }\n\n let parsed: PipelineKeyFile;\n try {\n parsed = JSON.parse(raw) as PipelineKeyFile;\n } catch {\n throw new Error('Pipeline keys file is not valid JSON');\n }\n\n // Basic PEM format validation\n if (\n typeof parsed.publicKeyPem !== 'string' ||\n !parsed.publicKeyPem.includes('-----BEGIN PUBLIC KEY-----')\n ) {\n throw new Error('Invalid public key PEM in pipeline keys file');\n }\n if (typeof parsed.privateKeyPem !== 'string' || !parsed.privateKeyPem.includes('-----BEGIN')) {\n throw new Error('Invalid private key PEM in pipeline keys file');\n }\n\n const publicKey = createPublicKey(parsed.publicKeyPem);\n const privateKey = createPrivateKey(parsed.privateKeyPem);\n\n return { privateKey, publicKey };\n}\n\n/** Overwrite private key material with zeros then delete. Idempotent. */\nexport function destroyPipelineKeys(cwd: string): void {\n const keyPath = join(cwd, KEY_DIR, KEY_FILE);\n\n if (!existsSync(keyPath)) return;\n\n // Reject symlinks even during destruction\n rejectSymlink(keyPath, 'pipeline-keys.json (destroy)');\n\n // Read ā overwrite private key material with zeros ā delete\n try {\n const raw = readFileSync(keyPath, 'utf-8');\n const parsed = JSON.parse(raw) as PipelineKeyFile;\n parsed.privateKeyPem = '0'.repeat(parsed.privateKeyPem.length);\n parsed.publicKeyPem = '0'.repeat(parsed.publicKeyPem.length);\n writeFileSync(keyPath, JSON.stringify(parsed, null, 2), { encoding: 'utf-8' });\n } catch {\n // Best-effort overwrite ā proceed to delete regardless\n }\n\n try {\n unlinkSync(keyPath);\n } catch {\n // Already gone ā idempotent\n }\n}\n\n// ---------------------------------------------------------------------------\n// 2. Artifact Signing\n// ---------------------------------------------------------------------------\n\n/** Sign artifact bytes with ECDSA P-384. Returns structured signature record. */\nexport function signArtifact(artifactBytes: Buffer, privateKey: KeyObject): ArtifactSignature {\n const digest = computeSha384(artifactBytes);\n const sig = sign('SHA384', artifactBytes, privateKey);\n\n return {\n digest,\n signature: sig.toString('base64'),\n algorithm: ALGORITHM,\n signedAt: new Date().toISOString(),\n };\n}\n\n// ---------------------------------------------------------------------------\n// 3. Artifact Verification\n// ---------------------------------------------------------------------------\n\n/** Verify ECDSA signature AND constant-time SHA-384 digest. Both must pass. */\nexport function verifyArtifact(\n artifactBytes: Buffer,\n signature: ArtifactSignature,\n publicKey: KeyObject\n): boolean {\n // Layer 1: ECDSA signature verification\n const sigValid = verify(\n 'SHA384',\n artifactBytes,\n publicKey,\n Buffer.from(signature.signature, 'base64')\n );\n\n if (!sigValid) return false;\n\n // Layer 2: Constant-time digest comparison\n const actualDigest = computeSha384(artifactBytes);\n return safeDigestEqual(actualDigest, signature.digest);\n}\n\n// ---------------------------------------------------------------------------\n// 4. Signature Manifest Management\n// ---------------------------------------------------------------------------\n\n/** Load signature manifest. Returns empty manifest if file doesn't exist. */\nexport function loadSignatureManifest(cwd: string): SignatureManifest {\n const manifestPath = join(cwd, ARTIFACTS_DIR, SIGNATURE_MANIFEST);\n\n rejectSymlink(manifestPath, 'signatures.json');\n\n if (!existsSync(manifestPath)) return emptyManifest();\n\n let raw: string;\n try {\n raw = readFileSync(manifestPath, 'utf-8');\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n throw new Error(`Cannot read signature manifest: ${msg}`, { cause: err });\n }\n\n try {\n const parsed = JSON.parse(raw) as SignatureManifest;\n // Basic shape validation ā don't trust what's on disk blindly\n if (parsed.version !== '1.0' || typeof parsed.signatures !== 'object') {\n throw new Error('Malformed signature manifest: invalid version or missing signatures object');\n }\n return parsed;\n } catch (err) {\n if (err instanceof Error && err.message.startsWith('Malformed')) throw err;\n throw new Error('Signature manifest is not valid JSON', { cause: err });\n }\n}\n\n/** Save a signature entry for a specific artifact. Read-modify-write. */\nexport function saveArtifactSignature(\n cwd: string,\n artifactFilename: string,\n sig: ArtifactSignature,\n signerOtter: string\n): void {\n const artifactsDir = join(cwd, ARTIFACTS_DIR);\n const manifestPath = join(artifactsDir, SIGNATURE_MANIFEST);\n\n rejectSymlink(manifestPath, 'signatures.json (save)');\n\n // Ensure artifacts directory exists\n mkdirSync(artifactsDir, { recursive: true });\n\n const manifest = loadSignatureManifest(cwd);\n\n manifest.signatures[artifactFilename] = {\n ...sig,\n signedBy: signerOtter,\n };\n\n writeFileSync(manifestPath, JSON.stringify(manifest, null, 2), { encoding: 'utf-8' });\n}\n\n/** Retrieve signature for a specific artifact, or null if absent. */\nexport function getArtifactSignature(\n cwd: string,\n artifactFilename: string\n): ArtifactSignature | null {\n const manifest = loadSignatureManifest(cwd);\n const entry = manifest.signatures[artifactFilename];\n if (!entry) return null;\n\n // Return just the ArtifactSignature fields (strip signedBy)\n return {\n digest: entry.digest,\n signature: entry.signature,\n algorithm: entry.algorithm,\n signedAt: entry.signedAt,\n };\n}\n\n// ---------------------------------------------------------------------------\n// 5. Audit Events ā SOC2 / FedRAMP / DoD ATO compliance\n// ---------------------------------------------------------------------------\n\n/**\n * Emit a structured ARTIFACT_SIGNATURE_FAIL audit event to stderr.\n *\n * Line prefix allows log shippers (FluentBit, syslog, CloudWatch, Splunk)\n * to route events via simple string filter before JSON parsing.\n */\nexport function emitSignatureAuditEvent(params: SignatureAuditEvent): void {\n const record = JSON.stringify({\n level: 'AUDIT',\n event: 'ARTIFACT_SIGNATURE_FAIL',\n timestamp: params.timestamp,\n source: params.source,\n artifactFilename: params.artifactFilename,\n expectedDigest: params.expectedDigest,\n actualDigest: params.actualDigest,\n phase: params.phase,\n });\n process.stderr.write(`ARTIFACT_SIGNATURE_FAIL ${record}\\n`);\n}\n\n// ---------------------------------------------------------------------------\n// 6. MCP Tool Registration\n// ---------------------------------------------------------------------------\n\n/** Per-artifact verification result returned by the MCP tool. */\nexport interface ArtifactVerificationResult {\n filename: string;\n verified: boolean;\n error?: string;\n signedBy?: string;\n signedAt?: string;\n}\n\n/** Register artifact signing verification tool on the MCP server. */\nexport function registerArtifactSigningTools(server: McpServer): void {\n server.tool(\n 'stackwright_pro_verify_artifact_signatures',\n 'Verify ECDSA P-384 signatures for all pipeline artifacts in .stackwright/artifacts/. ' +\n 'Auto-discovers keys from .stackwright/pipeline-keys.json. ' +\n 'Returns per-artifact verification status.',\n {\n cwd: z.string().optional().describe('Project root directory. Defaults to process.cwd().'),\n },\n async ({ cwd: cwdParam }) => {\n const cwd = cwdParam ?? process.cwd();\n\n // 1. Load pipeline keys\n let publicKey: KeyObject;\n try {\n const keys = loadPipelineKeys(cwd);\n publicKey = keys.publicKey;\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify({\n error: true,\n message: `Cannot load pipeline keys: ${msg}`,\n }),\n },\n ],\n isError: true,\n };\n }\n\n // 2. Load signature manifest\n let manifest: SignatureManifest;\n try {\n manifest = loadSignatureManifest(cwd);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify({\n error: true,\n message: `Cannot load signature manifest: ${msg}`,\n }),\n },\n ],\n isError: true,\n };\n }\n\n // 3. Discover artifact files on disk\n const artifactsPath = join(cwd, ARTIFACTS_DIR);\n let artifactFiles: string[] = [];\n try {\n if (existsSync(artifactsPath)) {\n artifactFiles = readdirSync(artifactsPath).filter(\n (f) => f.endsWith('.json') && f !== SIGNATURE_MANIFEST\n );\n }\n } catch {\n // If we can't read the directory, we'll report zero artifacts\n }\n\n // 4. Verify each artifact\n const results: ArtifactVerificationResult[] = [];\n let hasFailure = false;\n\n for (const filename of artifactFiles) {\n const filePath = join(artifactsPath, filename);\n\n // Symlink guard\n try {\n rejectSymlink(filePath, `artifact ${filename}`);\n } catch {\n results.push({\n filename,\n verified: false,\n error: 'Refusing to verify symlink',\n });\n hasFailure = true;\n continue;\n }\n\n // Read artifact bytes\n let artifactBytes: Buffer;\n try {\n artifactBytes = readFileSync(filePath);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n results.push({\n filename,\n verified: false,\n error: `Cannot read artifact: ${msg}`,\n });\n hasFailure = true;\n continue;\n }\n\n // Look up signature in manifest\n const entry = manifest.signatures[filename];\n if (!entry) {\n results.push({\n filename,\n verified: false,\n error: 'No signature found in manifest',\n });\n hasFailure = true;\n continue;\n }\n\n // Verify\n const sig: ArtifactSignature = {\n digest: entry.digest,\n signature: entry.signature,\n algorithm: entry.algorithm,\n signedAt: entry.signedAt,\n };\n\n const verified = verifyArtifact(artifactBytes, sig, publicKey);\n\n if (!verified) {\n const actualDigest = computeSha384(artifactBytes);\n emitSignatureAuditEvent({\n artifactFilename: filename,\n expectedDigest: sig.digest,\n actualDigest,\n phase: entry.signedBy ?? 'unknown',\n timestamp: new Date().toISOString(),\n source: 'stackwright_pro_verify_artifact_signatures',\n });\n\n results.push({\n filename,\n verified: false,\n error: `Signature verification failed ā artifact may have been tampered with`,\n signedBy: entry.signedBy,\n signedAt: entry.signedAt,\n });\n hasFailure = true;\n } else {\n results.push({\n filename,\n verified: true,\n signedBy: entry.signedBy,\n signedAt: entry.signedAt,\n });\n }\n }\n\n // 5. Report artifacts in manifest that are missing from disk\n for (const manifestFilename of Object.keys(manifest.signatures)) {\n if (!artifactFiles.includes(manifestFilename)) {\n results.push({\n filename: manifestFilename,\n verified: false,\n error: 'Artifact referenced in manifest but missing from disk',\n });\n hasFailure = true;\n }\n }\n\n const verifiedCount = results.filter((r) => r.verified).length;\n const failedCount = results.filter((r) => !r.verified).length;\n\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify({\n totalArtifacts: artifactFiles.length,\n verifiedCount,\n failedCount,\n results,\n ...(hasFailure\n ? {\n error:\n 'SIGNATURE VERIFICATION FAILED: One or more artifact signatures are invalid. ' +\n 'Do not proceed ā artifacts may have been tampered with.',\n }\n : {}),\n }),\n },\n ],\n isError: hasFailure,\n };\n }\n );\n}\n","/**\n * Safe Write ā Deterministic File-Write Guard\n *\n * The controlled I/O chokepoint for ALL file writes from specialist otters.\n * Every write goes through per-otter path allowlists. The LLM cannot write\n * to arbitrary filesystem paths.\n *\n * Why this matters: defense/regulated industry customers need guarantees that\n * \"the LLM cannot decide what to read and write from anywhere on your filesystem.\"\n */\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { boolCoerce } from '../coerce.js';\nimport { writeFileSync, existsSync, mkdirSync, lstatSync } from 'fs';\nimport { normalize, isAbsolute, dirname, join } from 'path';\n\n// ---------------------------------------------------------------------------\n// Per-otter path allowlists\n// ---------------------------------------------------------------------------\n\n/**\n * Allowlists define which file patterns each otter is permitted to write.\n * Paths are relative to the project root (cwd).\n * Patterns use simple prefix + suffix matching (no regex ā deterministic and auditable).\n */\ninterface PathAllowRule {\n /** Path prefix the file must start with (relative to project root) */\n prefix: string;\n /** File suffix/extension the file must end with */\n suffix: string;\n /** Human-readable description for audit logs */\n description: string;\n}\n\nconst OTTER_WRITE_ALLOWLISTS: Record<string, PathAllowRule[]> = {\n 'stackwright-pro-designer-otter': [\n { prefix: '.stackwright/artifacts/', suffix: '.json', description: 'Design language artifact' },\n ],\n 'stackwright-pro-theme-otter': [\n { prefix: '.stackwright/artifacts/', suffix: '.json', description: 'Theme tokens artifact' },\n ],\n 'stackwright-pro-auth-otter': [\n { prefix: '.stackwright/artifacts/', suffix: '.json', description: 'Auth config artifact' },\n { prefix: 'config/', suffix: '.yml', description: 'Auth YAML config' },\n { prefix: 'config/', suffix: '.yaml', description: 'Auth YAML config' },\n {\n prefix: '.env',\n suffix: '',\n description: 'Dotenv files (.env, .env.local, .env.production, etc.)',\n },\n ],\n 'stackwright-pro-data-otter': [\n { prefix: '.stackwright/artifacts/', suffix: '.json', description: 'Data config artifact' },\n { prefix: 'stackwright.yml', suffix: '', description: 'Stackwright config' },\n ],\n 'stackwright-pro-page-otter': [\n { prefix: 'pages/', suffix: '/content.yml', description: 'Page content YAML' },\n { prefix: 'pages/', suffix: '/content.yaml', description: 'Page content YAML' },\n { prefix: '.stackwright/artifacts/', suffix: '.json', description: 'Pages manifest' },\n ],\n 'stackwright-pro-dashboard-otter': [\n { prefix: 'pages/', suffix: '/content.yml', description: 'Dashboard content YAML' },\n { prefix: 'pages/', suffix: '/content.yaml', description: 'Dashboard content YAML' },\n { prefix: '.stackwright/artifacts/', suffix: '.json', description: 'Dashboard manifest' },\n ],\n 'stackwright-pro-workflow-otter': [\n { prefix: 'workflows/', suffix: '.yml', description: 'Workflow definition' },\n { prefix: 'workflows/', suffix: '.yaml', description: 'Workflow definition' },\n { prefix: '.stackwright/artifacts/', suffix: '.json', description: 'Workflow config' },\n ],\n 'stackwright-pro-api-otter': [\n { prefix: '.stackwright/artifacts/', suffix: '.json', description: 'API config artifact' },\n ],\n};\n\n// ---------------------------------------------------------------------------\n// Protected paths ā managed by other sink tools, never written here\n// ---------------------------------------------------------------------------\n\nconst PROTECTED_PATH_PREFIXES = [\n '.stackwright/pipeline-state.json',\n '.stackwright/pipeline-keys.json', // ephemeral signing keys\n '.stackwright/artifacts/signatures.json', // artifact signature manifest\n '.stackwright/questions/',\n '.stackwright/answers/',\n];\n\n// ---------------------------------------------------------------------------\n// Per-file-type content size limits (defense-in-depth: disk exhaustion vector)\n// Mirrors MAX_OTTER_BYTES in integrity.ts ā different thresholds per content type.\n// Exported for test assertions; callers cannot negotiate around these limits.\n// ---------------------------------------------------------------------------\n\n/** 512 KB ā JSON artifacts (.stackwright/artifacts/*.json) */\nexport const MAX_SAFE_WRITE_BYTES_JSON = 512 * 1024;\n\n/** 256 KB ā YAML content files (pages, workflows, config) */\nexport const MAX_SAFE_WRITE_BYTES_YAML = 256 * 1024;\n\n/** 4 KB ā dotenv files (.env, .env.local, .env.production) */\nexport const MAX_SAFE_WRITE_BYTES_ENV = 4 * 1024;\n\n/** 256 KB ā fallback for any unrecognized extension */\nexport const MAX_SAFE_WRITE_BYTES_DEFAULT = 256 * 1024;\n\n/**\n * Resolve the maximum allowed byte size for a given file path.\n * Exported for testing ā not for callers to negotiate around.\n */\nexport function getMaxBytesForPath(filePath: string): { limit: number; label: string } {\n if (filePath.endsWith('.json')) return { limit: MAX_SAFE_WRITE_BYTES_JSON, label: 'JSON' };\n if (filePath.endsWith('.yml') || filePath.endsWith('.yaml'))\n return { limit: MAX_SAFE_WRITE_BYTES_YAML, label: 'YAML' };\n if (filePath === '.env' || /^\\.env\\.[a-zA-Z0-9]+/.test(filePath))\n return { limit: MAX_SAFE_WRITE_BYTES_ENV, label: 'env' };\n return { limit: MAX_SAFE_WRITE_BYTES_DEFAULT, label: 'default' };\n}\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface SafeWriteInput {\n callerOtter: string;\n filePath: string;\n content: string;\n createDirectories?: boolean;\n _cwd?: string;\n}\n\ninterface SafeWriteSuccess {\n success: true;\n path: string;\n bytesWritten: number;\n allowRule: string;\n}\n\ninterface SafeWriteRejection {\n success: false;\n error: string;\n callerOtter: string;\n attemptedPath: string;\n allowedPaths: string[];\n}\n\n// ---------------------------------------------------------------------------\n// Core security logic ā exported for testing\n// ---------------------------------------------------------------------------\n\nexport function checkPathAllowed(\n callerOtter: string,\n filePath: string\n): { allowed: boolean; rule?: string; error?: string } {\n // 1. Normalize the path ā reject path traversal\n const normalized = normalize(filePath);\n if (normalized.includes('..')) {\n return { allowed: false, error: 'Path traversal detected: \"..\" segments are not allowed' };\n }\n\n // 2. Reject absolute paths\n if (isAbsolute(normalized)) {\n return {\n allowed: false,\n error: 'Absolute paths are not allowed ā use paths relative to project root',\n };\n }\n\n // 3. Foreman never writes directly\n if (callerOtter === 'stackwright-pro-foreman-otter') {\n return {\n allowed: false,\n error: 'The foreman otter coordinates ā it does not write files directly',\n };\n }\n\n // 4. Check caller is known\n const allowlist = OTTER_WRITE_ALLOWLISTS[callerOtter];\n if (!allowlist) {\n return {\n allowed: false,\n error: `Unknown otter: \"${callerOtter}\" is not in the write allowlist`,\n };\n }\n\n // 5. Reject protected paths (managed by other sink tools)\n for (const protectedPrefix of PROTECTED_PATH_PREFIXES) {\n if (normalized === protectedPrefix || normalized.startsWith(protectedPrefix)) {\n return {\n allowed: false,\n error: `Path \"${normalized}\" is managed by dedicated sink tools, not safe_write`,\n };\n }\n }\n\n // 6. Check path matches at least one allowlist rule\n for (const rule of allowlist) {\n const prefixMatch = normalized.startsWith(rule.prefix);\n const suffixMatch = rule.suffix === '' || normalized.endsWith(rule.suffix);\n if (prefixMatch && suffixMatch) {\n // For .env rules, enforce strict dotenv filename pattern\n // Only allow: .env, .env.local, .env.development, .env.production, .env.test, etc.\n // Reject: .envrc, .env.sh, .environment/, .envoy.yaml\n if (rule.prefix === '.env' && rule.suffix === '') {\n if (!/^\\.env(\\.[a-zA-Z0-9]{3,})*$/.test(normalized)) {\n continue; // this rule doesn't match, try next\n }\n }\n return { allowed: true, rule: rule.description };\n }\n }\n\n return {\n allowed: false,\n error: `Path \"${normalized}\" does not match any allowed write pattern for ${callerOtter}`,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Content validation helpers\n// ---------------------------------------------------------------------------\n\nfunction validateJsonContent(content: string): string | null {\n try {\n JSON.parse(content);\n return null;\n } catch (err) {\n return `Invalid JSON: ${err instanceof Error ? err.message : String(err)}`;\n }\n}\n\nfunction validateYamlContent(content: string): string | null {\n const trimmed = content.trimStart();\n\n // Entity expansion DoS check ā reject deeply nested anchor references\n // Pattern: &anchor followed by [*anchor] repeated many times\n // 20+ occurrences of any [*name] pattern indicates potential entity expansion attack\n const anchorRefPattern = /\\[(\\*[\\w]+)\\]/g;\n const matches = [...content.matchAll(anchorRefPattern)];\n if (matches.length >= 20) {\n return 'YAML entity expansion pattern detected ā too many anchor references';\n }\n\n // Also check for repeated identical anchor refs (exponential expansion)\n const anchorDefPattern = /&([\\w]+)/g;\n const defs = [...content.matchAll(anchorDefPattern)];\n if (defs.length >= 10) {\n // Check for exponential pattern: &a [*a *a *a...]\n const anchorNameCounts = new Map<string, number>();\n for (const [, name] of defs) {\n const count = (anchorNameCounts.get(name) ?? 0) + 1;\n anchorNameCounts.set(name, count);\n if (count >= 10) {\n return 'YAML entity expansion: repeated anchor definitions detected';\n }\n }\n }\n\n if (trimmed.startsWith('import ') || trimmed.startsWith('import{')) {\n return 'Content starts with \"import\" ā this looks like code, not YAML';\n }\n if (trimmed.startsWith('export ') || trimmed.startsWith('export{')) {\n return 'Content starts with \"export\" ā this looks like code, not YAML';\n }\n if (trimmed.startsWith('#!'))\n return 'Content starts with shebang ā this looks like a script, not YAML';\n if (/!!(?:python|ruby|perl|js|java)/i.test(content))\n return 'YAML deserialization attack tags detected';\n if (trimmed.startsWith('<') && !trimmed.startsWith('<<'))\n return 'Content looks like markup, not YAML';\n return null;\n}\n\nfunction validateEnvContent(content: string): string | null {\n const lines = content.split('\\n');\n for (let i = 0; i < lines.length; i++) {\n const raw = lines[i];\n if (raw === undefined) continue;\n const line = raw.trim();\n // Allow empty lines, comments, and key=value pairs\n if (line === '' || line.startsWith('#')) continue;\n if (!/^[A-Za-z_][A-Za-z0-9_]*=/.test(line)) {\n return `Line ${i + 1} is not a valid env entry (expected KEY=value): \"${line}\"`;\n }\n }\n return null;\n}\n\nfunction validateContent(filePath: string, content: string): string | null {\n if (filePath.endsWith('.json')) return validateJsonContent(content);\n if (filePath.endsWith('.yml') || filePath.endsWith('.yaml')) return validateYamlContent(content);\n if (filePath === '.env' || filePath.startsWith('.env')) return validateEnvContent(content);\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Handler (exported for direct testing ā no MCP server needed)\n// ---------------------------------------------------------------------------\n\nexport function handleSafeWrite(input: SafeWriteInput): { text: string; isError: boolean } {\n const cwd = input._cwd ?? process.cwd();\n const { callerOtter, filePath, content, createDirectories = true } = input;\n\n // 1. Path allowlist check\n const check = checkPathAllowed(callerOtter, filePath);\n if (!check.allowed) {\n const allowlist = OTTER_WRITE_ALLOWLISTS[callerOtter] ?? [];\n const allowedPaths = allowlist.map((r) => `${r.prefix}*${r.suffix} (${r.description})`);\n const result: SafeWriteRejection = {\n success: false,\n error: check.error ?? 'Path not allowed',\n callerOtter,\n attemptedPath: filePath,\n allowedPaths,\n };\n return { text: JSON.stringify(result), isError: true };\n }\n\n // 2. Content size limit check (defense-in-depth: disk exhaustion vector)\n const contentBytes = Buffer.byteLength(content, 'utf-8');\n const { limit: maxBytes, label: fileTypeLabel } = getMaxBytesForPath(filePath);\n if (contentBytes > maxBytes) {\n const result: SafeWriteRejection = {\n success: false,\n error: `Content size ${contentBytes} bytes exceeds ${fileTypeLabel} limit of ${maxBytes} bytes (${maxBytes / 1024} KB)`,\n callerOtter,\n attemptedPath: filePath,\n allowedPaths: [],\n };\n return { text: JSON.stringify(result), isError: true };\n }\n\n const normalized = normalize(filePath);\n const fullPath = join(cwd, normalized);\n\n // 3. Reject symlinks at target\n if (existsSync(fullPath)) {\n try {\n const stat = lstatSync(fullPath);\n if (stat.isSymbolicLink()) {\n const result: SafeWriteRejection = {\n success: false,\n error: 'Target path is a symlink ā refusing to write through symlinks for security',\n callerOtter,\n attemptedPath: filePath,\n allowedPaths: [],\n };\n return { text: JSON.stringify(result), isError: true };\n }\n } catch {\n // lstat failed ā file might have been removed between exists check and lstat, proceed\n }\n }\n\n // 4. Content validation\n const contentError = validateContent(normalized, content);\n if (contentError) {\n const result: SafeWriteRejection = {\n success: false,\n error: `Content validation failed: ${contentError}`,\n callerOtter,\n attemptedPath: filePath,\n allowedPaths: [],\n };\n return { text: JSON.stringify(result), isError: true };\n }\n\n // 5. Write the file\n try {\n if (createDirectories) {\n mkdirSync(dirname(fullPath), { recursive: true });\n }\n\n writeFileSync(fullPath, content, { encoding: 'utf-8' });\n\n const result: SafeWriteSuccess = {\n success: true,\n path: normalized,\n bytesWritten: Buffer.byteLength(content, 'utf-8'),\n allowRule: check.rule ?? 'unknown',\n };\n return { text: JSON.stringify(result), isError: false };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n const result: SafeWriteRejection = {\n success: false,\n error: `Write failed: ${message}`,\n callerOtter,\n attemptedPath: filePath,\n allowedPaths: [],\n };\n return { text: JSON.stringify(result), isError: true };\n }\n}\n\n// ---------------------------------------------------------------------------\n// MCP tool registration\n// ---------------------------------------------------------------------------\n\nexport function registerSafeWriteTools(server: McpServer): void {\n const DESC =\n 'Controlled file-write chokepoint. Every write from specialist otters goes through this tool with per-otter path allowlists. The LLM cannot write to arbitrary filesystem paths.';\n\n server.tool(\n 'stackwright_pro_safe_write',\n DESC,\n {\n callerOtter: z\n .string()\n .describe('The otter agent name requesting the write, e.g. \"stackwright-pro-page-otter\"'),\n filePath: z\n .string()\n .describe('Relative path from project root, e.g. \"pages/dashboard/content.yml\"'),\n content: z.string().describe('File content to write'),\n createDirectories: boolCoerce(z.boolean().optional().default(true)).describe(\n \"Create parent directories if they don't exist. Default: true\"\n ),\n },\n async ({ callerOtter, filePath, content, createDirectories }) => {\n const result = handleSafeWrite({\n callerOtter,\n filePath,\n content,\n ...(createDirectories != null ? { createDirectories } : {}),\n });\n return { content: [{ type: 'text' as const, text: result.text }], isError: result.isError };\n }\n );\n}\n","/**\n * Auth MCP Tools\n *\n * Implements stackwright_pro_configure_auth ā the tool that the auth-otter\n * has referenced since day one but that was never built. Its absence meant the\n * auth-otter would fall back to writing middleware.ts directly, bypassing the\n * TOOL GUARD that was supposed to prevent exactly that.\n *\n * For CAC/PKI: generated middleware.ts carries an explicit SECURITY REVIEW\n * REQUIRED comment. Certificate chain validation must be verified by a\n * security officer before production deployment on DoD systems.\n */\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { readFileSync, writeFileSync, existsSync } from 'fs';\nimport { join } from 'path';\nimport { jsonCoerce, boolCoerce, numCoerce } from '../coerce.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface ConfigureAuthParams {\n method: 'cac' | 'oidc' | 'oauth2' | 'none';\n provider?: 'azure-ad' | 'okta' | 'ping' | 'cognito' | 'custom';\n // CAC\n cacCaBundle?: string;\n cacEdipiLookup?: string;\n cacOcspEndpoint?: string;\n cacCertHeader?: string;\n // OIDC\n oidcDiscoveryUrl?: string;\n oidcClientId?: string;\n oidcClientSecret?: string;\n oidcScopes?: string;\n oidcRoleClaim?: string;\n // OAuth2\n oauth2AuthUrl?: string;\n oauth2TokenUrl?: string;\n oauth2ClientId?: string;\n oauth2ClientSecret?: string;\n oauth2Scopes?: string;\n // RBAC\n rbacRoles?: string[];\n rbacDefaultRole?: string;\n // Audit\n auditEnabled?: boolean;\n auditRetentionDays?: number;\n // Routes\n protectedRoutes?: string[];\n // Injection for tests\n _cwd?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction buildHierarchy(roles: string[]): Record<string, string[]> {\n const h: Record<string, string[]> = {};\n for (let i = 0; i < roles.length - 1; i++) {\n h[roles[i]!] = roles.slice(i + 1);\n }\n return h;\n}\n\nfunction hierarchyToYaml(hierarchy: Record<string, string[]>, indent: string): string {\n const entries = Object.entries(hierarchy);\n if (entries.length === 0) return `${indent}{}`;\n return entries.map(([role, subs]) => `${indent}${role}: [${subs.join(', ')}]`).join('\\n');\n}\n\nfunction rolesToYaml(roles: string[], indent: string): string {\n return roles.map((r) => `${indent}- ${r}`).join('\\n');\n}\n\nfunction routesToYaml(routes: string[], defaultRole: string, indent: string): string {\n return routes\n .map((r) => `${indent}- pattern: ${r}\\n${indent} requiredRole: ${defaultRole}`)\n .join('\\n');\n}\n\n/** Replace or append the auth: block in existing YAML content. */\nfunction upsertAuthBlock(existing: string, authYaml: string): string {\n const lines = existing.split('\\n');\n let authStart = -1;\n let authEnd = lines.length;\n\n for (let i = 0; i < lines.length; i++) {\n if (/^auth:/.test(lines[i]!)) {\n authStart = i;\n } else if (\n authStart >= 0 &&\n i > authStart &&\n /^\\S/.test(lines[i]!) &&\n lines[i]!.trim() !== ''\n ) {\n authEnd = i;\n break;\n }\n }\n\n if (authStart < 0) {\n // No existing auth block ā append\n return existing.trimEnd() + '\\n' + authYaml + '\\n';\n }\n\n // Replace auth block\n const before = lines.slice(0, authStart);\n const after = lines.slice(authEnd);\n return [...before, ...authYaml.trimEnd().split('\\n'), ...(after.length ? after : [])].join('\\n');\n}\n\n// ---------------------------------------------------------------------------\n// Content generators\n// ---------------------------------------------------------------------------\n\nfunction generateMiddlewareContent(\n method: string,\n params: ConfigureAuthParams,\n roles: string[],\n defaultRole: string,\n hierarchy: Record<string, string[]>,\n auditEnabled: boolean,\n auditRetentionDays: number,\n protectedRoutes: string[]\n): string {\n const rbacBlock = ` rbac: {\n roles: ${JSON.stringify(roles)},\n defaultRole: '${defaultRole}',\n hierarchy: ${JSON.stringify(hierarchy, null, 4)},\n },`;\n const auditBlock = ` audit: {\n enabled: ${auditEnabled},\n retentionDays: ${auditRetentionDays},\n },`;\n const routesBlock = ` protectedRoutes: ${JSON.stringify(protectedRoutes)},`;\n const configBlock = `export const config = {\n matcher: ${JSON.stringify(protectedRoutes)},\n};`;\n\n if (method === 'cac') {\n const caBundle = params.cacCaBundle ?? './certs/dod-ca-bundle.pem';\n const edipiLookup = params.cacEdipiLookup ?? './config/edipi-lookup.json';\n const ocspEndpoint = params.cacOcspEndpoint ?? 'https://ocsp.disa.mil';\n const certHeader = params.cacCertHeader ?? 'X-SSL-Client-Cert';\n return `// middleware.ts ā generated by @stackwright-pro/auth\n// ā ļø SECURITY REVIEW REQUIRED ā CAC/PKI certificate validation\n// DoD security officer review required before production deployment.\n// Verify: CA bundle completeness, EDIPI lookup endpoint, OCSP accessibility.\nimport { createProMiddleware } from '@stackwright-pro/auth-nextjs';\n\nexport const middleware = createProMiddleware({\n method: 'cac',\n cac: {\n caBundle: process.env.CAC_CA_BUNDLE ?? '${caBundle}',\n edipiLookup: '${edipiLookup}',\n ocspEndpoint: process.env.CAC_OCSP_ENDPOINT ?? '${ocspEndpoint}',\n certHeader: '${certHeader}',\n },\n${rbacBlock}\n${auditBlock}\n${routesBlock}\n});\n\n${configBlock}\n`;\n }\n\n if (method === 'oidc') {\n const scopes = params.oidcScopes ?? 'openid profile email';\n const roleClaim = params.oidcRoleClaim ?? 'roles';\n return `// middleware.ts ā generated by @stackwright-pro/auth-nextjs\nimport { createProMiddleware } from '@stackwright-pro/auth-nextjs';\n\nexport const middleware = createProMiddleware({\n method: 'oidc',\n oidc: {\n discoveryUrl: process.env.OIDC_DISCOVERY_URL!,\n clientId: process.env.OIDC_CLIENT_ID!,\n clientSecret: process.env.OIDC_CLIENT_SECRET!,\n scopes: '${scopes}',\n roleClaim: '${roleClaim}',\n },\n${rbacBlock}\n${auditBlock}\n${routesBlock}\n});\n\n${configBlock}\n`;\n }\n\n // oauth2\n const scopes = params.oauth2Scopes ?? 'read write';\n return `// middleware.ts ā generated by @stackwright-pro/auth-nextjs\nimport { createProMiddleware } from '@stackwright-pro/auth-nextjs';\n\nexport const middleware = createProMiddleware({\n method: 'oauth2',\n oauth2: {\n authorizationUrl: process.env.OAUTH2_AUTH_URL!,\n tokenUrl: process.env.OAUTH2_TOKEN_URL!,\n clientId: process.env.OAUTH2_CLIENT_ID!,\n clientSecret: process.env.OAUTH2_CLIENT_SECRET!,\n scopes: '${scopes}',\n },\n${rbacBlock}\n${auditBlock}\n${routesBlock}\n});\n\n${configBlock}\n`;\n}\n\nfunction generateEnvBlock(method: string, params: ConfigureAuthParams): string {\n if (method === 'cac') {\n return `# Authentication (CAC/PKI ā DoD)\n# ā ļø SECURITY REVIEW REQUIRED before production deployment\nCAC_CA_BUNDLE=./certs/dod-ca-bundle.pem\nCAC_OCSP_ENDPOINT=https://ocsp.disa.mil\n`;\n }\n\n if (method === 'oidc') {\n const label = params.provider ?? 'OIDC';\n const discoveryUrl =\n params.oidcDiscoveryUrl ?? 'https://your-provider/.well-known/openid-configuration';\n return `# Authentication (OIDC ā ${label})\nOIDC_DISCOVERY_URL=${discoveryUrl}\nOIDC_CLIENT_ID=your-client-id\nOIDC_CLIENT_SECRET=your-client-secret\n`;\n }\n\n // oauth2\n const authUrl = params.oauth2AuthUrl ?? 'https://your-auth-server/authorize';\n const tokenUrl = params.oauth2TokenUrl ?? 'https://your-auth-server/token';\n return `# Authentication (OAuth2)\nOAUTH2_AUTH_URL=${authUrl}\nOAUTH2_TOKEN_URL=${tokenUrl}\nOAUTH2_CLIENT_ID=your-client-id\nOAUTH2_CLIENT_SECRET=your-client-secret\n`;\n}\n\nfunction generateYamlBlock(\n method: string,\n params: ConfigureAuthParams,\n roles: string[],\n defaultRole: string,\n hierarchy: Record<string, string[]>,\n auditEnabled: boolean,\n auditRetentionDays: number,\n protectedRoutes: string[]\n): string {\n const rbacSection = ` rbac:\n roles:\n${rolesToYaml(roles, ' ')}\n defaultRole: ${defaultRole}\n hierarchy:\n${hierarchyToYaml(hierarchy, ' ')}`;\n\n const auditSection = ` audit:\n enabled: ${auditEnabled}\n retentionDays: ${auditRetentionDays}`;\n\n const routesSection = ` protectedRoutes:\n${routesToYaml(protectedRoutes, ' ', defaultRole)}`.replace(/\\n\\s+,/g, '');\n\n // Re-do routesSection cleanly:\n const routeLines = protectedRoutes\n .map((r) => ` - pattern: ${r}\\n requiredRole: ${defaultRole}`)\n .join('\\n');\n\n const providerLine = params.provider ? ` provider: ${params.provider}\\n` : '';\n\n if (method === 'cac') {\n const caBundle = params.cacCaBundle ?? './certs/dod-ca-bundle.pem';\n const edipiLookup = params.cacEdipiLookup ?? './config/edipi-lookup.json';\n const ocspEndpoint = params.cacOcspEndpoint ?? 'https://ocsp.disa.mil';\n const certHeader = params.cacCertHeader ?? 'X-SSL-Client-Cert';\n return `auth:\n method: cac\n${providerLine} middleware: ./middleware.ts\n cac:\n caBundle: \\${CAC_CA_BUNDLE}\n edipiLookup: ${edipiLookup}\n ocspEndpoint: \\${CAC_OCSP_ENDPOINT}\n certHeader: ${certHeader}\n${rbacSection}\n protectedRoutes:\n${routeLines}\n${auditSection}\n`;\n }\n\n if (method === 'oidc') {\n const scopes = params.oidcScopes ?? 'openid profile email';\n const roleClaim = params.oidcRoleClaim ?? 'roles';\n return `auth:\n method: oidc\n${providerLine} middleware: ./middleware.ts\n oidc:\n discoveryUrl: \\${OIDC_DISCOVERY_URL}\n clientId: \\${OIDC_CLIENT_ID}\n clientSecret: \\${OIDC_CLIENT_SECRET}\n scopes: ${scopes}\n roleClaim: ${roleClaim}\n${rbacSection}\n protectedRoutes:\n${routeLines}\n${auditSection}\n`;\n }\n\n // oauth2\n const scopes = params.oauth2Scopes ?? 'read write';\n return `auth:\n method: oauth2\n${providerLine} middleware: ./middleware.ts\n oauth2:\n authorizationUrl: \\${OAUTH2_AUTH_URL}\n tokenUrl: \\${OAUTH2_TOKEN_URL}\n clientId: \\${OAUTH2_CLIENT_ID}\n clientSecret: \\${OAUTH2_CLIENT_SECRET}\n scopes: ${scopes}\n${rbacSection}\n protectedRoutes:\n${routeLines}\n${auditSection}\n`;\n}\n\n// ---------------------------------------------------------------------------\n// Exported handler (called directly in tests ā no MCP server spin-up needed)\n// ---------------------------------------------------------------------------\n\nexport async function configureAuthHandler(\n params: ConfigureAuthParams,\n cwd: string\n): Promise<{ content: Array<{ type: 'text'; text: string }>; isError?: boolean }> {\n const {\n method,\n provider,\n rbacRoles = ['SUPER_ADMIN', 'ADMIN', 'ANALYST'],\n auditEnabled = true,\n auditRetentionDays = 90,\n protectedRoutes = ['/dashboard/:path*'],\n } = params;\n\n const roles = rbacRoles;\n const defaultRole = params.rbacDefaultRole ?? roles[roles.length - 1]!;\n const hierarchy = buildHierarchy(roles);\n\n // āā Short-circuit for method: none āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n if (method === 'none') {\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify({\n success: true,\n method: 'none',\n provider: null,\n rbacRoles: roles,\n rbacDefaultRole: defaultRole,\n protectedRoutesCount: protectedRoutes.length,\n filesWritten: [],\n securityWarning: null,\n }),\n },\n ],\n };\n }\n\n const filesWritten: string[] = [];\n\n try {\n // āā Step 2 ā middleware.ts āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n const middlewareContent = generateMiddlewareContent(\n method,\n params,\n roles,\n defaultRole,\n hierarchy,\n auditEnabled,\n auditRetentionDays,\n protectedRoutes\n );\n writeFileSync(join(cwd, 'middleware.ts'), middlewareContent, 'utf8');\n filesWritten.push('middleware.ts');\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify({ success: false, error: `Failed writing middleware.ts: ${msg}` }),\n },\n ],\n isError: true,\n };\n }\n\n try {\n // āā Step 3 ā .env.example āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n const envBlock = generateEnvBlock(method, params);\n const envPath = join(cwd, '.env.example');\n if (existsSync(envPath)) {\n const existing = readFileSync(envPath, 'utf8');\n writeFileSync(envPath, existing.trimEnd() + '\\n\\n' + envBlock, 'utf8');\n } else {\n writeFileSync(envPath, envBlock, 'utf8');\n }\n filesWritten.push('.env.example');\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify({ success: false, error: `Failed writing .env.example: ${msg}` }),\n },\n ],\n isError: true,\n };\n }\n\n try {\n // āā Step 4 ā stackwright.yml āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n const authYaml = generateYamlBlock(\n method,\n params,\n roles,\n defaultRole,\n hierarchy,\n auditEnabled,\n auditRetentionDays,\n protectedRoutes\n );\n const ymlPath = join(cwd, 'stackwright.yml');\n if (!existsSync(ymlPath)) {\n writeFileSync(ymlPath, authYaml, 'utf8');\n } else {\n const existing = readFileSync(ymlPath, 'utf8');\n writeFileSync(ymlPath, upsertAuthBlock(existing, authYaml), 'utf8');\n }\n filesWritten.push('stackwright.yml');\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify({ success: false, error: `Failed writing stackwright.yml: ${msg}` }),\n },\n ],\n isError: true,\n };\n }\n\n // āā Step 5 ā Return summary āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n const securityWarning =\n method === 'cac'\n ? 'SECURITY REVIEW REQUIRED ā CAC certificate chain must be verified before production deployment'\n : null;\n\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify({\n success: true,\n method,\n provider: provider ?? null,\n rbacRoles: roles,\n rbacDefaultRole: defaultRole,\n protectedRoutesCount: protectedRoutes.length,\n filesWritten,\n securityWarning,\n }),\n },\n ],\n };\n}\n\n// ---------------------------------------------------------------------------\n// MCP tool registration\n// ---------------------------------------------------------------------------\n\nexport function registerAuthTools(server: McpServer): void {\n server.tool(\n 'stackwright_pro_configure_auth',\n 'Generate authentication middleware and configuration for a Next.js Stackwright application. ' +\n 'Writes `middleware.ts` from a secure template, appends/updates the `auth:` section in `stackwright.yml`, ' +\n 'and generates `.env.example` with required environment variables. ' +\n 'ā ļø For CAC/PKI: generated `middleware.ts` carries a SECURITY REVIEW REQUIRED comment ā ' +\n 'certificate chain validation must be verified by a DoD security officer before production deployment. ' +\n 'This is the ONLY approved path to generating `middleware.ts`. Never write TypeScript auth files directly.',\n {\n method: z.enum(['cac', 'oidc', 'oauth2', 'none']),\n provider: z.enum(['azure-ad', 'okta', 'ping', 'cognito', 'custom']).optional(),\n // CAC\n cacCaBundle: z.string().optional(),\n cacEdipiLookup: z.string().optional(),\n cacOcspEndpoint: z.string().optional(),\n cacCertHeader: z.string().optional(),\n // OIDC\n oidcDiscoveryUrl: z.string().optional(),\n oidcClientId: z.string().optional(),\n oidcClientSecret: z.string().optional(),\n oidcScopes: z.string().optional(),\n oidcRoleClaim: z.string().optional(),\n // OAuth2\n oauth2AuthUrl: z.string().optional(),\n oauth2TokenUrl: z.string().optional(),\n oauth2ClientId: z.string().optional(),\n oauth2ClientSecret: z.string().optional(),\n oauth2Scopes: z.string().optional(),\n // RBAC\n rbacRoles: jsonCoerce(z.array(z.string()).optional()),\n rbacDefaultRole: z.string().optional(),\n // Audit\n auditEnabled: boolCoerce(z.boolean().optional()),\n auditRetentionDays: numCoerce(z.number().int().positive().optional()),\n // Routes\n protectedRoutes: jsonCoerce(z.array(z.string()).optional()),\n // Injection for tests\n _cwd: z.string().optional(),\n },\n async (params) => {\n const cwd = params._cwd ?? process.cwd();\n return configureAuthHandler(params, cwd);\n }\n );\n}\n","/**\n * Otter Integrity Verification\n * ============================\n * Protects the Pro Otter Raft from disk-based prompt injection / jailbreak attacks.\n *\n * TypeScript port of python/src/stackwright_pro/raft/integrity.py ā this lets\n * the MCP package verify otter files without a Python dependency.\n *\n * Certificate-pinned canonical checksums ā hardcoded in the MCP package.\n *\n * These are NOT read from disk. An attacker who modifies otter JSON files\n * in @stackwright-pro/otters cannot also modify these constants without\n * compromising the separately-published @stackwright-pro/mcp package.\n *\n * To update: node scripts/sync-mcp-checksums.cjs\n * (reads from packages/otters/src/checksums.json, writes this file)\n */\nimport { createHash, timingSafeEqual } from 'crypto';\nimport { readFileSync, readdirSync, lstatSync } from 'fs';\nimport { join, basename } from 'path';\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\n\n// ---------------------------------------------------------------------------\n// Certificate-pinned canonical checksums ā frozen Map, immutable by design.\n// DO NOT read these from disk ā that would defeat the entire purpose.\n// Object.freeze prevents property mutation at runtime; ReadonlyMap prevents\n// .set() / .delete() at compile time (belt-and-suspenders).\n// ---------------------------------------------------------------------------\n\nconst _checksums = new Map<string, string>([\n [\n 'stackwright-pro-api-otter.json',\n '9fbaed0ce6116b82d0289f24432037d04637c89b8e73062ed946e5d49b294734',\n ],\n [\n 'stackwright-pro-auth-otter.json',\n 'bf0e66e35d15ba818ba6ff1a007df34975565bacbb35cc0c80151fb1da13e573',\n ],\n [\n 'stackwright-pro-dashboard-otter.json',\n 'f5a83b74ad7c44edc6f39b45a568fa122d82aa4788f741ce14614da56d4e29a4',\n ],\n [\n 'stackwright-pro-data-otter.json',\n 'c406e1c775bcb1f2b038b40a92d9bd23172b40d774fc0fa50bad4c9714f53445',\n ],\n [\n 'stackwright-pro-designer-otter.json',\n 'af09ac8f06385bdbac63e2820daa2ff7d38b8ff1ff383c161f07e3fb9d9359c5',\n ],\n [\n 'stackwright-pro-foreman-otter.json',\n '247765094c110aa342a6d7312e49fc189089bdd2b013af98cfef43a0816ac7bf',\n ],\n [\n 'stackwright-pro-geo-otter.json',\n '6eb7ecf97254dbd79c09ad24348bf16001423cce9585c14bef81afd67b7b901b',\n ],\n [\n 'stackwright-pro-page-otter.json',\n '9a5672f0758c81539337d86955e2892cd412547b4f111c2aa098eed1e62d7626',\n ],\n [\n 'stackwright-pro-polish-otter.json',\n 'd31116995fdb417798af6056efd03bb1c71e0891371aba1774d283c03c9d77e8',\n ],\n [\n 'stackwright-pro-theme-otter.json',\n '08bb04009fdfb8743b10ac4d503cbaddaf8d7c804ba9b606aaed9cc516fd8e93',\n ],\n [\n 'stackwright-pro-workflow-otter.json',\n 'c90d6773b2287aa9a640c2715ca0e75f44c13e99fddcfb89ced36603f38930ce',\n ],\n [\n 'stackwright-services-otter.json',\n '2a99df3e50415d027c0bc2a57f509882928bb1ae516e61dda667641ce1652ac3',\n ],\n]);\nObject.freeze(_checksums);\nconst CANONICAL_CHECKSUMS: ReadonlyMap<string, string> = _checksums;\n\n// ---------------------------------------------------------------------------\n// Import-time format validation ā malformed constants are a packaging bug,\n// not a runtime surprise. Fail fast, fail loud.\n// ---------------------------------------------------------------------------\n\nconst SHA256_HEX_RE = /^[0-9a-f]{64}$/;\n\nfor (const [name, digest] of CANONICAL_CHECKSUMS) {\n if (!SHA256_HEX_RE.test(digest)) {\n throw new Error(\n `Malformed SHA-256 in CANONICAL_CHECKSUMS for \"${name}\": ` +\n `expected 64 hex chars, got ${digest.length}: \"${digest}\"`\n );\n }\n}\n\n// 1 MB ā generous headroom for agent definitions; anything larger is suspicious.\nconst MAX_OTTER_BYTES = 1 * 1024 * 1024;\n\n// ---------------------------------------------------------------------------\n// Core functions (exported for direct testing ā no MCP server needed)\n// ---------------------------------------------------------------------------\n\n/** Compute the hex-encoded SHA-256 digest of raw bytes. Pure, no I/O. */\nexport function computeSha256(data: Buffer): string {\n return createHash('sha256').update(data).digest('hex');\n}\n\n/** Constant-time comparison of two hex digest strings. */\nfunction safeEqual(a: string, b: string): boolean {\n if (a.length !== b.length) return false;\n return timingSafeEqual(Buffer.from(a, 'utf8'), Buffer.from(b, 'utf8'));\n}\n\n// ---------------------------------------------------------------------------\n// Single-file verification\n// ---------------------------------------------------------------------------\n\nexport interface VerifyOtterFileResult {\n verified: boolean;\n filename: string;\n error?: string;\n}\n\n/**\n * Read a single otter JSON file, check its size, compute its SHA-256,\n * and constant-time compare against the canonical checksum.\n *\n * Single read ā hash ā decode. No TOCTOU window.\n */\nexport function verifyOtterFile(filePath: string): VerifyOtterFileResult {\n const filename = basename(filePath);\n\n // Fast-fail on unknown filenames before any I/O\n const expected = CANONICAL_CHECKSUMS.get(filename);\n if (expected === undefined) {\n return { verified: false, filename, error: `Unknown otter file: not in canonical set` };\n }\n\n // Symlink guard ā refuse to follow symlinks (prevents symlink-based swaps)\n let stat: ReturnType<typeof lstatSync>;\n try {\n stat = lstatSync(filePath);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n return { verified: false, filename, error: `Cannot stat file: ${msg}` };\n }\n\n if (stat.isSymbolicLink()) {\n return { verified: false, filename, error: 'Refusing to verify symlink' };\n }\n\n // Stat-based size pre-check ā don't materialise oversized payloads\n const size = stat.size;\n\n if (size > MAX_OTTER_BYTES) {\n return {\n verified: false,\n filename,\n error: `File exceeds size limit (${MAX_OTTER_BYTES.toLocaleString()} bytes, got ${size.toLocaleString()})`,\n };\n }\n\n // Single read ā used for hashing and UTF-8 validation (zero TOCTOU window)\n let raw: Buffer;\n try {\n raw = readFileSync(filePath);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n return { verified: false, filename, error: `Cannot read file: ${msg}` };\n }\n\n // Belt-and-suspenders: re-check length after read in case of a race\n if (raw.length > MAX_OTTER_BYTES) {\n return {\n verified: false,\n filename,\n error: `File exceeds size limit after read (${MAX_OTTER_BYTES.toLocaleString()} bytes, got ${raw.length.toLocaleString()})`,\n };\n }\n\n // Hash the raw bytes\n const actual = computeSha256(raw);\n\n // Constant-time comparison prevents timing-oracle attacks\n if (!safeEqual(actual, expected)) {\n return {\n verified: false,\n filename,\n error: `SHA-256 mismatch: expected ${expected.substring(0, 8)}ā¦, got ${actual.substring(0, 8)}ā¦`,\n };\n }\n\n // UTF-8 validation ā binary injection guard\n try {\n const decoder = new TextDecoder('utf-8', { fatal: true });\n decoder.decode(raw);\n } catch {\n return {\n verified: false,\n filename,\n error: 'File is not valid UTF-8 ā may be corrupted or contain binary injection',\n };\n }\n\n return { verified: true, filename };\n}\n\n// ---------------------------------------------------------------------------\n// Directory-level verification\n// ---------------------------------------------------------------------------\n\nexport interface VerifyAllOttersResult {\n verified: string[];\n failed: Array<{ filename: string; error: string }>;\n unknown: string[];\n}\n\n/**\n * Scan a directory for `*-otter.json` files, verify each one against\n * canonical checksums. Returns lists of verified, failed, and unknown files.\n */\nexport function verifyAllOtters(otterDir: string): VerifyAllOttersResult {\n // ---------------------------------------------------------------------------\n // Path traversal guard ā reject any input containing \"..\" sequences before\n // any I/O. An attacker controlling this parameter could otherwise scan\n // directories outside the expected otter install locations.\n // ---------------------------------------------------------------------------\n if (/(?:^|[/\\\\])\\.\\.(?:[/\\\\]|$)/.test(otterDir) || otterDir.includes('..')) {\n return {\n verified: [],\n failed: [\n {\n filename: '<directory>',\n error: `Security: path traversal sequence detected in otter directory parameter`,\n },\n ],\n unknown: [],\n };\n }\n\n const verified: string[] = [];\n const failed: Array<{ filename: string; error: string }> = [];\n const unknown: string[] = [];\n\n let entries: string[];\n try {\n entries = readdirSync(otterDir);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n return {\n verified: [],\n failed: [{ filename: '<directory>', error: `Cannot read directory: ${msg}` }],\n unknown: [],\n };\n }\n\n const otterFiles = entries.filter((f) => f.endsWith('-otter.json'));\n\n for (const filename of otterFiles) {\n const filePath = join(otterDir, filename);\n\n // Skip symlinks at the directory-scan level too\n try {\n if (lstatSync(filePath).isSymbolicLink()) {\n failed.push({ filename, error: 'Skipped: symlink' });\n continue;\n }\n } catch {\n // verifyOtterFile will handle stat errors\n }\n\n const result = verifyOtterFile(filePath);\n\n if (result.verified) {\n verified.push(result.filename);\n } else if (result.error?.startsWith('Unknown otter file')) {\n unknown.push(result.filename);\n } else {\n failed.push({ filename: result.filename, error: result.error ?? 'Unknown error' });\n }\n }\n\n // Check for missing canonical files ā ones we expect but didn't find on disk\n for (const canonicalName of CANONICAL_CHECKSUMS.keys()) {\n if (!otterFiles.includes(canonicalName)) {\n failed.push({ filename: canonicalName, error: 'Missing from directory' });\n }\n }\n\n return { verified, failed, unknown };\n}\n\n// ---------------------------------------------------------------------------\n// Otter directory resolution\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_SEARCH_PATHS = ['node_modules/@stackwright-pro/otters/src/', 'packages/otters/src/'];\n\nfunction resolveOtterDir(): string | null {\n const cwd = process.cwd();\n for (const relative of DEFAULT_SEARCH_PATHS) {\n const candidate = join(cwd, relative);\n try {\n lstatSync(candidate);\n return candidate;\n } catch {\n // Not found, try next\n }\n }\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Audit stream ā SOC2 / FedRAMP / DoD ATO compliance\n// ---------------------------------------------------------------------------\n\n/**\n * Structured audit event parameters for an integrity failure.\n * Kept as a plain interface so callers can pass partial results without\n * constructing the full VerifyAllOttersResult.\n */\nexport interface IntegrityAuditEvent {\n otterDir: string;\n failed: Array<{ filename: string; error: string }>;\n unknown: string[];\n}\n\n/**\n * Emit a structured INTEGRITY_FAIL audit event to stderr.\n *\n * Writes a single line to process.stderr in the format:\n * INTEGRITY_FAIL {\"level\":\"AUDIT\",\"event\":\"INTEGRITY_FAIL\",...}\n *\n * The line prefix \"INTEGRITY_FAIL\" (without JSON) allows log shippers\n * (FluentBit, syslog, CloudWatch Logs, Splunk) to match and route the\n * event to a dedicated audit stream using a simple string filter, even\n * before attempting JSON parsing.\n *\n * Exported for unit testing. Do not call directly in production code ā\n * use registerIntegrityTools() which calls this automatically.\n */\nexport function emitIntegrityAuditEvent(params: IntegrityAuditEvent): void {\n const record = JSON.stringify({\n level: 'AUDIT',\n event: 'INTEGRITY_FAIL',\n timestamp: new Date().toISOString(),\n source: 'stackwright_pro_verify_otter_integrity',\n otterDir: params.otterDir,\n failedCount: params.failed.length,\n unknownCount: params.unknown.length,\n failures: params.failed,\n unknown: params.unknown,\n });\n process.stderr.write(`INTEGRITY_FAIL ${record}\\n`);\n}\n\n// ---------------------------------------------------------------------------\n// MCP tool registration\n// ---------------------------------------------------------------------------\n\nexport function registerIntegrityTools(server: McpServer): void {\n server.tool(\n 'stackwright_pro_verify_otter_integrity',\n 'Verify SHA-256 integrity of all Pro otter agent definitions. Call this at startup before discovering otters. Auto-discovers the otter directory from known paths. Returns verified/failed/unknown lists.',\n {},\n async () => {\n const resolved = resolveOtterDir();\n\n if (!resolved) {\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify({\n error: true,\n message:\n 'Could not locate otter directory. Searched: ' + DEFAULT_SEARCH_PATHS.join(', '),\n }),\n },\n ],\n isError: true,\n };\n }\n\n const result = verifyAllOtters(resolved);\n\n const allGood = result.failed.length === 0 && result.unknown.length === 0;\n\n // Emit to dedicated audit stream for SOC2/FedRAMP/DoD ATO compliance\n if (!allGood) {\n emitIntegrityAuditEvent({\n otterDir: resolved,\n failed: result.failed,\n unknown: result.unknown,\n });\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify({\n otterDir: resolved,\n totalCanonical: CANONICAL_CHECKSUMS.size,\n verifiedCount: result.verified.length,\n failedCount: result.failed.length,\n unknownCount: result.unknown.length,\n verified: result.verified,\n failed: result.failed,\n unknown: result.unknown,\n ...(allGood\n ? {}\n : {\n error:\n 'INTEGRITY CHECK FAILED: SHA-256 mismatch detected in otter agent definitions. Do not proceed ā otter files may have been tampered with.',\n }),\n }),\n },\n ],\n isError: !allGood,\n };\n }\n );\n}\n","/**\n * Domain Knowledge Tools ā \"Sinks Not Pipes\"\n *\n * Pulls domain-specific knowledge OUT of LLM prompts, INTO deterministic TypeScript.\n * - stackwright_pro_list_collections\n * - stackwright_pro_resolve_data_strategy\n * - stackwright_pro_validate_workflow\n */\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { readFileSync, existsSync } from 'fs';\nimport { join } from 'path';\nimport { jsonCoerce } from '../coerce.js';\n\n// ---------------------------------------------------------------------------\n// Tool 1: List Collections\n// ---------------------------------------------------------------------------\n\nexport interface ListCollectionsInput {\n _cwd?: string;\n}\n\nexport interface CollectionInfo {\n name: string;\n endpoint: string;\n type?: string;\n}\n\n/** Read collections from data-otter artifact (primary) or stackwright.yml (fallback). */\nexport function handleListCollections(input: ListCollectionsInput): {\n text: string;\n isError: boolean;\n} {\n const cwd = input._cwd ?? process.cwd();\n\n const sources: Array<{ path: string; source: string; parse: (raw: string) => CollectionInfo[] }> =\n [\n {\n path: join(cwd, '.stackwright', 'artifacts', 'data-config.json'),\n source: 'data-config.json',\n parse: (raw) => {\n const parsed = JSON.parse(raw);\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {\n // Not a valid artifact ā fall through to YAML fallback\n return [];\n }\n return extractCollectionsFromArtifact(parsed as Record<string, unknown>);\n },\n },\n {\n path: join(cwd, 'stackwright.yml'),\n source: 'stackwright.yml',\n parse: extractCollectionsFromYaml,\n },\n ];\n\n for (const { path, source, parse } of sources) {\n if (!existsSync(path)) continue;\n try {\n const collections = parse(readFileSync(path, 'utf8'));\n return {\n text: JSON.stringify({ collections, source, collectionCount: collections.length }),\n isError: false,\n };\n } catch {\n // Source exists but is unparseable ā try next\n }\n }\n\n return {\n text: JSON.stringify({\n collections: [],\n source: 'none',\n collectionCount: 0,\n hint: 'Run API Otter and Data Otter first',\n }),\n isError: false,\n };\n}\n\n/** Pull collections from the data-otter's JSON artifact. */\nfunction extractCollectionsFromArtifact(raw: Record<string, unknown>): CollectionInfo[] {\n const collections: CollectionInfo[] = [];\n const integrations = raw.integrations ?? raw.collections ?? [];\n if (!Array.isArray(integrations)) return collections;\n\n for (const item of integrations) {\n if (!item || typeof item !== 'object') continue;\n const obj = item as Record<string, unknown>;\n\n // Direct collection entry\n if (typeof obj.name === 'string' && typeof obj.endpoint === 'string') {\n collections.push(makeCollectionInfo(obj.name, obj.endpoint, obj.type));\n continue;\n }\n\n // Nested collections inside integration entry\n if (!Array.isArray(obj.collections)) continue;\n for (const col of obj.collections) {\n if (!col || typeof col !== 'object') continue;\n const c = col as Record<string, unknown>;\n if (typeof c.name === 'string' && typeof c.endpoint === 'string') {\n collections.push(makeCollectionInfo(c.name, c.endpoint, c.type ?? obj.type));\n }\n }\n }\n return collections;\n}\n\nfunction makeCollectionInfo(name: string, endpoint: string, type: unknown): CollectionInfo {\n return { name, endpoint, ...(typeof type === 'string' ? { type } : {}) };\n}\n\n/** Best-effort regex extraction from stackwright.yml integrations block. */\nfunction extractCollectionsFromYaml(yamlText: string): CollectionInfo[] {\n const collections: CollectionInfo[] = [];\n const lines = yamlText.split('\\n');\n\n let inIntegrations = false;\n let currentName: string | null = null;\n let currentEndpoint: string | null = null;\n let currentType: string | null = null;\n\n for (const line of lines) {\n if (line.length > 1000) continue; // Defense against ReDoS on pathological lines\n if (/^integrations:\\s*$/.test(line)) {\n inIntegrations = true;\n continue;\n }\n if (inIntegrations && /^[a-z]/.test(line) && !line.startsWith(' ')) {\n inIntegrations = false;\n }\n if (!inIntegrations) continue;\n\n const stripQuotes = (s: string) => s.trim().replace(/^['\"]|['\"]$/g, '');\n\n const typeMatch = line.match(/^\\s+type:\\s*(.+)$/);\n if (typeMatch?.[1]) currentType = stripQuotes(typeMatch[1]);\n\n const nameMatch = line.match(/^[\\s-]+name:\\s*(.+)$/);\n if (nameMatch?.[1]) {\n if (currentName && currentEndpoint) {\n collections.push(makeCollectionInfo(currentName, currentEndpoint, currentType));\n }\n currentName = stripQuotes(nameMatch[1]);\n currentEndpoint = null;\n }\n\n const endpointMatch = line.match(/^\\s+endpoint:\\s*(.+)$/);\n if (endpointMatch?.[1]) currentEndpoint = stripQuotes(endpointMatch[1]);\n }\n\n if (currentName && currentEndpoint) {\n collections.push(makeCollectionInfo(currentName, currentEndpoint, currentType));\n }\n return collections;\n}\n\n// ---------------------------------------------------------------------------\n// Tool 2: Resolve Data Strategy\n// ---------------------------------------------------------------------------\n\nexport interface DataStrategy {\n strategy: string;\n mechanism: string;\n mechanismPackage?: string;\n revalidateSeconds?: number;\n pulse: boolean;\n requiredPackages: Record<string, string>;\n handoffFlags: string[];\n description: string;\n}\n\nconst DATA_STRATEGIES: Record<string, DataStrategy> = {\n 'pulse-fast': {\n strategy: 'pulse-fast',\n mechanism: 'Client-side polling via @stackwright-pro/pulse',\n mechanismPackage: '@stackwright-pro/pulse',\n pulse: true,\n requiredPackages: { '@stackwright-pro/pulse': 'latest', '@tanstack/react-query': '^5.0.0' },\n handoffFlags: ['PULSE_MODE=true'],\n description:\n 'Real-time updates every few seconds. Uses client-side polling. Dashboard Otter should use *_pulse component variants.',\n },\n 'isr-fast': {\n strategy: 'isr-fast',\n mechanism: 'Next.js ISR',\n revalidateSeconds: 60,\n pulse: false,\n requiredPackages: {},\n handoffFlags: [],\n description:\n 'Near real-time with 60-second ISR revalidation. Good for dashboards that need minute-level freshness.',\n },\n 'isr-standard': {\n strategy: 'isr-standard',\n mechanism: 'Next.js ISR',\n revalidateSeconds: 3600,\n pulse: false,\n requiredPackages: {},\n handoffFlags: [],\n description: 'Standard hourly revalidation. Good for most API-backed pages.',\n },\n 'isr-slow': {\n strategy: 'isr-slow',\n mechanism: 'Next.js ISR',\n revalidateSeconds: 86400,\n pulse: false,\n requiredPackages: {},\n handoffFlags: [],\n description: 'Daily revalidation. Good for infrequently changing data.',\n },\n};\n\nexport interface ResolveDataStrategyInput {\n strategy: string;\n}\n\n/** Look up the data freshness strategy. Replaces the markdown table in the data-otter prompt. */\nexport function handleResolveDataStrategy(input: ResolveDataStrategyInput): {\n text: string;\n isError: boolean;\n} {\n const key = input.strategy.trim().toLowerCase();\n const match = DATA_STRATEGIES[key];\n\n if (!match) {\n const validKeys = Object.keys(DATA_STRATEGIES).join(', ');\n return {\n text: JSON.stringify({\n error: true,\n message: `Unknown strategy: \"${input.strategy}\". Valid strategies: ${validKeys}`,\n validStrategies: Object.keys(DATA_STRATEGIES),\n }),\n isError: true,\n };\n }\n\n // Hint: the exact tool call the otter should make next\n const configureIsrCall = match.pulse\n ? null\n : {\n tool: 'stackwright_pro_configure_isr_batch',\n args: {\n collections: [{ name: '$COLLECTION', revalidateSeconds: match.revalidateSeconds }],\n },\n };\n\n return {\n text: JSON.stringify({ ...match, configureIsrCall }),\n isError: false,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Tool 3: Validate Workflow\n// ---------------------------------------------------------------------------\n\nexport interface WorkflowValidationIssue {\n code: string;\n message: string;\n path?: string;\n}\n\nexport interface ValidateWorkflowInput {\n workflow?: Record<string, unknown>;\n _cwd?: string;\n}\n\n/** Shorthand for returning a validation failure. */\nfunction fail(errors: WorkflowValidationIssue[]): { text: string; isError: boolean } {\n return { text: JSON.stringify({ valid: false, errors, warnings: [] }), isError: true };\n}\n\n/**\n * Inline workflow validation (Approach B) ā no cross-package import.\n * CLAUDE.md invariant 1 forbids runtime imports from @stackwright-pro/workflow.\n */\nexport function handleValidateWorkflow(input: ValidateWorkflowInput): {\n text: string;\n isError: boolean;\n} {\n const cwd = input._cwd ?? process.cwd();\n let raw: Record<string, unknown>;\n\n // Resolve: explicit object > artifact file\n if (input.workflow && Object.keys(input.workflow).length > 0) {\n raw = input.workflow;\n } else {\n const artifactPath = join(cwd, '.stackwright', 'artifacts', 'workflow-config.json');\n if (!existsSync(artifactPath)) {\n return fail([\n {\n code: 'NO_WORKFLOW',\n message:\n 'No workflow provided and .stackwright/artifacts/workflow-config.json not found. Pass a workflow object or run the workflow otter first.',\n },\n ]);\n }\n try {\n raw = JSON.parse(readFileSync(artifactPath, 'utf8'));\n } catch (err) {\n return fail([{ code: 'INVALID_JSON', message: `Failed to parse workflow artifact: ${err}` }]);\n }\n }\n\n // Unwrap { workflow: { ... } } envelope if present\n const workflow = (\n raw.workflow && typeof raw.workflow === 'object' ? raw.workflow : raw\n ) as Record<string, unknown>;\n\n const errors: WorkflowValidationIssue[] = [];\n const warnings: WorkflowValidationIssue[] = [];\n\n // Rule 1: workflow.id\n if (typeof workflow.id !== 'string' || !workflow.id) {\n errors.push({ code: 'MISSING_ID', message: 'workflow.id is required', path: 'workflow.id' });\n } else if (!/^[a-z0-9-]+$/.test(workflow.id)) {\n errors.push({\n code: 'INVALID_ID',\n message: `workflow.id \"${workflow.id}\" must match ^[a-z0-9-]+$`,\n path: 'workflow.id',\n });\n }\n\n // Rule 2: workflow.label\n if (typeof workflow.label !== 'string' || !workflow.label) {\n errors.push({\n code: 'MISSING_LABEL',\n message: 'workflow.label is required',\n path: 'workflow.label',\n });\n }\n\n // Rule 3: steps array\n const steps = workflow.steps;\n if (!Array.isArray(steps)) {\n errors.push({\n code: 'MISSING_STEPS',\n message: 'workflow.steps must be an array',\n path: 'workflow.steps',\n });\n return { text: JSON.stringify({ valid: false, errors, warnings }), isError: false };\n }\n\n if (steps.length < 2) {\n errors.push({\n code: 'TOO_FEW_STEPS',\n message: 'A workflow must have at least 2 steps',\n path: 'workflow.steps',\n });\n }\n\n // Build step ID index\n const stepIds = new Set<string>();\n const duplicateIds: string[] = [];\n\n for (const step of steps) {\n if (!step || typeof step !== 'object') continue;\n const id = (step as Record<string, unknown>).id;\n if (typeof id !== 'string' || !id) {\n errors.push({\n code: 'MISSING_STEP_ID',\n message: 'Every step must have an id',\n path: 'workflow.steps',\n });\n continue;\n }\n if (!/^[a-z0-9_]+$/.test(id)) {\n errors.push({\n code: 'INVALID_STEP_ID',\n message: `Step ID \"${id}\" must match ^[a-z0-9_]+$`,\n path: `workflow.steps[${id}].id`,\n });\n }\n if (stepIds.has(id)) duplicateIds.push(id);\n stepIds.add(id);\n }\n\n if (duplicateIds.length > 0) {\n errors.push({\n code: 'DUPLICATE_STEP_IDS',\n message: `Duplicate step IDs: ${duplicateIds.join(', ')}`,\n path: 'workflow.steps',\n });\n }\n\n // Rule 4: initial_step references existing step\n const initialStep = workflow.initial_step;\n if (typeof initialStep !== 'string' || !initialStep) {\n errors.push({\n code: 'MISSING_INITIAL_STEP',\n message: 'workflow.initial_step is required',\n path: 'workflow.initial_step',\n });\n } else if (!stepIds.has(initialStep)) {\n errors.push({\n code: 'INVALID_INITIAL_STEP',\n message: `initial_step \"${initialStep}\" does not reference an existing step. Valid: ${[...stepIds].join(', ')}`,\n path: 'workflow.initial_step',\n });\n }\n\n // Rules 5+6: transition targets + service: warnings\n for (const step of steps) {\n if (!step || typeof step !== 'object') continue;\n const s = step as Record<string, unknown>;\n const stepId = String(s.id ?? '??');\n validateTransitionTargets(s, stepId, stepIds, errors);\n collectServiceWarnings(s, stepId, warnings);\n }\n\n // Workflow-level persistence service check\n if (typeof workflow.persistence === 'string' && workflow.persistence.startsWith('service:')) {\n warnings.push({\n code: 'WARN_SERVICE_REFERENCE',\n message:\n 'service: reference at \"workflow.persistence\" requires @stackwright-pro/services. Prism mock fallback will be used until services layer is configured.',\n path: 'workflow.persistence',\n });\n }\n\n // Rule 7: at least one terminal step\n const hasTerminal = steps.some((step: unknown) => {\n if (!step || typeof step !== 'object') return false;\n return (step as Record<string, unknown>).type === 'terminal';\n });\n if (!hasTerminal) {\n errors.push({\n code: 'NO_TERMINAL_STATE',\n message: 'Workflow must have at least one step with type: terminal',\n path: 'workflow.steps',\n });\n }\n\n return { text: JSON.stringify({ valid: errors.length === 0, errors, warnings }), isError: false };\n}\n\n/** Check all transition targets within a step reference real step IDs. */\nfunction validateTransitionTargets(\n step: Record<string, unknown>,\n stepId: string,\n stepIds: Set<string>,\n errors: WorkflowValidationIssue[]\n): void {\n const check = (target: unknown, path: string) => {\n if (typeof target === 'string' && !stepIds.has(target)) {\n errors.push({\n code: 'ORPHANED_TRANSITION',\n message: `Step \"${stepId}\" transitions to \"${target}\" which does not exist`,\n path,\n });\n }\n };\n\n // on_submit.transition\n const onSubmit = step.on_submit as Record<string, unknown> | undefined;\n if (onSubmit && typeof onSubmit === 'object') {\n check(onSubmit.transition, `workflow.steps[${stepId}].on_submit.transition`);\n }\n\n // actions[].transition\n if (Array.isArray(step.actions)) {\n for (const action of step.actions) {\n if (!action || typeof action !== 'object') continue;\n const a = action as Record<string, unknown>;\n check(a.transition, `workflow.steps[${stepId}].actions[${a.id ?? '??'}].transition`);\n }\n }\n\n // conditions[].then.transition\n if (Array.isArray(step.conditions)) {\n for (const cond of step.conditions) {\n if (!cond || typeof cond !== 'object') continue;\n const then = (cond as Record<string, unknown>).then as Record<string, unknown> | undefined;\n if (then && typeof then === 'object') {\n check(then.transition, `workflow.steps[${stepId}].conditions`);\n }\n }\n }\n\n // show_fields_from\n if (Array.isArray(step.show_fields_from)) {\n for (const ref of step.show_fields_from)\n check(ref, `workflow.steps[${stepId}].show_fields_from`);\n }\n\n // display.source_step / display.source_steps\n const display = step.display as Record<string, unknown> | undefined;\n if (display && typeof display === 'object') {\n check(display.source_step, `workflow.steps[${stepId}].display.source_step`);\n if (Array.isArray(display.source_steps)) {\n for (const ref of display.source_steps)\n check(ref, `workflow.steps[${stepId}].display.source_steps`);\n }\n }\n}\n\n/** Collect service: references as warnings (non-blocking). */\nfunction collectServiceWarnings(\n step: Record<string, unknown>,\n stepId: string,\n warnings: WorkflowValidationIssue[]\n): void {\n const isService = (val: unknown): val is string =>\n typeof val === 'string' && val.startsWith('service:');\n\n const warn = (path: string) => {\n warnings.push({\n code: 'WARN_SERVICE_REFERENCE',\n message: `service: reference at \"${path}\" requires @stackwright-pro/services. Prism mock fallback will be used until services layer is configured.`,\n path,\n });\n };\n\n const onSubmit = step.on_submit as Record<string, unknown> | undefined;\n if (onSubmit && typeof onSubmit === 'object' && isService(onSubmit.action))\n warn(`${stepId}.on_submit.action`);\n\n const onEnter = step.on_enter as Record<string, unknown> | undefined;\n if (onEnter && typeof onEnter === 'object' && isService(onEnter.action))\n warn(`${stepId}.on_enter.action`);\n\n if (Array.isArray(step.actions)) {\n for (const action of step.actions) {\n if (!action || typeof action !== 'object') continue;\n const a = action as Record<string, unknown>;\n if (isService(a.action)) warn(`${stepId}.actions.${a.id ?? '??'}.action`);\n }\n }\n\n if (Array.isArray(step.fields)) {\n for (const field of step.fields) {\n if (!field || typeof field !== 'object') continue;\n const f = field as Record<string, unknown>;\n if (isService(f.data_source)) warn(`${stepId}.fields.${f.name ?? '??'}.data_source`);\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// MCP Tool Registration\n// ---------------------------------------------------------------------------\n\nexport function registerDomainTools(server: McpServer): void {\n const res = (r: { text: string; isError: boolean }) => ({\n content: [{ type: 'text' as const, text: r.text }],\n isError: r.isError,\n });\n\n server.tool(\n 'stackwright_pro_list_collections',\n 'List API-backed collections available for page generation. ' +\n 'Reads from Data Otter artifact (.stackwright/artifacts/data-config.json) or stackwright.yml. ' +\n 'Call this before generating pages that bind to data.',\n {},\n async () => res(handleListCollections({}))\n );\n\n server.tool(\n 'stackwright_pro_resolve_data_strategy',\n \"Look up the data freshness strategy configuration from the user's answer. \" +\n 'Returns mechanism, revalidation seconds, required packages, and the exact MCP tool call to make. ' +\n 'Replaces the strategy table in the data-otter prompt.',\n {\n strategy: z\n .string()\n .describe(\n 'The data-1 answer value: \"pulse-fast\", \"isr-fast\", \"isr-standard\", or \"isr-slow\"'\n ),\n },\n async ({ strategy }) => res(handleResolveDataStrategy({ strategy }))\n );\n\n server.tool(\n 'stackwright_pro_validate_workflow',\n 'Validate a workflow definition against the Stackwright workflow schema. ' +\n 'Checks step ID uniqueness, transition targets, terminal state existence, and service references. ' +\n 'Call this after the workflow otter produces output.',\n {\n workflow: jsonCoerce(z.record(z.string(), z.unknown()).optional()).describe(\n 'Parsed workflow object. If omitted, reads from .stackwright/artifacts/workflow-config.json'\n ),\n },\n async ({ workflow }) => res(handleValidateWorkflow(workflow ? { workflow } : {}))\n );\n}\n","/**\n * Type Schemas Tool ā \"Sinks Not Pipes\"\n *\n * Exposes a human-readable summary of available @stackwright-pro/types schemas.\n * The foreman uses this for schema-based routing: \"which otter owns this domain?\"\n * instead of hardcoded capability descriptions in the prompt.\n */\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\n\n/**\n * Schema summary returned by the tool and written to .stackwright/type-schemas.json\n */\nexport interface TypeSchemaSummary {\n version: '1.0';\n generatedAt: string;\n domains: {\n workflow: {\n description: string;\n schemas: string[];\n otter: string;\n artifactKey: string;\n };\n auth: {\n description: string;\n schemas: string[];\n otter: string;\n artifactKey: string;\n };\n openapi: {\n description: string;\n interfaces: string[];\n otter: string;\n artifactKey: string;\n };\n pulse: {\n description: string;\n interfaces: string[];\n note: string;\n };\n enterprise: {\n description: string;\n interfaces: string[];\n note: string;\n };\n };\n}\n\nexport function buildTypeSchemaSummary(): TypeSchemaSummary {\n return {\n version: '1.0',\n generatedAt: new Date().toISOString(),\n domains: {\n workflow: {\n description: 'Workflow DSL ā step definitions, auth blocks, field types, conditions',\n schemas: [\n 'WorkflowFileSchema',\n 'WorkflowDefinitionSchema',\n 'WorkflowStepSchema',\n 'WorkflowStepTypeSchema',\n 'WorkflowFieldSchema',\n 'WorkflowActionSchema',\n 'WorkflowAuthSchema',\n 'WorkflowThemeSchema',\n 'TransitionConditionSchema',\n 'PersistenceSchema',\n ],\n otter: 'stackwright-pro-workflow-otter',\n artifactKey: 'workflowConfig',\n },\n auth: {\n description: 'Authentication providers ā PKI/CAC, OIDC, RBAC configuration',\n schemas: [\n 'authConfigSchema',\n 'pkiConfigSchema',\n 'oidcConfigSchema',\n 'rbacConfigSchema',\n 'componentAuthSchema',\n 'authUserSchema',\n 'authSessionSchema',\n ],\n otter: 'stackwright-pro-auth-otter',\n artifactKey: 'authConfig',\n },\n openapi: {\n description: 'OpenAPI spec integration ā collection config, endpoint filters, actions',\n interfaces: [\n 'OpenAPIConfig',\n 'ActionConfig',\n 'EndpointFilter',\n 'ApprovedSpec',\n 'PrebuildSecurityConfig',\n 'SiteConfig',\n 'ValidationResult',\n ],\n otter: 'stackwright-pro-api-otter',\n artifactKey: 'apiConfig',\n },\n pulse: {\n description: 'Real-time data polling ā source-agnostic polling options and states',\n interfaces: ['PulseOptions', 'PulseMeta', 'PulseState'],\n note: 'React-bound types (PulseProps, PulseIndicatorProps) remain in @stackwright-pro/pulse',\n },\n enterprise: {\n description: 'Enterprise collection access ā multi-tenant provider extension',\n interfaces: [\n 'EnterpriseCollectionProvider',\n 'CollectionProvider',\n 'CollectionEntry',\n 'CollectionListOptions',\n 'CollectionListResult',\n 'TenantFilter',\n 'Collection',\n ],\n note: 'CollectionProvider, CollectionEntry, CollectionListOptions, and CollectionListResult are re-exported from @stackwright/types (^1.5.0). EnterpriseCollectionProvider, TenantFilter, and Collection are Pro-only extensions.',\n },\n },\n };\n}\n\nexport function registerTypeSchemasTool(server: McpServer): void {\n server.tool(\n 'stackwright_pro_get_type_schemas',\n 'Returns a structured summary of all canonical @stackwright-pro/types schemas, organized by domain. Use this to determine which otter owns a given schema and what artifact key to expect.',\n {\n format: z\n .enum(['full', 'domains-only'])\n .optional()\n .default('full')\n .describe('full = complete summary with all fields; domains-only = just domain names'),\n },\n async ({ format }) => {\n const summary = buildTypeSchemaSummary();\n const output = format === 'domains-only' ? Object.keys(summary.domains) : summary;\n return {\n content: [{ type: 'text', text: JSON.stringify(output, null, 2) }],\n };\n }\n );\n}\n","{\n \"dependencies\": {\n \"@stackwright-pro/types\": \"workspace:*\",\n \"@modelcontextprotocol/sdk\": \"^1.10.0\",\n \"@stackwright-pro/cli-data-explorer\": \"workspace:*\",\n \"zod\": \"^4.4.3\"\n },\n \"devDependencies\": {\n \"@types/node\": \"catalog:\",\n \"tsup\": \"catalog:\",\n \"typescript\": \"catalog:\",\n \"vitest\": \"catalog:\"\n },\n \"scripts\": {\n \"prepublishOnly\": \"node scripts/verify-integrity-sync.js\",\n \"build\": \"tsup\",\n \"dev\": \"tsup --watch\",\n \"start\": \"node dist/server.js\",\n \"test\": \"vitest run\",\n \"test:coverage\": \"vitest run --coverage\"\n },\n \"name\": \"@stackwright-pro/mcp\",\n \"version\": \"0.2.0-alpha.58\",\n \"description\": \"MCP tools for Stackwright Pro - Data Explorer, Security, ISR, and Dashboard generation\",\n \"license\": \"SEE LICENSE IN LICENSE\",\n \"main\": \"./dist/server.js\",\n \"bin\": {\n \"stackwright-pro-mcp\": \"./dist/server.js\"\n },\n \"module\": \"./dist/server.mjs\",\n \"types\": \"./dist/server.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/server.d.ts\",\n \"import\": \"./dist/server.mjs\",\n \"require\": \"./dist/server.js\"\n },\n \"./integrity\": {\n \"types\": \"./dist/integrity.d.ts\",\n \"import\": \"./dist/integrity.mjs\",\n \"require\": \"./dist/integrity.js\"\n },\n \"./type-schemas\": {\n \"types\": \"./dist/tools/type-schemas.d.ts\",\n \"import\": \"./dist/tools/type-schemas.mjs\",\n \"require\": \"./dist/tools/type-schemas.js\"\n }\n },\n \"files\": [\n \"dist\"\n ],\n \"publishConfig\": {\n \"access\": \"public\"\n }\n}\n"],"mappings":";AAAA,SAAS,iBAAiB;AAC1B,SAAS,4BAA4B;;;ACArC,SAAS,KAAAA,UAAS;AAClB,SAAS,cAAc,sBAAsB;;;ACkB7C,SAAS,SAAS;AAQX,SAAS,WAAmC,QAAW;AAC5D,SAAO,EAAE,WAAW,CAAC,MAAM;AACzB,QAAI,OAAO,MAAM,UAAU;AACzB,UAAI;AACF,eAAO,KAAK,MAAM,CAAC;AAAA,MACrB,QAAQ;AACN,eAAO;AAAA,MACT;AAAA,IACF;AACA,WAAO;AAAA,EACT,GAAG,MAAM;AACX;AAOO,SAAS,WAAmC,QAAW;AAC5D,SAAO,EAAE,WAAW,CAAC,MAAO,MAAM,SAAS,OAAO,MAAM,UAAU,QAAQ,GAAI,MAAM;AACtF;AAMO,SAAS,UAAkC,QAAW;AAC3D,SAAO,EAAE,WAAW,CAAC,MAAM;AACzB,QAAI,OAAO,MAAM,YAAY,EAAE,KAAK,MAAM,IAAI;AAC5C,YAAM,IAAI,OAAO,CAAC;AAClB,UAAI,CAAC,OAAO,MAAM,CAAC,EAAG,QAAO;AAAA,IAC/B;AACA,WAAO;AAAA,EACT,GAAG,MAAM;AACX;;;ADrDO,SAAS,0BAA0BC,SAAyB;AAEjE,EAAAA,QAAO;AAAA,IACL;AAAA,IACA;AAAA,IAIA;AAAA,MACE,UAAUC,GAAE,OAAO,EAAE,SAAS,EAAE,SAAS,0CAA0C;AAAA,MACnF,aAAaA,GACV,OAAO,EACP,SAAS,EACT,SAAS,mDAAmD;AAAA,IACjE;AAAA,IACA,OAAO,EAAE,UAAU,YAAY,MAAM;AACnC,YAAM,SAAS,aAAa;AAAA,QAC1B,GAAI,aAAa,UAAa,EAAE,SAAS;AAAA,QACzC,GAAI,gBAAgB,UAAa,EAAE,YAAY;AAAA,MACjD,CAAC;AAED,UAAI,CAAC,OAAO,SAAS;AACnB,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM,gCAAgC,OAAO,UAAU,CAAC,GAAG,KAAK,IAAI,CAAC;AAAA,YACvE;AAAA,UACF;AAAA,UACA,SAAS;AAAA,QACX;AAAA,MACF;AAEA,YAAM,QAAkB,CAAC,mBAAY,OAAO,SAAS,MAAM;AAAA,CAAkB;AAE7E,iBAAW,UAAU,OAAO,UAAU;AACpC,cAAM,KAAK,aAAM,OAAO,IAAI,KAAK,OAAO,IAAI,GAAG;AAC/C,cAAM,KAAK,gBAAgB,OAAO,QAAQ,EAAE;AAC5C,cAAM,KAAK,cAAc,OAAO,UAAU,EAAE;AAC5C,YAAI,OAAO,OAAO,SAAS,GAAG;AAC5B,gBAAM,aAAa,OAAO,OACvB,MAAM,GAAG,CAAC,EACV,IAAI,CAAC,MAAM,GAAG,EAAE,IAAI,IAAI,EAAE,IAAI,EAAE,EAChC,KAAK,IAAI;AACZ,gBAAM,KAAK,aAAa,UAAU,GAAG,OAAO,OAAO,SAAS,IAAI,QAAQ,EAAE,EAAE;AAAA,QAC9E;AACA,cAAM,KAAK,EAAE;AAAA,MACf;AAEA,YAAM;AAAA,QACJ;AAAA;AAAA,MACF;AAEA,aAAO;AAAA,QACL,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM,MAAM,KAAK,IAAI;AAAA,UACvB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,EAAAD,QAAO;AAAA,IACL;AAAA,IACA;AAAA,IAIA;AAAA,MACE,kBAAkB,WAAWC,GAAE,MAAMA,GAAE,OAAO,CAAC,CAAC,EAAE;AAAA,QAChD;AAAA,MACF;AAAA,MACA,iBAAiB,WAAWA,GAAE,MAAMA,GAAE,OAAO,CAAC,EAAE,SAAS,CAAC,EAAE;AAAA,QAC1D;AAAA,MACF;AAAA,MAEA,aAAaA,GAAE,OAAO,EAAE,SAAS,EAAE,SAAS,wBAAwB;AAAA,IACtE;AAAA,IACA,OAAO,EAAE,kBAAkB,iBAAiB,YAAY,MAAM;AAC5D,YAAM,SAAS,eAAe;AAAA,QAC5B;AAAA,QACA,GAAI,oBAAoB,UAAa,EAAE,gBAAgB;AAAA,QACvD,aAAa,eAAe,QAAQ,IAAI;AAAA,MAC1C,CAAC;AAED,UAAI,CAAC,OAAO,SAAS;AACnB,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM,4BAA4B,OAAO,UAAU,KAAK,IAAI,CAAC;AAAA,YAC/D;AAAA,UACF;AAAA,UACA,SAAS;AAAA,QACX;AAAA,MACF;AAEA,YAAM,QAAkB,CAAC,wCAAiC;AAC1D,YAAM,KAAK,SAAS;AACpB,YAAM,KAAK,eAAe;AAC1B,YAAM,KAAK,mBAAmB;AAC9B,YAAM,KAAK,gBAAgB;AAE3B,UAAI,OAAO,OAAO,WAAW,OAAO,OAAO,QAAQ,SAAS,GAAG;AAC7D,cAAM,KAAK,gBAAgB;AAC3B,mBAAWC,SAAQ,OAAO,OAAO,SAAS;AACxC,gBAAM,KAAK,aAAaA,KAAI,EAAE;AAAA,QAChC;AAAA,MACF;AAEA,UAAI,OAAO,OAAO,WAAW,OAAO,OAAO,QAAQ,SAAS,GAAG;AAC7D,cAAM,KAAK,gBAAgB;AAC3B,mBAAW,WAAW,OAAO,OAAO,SAAS;AAC3C,gBAAM,KAAK,aAAa,OAAO,EAAE;AAAA,QACnC;AAAA,MACF;AAEA,YAAM,KAAK,KAAK;AAEhB,UAAI,OAAO,YAAY,OAAO,SAAS,SAAS,GAAG;AACjD,cAAM,KAAK,0BAAgB;AAC3B,mBAAW,WAAW,OAAO,UAAU;AACrC,gBAAM,KAAK,KAAK,OAAO,EAAE;AAAA,QAC3B;AAAA,MACF;AAEA,aAAO;AAAA,QACL,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM,MAAM,KAAK,IAAI;AAAA,UACvB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;AEnJA,SAAS,KAAAC,UAAS;AAClB,SAAS,kBAAkB;AAC3B,OAAO,QAAQ;AACf,OAAO,UAAU;AAMV,SAAS,sBAAsBC,SAAyB;AAE7D,EAAAA,QAAO;AAAA,IACL;AAAA,IACA;AAAA,IAIA;AAAA,MACE,UAAUD,GAAE,OAAO,EAAE,SAAS,kDAAkD;AAAA,MAChF,YAAYA,GACT,OAAO,EACP,SAAS,EACT,SAAS,uDAAuD;AAAA,IACrE;AAAA,IACA,OAAO,EAAE,UAAU,WAAW,MAAM;AAElC,UAAI,kBAAkB;AACtB,YAAM,YAAkE,CAAC;AAEzE,YAAM,aAAa,cAAc,KAAK,KAAK,QAAQ,IAAI,GAAG,iBAAiB;AAE3E,UAAI,GAAG,WAAW,UAAU,GAAG;AAC7B,YAAI;AACF,gBAAM,UAAU,GAAG,aAAa,YAAY,MAAM;AAGlD,gBAAM,gBAAgB,QAAQ;AAAA,YAC5B;AAAA,UACF;AACA,cAAI,iBAAiB,cAAc,CAAC,MAAM,QAAQ;AAChD,8BAAkB;AAElB,kBAAM,cAAc,QAAQ;AAAA,cAC1B;AAAA,YACF;AACA,uBAAW,SAAS,aAAa;AAC/B,wBAAU,KAAK;AAAA,gBACb,MAAM,MAAM,CAAC,EAAG,KAAK;AAAA,gBACrB,KAAK,MAAM,CAAC,EAAG,KAAK;AAAA,gBACpB,QAAQ,MAAM,CAAC,EAAG,KAAK;AAAA,cACzB,CAAC;AAAA,YACH;AAAA,UACF;AAAA,QACF,QAAQ;AAAA,QAER;AAAA,MACF;AAGA,UAAI,CAAC,iBAAiB;AACpB,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,eAAqN,QAAQ;AAAA;AAAA,YACrO;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAGA,YAAM,eAAe,UAAU,KAAK,CAAC,MAAM,EAAE,QAAQ,QAAQ;AAE7D,UAAI,CAAC,cAAc;AACjB,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MACE;AAAA;AAAA;AAAA;AAAA,OAAiE,QAAQ;AAAA;AAAA;AAAA,YAE7E;AAAA,UACF;AAAA,UACA,SAAS;AAAA,QACX;AAAA,MACF;AAGA,UAAI,CAAC,SAAS,WAAW,SAAS,KAAK,CAAC,SAAS,WAAW,UAAU,GAAG;AACvE,YAAI,GAAG,WAAW,QAAQ,GAAG;AAC3B,gBAAM,cAAc,GAAG,aAAa,UAAU,MAAM;AACpD,gBAAM,SAAS,WAAW,QAAQ,EAAE,OAAO,WAAW,EAAE,OAAO,KAAK;AAEpE,cAAI,WAAW,aAAa,QAAQ;AAClC,mBAAO;AAAA,cACL,SAAS;AAAA,gBACP;AAAA,kBACE,MAAM;AAAA,kBACN,MAAM;AAAA;AAAA;AAAA;AAAA,YAAwE,aAAa,OAAO,UAAU,GAAG,EAAE,CAAC;AAAA,YAAkB,OAAO,UAAU,GAAG,EAAE,CAAC;AAAA;AAAA;AAAA,gBAC7J;AAAA,cACF;AAAA,cACA,SAAS;AAAA,YACX;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,aAAO;AAAA,QACL,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM;AAAA;AAAA,QAA6B,aAAa,IAAI;AAAA,OAAU,QAAQ;AAAA,iBAAoB,UAAU,MAAM;AAAA,UAC5G;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,EAAAC,QAAO;AAAA,IACL;AAAA,IACA;AAAA,IAGA;AAAA,MACE,MAAMD,GAAE,OAAO,EAAE,SAAS,kCAAkC;AAAA,MAC5D,KAAKA,GAAE,OAAO,EAAE,SAAS,sCAAsC;AAAA,MAC/D,YAAYA,GAAE,OAAO,EAAE,SAAS,EAAE,SAAS,yBAAyB;AAAA,IACtE;AAAA,IACA,OAAO,EAAE,MAAM,KAAK,WAAW,MAAM;AACnC,YAAM,aAAa,cAAc,KAAK,KAAK,QAAQ,IAAI,GAAG,iBAAiB;AAG3E,UAAI,SAAS;AAEb,UAAI;AACF,YAAI,IAAI,WAAW,SAAS,KAAK,IAAI,WAAW,UAAU,GAAG;AAAA,QAE7D,WAAW,GAAG,WAAW,GAAG,GAAG;AAC7B,gBAAM,cAAc,GAAG,aAAa,KAAK,MAAM;AAC/C,mBAAS,WAAW,QAAQ,EAAE,OAAO,WAAW,EAAE,OAAO,KAAK;AAAA,QAChE,OAAO;AACL,iBAAO;AAAA,YACL,SAAS;AAAA,cACP;AAAA,gBACE,MAAM;AAAA,gBACN,MAAM,+BAA0B,GAAG;AAAA,cACrC;AAAA,YACF;AAAA,YACA,SAAS;AAAA,UACX;AAAA,QACF;AAAA,MACF,SAAS,GAAG;AACV,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM,+BAA0B,CAAC;AAAA,YACnC;AAAA,UACF;AAAA,UACA,SAAS;AAAA,QACX;AAAA,MACF;AAEA,YAAM,cAAc,aAAa,IAAI;AAAA,WAChC,GAAG;AAAA,cACA,MAAM;AAEd,aAAO;AAAA,QACL,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM;AAAA;AAAA,EAAwE,WAAW;AAAA;AAAA,oBAAyB,MAAM;AAAA,UAC1H;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,EAAAC,QAAO;AAAA,IACL;AAAA,IACA;AAAA,IAGA;AAAA,MACE,YAAYD,GAAE,OAAO,EAAE,SAAS,EAAE,SAAS,yBAAyB;AAAA,IACtE;AAAA,IACA,OAAO,EAAE,WAAW,MAAM;AACxB,YAAM,aAAa,cAAc,KAAK,KAAK,QAAQ,IAAI,GAAG,iBAAiB;AAE3E,UAAI,CAAC,GAAG,WAAW,UAAU,GAAG;AAC9B,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM;AAAA,YACR;AAAA,UACF;AAAA,UACA,SAAS;AAAA,QACX;AAAA,MACF;AAEA,YAAM,UAAU,GAAG,aAAa,YAAY,MAAM;AAGlD,YAAM,kBACJ,QAAQ,SAAS,WAAW,KAC5B,QAAQ,SAAS,WAAW,KAC5B,QAAQ,SAAS,eAAe;AAElC,UAAI,CAAC,iBAAiB;AACpB,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM;AAAA,YACR;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAGA,YAAM,QAA8D,CAAC;AACrE,YAAM,cAAc,QAAQ;AAAA,QAC1B;AAAA,MACF;AAEA,iBAAW,SAAS,aAAa;AAC/B,cAAM,KAAK;AAAA,UACT,MAAM,MAAM,CAAC,EAAG,KAAK;AAAA,UACrB,KAAK,MAAM,CAAC,EAAG,KAAK;AAAA,UACpB,QAAQ,MAAM,CAAC,EAAG,KAAK,EAAE,UAAU,GAAG,EAAE,IAAI;AAAA,QAC9C,CAAC;AAAA,MACH;AAEA,UAAI,MAAM,WAAW,GAAG;AACtB,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM;AAAA,YACR;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,YAAM,QAAQ,CAAC,6BAAsB,MAAM,MAAM;AAAA,CAAM;AACvD,iBAAW,QAAQ,OAAO;AACxB,cAAM,KAAK,aAAM,KAAK,IAAI,EAAE;AAC5B,cAAM,KAAK,WAAW,KAAK,GAAG,EAAE;AAChC,cAAM,KAAK,YAAY,KAAK,MAAM,EAAE;AACpC,cAAM,KAAK,EAAE;AAAA,MACf;AAEA,aAAO;AAAA,QACL,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM,MAAM,KAAK,IAAI;AAAA,UACvB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;ACzQA,SAAS,KAAAE,UAAS;AASX,SAAS,iBAAiBC,SAAyB;AAExD,EAAAA,QAAO;AAAA,IACL;AAAA,IACA;AAAA,IAIA;AAAA,MACE,YAAYC,GAAE,OAAO,EAAE,SAAS,iDAAiD;AAAA,MACjF,mBAAmB,UAAUA,GAAE,OAAO,EAAE,SAAS,CAAC,EAAE;AAAA,QAClD;AAAA,MACF;AAAA,MACA,UAAUA,GACP,KAAK,CAAC,YAAY,QAAQ,OAAO,CAAC,EAClC,SAAS,EACT,SAAS,iCAAiC;AAAA,MAC7C,YAAYA,GAAE,OAAO,EAAE,SAAS,EAAE,SAAS,yBAAyB;AAAA,IACtE;AAAA,IACA,OAAO,EAAE,YAAY,oBAAoB,IAAI,WAAW,YAAY,WAAW,MAAM;AACnF,YAAM,aAAa;AAEnB,YAAM,cAAc;AAAA;AAAA,YAEd,UAAU;AAAA;AAAA;AAAA,oBAGF,UAAU;AAAA,kBACZ,QAAQ;AAEpB,UAAI;AACJ,UAAI,aAAa,IAAI;AACnB,sBAAc,8CAAyC,aAAa;AAAA,MACtE,WAAW,aAAa,KAAK;AAC3B,sBAAc,6CAAsC,aAAa,IAAI,QAAQ,CAAC,IAAI;AAAA,MACpF,WAAW,aAAa,MAAM;AAC5B,sBAAc,8CAAuC,aAAa,IAAI,QAAQ,CAAC,IAAI;AAAA,MACrF,OAAO;AACL,sBACE,oDAAwC,aAAa,MAAM,QAAQ,CAAC,IAAI;AAAA,MAC5E;AAEA,aAAO;AAAA,QACL,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM,uCAA6B,UAAU;AAAA;AAAA,EAAS,WAAW;AAAA;AAAA,YAAiB,aAAa,aAAa,qCAAgC,aAAa,SAAS,iCAA0B,0BAAqB;AAAA;AAAA;AAAA,EAAmB,WAAW;AAAA;AAAA,UACjP;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,EAAAD,QAAO;AAAA,IACL;AAAA,IACA;AAAA,IAGA;AAAA,MACE,aAAa;AAAA,QACXC,GAAE;AAAA,UACAA,GAAE,OAAO;AAAA,YACP,MAAMA,GAAE,OAAO,EAAE,SAAS,iBAAiB;AAAA,YAC3C,mBAAmB,UAAUA,GAAE,OAAO,EAAE,SAAS,CAAC,EAAE,SAAS,uBAAuB;AAAA,UACtF,CAAC;AAAA,QACH;AAAA,MACF,EAAE,SAAS,oCAAoC;AAAA,MAC/C,iBAAiBA,GACd,KAAK,CAAC,YAAY,QAAQ,OAAO,CAAC,EAClC,SAAS,EACT,SAAS,2BAA2B;AAAA,MACvC,YAAYA,GAAE,OAAO,EAAE,SAAS,EAAE,SAAS,yBAAyB;AAAA,IACtE;AAAA,IACA,OAAO,EAAE,aAAa,kBAAkB,YAAY,WAAW,MAAM;AACnE,YAAM,QAAQ,CAAC;AAAA,CAA+B;AAE9C,iBAAW,OAAO,aAAa;AAC7B,cAAM,MAAM,IAAI,qBAAqB;AACrC,YAAI,YAAY;AAChB,YAAI,MAAM,GAAI,aAAY;AAAA,iBACjB,MAAM,IAAK,aAAY;AAAA,iBACvB,OAAO,KAAM,aAAY;AAElC,cAAM,KAAK,GAAG,SAAS,IAAI,IAAI,IAAI,gBAAgB,GAAG,GAAG;AAAA,MAC3D;AAEA,YAAM,KAAK;AAAA,YAAe,eAAe,EAAE;AAE3C,aAAO;AAAA,QACL,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM,MAAM,KAAK,IAAI;AAAA,UACvB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;AC5GA,SAAS,KAAAC,UAAS;AAClB,SAAS,gBAAAC,qBAAoB;AAOtB,SAAS,uBAAuBC,SAAyB;AAE9D,EAAAA,QAAO;AAAA,IACL;AAAA,IACA;AAAA,IAGA;AAAA,MACE,UAAU,WAAWC,GAAE,MAAMA,GAAE,OAAO,CAAC,CAAC,EAAE,SAAS,sCAAsC;AAAA,MACzF,QAAQA,GAAE,KAAK,CAAC,QAAQ,SAAS,OAAO,CAAC,EAAE,SAAS,EAAE,SAAS,wBAAwB;AAAA,MACvF,WAAWA,GAAE,OAAO,EAAE,SAAS,EAAE,SAAS,YAAY;AAAA,MACtD,UAAUA,GAAE,OAAO,EAAE,SAAS,EAAE,SAAS,yCAAyC;AAAA,IACpF;AAAA,IACA,OAAO,EAAE,UAAU,SAAS,SAAS,WAAW,SAAS,MAAM;AAE7D,UAAI,gBAAuB,CAAC;AAC5B,UAAI,UAAU;AACZ,cAAM,SAASC,cAAa,EAAE,SAAS,CAAC;AACxC,YAAI,OAAO,SAAS;AAClB,0BAAgB,OAAO,SAAS,OAAO,CAAC,MAAM,SAAS,SAAS,EAAE,IAAI,CAAC;AAAA,QACzE;AAAA,MACF;AAEA,YAAM,QACJ,aAAa,SAAS,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,IAAI,EAAE,MAAM,CAAC,CAAC,EAAE,KAAK,KAAK;AAErF,YAAM,YAAY;AAAA,QAChB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,eAAe,KAAK;AAAA,QACpB;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAGA,UAAI,WAAW,UAAU,WAAW,SAAS;AAC3C,mBAAW,QAAQ,UAAU;AAC3B,oBAAU,KAAK,kBAAkB;AACjC,oBAAU,KAAK,kBAAkB;AACjC,oBAAU,KAAK,cAAc;AAC7B,oBAAU,KAAK,6BAA6B;AAC5C,oBAAU,KAAK,0BAA0B;AACzC,oBAAU,KAAK,uBAAuB,IAAI,WAAW;AACrD,oBAAU,KAAK,0BAA0B;AACzC,oBAAU,KAAK,6BAA6B;AAC5C,oBAAU,KAAK,2BAA2B;AAC1C,oBAAU,KAAK,oBAAoB;AACnC,oBAAU,KAAK,6BAA6B;AAC5C,oBAAU,KAAK,EAAE;AAAA,QACnB;AAAA,MACF;AAGA,gBAAU,KAAK,6BAA6B;AAC5C,gBAAU,KAAK,gBAAgB,SAAS,CAAC,CAAC,UAAU;AACpD,gBAAU,KAAK,qBAAqB,SAAS,CAAC,CAAC,EAAE;AACjD,gBAAU,KAAK,yBAAyB;AACxC,gBAAU,KAAK,wBAAwB;AACvC,YAAM,cAAc,CAAC,MAAM,QAAQ,UAAU,YAAY;AACzD,gBAAU;AAAA,QACR,kBACE,cAAc,CAAC,GAAG,QACd,MAAM,GAAG,CAAC,EACX,IAAI,CAAC,MAAW,EAAE,IAAI,EACtB,KAAK,IAAI,KAAK,YAAY,KAAK,IAAI,CACxC;AAAA,MACF;AACA,gBAAU,KAAK,EAAE;AAEjB,UAAI,WAAW,SAAS;AACtB,kBAAU,KAAK,wBAAwB;AACvC,kBAAU,KAAK,gBAAgB,SAAS,CAAC,CAAC,QAAQ;AAClD,kBAAU,KAAK,qBAAqB,SAAS,CAAC,CAAC,EAAE;AACjD,kBAAU,KAAK,gBAAgB;AAC/B,kBAAU,KAAK,qBAAqB;AACpC,kBAAU,KAAK,sBAAsB;AACrC,kBAAU,KAAK,0BAA0B;AACzC,kBAAU,KAAK,uBAAuB;AACtC,kBAAU,KAAK,wBAAwB;AACvC,kBAAU,KAAK,0BAA0B;AACzC,kBAAU,KAAK,yBAAyB;AACxC,kBAAU,KAAK,0BAA0B;AACzC,kBAAU,KAAK,uBAAuB;AAAA,MACxC;AAEA,YAAM,OAAO,UAAU,KAAK,IAAI;AAEhC,aAAO;AAAA,QACL,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM,sCAA+B,SAAS,KAAK,IAAI,CAAC;AAAA;AAAA,UAAe,MAAM;AAAA;AAAA;AAAA,EAAmB,IAAI;AAAA;AAAA;AAAA;AAAA,UACtG;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,EAAAF,QAAO;AAAA,IACL;AAAA,IACA;AAAA,IAGA;AAAA,MACE,QAAQC,GAAE,OAAO,EAAE,SAAS,iCAAiC;AAAA,MAC7D,WAAWA,GAAE,OAAO,EAAE,SAAS,EAAE,SAAS,0CAA0C;AAAA,MACpF,UAAUA,GAAE,OAAO,EAAE,SAAS,EAAE,SAAS,wCAAwC;AAAA,IACnF;AAAA,IACA,OAAO,EAAE,QAAQ,YAAY,MAAM,SAAS,MAAM;AAEhD,UAAI,SAAgB,CAAC;AACrB,UAAI,UAAU;AACZ,cAAM,SAASC,cAAa,EAAE,SAAS,CAAC;AACxC,YAAI,OAAO,SAAS;AAClB,gBAAM,MAAM,OAAO,SAAS,KAAK,CAAC,MAAM,EAAE,SAAS,MAAM;AACzD,cAAI,KAAK;AACP,qBAAS,IAAI;AAAA,UACf;AAAA,QACF;AAAA,MACF;AAEA,YAAM,aAAa,OAAO,OAAO,CAAC,EAAE,YAAY,IAAI,OAAO,MAAM,CAAC;AAElE,YAAM,YAAY;AAAA,QAChB,qBAAqB,UAAU;AAAA,QAC/B;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,eAAe,UAAU,iBAAiB,MAAM,IAAI,SAAS;AAAA,QAC7D;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,qBAAqB,MAAM,IAAI,SAAS;AAAA,QACxC;AAAA,QACA;AAAA,QACA,qCAAqC,MAAM;AAAA,QAC3C;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAGA,YAAM,gBACJ,OAAO,SAAS,IACZ,OAAO,MAAM,GAAG,CAAC,IACjB;AAAA,QACE,EAAE,MAAM,WAAW,MAAM,SAAS;AAAA,QAClC,EAAE,MAAM,cAAc,MAAM,WAAW;AAAA,QACvC,EAAE,MAAM,cAAc,MAAM,WAAW;AAAA,MACzC;AAGN,YAAM,MAAM,KAAK,KAAK,cAAc,SAAS,CAAC;AAC9C,YAAM,OAAO,cAAc,MAAM,GAAG,GAAG;AACvC,YAAM,OAAO,cAAc,MAAM,GAAG;AAEpC,iBAAW,CAAC,UAAU,SAAS,KAAK,CAAC,MAAM,IAAI,EAAE,QAAQ,GAAG;AAC1D,kBAAU,KAAK,oBAAoB;AACnC,kBAAU,KAAK,0BAA0B;AACzC,mBAAW,SAAS,WAAW;AAC7B,gBAAM,QAAQ,MAAM,KACjB,QAAQ,MAAM,GAAG,EACjB,QAAQ,SAAS,CAAC,MAAc,EAAE,YAAY,CAAC;AAClD,oBAAU,KAAK,gCAAgC;AAC/C,oBAAU,KAAK,yBAAyB,MAAM,IAAI,SAAS;AAC3D,oBAAU,KAAK,wBAAwB;AACvC,oBAAU,KAAK,0BAA0B,KAAK,GAAG;AACjD,oBAAU,KAAK,gCAAgC;AAC/C,oBAAU,KAAK,2BAA2B;AAC1C,oBAAU,KAAK,+BAA+B,MAAM,IAAI,MAAM,IAAI,MAAM;AACxE,oBAAU,KAAK,qCAAqC;AAAA,QACtD;AAAA,MACF;AAGA,gBAAU,KAAK,EAAE;AACjB,gBAAU,KAAK,wBAAwB;AACvC,gBAAU,KAAK,gBAAgB;AAC/B,gBAAU,KAAK,gCAAgC,UAAU,GAAG;AAC5D,gBAAU,KAAK,4BAA4B;AAC3C,gBAAU,KAAK,qBAAqB,MAAM,GAAG;AAC7C,gBAAU,KAAK,4BAA4B;AAE3C,YAAM,OAAO,UAAU,KAAK,IAAI;AAEhC,aAAO;AAAA,QACL,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM,wCAAiC,MAAM;AAAA;AAAA;AAAA,EAAmB,IAAI;AAAA;AAAA;AAAA,8BAAoC,MAAM,KAAK,SAAS;AAAA,UAC9H;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;ACtMA,SAAS,KAAAC,UAAS;AA8ClB,IAAM,yBAGD;AAAA,EACH;AAAA,IACE,UAAU,CAAC,WAAW,SAAS,QAAQ;AAAA,IACvC,WAAW,CAAC,WAAW,QAAQ,iBAAiB,SAAS;AAAA,EAC3D;AAAA,EACA;AAAA,IACE,UAAU,CAAC,QAAQ,WAAW;AAAA,IAC9B,WAAW,CAAC,mBAAmB,OAAO;AAAA,EACxC;AAAA,EACA;AAAA,IACE,UAAU,CAAC,cAAc,gBAAgB,WAAW;AAAA,IACpD,WAAW,CAAC,WAAW,UAAU,KAAK;AAAA,EACxC;AAAA,EACA;AAAA,IACE,UAAU,CAAC,cAAc,QAAQ,aAAa;AAAA,IAC9C,WAAW,CAAC,WAAW,SAAS,YAAY;AAAA,EAC9C;AAAA,EACA;AAAA,IACE,UAAU,CAAC,cAAc,WAAW,SAAS;AAAA,IAC7C,WAAW,CAAC,UAAU,WAAW,UAAU;AAAA,EAC7C;AACF;AAMO,SAAS,cAAc,OAAoD;AAChF,QAAM,EAAE,eAAe,UAAU,SAAS,UAAU,cAAc,QAAQ,IAAI;AAE9E,QAAM,OAA8B;AAAA,IAClC,QAAQ;AAAA,IACR,aAAa;AAAA,EACf;AAEA,MAAI,kBAAkB,mBAAmB,WAAW,QAAQ,SAAS,GAAG;AACtE,UAAM,SAAS,eAAe,QAAQ;AACtC,SAAK,kBAAkB;AAAA,MACrB;AAAA,MACA;AAAA,MACA,SAAS,QAAQ,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE;AAAA,IAC5C;AAAA,EACF,OAAO;AAEL,UAAM,gBAAgB,UAAU,YAAY,OAAO;AAAA;AAAA,IAAS;AAC5D,SAAK,SAAS,GAAG,aAAa,GAAG,QAAQ;AAAA,EAC3C;AAEA,MAAI,aAAa,YAAY;AAC3B,SAAK,mBAAmB,aAAa,eAAe,OAAO;AAAA,EAC7D;AAEA,SAAO;AACT;AAMO,SAAS,qBAAqB,OAAwD;AAC3F,QAAM,kBAAkB,MAAM,kBAAkB,YAAY;AAC5D,QAAM,cAAc,OAAO,OAAO,MAAM,eAAe,EAAE,IAAI,CAAC,MAAM,EAAE,YAAY,CAAC;AAEnF,aAAW,WAAW,wBAAwB;AAC5C,UAAM,kBAAkB,QAAQ,SAAS,KAAK,CAAC,OAAO,gBAAgB,SAAS,EAAE,CAAC;AAClF,QAAI,CAAC,gBAAiB;AAEtB,UAAM,oBAAoB,YAAY;AAAA,MAAO,CAAC,QAC5C,QAAQ,UAAU,KAAK,CAAC,MAAM,IAAI,SAAS,CAAC,CAAC;AAAA,IAC/C;AAEA,QAAI,kBAAkB,SAAS,GAAG;AAChC,YAAM,kBAAkB,QAAQ,SAAS,OAAO,CAAC,OAAO,gBAAgB,SAAS,EAAE,CAAC;AACpF,YAAM,iBAAiB,gBAAgB,CAAC,KAAK;AAC7C,aAAO;AAAA,QACL,UAAU;AAAA,QACV,aACE,+BAA+B,gBAAgB,KAAK,IAAI,CAAC,6BAC9B,kBAAkB,KAAK,IAAI,CAAC;AAAA,QACzD,oBAAoB;AAAA,UAClB,8BAA8B,cAAc;AAAA,UAC5C;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO,EAAE,UAAU,MAAM;AAC3B;AAOA,SAAS,eAAe,MAAsB;AAC5C,QAAM,MAAM;AACZ,MAAI,KAAK,UAAU,IAAK,QAAO;AAC/B,SAAO,KAAK,MAAM,GAAG,MAAM,CAAC,IAAI;AAClC;AAGA,SAAS,aACP,cACA,SACQ;AACR,MAAI,iBAAiB,mBAAmB,WAAW,QAAQ,SAAS,GAAG;AACrE,WAAO,QAAQ,CAAC,KAAK;AAAA,EACvB;AACA,SAAO;AACT;AAMO,SAAS,2BAA2BC,SAAyB;AAIlE,EAAAA,QAAO;AAAA,IACL;AAAA,IACA;AAAA,IAGA;AAAA,MACE,SAASC,GAAE,OAAO,EAAE,SAAS,EAAE,SAAS,8CAA8C;AAAA,MACtF,eAAeA,GACZ,KAAK,CAAC,iBAAiB,WAAW,CAAC,EACnC,SAAS,8BAA8B;AAAA,MAC1C,UAAUA,GAAE,OAAO,EAAE,SAAS,4CAA4C;AAAA,MAC1E,SAAS,WAAWA,GAAE,MAAMA,GAAE,OAAO,CAAC,EAAE,SAAS,CAAC,EAAE;AAAA,QAClD;AAAA,MACF;AAAA,MACA,UAAUA,GACP,KAAK,CAAC,YAAY,aAAa,UAAU,CAAC,EAC1C,SAAS,EACT,QAAQ,WAAW,EACnB,SAAS,wDAAwD;AAAA,MACpE,cAAcA,GAAE,OAAO,EAAE,SAAS,EAAE,SAAS,sCAAsC;AAAA,IACrF;AAAA,IACA,OAAO,EAAE,SAAS,eAAe,UAAU,SAAS,UAAU,aAAa,MAAM;AAC/E,YAAM,SAAS,cAAc;AAAA,QAC3B,SAAS,WAAW;AAAA,QACpB;AAAA,QACA;AAAA,QACA,SAAS,WAAW;AAAA,QACpB,UAAW,YAAY;AAAA,QACvB,cAAc,gBAAgB;AAAA,MAChC,CAAC;AAED,aAAO;AAAA,QACL,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MACE,iCAA0B,eAAe,SAAS,YAAY,MAAM,EAAE,2CAErE,OAAO,kBACJ,4DACA;AAAA,UACR;AAAA,UACA;AAAA,YACE,MAAM;AAAA,YACN,MAAM,KAAK,UAAU,MAAM;AAAA,UAC7B;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAKA,EAAAD,QAAO;AAAA,IACL;AAAA,IACA;AAAA,IAGA;AAAA,MACE,mBAAmBC,GAAE,OAAO,EAAE,SAAS,gCAAgC;AAAA,MACvE,iBAAiB,WAAWA,GAAE,OAAOA,GAAE,OAAO,GAAGA,GAAE,OAAO,CAAC,CAAC,EAAE;AAAA,QAC5D;AAAA,MACF;AAAA,IACF;AAAA,IACA,OAAO,EAAE,mBAAmB,gBAAgB,MAAM;AAChD,YAAM,SAAS,qBAAqB,EAAE,mBAAmB,gBAAgB,CAAC;AAE1E,UAAI,OAAO,UAAU;AACnB,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MACE;AAAA;AAAA,gBACiB,iBAAiB;AAAA,gBACjB,KAAK,UAAU,eAAe,CAAC;AAAA;AAAA,EAC7C,OAAO,WAAW;AAAA;AAAA;AAAA,EACG,OAAO,oBAAoB,IAAI,CAAC,MAAM,YAAO,CAAC,EAAE,EAAE,KAAK,IAAI,CAAC;AAAA;AAAA;AAAA,YAExF;AAAA,YACA;AAAA,cACE,MAAM;AAAA,cACN,MAAM,KAAK,UAAU,MAAM;AAAA,YAC7B;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,aAAO;AAAA,QACL,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM;AAAA,UACR;AAAA,UACA;AAAA,YACE,MAAM;AAAA,YACN,MAAM,KAAK,UAAU,MAAM;AAAA,UAC7B;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;AChSA,SAAS,KAAAC,UAAS;AAClB,SAAS,cAAc,eAAe,YAAY,cAAc,iBAAiB;AACjF,SAAS,gBAAgB;AACzB,OAAOC,WAAU;AAsCjB,IAAM,gBAAwC;AAAA,EAC5C,wBAAwB;AAAA,EACxB,2BAA2B;AAAA,EAC3B,4BAA4B;AAAA,EAC5B,yBAAyB;AAAA,EACzB,gCAAgC;AAAA,EAChC,KAAK;AACP;AAEA,IAAM,oBAA4C;AAAA,EAChD,wBAAwB;AAC1B;AAEO,SAAS,qBAAqBC,SAAyB;AAC5D,EAAAA,QAAO;AAAA,IACL;AAAA,IACA;AAAA,IAKA;AAAA;AAAA,MAEE,UAAU,WAAWC,GAAE,OAAOA,GAAE,OAAO,GAAGA,GAAE,OAAO,CAAC,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE;AAAA,QAC5E;AAAA,MACF;AAAA,MACA,aAAa,WAAWA,GAAE,OAAOA,GAAE,OAAO,GAAGA,GAAE,OAAO,CAAC,EAAE,SAAS,CAAC,EAAE;AAAA,QACnE;AAAA,MACF;AAAA,MACA,SAAS,WAAWA,GAAE,OAAOA,GAAE,OAAO,GAAGA,GAAE,OAAO,CAAC,EAAE,SAAS,CAAC,EAAE;AAAA,QAC/D;AAAA,MACF;AAAA,MACA,WAAWA,GACR,OAAO,EACP,SAAS,EACT;AAAA,QACC;AAAA,MACF;AAAA,MACF,YAAY,WAAWA,GAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,IAAI,CAAC,EAAE;AAAA,QAC3D;AAAA,MACF;AAAA,MACA,iBAAiB,WAAWA,GAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,KAAK,CAAC,EAAE;AAAA,QACjE;AAAA,MAEF;AAAA,IACF;AAAA,IACA,OAAO,EAAE,UAAU,aAAa,SAAS,WAAW,YAAY,gBAAgB,MAAM;AAGpF,YAAM,iBAAyC,kBAC3C,EAAE,GAAG,eAAe,GAAG,SAAS,IAChC,EAAE,GAAG,SAAS;AAElB,YAAM,oBAAwD,kBAC1D,EAAE,GAAG,mBAAmB,GAAI,eAAe,CAAC,EAAG,IAC/C;AAIJ,YAAM,SAAS,cAAc;AAAA,QAC3B,UAAU;AAAA,QACV;AAAA,QACA,GAAI,sBAAsB,SAAY,EAAE,aAAa,kBAAkB,IAAI,CAAC;AAAA,QAC5E,GAAI,YAAY,SAAY,EAAE,QAAQ,IAAI,CAAC;AAAA,QAC3C,GAAI,cAAc,SAAY,EAAE,UAAU,IAAI,CAAC;AAAA,MACjD,CAAC;AAED,YAAM,aAAa,OAAO,UACtB,gCAA2B,OAAO,eAAe,KACjD,kBAAa,OAAO,KAAK;AAE7B,YAAM,QAAQ;AAAA,QACZ;AAAA,QACA;AAAA,QACA,OAAO,MAAM,SAAS,IAClB,UAAU,OAAO,MAAM,MAAM,MAAM,OAAO,MAAM,KAAK,IAAI,CAAC,KAC1D;AAAA,QACJ,OAAO,QAAQ,SAAS,IACpB,4BAA4B,OAAO,QAAQ,MAAM,MAAM,OAAO,QAAQ,KAAK,IAAI,CAAC,KAChF;AAAA,QACJ,OAAO,aAAa,SAAS,IACzB,kBAAkB,OAAO,aAAa,MAAM,MAAM,OAAO,aAAa,KAAK,IAAI,CAAC,KAChF;AAAA,QACJ,iBAAiB,OAAO,YAAY,qBAAqB,OAAO,WAAW,aAAa,uBAAuB,SAAS;AAAA,MAC1H;AAEA,aAAO;AAAA,QACL,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM,MAAM,KAAK,IAAI;AAAA,UACvB;AAAA,UACA;AAAA,YACE,MAAM;AAAA,YACN,MAAM,KAAK,UAAU,MAAM;AAAA,UAC7B;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAMO,SAAS,cAAc,MAMN;AACtB,QAAM,cAA8D;AAAA,IAClE,OAAO,CAAC;AAAA,IACR,SAAS,CAAC;AAAA,IACV,cAAc,CAAC;AAAA,IACf,WAAW;AAAA,IACX,iBAAiB;AAAA,EACnB;AAEA,MAAI;AAIF,UAAM,MAAM,QAAQ,IAAI;AACxB,UAAM,iBAAiB,KAAK,YAAYC,MAAK,QAAQ,KAAK,SAAS,IAAI;AAGvE,UAAM,aAAa,IAAI,SAASA,MAAK,GAAG,IAAI,MAAM,MAAMA,MAAK;AAC7D,QAAI,mBAAmB,OAAO,CAAC,eAAe,WAAW,UAAU,GAAG;AACpE,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO,CAAC;AAAA,QACR,SAAS,CAAC;AAAA,QACV,cAAc,CAAC;AAAA,QACf,WAAW;AAAA,QACX,iBAAiB;AAAA;AAAA,QAEjB,OAAO;AAAA,MACT;AAAA,IACF;AAKA,UAAM,4BAA4BA,MAAK,KAAK,gBAAgB,cAAc;AAE1E,QAAI,CAAC,WAAW,yBAAyB,GAAG;AAC1C,aAAO;AAAA,QACL,SAAS;AAAA,QACT,GAAG;AAAA,QACH,OAAO,4BAA4B,cAAc;AAAA,MACnD;AAAA,IACF;AAKA,QAAI;AACJ,QAAI;AACF,mBAAa,aAAa,cAAc;AAAA,IAC1C,QAAQ;AACN,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO,CAAC;AAAA,QACR,SAAS,CAAC;AAAA,QACV,cAAc,CAAC;AAAA,QACf,WAAW;AAAA,QACX,iBAAiB;AAAA,QACjB,OAAO;AAAA,MACT;AAAA,IACF;AAEA,UAAM,UAAU,aAAa,GAAG;AAChC,UAAM,iBAAiB,QAAQ,SAASA,MAAK,GAAG,IAAI,UAAU,UAAUA,MAAK;AAC7E,QAAI,eAAe,WAAW,CAAC,WAAW,WAAW,cAAc,GAAG;AACpE,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO,CAAC;AAAA,QACR,SAAS,CAAC;AAAA,QACV,cAAc,CAAC;AAAA,QACf,WAAW;AAAA,QACX,iBAAiB;AAAA;AAAA,QAEjB,OAAO;AAAA,MACT;AAAA,IACF;AAQA,UAAM,sBAAsBA,MAAK,KAAK,YAAY,cAAc;AAEhE,UAAM,UAAU,UAAU,mBAAmB;AAC7C,QAAI,QAAQ,eAAe,GAAG;AAC5B,aAAO;AAAA,QACL,GAAG;AAAA,QACH,SAAS;AAAA,QACT,OAAO;AAAA,MACT;AAAA,IACF;AAMA,UAAM,oBAAoB;AAC1B,UAAM,cAAc;AAAA,MAClB,GAAG,OAAO,KAAK,KAAK,YAAY,CAAC,CAAC;AAAA,MAClC,GAAG,OAAO,KAAK,KAAK,eAAe,CAAC,CAAC;AAAA,IACvC;AACA,eAAW,OAAO,aAAa;AAC7B,UAAI,CAAC,kBAAkB,KAAK,GAAG,GAAG;AAChC,eAAO;AAAA,UACL,GAAG;AAAA,UACH,SAAS;AAAA,UACT,OAAO,0BAA0B,GAAG;AAAA,QACtC;AAAA,MACF;AAAA,IACF;AAOA,UAAM,kBACJ;AACF,UAAM,oBAAoB;AAAA,MACxB,GAAG,OAAO,QAAQ,KAAK,YAAY,CAAC,CAAC;AAAA,MACrC,GAAG,OAAO,QAAQ,KAAK,eAAe,CAAC,CAAC;AAAA,IAC1C;AACA,eAAW,CAAC,KAAK,OAAO,KAAK,mBAAmB;AAC9C,UAAI,CAAC,gBAAgB,KAAK,QAAQ,KAAK,CAAC,GAAG;AACzC,eAAO;AAAA,UACL,GAAG;AAAA,UACH,SAAS;AAAA,UACT,OAAO,iCAAiC,GAAG,OAAO,OAAO;AAAA,QAC3D;AAAA,MACF;AAAA,IACF;AAKA,UAAM,yBAAyB,oBAAI,IAAI;AAAA,MACrC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,IACF,CAAC;AACD,QAAI,KAAK,SAAS;AAChB,iBAAW,OAAO,OAAO,KAAK,KAAK,OAAO,GAAG;AAC3C,YAAI,uBAAuB,IAAI,GAAG,GAAG;AACnC,iBAAO;AAAA,YACL,GAAG;AAAA,YACH,SAAS;AAAA,YACT,OAAO,kCAAkC,GAAG;AAAA,UAC9C;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAKA,UAAM,MAAM,aAAa,qBAAqB,MAAM;AAGpD,UAAM,oBAAoBD,GACvB,OAAO;AAAA;AAAA,MAEN,cAAcA,GAAE,OAAOA,GAAE,OAAO,GAAGA,GAAE,OAAO,CAAC,EAAE,SAAS;AAAA,MACxD,iBAAiBA,GAAE,OAAOA,GAAE,OAAO,GAAGA,GAAE,OAAO,CAAC,EAAE,SAAS;AAAA,MAC3D,SAASA,GAAE,OAAOA,GAAE,OAAO,GAAGA,GAAE,OAAO,CAAC,EAAE,SAAS;AAAA,IACrD,CAAC,EACA,YAAY;AAEf,UAAM,eAAe,kBAAkB,UAAU,KAAK,MAAM,GAAG,CAAC;AAChE,QAAI,CAAC,aAAa,SAAS;AACzB,aAAO;AAAA,QACL,GAAG;AAAA,QACH,SAAS;AAAA,QACT,OAAO,mCAAmC,aAAa,MAAM,OAAO;AAAA,MACtE;AAAA,IACF;AAGA,UAAM,SAAS,aAAa;AAK5B,UAAM,QAAkB,CAAC;AACzB,UAAM,UAAoB,CAAC;AAC3B,UAAM,eAAyB,CAAC;AAIhC,UAAM,cAAc,oBAAI,IAAY;AAAA,MAClC,GAAG,OAAO,KAAK,OAAO,gBAAgB,CAAC,CAAC;AAAA,MACxC,GAAG,OAAO,KAAK,OAAO,mBAAmB,CAAC,CAAC;AAAA,IAC7C,CAAC;AAGD,WAAO,eAAe,OAAO,gBAAgB,CAAC;AAC9C,eAAW,CAAC,KAAK,OAAO,KAAK,OAAO,QAAQ,KAAK,QAAQ,GAAG;AAC1D,UAAI,YAAY,IAAI,GAAG,GAAG;AACxB,gBAAQ,KAAK,GAAG;AAAA,MAClB,OAAO;AACL,eAAO,aAAa,GAAG,IAAI;AAC3B,oBAAY,IAAI,GAAG;AACnB,cAAM,KAAK,GAAG;AAAA,MAChB;AAAA,IACF;AAGA,QAAI,KAAK,eAAe,OAAO,KAAK,KAAK,WAAW,EAAE,SAAS,GAAG;AAChE,aAAO,kBAAkB,OAAO,mBAAmB,CAAC;AACpD,iBAAW,CAAC,KAAK,OAAO,KAAK,OAAO,QAAQ,KAAK,WAAW,GAAG;AAC7D,YAAI,YAAY,IAAI,GAAG,GAAG;AACxB,kBAAQ,KAAK,GAAG;AAAA,QAClB,OAAO;AACL,iBAAO,gBAAgB,GAAG,IAAI;AAC9B,sBAAY,IAAI,GAAG;AACnB,gBAAM,KAAK,GAAG;AAAA,QAChB;AAAA,MACF;AAAA,IACF;AAGA,QAAI,KAAK,WAAW,OAAO,KAAK,KAAK,OAAO,EAAE,SAAS,GAAG;AACxD,aAAO,UAAU,OAAO,WAAW,CAAC;AACpC,iBAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,KAAK,OAAO,GAAG;AACvD,YAAI,OAAO,QAAQ,GAAG,MAAM,QAAW;AACrC,iBAAO,QAAQ,GAAG,IAAI;AACtB,uBAAa,KAAK,GAAG;AAAA,QACvB;AAAA,MACF;AAAA,IACF;AAKA,kBAAc,qBAAqB,KAAK,UAAU,QAAQ,MAAM,CAAC,IAAI,IAAI;AAKzE,QAAI,YAAY;AAChB,QAAI;AAEJ,QAAI,KAAK,YAAY;AACnB,UAAI;AACF,iBAAS,gBAAgB,EAAE,KAAK,YAAY,OAAO,QAAQ,SAAS,IAAO,CAAC;AAC5E,oBAAY;AAAA,MACd,SAAS,KAAK;AAGZ,oBAAY;AACZ,cAAM,WAAW;AACjB,uBACE,SAAS,QAAQ,SAAS,EAAE,KAAK,MAChC,eAAe,QAAQ,IAAI,UAAU;AAAA,MAC1C;AAAA,IACF;AAEA,WAAO;AAAA,MACL,SAAS;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,iBAAiB;AAAA,MACjB,GAAI,iBAAiB,SAAY,EAAE,aAAa,IAAI,CAAC;AAAA,IACvD;AAAA,EACF,SAAS,KAAK;AACZ,WAAO;AAAA,MACL,GAAG;AAAA,MACH,SAAS;AAAA,MACT,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,IACxD;AAAA,EACF;AACF;;;AClaA,SAAS,UAAU,iBAAiB;AACpC,SAAS,cAAAE,aAAY,aAAAC,YAAW,WAAW,kBAAkB;AAC7D,SAAS,YAAY;AAErB,SAAS,KAAAC,UAAS;;;AC4BlB,SAAS,SAAS,KAAa,WAA2B;AACxD,MAAI,IAAI,UAAU,UAAW,QAAO;AACpC,SAAO,IAAI,UAAU,GAAG,YAAY,CAAC,IAAI;AAC3C;AAMA,SAAS,eAAe,IAAoB;AAG1C,QAAM,QAAQ,GAAG,MAAM,GAAG;AAC1B,MAAI,MAAM,UAAU,GAAG;AACrB,UAAM,SAAS,MAAM,CAAC,EAAE,YAAY,EAAE,UAAU,GAAG,CAAC;AACpD,UAAM,MAAM,MAAM,CAAC;AACnB,WAAO,SAAS,GAAG,MAAM,IAAI,GAAG,IAAI,EAAE;AAAA,EACxC;AACA,SAAO;AAAA,IACL,GACG,YAAY,EACZ,QAAQ,cAAc,EAAE,EACxB,UAAU,GAAG,EAAE;AAAA,IAClB;AAAA,EACF;AACF;AAKA,SAAS,uBAAuB,MAAuC;AACrE,UAAQ,MAAM;AAAA,IACZ,KAAK;AACH,aAAO;AAAA,QACL,EAAE,OAAO,OAAO,aAAa,gCAAgC;AAAA,QAC7D,EAAE,OAAO,MAAM,aAAa,iCAAiC;AAAA,MAC/D;AAAA,IACF,KAAK;AACH,aAAO;AAAA,QACL,EAAE,OAAO,WAAW,aAAa,kCAAkC;AAAA,QACnE,EAAE,OAAO,QAAQ,aAAa,oCAAoC;AAAA,MACpE;AAAA,IACF;AACE,aAAO;AAAA,QACL,EAAE,OAAO,YAAY,aAAa,eAAe;AAAA,QACjD,EAAE,OAAO,YAAY,aAAa,gBAAgB;AAAA,MACpD;AAAA,EACJ;AACF;AAKO,SAAS,cAAc,GAA8C;AAE1E,QAAM,SAAS,eAAe,EAAE,EAAE;AAGlC,QAAM,cAAc,EAAE,SAAS;AAG/B,MAAI;AAEJ,MAAI,EAAE,WAAW,EAAE,QAAQ,UAAU,GAAG;AAEtC,cAAU,EAAE,QAAQ,IAAI,CAAC,SAAS;AAAA,MAChC,OAAO,SAAS,IAAI,OAAO,EAAE;AAAA,MAC7B,aAAa,IAAI,UAAU,IAAI,QAAQ,IAAI,QAAQ;AAAA,IACrD,EAAE;AAAA,EACJ,WAAW,EAAE,WAAW,EAAE,QAAQ,WAAW,GAAG;AAE9C,cAAU;AAAA,MACR,GAAG,EAAE,QAAQ,IAAI,CAAC,SAAS,EAAE,OAAO,SAAS,IAAI,OAAO,EAAE,GAAG,aAAa,IAAI,MAAM,EAAE;AAAA,MACtF,EAAE,OAAO,SAAS,aAAa,4BAA4B;AAAA,IAC7D;AAAA,EACF,OAAO;AAEL,cAAU,uBAAuB,EAAE,IAAI;AAAA,EACzC;AAGA,MAAI,QAAQ,SAAS,GAAG;AACtB,YAAQ,KAAK,EAAE,OAAO,SAAS,aAAa,qBAAqB,CAAC;AAAA,EACpE;AAGA,YAAU,QAAQ,MAAM,GAAG,CAAC;AAE5B,SAAO;AAAA,IACL,UAAU,EAAE,YAAY,EAAE,OAAO;AAAA;AAAA,EAAO,EAAE,IAAI,KAAK;AAAA,IACnD;AAAA,IACA,cAAc;AAAA,IACd;AAAA,EACF;AACF;AASO,SAAS,eACd,WACA,UAAuD,CAAC,GACrC;AACnB,QAAM,UAA6B,CAAC;AAEpC,aAAW,KAAK,WAAW;AAEzB,QAAI,EAAE,WAAW;AACf,YAAM,gBAAgB,QAAQ,EAAE,UAAU,UAAU;AACpD,UAAI,kBAAkB,QAAW;AAE/B;AAAA,MACF;AAGA,YAAM,iBAAiB,MAAM,QAAQ,EAAE,UAAU,KAAK,IAClD,EAAE,UAAU,QACZ,CAAC,EAAE,UAAU,KAAK;AAEtB,YAAM,cAAc,MAAM,QAAQ,aAAa,IAAI,cAAc,CAAC,IAAI;AAEtE,UAAI,CAAC,eAAe,SAAS,WAAqB,GAAG;AAEnD;AAAA,MACF;AAAA,IACF;AAEA,YAAQ,KAAK,cAAc,CAAC,CAAC;AAAA,EAC/B;AAEA,SAAO;AACT;AAKO,SAAS,0BAA0B,MAA0C;AAElF,MAAI,UAAU;AAGd,YAAU,QAAQ,QAAQ,gCAAgC,EAAE;AAC5D,YAAU,QAAQ,QAAQ,aAAa,EAAE;AAGzC,QAAM,aAAa,QAAQ,QAAQ,GAAG;AACtC,QAAM,eAAe,QAAQ,QAAQ,GAAG;AAExC,MAAI,QAAQ;AACZ,MAAI,eAAe,MAAM,iBAAiB,IAAI;AAC5C,YAAQ,KAAK,IAAI,YAAY,YAAY;AAAA,EAC3C,WAAW,eAAe,IAAI;AAC5B,YAAQ;AAAA,EACV,WAAW,iBAAiB,IAAI;AAC9B,YAAQ;AAAA,EACV;AAEA,MAAI,UAAU,IAAI;AAChB,UAAM,IAAI,MAAM,2BAA2B;AAAA,EAC7C;AAEA,YAAU,QAAQ,UAAU,KAAK;AAGjC,QAAM,YAAY,QAAQ,YAAY,GAAG;AACzC,QAAM,cAAc,QAAQ,YAAY,GAAG;AAC3C,QAAM,MAAM,KAAK,IAAI,WAAW,WAAW;AAE3C,MAAI,QAAQ,IAAI;AACd,UAAM,IAAI,MAAM,wBAAwB;AAAA,EAC1C;AAEA,YAAU,QAAQ,UAAU,GAAG,MAAM,CAAC;AAGtC,YAAU,QAAQ,QAAQ,gBAAgB,IAAI;AAC9C,YAAU,QAAQ,QAAQ,MAAM,GAAG;AAEnC,QAAM,SAAS,KAAK,MAAM,OAAO;AAGjC,MAAI;AAEJ,MAAI,MAAM,QAAQ,MAAM,GAAG;AACzB,gBAAY;AAAA,EACd,WAAW,OAAO,aAAa,MAAM,QAAQ,OAAO,SAAS,GAAG;AAC9D,gBAAY,OAAO;AAAA,EACrB,WAAW,OAAO,QAAQ,MAAM,QAAS,OAAO,KAAiC,SAAS,GAAG;AAC3F,gBAAa,OAAO,KAAiC;AAAA,EACvD,OAAO;AACL,UAAM,IAAI,MAAM,sCAAsC;AAAA,EACxD;AAIA,WAAS,SAAS,KAAuD;AACvE,UAAM,YAAqC,CAAC;AAC5C,eAAW,OAAO,OAAO,KAAK,GAAG,GAAG;AAClC,UAAI,QAAQ,eAAe,QAAQ,iBAAiB,QAAQ,aAAa;AAEvE;AAAA,MACF;AACA,YAAM,MAAM,IAAI,GAAG;AACnB,UAAI,OAAO,OAAO,QAAQ,YAAY,CAAC,MAAM,QAAQ,GAAG,GAAG;AACzD,kBAAU,GAAG,IAAI,SAAS,GAA8B;AAAA,MAC1D,WAAW,MAAM,QAAQ,GAAG,GAAG;AAC7B,kBAAU,GAAG,IAAI,IAAI;AAAA,UAAI,CAAC,SACxB,QAAQ,OAAO,SAAS,YAAY,CAAC,MAAM,QAAQ,IAAI,IACnD,SAAS,IAA+B,IACxC;AAAA,QACN;AAAA,MACF,OAAO;AACL,kBAAU,GAAG,IAAI;AAAA,MACnB;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAGA,cAAY,UAAU,IAAI,CAAC,MAAM;AAC/B,QAAI,KAAK,OAAO,MAAM,UAAU;AAC9B,aAAO,SAAS,CAA4B;AAAA,IAC9C;AACA,WAAO;AAAA,EACT,CAAC;AAED,SAAO;AACT;AAKO,SAAS,wBACd,SACA,WAC6C;AAC7C,QAAM,SAAsD,CAAC;AAE7D,aAAW,UAAU,SAAS;AAE5B,UAAM,cAAc,OAAO,gBAAgB,YAAY;AACvD,UAAM,WAAW,UAAU,KAAK,CAAC,MAAM;AACrC,YAAM,UAAU,eAAe,EAAE,EAAE,EAAE,YAAY;AACjD,aAAO,YAAY,eAAe,EAAE,GAAG,YAAY,EAAE,SAAS,WAAW;AAAA,IAC3E,CAAC;AAED,QAAI,CAAC,UAAU;AAEb,YAAM,UAAU,UAAU,KAAK,CAAC,MAAM;AACpC,cAAM,UAAU,eAAe,EAAE,EAAE,EAAE,YAAY;AACjD,eAAO,QAAQ,WAAW,YAAY,MAAM,GAAG,EAAE,CAAC,CAAC;AAAA,MACrD,CAAC;AACD,UAAI,SAAS;AACX,eAAO,QAAQ,EAAE,IAAI,OAAO,iBAAiB,CAAC,KAAK;AAAA,MACrD;AACA;AAAA,IACF;AAGA,QAAI,SAAS,SAAS,kBAAkB,OAAO,iBAAiB,SAAS,GAAG;AAC1E,aAAO,SAAS,EAAE,IAAI,OAAO;AAAA,IAC/B,WAAW,SAAS,SAAS,WAAW;AACtC,aAAO,SAAS,EAAE,IAAI,OAAO,iBAAiB,CAAC,MAAM;AAAA,IACvD,OAAO;AAEL,UAAI,OAAO,YAAY;AACrB,eAAO,SAAS,EAAE,IAAI,OAAO;AAAA,MAC/B,WAAW,OAAO,iBAAiB,SAAS,GAAG;AAE7C,cAAM,SAAS,SAAS,SAAS,KAAK,CAAC,MAAM,EAAE,UAAU,OAAO,iBAAiB,CAAC,CAAC;AACnF,eAAO,SAAS,EAAE,IAAI,QAAQ,SAAS,OAAO,iBAAiB,CAAC;AAAA,MAClE;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;;;ADhTA,IAAM,yBAAyBC,GAAE,OAAO;AAAA,EACtC,IAAIA,GAAE,OAAO;AAAA,EACb,UAAUA,GAAE,OAAO;AAAA,EACnB,MAAMA,GAAE,KAAK,CAAC,QAAQ,UAAU,gBAAgB,SAAS,CAAC;AAAA,EAC1D,UAAUA,GAAE,QAAQ,EAAE,SAAS;AAAA,EAC/B,SAASA,GACN;AAAA,IACCA,GAAE,OAAO;AAAA,MACP,OAAOA,GAAE,OAAO;AAAA,MAChB,OAAOA,GAAE,OAAO;AAAA,IAClB,CAAC;AAAA,EACH,EACC,SAAS;AAAA,EACZ,SAASA,GAAE,MAAM,CAACA,GAAE,OAAO,GAAGA,GAAE,QAAQ,GAAGA,GAAE,MAAMA,GAAE,OAAO,CAAC,CAAC,CAAC,EAAE,SAAS;AAAA,EAC1E,MAAMA,GAAE,OAAO,EAAE,SAAS;AAAA,EAC1B,WAAWA,GACR,OAAO;AAAA,IACN,YAAYA,GAAE,OAAO;AAAA,IACrB,OAAOA,GAAE,MAAM,CAACA,GAAE,OAAO,GAAGA,GAAE,MAAMA,GAAE,OAAO,CAAC,CAAC,CAAC;AAAA,EAClD,CAAC,EACA,SAAS;AACd,CAAC;AAEM,SAAS,sBAAsBC,SAAyB;AAC7D,EAAAA,QAAO;AAAA,IACL;AAAA,IACA;AAAA,IAQA;AAAA,MACE,OAAOD,GAAE,OAAO,EAAE,SAAS,gEAAgE;AAAA,MAC3F,WAAW,WAAWA,GAAE,MAAM,sBAAsB,EAAE,SAAS,CAAC,EAAE;AAAA,QAChE;AAAA,MAEF;AAAA,MACA,SAAS;AAAA,QACPA,GAAE,OAAOA,GAAE,OAAO,GAAGA,GAAE,MAAM,CAACA,GAAE,OAAO,GAAGA,GAAE,MAAMA,GAAE,OAAO,CAAC,GAAGA,GAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,SAAS;AAAA,MACzF,EAAE,SAAS,mEAAmE;AAAA,IAChF;AAAA,IACA,OAAO,EAAE,OAAO,WAAW,QAAQ,MAAM;AAKvC,UAAI;AAGJ,YAAM,aAAa;AACnB,UAAI,CAAC,WAAW,KAAK,KAAK,GAAG;AAC3B,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM,KAAK,UAAU;AAAA,gBACnB,OAAO,wBAAwB,MAAM,MAAM,GAAG,EAAE,CAAC;AAAA,cACnD,CAAC;AAAA,YACH;AAAA,UACF;AAAA,UACA,SAAS;AAAA,QACX;AAAA,MACF;AAEA,UAAI,aAAa,UAAU,SAAS,GAAG;AACrC,4BAAoB;AAAA,MACtB,OAAO;AAEL,cAAM,oBAAoB,KAAK,QAAQ,IAAI,GAAG,gBAAgB,aAAa,GAAG,KAAK,OAAO;AAC1F,YAAI;AACF,gBAAM,MAAM,MAAM,SAAS,mBAAmB,OAAO;AACrD,gBAAM,YAAY,KAAK,MAAM,GAAG;AAChC,8BAAqB,UAAU,aAAa,CAAC;AAAA,QAC/C,QAAQ;AAEN,cAAI;AACF,kBAAM,eAAe,KAAK,QAAQ,IAAI,GAAG,gBAAgB,wBAAwB;AACjF,kBAAM,MAAM,MAAM,SAAS,cAAc,OAAO;AAChD,kBAAM,WAAW,KAAK,MAAM,GAAG;AAG/B,kBAAM,YAAY,SAAS,OAAO,KAAK,CAAC,MAAM,EAAE,UAAU,KAAK;AAC/D,gCAAqB,WAAW,aAAa,CAAC;AAAA,UAChD,SAAS,KAAK;AACZ,kBAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,mBAAO;AAAA,cACL,SAAS;AAAA,gBACP;AAAA,kBACE,MAAM;AAAA,kBACN,MAAM,KAAK,UAAU;AAAA,oBACnB,OAAO,+CAA+C,KAAK,MAAM,GAAG;AAAA,oBACpE,MAAM;AAAA,kBACR,CAAC;AAAA,gBACH;AAAA,cACF;AAAA,cACA,SAAS;AAAA,YACX;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAGA,YAAM,UAAU,eAAe,mBAAmB,WAAW,CAAC,CAAC;AAM/D,YAAM,cAAcA,GAAE,OAAO,EAAE,IAAI,IAAI,yCAAyC;AAChF,iBAAW,KAAK,SAAS;AACvB,mBAAW,OAAO,EAAE,SAAS;AAC3B,gBAAM,QAAQ,YAAY,UAAU,IAAI,KAAK;AAC7C,cAAI,CAAC,MAAM,SAAS;AAClB,mBAAO;AAAA,cACL,SAAS;AAAA,gBACP;AAAA,kBACE,MAAM;AAAA,kBACN,MAAM,KAAK,UAAU;AAAA,oBACnB,OAAO,2BAA2B,KAAK,4BAA4B,MAAM,MAAM,OAAO,CAAC,GAAG,WAAW,gBAAgB;AAAA,kBACvH,CAAC;AAAA,gBACH;AAAA,cACF;AAAA,cACA,SAAS;AAAA,YACX;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,UAAI,QAAQ,WAAW,GAAG;AACxB,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MACE,UAAU,KAAK,mHAEsC,KAAK;AAAA,YAC9D;AAAA,YACA;AAAA,cACE,MAAM;AAAA;AAAA,cAEN,MAAM,KAAK,UAAU,CAAC,CAAC;AAAA,YACzB;AAAA,UACF;AAAA,UACA,SAAS;AAAA,QACX;AAAA,MACF;AAMA,aAAO;AAAA,QACL,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MACE,WAAW,QAAQ,MAAM,yBAAyB,KAAK;AAAA,UAG3D;AAAA,UACA;AAAA,YACE,MAAM;AAAA,YACN,MAAM,KAAK,UAAU,OAAO;AAAA,UAC9B;AAAA,QACF;AAAA,QACA,SAAS;AAAA,MACX;AAAA,IACF;AAAA,EACF;AAKA,EAAAC,QAAO;AAAA,IACL;AAAA,IACA;AAAA,IAGA,EAAE,OAAOD,GAAE,OAAO,EAAE,SAAS,2CAA2C,EAAE;AAAA,IAC1E,OAAO,EAAE,MAAM,MAAM;AACnB,YAAM,aAAa;AACnB,UAAI,CAAC,WAAW,KAAK,KAAK,GAAG;AAC3B,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM,KAAK,UAAU,EAAE,OAAO,wBAAwB,MAAM,MAAM,GAAG,EAAE,CAAC,IAAI,CAAC;AAAA,YAC/E;AAAA,UACF;AAAA,UACA,SAAS;AAAA,QACX;AAAA,MACF;AAEA,YAAM,MAAM,QAAQ,IAAI;AAGxB,YAAM,gBAAgB,KAAK,KAAK,gBAAgB,aAAa,GAAG,KAAK,OAAO;AAC5E,UAAI,YAMC,CAAC;AACN,UAAI;AACF,cAAM,MAAM,MAAM,SAAS,eAAe,OAAO;AACjD,cAAM,SAAS,KAAK,MAAM,GAAG;AAC7B,oBAAY,OAAO,aAAa,CAAC;AAAA,MACnC,QAAQ;AAEN,eAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,KAAK,UAAU,EAAE,MAAM,KAAK,CAAC,EAAE,CAAC,EAAE;AAAA,MACtF;AAEA,UAAI,UAAU,WAAW,GAAG;AAC1B,eAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,KAAK,UAAU,EAAE,MAAM,KAAK,CAAC,EAAE,CAAC,EAAE;AAAA,MACtF;AAGA,YAAM,cAAc,KAAK,KAAK,gBAAgB,WAAW,GAAG,KAAK,OAAO;AACxE,UAAI,cAAc,oBAAI,IAAY;AAClC,UAAI;AACF,cAAM,MAAM,MAAM,SAAS,aAAa,OAAO;AAC/C,cAAM,SAAS,KAAK,MAAM,GAAG;AAC7B,sBAAc,IAAI,IAAI,OAAO,KAAK,OAAO,WAAW,CAAC,CAAC,CAAC;AAAA,MACzD,QAAQ;AAAA,MAER;AAGA,YAAM,OAAO,UAAU,KAAK,CAAC,MAAM,CAAC,YAAY,IAAI,EAAE,EAAE,CAAC;AACzD,UAAI,CAAC,MAAM;AACT,eAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,KAAK,UAAU,EAAE,MAAM,KAAK,CAAC,EAAE,CAAC,EAAE;AAAA,MACtF;AAEA,aAAO;AAAA,QACL,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM,KAAK,UAAU;AAAA,cACnB,MAAM;AAAA,cACN,YAAY,KAAK;AAAA,cACjB,UAAU,KAAK;AAAA,cACf,MAAM,KAAK;AAAA,cACX,SAAS,KAAK,WAAW;AAAA,cACzB,MAAM,KAAK,QAAQ;AAAA,cACnB,OAAO,UAAU,QAAQ,IAAI,IAAI;AAAA,cACjC,OAAO,UAAU;AAAA,YACnB,CAAC;AAAA,UACH;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAKA,EAAAC,QAAO;AAAA,IACL;AAAA,IACA;AAAA,IAGA;AAAA,MACE,OAAOD,GAAE,OAAO,EAAE,SAAS,4BAA4B;AAAA,MACvD,YAAYA,GAAE,OAAO,EAAE,SAAS,2DAA2D;AAAA,MAC3F,QAAQA,GAAE,OAAO,EAAE,SAAS,6BAA6B;AAAA,IAC3D;AAAA,IACA,OAAO,EAAE,OAAO,YAAY,OAAO,MAAM;AACvC,YAAM,aAAa;AACnB,UAAI,CAAC,WAAW,KAAK,KAAK,GAAG;AAC3B,eAAO;AAAA,UACL,SAAS;AAAA,YACP,EAAE,MAAM,QAAiB,MAAM,KAAK,UAAU,EAAE,OAAO,qBAAqB,CAAC,EAAE;AAAA,UACjF;AAAA,UACA,SAAS;AAAA,QACX;AAAA,MACF;AACA,UAAI,CAAC,6BAA6B,KAAK,UAAU,GAAG;AAClD,eAAO;AAAA,UACL,SAAS;AAAA,YACP,EAAE,MAAM,QAAiB,MAAM,KAAK,UAAU,EAAE,OAAO,qBAAqB,CAAC,EAAE;AAAA,UACjF;AAAA,UACA,SAAS;AAAA,QACX;AAAA,MACF;AACA,YAAM,aAAa,OAAO,MAAM,GAAG,GAAI;AAEvC,YAAM,MAAM,QAAQ,IAAI;AACxB,YAAM,aAAa,KAAK,KAAK,gBAAgB,SAAS;AACtD,YAAM,cAAc,KAAK,YAAY,GAAG,KAAK,OAAO;AAGpD,UAAIE,YAAW,UAAU,KAAKC,WAAU,UAAU,EAAE,eAAe,GAAG;AACpE,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM,KAAK,UAAU,EAAE,OAAO,oDAA+C,CAAC;AAAA,YAChF;AAAA,UACF;AAAA,UACA,SAAS;AAAA,QACX;AAAA,MACF;AACA,gBAAU,YAAY,EAAE,WAAW,KAAK,CAAC;AAGzC,UAAI,WAKA;AAAA,QACF,SAAS;AAAA,QACT;AAAA,QACA,SAAS,CAAC;AAAA,MACZ;AACA,UAAI;AACF,YAAID,YAAW,WAAW,GAAG;AAC3B,cAAIC,WAAU,WAAW,EAAE,eAAe,GAAG;AAC3C,mBAAO;AAAA,cACL,SAAS;AAAA,gBACP;AAAA,kBACE,MAAM;AAAA,kBACN,MAAM,KAAK,UAAU,EAAE,OAAO,qDAAgD,CAAC;AAAA,gBACjF;AAAA,cACF;AAAA,cACA,SAAS;AAAA,YACX;AAAA,UACF;AACA,gBAAM,MAAM,MAAM,SAAS,aAAa,OAAO;AAC/C,qBAAW,KAAK,MAAM,GAAG;AAAA,QAC3B;AAAA,MACF,QAAQ;AAAA,MAER;AAGA,eAAS,QAAQ,UAAU,IAAI;AAC/B,eAAS,aAAY,oBAAI,KAAK,GAAE,YAAY;AAG5C,YAAM,MAAM,GAAG,WAAW;AAC1B,YAAM,UAAU,KAAK,KAAK,UAAU,UAAU,MAAM,CAAC,GAAG,OAAO;AAC/D,iBAAW,KAAK,WAAW;AAE3B,aAAO;AAAA,QACL,SAAS;AAAA,UACP,EAAE,MAAM,QAAiB,MAAM,KAAK,UAAU,EAAE,UAAU,MAAM,OAAO,WAAW,CAAC,EAAE;AAAA,QACvF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;AEjXA,SAAS,KAAAC,UAAS;AAElB,SAAS,gBAAAC,eAAc,iBAAAC,gBAAe,cAAAC,aAAY,aAAAC,YAAW,aAAAC,kBAAiB;AAC9E,SAAS,QAAAC,aAAY;AAerB,IAAM,sBAA+C;AAAA,EACnD,CAAC,YAAY,UAAU;AAAA,EACvB,CAAC,SAAS,OAAO;AAAA,EACjB,CAAC,OAAO,KAAK;AAAA,EACb,CAAC,QAAQ,MAAM;AAAA,EACf,CAAC,aAAa,WAAW;AAAA,EACzB,CAAC,QAAQ,MAAM;AAAA,EACf,CAAC,QAAQ,OAAO;AAAA,EAChB,CAAC,YAAY,UAAU;AAAA,EACvB,CAAC,UAAU,QAAQ;AAAA,EACnB,CAAC,OAAO,KAAK;AACf;AAEA,IAAM,iBAAyC;AAAA,EAC7C,UAAU;AAAA,EACV,OAAO;AAAA,EACP,KAAK;AAAA,EACL,MAAM;AAAA,EACN,OAAO;AAAA,EACP,WAAW;AAAA,EACX,MAAM;AAAA,EACN,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,KAAK;AACP;AAMA,SAAS,YAAY,WAA2B;AAC9C,QAAM,QAAQ,UAAU,YAAY;AACpC,aAAW,CAAC,SAAS,KAAK,KAAK,qBAAqB;AAClD,QAAI,MAAM,SAAS,OAAO,EAAG,QAAO;AAAA,EACtC;AAEA,SAAO,MAAM,QAAQ,qBAAqB,EAAE,EAAE,QAAQ,WAAW,EAAE;AACrE;AAmBO,SAAS,yBAAyB,OAGvC;AACA,QAAM,QAAQ,YAAY,MAAM,SAAS;AACzC,MAAI;AACF,UAAM,YAAY,0BAA0B,MAAM,YAAY;AAC9D,WAAO;AAAA,MACL,QAAQ,EAAE,OAAO,OAAO,MAAM,WAAW,UAAU;AAAA,MACnD,SAAS;AAAA,IACX;AAAA,EACF,SAAS,KAAK;AACZ,UAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,WAAO;AAAA,MACL,QAAQ;AAAA,QACN,OAAO;AAAA,QACP,WAAW,MAAM;AAAA,QACjB;AAAA,QACA,WAAW,CAAC;AAAA,QACZ,YAAY;AAAA,MACd;AAAA,MACA,SAAS;AAAA,IACX;AAAA,EACF;AACF;AAmBO,SAAS,mBAAmB,OAA8D;AAC/F,QAAM,MAAM,MAAM,QAAQ,QAAQ,IAAI;AACtC,QAAM,MAAMC,MAAK,KAAK,cAAc;AACpC,QAAM,WAAWA,MAAK,KAAK,wBAAwB;AACnD,MAAI;AACF,IAAAC,WAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AAGlC,QAAIC,YAAW,QAAQ,GAAG;AACxB,YAAM,OAAOC,WAAU,QAAQ;AAC/B,UAAI,KAAK,eAAe,GAAG;AACzB,cAAM,UAAU,iCAAiC,QAAQ;AACzD,eAAO;AAAA,UACL,MAAM,KAAK,UAAU,EAAE,SAAS,OAAO,OAAO,QAAQ,CAAC;AAAA,UACvD,SAAS;AAAA,QACX;AAAA,MACF;AAAA,IACF;AAEA,UAAM,WAAW;AAAA,MACf,SAAS;AAAA,MACT,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,MAClC,QAAQ,MAAM;AAAA,IAChB;AACA,IAAAC,eAAc,UAAU,KAAK,UAAU,UAAU,MAAM,CAAC,IAAI,IAAI;AAChE,WAAO;AAAA,MACL,MAAM,KAAK,UAAU,EAAE,SAAS,MAAM,MAAM,UAAU,YAAY,MAAM,OAAO,OAAO,CAAC;AAAA,MACvF,SAAS;AAAA,IACX;AAAA,EACF,SAAS,KAAK;AACZ,UAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,WAAO;AAAA,MACL,MAAM,KAAK,UAAU,EAAE,SAAS,OAAO,OAAO,QAAQ,CAAC;AAAA,MACvD,SAAS;AAAA,IACX;AAAA,EACF;AACF;AAiBO,SAAS,uBAAuB,OAGrC;AACA,QAAM,MAAM,MAAM,QAAQ,QAAQ,IAAI;AACtC,QAAM,MAAMJ,MAAK,KAAK,gBAAgB,SAAS;AAC/C,QAAM,WAAWA,MAAK,KAAK,GAAG,MAAM,KAAK,OAAO;AAChD,MAAI;AACF,IAAAC,WAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AAElC,QAAI;AACJ,QAAI,MAAM,aAAa,MAAM,UAAU,SAAS,GAAG;AACjD,gBAAU,wBAAwB,MAAM,YAAY,MAAM,SAAS;AAAA,IACrE,OAAO;AAEL,gBAAU,OAAO;AAAA,QACf,MAAM,WAAW,IAAI,CAAC,MAAM,CAAC,EAAE,iBAAiB,EAAE,iBAAiB,CAAC,KAAK,EAAE,CAAC;AAAA,MAC9E;AAAA,IACF;AAEA,UAAM,UAAU;AAAA,MACd,SAAS;AAAA,MACT,OAAO,MAAM;AAAA,MACb,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,MACpC;AAAA,IACF;AAGA,QAAIC,YAAW,QAAQ,GAAG;AACxB,YAAM,OAAOC,WAAU,QAAQ;AAC/B,UAAI,KAAK,eAAe,GAAG;AACzB,cAAM,UAAU,iCAAiC,QAAQ;AACzD,eAAO;AAAA,UACL,MAAM,KAAK,UAAU,EAAE,SAAS,OAAO,OAAO,QAAQ,CAAC;AAAA,UACvD,SAAS;AAAA,QACX;AAAA,MACF;AAAA,IACF;AAEA,IAAAC,eAAc,UAAU,KAAK,UAAU,SAAS,MAAM,CAAC,IAAI,IAAI;AAC/D,WAAO;AAAA,MACL,MAAM,KAAK,UAAU;AAAA,QACnB,SAAS;AAAA,QACT,MAAM;AAAA,QACN,cAAc,OAAO,KAAK,OAAO,EAAE;AAAA,MACrC,CAAC;AAAA,MACD,SAAS;AAAA,IACX;AAAA,EACF,SAAS,KAAK;AACZ,UAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,WAAO;AAAA,MACL,MAAM,KAAK,UAAU,EAAE,SAAS,OAAO,OAAO,QAAQ,CAAC;AAAA,MACvD,SAAS;AAAA,IACX;AAAA,EACF;AACF;AASO,SAAS,uBAAuB,OAGrC;AACA,QAAM,MAAM,MAAM,QAAQ,QAAQ,IAAI;AACtC,QAAM,WAAWJ,MAAK,KAAK,gBAAgB,WAAW,GAAG,MAAM,KAAK,OAAO;AAC3E,MAAI,CAACE,YAAW,QAAQ,GAAG;AACzB,WAAO;AAAA,MACL,MAAM,KAAK,UAAU,EAAE,SAAS,MAAM,OAAO,MAAM,MAAM,CAAC;AAAA,MAC1D,SAAS;AAAA,IACX;AAAA,EACF;AACA,MAAI;AACF,UAAM,MAAMG,cAAa,UAAU,MAAM;AACzC,UAAM,SAAS,KAAK,MAAM,GAAG;AAC7B,WAAO,EAAE,MAAM,KAAK,UAAU,MAAM,GAAG,SAAS,MAAM;AAAA,EACxD,SAAS,KAAK;AACZ,UAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,WAAO;AAAA,MACL,MAAM,KAAK,UAAU,EAAE,OAAO,MAAM,OAAO,MAAM,OAAO,WAAW,QAAQ,CAAC;AAAA,MAC5E,SAAS;AAAA,IACX;AAAA,EACF;AACF;AAQO,SAAS,mBAAmB,OAA8D;AAC/F,QAAM,aAAa,MAAM,MAAM,YAAY,EAAE,KAAK;AAClD,QAAM,YAAY,eAAe,UAAU;AAC3C,MAAI,CAAC,WAAW;AACd,WAAO;AAAA,MACL,MAAM,KAAK,UAAU,EAAE,OAAO,MAAM,SAAS,kBAAkB,MAAM,KAAK,GAAG,CAAC;AAAA,MAC9E,SAAS;AAAA,IACX;AAAA,EACF;AACA,SAAO;AAAA,IACL,MAAM,KAAK,UAAU,EAAE,OAAO,YAAY,UAAU,CAAC;AAAA,IACrD,SAAS;AAAA,EACX;AACF;AASO,SAAS,uBAAuB,OAGrC;AACA,QAAM,MAAM,MAAM,QAAQ,QAAQ,IAAI;AACtC,QAAM,MAAML,MAAK,KAAK,cAAc;AACpC,QAAM,WAAWA,MAAK,KAAK,oBAAoB;AAC/C,MAAI;AACF,IAAAC,WAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AAGlC,QAAIC,YAAW,QAAQ,GAAG;AACxB,YAAM,OAAOC,WAAU,QAAQ;AAC/B,UAAI,KAAK,eAAe,GAAG;AACzB,eAAO;AAAA,UACL,MAAM,KAAK,UAAU;AAAA,YACnB,SAAS;AAAA,YACT,OAAO,iCAAiC,QAAQ;AAAA,UAClD,CAAC;AAAA,UACD,SAAS;AAAA,QACX;AAAA,MACF;AAAA,IACF;AAEA,UAAM,UAAU;AAAA,MACd,SAAS;AAAA,MACT,UAAS,oBAAI,KAAK,GAAE,YAAY;AAAA,MAChC,cAAc,MAAM;AAAA,IACtB;AACA,IAAAC,eAAc,UAAU,KAAK,UAAU,SAAS,MAAM,CAAC,IAAI,IAAI;AAC/D,WAAO;AAAA,MACL,MAAM,KAAK,UAAU,EAAE,SAAS,MAAM,MAAM,SAAS,CAAC;AAAA,MACtD,SAAS;AAAA,IACX;AAAA,EACF,SAAS,KAAK;AACZ,UAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,WAAO;AAAA,MACL,MAAM,KAAK,UAAU,EAAE,SAAS,OAAO,OAAO,QAAQ,CAAC;AAAA,MACvD,SAAS;AAAA,IACX;AAAA,EACF;AACF;AAMO,SAAS,2BAA2BE,SAAyB;AAIlE,EAAAA,QAAO;AAAA,IACL;AAAA,IACA;AAAA,IAGA;AAAA,MACE,cAAcC,GAAE,OAAO,EAAE,SAAS,uDAAuD;AAAA,IAC3F;AAAA,IACA,OAAO,EAAE,aAAa,MAAM;AAC1B,YAAM,EAAE,MAAM,QAAQ,IAAI,uBAAuB,EAAE,aAAa,CAAC;AACjE,aAAO;AAAA,QACL,SAAS,CAAC,EAAE,MAAM,QAAiB,KAAK,CAAC;AAAA,QACzC;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAKA,EAAAD,QAAO;AAAA,IACL;AAAA,IACA;AAAA,IAIA;AAAA,MACE,WAAWC,GAAE,OAAO,EAAE,SAAS,kDAAkD;AAAA,MACjF,cAAcA,GACX,OAAO,EACP,SAAS,wEAAwE;AAAA,IACtF;AAAA,IACA,OAAO,EAAE,WAAW,aAAa,MAAM;AACrC,YAAM,EAAE,QAAQ,QAAQ,IAAI,yBAAyB,EAAE,WAAW,aAAa,CAAC;AAChF,aAAO;AAAA,QACL,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,KAAK,UAAU,MAAM,EAAE,CAAC;AAAA,QACjE;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAKA,EAAAD,QAAO;AAAA,IACL;AAAA,IACA;AAAA,IAEA;AAAA,MACE,QAAQ;AAAA,QACNC,GAAE;AAAA,UACAA,GAAE,OAAO;AAAA,YACP,OAAOA,GAAE,OAAO;AAAA,YAChB,OAAOA,GAAE,OAAO;AAAA,YAChB,WAAWA,GAAE,MAAMA,GAAE,IAAI,CAAC;AAAA,YAC1B,kBAAkBA,GACf,OAAO;AAAA,cACN,cAAcA,GAAE,OAAOA,GAAE,OAAO,GAAGA,GAAE,OAAO,CAAC,EAAE,SAAS;AAAA,cACxD,aAAaA,GAAE,OAAOA,GAAE,OAAO,GAAGA,GAAE,OAAO,CAAC,EAAE,SAAS;AAAA,YACzD,CAAC,EACA,SAAS;AAAA,UACd,CAAC;AAAA,QACH;AAAA,MACF,EAAE,SAAS,yEAAyE;AAAA,IACtF;AAAA,IACA,OAAO,EAAE,OAAO,MAAM;AACpB,YAAM,EAAE,MAAM,QAAQ,IAAI,mBAAmB,EAAE,OAAO,CAAC;AACvD,aAAO;AAAA,QACL,SAAS,CAAC,EAAE,MAAM,QAAiB,KAAK,CAAC;AAAA,QACzC;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAKA,EAAAD,QAAO;AAAA,IACL;AAAA,IACA;AAAA,IAEA;AAAA,MACE,OAAOC,GAAE,OAAO,EAAE,SAAS,6BAA6B;AAAA,MACxD,YAAY;AAAA,QACVA,GAAE;AAAA,UACAA,GAAE,OAAO;AAAA,YACP,iBAAiBA,GAAE,OAAO;AAAA,YAC1B,kBAAkBA,GAAE,MAAMA,GAAE,OAAO,CAAC;AAAA,YACpC,YAAYA,GAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,UAC7C,CAAC;AAAA,QACH;AAAA,MACF,EAAE;AAAA,QACA;AAAA,MACF;AAAA,MACA,WAAW,WAAWA,GAAE,MAAMA,GAAE,IAAI,CAAC,EAAE,SAAS,CAAC,EAAE;AAAA,QACjD;AAAA,MACF;AAAA,IACF;AAAA,IACA,OAAO,EAAE,OAAO,YAAY,UAAU,MAAM;AAC1C,YAAM,EAAE,MAAM,QAAQ,IAAI,uBAAuB;AAAA,QAC/C;AAAA,QACA;AAAA,QACA,GAAI,aAAa,UAAU,SAAS,IAChC,EAAE,UAAmD,IACrD,CAAC;AAAA,MACP,CAAC;AACD,aAAO;AAAA,QACL,SAAS,CAAC,EAAE,MAAM,QAAiB,KAAK,CAAC;AAAA,QACzC;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAKA,EAAAD,QAAO;AAAA,IACL;AAAA,IACA;AAAA,IAEA;AAAA,MACE,OAAOC,GAAE,OAAO,EAAE,SAAS,6BAA6B;AAAA,IAC1D;AAAA,IACA,OAAO,EAAE,MAAM,MAAM;AACnB,YAAM,EAAE,MAAM,QAAQ,IAAI,uBAAuB,EAAE,MAAM,CAAC;AAC1D,aAAO;AAAA,QACL,SAAS,CAAC,EAAE,MAAM,QAAiB,KAAK,CAAC;AAAA,QACzC;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAKA,EAAAD,QAAO;AAAA,IACL;AAAA,IACA;AAAA,IAEA;AAAA,MACE,OAAOC,GAAE,OAAO,EAAE,SAAS,6CAA6C;AAAA,IAC1E;AAAA,IACA,OAAO,EAAE,MAAM,MAAM;AACnB,YAAM,EAAE,MAAM,QAAQ,IAAI,mBAAmB,EAAE,MAAM,CAAC;AACtD,aAAO;AAAA,QACL,SAAS,CAAC,EAAE,MAAM,QAAiB,KAAK,CAAC;AAAA,QACzC;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;AC5eA,SAAS,KAAAC,WAAS;AAClB,SAAS,gBAAAC,eAAc,iBAAAC,gBAAe,cAAAC,aAAY,aAAAC,YAAW,aAAAC,kBAAiB;AAC9E,SAAS,QAAAC,aAAY;AAGrB,SAAS,cAAAC,mBAAkB;;;ACD3B;AAAA,EACE,cAAAC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AACP;AAAA,EACE,gBAAAC;AAAA,EACA,iBAAAC;AAAA,EACA,cAAAC;AAAA,EACA,aAAAC;AAAA,EACA,aAAAC;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,QAAAC,aAAY;AAErB,SAAS,KAAAC,WAAS;AAMlB,IAAM,YAAY;AAClB,IAAM,WAAW;AACjB,IAAM,UAAU;AAChB,IAAM,qBAAqB;AAC3B,IAAM,gBAAgB;AAkDtB,SAAS,cAAc,UAAkB,SAAuB;AAC9D,MAAI,CAACJ,YAAW,QAAQ,EAAG;AAC3B,QAAM,OAAOE,WAAU,QAAQ;AAC/B,MAAI,KAAK,eAAe,GAAG;AACzB,UAAM,IAAI,MAAM,2CAA2C,OAAO,KAAK,QAAQ,EAAE;AAAA,EACnF;AACF;AAGA,SAAS,cAAc,MAAsB;AAC3C,SAAOL,YAAW,QAAQ,EAAE,OAAO,IAAI,EAAE,OAAO,KAAK;AACvD;AAGA,SAAS,gBAAgB,GAAW,GAAoB;AACtD,MAAI,EAAE,WAAW,EAAE,OAAQ,QAAO;AAClC,SAAO,gBAAgB,OAAO,KAAK,GAAG,MAAM,GAAG,OAAO,KAAK,GAAG,MAAM,CAAC;AACvE;AAGA,SAAS,gBAAmC;AAC1C,SAAO;AAAA,IACL,SAAS;AAAA,IACT,WAAW;AAAA,IACX,YAAY,CAAC;AAAA,EACf;AACF;AAOO,SAAS,iBAAiB,KAA4D;AAC3F,QAAM,SAASM,MAAK,KAAK,OAAO;AAChC,QAAM,UAAUA,MAAK,QAAQ,QAAQ;AAGrC,gBAAc,SAAS,oBAAoB;AAG3C,EAAAF,WAAU,QAAQ,EAAE,WAAW,KAAK,CAAC;AAGrC,QAAM,EAAE,WAAW,WAAW,IAAI,oBAAoB,MAAM;AAAA,IAC1D,YAAY;AAAA,EACd,CAAC;AAED,QAAM,eAAe,UAAU,OAAO,EAAE,MAAM,QAAQ,QAAQ,MAAM,CAAC;AACrE,QAAM,gBAAgB,WAAW,OAAO,EAAE,MAAM,SAAS,QAAQ,MAAM,CAAC;AAGxE,QAAM,cAAcJ,YAAW,QAAQ,EAAE,OAAO,YAAY,EAAE,OAAO,KAAK;AAE1E,QAAM,UAA2B;AAAA,IAC/B,SAAS;AAAA,IACT,WAAW;AAAA,IACX,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IAClC;AAAA,IACA;AAAA,EACF;AAEA,EAAAE,eAAc,SAAS,KAAK,UAAU,SAAS,MAAM,CAAC,GAAG,EAAE,UAAU,QAAQ,CAAC;AAE9E,SAAO,EAAE,cAAc,YAAY;AACrC;AAGO,SAAS,iBAAiB,KAA8D;AAC7F,QAAM,UAAUI,MAAK,KAAK,SAAS,QAAQ;AAG3C,gBAAc,SAAS,oBAAoB;AAE3C,MAAI,CAACH,YAAW,OAAO,GAAG;AACxB,UAAM,IAAI,MAAM,8DAAyD;AAAA,EAC3E;AAEA,MAAI;AACJ,MAAI;AACF,UAAMF,cAAa,SAAS,OAAO;AAAA,EACrC,SAAS,KAAK;AACZ,UAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,UAAM,IAAI,MAAM,8BAA8B,GAAG,IAAI,EAAE,OAAO,IAAI,CAAC;AAAA,EACrE;AAEA,MAAI;AACJ,MAAI;AACF,aAAS,KAAK,MAAM,GAAG;AAAA,EACzB,QAAQ;AACN,UAAM,IAAI,MAAM,sCAAsC;AAAA,EACxD;AAGA,MACE,OAAO,OAAO,iBAAiB,YAC/B,CAAC,OAAO,aAAa,SAAS,4BAA4B,GAC1D;AACA,UAAM,IAAI,MAAM,8CAA8C;AAAA,EAChE;AACA,MAAI,OAAO,OAAO,kBAAkB,YAAY,CAAC,OAAO,cAAc,SAAS,YAAY,GAAG;AAC5F,UAAM,IAAI,MAAM,+CAA+C;AAAA,EACjE;AAEA,QAAM,YAAY,gBAAgB,OAAO,YAAY;AACrD,QAAM,aAAa,iBAAiB,OAAO,aAAa;AAExD,SAAO,EAAE,YAAY,UAAU;AACjC;AAkCO,SAAS,aAAa,eAAuB,YAA0C;AAC5F,QAAM,SAAS,cAAc,aAAa;AAC1C,QAAM,MAAM,KAAK,UAAU,eAAe,UAAU;AAEpD,SAAO;AAAA,IACL;AAAA,IACA,WAAW,IAAI,SAAS,QAAQ;AAAA,IAChC,WAAW;AAAA,IACX,WAAU,oBAAI,KAAK,GAAE,YAAY;AAAA,EACnC;AACF;AAOO,SAAS,eACd,eACA,WACA,WACS;AAET,QAAM,WAAW;AAAA,IACf;AAAA,IACA;AAAA,IACA;AAAA,IACA,OAAO,KAAK,UAAU,WAAW,QAAQ;AAAA,EAC3C;AAEA,MAAI,CAAC,SAAU,QAAO;AAGtB,QAAM,eAAe,cAAc,aAAa;AAChD,SAAO,gBAAgB,cAAc,UAAU,MAAM;AACvD;AAOO,SAAS,sBAAsB,KAAgC;AACpE,QAAM,eAAeO,MAAK,KAAK,eAAe,kBAAkB;AAEhE,gBAAc,cAAc,iBAAiB;AAE7C,MAAI,CAACC,YAAW,YAAY,EAAG,QAAO,cAAc;AAEpD,MAAI;AACJ,MAAI;AACF,UAAMC,cAAa,cAAc,OAAO;AAAA,EAC1C,SAAS,KAAK;AACZ,UAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,UAAM,IAAI,MAAM,mCAAmC,GAAG,IAAI,EAAE,OAAO,IAAI,CAAC;AAAA,EAC1E;AAEA,MAAI;AACF,UAAM,SAAS,KAAK,MAAM,GAAG;AAE7B,QAAI,OAAO,YAAY,SAAS,OAAO,OAAO,eAAe,UAAU;AACrE,YAAM,IAAI,MAAM,4EAA4E;AAAA,IAC9F;AACA,WAAO;AAAA,EACT,SAAS,KAAK;AACZ,QAAI,eAAe,SAAS,IAAI,QAAQ,WAAW,WAAW,EAAG,OAAM;AACvE,UAAM,IAAI,MAAM,wCAAwC,EAAE,OAAO,IAAI,CAAC;AAAA,EACxE;AACF;AAGO,SAAS,sBACd,KACA,kBACA,KACA,aACM;AACN,QAAM,eAAeF,MAAK,KAAK,aAAa;AAC5C,QAAM,eAAeA,MAAK,cAAc,kBAAkB;AAE1D,gBAAc,cAAc,wBAAwB;AAGpD,EAAAG,WAAU,cAAc,EAAE,WAAW,KAAK,CAAC;AAE3C,QAAM,WAAW,sBAAsB,GAAG;AAE1C,WAAS,WAAW,gBAAgB,IAAI;AAAA,IACtC,GAAG;AAAA,IACH,UAAU;AAAA,EACZ;AAEA,EAAAC,eAAc,cAAc,KAAK,UAAU,UAAU,MAAM,CAAC,GAAG,EAAE,UAAU,QAAQ,CAAC;AACtF;AAGO,SAAS,qBACd,KACA,kBAC0B;AAC1B,QAAM,WAAW,sBAAsB,GAAG;AAC1C,QAAM,QAAQ,SAAS,WAAW,gBAAgB;AAClD,MAAI,CAAC,MAAO,QAAO;AAGnB,SAAO;AAAA,IACL,QAAQ,MAAM;AAAA,IACd,WAAW,MAAM;AAAA,IACjB,WAAW,MAAM;AAAA,IACjB,UAAU,MAAM;AAAA,EAClB;AACF;AAYO,SAAS,wBAAwB,QAAmC;AACzE,QAAM,SAAS,KAAK,UAAU;AAAA,IAC5B,OAAO;AAAA,IACP,OAAO;AAAA,IACP,WAAW,OAAO;AAAA,IAClB,QAAQ,OAAO;AAAA,IACf,kBAAkB,OAAO;AAAA,IACzB,gBAAgB,OAAO;AAAA,IACvB,cAAc,OAAO;AAAA,IACrB,OAAO,OAAO;AAAA,EAChB,CAAC;AACD,UAAQ,OAAO,MAAM,2BAA2B,MAAM;AAAA,CAAI;AAC5D;AAgBO,SAAS,6BAA6BC,SAAyB;AACpE,EAAAA,QAAO;AAAA,IACL;AAAA,IACA;AAAA,IAGA;AAAA,MACE,KAAKC,IAAE,OAAO,EAAE,SAAS,EAAE,SAAS,oDAAoD;AAAA,IAC1F;AAAA,IACA,OAAO,EAAE,KAAK,SAAS,MAAM;AAC3B,YAAM,MAAM,YAAY,QAAQ,IAAI;AAGpC,UAAI;AACJ,UAAI;AACF,cAAM,OAAO,iBAAiB,GAAG;AACjC,oBAAY,KAAK;AAAA,MACnB,SAAS,KAAK;AACZ,cAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM,KAAK,UAAU;AAAA,gBACnB,OAAO;AAAA,gBACP,SAAS,8BAA8B,GAAG;AAAA,cAC5C,CAAC;AAAA,YACH;AAAA,UACF;AAAA,UACA,SAAS;AAAA,QACX;AAAA,MACF;AAGA,UAAI;AACJ,UAAI;AACF,mBAAW,sBAAsB,GAAG;AAAA,MACtC,SAAS,KAAK;AACZ,cAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM,KAAK,UAAU;AAAA,gBACnB,OAAO;AAAA,gBACP,SAAS,mCAAmC,GAAG;AAAA,cACjD,CAAC;AAAA,YACH;AAAA,UACF;AAAA,UACA,SAAS;AAAA,QACX;AAAA,MACF;AAGA,YAAM,gBAAgBN,MAAK,KAAK,aAAa;AAC7C,UAAI,gBAA0B,CAAC;AAC/B,UAAI;AACF,YAAIC,YAAW,aAAa,GAAG;AAC7B,0BAAgB,YAAY,aAAa,EAAE;AAAA,YACzC,CAAC,MAAM,EAAE,SAAS,OAAO,KAAK,MAAM;AAAA,UACtC;AAAA,QACF;AAAA,MACF,QAAQ;AAAA,MAER;AAGA,YAAM,UAAwC,CAAC;AAC/C,UAAI,aAAa;AAEjB,iBAAW,YAAY,eAAe;AACpC,cAAM,WAAWD,MAAK,eAAe,QAAQ;AAG7C,YAAI;AACF,wBAAc,UAAU,YAAY,QAAQ,EAAE;AAAA,QAChD,QAAQ;AACN,kBAAQ,KAAK;AAAA,YACX;AAAA,YACA,UAAU;AAAA,YACV,OAAO;AAAA,UACT,CAAC;AACD,uBAAa;AACb;AAAA,QACF;AAGA,YAAI;AACJ,YAAI;AACF,0BAAgBE,cAAa,QAAQ;AAAA,QACvC,SAAS,KAAK;AACZ,gBAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,kBAAQ,KAAK;AAAA,YACX;AAAA,YACA,UAAU;AAAA,YACV,OAAO,yBAAyB,GAAG;AAAA,UACrC,CAAC;AACD,uBAAa;AACb;AAAA,QACF;AAGA,cAAM,QAAQ,SAAS,WAAW,QAAQ;AAC1C,YAAI,CAAC,OAAO;AACV,kBAAQ,KAAK;AAAA,YACX;AAAA,YACA,UAAU;AAAA,YACV,OAAO;AAAA,UACT,CAAC;AACD,uBAAa;AACb;AAAA,QACF;AAGA,cAAM,MAAyB;AAAA,UAC7B,QAAQ,MAAM;AAAA,UACd,WAAW,MAAM;AAAA,UACjB,WAAW,MAAM;AAAA,UACjB,UAAU,MAAM;AAAA,QAClB;AAEA,cAAM,WAAW,eAAe,eAAe,KAAK,SAAS;AAE7D,YAAI,CAAC,UAAU;AACb,gBAAM,eAAe,cAAc,aAAa;AAChD,kCAAwB;AAAA,YACtB,kBAAkB;AAAA,YAClB,gBAAgB,IAAI;AAAA,YACpB;AAAA,YACA,OAAO,MAAM,YAAY;AAAA,YACzB,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,YAClC,QAAQ;AAAA,UACV,CAAC;AAED,kBAAQ,KAAK;AAAA,YACX;AAAA,YACA,UAAU;AAAA,YACV,OAAO;AAAA,YACP,UAAU,MAAM;AAAA,YAChB,UAAU,MAAM;AAAA,UAClB,CAAC;AACD,uBAAa;AAAA,QACf,OAAO;AACL,kBAAQ,KAAK;AAAA,YACX;AAAA,YACA,UAAU;AAAA,YACV,UAAU,MAAM;AAAA,YAChB,UAAU,MAAM;AAAA,UAClB,CAAC;AAAA,QACH;AAAA,MACF;AAGA,iBAAW,oBAAoB,OAAO,KAAK,SAAS,UAAU,GAAG;AAC/D,YAAI,CAAC,cAAc,SAAS,gBAAgB,GAAG;AAC7C,kBAAQ,KAAK;AAAA,YACX,UAAU;AAAA,YACV,UAAU;AAAA,YACV,OAAO;AAAA,UACT,CAAC;AACD,uBAAa;AAAA,QACf;AAAA,MACF;AAEA,YAAM,gBAAgB,QAAQ,OAAO,CAAC,MAAM,EAAE,QAAQ,EAAE;AACxD,YAAM,cAAc,QAAQ,OAAO,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE;AAEvD,aAAO;AAAA,QACL,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM,KAAK,UAAU;AAAA,cACnB,gBAAgB,cAAc;AAAA,cAC9B;AAAA,cACA;AAAA,cACA;AAAA,cACA,GAAI,aACA;AAAA,gBACE,OACE;AAAA,cAEJ,IACA,CAAC;AAAA,YACP,CAAC;AAAA,UACH;AAAA,QACF;AAAA,QACA,SAAS;AAAA,MACX;AAAA,IACF;AAAA,EACF;AACF;;;ADtiBA,SAAS,oBAAoB,wBAAwB;AAOrD,IAAM,cAAc;AAAA,EAClB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAIA,IAAM,qBAAsD;AAAA,EAC1D,UAAU,CAAC;AAAA,EACX,OAAO,CAAC,UAAU;AAAA,EAClB,KAAK,CAAC;AAAA,EACN,MAAM,CAAC,KAAK;AAAA,EACZ,KAAK,CAAC,MAAM;AAAA;AAAA;AAAA,EAGZ,UAAU,CAAC;AAAA;AAAA;AAAA;AAAA,EAIX,UAAU,CAAC,OAAO,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA,EAK5B,OAAO,CAAC,YAAY,SAAS,QAAQ,UAAU;AAAA,EAC/C,WAAW,CAAC,YAAY,SAAS,QAAQ,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA,EAKnD,MAAM,CAAC,SAAS,aAAa,YAAY,KAAK;AAAA;AAAA;AAAA,EAG9C,QAAQ,CAAC,MAAM;AACjB;AAGA,IAAM,iBAAwC;AAAA,EAC5C,UAAU;AAAA,EACV,OAAO;AAAA,EACP,KAAK;AAAA,EACL,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,WAAW;AAAA,EACX,UAAU;AAAA,EACV,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,KAAK;AACP;AAGA,IAAMK,kBAAwC;AAAA,EAC5C,UAAU;AAAA,EACV,OAAO;AAAA,EACP,KAAK;AAAA,EACL,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,WAAW;AAAA,EACX,UAAU;AAAA,EACV,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,KAAK;AACP;AA2BA,SAAS,aAAa,OAA+B;AACnD,SAAQ,YAAkC,SAAS,KAAK;AAC1D;AAEA,SAAS,qBAAkC;AACzC,SAAO;AAAA,IACL,oBAAoB;AAAA,IACpB,UAAU;AAAA,IACV,UAAU;AAAA,IACV,iBAAiB;AAAA,IACjB,YAAY;AAAA,EACd;AACF;AAEA,SAAS,qBAAoC;AAC3C,QAAM,OAAM,oBAAI,KAAK,GAAE,YAAY;AACnC,QAAM,SAAsC,CAAC;AAC7C,aAAW,KAAK,aAAa;AAC3B,WAAO,CAAC,IAAI,mBAAmB;AAAA,EACjC;AACA,SAAO;AAAA,IACL,SAAS;AAAA,IACT,cAAc,YAAY,CAAC;AAAA,IAC3B,QAAQ;AAAA,IACR;AAAA,IACA,WAAW;AAAA,IACX,WAAW;AAAA,EACb;AACF;AAEA,SAAS,UAAU,KAAqB;AACtC,SAAOC,MAAK,KAAK,gBAAgB,qBAAqB;AACxD;AAEA,SAAS,UAAU,KAA4B;AAC7C,QAAM,IAAI,UAAU,GAAG;AACvB,MAAI,CAACC,YAAW,CAAC,EAAG,QAAO,mBAAmB;AAC9C,QAAM,MAAM,KAAK,MAAM,aAAa,CAAC,CAAC;AAEtC,MAAI,OAAO,QAAQ,YAAY,QAAQ,QAAQ,IAAI,YAAY,OAAO;AACpE,WAAO,mBAAmB;AAAA,EAC5B;AACA,SAAO;AACT;AAMA,SAAS,cAAc,UAAkB,SAAuB;AAC9D,MAAIA,YAAW,QAAQ,GAAG;AACxB,UAAM,OAAOC,WAAU,QAAQ;AAC/B,QAAI,KAAK,eAAe,GAAG;AACzB,YAAM,IAAI,MAAM,iCAAiC,QAAQ,EAAE;AAAA,IAC7D;AAAA,EACF;AACA,EAAAC,eAAc,UAAU,OAAO;AACjC;AAMA,SAAS,aAAa,UAA0B;AAC9C,MAAIF,YAAW,QAAQ,GAAG;AACxB,UAAM,OAAOC,WAAU,QAAQ;AAC/B,QAAI,KAAK,eAAe,GAAG;AACzB,YAAM,IAAI,MAAM,6BAA6B,QAAQ,EAAE;AAAA,IACzD;AAAA,EACF;AACA,SAAOE,cAAa,UAAU,OAAO;AACvC;AAEA,SAAS,WAAW,KAAa,OAA4B;AAC3D,QAAM,MAAMJ,MAAK,KAAK,cAAc;AACpC,EAAAK,WAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AAClC,QAAM,aAAY,oBAAI,KAAK,GAAE,YAAY;AACzC,gBAAc,UAAU,GAAG,GAAG,KAAK,UAAU,OAAO,MAAM,CAAC,IAAI,IAAI;AACrE;AAGA,SAAS,wBAAwB,MAAuB;AACtD,MAAI,UAAU;AAEd,YAAU,QAAQ,QAAQ,qBAAqB,EAAE;AACjD,YAAU,QAAQ,QAAQ,aAAa,EAAE;AAGzC,QAAM,aAAa,QAAQ,QAAQ,GAAG;AACtC,MAAI,eAAe,GAAI,OAAM,IAAI,MAAM,kCAAkC;AACzE,YAAU,QAAQ,UAAU,UAAU;AAEtC,QAAM,YAAY,QAAQ,YAAY,GAAG;AACzC,MAAI,cAAc,GAAI,OAAM,IAAI,MAAM,kCAAkC;AACxE,YAAU,QAAQ,UAAU,GAAG,YAAY,CAAC;AAG5C,YAAU,QAAQ,QAAQ,gBAAgB,IAAI;AAC9C,SAAO,KAAK,MAAM,OAAO;AAC3B;AAMO,SAAS,uBAAuB,MAAmD;AACxF,QAAM,MAAM,QAAQ,QAAQ,IAAI;AAChC,MAAI;AACF,UAAM,QAAQ,UAAU,GAAG;AAG3B,UAAM,UAAUL,MAAK,KAAK,gBAAgB,oBAAoB;AAC9D,QAAI,CAACC,YAAW,OAAO,GAAG;AACxB,UAAI;AACF,cAAM,EAAE,YAAY,IAAI,iBAAiB,GAAG;AAE5C,QAAC,MAA6C,uBAAuB,IAAI;AACzE,mBAAW,KAAK,KAAK;AAAA,MACvB,QAAQ;AAAA,MAER;AAAA,IACF;AAEA,WAAO,EAAE,MAAM,KAAK,UAAU,KAAK,GAAG,SAAS,MAAM;AAAA,EACvD,SAAS,KAAK;AACZ,WAAO,EAAE,MAAM,KAAK,UAAU,EAAE,OAAO,MAAM,SAAS,OAAO,GAAG,EAAE,CAAC,GAAG,SAAS,KAAK;AAAA,EACtF;AACF;AAWO,SAAS,uBAAuB,OAGrC;AACA,QAAM,MAAM,MAAM,QAAQ,QAAQ,IAAI;AAGtC,MAAI,MAAM,SAAS,CAAC,aAAa,MAAM,KAAK,GAAG;AAC7C,WAAO;AAAA,MACL,MAAM,KAAK,UAAU;AAAA,QACnB,OAAO;AAAA,QACP,SAAS,kBAAkB,MAAM,KAAK,uBAAuB,YAAY,KAAK,IAAI,CAAC;AAAA,MACrF,CAAC;AAAA,MACD,SAAS;AAAA,IACX;AAAA,EACF;AAGA,QAAM,eAAe,CAAC,sBAAsB,YAAY,YAAY,iBAAiB;AACrF,MAAI,MAAM,SAAS,CAAC,aAAa,SAAS,MAAM,KAAsC,GAAG;AACvF,WAAO;AAAA,MACL,MAAM,KAAK,UAAU;AAAA,QACnB,OAAO;AAAA,QACP,SAAS,kBAAkB,MAAM,KAAK,uBAAuB,aAAa,KAAK,IAAI,CAAC;AAAA,MACtF,CAAC;AAAA,MACD,SAAS;AAAA,IACX;AAAA,EACF;AAEA,MAAI;AACF,UAAM,QAAQ,UAAU,GAAG;AAG3B,QAAI,MAAM,QAAQ;AAChB,YAAM,SAAS,MAAM;AAAA,IACvB;AAGA,QAAI,MAAM,OAAO;AACf,YAAM,QAAQ,MAAM;AACpB,UAAI,CAAC,MAAM,OAAO,KAAK,GAAG;AACxB,cAAM,OAAO,KAAK,IAAI,mBAAmB;AAAA,MAC3C;AACA,YAAM,aAAa,MAAM,OAAO,KAAK;AAErC,UAAI,MAAM,SAAS,MAAM,UAAU,QAAW;AAC5C,mBAAW,MAAM,KAAK,IAAI,MAAM;AAAA,MAClC;AAEA,UAAI,MAAM,gBAAgB;AACxB,mBAAW,cAAc;AAAA,MAC3B;AAEA,YAAM,eAAe;AAAA,IACvB;AAEA,eAAW,KAAK,KAAK;AACrB,WAAO,EAAE,MAAM,KAAK,UAAU,KAAK,GAAG,SAAS,MAAM;AAAA,EACvD,SAAS,KAAK;AACZ,WAAO,EAAE,MAAM,KAAK,UAAU,EAAE,OAAO,MAAM,SAAS,OAAO,GAAG,EAAE,CAAC,GAAG,SAAS,KAAK;AAAA,EACtF;AACF;AAEO,SAAS,0BACd,MACA,OACoC;AACpC,QAAM,MAAM,QAAQ,QAAQ,IAAI;AAEhC,MAAI,OAAO;AACT,QAAI,CAAC,aAAa,KAAK,GAAG;AACxB,aAAO;AAAA,QACL,MAAM,KAAK,UAAU;AAAA,UACnB,OAAO;AAAA,UACP,SAAS,kBAAkB,KAAK,uBAAuB,YAAY,KAAK,IAAI,CAAC;AAAA,QAC/E,CAAC;AAAA,QACD,SAAS;AAAA,MACX;AAAA,IACF;AACA,UAAM,aAAaD,MAAK,KAAK,gBAAgB,WAAW,GAAG,KAAK,OAAO;AACvE,QAAI,CAACC,YAAW,UAAU,GAAG;AAC3B,aAAO;AAAA,QACL,MAAM,KAAK,UAAU,EAAE,OAAO,OAAO,OAAO,QAAQ,wBAAwB,CAAC;AAAA,QAC7E,SAAS;AAAA,MACX;AAAA,IACF;AACA,QAAI;AACF,YAAM,MAAM,aAAa,UAAU;AACnC,YAAM,SAAS,KAAK,MAAM,GAAG;AAC7B,UACE,OAAO,OAAO,SAAS,MAAM,YAC7B,OAAO,OAAO,OAAO,MAAM,YAC3B,OAAO,OAAO,SAAS,MAAM,YAC7B,OAAO,SAAS,MAAM,MACtB;AACA,eAAO;AAAA,UACL,MAAM,KAAK,UAAU,EAAE,OAAO,OAAO,OAAO,QAAQ,2BAA2B,CAAC;AAAA,UAChF,SAAS;AAAA,QACX;AAAA,MACF;AACA,aAAO,EAAE,MAAM,KAAK,UAAU,EAAE,OAAO,MAAM,MAAM,CAAC,GAAG,SAAS,MAAM;AAAA,IACxE,QAAQ;AACN,aAAO;AAAA,QACL,MAAM,KAAK,UAAU,EAAE,OAAO,OAAO,OAAO,QAAQ,kCAAkC,CAAC;AAAA,QACvF,SAAS;AAAA,MACX;AAAA,IACF;AAAA,EACF;AAEA,MAAI;AACF,UAAM,aAAaD,MAAK,KAAK,gBAAgB,SAAS;AACtD,UAAM,iBAA2B,CAAC;AAClC,UAAM,gBAA0B,CAAC;AAEjC,eAAWM,UAAS,aAAa;AAC/B,YAAM,aAAaN,MAAK,YAAY,GAAGM,MAAK,OAAO;AACnD,UAAIL,YAAW,UAAU,GAAG;AAE1B,YAAI;AACF,gBAAM,MAAM,aAAa,UAAU;AACnC,gBAAM,SAAS,KAAK,MAAM,GAAG;AAG7B,cACE,OAAO,OAAO,SAAS,MAAM,YAC7B,OAAO,OAAO,OAAO,MAAM,YAC3B,OAAO,OAAO,SAAS,MAAM,YAC7B,OAAO,SAAS,MAAM,MACtB;AAEA,0BAAc,KAAKK,MAAK;AACxB;AAAA,UACF;AAEA,yBAAe,KAAKA,MAAK;AAAA,QAC3B,QAAQ;AAEN,wBAAc,KAAKA,MAAK;AAAA,QAC1B;AAAA,MACF,OAAO;AACL,sBAAc,KAAKA,MAAK;AAAA,MAC1B;AAAA,IACF;AAEA,WAAO;AAAA,MACL,MAAM,KAAK,UAAU;AAAA,QACnB,OAAO,cAAc,WAAW;AAAA,QAChC;AAAA,QACA;AAAA,QACA,aAAa,YAAY;AAAA,MAC3B,CAAC;AAAA,MACD,SAAS;AAAA,IACX;AAAA,EACF,SAAS,KAAK;AACZ,WAAO,EAAE,MAAM,KAAK,UAAU,EAAE,OAAO,MAAM,SAAS,OAAO,GAAG,EAAE,CAAC,GAAG,SAAS,KAAK;AAAA,EACtF;AACF;AAeO,SAAS,qBAAqB,MAAmD;AACtF,QAAM,MAAM,QAAQ,QAAQ,IAAI;AAChC,MAAI;AACF,UAAM,QAAQ,UAAU,GAAG;AAE3B,UAAM,YAAsB,CAAC;AAC7B,UAAM,QAAkB,CAAC;AACzB,UAAM,UAAoB,CAAC;AAE3B,eAAW,SAAS,aAAa;AAC/B,YAAM,KAAK,MAAM,OAAO,KAAK;AAC7B,UAAI,IAAI,UAAU;AAChB,kBAAU,KAAK,KAAK;AACpB;AAAA,MACF;AAEA,YAAM,OAAO,mBAAmB,KAAK;AACrC,YAAM,YAAY,KAAK,OAAO,CAAC,QAAQ,CAAC,MAAM,OAAO,GAAG,GAAG,QAAQ;AACnE,UAAI,UAAU,WAAW,GAAG;AAC1B,cAAM,KAAK,KAAK;AAAA,MAClB,OAAO;AACL,gBAAQ,KAAK,KAAK;AAAA,MACpB;AAAA,IACF;AAEA,WAAO;AAAA,MACL,MAAM,KAAK,UAAU;AAAA,QACnB,aAAa;AAAA,QACb,iBAAiB;AAAA,QACjB,eAAe;AAAA,QACf,UAAU,MAAM;AAAA,QAChB,aAAa,MAAM,WAAW,KAAK,QAAQ,WAAW;AAAA,MACxD,CAAC;AAAA,MACD,SAAS;AAAA,IACX;AAAA,EACF,SAAS,KAAK;AACZ,UAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,WAAO,EAAE,MAAM,KAAK,UAAU,EAAE,OAAO,MAAM,QAAQ,CAAC,GAAG,SAAS,KAAK;AAAA,EACzE;AACF;AAEO,SAAS,oBAAoB,MAAmD;AACrF,QAAM,MAAM,QAAQ,QAAQ,IAAI;AAChC,MAAI;AACF,UAAM,eAAeN,MAAK,KAAK,gBAAgB,WAAW;AAG1D,QAAI,WAA4D;AAChE,QAAI;AACF,iBAAW,sBAAsB,GAAG;AAAA,IACtC,QAAQ;AAAA,IAER;AAEA,UAAM,YAOD,CAAC;AACN,QAAI,iBAAiB;AAErB,eAAW,SAAS,aAAa;AAC/B,YAAM,eAAe,eAAe,KAAK;AACzC,YAAM,WAAWA,MAAK,cAAc,YAAY;AAChD,YAAM,SAASC,YAAW,QAAQ;AAClC,UAAI,OAAQ;AAGZ,UAAI,SAAS;AACb,UAAI,iBAAiC;AAErC,UAAI,UAAU,UAAU;AACtB,cAAM,QAAQ,SAAS,WAAW,YAAY;AAC9C,YAAI,OAAO;AACT,mBAAS;AAET,cAAI;AACF,kBAAM,WAAW,OAAO,KAAK,aAAa,QAAQ,GAAG,OAAO;AAC5D,kBAAM,EAAE,UAAU,IAAI,iBAAiB,GAAG;AAC1C,6BAAiB,eAAe,UAAU,OAAO,SAAS;AAAA,UAC5D,QAAQ;AACN,6BAAiB;AAAA,UACnB;AAAA,QACF;AAAA,MACF;AAEA,gBAAU,KAAK,EAAE,OAAO,cAAc,QAAQ,MAAM,UAAU,QAAQ,eAAe,CAAC;AAAA,IACxF;AAEA,WAAO;AAAA,MACL,MAAM,KAAK,UAAU,EAAE,WAAW,gBAAgB,YAAY,YAAY,OAAO,CAAC;AAAA,MAClF,SAAS;AAAA,IACX;AAAA,EACF,SAAS,KAAK;AACZ,WAAO,EAAE,MAAM,KAAK,UAAU,EAAE,OAAO,MAAM,SAAS,OAAO,GAAG,EAAE,CAAC,GAAG,SAAS,KAAK;AAAA,EACtF;AACF;AAQO,SAAS,0BAA0B,OAGxC;AACA,QAAM,MAAM,MAAM,QAAQ,QAAQ,IAAI;AACtC,QAAM,EAAE,OAAO,aAAa,IAAI;AAEhC,MAAI,CAAC,aAAa,KAAK,GAAG;AACxB,WAAO;AAAA,MACL,MAAM,KAAK,UAAU,EAAE,OAAO,MAAM,SAAS,kBAAkB,KAAK,GAAG,CAAC;AAAA,MACxE,SAAS;AAAA,IACX;AAAA,EACF;AAEA,MAAI;AACF,UAAM,YAAY,0BAA0B,YAAY;AAGxD,QAAI,mBAGA;AAAA,MACF,cAAc,CAAC;AAAA,MACf,aAAa,CAAC;AAAA,IAChB;AACA,QAAI;AACF,YAAM,aAAa,wBAAwB,YAAY;AACvD,UAAI,WAAW,oBAAoB,OAAO,WAAW,qBAAqB,UAAU;AAClF,cAAM,KAAK,WAAW;AACtB,2BAAmB;AAAA,UACjB,cAAe,GAAG,gBAA2C,CAAC;AAAA,UAC9D,aAAc,GAAG,eAA0C,CAAC;AAAA,QAC9D;AAAA,MACF;AAAA,IACF,QAAQ;AAAA,IAER;AAEA,UAAM,eAAeD,MAAK,KAAK,gBAAgB,WAAW;AAC1D,IAAAK,WAAU,cAAc,EAAE,WAAW,KAAK,CAAC;AAC3C,UAAM,WAAWL,MAAK,cAAc,GAAG,KAAK,OAAO;AAEnD,UAAM,UAAU;AAAA,MACd,SAAS;AAAA,MACT;AAAA,MACA,OAAOD,gBAAe,KAAK;AAAA,MAC3B,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,MACpC;AAAA,MACA;AAAA,IACF;AAEA,kBAAc,UAAU,KAAK,UAAU,SAAS,MAAM,CAAC,IAAI,IAAI;AAG/D,UAAM,QAAQ,UAAU,GAAG;AAC3B,QAAI,CAAC,MAAM,OAAO,KAAK,EAAG,OAAM,OAAO,KAAK,IAAI,mBAAmB;AACnE,UAAM,KAAK,MAAM,OAAO,KAAK;AAC7B,OAAG,qBAAqB;AACxB,eAAW,KAAK,KAAK;AAErB,WAAO;AAAA,MACL,MAAM,KAAK,UAAU;AAAA,QACnB,SAAS;AAAA,QACT;AAAA,QACA,eAAe,UAAU;AAAA,QACzB;AAAA,QACA,MAAM;AAAA,MACR,CAAC;AAAA,MACD,SAAS;AAAA,IACX;AAAA,EACF,SAAS,KAAK;AACZ,UAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,WAAO,EAAE,MAAM,KAAK,UAAU,EAAE,OAAO,MAAM,OAAO,QAAQ,CAAC,GAAG,SAAS,KAAK;AAAA,EAChF;AACF;AAOO,SAAS,4BAA4B,OAG1C;AACA,QAAM,MAAM,MAAM,QAAQ,QAAQ,IAAI;AACtC,QAAM,EAAE,MAAM,IAAI;AAElB,MAAI,CAAC,aAAa,KAAK,GAAG;AACxB,WAAO;AAAA,MACL,MAAM,KAAK,UAAU,EAAE,OAAO,MAAM,SAAS,kBAAkB,KAAK,GAAG,CAAC;AAAA,MACxE,SAAS;AAAA,IACX;AAAA,EACF;AAEA,MAAI;AAEF,UAAM,cAAcC,MAAK,KAAK,gBAAgB,WAAW,GAAG,KAAK,OAAO;AACxE,QAAI,UAAmB,CAAC;AACxB,QAAIC,YAAW,WAAW,GAAG;AAC3B,gBAAU,KAAK,MAAM,aAAa,WAAW,CAAC;AAAA,IAChD;AAGA,QAAI,mBAAmB;AACvB,UAAM,mBAAmBD,MAAK,KAAK,gBAAgB,oBAAoB;AACvE,QAAIC,YAAW,gBAAgB,GAAG;AAChC,UAAI;AACF,cAAM,QAAQ,KAAK,MAAM,aAAa,gBAAgB,CAAC;AACvD,YAAI,OAAO,MAAM,iBAAiB,YAAY,MAAM,aAAa,KAAK,EAAE,SAAS,GAAG;AAClF,6BAAmB,MAAM,aAAa,KAAK;AAAA,QAC7C;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF;AAGA,UAAM,OAAO,mBAAmB,KAAK;AACrC,UAAM,mBAA6B,CAAC;AACpC,UAAM,sBAAgC,CAAC;AAEvC,eAAW,OAAO,MAAM;AACtB,YAAM,eAAe,eAAe,GAAG;AACvC,YAAM,eAAeD,MAAK,KAAK,gBAAgB,aAAa,YAAY;AACxE,UAAIC,YAAW,YAAY,GAAG;AAC5B,cAAM,aAAa,aAAa,YAAY;AAC5C,cAAM,WAAW,OAAO,KAAK,YAAY,OAAO;AAChD,cAAM,UAAU,KAAK,MAAM,UAAU;AAKrC,YAAI,oBAAoB;AACxB,YAAI,qBAAqB;AAEzB,YAAI;AACF,gBAAM,MAAM,qBAAqB,KAAK,YAAY;AAClD,cAAI,KAAK;AACP,iCAAqB;AACrB,kBAAM,EAAE,UAAU,IAAI,iBAAiB,GAAG;AAC1C,gCAAoB,eAAe,UAAU,KAAK,SAAS;AAE3D,gBAAI,CAAC,mBAAmB;AAEtB,oBAAM,eAAeM,YAAW,QAAQ,EAAE,OAAO,QAAQ,EAAE,OAAO,KAAK;AACvE,sCAAwB;AAAA,gBACtB,kBAAkB;AAAA,gBAClB,gBAAgB,IAAI;AAAA,gBACpB;AAAA,gBACA,OAAO;AAAA,gBACP,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,gBAClC,QAAQ;AAAA,cACV,CAAC;AAED,kCAAoB,KAAK,GAAG;AAC5B,+BAAiB;AAAA,gBACf,IAAI,YAAY;AAAA;AAAA,cAClB;AACA;AAAA,YACF;AAAA,UACF;AAAA,QACF,QAAQ;AAAA,QAER;AAKA,cAAM,gBAAgBR,gBAAe,GAAG;AACxC,cAAM,gBAAgB,QAAQ,aAAa;AAC3C,cAAM,kBAAkB,eAAe,QAAQ,iBAAiB,EAAE;AAElE,YAAI,CAAC,eAAe;AAClB,8BAAoB,KAAK,GAAG;AAC5B,2BAAiB;AAAA,YACf,IAAI,YAAY;AAAA;AAAA,UAClB;AAAA,QACF,WAAW,oBAAoB,eAAe;AAC5C,8BAAoB,KAAK,GAAG;AAC5B,2BAAiB;AAAA,YACf,IAAI,YAAY;AAAA,wDAA6D,aAAa,mBAAmB,aAAa;AAAA,UAC5H;AAAA,QACF,OAAO;AACL,gBAAM,YAAY,qBACd,oBACE,0BACA,+BACF;AACJ,2BAAiB;AAAA,YACf,IAAI,YAAY,IAAI,SAAS;AAAA,EAAM,KAAK,UAAU,SAAS,MAAM,CAAC,CAAC;AAAA,UACrE;AAAA,QACF;AAAA,MACF,OAAO;AACL,4BAAoB,KAAK,GAAG;AAC5B,yBAAiB,KAAK,IAAI,YAAY;AAAA,oBAAyB;AAAA,MACjE;AAAA,IACF;AAGA,UAAM,QAAkB,CAAC;AAEzB,QAAI,kBAAkB;AACpB,YAAM,KAAK,kBAAkB,kBAAkB,EAAE;AAAA,IACnD;AAEA,UAAM,KAAK,YAAY,KAAK,UAAU,SAAS,MAAM,CAAC,CAAC;AAEvD,QAAI,iBAAiB,SAAS,GAAG;AAC/B,YAAM,KAAK,IAAI,uBAAuB,IAAI,GAAG,gBAAgB;AAAA,IAC/D;AAIA,UAAM,iBAAiB,sBAAsB,KAAK;AAClD,UAAM,KAAK,IAAI,2BAA2B;AAC1C,UAAM,KAAK,cAAc;AAEzB,UAAM,KAAK,IAAI,kEAAkE;AAEjF,UAAM,SAAS,MAAM,KAAK,IAAI;AAC9B,UAAM,wBAAwB,oBAAoB,WAAW;AAE7D,WAAO;AAAA,MACL,MAAM,KAAK,UAAU;AAAA,QACnB,WAAWA,gBAAe,KAAK;AAAA,QAC/B;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAAA,MACD,SAAS;AAAA,IACX;AAAA,EACF,SAAS,KAAK;AACZ,UAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,WAAO,EAAE,MAAM,KAAK,UAAU,EAAE,OAAO,MAAM,OAAO,QAAQ,CAAC,GAAG,SAAS,KAAK;AAAA,EAChF;AACF;AASA,IAAM,sBAAiE;AAAA,EACrE;AAAA,IACE,SAAS;AAAA,IACT,OAAO;AAAA,EACT;AAAA,EACA,EAAE,SAAS,oBAAoB,OAAO,mBAAmB;AAAA,EACzD,EAAE,SAAS,iDAAiD,OAAO,mBAAmB;AAAA,EACtF,EAAE,SAAS,kBAAkB,OAAO,iBAAiB;AAAA,EACrD,EAAE,SAAS,eAAe,OAAO,cAAc;AAAA,EAC/C,EAAE,SAAS,QAAQ,OAAO,UAAU;AAAA,EACpC,EAAE,SAAS,iBAAiB,OAAO,aAAa;AAAA,EAChD,EAAE,SAAS,kCAAkC,OAAO,sBAAsB;AAC5E;AAgBA,IAAM,sBAA+C;AAAA,EACnD,UAAU,CAAC,kBAAkB,iBAAiB;AAAA,EAC9C,OAAO,CAAC,QAAQ;AAAA,EAChB,KAAK,CAAC,YAAY,WAAW,aAAa;AAAA,EAC1C,MAAM,CAAC,WAAW,aAAa;AAAA,EAC/B,MAAM,CAAC,WAAW,eAAe,YAAY,aAAa;AAAA,EAC1D,OAAO,CAAC,WAAW,aAAa;AAAA,EAChC,WAAW,CAAC,WAAW,aAAa;AAAA,EACpC,UAAU,CAAC,WAAW,aAAa;AAAA,EACnC,UAAU,CAAC,WAAW,eAAe,OAAO;AAAA,EAC5C,QAAQ,CAAC,WAAW,aAAa;AAAA,EACjC,KAAK,CAAC,WAAW,eAAe,gBAAgB;AAClD;AAWA,IAAM,wBAA+C;AAAA,EACnD,UAAU,KAAK;AAAA,IACb;AAAA,MACE,SAAS;AAAA,MACT,aAAa;AAAA,MACb,aAAa;AAAA,QACX,MAAM;AAAA,QACN,aAAa;AAAA,QACb,SAAS;AAAA,QACT,eAAe;AAAA,QACf,aAAa;AAAA,MACf;AAAA,MACA,gBAAgB;AAAA,QACd,WAAW;AAAA,QACX,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,EAAE,EAAE;AAAA,QAC9D,gBAAgB,EAAE,SAAS,WAAW,QAAQ,UAAU;AAAA,QACxD,YAAY;AAAA,UACV,UAAU;AAAA,UACV,aAAa;AAAA,UACb,UAAU;AAAA,UACV,YAAY;AAAA,UACZ,YAAY;AAAA,QACd;AAAA,QACA,eAAe;AAAA,QACf,cAAc;AAAA,QACd,iBAAiB;AAAA,MACnB;AAAA,MACA,iBAAiB;AAAA,QACf,OAAO;AAAA,UACL,YAAY;AAAA,UACZ,YAAY;AAAA,UACZ,SAAS;AAAA,UACT,SAAS;AAAA,UACT,QAAQ;AAAA,QACV;AAAA,QACA,MAAM;AAAA,UACJ,YAAY;AAAA,UACZ,YAAY;AAAA,UACZ,SAAS;AAAA,UACT,SAAS;AAAA,UACT,QAAQ;AAAA,QACV;AAAA,MACF;AAAA,MACA,YAAY;AAAA,MACZ,kBAAkB,CAAC;AAAA,IACrB;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EAEA,OAAO,KAAK;AAAA,IACV;AAAA,MACE,SAAS;AAAA,MACT,aAAa;AAAA,MACb,kBAAkB;AAAA,MAClB,aAAa;AAAA,MACb,QAAQ;AAAA,QACN,QAAQ,EAAE,eAAe,WAAW,YAAY,UAAU;AAAA,QAC1D,SAAS,EAAE,aAAa,OAAO,aAAa,OAAO;AAAA,QACnD,YAAY,EAAE,aAAa,SAAS,WAAW,OAAO;AAAA,QACtD,OAAO,EAAE,aAAa,OAAO,aAAa,MAAM;AAAA,QAChD,SAAS,EAAE,aAAa,6BAA6B;AAAA,MACvD;AAAA,MACA,cAAc;AAAA,QACZ,gBAAgB;AAAA,QAChB,gBAAgB;AAAA,QAChB,aAAa;AAAA,QACb,wBAAwB;AAAA,QACxB,aAAa;AAAA,QACb,YAAY;AAAA,MACd;AAAA,MACA,MAAM,EAAE,gBAAgB,kBAAkB,gBAAgB,cAAc;AAAA,IAC1E;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EAEA,KAAK,KAAK;AAAA,IACR;AAAA,MACE,SAAS;AAAA,MACT,aAAa;AAAA,MACb,UAAU;AAAA,QACR;AAAA,UACE,MAAM;AAAA,UACN,UAAU;AAAA,UACV,QAAQ;AAAA,UACR,YAAY;AAAA,UACZ,cAAc;AAAA,QAChB;AAAA,MACF;AAAA,MACA,MAAM,EAAE,MAAM,UAAU,QAAQ,iBAAiB,QAAQ,YAAY;AAAA,MACrE,SAAS;AAAA,MACT,UAAU;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EAEA,MAAM,KAAK;AAAA,IACT;AAAA,MACE,SAAS;AAAA,MACT,aAAa;AAAA,MACb,UAAU;AAAA,MACV,WAAW;AAAA,MACX,aAAa,CAAC,EAAE,MAAM,aAAa,YAAY,IAAI,OAAO,MAAM,CAAC;AAAA,MACjE,WAAW,EAAE,UAAU,CAAC,eAAe,GAAG,UAAU,CAAC,WAAW,EAAE;AAAA,MAClE,kBAAkB,EAAE,cAAc,CAAC,GAAG,aAAa,CAAC,EAAE;AAAA,IACxD;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EAEA,KAAK,KAAK;AAAA,IACR;AAAA,MACE,SAAS;AAAA,MACT,aAAa;AAAA,MACb,gBAAgB;AAAA,QACd;AAAA,UACE,YAAY;AAAA,UACZ,UAAU;AAAA,UACV,UAAU;AAAA,UACV,YAAY;AAAA,UACZ,YAAY;AAAA,QACd;AAAA,MACF;AAAA,MACA,OAAO;AAAA,QACL;AAAA,UACE,MAAM;AAAA,UACN,MAAM;AAAA,UACN,aAAa,CAAC,SAAS;AAAA,UACvB,WAAW;AAAA,QACb;AAAA,MACF;AAAA,IACF;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EAEA,UAAU,KAAK;AAAA,IACb;AAAA,MACE,SAAS;AAAA,MACT,aAAa;AAAA,MACb,gBAAgB;AAAA,QACd,IAAI;AAAA,QACJ,OAAO;AAAA,QACP,OAAO,CAAC,oCAAoC;AAAA,QAC5C,qBAAqB,CAAC,wBAAwB;AAAA,QAC9C,UAAU,CAAC;AAAA,MACb;AAAA,IACF;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EAEA,UAAU,KAAK;AAAA,IACb;AAAA,MACE,SAAS;AAAA,MACT,aAAa;AAAA,MACb,OAAO;AAAA,QACL;AAAA,UACE,MAAM;AAAA,UACN,SAAS;AAAA,UACT,OAAO;AAAA,UACP,YAAY;AAAA,QACd;AAAA,MACF;AAAA,MACA,WAAW;AAAA,QACT;AAAA,UACE,MAAM;AAAA,UACN,QAAQ;AAAA,UACR,aAAa;AAAA,QACf;AAAA,MACF;AAAA,MACA,cAAc,CAAC,+BAA+B;AAAA,MAC9C,kBAAkB,CAAC,gBAAgB,mBAAmB,mBAAmB;AAAA,IAC3E;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EAEA,OAAO,KAAK;AAAA,IACV;AAAA,MACE,SAAS;AAAA,MACT,aAAa;AAAA,MACb,OAAO;AAAA,QACL;AAAA,UACE,MAAM;AAAA,UACN,MAAM;AAAA,UACN,YAAY;AAAA,UACZ,cAAc;AAAA,UACd,cAAc;AAAA,QAChB;AAAA,QACA;AAAA,UACE,MAAM;AAAA,UACN,MAAM;AAAA,UACN,YAAY;AAAA,UACZ,cAAc;AAAA,UACd,cAAc;AAAA,QAChB;AAAA,MACF;AAAA,IACF;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EAEA,WAAW,KAAK;AAAA,IACd;AAAA,MACE,SAAS;AAAA,MACT,aAAa;AAAA,MACb,OAAO;AAAA,QACL;AAAA,UACE,MAAM;AAAA,UACN,QAAQ;AAAA,UACR,aAAa,CAAC,aAAa,UAAU;AAAA,UACrC,MAAM;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EAEA,MAAM,KAAK;AAAA,IACT;AAAA,MACE,SAAS;AAAA,MACT,aAAa;AAAA,MACb,YAAY;AAAA,QACV,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,WAAW,CAAC,SAAS,SAAS;AAAA,QAC9B,iBAAiB;AAAA,QACjB,iBAAiB,CAAC,qBAAqB,qBAAqB;AAAA,QAC5D,cAAc;AAAA,QACd,oBAAoB;AAAA,MACtB;AAAA,IACF;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EAEA,QAAQ,KAAK;AAAA,IACX;AAAA,MACE,SAAS;AAAA,MACT,aAAa;AAAA,MACb,aAAa,EAAE,MAAM,IAAI,WAAW,KAAK;AAAA,MACzC,YAAY,EAAE,WAAW,GAAG,OAAO,CAAC,cAAc,cAAc,YAAY,EAAE;AAAA,MAC9E,gBAAgB;AAAA,IAClB;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEO,SAAS,uBAAuB,OAGrC;AACA,QAAM,MAAM,MAAM,QAAQ,QAAQ,IAAI;AACtC,QAAM,EAAE,OAAO,cAAc,UAAU,eAAe,IAAI;AAE1D,MAAI,CAAC,aAAa,KAAK,GAAG;AACxB,WAAO;AAAA,MACL,MAAM,KAAK,UAAU,EAAE,OAAO,MAAM,SAAS,kBAAkB,KAAK,GAAG,CAAC;AAAA,MACxE,SAAS;AAAA,IACX;AAAA,EACF;AAEA,MAAI;AAEJ,MAAI,gBAAgB;AAGlB,eAAW;AAAA,EACb,OAAO;AAEL,UAAM,OAAO,gBAAgB;AAG7B,eAAW,EAAE,SAAS,MAAM,KAAK,qBAAqB;AACpD,UAAI,QAAQ,KAAK,IAAI,GAAG;AACtB,cAAM,SAAgC;AAAA,UACpC,OAAO;AAAA,UACP;AAAA,UACA,WAAW;AAAA,UACX,aAAa,uCAAuC,KAAK;AAAA,QAC3D;AACA,eAAO,EAAE,MAAM,KAAK,UAAU,MAAM,GAAG,SAAS,MAAM;AAAA,MACxD;AAAA,IACF;AAGA,QAAI;AACF,iBAAW,wBAAwB,IAAI;AAAA,IACzC,QAAQ;AACN,YAAM,SAAgC;AAAA,QACpC,OAAO;AAAA,QACP;AAAA,QACA,WAAW;AAAA,QACX,aACE;AAAA,MACJ;AACA,aAAO,EAAE,MAAM,KAAK,UAAU,MAAM,GAAG,SAAS,MAAM;AAAA,IACxD;AAAA,EACF;AAGA,MAAI,CAAC,SAAS,WAAW,CAAC,SAAS,aAAa;AAC9C,UAAM,SAAgC;AAAA,MACpC,OAAO;AAAA,MACP;AAAA,MACA,WAAW;AAAA,MACX,aACE;AAAA,IACJ;AACA,WAAO,EAAE,MAAM,KAAK,UAAU,MAAM,GAAG,SAAS,MAAM;AAAA,EACxD;AAGA,QAAM,eAAe,oBAAoB,KAAK;AAC9C,QAAM,cAAc,aAAa,OAAO,CAAC,MAAM,EAAE,KAAK,SAAS;AAC/D,MAAI,YAAY,SAAS,GAAG;AAC1B,UAAM,SAAgC;AAAA,MACpC,OAAO;AAAA,MACP;AAAA,MACA,WAAW;AAAA,MACX,aAAa,QAAQ,KAAK,uCAAuC,YAAY,KAAK,IAAI,CAAC;AAAA,IACzF;AACA,WAAO,EAAE,MAAM,KAAK,UAAU,MAAM,GAAG,SAAS,MAAM;AAAA,EACxD;AAIA,QAAM,uBAKF;AAAA,IACF,UAAU,CAACS,cAAa;AAGtB,YAAM,iBAAiBA,UAAS,gBAAgB;AAChD,UAAI,CAAC,eAAgB,QAAO,EAAE,SAAS,KAAK;AAC5C,YAAM,SAAS,mBAAmB,UAAU,cAAc;AAC1D,UAAI,CAAC,OAAO,SAAS;AACnB,cAAM,SAAS,OAAO,MAAM,OACzB,MAAM,GAAG,CAAC,EACV,IAAI,CAAC,MAAM,GAAG,EAAE,KAAK,KAAK,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,EAC9C,KAAK,IAAI;AACZ,eAAO,EAAE,SAAS,OAAO,OAAO,EAAE,SAAS,OAAO,EAAE;AAAA,MACtD;AACA,aAAO,EAAE,SAAS,KAAK;AAAA,IACzB;AAAA,IACA,MAAM,CAACA,cAAa;AAElB,YAAM,aAAaA,UAAS,YAAY;AACxC,UAAI,CAAC,WAAY,QAAO,EAAE,SAAS,KAAK;AACxC,YAAM,SAAS,iBAAiB,UAAU,UAAU;AACpD,UAAI,CAAC,OAAO,SAAS;AACnB,cAAM,SAAS,OAAO,MAAM,OACzB,MAAM,GAAG,CAAC,EACV,IAAI,CAAC,MAAM,GAAG,EAAE,KAAK,KAAK,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,EAC9C,KAAK,IAAI;AACZ,eAAO,EAAE,SAAS,OAAO,OAAO,EAAE,SAAS,OAAO,EAAE;AAAA,MACtD;AACA,aAAO,EAAE,SAAS,KAAK;AAAA,IACzB;AAAA,EACF;AAEA,QAAM,eAAe,qBAAqB,KAAK;AAC/C,MAAI,cAAc;AAChB,UAAM,YAAY,aAAa,QAAQ;AACvC,QAAI,CAAC,UAAU,SAAS;AACtB,YAAM,SAAgC;AAAA,QACpC,OAAO;AAAA,QACP;AAAA,QACA,WAAW;AAAA,QACX,aAAa,2CAA2C,UAAU,OAAO,OAAO;AAAA,MAClF;AACA,aAAO,EAAE,MAAM,KAAK,UAAU,MAAM,GAAG,SAAS,MAAM;AAAA,IACxD;AAAA,EACF;AAGA,MAAI;AACF,UAAM,eAAeR,MAAK,KAAK,gBAAgB,WAAW;AAC1D,IAAAK,WAAU,cAAc,EAAE,WAAW,KAAK,CAAC;AAC3C,UAAM,eAAe,eAAe,KAAK;AACzC,UAAM,eAAeL,MAAK,cAAc,YAAY;AAGpD,UAAM,aAAa,KAAK,UAAU,UAAU,MAAM,CAAC,IAAI;AACvD,UAAM,gBAAgB,OAAO,KAAK,YAAY,OAAO;AACrD,kBAAc,cAAc,UAAU;AAGtC,QAAI,SAAS;AACb,QAAI;AACF,YAAM,EAAE,WAAW,IAAI,iBAAiB,GAAG;AAC3C,YAAM,MAAM,aAAa,eAAe,UAAU;AAClD,YAAM,cAAcD,gBAAe,KAAK;AACxC,4BAAsB,KAAK,cAAc,KAAK,WAAW;AACzD,eAAS;AAAA,IACX,QAAQ;AAAA,IAGR;AAGA,UAAM,QAAQ,UAAU,GAAG;AAC3B,QAAI,CAAC,MAAM,OAAO,KAAK,EAAG,OAAM,OAAO,KAAK,IAAI,mBAAmB;AACnE,UAAM,KAAK,MAAM,OAAO,KAAK;AAC7B,OAAG,kBAAkB;AACrB,eAAW,KAAK,KAAK;AAErB,UAAM,UAAU,OAAO,KAAK,QAAQ,EAAE,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI;AAC3D,UAAM,SAA8B;AAAA,MAClC,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA,SAAS,SAAS,YAAY,WAAW,OAAO,GAAG,OAAO,KAAK,QAAQ,EAAE,SAAS,IAAI,UAAU,EAAE,IAAI,SAAS,cAAc,EAAE;AAAA,IACjI;AACA,WAAO,EAAE,MAAM,KAAK,UAAU,MAAM,GAAG,SAAS,MAAM;AAAA,EACxD,SAAS,KAAK;AACZ,UAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,WAAO,EAAE,MAAM,KAAK,UAAU,EAAE,OAAO,MAAM,OAAO,QAAQ,CAAC,GAAG,SAAS,KAAK;AAAA,EAChF;AACF;AAMO,SAAS,sBAAsBU,SAAyB;AAC7D,QAAM,OAAO;AACb,QAAM,MAAM,CAAC,OAA2C;AAAA,IACtD,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,EAAE,KAAK,CAAC;AAAA,IACjD,SAAS,EAAE;AAAA,EACb;AAEA,EAAAA,QAAO;AAAA,IACL;AAAA,IACA,8DAA8D,IAAI;AAAA,IAClE,CAAC;AAAA,IACD,YAAY,IAAI,uBAAuB,CAAC;AAAA,EAC1C;AAEA,EAAAA,QAAO;AAAA,IACL;AAAA,IACA,sDAA4C,IAAI;AAAA,IAChD;AAAA,MACE,OAAOC,IAAE,OAAO,EAAE,SAAS,EAAE,SAAS,kCAAkC;AAAA,MACxE,OAAOA,IACJ,KAAK,CAAC,sBAAsB,YAAY,YAAY,iBAAiB,CAAC,EACtE,SAAS,EACT,SAAS,sBAAsB;AAAA,MAClC,OAAO,WAAWA,IAAE,QAAQ,EAAE,SAAS,CAAC,EAAE;AAAA,QACxC;AAAA,MACF;AAAA,MACA,QAAQA,IACL,KAAK,CAAC,SAAS,aAAa,aAAa,MAAM,CAAC,EAChD,SAAS,EACT,SAAS,2BAA2B;AAAA,MACvC,gBAAgB,WAAWA,IAAE,QAAQ,EAAE,SAAS,CAAC,EAAE;AAAA,QACjD;AAAA,MACF;AAAA,IACF;AAAA,IACA,OAAO,SACL;AAAA,MACE,uBAAuB;AAAA,QACrB,GAAI,KAAK,SAAS,OAAO,EAAE,OAAO,KAAK,MAAM,IAAI,CAAC;AAAA,QAClD,GAAI,KAAK,SAAS,OAAO,EAAE,OAAO,KAAK,MAAM,IAAI,CAAC;AAAA,QAClD,GAAI,KAAK,SAAS,OAAO,EAAE,OAAO,KAAK,MAAM,IAAI,CAAC;AAAA,QAClD,GAAI,KAAK,UAAU,OAAO,EAAE,QAAQ,KAAK,OAAO,IAAI,CAAC;AAAA,QACrD,GAAI,KAAK,kBAAkB,OAAO,EAAE,gBAAgB,KAAK,eAAe,IAAI,CAAC;AAAA,MAC/E,CAAC;AAAA,IACH;AAAA,EACJ;AAEA,EAAAD,QAAO;AAAA,IACL;AAAA,IACA,6GAA6G,IAAI;AAAA,IACjH;AAAA,MACE,OAAOC,IACJ,OAAO,EACP,SAAS,EACT,SAAS,2EAA2E;AAAA,IACzF;AAAA,IACA,OAAO,EAAE,MAAM,MAAM,IAAI,0BAA0B,QAAW,KAAK,CAAC;AAAA,EACtE;AAEA,EAAAD,QAAO;AAAA,IACL;AAAA,IACA,uJAAkJ,IAAI;AAAA,IACtJ,CAAC;AAAA,IACD,YAAY,IAAI,qBAAqB,CAAC;AAAA,EACxC;AAEA,EAAAA,QAAO;AAAA,IACL;AAAA,IACA,mFAAmF,IAAI;AAAA,IACvF,CAAC;AAAA,IACD,YAAY,IAAI,oBAAoB,CAAC;AAAA,EACvC;AAEA,EAAAA,QAAO;AAAA,IACL;AAAA,IACA,+JAA0J,IAAI;AAAA,IAC9J;AAAA,MACE,OAAOC,IACJ,OAAO,EACP,SAAS,EACT,SAAS,yDAAyD;AAAA,MACrE,cAAcA,IACX,OAAO,EACP,SAAS,EACT,SAAS,gDAAgD;AAAA,MAC5D,WAAW,WAAWA,IAAE,MAAMA,IAAE,IAAI,CAAC,EAAE,SAAS,CAAC,EAAE;AAAA,QACjD;AAAA,MACF;AAAA,IACF;AAAA,IACA,OAAO,EAAE,OAAO,cAAc,UAAU,MAAM;AAE5C,UAAI,SAAS,aAAa,MAAM,QAAQ,SAAS,GAAG;AAClD,cAAM,aAAa;AACnB,YAAI,CAAC,WAAW,KAAK,KAAK,GAAG;AAC3B,iBAAO;AAAA,YACL,SAAS;AAAA,cACP,EAAE,MAAM,QAAiB,MAAM,KAAK,UAAU,EAAE,OAAO,qBAAqB,CAAC,EAAE;AAAA,YACjF;AAAA,YACA,SAAS;AAAA,UACX;AAAA,QACF;AACA,cAAM,eAAeV,MAAK,QAAQ,IAAI,GAAG,gBAAgB,WAAW;AACpE,QAAAK,WAAU,cAAc,EAAE,WAAW,KAAK,CAAC;AAC3C,cAAM,UAAUL,MAAK,cAAc,GAAG,KAAK,OAAO;AAClD,QAAAG;AAAA,UACE;AAAA,UACA,KAAK,UAAU,EAAE,OAAO,WAAW,YAAW,oBAAI,KAAK,GAAE,YAAY,EAAE,GAAG,MAAM,CAAC;AAAA,QACnF;AACA,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM,KAAK,UAAU;AAAA,gBACnB,SAAS;AAAA,gBACT;AAAA,gBACA,OAAQ,UAAwB;AAAA,cAClC,CAAC;AAAA,YACH;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,aAAO;AAAA,QACL,0BAA0B,EAAE,OAAO,SAAS,IAAI,cAAc,gBAAgB,GAAG,CAAC;AAAA,MACpF;AAAA,IACF;AAAA,EACF;AAEA,EAAAM,QAAO;AAAA,IACL;AAAA,IACA,yFAAyF,IAAI;AAAA,IAC7F,EAAE,OAAOC,IAAE,OAAO,EAAE,SAAS,yCAAyC,EAAE;AAAA,IACxE,OAAO,EAAE,MAAM,MAAM,IAAI,4BAA4B,EAAE,MAAM,CAAC,CAAC;AAAA,EACjE;AAEA,EAAAD,QAAO;AAAA,IACL;AAAA,IACA,2FAA2F,IAAI;AAAA,IAC/F;AAAA,MACE,OAAOC,IAAE,OAAO,EAAE,SAAS,oDAAoD;AAAA,MAC/E,cAAcA,IACX,OAAO,EACP,SAAS,EACT,SAAS,6EAA6E;AAAA,MACzF,UAAU,WAAWA,IAAE,OAAOA,IAAE,OAAO,GAAGA,IAAE,QAAQ,CAAC,EAAE,SAAS,CAAC,EAAE;AAAA,QACjE;AAAA,MACF;AAAA,IACF;AAAA,IACA,OAAO,EAAE,OAAO,cAAc,SAAS,MAAM;AAC3C,UAAI,UAAU;AACZ,eAAO;AAAA,UACL,uBAAuB,EAAE,OAAO,SAA8C,CAAC;AAAA,QACjF;AAAA,MACF;AACA,aAAO,IAAI,uBAAuB,EAAE,OAAO,cAAc,gBAAgB,GAAG,CAAC,CAAC;AAAA,IAChF;AAAA,EACF;AACF;;;AE/4CA,SAAS,KAAAC,WAAS;AAElB,SAAS,iBAAAC,gBAAe,cAAAC,aAAY,aAAAC,YAAW,aAAAC,kBAAiB;AAChE,SAAS,WAAW,YAAY,SAAS,QAAAC,aAAY;AAoBrD,IAAM,yBAA0D;AAAA,EAC9D,kCAAkC;AAAA,IAChC,EAAE,QAAQ,2BAA2B,QAAQ,SAAS,aAAa,2BAA2B;AAAA,EAChG;AAAA,EACA,+BAA+B;AAAA,IAC7B,EAAE,QAAQ,2BAA2B,QAAQ,SAAS,aAAa,wBAAwB;AAAA,EAC7F;AAAA,EACA,8BAA8B;AAAA,IAC5B,EAAE,QAAQ,2BAA2B,QAAQ,SAAS,aAAa,uBAAuB;AAAA,IAC1F,EAAE,QAAQ,WAAW,QAAQ,QAAQ,aAAa,mBAAmB;AAAA,IACrE,EAAE,QAAQ,WAAW,QAAQ,SAAS,aAAa,mBAAmB;AAAA,IACtE;AAAA,MACE,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,aAAa;AAAA,IACf;AAAA,EACF;AAAA,EACA,8BAA8B;AAAA,IAC5B,EAAE,QAAQ,2BAA2B,QAAQ,SAAS,aAAa,uBAAuB;AAAA,IAC1F,EAAE,QAAQ,mBAAmB,QAAQ,IAAI,aAAa,qBAAqB;AAAA,EAC7E;AAAA,EACA,8BAA8B;AAAA,IAC5B,EAAE,QAAQ,UAAU,QAAQ,gBAAgB,aAAa,oBAAoB;AAAA,IAC7E,EAAE,QAAQ,UAAU,QAAQ,iBAAiB,aAAa,oBAAoB;AAAA,IAC9E,EAAE,QAAQ,2BAA2B,QAAQ,SAAS,aAAa,iBAAiB;AAAA,EACtF;AAAA,EACA,mCAAmC;AAAA,IACjC,EAAE,QAAQ,UAAU,QAAQ,gBAAgB,aAAa,yBAAyB;AAAA,IAClF,EAAE,QAAQ,UAAU,QAAQ,iBAAiB,aAAa,yBAAyB;AAAA,IACnF,EAAE,QAAQ,2BAA2B,QAAQ,SAAS,aAAa,qBAAqB;AAAA,EAC1F;AAAA,EACA,kCAAkC;AAAA,IAChC,EAAE,QAAQ,cAAc,QAAQ,QAAQ,aAAa,sBAAsB;AAAA,IAC3E,EAAE,QAAQ,cAAc,QAAQ,SAAS,aAAa,sBAAsB;AAAA,IAC5E,EAAE,QAAQ,2BAA2B,QAAQ,SAAS,aAAa,kBAAkB;AAAA,EACvF;AAAA,EACA,6BAA6B;AAAA,IAC3B,EAAE,QAAQ,2BAA2B,QAAQ,SAAS,aAAa,sBAAsB;AAAA,EAC3F;AACF;AAMA,IAAM,0BAA0B;AAAA,EAC9B;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA,EACA;AACF;AASO,IAAM,4BAA4B,MAAM;AAGxC,IAAM,4BAA4B,MAAM;AAGxC,IAAM,2BAA2B,IAAI;AAGrC,IAAM,+BAA+B,MAAM;AAM3C,SAAS,mBAAmB,UAAoD;AACrF,MAAI,SAAS,SAAS,OAAO,EAAG,QAAO,EAAE,OAAO,2BAA2B,OAAO,OAAO;AACzF,MAAI,SAAS,SAAS,MAAM,KAAK,SAAS,SAAS,OAAO;AACxD,WAAO,EAAE,OAAO,2BAA2B,OAAO,OAAO;AAC3D,MAAI,aAAa,UAAU,uBAAuB,KAAK,QAAQ;AAC7D,WAAO,EAAE,OAAO,0BAA0B,OAAO,MAAM;AACzD,SAAO,EAAE,OAAO,8BAA8B,OAAO,UAAU;AACjE;AAiCO,SAAS,iBACd,aACA,UACqD;AAErD,QAAM,aAAa,UAAU,QAAQ;AACrC,MAAI,WAAW,SAAS,IAAI,GAAG;AAC7B,WAAO,EAAE,SAAS,OAAO,OAAO,yDAAyD;AAAA,EAC3F;AAGA,MAAI,WAAW,UAAU,GAAG;AAC1B,WAAO;AAAA,MACL,SAAS;AAAA,MACT,OAAO;AAAA,IACT;AAAA,EACF;AAGA,MAAI,gBAAgB,iCAAiC;AACnD,WAAO;AAAA,MACL,SAAS;AAAA,MACT,OAAO;AAAA,IACT;AAAA,EACF;AAGA,QAAM,YAAY,uBAAuB,WAAW;AACpD,MAAI,CAAC,WAAW;AACd,WAAO;AAAA,MACL,SAAS;AAAA,MACT,OAAO,mBAAmB,WAAW;AAAA,IACvC;AAAA,EACF;AAGA,aAAW,mBAAmB,yBAAyB;AACrD,QAAI,eAAe,mBAAmB,WAAW,WAAW,eAAe,GAAG;AAC5E,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO,SAAS,UAAU;AAAA,MAC5B;AAAA,IACF;AAAA,EACF;AAGA,aAAW,QAAQ,WAAW;AAC5B,UAAM,cAAc,WAAW,WAAW,KAAK,MAAM;AACrD,UAAM,cAAc,KAAK,WAAW,MAAM,WAAW,SAAS,KAAK,MAAM;AACzE,QAAI,eAAe,aAAa;AAI9B,UAAI,KAAK,WAAW,UAAU,KAAK,WAAW,IAAI;AAChD,YAAI,CAAC,8BAA8B,KAAK,UAAU,GAAG;AACnD;AAAA,QACF;AAAA,MACF;AACA,aAAO,EAAE,SAAS,MAAM,MAAM,KAAK,YAAY;AAAA,IACjD;AAAA,EACF;AAEA,SAAO;AAAA,IACL,SAAS;AAAA,IACT,OAAO,SAAS,UAAU,kDAAkD,WAAW;AAAA,EACzF;AACF;AAMA,SAAS,oBAAoB,SAAgC;AAC3D,MAAI;AACF,SAAK,MAAM,OAAO;AAClB,WAAO;AAAA,EACT,SAAS,KAAK;AACZ,WAAO,iBAAiB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,EAC1E;AACF;AAEA,SAAS,oBAAoB,SAAgC;AAC3D,QAAM,UAAU,QAAQ,UAAU;AAKlC,QAAM,mBAAmB;AACzB,QAAM,UAAU,CAAC,GAAG,QAAQ,SAAS,gBAAgB,CAAC;AACtD,MAAI,QAAQ,UAAU,IAAI;AACxB,WAAO;AAAA,EACT;AAGA,QAAM,mBAAmB;AACzB,QAAM,OAAO,CAAC,GAAG,QAAQ,SAAS,gBAAgB,CAAC;AACnD,MAAI,KAAK,UAAU,IAAI;AAErB,UAAM,mBAAmB,oBAAI,IAAoB;AACjD,eAAW,CAAC,EAAE,IAAI,KAAK,MAAM;AAC3B,YAAM,SAAS,iBAAiB,IAAI,IAAI,KAAK,KAAK;AAClD,uBAAiB,IAAI,MAAM,KAAK;AAChC,UAAI,SAAS,IAAI;AACf,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AAEA,MAAI,QAAQ,WAAW,SAAS,KAAK,QAAQ,WAAW,SAAS,GAAG;AAClE,WAAO;AAAA,EACT;AACA,MAAI,QAAQ,WAAW,SAAS,KAAK,QAAQ,WAAW,SAAS,GAAG;AAClE,WAAO;AAAA,EACT;AACA,MAAI,QAAQ,WAAW,IAAI;AACzB,WAAO;AACT,MAAI,kCAAkC,KAAK,OAAO;AAChD,WAAO;AACT,MAAI,QAAQ,WAAW,GAAG,KAAK,CAAC,QAAQ,WAAW,IAAI;AACrD,WAAO;AACT,SAAO;AACT;AAEA,SAAS,mBAAmB,SAAgC;AAC1D,QAAM,QAAQ,QAAQ,MAAM,IAAI;AAChC,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,UAAM,MAAM,MAAM,CAAC;AACnB,QAAI,QAAQ,OAAW;AACvB,UAAM,OAAO,IAAI,KAAK;AAEtB,QAAI,SAAS,MAAM,KAAK,WAAW,GAAG,EAAG;AACzC,QAAI,CAAC,2BAA2B,KAAK,IAAI,GAAG;AAC1C,aAAO,QAAQ,IAAI,CAAC,oDAAoD,IAAI;AAAA,IAC9E;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,gBAAgB,UAAkB,SAAgC;AACzE,MAAI,SAAS,SAAS,OAAO,EAAG,QAAO,oBAAoB,OAAO;AAClE,MAAI,SAAS,SAAS,MAAM,KAAK,SAAS,SAAS,OAAO,EAAG,QAAO,oBAAoB,OAAO;AAC/F,MAAI,aAAa,UAAU,SAAS,WAAW,MAAM,EAAG,QAAO,mBAAmB,OAAO;AACzF,SAAO;AACT;AAMO,SAAS,gBAAgB,OAA2D;AACzF,QAAM,MAAM,MAAM,QAAQ,QAAQ,IAAI;AACtC,QAAM,EAAE,aAAa,UAAU,SAAS,oBAAoB,KAAK,IAAI;AAGrE,QAAM,QAAQ,iBAAiB,aAAa,QAAQ;AACpD,MAAI,CAAC,MAAM,SAAS;AAClB,UAAM,YAAY,uBAAuB,WAAW,KAAK,CAAC;AAC1D,UAAM,eAAe,UAAU,IAAI,CAAC,MAAM,GAAG,EAAE,MAAM,IAAI,EAAE,MAAM,KAAK,EAAE,WAAW,GAAG;AACtF,UAAM,SAA6B;AAAA,MACjC,SAAS;AAAA,MACT,OAAO,MAAM,SAAS;AAAA,MACtB;AAAA,MACA,eAAe;AAAA,MACf;AAAA,IACF;AACA,WAAO,EAAE,MAAM,KAAK,UAAU,MAAM,GAAG,SAAS,KAAK;AAAA,EACvD;AAGA,QAAM,eAAe,OAAO,WAAW,SAAS,OAAO;AACvD,QAAM,EAAE,OAAO,UAAU,OAAO,cAAc,IAAI,mBAAmB,QAAQ;AAC7E,MAAI,eAAe,UAAU;AAC3B,UAAM,SAA6B;AAAA,MACjC,SAAS;AAAA,MACT,OAAO,gBAAgB,YAAY,kBAAkB,aAAa,aAAa,QAAQ,WAAW,WAAW,IAAI;AAAA,MACjH;AAAA,MACA,eAAe;AAAA,MACf,cAAc,CAAC;AAAA,IACjB;AACA,WAAO,EAAE,MAAM,KAAK,UAAU,MAAM,GAAG,SAAS,KAAK;AAAA,EACvD;AAEA,QAAM,aAAa,UAAU,QAAQ;AACrC,QAAM,WAAWA,MAAK,KAAK,UAAU;AAGrC,MAAIH,YAAW,QAAQ,GAAG;AACxB,QAAI;AACF,YAAM,OAAOE,WAAU,QAAQ;AAC/B,UAAI,KAAK,eAAe,GAAG;AACzB,cAAM,SAA6B;AAAA,UACjC,SAAS;AAAA,UACT,OAAO;AAAA,UACP;AAAA,UACA,eAAe;AAAA,UACf,cAAc,CAAC;AAAA,QACjB;AACA,eAAO,EAAE,MAAM,KAAK,UAAU,MAAM,GAAG,SAAS,KAAK;AAAA,MACvD;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AAGA,QAAM,eAAe,gBAAgB,YAAY,OAAO;AACxD,MAAI,cAAc;AAChB,UAAM,SAA6B;AAAA,MACjC,SAAS;AAAA,MACT,OAAO,8BAA8B,YAAY;AAAA,MACjD;AAAA,MACA,eAAe;AAAA,MACf,cAAc,CAAC;AAAA,IACjB;AACA,WAAO,EAAE,MAAM,KAAK,UAAU,MAAM,GAAG,SAAS,KAAK;AAAA,EACvD;AAGA,MAAI;AACF,QAAI,mBAAmB;AACrB,MAAAD,WAAU,QAAQ,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;AAAA,IAClD;AAEA,IAAAF,eAAc,UAAU,SAAS,EAAE,UAAU,QAAQ,CAAC;AAEtD,UAAM,SAA2B;AAAA,MAC/B,SAAS;AAAA,MACT,MAAM;AAAA,MACN,cAAc,OAAO,WAAW,SAAS,OAAO;AAAA,MAChD,WAAW,MAAM,QAAQ;AAAA,IAC3B;AACA,WAAO,EAAE,MAAM,KAAK,UAAU,MAAM,GAAG,SAAS,MAAM;AAAA,EACxD,SAAS,KAAK;AACZ,UAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,UAAM,SAA6B;AAAA,MACjC,SAAS;AAAA,MACT,OAAO,iBAAiB,OAAO;AAAA,MAC/B;AAAA,MACA,eAAe;AAAA,MACf,cAAc,CAAC;AAAA,IACjB;AACA,WAAO,EAAE,MAAM,KAAK,UAAU,MAAM,GAAG,SAAS,KAAK;AAAA,EACvD;AACF;AAMO,SAAS,uBAAuBK,SAAyB;AAC9D,QAAM,OACJ;AAEF,EAAAA,QAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,MACE,aAAaC,IACV,OAAO,EACP,SAAS,8EAA8E;AAAA,MAC1F,UAAUA,IACP,OAAO,EACP,SAAS,qEAAqE;AAAA,MACjF,SAASA,IAAE,OAAO,EAAE,SAAS,uBAAuB;AAAA,MACpD,mBAAmB,WAAWA,IAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,IAAI,CAAC,EAAE;AAAA,QAClE;AAAA,MACF;AAAA,IACF;AAAA,IACA,OAAO,EAAE,aAAa,UAAU,SAAS,kBAAkB,MAAM;AAC/D,YAAM,SAAS,gBAAgB;AAAA,QAC7B;AAAA,QACA;AAAA,QACA;AAAA,QACA,GAAI,qBAAqB,OAAO,EAAE,kBAAkB,IAAI,CAAC;AAAA,MAC3D,CAAC;AACD,aAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,OAAO,KAAK,CAAC,GAAG,SAAS,OAAO,QAAQ;AAAA,IAC5F;AAAA,EACF;AACF;;;AC9ZA,SAAS,KAAAC,WAAS;AAClB,SAAS,gBAAAC,eAAc,iBAAAC,gBAAe,cAAAC,mBAAkB;AACxD,SAAS,QAAAC,aAAY;AA2CrB,SAAS,eAAe,OAA2C;AACjE,QAAM,IAA8B,CAAC;AACrC,WAAS,IAAI,GAAG,IAAI,MAAM,SAAS,GAAG,KAAK;AACzC,MAAE,MAAM,CAAC,CAAE,IAAI,MAAM,MAAM,IAAI,CAAC;AAAA,EAClC;AACA,SAAO;AACT;AAEA,SAAS,gBAAgB,WAAqC,QAAwB;AACpF,QAAM,UAAU,OAAO,QAAQ,SAAS;AACxC,MAAI,QAAQ,WAAW,EAAG,QAAO,GAAG,MAAM;AAC1C,SAAO,QAAQ,IAAI,CAAC,CAAC,MAAM,IAAI,MAAM,GAAG,MAAM,GAAG,IAAI,MAAM,KAAK,KAAK,IAAI,CAAC,GAAG,EAAE,KAAK,IAAI;AAC1F;AAEA,SAAS,YAAY,OAAiB,QAAwB;AAC5D,SAAO,MAAM,IAAI,CAAC,MAAM,GAAG,MAAM,KAAK,CAAC,EAAE,EAAE,KAAK,IAAI;AACtD;AAEA,SAAS,aAAa,QAAkB,aAAqB,QAAwB;AACnF,SAAO,OACJ,IAAI,CAAC,MAAM,GAAG,MAAM,cAAc,CAAC;AAAA,EAAK,MAAM,mBAAmB,WAAW,EAAE,EAC9E,KAAK,IAAI;AACd;AAGA,SAAS,gBAAgB,UAAkB,UAA0B;AACnE,QAAM,QAAQ,SAAS,MAAM,IAAI;AACjC,MAAI,YAAY;AAChB,MAAI,UAAU,MAAM;AAEpB,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,QAAI,SAAS,KAAK,MAAM,CAAC,CAAE,GAAG;AAC5B,kBAAY;AAAA,IACd,WACE,aAAa,KACb,IAAI,aACJ,MAAM,KAAK,MAAM,CAAC,CAAE,KACpB,MAAM,CAAC,EAAG,KAAK,MAAM,IACrB;AACA,gBAAU;AACV;AAAA,IACF;AAAA,EACF;AAEA,MAAI,YAAY,GAAG;AAEjB,WAAO,SAAS,QAAQ,IAAI,OAAO,WAAW;AAAA,EAChD;AAGA,QAAM,SAAS,MAAM,MAAM,GAAG,SAAS;AACvC,QAAM,QAAQ,MAAM,MAAM,OAAO;AACjC,SAAO,CAAC,GAAG,QAAQ,GAAG,SAAS,QAAQ,EAAE,MAAM,IAAI,GAAG,GAAI,MAAM,SAAS,QAAQ,CAAC,CAAE,EAAE,KAAK,IAAI;AACjG;AAMA,SAAS,0BACP,QACA,QACA,OACA,aACA,WACA,cACA,oBACA,iBACQ;AACR,QAAM,YAAY;AAAA,aACP,KAAK,UAAU,KAAK,CAAC;AAAA,oBACd,WAAW;AAAA,iBACd,KAAK,UAAU,WAAW,MAAM,CAAC,CAAC;AAAA;AAEjD,QAAM,aAAa;AAAA,eACN,YAAY;AAAA,qBACN,kBAAkB;AAAA;AAErC,QAAM,cAAc,sBAAsB,KAAK,UAAU,eAAe,CAAC;AACzE,QAAM,cAAc;AAAA,aACT,KAAK,UAAU,eAAe,CAAC;AAAA;AAG1C,MAAI,WAAW,OAAO;AACpB,UAAM,WAAW,OAAO,eAAe;AACvC,UAAM,cAAc,OAAO,kBAAkB;AAC7C,UAAM,eAAe,OAAO,mBAAmB;AAC/C,UAAM,aAAa,OAAO,iBAAiB;AAC3C,WAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,8CASmC,QAAQ;AAAA,oBAClC,WAAW;AAAA,sDACuB,YAAY;AAAA,mBAC/C,UAAU;AAAA;AAAA,EAE3B,SAAS;AAAA,EACT,UAAU;AAAA,EACV,WAAW;AAAA;AAAA;AAAA,EAGX,WAAW;AAAA;AAAA,EAEX;AAEA,MAAI,WAAW,QAAQ;AACrB,UAAMC,UAAS,OAAO,cAAc;AACpC,UAAM,YAAY,OAAO,iBAAiB;AAC1C,WAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,eASIA,OAAM;AAAA,kBACH,SAAS;AAAA;AAAA,EAEzB,SAAS;AAAA,EACT,UAAU;AAAA,EACV,WAAW;AAAA;AAAA;AAAA,EAGX,WAAW;AAAA;AAAA,EAEX;AAGA,QAAM,SAAS,OAAO,gBAAgB;AACtC,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,eAUM,MAAM;AAAA;AAAA,EAEnB,SAAS;AAAA,EACT,UAAU;AAAA,EACV,WAAW;AAAA;AAAA;AAAA,EAGX,WAAW;AAAA;AAEb;AAEA,SAAS,iBAAiB,QAAgB,QAAqC;AAC7E,MAAI,WAAW,OAAO;AACpB,WAAO;AAAA;AAAA;AAAA;AAAA;AAAA,EAKT;AAEA,MAAI,WAAW,QAAQ;AACrB,UAAM,QAAQ,OAAO,YAAY;AACjC,UAAM,eACJ,OAAO,oBAAoB;AAC7B,WAAO,iCAA4B,KAAK;AAAA,qBACvB,YAAY;AAAA;AAAA;AAAA;AAAA,EAI/B;AAGA,QAAM,UAAU,OAAO,iBAAiB;AACxC,QAAM,WAAW,OAAO,kBAAkB;AAC1C,SAAO;AAAA,kBACS,OAAO;AAAA,mBACN,QAAQ;AAAA;AAAA;AAAA;AAI3B;AAEA,SAAS,kBACP,QACA,QACA,OACA,aACA,WACA,cACA,oBACA,iBACQ;AACR,QAAM,cAAc;AAAA;AAAA,EAEpB,YAAY,OAAO,QAAQ,CAAC;AAAA,mBACX,WAAW;AAAA;AAAA,EAE5B,gBAAgB,WAAW,QAAQ,CAAC;AAEpC,QAAM,eAAe;AAAA,eACR,YAAY;AAAA,qBACN,kBAAkB;AAErC,QAAM,gBAAgB;AAAA,EACtB,aAAa,iBAAiB,QAAQ,WAAW,CAAC,GAAG,QAAQ,WAAW,EAAE;AAG1E,QAAM,aAAa,gBAChB,IAAI,CAAC,MAAM,kBAAkB,CAAC;AAAA,sBAAyB,WAAW,EAAE,EACpE,KAAK,IAAI;AAEZ,QAAM,eAAe,OAAO,WAAW,eAAe,OAAO,QAAQ;AAAA,IAAO;AAE5E,MAAI,WAAW,OAAO;AACpB,UAAM,WAAW,OAAO,eAAe;AACvC,UAAM,cAAc,OAAO,kBAAkB;AAC7C,UAAM,eAAe,OAAO,mBAAmB;AAC/C,UAAM,aAAa,OAAO,iBAAiB;AAC3C,WAAO;AAAA;AAAA,EAET,YAAY;AAAA;AAAA;AAAA,mBAGK,WAAW;AAAA;AAAA,kBAEZ,UAAU;AAAA,EAC1B,WAAW;AAAA;AAAA,EAEX,UAAU;AAAA,EACV,YAAY;AAAA;AAAA,EAEZ;AAEA,MAAI,WAAW,QAAQ;AACrB,UAAMA,UAAS,OAAO,cAAc;AACpC,UAAM,YAAY,OAAO,iBAAiB;AAC1C,WAAO;AAAA;AAAA,EAET,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA,cAKAA,OAAM;AAAA,iBACH,SAAS;AAAA,EACxB,WAAW;AAAA;AAAA,EAEX,UAAU;AAAA,EACV,YAAY;AAAA;AAAA,EAEZ;AAGA,QAAM,SAAS,OAAO,gBAAgB;AACtC,SAAO;AAAA;AAAA,EAEP,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,cAMA,MAAM;AAAA,EAClB,WAAW;AAAA;AAAA,EAEX,UAAU;AAAA,EACV,YAAY;AAAA;AAEd;AAMA,eAAsB,qBACpB,QACA,KACgF;AAChF,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA,YAAY,CAAC,eAAe,SAAS,SAAS;AAAA,IAC9C,eAAe;AAAA,IACf,qBAAqB;AAAA,IACrB,kBAAkB,CAAC,mBAAmB;AAAA,EACxC,IAAI;AAEJ,QAAM,QAAQ;AACd,QAAM,cAAc,OAAO,mBAAmB,MAAM,MAAM,SAAS,CAAC;AACpE,QAAM,YAAY,eAAe,KAAK;AAGtC,MAAI,WAAW,QAAQ;AACrB,WAAO;AAAA,MACL,SAAS;AAAA,QACP;AAAA,UACE,MAAM;AAAA,UACN,MAAM,KAAK,UAAU;AAAA,YACnB,SAAS;AAAA,YACT,QAAQ;AAAA,YACR,UAAU;AAAA,YACV,WAAW;AAAA,YACX,iBAAiB;AAAA,YACjB,sBAAsB,gBAAgB;AAAA,YACtC,cAAc,CAAC;AAAA,YACf,iBAAiB;AAAA,UACnB,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,eAAyB,CAAC;AAEhC,MAAI;AAEF,UAAM,oBAAoB;AAAA,MACxB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,IAAAC,eAAcC,MAAK,KAAK,eAAe,GAAG,mBAAmB,MAAM;AACnE,iBAAa,KAAK,eAAe;AAAA,EACnC,SAAS,KAAK;AACZ,UAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,WAAO;AAAA,MACL,SAAS;AAAA,QACP;AAAA,UACE,MAAM;AAAA,UACN,MAAM,KAAK,UAAU,EAAE,SAAS,OAAO,OAAO,iCAAiC,GAAG,GAAG,CAAC;AAAA,QACxF;AAAA,MACF;AAAA,MACA,SAAS;AAAA,IACX;AAAA,EACF;AAEA,MAAI;AAEF,UAAM,WAAW,iBAAiB,QAAQ,MAAM;AAChD,UAAM,UAAUA,MAAK,KAAK,cAAc;AACxC,QAAIC,YAAW,OAAO,GAAG;AACvB,YAAM,WAAWC,cAAa,SAAS,MAAM;AAC7C,MAAAH,eAAc,SAAS,SAAS,QAAQ,IAAI,SAAS,UAAU,MAAM;AAAA,IACvE,OAAO;AACL,MAAAA,eAAc,SAAS,UAAU,MAAM;AAAA,IACzC;AACA,iBAAa,KAAK,cAAc;AAAA,EAClC,SAAS,KAAK;AACZ,UAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,WAAO;AAAA,MACL,SAAS;AAAA,QACP;AAAA,UACE,MAAM;AAAA,UACN,MAAM,KAAK,UAAU,EAAE,SAAS,OAAO,OAAO,gCAAgC,GAAG,GAAG,CAAC;AAAA,QACvF;AAAA,MACF;AAAA,MACA,SAAS;AAAA,IACX;AAAA,EACF;AAEA,MAAI;AAEF,UAAM,WAAW;AAAA,MACf;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,UAAM,UAAUC,MAAK,KAAK,iBAAiB;AAC3C,QAAI,CAACC,YAAW,OAAO,GAAG;AACxB,MAAAF,eAAc,SAAS,UAAU,MAAM;AAAA,IACzC,OAAO;AACL,YAAM,WAAWG,cAAa,SAAS,MAAM;AAC7C,MAAAH,eAAc,SAAS,gBAAgB,UAAU,QAAQ,GAAG,MAAM;AAAA,IACpE;AACA,iBAAa,KAAK,iBAAiB;AAAA,EACrC,SAAS,KAAK;AACZ,UAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,WAAO;AAAA,MACL,SAAS;AAAA,QACP;AAAA,UACE,MAAM;AAAA,UACN,MAAM,KAAK,UAAU,EAAE,SAAS,OAAO,OAAO,mCAAmC,GAAG,GAAG,CAAC;AAAA,QAC1F;AAAA,MACF;AAAA,MACA,SAAS;AAAA,IACX;AAAA,EACF;AAGA,QAAM,kBACJ,WAAW,QACP,wGACA;AAEN,SAAO;AAAA,IACL,SAAS;AAAA,MACP;AAAA,QACE,MAAM;AAAA,QACN,MAAM,KAAK,UAAU;AAAA,UACnB,SAAS;AAAA,UACT;AAAA,UACA,UAAU,YAAY;AAAA,UACtB,WAAW;AAAA,UACX,iBAAiB;AAAA,UACjB,sBAAsB,gBAAgB;AAAA,UACtC;AAAA,UACA;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AACF;AAMO,SAAS,kBAAkBI,SAAyB;AACzD,EAAAA,QAAO;AAAA,IACL;AAAA,IACA;AAAA,IAMA;AAAA,MACE,QAAQC,IAAE,KAAK,CAAC,OAAO,QAAQ,UAAU,MAAM,CAAC;AAAA,MAChD,UAAUA,IAAE,KAAK,CAAC,YAAY,QAAQ,QAAQ,WAAW,QAAQ,CAAC,EAAE,SAAS;AAAA;AAAA,MAE7E,aAAaA,IAAE,OAAO,EAAE,SAAS;AAAA,MACjC,gBAAgBA,IAAE,OAAO,EAAE,SAAS;AAAA,MACpC,iBAAiBA,IAAE,OAAO,EAAE,SAAS;AAAA,MACrC,eAAeA,IAAE,OAAO,EAAE,SAAS;AAAA;AAAA,MAEnC,kBAAkBA,IAAE,OAAO,EAAE,SAAS;AAAA,MACtC,cAAcA,IAAE,OAAO,EAAE,SAAS;AAAA,MAClC,kBAAkBA,IAAE,OAAO,EAAE,SAAS;AAAA,MACtC,YAAYA,IAAE,OAAO,EAAE,SAAS;AAAA,MAChC,eAAeA,IAAE,OAAO,EAAE,SAAS;AAAA;AAAA,MAEnC,eAAeA,IAAE,OAAO,EAAE,SAAS;AAAA,MACnC,gBAAgBA,IAAE,OAAO,EAAE,SAAS;AAAA,MACpC,gBAAgBA,IAAE,OAAO,EAAE,SAAS;AAAA,MACpC,oBAAoBA,IAAE,OAAO,EAAE,SAAS;AAAA,MACxC,cAAcA,IAAE,OAAO,EAAE,SAAS;AAAA;AAAA,MAElC,WAAW,WAAWA,IAAE,MAAMA,IAAE,OAAO,CAAC,EAAE,SAAS,CAAC;AAAA,MACpD,iBAAiBA,IAAE,OAAO,EAAE,SAAS;AAAA;AAAA,MAErC,cAAc,WAAWA,IAAE,QAAQ,EAAE,SAAS,CAAC;AAAA,MAC/C,oBAAoB,UAAUA,IAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,CAAC;AAAA;AAAA,MAEpE,iBAAiB,WAAWA,IAAE,MAAMA,IAAE,OAAO,CAAC,EAAE,SAAS,CAAC;AAAA;AAAA,MAE1D,MAAMA,IAAE,OAAO,EAAE,SAAS;AAAA,IAC5B;AAAA,IACA,OAAO,WAAW;AAChB,YAAM,MAAM,OAAO,QAAQ,QAAQ,IAAI;AACvC,aAAO,qBAAqB,QAAQ,GAAG;AAAA,IACzC;AAAA,EACF;AACF;;;ACxgBA,SAAS,cAAAC,aAAY,mBAAAC,wBAAuB;AAC5C,SAAS,gBAAAC,eAAc,eAAAC,cAAa,aAAAC,kBAAiB;AACrD,SAAS,QAAAC,OAAM,gBAAgB;AAU/B,IAAM,aAAa,oBAAI,IAAoB;AAAA,EACzC;AAAA,IACE;AAAA,IACA;AAAA,EACF;AAAA,EACA;AAAA,IACE;AAAA,IACA;AAAA,EACF;AAAA,EACA;AAAA,IACE;AAAA,IACA;AAAA,EACF;AAAA,EACA;AAAA,IACE;AAAA,IACA;AAAA,EACF;AAAA,EACA;AAAA,IACE;AAAA,IACA;AAAA,EACF;AAAA,EACA;AAAA,IACE;AAAA,IACA;AAAA,EACF;AAAA,EACA;AAAA,IACE;AAAA,IACA;AAAA,EACF;AAAA,EACA;AAAA,IACE;AAAA,IACA;AAAA,EACF;AAAA,EACA;AAAA,IACE;AAAA,IACA;AAAA,EACF;AAAA,EACA;AAAA,IACE;AAAA,IACA;AAAA,EACF;AAAA,EACA;AAAA,IACE;AAAA,IACA;AAAA,EACF;AAAA,EACA;AAAA,IACE;AAAA,IACA;AAAA,EACF;AACF,CAAC;AACD,OAAO,OAAO,UAAU;AACxB,IAAM,sBAAmD;AAOzD,IAAM,gBAAgB;AAEtB,WAAW,CAAC,MAAM,MAAM,KAAK,qBAAqB;AAChD,MAAI,CAAC,cAAc,KAAK,MAAM,GAAG;AAC/B,UAAM,IAAI;AAAA,MACR,iDAAiD,IAAI,iCACrB,OAAO,MAAM,MAAM,MAAM;AAAA,IAC3D;AAAA,EACF;AACF;AAGA,IAAM,kBAAkB,IAAI,OAAO;AAO5B,SAAS,cAAc,MAAsB;AAClD,SAAOL,YAAW,QAAQ,EAAE,OAAO,IAAI,EAAE,OAAO,KAAK;AACvD;AAGA,SAAS,UAAU,GAAW,GAAoB;AAChD,MAAI,EAAE,WAAW,EAAE,OAAQ,QAAO;AAClC,SAAOC,iBAAgB,OAAO,KAAK,GAAG,MAAM,GAAG,OAAO,KAAK,GAAG,MAAM,CAAC;AACvE;AAkBO,SAAS,gBAAgB,UAAyC;AACvE,QAAM,WAAW,SAAS,QAAQ;AAGlC,QAAM,WAAW,oBAAoB,IAAI,QAAQ;AACjD,MAAI,aAAa,QAAW;AAC1B,WAAO,EAAE,UAAU,OAAO,UAAU,OAAO,2CAA2C;AAAA,EACxF;AAGA,MAAI;AACJ,MAAI;AACF,WAAOG,WAAU,QAAQ;AAAA,EAC3B,SAAS,KAAK;AACZ,UAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,WAAO,EAAE,UAAU,OAAO,UAAU,OAAO,qBAAqB,GAAG,GAAG;AAAA,EACxE;AAEA,MAAI,KAAK,eAAe,GAAG;AACzB,WAAO,EAAE,UAAU,OAAO,UAAU,OAAO,6BAA6B;AAAA,EAC1E;AAGA,QAAM,OAAO,KAAK;AAElB,MAAI,OAAO,iBAAiB;AAC1B,WAAO;AAAA,MACL,UAAU;AAAA,MACV;AAAA,MACA,OAAO,4BAA4B,gBAAgB,eAAe,CAAC,eAAe,KAAK,eAAe,CAAC;AAAA,IACzG;AAAA,EACF;AAGA,MAAI;AACJ,MAAI;AACF,UAAMF,cAAa,QAAQ;AAAA,EAC7B,SAAS,KAAK;AACZ,UAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,WAAO,EAAE,UAAU,OAAO,UAAU,OAAO,qBAAqB,GAAG,GAAG;AAAA,EACxE;AAGA,MAAI,IAAI,SAAS,iBAAiB;AAChC,WAAO;AAAA,MACL,UAAU;AAAA,MACV;AAAA,MACA,OAAO,uCAAuC,gBAAgB,eAAe,CAAC,eAAe,IAAI,OAAO,eAAe,CAAC;AAAA,IAC1H;AAAA,EACF;AAGA,QAAM,SAAS,cAAc,GAAG;AAGhC,MAAI,CAAC,UAAU,QAAQ,QAAQ,GAAG;AAChC,WAAO;AAAA,MACL,UAAU;AAAA,MACV;AAAA,MACA,OAAO,8BAA8B,SAAS,UAAU,GAAG,CAAC,CAAC,eAAU,OAAO,UAAU,GAAG,CAAC,CAAC;AAAA,IAC/F;AAAA,EACF;AAGA,MAAI;AACF,UAAM,UAAU,IAAI,YAAY,SAAS,EAAE,OAAO,KAAK,CAAC;AACxD,YAAQ,OAAO,GAAG;AAAA,EACpB,QAAQ;AACN,WAAO;AAAA,MACL,UAAU;AAAA,MACV;AAAA,MACA,OAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO,EAAE,UAAU,MAAM,SAAS;AACpC;AAgBO,SAAS,gBAAgB,UAAyC;AAMvE,MAAI,6BAA6B,KAAK,QAAQ,KAAK,SAAS,SAAS,IAAI,GAAG;AAC1E,WAAO;AAAA,MACL,UAAU,CAAC;AAAA,MACX,QAAQ;AAAA,QACN;AAAA,UACE,UAAU;AAAA,UACV,OAAO;AAAA,QACT;AAAA,MACF;AAAA,MACA,SAAS,CAAC;AAAA,IACZ;AAAA,EACF;AAEA,QAAM,WAAqB,CAAC;AAC5B,QAAM,SAAqD,CAAC;AAC5D,QAAM,UAAoB,CAAC;AAE3B,MAAI;AACJ,MAAI;AACF,cAAUC,aAAY,QAAQ;AAAA,EAChC,SAAS,KAAK;AACZ,UAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,WAAO;AAAA,MACL,UAAU,CAAC;AAAA,MACX,QAAQ,CAAC,EAAE,UAAU,eAAe,OAAO,0BAA0B,GAAG,GAAG,CAAC;AAAA,MAC5E,SAAS,CAAC;AAAA,IACZ;AAAA,EACF;AAEA,QAAM,aAAa,QAAQ,OAAO,CAAC,MAAM,EAAE,SAAS,aAAa,CAAC;AAElE,aAAW,YAAY,YAAY;AACjC,UAAM,WAAWE,MAAK,UAAU,QAAQ;AAGxC,QAAI;AACF,UAAID,WAAU,QAAQ,EAAE,eAAe,GAAG;AACxC,eAAO,KAAK,EAAE,UAAU,OAAO,mBAAmB,CAAC;AACnD;AAAA,MACF;AAAA,IACF,QAAQ;AAAA,IAER;AAEA,UAAM,SAAS,gBAAgB,QAAQ;AAEvC,QAAI,OAAO,UAAU;AACnB,eAAS,KAAK,OAAO,QAAQ;AAAA,IAC/B,WAAW,OAAO,OAAO,WAAW,oBAAoB,GAAG;AACzD,cAAQ,KAAK,OAAO,QAAQ;AAAA,IAC9B,OAAO;AACL,aAAO,KAAK,EAAE,UAAU,OAAO,UAAU,OAAO,OAAO,SAAS,gBAAgB,CAAC;AAAA,IACnF;AAAA,EACF;AAGA,aAAW,iBAAiB,oBAAoB,KAAK,GAAG;AACtD,QAAI,CAAC,WAAW,SAAS,aAAa,GAAG;AACvC,aAAO,KAAK,EAAE,UAAU,eAAe,OAAO,yBAAyB,CAAC;AAAA,IAC1E;AAAA,EACF;AAEA,SAAO,EAAE,UAAU,QAAQ,QAAQ;AACrC;AAMA,IAAM,uBAAuB,CAAC,6CAA6C,sBAAsB;AAEjG,SAAS,kBAAiC;AACxC,QAAM,MAAM,QAAQ,IAAI;AACxB,aAAW,YAAY,sBAAsB;AAC3C,UAAM,YAAYC,MAAK,KAAK,QAAQ;AACpC,QAAI;AACF,MAAAD,WAAU,SAAS;AACnB,aAAO;AAAA,IACT,QAAQ;AAAA,IAER;AAAA,EACF;AACA,SAAO;AACT;AA+BO,SAAS,wBAAwB,QAAmC;AACzE,QAAM,SAAS,KAAK,UAAU;AAAA,IAC5B,OAAO;AAAA,IACP,OAAO;AAAA,IACP,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IAClC,QAAQ;AAAA,IACR,UAAU,OAAO;AAAA,IACjB,aAAa,OAAO,OAAO;AAAA,IAC3B,cAAc,OAAO,QAAQ;AAAA,IAC7B,UAAU,OAAO;AAAA,IACjB,SAAS,OAAO;AAAA,EAClB,CAAC;AACD,UAAQ,OAAO,MAAM,kBAAkB,MAAM;AAAA,CAAI;AACnD;AAMO,SAAS,uBAAuBE,SAAyB;AAC9D,EAAAA,QAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,CAAC;AAAA,IACD,YAAY;AACV,YAAM,WAAW,gBAAgB;AAEjC,UAAI,CAAC,UAAU;AACb,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM,KAAK,UAAU;AAAA,gBACnB,OAAO;AAAA,gBACP,SACE,iDAAiD,qBAAqB,KAAK,IAAI;AAAA,cACnF,CAAC;AAAA,YACH;AAAA,UACF;AAAA,UACA,SAAS;AAAA,QACX;AAAA,MACF;AAEA,YAAM,SAAS,gBAAgB,QAAQ;AAEvC,YAAM,UAAU,OAAO,OAAO,WAAW,KAAK,OAAO,QAAQ,WAAW;AAGxE,UAAI,CAAC,SAAS;AACZ,gCAAwB;AAAA,UACtB,UAAU;AAAA,UACV,QAAQ,OAAO;AAAA,UACf,SAAS,OAAO;AAAA,QAClB,CAAC;AAAA,MACH;AAEA,aAAO;AAAA,QACL,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM,KAAK,UAAU;AAAA,cACnB,UAAU;AAAA,cACV,gBAAgB,oBAAoB;AAAA,cACpC,eAAe,OAAO,SAAS;AAAA,cAC/B,aAAa,OAAO,OAAO;AAAA,cAC3B,cAAc,OAAO,QAAQ;AAAA,cAC7B,UAAU,OAAO;AAAA,cACjB,QAAQ,OAAO;AAAA,cACf,SAAS,OAAO;AAAA,cAChB,GAAI,UACA,CAAC,IACD;AAAA,gBACE,OACE;AAAA,cACJ;AAAA,YACN,CAAC;AAAA,UACH;AAAA,QACF;AAAA,QACA,SAAS,CAAC;AAAA,MACZ;AAAA,IACF;AAAA,EACF;AACF;;;ACjaA,SAAS,KAAAC,WAAS;AAClB,SAAS,gBAAAC,eAAc,cAAAC,mBAAkB;AACzC,SAAS,QAAAC,aAAY;AAkBd,SAAS,sBAAsB,OAGpC;AACA,QAAM,MAAM,MAAM,QAAQ,QAAQ,IAAI;AAEtC,QAAM,UACJ;AAAA,IACE;AAAA,MACE,MAAMC,MAAK,KAAK,gBAAgB,aAAa,kBAAkB;AAAA,MAC/D,QAAQ;AAAA,MACR,OAAO,CAAC,QAAQ;AACd,cAAM,SAAS,KAAK,MAAM,GAAG;AAC7B,YAAI,OAAO,WAAW,YAAY,WAAW,QAAQ,MAAM,QAAQ,MAAM,GAAG;AAE1E,iBAAO,CAAC;AAAA,QACV;AACA,eAAO,+BAA+B,MAAiC;AAAA,MACzE;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAMA,MAAK,KAAK,iBAAiB;AAAA,MACjC,QAAQ;AAAA,MACR,OAAO;AAAA,IACT;AAAA,EACF;AAEF,aAAW,EAAE,MAAAC,OAAM,QAAQ,MAAM,KAAK,SAAS;AAC7C,QAAI,CAACC,YAAWD,KAAI,EAAG;AACvB,QAAI;AACF,YAAM,cAAc,MAAME,cAAaF,OAAM,MAAM,CAAC;AACpD,aAAO;AAAA,QACL,MAAM,KAAK,UAAU,EAAE,aAAa,QAAQ,iBAAiB,YAAY,OAAO,CAAC;AAAA,QACjF,SAAS;AAAA,MACX;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,SAAO;AAAA,IACL,MAAM,KAAK,UAAU;AAAA,MACnB,aAAa,CAAC;AAAA,MACd,QAAQ;AAAA,MACR,iBAAiB;AAAA,MACjB,MAAM;AAAA,IACR,CAAC;AAAA,IACD,SAAS;AAAA,EACX;AACF;AAGA,SAAS,+BAA+B,KAAgD;AACtF,QAAM,cAAgC,CAAC;AACvC,QAAM,eAAe,IAAI,gBAAgB,IAAI,eAAe,CAAC;AAC7D,MAAI,CAAC,MAAM,QAAQ,YAAY,EAAG,QAAO;AAEzC,aAAW,QAAQ,cAAc;AAC/B,QAAI,CAAC,QAAQ,OAAO,SAAS,SAAU;AACvC,UAAM,MAAM;AAGZ,QAAI,OAAO,IAAI,SAAS,YAAY,OAAO,IAAI,aAAa,UAAU;AACpE,kBAAY,KAAK,mBAAmB,IAAI,MAAM,IAAI,UAAU,IAAI,IAAI,CAAC;AACrE;AAAA,IACF;AAGA,QAAI,CAAC,MAAM,QAAQ,IAAI,WAAW,EAAG;AACrC,eAAW,OAAO,IAAI,aAAa;AACjC,UAAI,CAAC,OAAO,OAAO,QAAQ,SAAU;AACrC,YAAM,IAAI;AACV,UAAI,OAAO,EAAE,SAAS,YAAY,OAAO,EAAE,aAAa,UAAU;AAChE,oBAAY,KAAK,mBAAmB,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,IAAI,IAAI,CAAC;AAAA,MAC7E;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,mBAAmB,MAAc,UAAkB,MAA+B;AACzF,SAAO,EAAE,MAAM,UAAU,GAAI,OAAO,SAAS,WAAW,EAAE,KAAK,IAAI,CAAC,EAAG;AACzE;AAGA,SAAS,2BAA2B,UAAoC;AACtE,QAAM,cAAgC,CAAC;AACvC,QAAM,QAAQ,SAAS,MAAM,IAAI;AAEjC,MAAI,iBAAiB;AACrB,MAAI,cAA6B;AACjC,MAAI,kBAAiC;AACrC,MAAI,cAA6B;AAEjC,aAAW,QAAQ,OAAO;AACxB,QAAI,KAAK,SAAS,IAAM;AACxB,QAAI,qBAAqB,KAAK,IAAI,GAAG;AACnC,uBAAiB;AACjB;AAAA,IACF;AACA,QAAI,kBAAkB,SAAS,KAAK,IAAI,KAAK,CAAC,KAAK,WAAW,GAAG,GAAG;AAClE,uBAAiB;AAAA,IACnB;AACA,QAAI,CAAC,eAAgB;AAErB,UAAM,cAAc,CAAC,MAAc,EAAE,KAAK,EAAE,QAAQ,gBAAgB,EAAE;AAEtE,UAAM,YAAY,KAAK,MAAM,mBAAmB;AAChD,QAAI,YAAY,CAAC,EAAG,eAAc,YAAY,UAAU,CAAC,CAAC;AAE1D,UAAM,YAAY,KAAK,MAAM,sBAAsB;AACnD,QAAI,YAAY,CAAC,GAAG;AAClB,UAAI,eAAe,iBAAiB;AAClC,oBAAY,KAAK,mBAAmB,aAAa,iBAAiB,WAAW,CAAC;AAAA,MAChF;AACA,oBAAc,YAAY,UAAU,CAAC,CAAC;AACtC,wBAAkB;AAAA,IACpB;AAEA,UAAM,gBAAgB,KAAK,MAAM,uBAAuB;AACxD,QAAI,gBAAgB,CAAC,EAAG,mBAAkB,YAAY,cAAc,CAAC,CAAC;AAAA,EACxE;AAEA,MAAI,eAAe,iBAAiB;AAClC,gBAAY,KAAK,mBAAmB,aAAa,iBAAiB,WAAW,CAAC;AAAA,EAChF;AACA,SAAO;AACT;AAiBA,IAAM,kBAAgD;AAAA,EACpD,cAAc;AAAA,IACZ,UAAU;AAAA,IACV,WAAW;AAAA,IACX,kBAAkB;AAAA,IAClB,OAAO;AAAA,IACP,kBAAkB,EAAE,0BAA0B,UAAU,yBAAyB,SAAS;AAAA,IAC1F,cAAc,CAAC,iBAAiB;AAAA,IAChC,aACE;AAAA,EACJ;AAAA,EACA,YAAY;AAAA,IACV,UAAU;AAAA,IACV,WAAW;AAAA,IACX,mBAAmB;AAAA,IACnB,OAAO;AAAA,IACP,kBAAkB,CAAC;AAAA,IACnB,cAAc,CAAC;AAAA,IACf,aACE;AAAA,EACJ;AAAA,EACA,gBAAgB;AAAA,IACd,UAAU;AAAA,IACV,WAAW;AAAA,IACX,mBAAmB;AAAA,IACnB,OAAO;AAAA,IACP,kBAAkB,CAAC;AAAA,IACnB,cAAc,CAAC;AAAA,IACf,aAAa;AAAA,EACf;AAAA,EACA,YAAY;AAAA,IACV,UAAU;AAAA,IACV,WAAW;AAAA,IACX,mBAAmB;AAAA,IACnB,OAAO;AAAA,IACP,kBAAkB,CAAC;AAAA,IACnB,cAAc,CAAC;AAAA,IACf,aAAa;AAAA,EACf;AACF;AAOO,SAAS,0BAA0B,OAGxC;AACA,QAAM,MAAM,MAAM,SAAS,KAAK,EAAE,YAAY;AAC9C,QAAM,QAAQ,gBAAgB,GAAG;AAEjC,MAAI,CAAC,OAAO;AACV,UAAM,YAAY,OAAO,KAAK,eAAe,EAAE,KAAK,IAAI;AACxD,WAAO;AAAA,MACL,MAAM,KAAK,UAAU;AAAA,QACnB,OAAO;AAAA,QACP,SAAS,sBAAsB,MAAM,QAAQ,wBAAwB,SAAS;AAAA,QAC9E,iBAAiB,OAAO,KAAK,eAAe;AAAA,MAC9C,CAAC;AAAA,MACD,SAAS;AAAA,IACX;AAAA,EACF;AAGA,QAAM,mBAAmB,MAAM,QAC3B,OACA;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,MACJ,aAAa,CAAC,EAAE,MAAM,eAAe,mBAAmB,MAAM,kBAAkB,CAAC;AAAA,IACnF;AAAA,EACF;AAEJ,SAAO;AAAA,IACL,MAAM,KAAK,UAAU,EAAE,GAAG,OAAO,iBAAiB,CAAC;AAAA,IACnD,SAAS;AAAA,EACX;AACF;AAkBA,SAAS,KAAK,QAAuE;AACnF,SAAO,EAAE,MAAM,KAAK,UAAU,EAAE,OAAO,OAAO,QAAQ,UAAU,CAAC,EAAE,CAAC,GAAG,SAAS,KAAK;AACvF;AAMO,SAAS,uBAAuB,OAGrC;AACA,QAAM,MAAM,MAAM,QAAQ,QAAQ,IAAI;AACtC,MAAI;AAGJ,MAAI,MAAM,YAAY,OAAO,KAAK,MAAM,QAAQ,EAAE,SAAS,GAAG;AAC5D,UAAM,MAAM;AAAA,EACd,OAAO;AACL,UAAM,eAAeD,MAAK,KAAK,gBAAgB,aAAa,sBAAsB;AAClF,QAAI,CAACE,YAAW,YAAY,GAAG;AAC7B,aAAO,KAAK;AAAA,QACV;AAAA,UACE,MAAM;AAAA,UACN,SACE;AAAA,QACJ;AAAA,MACF,CAAC;AAAA,IACH;AACA,QAAI;AACF,YAAM,KAAK,MAAMC,cAAa,cAAc,MAAM,CAAC;AAAA,IACrD,SAAS,KAAK;AACZ,aAAO,KAAK,CAAC,EAAE,MAAM,gBAAgB,SAAS,sCAAsC,GAAG,GAAG,CAAC,CAAC;AAAA,IAC9F;AAAA,EACF;AAGA,QAAM,WACJ,IAAI,YAAY,OAAO,IAAI,aAAa,WAAW,IAAI,WAAW;AAGpE,QAAM,SAAoC,CAAC;AAC3C,QAAM,WAAsC,CAAC;AAG7C,MAAI,OAAO,SAAS,OAAO,YAAY,CAAC,SAAS,IAAI;AACnD,WAAO,KAAK,EAAE,MAAM,cAAc,SAAS,2BAA2B,MAAM,cAAc,CAAC;AAAA,EAC7F,WAAW,CAAC,eAAe,KAAK,SAAS,EAAE,GAAG;AAC5C,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,SAAS,gBAAgB,SAAS,EAAE;AAAA,MACpC,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AAGA,MAAI,OAAO,SAAS,UAAU,YAAY,CAAC,SAAS,OAAO;AACzD,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,SAAS;AAAA,MACT,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AAGA,QAAM,QAAQ,SAAS;AACvB,MAAI,CAAC,MAAM,QAAQ,KAAK,GAAG;AACzB,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,SAAS;AAAA,MACT,MAAM;AAAA,IACR,CAAC;AACD,WAAO,EAAE,MAAM,KAAK,UAAU,EAAE,OAAO,OAAO,QAAQ,SAAS,CAAC,GAAG,SAAS,MAAM;AAAA,EACpF;AAEA,MAAI,MAAM,SAAS,GAAG;AACpB,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,SAAS;AAAA,MACT,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AAGA,QAAM,UAAU,oBAAI,IAAY;AAChC,QAAM,eAAyB,CAAC;AAEhC,aAAW,QAAQ,OAAO;AACxB,QAAI,CAAC,QAAQ,OAAO,SAAS,SAAU;AACvC,UAAM,KAAM,KAAiC;AAC7C,QAAI,OAAO,OAAO,YAAY,CAAC,IAAI;AACjC,aAAO,KAAK;AAAA,QACV,MAAM;AAAA,QACN,SAAS;AAAA,QACT,MAAM;AAAA,MACR,CAAC;AACD;AAAA,IACF;AACA,QAAI,CAAC,eAAe,KAAK,EAAE,GAAG;AAC5B,aAAO,KAAK;AAAA,QACV,MAAM;AAAA,QACN,SAAS,YAAY,EAAE;AAAA,QACvB,MAAM,kBAAkB,EAAE;AAAA,MAC5B,CAAC;AAAA,IACH;AACA,QAAI,QAAQ,IAAI,EAAE,EAAG,cAAa,KAAK,EAAE;AACzC,YAAQ,IAAI,EAAE;AAAA,EAChB;AAEA,MAAI,aAAa,SAAS,GAAG;AAC3B,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,SAAS,uBAAuB,aAAa,KAAK,IAAI,CAAC;AAAA,MACvD,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AAGA,QAAM,cAAc,SAAS;AAC7B,MAAI,OAAO,gBAAgB,YAAY,CAAC,aAAa;AACnD,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,SAAS;AAAA,MACT,MAAM;AAAA,IACR,CAAC;AAAA,EACH,WAAW,CAAC,QAAQ,IAAI,WAAW,GAAG;AACpC,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,SAAS,iBAAiB,WAAW,iDAAiD,CAAC,GAAG,OAAO,EAAE,KAAK,IAAI,CAAC;AAAA,MAC7G,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AAGA,aAAW,QAAQ,OAAO;AACxB,QAAI,CAAC,QAAQ,OAAO,SAAS,SAAU;AACvC,UAAM,IAAI;AACV,UAAM,SAAS,OAAO,EAAE,MAAM,IAAI;AAClC,8BAA0B,GAAG,QAAQ,SAAS,MAAM;AACpD,2BAAuB,GAAG,QAAQ,QAAQ;AAAA,EAC5C;AAGA,MAAI,OAAO,SAAS,gBAAgB,YAAY,SAAS,YAAY,WAAW,UAAU,GAAG;AAC3F,aAAS,KAAK;AAAA,MACZ,MAAM;AAAA,MACN,SACE;AAAA,MACF,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AAGA,QAAM,cAAc,MAAM,KAAK,CAAC,SAAkB;AAChD,QAAI,CAAC,QAAQ,OAAO,SAAS,SAAU,QAAO;AAC9C,WAAQ,KAAiC,SAAS;AAAA,EACpD,CAAC;AACD,MAAI,CAAC,aAAa;AAChB,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,SAAS;AAAA,MACT,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AAEA,SAAO,EAAE,MAAM,KAAK,UAAU,EAAE,OAAO,OAAO,WAAW,GAAG,QAAQ,SAAS,CAAC,GAAG,SAAS,MAAM;AAClG;AAGA,SAAS,0BACP,MACA,QACA,SACA,QACM;AACN,QAAM,QAAQ,CAAC,QAAiBF,UAAiB;AAC/C,QAAI,OAAO,WAAW,YAAY,CAAC,QAAQ,IAAI,MAAM,GAAG;AACtD,aAAO,KAAK;AAAA,QACV,MAAM;AAAA,QACN,SAAS,SAAS,MAAM,qBAAqB,MAAM;AAAA,QACnD,MAAAA;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAGA,QAAM,WAAW,KAAK;AACtB,MAAI,YAAY,OAAO,aAAa,UAAU;AAC5C,UAAM,SAAS,YAAY,kBAAkB,MAAM,wBAAwB;AAAA,EAC7E;AAGA,MAAI,MAAM,QAAQ,KAAK,OAAO,GAAG;AAC/B,eAAW,UAAU,KAAK,SAAS;AACjC,UAAI,CAAC,UAAU,OAAO,WAAW,SAAU;AAC3C,YAAM,IAAI;AACV,YAAM,EAAE,YAAY,kBAAkB,MAAM,aAAa,EAAE,MAAM,IAAI,cAAc;AAAA,IACrF;AAAA,EACF;AAGA,MAAI,MAAM,QAAQ,KAAK,UAAU,GAAG;AAClC,eAAW,QAAQ,KAAK,YAAY;AAClC,UAAI,CAAC,QAAQ,OAAO,SAAS,SAAU;AACvC,YAAM,OAAQ,KAAiC;AAC/C,UAAI,QAAQ,OAAO,SAAS,UAAU;AACpC,cAAM,KAAK,YAAY,kBAAkB,MAAM,cAAc;AAAA,MAC/D;AAAA,IACF;AAAA,EACF;AAGA,MAAI,MAAM,QAAQ,KAAK,gBAAgB,GAAG;AACxC,eAAW,OAAO,KAAK;AACrB,YAAM,KAAK,kBAAkB,MAAM,oBAAoB;AAAA,EAC3D;AAGA,QAAM,UAAU,KAAK;AACrB,MAAI,WAAW,OAAO,YAAY,UAAU;AAC1C,UAAM,QAAQ,aAAa,kBAAkB,MAAM,uBAAuB;AAC1E,QAAI,MAAM,QAAQ,QAAQ,YAAY,GAAG;AACvC,iBAAW,OAAO,QAAQ;AACxB,cAAM,KAAK,kBAAkB,MAAM,wBAAwB;AAAA,IAC/D;AAAA,EACF;AACF;AAGA,SAAS,uBACP,MACA,QACA,UACM;AACN,QAAM,YAAY,CAAC,QACjB,OAAO,QAAQ,YAAY,IAAI,WAAW,UAAU;AAEtD,QAAM,OAAO,CAACA,UAAiB;AAC7B,aAAS,KAAK;AAAA,MACZ,MAAM;AAAA,MACN,SAAS,0BAA0BA,KAAI;AAAA,MACvC,MAAAA;AAAA,IACF,CAAC;AAAA,EACH;AAEA,QAAM,WAAW,KAAK;AACtB,MAAI,YAAY,OAAO,aAAa,YAAY,UAAU,SAAS,MAAM;AACvE,SAAK,GAAG,MAAM,mBAAmB;AAEnC,QAAM,UAAU,KAAK;AACrB,MAAI,WAAW,OAAO,YAAY,YAAY,UAAU,QAAQ,MAAM;AACpE,SAAK,GAAG,MAAM,kBAAkB;AAElC,MAAI,MAAM,QAAQ,KAAK,OAAO,GAAG;AAC/B,eAAW,UAAU,KAAK,SAAS;AACjC,UAAI,CAAC,UAAU,OAAO,WAAW,SAAU;AAC3C,YAAM,IAAI;AACV,UAAI,UAAU,EAAE,MAAM,EAAG,MAAK,GAAG,MAAM,YAAY,EAAE,MAAM,IAAI,SAAS;AAAA,IAC1E;AAAA,EACF;AAEA,MAAI,MAAM,QAAQ,KAAK,MAAM,GAAG;AAC9B,eAAW,SAAS,KAAK,QAAQ;AAC/B,UAAI,CAAC,SAAS,OAAO,UAAU,SAAU;AACzC,YAAM,IAAI;AACV,UAAI,UAAU,EAAE,WAAW,EAAG,MAAK,GAAG,MAAM,WAAW,EAAE,QAAQ,IAAI,cAAc;AAAA,IACrF;AAAA,EACF;AACF;AAMO,SAAS,oBAAoBG,SAAyB;AAC3D,QAAM,MAAM,CAAC,OAA2C;AAAA,IACtD,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,EAAE,KAAK,CAAC;AAAA,IACjD,SAAS,EAAE;AAAA,EACb;AAEA,EAAAA,QAAO;AAAA,IACL;AAAA,IACA;AAAA,IAGA,CAAC;AAAA,IACD,YAAY,IAAI,sBAAsB,CAAC,CAAC,CAAC;AAAA,EAC3C;AAEA,EAAAA,QAAO;AAAA,IACL;AAAA,IACA;AAAA,IAGA;AAAA,MACE,UAAUC,IACP,OAAO,EACP;AAAA,QACC;AAAA,MACF;AAAA,IACJ;AAAA,IACA,OAAO,EAAE,SAAS,MAAM,IAAI,0BAA0B,EAAE,SAAS,CAAC,CAAC;AAAA,EACrE;AAEA,EAAAD,QAAO;AAAA,IACL;AAAA,IACA;AAAA,IAGA;AAAA,MACE,UAAU,WAAWC,IAAE,OAAOA,IAAE,OAAO,GAAGA,IAAE,QAAQ,CAAC,EAAE,SAAS,CAAC,EAAE;AAAA,QACjE;AAAA,MACF;AAAA,IACF;AAAA,IACA,OAAO,EAAE,SAAS,MAAM,IAAI,uBAAuB,WAAW,EAAE,SAAS,IAAI,CAAC,CAAC,CAAC;AAAA,EAClF;AACF;;;AClkBA,SAAS,KAAAC,WAAS;AAwCX,SAAS,yBAA4C;AAC1D,SAAO;AAAA,IACL,SAAS;AAAA,IACT,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,IACpC,SAAS;AAAA,MACP,UAAU;AAAA,QACR,aAAa;AAAA,QACb,SAAS;AAAA,UACP;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,QACA,OAAO;AAAA,QACP,aAAa;AAAA,MACf;AAAA,MACA,MAAM;AAAA,QACJ,aAAa;AAAA,QACb,SAAS;AAAA,UACP;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,QACA,OAAO;AAAA,QACP,aAAa;AAAA,MACf;AAAA,MACA,SAAS;AAAA,QACP,aAAa;AAAA,QACb,YAAY;AAAA,UACV;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,QACA,OAAO;AAAA,QACP,aAAa;AAAA,MACf;AAAA,MACA,OAAO;AAAA,QACL,aAAa;AAAA,QACb,YAAY,CAAC,gBAAgB,aAAa,YAAY;AAAA,QACtD,MAAM;AAAA,MACR;AAAA,MACA,YAAY;AAAA,QACV,aAAa;AAAA,QACb,YAAY;AAAA,UACV;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,QACA,MAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACF;AAEO,SAAS,wBAAwBC,SAAyB;AAC/D,EAAAA,QAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,MACE,QAAQD,IACL,KAAK,CAAC,QAAQ,cAAc,CAAC,EAC7B,SAAS,EACT,QAAQ,MAAM,EACd,SAAS,2EAA2E;AAAA,IACzF;AAAA,IACA,OAAO,EAAE,OAAO,MAAM;AACpB,YAAM,UAAU,uBAAuB;AACvC,YAAM,SAAS,WAAW,iBAAiB,OAAO,KAAK,QAAQ,OAAO,IAAI;AAC1E,aAAO;AAAA,QACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,QAAQ,MAAM,CAAC,EAAE,CAAC;AAAA,MACnE;AAAA,IACF;AAAA,EACF;AACF;;;AC3IA;AAAA,EACE,cAAgB;AAAA,IACd,0BAA0B;AAAA,IAC1B,6BAA6B;AAAA,IAC7B,sCAAsC;AAAA,IACtC,KAAO;AAAA,EACT;AAAA,EACA,iBAAmB;AAAA,IACjB,eAAe;AAAA,IACf,MAAQ;AAAA,IACR,YAAc;AAAA,IACd,QAAU;AAAA,EACZ;AAAA,EACA,SAAW;AAAA,IACT,gBAAkB;AAAA,IAClB,OAAS;AAAA,IACT,KAAO;AAAA,IACP,OAAS;AAAA,IACT,MAAQ;AAAA,IACR,iBAAiB;AAAA,EACnB;AAAA,EACA,MAAQ;AAAA,EACR,SAAW;AAAA,EACX,aAAe;AAAA,EACf,SAAW;AAAA,EACX,MAAQ;AAAA,EACR,KAAO;AAAA,IACL,uBAAuB;AAAA,EACzB;AAAA,EACA,QAAU;AAAA,EACV,OAAS;AAAA,EACT,SAAW;AAAA,IACT,KAAK;AAAA,MACH,OAAS;AAAA,MACT,QAAU;AAAA,MACV,SAAW;AAAA,IACb;AAAA,IACA,eAAe;AAAA,MACb,OAAS;AAAA,MACT,QAAU;AAAA,MACV,SAAW;AAAA,IACb;AAAA,IACA,kBAAkB;AAAA,MAChB,OAAS;AAAA,MACT,QAAU;AAAA,MACV,SAAW;AAAA,IACb;AAAA,EACF;AAAA,EACA,OAAS;AAAA,IACP;AAAA,EACF;AAAA,EACA,eAAiB;AAAA,IACf,QAAU;AAAA,EACZ;AACF;;;AlBnCA,IAAM,SAAS,IAAI,UAAU;AAAA,EAC3B,MAAM;AAAA,EACN,SAAS,gBAAY;AACvB,CAAC;AAGD,0BAA0B,MAAM;AAChC,sBAAsB,MAAM;AAC5B,iBAAiB,MAAM;AACvB,uBAAuB,MAAM;AAC7B,2BAA2B,MAAM;AACjC,qBAAqB,MAAM;AAC3B,sBAAsB,MAAM;AAC5B,2BAA2B,MAAM;AACjC,sBAAsB,MAAM;AAC5B,uBAAuB,MAAM;AAC7B,kBAAkB,MAAM;AACxB,uBAAuB,MAAM;AAC7B,6BAA6B,MAAM;AACnC,oBAAoB,MAAM;AAC1B,wBAAwB,MAAM;AAE9B,eAAe,OAAO;AACpB,QAAM,YAAY,IAAI,qBAAqB;AAC3C,QAAM,OAAO,QAAQ,SAAS;AAC9B,UAAQ,MAAM,6CAA6C;AAC7D;AAEA,KAAK,EAAE,MAAM,CAAC,QAAQ;AACpB,UAAQ,MAAM,UAAU,GAAG;AAC3B,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":["z","server","z","path","z","server","z","server","z","z","listEntities","server","z","listEntities","z","server","z","z","path","server","z","path","existsSync","lstatSync","z","z","server","existsSync","lstatSync","z","readFileSync","writeFileSync","existsSync","mkdirSync","lstatSync","join","join","mkdirSync","existsSync","lstatSync","writeFileSync","readFileSync","server","z","z","readFileSync","writeFileSync","existsSync","mkdirSync","lstatSync","join","createHash","createHash","readFileSync","writeFileSync","existsSync","mkdirSync","lstatSync","join","z","join","existsSync","readFileSync","mkdirSync","writeFileSync","server","z","PHASE_TO_OTTER","join","existsSync","lstatSync","writeFileSync","readFileSync","mkdirSync","phase","createHash","artifact","server","z","z","writeFileSync","existsSync","mkdirSync","lstatSync","join","server","z","z","readFileSync","writeFileSync","existsSync","join","scopes","writeFileSync","join","existsSync","readFileSync","server","z","createHash","timingSafeEqual","readFileSync","readdirSync","lstatSync","join","server","z","readFileSync","existsSync","join","join","path","existsSync","readFileSync","server","z","z","server"]}
|