@oddessentials/odd-docs 2.1.0 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -6,7 +6,7 @@ import { createRequire } from "module";
6
6
 
7
7
  // src/cli/commands/generate.ts
8
8
  import { writeFile, mkdir } from "fs/promises";
9
- import { join as join2, resolve } from "path";
9
+ import { join as join2, resolve as resolve2, relative as relative2 } from "path";
10
10
 
11
11
  // src/core/parser/manifestParser.ts
12
12
  import { readFile } from "fs/promises";
@@ -654,11 +654,72 @@ function getThemeScript() {
654
654
  `;
655
655
  }
656
656
 
657
+ // src/core/safety.ts
658
+ import { resolve, relative, sep } from "path";
659
+ import { realpathSync, existsSync } from "fs";
660
+ var FORBIDDEN_PATTERNS = [
661
+ ".git/**",
662
+ "node_modules/**",
663
+ ".env*",
664
+ "package-lock.json",
665
+ "*.log"
666
+ ];
667
+ function resolveAndCheckPath(projectRoot, relPath) {
668
+ const rootReal = realpathSync(projectRoot);
669
+ const candidate = resolve(projectRoot, relPath);
670
+ let resolved;
671
+ if (existsSync(candidate)) {
672
+ resolved = realpathSync(candidate);
673
+ } else {
674
+ resolved = resolve(projectRoot, relPath);
675
+ }
676
+ const rootWithSep = rootReal.endsWith(sep) ? rootReal : rootReal + sep;
677
+ if (!resolved.startsWith(rootWithSep) && resolved !== rootReal) {
678
+ throw new Error(`Path escapes project root: ${relPath}`);
679
+ }
680
+ return resolved;
681
+ }
682
+ function checkForbidden(relPath, extraPatterns = []) {
683
+ const p = relPath.replace(/\\/g, "/");
684
+ if (!p) {
685
+ return { forbidden: true, rule: "<empty path>" };
686
+ }
687
+ const patterns = [...FORBIDDEN_PATTERNS, ...extraPatterns];
688
+ for (const rule of patterns) {
689
+ if (matchesPattern(p, rule)) {
690
+ return { forbidden: true, rule };
691
+ }
692
+ }
693
+ return { forbidden: false };
694
+ }
695
+ function matchesPattern(path, pattern) {
696
+ const p = path.replace(/\\/g, "/");
697
+ const pat = pattern.replace(/\\/g, "/");
698
+ if (pat.includes("**")) {
699
+ const prefix = pat.split("**")[0];
700
+ return p.startsWith(prefix);
701
+ }
702
+ if (pat.includes("*")) {
703
+ const regex = new RegExp("^" + pat.replace(/\*/g, "[^/]*") + "$");
704
+ return regex.test(p);
705
+ }
706
+ return p === pat;
707
+ }
708
+ function validateOutputPath(projectRoot, outputPath) {
709
+ const absPath = resolveAndCheckPath(projectRoot, outputPath);
710
+ const relPath = relative(projectRoot, absPath);
711
+ const forbidden = checkForbidden(relPath);
712
+ if (forbidden.forbidden) {
713
+ throw new Error(`Forbidden path: ${relPath} (matched: ${forbidden.rule})`);
714
+ }
715
+ return absPath;
716
+ }
717
+
657
718
  // src/cli/commands/generate.ts
658
719
  async function generate(repoPath, options = {}) {
659
- const absPath = resolve(repoPath);
720
+ const absPath = resolve2(repoPath);
660
721
  const format = options.format ?? "md";
661
- const outputDir = options.output ? resolve(options.output) : join2(absPath, "docs", "generated");
722
+ const outputDir = options.output ? resolve2(options.output) : join2(absPath, "docs", "generated");
662
723
  console.log(`Generating documentation for: ${absPath}`);
663
724
  const manifestResult = await parseManifest(absPath);
664
725
  console.log(` Entity: ${manifestResult.entity.id}@${manifestResult.entity.version}`);
@@ -667,24 +728,33 @@ async function generate(repoPath, options = {}) {
667
728
  await mkdir(outputDir, { recursive: true });
668
729
  if (format === "md" || format === "both") {
669
730
  const markdown = renderMarkdown(ir);
670
- const mdPath = join2(outputDir, `${ir.entity.id}.md`);
731
+ const mdPath = validateOutputPath(
732
+ absPath,
733
+ relative2(absPath, join2(outputDir, `${ir.entity.id}.md`))
734
+ );
671
735
  await writeFile(mdPath, markdown, "utf-8");
672
736
  console.log(` \u2713 Markdown: ${mdPath}`);
673
737
  }
674
738
  if (format === "html" || format === "both") {
675
739
  const html = renderHTML(ir);
676
- const htmlPath = join2(outputDir, `${ir.entity.id}.html`);
740
+ const htmlPath = validateOutputPath(
741
+ absPath,
742
+ relative2(absPath, join2(outputDir, `${ir.entity.id}.html`))
743
+ );
677
744
  await writeFile(htmlPath, html, "utf-8");
678
745
  console.log(` \u2713 HTML: ${htmlPath}`);
679
746
  }
680
- const irPath = join2(outputDir, `${ir.entity.id}.ir.json`);
747
+ const irPath = validateOutputPath(
748
+ absPath,
749
+ relative2(absPath, join2(outputDir, `${ir.entity.id}.ir.json`))
750
+ );
681
751
  await writeFile(irPath, JSON.stringify(ir, null, 2), "utf-8");
682
752
  console.log(` \u2713 Doc IR: ${irPath}`);
683
753
  console.log("Done!");
684
754
  }
685
755
 
686
756
  // src/cli/commands/validate.ts
687
- import { resolve as resolve2 } from "path";
757
+ import { resolve as resolve3 } from "path";
688
758
 
689
759
  // src/core/capabilities.ts
690
760
  var KNOWN_CAPABILITIES = [
@@ -859,7 +929,7 @@ function formatValidationResult(result, repoPath) {
859
929
 
860
930
  // src/cli/commands/validate.ts
861
931
  async function validate(repoPath, options = {}) {
862
- const absPath = resolve2(repoPath);
932
+ const absPath = resolve3(repoPath);
863
933
  console.log(`Validating: ${absPath}`);
864
934
  console.log(`Mode: ${options.strict ? "strict" : "normal"}`);
865
935
  console.log("");
@@ -878,8 +948,8 @@ async function validate(repoPath, options = {}) {
878
948
  }
879
949
 
880
950
  // src/cli/commands/serve.ts
881
- import { existsSync } from "fs";
882
- import { join as join4, resolve as resolve3 } from "path";
951
+ import { existsSync as existsSync2 } from "fs";
952
+ import { join as join4, resolve as resolve4 } from "path";
883
953
 
884
954
  // src/server/index.ts
885
955
  import { createServer } from "http";
@@ -887,7 +957,7 @@ import { createServer } from "http";
887
957
  // src/server/fileServer.ts
888
958
  import { createReadStream, statSync } from "fs";
889
959
  import { realpath } from "fs/promises";
890
- import { join as join3, extname, relative, isAbsolute } from "path";
960
+ import { join as join3, extname, relative as relative3, isAbsolute } from "path";
891
961
  import { createHash as createHash2 } from "crypto";
892
962
  var MAX_RESPONSE_SIZE = 50 * 1024 * 1024;
893
963
  var MIME_TYPES = {
@@ -980,7 +1050,7 @@ var FileServer = class {
980
1050
  } catch {
981
1051
  return null;
982
1052
  }
983
- const rel = relative(this.resolvedRoot, resolvedTarget);
1053
+ const rel = relative3(this.resolvedRoot, resolvedTarget);
984
1054
  if (rel.startsWith("..") || isAbsolute(rel)) {
985
1055
  console.warn(`[odd-docs] Path traversal blocked: ${pathname}`);
986
1056
  return null;
@@ -1337,7 +1407,7 @@ var OddDocsServer = class {
1337
1407
  });
1338
1408
  await this.liveReload.start();
1339
1409
  }
1340
- return new Promise((resolve4, reject) => {
1410
+ return new Promise((resolve5, reject) => {
1341
1411
  this.server.listen(this.options.port, this.options.host, () => {
1342
1412
  console.log(
1343
1413
  `[odd-docs] Server started at http://${this.options.host}:${this.options.port}`
@@ -1346,7 +1416,7 @@ var OddDocsServer = class {
1346
1416
  if (this.liveReload) {
1347
1417
  console.log(`[odd-docs] Live reload: ${this.options.reloadMode}`);
1348
1418
  }
1349
- resolve4();
1419
+ resolve5();
1350
1420
  });
1351
1421
  this.server.on("error", reject);
1352
1422
  });
@@ -1356,8 +1426,8 @@ var OddDocsServer = class {
1356
1426
  await this.liveReload.stop();
1357
1427
  }
1358
1428
  if (this.server) {
1359
- return new Promise((resolve4) => {
1360
- this.server.close(() => resolve4());
1429
+ return new Promise((resolve5) => {
1430
+ this.server.close(() => resolve5());
1361
1431
  });
1362
1432
  }
1363
1433
  }
@@ -1386,9 +1456,9 @@ var OddDocsServer = class {
1386
1456
 
1387
1457
  // src/cli/commands/serve.ts
1388
1458
  async function serve(repoPath, options = {}) {
1389
- const resolvedPath = resolve3(repoPath);
1390
- const outputDir = options.output ? resolve3(options.output) : join4(resolvedPath, "docs", "generated");
1391
- if (!existsSync(outputDir)) {
1459
+ const resolvedPath = resolve4(repoPath);
1460
+ const outputDir = options.output ? resolve4(options.output) : join4(resolvedPath, "docs", "generated");
1461
+ if (!existsSync2(outputDir)) {
1392
1462
  console.log("[odd-docs] Documentation not found, generating...");
1393
1463
  await generate(repoPath, { output: outputDir, format: "html" });
1394
1464
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/cli/index.ts","../../src/cli/commands/generate.ts","../../src/core/parser/manifestParser.ts","../../src/core/ir/builder.ts","../../src/core/parser/schemaParser.ts","../../src/core/renderer/markdownRenderer.ts","../../src/core/renderer/htmlRenderer.ts","../../src/cli/commands/validate.ts","../../src/core/capabilities.ts","../../src/core/ir/validator.ts","../../src/cli/commands/serve.ts","../../src/server/index.ts","../../src/server/fileServer.ts","../../src/server/livereload.ts","../../src/server/api.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { Command } from 'commander';\nimport { createRequire } from 'node:module';\nimport { generate } from './commands/generate.js';\nimport { validate } from './commands/validate.js';\nimport { serve } from './commands/serve.js';\n\n// Use createRequire for cross-platform compatibility with npx\n// This approach works reliably when the package is installed via npm/npx\nconst require = createRequire(import.meta.url);\nconst packageJson = require('../../package.json') as { version: string };\n\n// Handle --version explicitly before commander for reliable npx output\n// Commander's .version() output may not be captured properly by npx\nif (process.argv.includes('--version') || process.argv.includes('-V')) {\n console.log(packageJson.version);\n process.exit(0);\n}\n\nconst program = new Command();\n\nprogram.name('odd-docs').description('MCP-native documentation generator');\n\nprogram\n .command('generate')\n .description('Generate documentation for an MCP repo')\n .argument('<repo-path>', 'Path to the repository')\n .option('-f, --format <format>', 'Output format: md, html, or both', 'md')\n .option('-o, --output <dir>', 'Output directory')\n .option('--introspect <url>', 'MCP server URL for live introspection')\n .action(async (repoPath: string, options) => {\n try {\n await generate(repoPath, {\n format: options.format,\n output: options.output,\n introspect: options.introspect,\n });\n } catch (error) {\n console.error('Error:', error instanceof Error ? error.message : error);\n process.exit(1);\n }\n });\n\nprogram\n .command('validate')\n .description('Validate documentation inputs for an MCP repo')\n .argument('<repo-path>', 'Path to the repository')\n .option('-s, --strict', 'Fail on unknown safety-affecting capabilities')\n .action(async (repoPath: string, options) => {\n try {\n const valid = await validate(repoPath, { strict: options.strict });\n process.exit(valid ? 0 : 1);\n } catch (error) {\n console.error('Error:', error instanceof Error ? error.message : error);\n process.exit(1);\n }\n });\n\nprogram\n .command('serve')\n .description('Start a local dev server for generated documentation')\n .argument('<repo-path>', 'Path to the repository')\n .option('-p, --port <port>', 'Port to listen on', '3000')\n .option('-H, --host <host>', 'Host to bind (default: localhost for safety)', 'localhost')\n .option('-o, --output <dir>', 'Documentation output directory')\n .option('--no-watch', 'Disable file watching')\n .option('--watch-mode <mode>', 'Watch mode: auto or poll (use poll for Docker/NFS)', 'auto')\n .option('--reload <mode>', 'Reload mechanism: ws, sse, poll, none', 'ws')\n .option('--no-open', 'Do not open browser on start')\n .option('--introspect <target>', 'MCP target: http://host:port or stdio:<cmd>')\n .option('--enable-mutations', 'Enable mutation API endpoints (requires token)')\n .option('--mutation-token <token>', 'Token for mutation endpoints (or ODD_DOCS_MUTATION_TOKEN)')\n .action(async (repoPath: string, options) => {\n try {\n await serve(repoPath, {\n port: parseInt(options.port, 10),\n host: options.host,\n output: options.output,\n watch: options.watch,\n watchMode: options.watchMode,\n reload: options.reload,\n open: options.open,\n introspect: options.introspect,\n enableMutations: options.enableMutations,\n mutationToken: options.mutationToken,\n });\n } catch (error) {\n console.error('Error:', error instanceof Error ? error.message : error);\n process.exit(1);\n }\n });\n\nprogram.parse();\n","import { writeFile, mkdir } from 'node:fs/promises';\nimport { join, resolve } from 'node:path';\nimport { parseManifest } from '../../core/parser/manifestParser.js';\nimport { buildDocIR } from '../../core/ir/builder.js';\nimport { renderMarkdown } from '../../core/renderer/markdownRenderer.js';\nimport { renderHTML } from '../../core/renderer/htmlRenderer.js';\n\nexport interface GenerateOptions {\n format?: 'md' | 'html' | 'both';\n output?: string;\n introspect?: string;\n}\n\nexport async function generate(repoPath: string, options: GenerateOptions = {}): Promise<void> {\n const absPath = resolve(repoPath);\n const format = options.format ?? 'md';\n const outputDir = options.output ? resolve(options.output) : join(absPath, 'docs', 'generated');\n\n console.log(`Generating documentation for: ${absPath}`);\n\n // Parse manifest\n const manifestResult = await parseManifest(absPath);\n console.log(` Entity: ${manifestResult.entity.id}@${manifestResult.entity.version}`);\n\n // Build Doc IR\n const ir = buildDocIR(manifestResult);\n console.log(` Determinism key: ${ir.determinismKey}`);\n\n // Ensure output directory exists\n await mkdir(outputDir, { recursive: true });\n\n // Render formats\n if (format === 'md' || format === 'both') {\n const markdown = renderMarkdown(ir);\n const mdPath = join(outputDir, `${ir.entity.id}.md`);\n await writeFile(mdPath, markdown, 'utf-8');\n console.log(` ✓ Markdown: ${mdPath}`);\n }\n\n if (format === 'html' || format === 'both') {\n const html = renderHTML(ir);\n const htmlPath = join(outputDir, `${ir.entity.id}.html`);\n await writeFile(htmlPath, html, 'utf-8');\n console.log(` ✓ HTML: ${htmlPath}`);\n }\n\n // Write IR for debugging/caching\n const irPath = join(outputDir, `${ir.entity.id}.ir.json`);\n await writeFile(irPath, JSON.stringify(ir, null, 2), 'utf-8');\n console.log(` ✓ Doc IR: ${irPath}`);\n\n console.log('Done!');\n}\n","import { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { DocIR, Capability, SchemaSection } from '../ir/types.js';\n\ninterface ToolManifest {\n tool_id: string;\n version: string;\n description?: string;\n execution_mode?: 'IN_PROCESS' | 'RUNNER';\n parameters?: Record<string, unknown>;\n capabilities?: {\n network?: string[];\n filesystem?: string[];\n secrets?: string[];\n };\n timeout_ms?: number;\n resource_limits?: {\n memory_mb?: number;\n cpu_cores?: number;\n };\n deprecation?: {\n deprecated_at: string;\n sunset_date: string;\n migration_url?: string;\n };\n}\n\nexport interface ManifestParseResult {\n entity: DocIR['entity'];\n inputs: SchemaSection;\n constraints?: DocIR['constraints'];\n lifecycle?: DocIR['lifecycle'];\n}\n\n/**\n * Parse an MCP tool manifest file into partial Doc IR\n */\nexport async function parseManifest(repoPath: string): Promise<ManifestParseResult> {\n const manifestPath = join(repoPath, 'manifest.json');\n\n let content: string;\n try {\n content = await readFile(manifestPath, 'utf-8');\n } catch {\n throw new Error(`Manifest not found: ${manifestPath}`);\n }\n\n let manifest: ToolManifest;\n try {\n manifest = JSON.parse(content) as ToolManifest;\n } catch {\n throw new Error(`Invalid JSON in manifest: ${manifestPath}`);\n }\n\n // Validate required fields\n if (!manifest.tool_id) {\n throw new Error('Manifest missing required field: tool_id');\n }\n if (!manifest.version) {\n throw new Error('Manifest missing required field: version');\n }\n\n // Build capabilities array\n const capabilities: Capability[] = [];\n if (manifest.capabilities) {\n for (const [type, values] of Object.entries(manifest.capabilities)) {\n if (Array.isArray(values) && values.length > 0) {\n capabilities.push({ type, values, provenance: 'manifest' });\n }\n }\n }\n\n const result: ManifestParseResult = {\n entity: {\n type: 'tool',\n id: manifest.tool_id,\n version: manifest.version,\n description: manifest.description,\n },\n inputs: {\n schema: manifest.parameters,\n provenance: 'manifest',\n },\n };\n\n // Add constraints if present\n if (capabilities.length > 0 || manifest.timeout_ms || manifest.resource_limits) {\n result.constraints = {\n capabilities: capabilities.length > 0 ? capabilities : undefined,\n timeoutMs: manifest.timeout_ms,\n resourceLimits: manifest.resource_limits\n ? {\n memoryMb: manifest.resource_limits.memory_mb,\n cpuCores: manifest.resource_limits.cpu_cores,\n }\n : undefined,\n };\n }\n\n // Add lifecycle if deprecation present\n if (manifest.deprecation) {\n result.lifecycle = {\n version: manifest.version,\n deprecation: {\n deprecatedAt: manifest.deprecation.deprecated_at,\n sunsetDate: manifest.deprecation.sunset_date,\n migrationUrl: manifest.deprecation.migration_url,\n },\n };\n }\n\n return result;\n}\n","import { createHash } from 'node:crypto';\nimport type { DocIR } from './types.js';\nimport { enrichSchemaSection } from '../parser/schemaParser.js';\nimport type { ManifestParseResult } from '../parser/manifestParser.js';\n\n/**\n * Build a complete Doc IR from parsed sources\n */\nexport function buildDocIR(manifest: ManifestParseResult): DocIR {\n const enrichedInputs = enrichSchemaSection(manifest.inputs);\n\n const ir: DocIR = {\n version: '1.0.0',\n generatedAt: new Date().toISOString(),\n determinismKey: '', // Computed below\n entity: manifest.entity,\n inputs: enrichedInputs,\n constraints: manifest.constraints,\n lifecycle: manifest.lifecycle,\n provenance: {\n entity: 'manifest',\n inputs: 'manifest',\n },\n };\n\n // Compute determinism key\n ir.determinismKey = computeDeterminismKey(ir);\n\n return ir;\n}\n\n/**\n * Compute SHA-256 determinism key for caching and diffing\n */\nexport function computeDeterminismKey(ir: Omit<DocIR, 'determinismKey' | 'generatedAt'>): string {\n const canonical = JSON.stringify({\n entity: ir.entity,\n inputs: ir.inputs,\n constraints: ir.constraints,\n lifecycle: ir.lifecycle,\n });\n\n const hash = createHash('sha256').update(canonical).digest('hex');\n return `sha256:${hash}`;\n}\n","import type { Parameter, SchemaSection } from '../ir/types.js';\n\ninterface JSONSchema {\n type?: string;\n properties?: Record<string, JSONSchema>;\n required?: string[];\n description?: string;\n default?: unknown;\n enum?: unknown[];\n minimum?: number;\n maximum?: number;\n minLength?: number;\n maxLength?: number;\n pattern?: string;\n items?: JSONSchema;\n $ref?: string;\n}\n\n/**\n * Parse JSON Schema into a list of parameters for documentation\n */\nexport function parseSchema(schema: Record<string, unknown> | undefined): Parameter[] {\n if (!schema) return [];\n\n const jsonSchema = schema as JSONSchema;\n const parameters: Parameter[] = [];\n const required = new Set(jsonSchema.required ?? []);\n\n if (jsonSchema.properties) {\n for (const [name, propSchema] of Object.entries(jsonSchema.properties)) {\n parameters.push(parseProperty(name, propSchema, required.has(name)));\n }\n }\n\n return parameters;\n}\n\nfunction parseProperty(name: string, schema: JSONSchema, isRequired: boolean): Parameter {\n const param: Parameter = {\n name,\n type: resolveType(schema),\n required: isRequired,\n };\n\n if (schema.description) {\n param.description = schema.description;\n }\n\n if (schema.default !== undefined) {\n param.default = schema.default;\n }\n\n if (schema.enum) {\n param.enum = schema.enum;\n }\n\n // Build constraints string\n const constraints = buildConstraints(schema);\n if (constraints) {\n param.constraints = constraints;\n }\n\n return param;\n}\n\nfunction resolveType(schema: JSONSchema): string {\n if (schema.$ref) {\n // Extract type name from $ref\n const refParts = schema.$ref.split('/');\n return refParts[refParts.length - 1];\n }\n\n if (schema.enum) {\n return 'enum';\n }\n\n if (schema.type === 'array' && schema.items) {\n return `${resolveType(schema.items)}[]`;\n }\n\n return schema.type ?? 'unknown';\n}\n\nfunction buildConstraints(schema: JSONSchema): string | undefined {\n const parts: string[] = [];\n\n if (schema.minimum !== undefined) {\n parts.push(`min: ${schema.minimum}`);\n }\n if (schema.maximum !== undefined) {\n parts.push(`max: ${schema.maximum}`);\n }\n if (schema.minLength !== undefined) {\n parts.push(`minLength: ${schema.minLength}`);\n }\n if (schema.maxLength !== undefined) {\n parts.push(`maxLength: ${schema.maxLength}`);\n }\n if (schema.pattern) {\n parts.push(`pattern: ${schema.pattern}`);\n }\n\n return parts.length > 0 ? parts.join(', ') : undefined;\n}\n\n/**\n * Enrich a SchemaSection with parsed parameters\n */\nexport function enrichSchemaSection(section: SchemaSection): SchemaSection {\n return {\n ...section,\n parameters: parseSchema(section.schema),\n };\n}\n","import type { DocIR, Parameter, ProvenanceSource } from '../ir/types.js';\n\n/**\n * Render Doc IR to Markdown\n */\nexport function renderMarkdown(ir: DocIR): string {\n const lines: string[] = [];\n\n // Header\n lines.push(`# ${ir.entity.id}`);\n lines.push('');\n lines.push(`**Version:** ${ir.entity.version} `);\n lines.push(`**Type:** ${ir.entity.type} `);\n if (ir.entity.description) {\n lines.push('');\n lines.push(ir.entity.description);\n }\n lines.push('');\n\n // Overview\n if (ir.overview) {\n lines.push('## Overview');\n lines.push('');\n if (ir.overview.intent) {\n lines.push(`**Intent:** ${ir.overview.intent}`);\n lines.push('');\n }\n if (ir.overview.useCases?.length) {\n lines.push('### Use Cases');\n lines.push('');\n for (const useCase of ir.overview.useCases) {\n lines.push(`- ${useCase}`);\n }\n lines.push('');\n }\n if (ir.overview.sideEffects?.length) {\n lines.push('### Side Effects');\n lines.push('');\n for (const effect of ir.overview.sideEffects) {\n lines.push(\n `- **${effect.type}**: ${effect.description} ${provenanceBadge(effect.provenance)}`\n );\n }\n lines.push('');\n }\n }\n\n // Inputs\n if (ir.inputs?.parameters?.length) {\n lines.push('## Inputs');\n lines.push('');\n lines.push(provenanceBadge(ir.inputs.provenance));\n lines.push('');\n lines.push(renderParameterTable(ir.inputs.parameters));\n lines.push('');\n }\n\n // Outputs\n if (ir.outputs?.parameters?.length) {\n lines.push('## Outputs');\n lines.push('');\n lines.push(provenanceBadge(ir.outputs.provenance));\n lines.push('');\n lines.push(renderParameterTable(ir.outputs.parameters));\n lines.push('');\n }\n\n // Constraints\n if (ir.constraints) {\n lines.push('## Constraints');\n lines.push('');\n if (ir.constraints.capabilities?.length) {\n lines.push('### Capabilities');\n lines.push('');\n for (const cap of ir.constraints.capabilities) {\n const values = cap.values?.join(', ') ?? 'enabled';\n lines.push(`- **${cap.type}**: ${values} ${provenanceBadge(cap.provenance)}`);\n }\n lines.push('');\n }\n if (ir.constraints.timeoutMs) {\n lines.push(`**Timeout:** ${ir.constraints.timeoutMs}ms`);\n lines.push('');\n }\n if (ir.constraints.resourceLimits) {\n lines.push('### Resource Limits');\n lines.push('');\n if (ir.constraints.resourceLimits.memoryMb) {\n lines.push(`- Memory: ${ir.constraints.resourceLimits.memoryMb} MB`);\n }\n if (ir.constraints.resourceLimits.cpuCores) {\n lines.push(`- CPU: ${ir.constraints.resourceLimits.cpuCores} cores`);\n }\n lines.push('');\n }\n }\n\n // Errors\n if (ir.errors?.length) {\n lines.push('## Errors');\n lines.push('');\n lines.push('| Code | Description | Recovery |');\n lines.push('|------|-------------|----------|');\n for (const err of ir.errors) {\n lines.push(`| \\`${err.code}\\` | ${err.description ?? ''} | ${err.recovery ?? ''} |`);\n }\n lines.push('');\n }\n\n // Lifecycle\n if (ir.lifecycle?.deprecation) {\n lines.push('## Lifecycle');\n lines.push('');\n lines.push('> [!WARNING]');\n lines.push(`> This tool is deprecated as of ${ir.lifecycle.deprecation.deprecatedAt}.`);\n lines.push(`> Sunset date: ${ir.lifecycle.deprecation.sunsetDate}`);\n if (ir.lifecycle.deprecation.migrationUrl) {\n lines.push(`> Migration guide: ${ir.lifecycle.deprecation.migrationUrl}`);\n }\n lines.push('');\n }\n\n // Examples\n if (ir.narrative?.examples?.length) {\n lines.push('## Examples');\n lines.push('');\n for (const example of ir.narrative.examples) {\n if (example.title) {\n lines.push(`### ${example.title}`);\n lines.push('');\n }\n if (example.description) {\n lines.push(example.description);\n lines.push('');\n }\n if (example.input) {\n lines.push('**Input:**');\n lines.push('```json');\n lines.push(JSON.stringify(example.input, null, 2));\n lines.push('```');\n lines.push('');\n }\n if (example.output) {\n lines.push('**Output:**');\n lines.push('```json');\n lines.push(JSON.stringify(example.output, null, 2));\n lines.push('```');\n lines.push('');\n }\n }\n }\n\n // Notes\n if (ir.narrative?.notes?.length) {\n lines.push('## Notes');\n lines.push('');\n lines.push('*[author notes]*');\n lines.push('');\n for (const note of ir.narrative.notes) {\n lines.push(note);\n lines.push('');\n }\n }\n\n // Footer\n lines.push('---');\n lines.push('');\n lines.push(`*Generated at ${ir.generatedAt}* `);\n lines.push(`*Determinism key: \\`${ir.determinismKey}\\`*`);\n\n return lines.join('\\n');\n}\n\nfunction renderParameterTable(params: Parameter[]): string {\n const lines: string[] = [];\n lines.push('| Name | Type | Required | Default | Description |');\n lines.push('|------|------|----------|---------|-------------|');\n\n for (const param of params) {\n const required = param.required ? '✓' : '';\n const defaultVal = param.default !== undefined ? `\\`${JSON.stringify(param.default)}\\`` : '';\n const desc = param.description ?? '';\n lines.push(`| \\`${param.name}\\` | \\`${param.type}\\` | ${required} | ${defaultVal} | ${desc} |`);\n }\n\n return lines.join('\\n');\n}\n\nfunction provenanceBadge(source?: ProvenanceSource): string {\n if (!source) return '';\n const badges: Record<ProvenanceSource, string> = {\n introspection: '`[from introspection]`',\n manifest: '`[from schema]`',\n overlay: '`[from overlay]`',\n narrative: '`[author notes]`',\n };\n return badges[source] ?? '';\n}\n","import { marked } from 'marked';\nimport type { DocIR } from '../ir/types.js';\nimport { renderMarkdown } from './markdownRenderer.js';\n\n/**\n * Render Doc IR to static HTML\n */\nexport function renderHTML(ir: DocIR): string {\n // First render to markdown, then convert to HTML\n const markdown = renderMarkdown(ir);\n const htmlContent = marked.parse(markdown) as string;\n\n return `<!DOCTYPE html>\n<html lang=\"en\" data-theme=\"light\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <meta name=\"description\" content=\"${escapeHtml(ir.entity.description ?? `Documentation for ${ir.entity.id}`)}\">\n <title>${escapeHtml(ir.entity.id)} - odd-docs</title>\n <style>\n${getThemeStyles()}\n </style>\n</head>\n<body>\n <div class=\"container\">\n <header>\n <nav class=\"breadcrumb\">\n <a href=\"index.html\">Home</a> / <span>${escapeHtml(ir.entity.id)}</span>\n </nav>\n </header>\n <main class=\"content\">\n${htmlContent}\n </main>\n <footer>\n <p class=\"meta\">\n Generated by <a href=\"https://github.com/oddessentials/odd-docs\">odd-docs</a> at ${ir.generatedAt}\n </p>\n <p class=\"determinism\">\n <code>${ir.determinismKey}</code>\n </p>\n </footer>\n </div>\n <script>\n${getThemeScript()}\n </script>\n</body>\n</html>`;\n}\n\n/**\n * Generate index page for multiple docs\n */\nexport function renderIndexHTML(docs: DocIR[]): string {\n const items = docs\n .map(\n (ir) => `\n <li>\n <a href=\"${ir.entity.id}.html\">\n <strong>${escapeHtml(ir.entity.id)}</strong>\n <span class=\"version\">v${ir.entity.version}</span>\n </a>\n <p>${escapeHtml(ir.entity.description ?? '')}</p>\n </li>`\n )\n .join('\\n');\n\n return `<!DOCTYPE html>\n<html lang=\"en\" data-theme=\"light\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Documentation - odd-docs</title>\n <style>\n${getThemeStyles()}\n </style>\n</head>\n<body>\n <div class=\"container\">\n <header>\n <h1>Documentation</h1>\n </header>\n <main class=\"content\">\n <ul class=\"doc-list\">\n${items}\n </ul>\n </main>\n <footer>\n <p class=\"meta\">Generated by <a href=\"https://github.com/oddessentials/odd-docs\">odd-docs</a></p>\n </footer>\n </div>\n <script>\n${getThemeScript()}\n </script>\n</body>\n</html>`;\n}\n\nfunction escapeHtml(str: string): string {\n return str\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#039;');\n}\n\nfunction getThemeStyles(): string {\n return `\n /* CSS Variables for theming */\n :root {\n /* Colors - neutral palette */\n --color-bg: #ffffff;\n --color-bg-secondary: #f8f9fa;\n --color-text: #1a1a2e;\n --color-text-muted: #6c757d;\n --color-border: #dee2e6;\n --color-link: #0066cc;\n --color-link-hover: #004499;\n --color-accent: #0066cc;\n --color-success: #28a745;\n --color-warning: #ffc107;\n --color-error: #dc3545;\n \n /* Typography */\n --font-sans: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;\n --font-mono: 'SF Mono', Monaco, 'Cascadia Code', monospace;\n --font-size-base: 16px;\n --line-height: 1.6;\n \n /* Spacing */\n --space-xs: 0.25rem;\n --space-sm: 0.5rem;\n --space-md: 1rem;\n --space-lg: 1.5rem;\n --space-xl: 2rem;\n \n /* Layout */\n --max-width: 800px;\n --border-radius: 4px;\n }\n \n [data-theme=\"dark\"] {\n --color-bg: #1a1a2e;\n --color-bg-secondary: #16213e;\n --color-text: #e8e8e8;\n --color-text-muted: #a0a0a0;\n --color-border: #3a3a5e;\n --color-link: #66b3ff;\n --color-link-hover: #99ccff;\n }\n \n /* Reset */\n *, *::before, *::after {\n box-sizing: border-box;\n }\n \n body {\n margin: 0;\n padding: 0;\n font-family: var(--font-sans);\n font-size: var(--font-size-base);\n line-height: var(--line-height);\n color: var(--color-text);\n background: var(--color-bg);\n }\n \n /* Container */\n .container {\n max-width: var(--max-width);\n margin: 0 auto;\n padding: var(--space-lg);\n }\n \n /* Typography */\n h1, h2, h3, h4, h5, h6 {\n margin-top: var(--space-xl);\n margin-bottom: var(--space-md);\n line-height: 1.3;\n }\n \n h1 { font-size: 2rem; }\n h2 { font-size: 1.5rem; border-bottom: 1px solid var(--color-border); padding-bottom: var(--space-sm); }\n h3 { font-size: 1.25rem; }\n \n p { margin: var(--space-md) 0; }\n \n a {\n color: var(--color-link);\n text-decoration: none;\n }\n \n a:hover {\n color: var(--color-link-hover);\n text-decoration: underline;\n }\n \n /* Code */\n code {\n font-family: var(--font-mono);\n font-size: 0.9em;\n background: var(--color-bg-secondary);\n padding: var(--space-xs) var(--space-sm);\n border-radius: var(--border-radius);\n }\n \n pre {\n background: var(--color-bg-secondary);\n padding: var(--space-md);\n border-radius: var(--border-radius);\n overflow-x: auto;\n }\n \n pre code {\n background: none;\n padding: 0;\n }\n \n /* Tables */\n table {\n width: 100%;\n border-collapse: collapse;\n margin: var(--space-md) 0;\n }\n \n th, td {\n padding: var(--space-sm) var(--space-md);\n border: 1px solid var(--color-border);\n text-align: left;\n }\n \n th {\n background: var(--color-bg-secondary);\n font-weight: 600;\n }\n \n /* Provenance badges */\n code[class*=\"from\"] {\n font-size: 0.75em;\n color: var(--color-text-muted);\n background: transparent;\n }\n \n /* Blockquotes (for warnings/notes) */\n blockquote {\n margin: var(--space-md) 0;\n padding: var(--space-md);\n border-left: 4px solid var(--color-warning);\n background: var(--color-bg-secondary);\n }\n \n blockquote p:first-child { margin-top: 0; }\n blockquote p:last-child { margin-bottom: 0; }\n \n /* Lists */\n ul, ol {\n padding-left: var(--space-lg);\n }\n \n li { margin: var(--space-sm) 0; }\n \n /* Doc list (index page) */\n .doc-list {\n list-style: none;\n padding: 0;\n }\n \n .doc-list li {\n padding: var(--space-md);\n border: 1px solid var(--color-border);\n border-radius: var(--border-radius);\n margin-bottom: var(--space-md);\n }\n \n .doc-list a {\n display: flex;\n align-items: center;\n gap: var(--space-sm);\n }\n \n .doc-list .version {\n color: var(--color-text-muted);\n font-size: 0.875em;\n }\n \n .doc-list p {\n margin: var(--space-sm) 0 0;\n color: var(--color-text-muted);\n }\n \n /* Header */\n header {\n margin-bottom: var(--space-lg);\n }\n \n .breadcrumb {\n font-size: 0.875em;\n color: var(--color-text-muted);\n }\n \n .breadcrumb a {\n color: inherit;\n }\n \n /* Footer */\n footer {\n margin-top: var(--space-xl);\n padding-top: var(--space-lg);\n border-top: 1px solid var(--color-border);\n font-size: 0.875em;\n color: var(--color-text-muted);\n }\n \n .determinism code {\n font-size: 0.75em;\n }\n \n /* Theme toggle */\n .theme-toggle {\n position: fixed;\n top: var(--space-md);\n right: var(--space-md);\n padding: var(--space-sm) var(--space-md);\n border: 1px solid var(--color-border);\n border-radius: var(--border-radius);\n background: var(--color-bg);\n cursor: pointer;\n font-size: 0.875em;\n }\n \n /* Responsive */\n @media (max-width: 600px) {\n .container { padding: var(--space-md); }\n h1 { font-size: 1.5rem; }\n h2 { font-size: 1.25rem; }\n table { font-size: 0.875em; }\n }\n `;\n}\n\nfunction getThemeScript(): string {\n return `\n // Theme toggle\n const toggle = document.createElement('button');\n toggle.className = 'theme-toggle';\n toggle.textContent = '🌙';\n toggle.onclick = () => {\n const html = document.documentElement;\n const isDark = html.dataset.theme === 'dark';\n html.dataset.theme = isDark ? 'light' : 'dark';\n toggle.textContent = isDark ? '🌙' : '☀️';\n localStorage.setItem('theme', html.dataset.theme);\n };\n document.body.appendChild(toggle);\n \n // Restore saved theme\n const saved = localStorage.getItem('theme');\n if (saved) {\n document.documentElement.dataset.theme = saved;\n toggle.textContent = saved === 'dark' ? '☀️' : '🌙';\n } else if (window.matchMedia('(prefers-color-scheme: dark)').matches) {\n document.documentElement.dataset.theme = 'dark';\n toggle.textContent = '☀️';\n }\n `;\n}\n","import { resolve } from 'node:path';\nimport { parseManifest } from '../../core/parser/manifestParser.js';\nimport { buildDocIR } from '../../core/ir/builder.js';\nimport { validateDocIR, formatValidationResult } from '../../core/ir/validator.js';\n\nexport interface ValidateOptions {\n strict?: boolean;\n}\n\nexport async function validate(repoPath: string, options: ValidateOptions = {}): Promise<boolean> {\n const absPath = resolve(repoPath);\n\n console.log(`Validating: ${absPath}`);\n console.log(`Mode: ${options.strict ? 'strict' : 'normal'}`);\n console.log('');\n\n try {\n // Parse manifest\n const manifestResult = await parseManifest(absPath);\n\n // Build Doc IR\n const ir = buildDocIR(manifestResult);\n\n // Validate\n const result = validateDocIR(ir, { strict: options.strict });\n\n // Format and print result\n console.log(formatValidationResult(result, absPath));\n\n return result.valid;\n } catch (error) {\n console.error('✗ Validation failed');\n console.error('');\n console.error(`Error: ${error instanceof Error ? error.message : error}`);\n return false;\n }\n}\n","/**\n * Known capabilities allowlist\n * Safety-affecting capabilities trigger stricter validation\n */\n\nexport const KNOWN_CAPABILITIES = [\n 'network',\n 'filesystem',\n 'secrets',\n 'exec',\n 'subprocess',\n 'database',\n 'queue',\n] as const;\n\nexport type KnownCapability = (typeof KNOWN_CAPABILITIES)[number];\n\n/**\n * Capabilities that imply safety-critical operations\n * Unknown capabilities matching these patterns fail in --strict mode\n */\nexport const SAFETY_AFFECTING_PATTERNS = ['network', 'exec', 'subprocess', 'write', 'delete'];\n\nexport function isKnownCapability(capability: string): capability is KnownCapability {\n return KNOWN_CAPABILITIES.includes(capability as KnownCapability);\n}\n\nexport function isSafetyAffecting(capability: string): boolean {\n return SAFETY_AFFECTING_PATTERNS.some((pattern) =>\n capability.toLowerCase().includes(pattern.toLowerCase())\n );\n}\n","import type { DocIR, ProvenanceSource } from '../ir/types.js';\nimport { isKnownCapability, isSafetyAffecting } from '../capabilities.js';\n\nexport type ValidationSeverity = 'error' | 'warning';\n\nexport interface ValidationIssue {\n severity: ValidationSeverity;\n code: string;\n message: string;\n path?: string;\n provenance?: ProvenanceSource;\n}\n\nexport interface ValidationResult {\n valid: boolean;\n issues: ValidationIssue[];\n}\n\nexport interface ValidateOptions {\n strict?: boolean;\n}\n\n/**\n * Validate Doc IR for completeness and consistency\n */\nexport function validateDocIR(ir: DocIR, options: ValidateOptions = {}): ValidationResult {\n const issues: ValidationIssue[] = [];\n\n // Required field checks\n if (!ir.entity.id) {\n issues.push({\n severity: 'error',\n code: 'MISSING_TOOL_ID',\n message: 'Tool ID is required',\n path: 'entity.id',\n });\n }\n\n if (!ir.entity.version) {\n issues.push({\n severity: 'error',\n code: 'MISSING_VERSION',\n message: 'Version is required',\n path: 'entity.version',\n });\n }\n\n if (!ir.inputs?.schema && !ir.inputs?.parameters?.length) {\n issues.push({\n severity: 'error',\n code: 'MISSING_PARAMETERS_SCHEMA',\n message: 'Parameters schema is required',\n path: 'inputs',\n });\n }\n\n // Capability validation\n if (ir.constraints?.capabilities) {\n for (const cap of ir.constraints.capabilities) {\n if (!isKnownCapability(cap.type)) {\n const isSafety = isSafetyAffecting(cap.type);\n issues.push({\n severity: options.strict && isSafety ? 'error' : 'warning',\n code: 'UNKNOWN_CAPABILITY',\n message: `Unknown capability: ${cap.type}${isSafety ? ' (safety-affecting)' : ''}`,\n path: `constraints.capabilities.${cap.type}`,\n provenance: cap.provenance,\n });\n }\n }\n }\n\n // Structural contradiction checks\n issues.push(...checkStructuralContradictions(ir));\n\n const hasErrors = issues.some((i) => i.severity === 'error');\n\n return {\n valid: !hasErrors,\n issues,\n };\n}\n\n/**\n * Check for structural contradictions between sources\n */\nfunction checkStructuralContradictions(ir: DocIR): ValidationIssue[] {\n const issues: ValidationIssue[] = [];\n\n // Check if narrative mentions parameters not in schema\n if (ir.narrative?.notes && ir.inputs?.parameters) {\n const schemaParams = new Set(ir.inputs.parameters.map((p) => p.name.toLowerCase()));\n\n for (const note of ir.narrative.notes) {\n // Match patterns like \"parameter X\" or \"the X parameter\"\n const paramMentions = note.match(/(?:parameter|param)\\s+[`\"']?(\\w+)[`\"']?/gi) ?? [];\n const theParamMentions = note.match(/the\\s+[`\"']?(\\w+)[`\"']?\\s+parameter/gi) ?? [];\n\n for (const match of [...paramMentions, ...theParamMentions]) {\n const paramName = match.replace(/.*?[`\"']?(\\w+)[`\"']?.*/i, '$1').toLowerCase();\n if (paramName && !schemaParams.has(paramName) && paramName !== 'parameter') {\n issues.push({\n severity: 'error',\n code: 'NARRATIVE_REFERENCES_UNDEFINED_PARAM',\n message: `Narrative references parameter \"${paramName}\" not in schema`,\n path: 'narrative.notes',\n provenance: 'narrative',\n });\n }\n }\n }\n }\n\n // Check if examples use parameters not in schema\n if (ir.narrative?.examples && ir.inputs?.parameters) {\n const schemaParams = new Set(ir.inputs.parameters.map((p) => p.name));\n\n for (const example of ir.narrative.examples) {\n if (example.input && typeof example.input === 'object') {\n for (const key of Object.keys(example.input as Record<string, unknown>)) {\n if (!schemaParams.has(key)) {\n issues.push({\n severity: 'warning',\n code: 'EXAMPLE_USES_UNDEFINED_PARAM',\n message: `Example uses parameter \"${key}\" not in schema`,\n path: `narrative.examples.${example.title ?? 'unnamed'}`,\n provenance: 'narrative',\n });\n }\n }\n }\n }\n }\n\n // Check for side effect / capability contradictions\n if (ir.overview?.sideEffects && ir.constraints?.capabilities) {\n const capTypes = new Set(ir.constraints.capabilities.map((c) => c.type));\n\n for (const effect of ir.overview.sideEffects) {\n // Map side effect types to capability types\n const expectedCap = mapSideEffectToCapability(effect.type);\n if (expectedCap && !capTypes.has(expectedCap)) {\n issues.push({\n severity: 'error',\n code: 'SIDE_EFFECT_CAPABILITY_MISMATCH',\n message: `Side effect \"${effect.type}\" requires capability \"${expectedCap}\" which is not declared`,\n path: `overview.sideEffects.${effect.type}`,\n provenance: effect.provenance,\n });\n }\n }\n }\n\n return issues;\n}\n\nfunction mapSideEffectToCapability(effectType: string): string | null {\n const mapping: Record<string, string> = {\n filesystem: 'filesystem',\n network: 'network',\n secrets: 'secrets',\n exec: 'exec',\n subprocess: 'subprocess',\n database: 'database',\n queue: 'queue',\n };\n return mapping[effectType] ?? null;\n}\n\n/**\n * Format validation result for CLI output\n */\nexport function formatValidationResult(result: ValidationResult, repoPath: string): string {\n const lines: string[] = [];\n\n lines.push(`Validating: ${repoPath}`);\n lines.push('');\n\n if (result.valid) {\n lines.push('✓ Validation passed');\n } else {\n lines.push('✗ Validation failed');\n }\n lines.push('');\n\n const errors = result.issues.filter((i) => i.severity === 'error');\n const warnings = result.issues.filter((i) => i.severity === 'warning');\n\n if (errors.length > 0) {\n lines.push(`Errors (${errors.length}):`);\n for (const issue of errors) {\n lines.push(` ✗ [${issue.code}] ${issue.message}`);\n if (issue.path) {\n lines.push(` at ${issue.path}`);\n }\n }\n lines.push('');\n }\n\n if (warnings.length > 0) {\n lines.push(`Warnings (${warnings.length}):`);\n for (const issue of warnings) {\n lines.push(` ⚠ [${issue.code}] ${issue.message}`);\n if (issue.path) {\n lines.push(` at ${issue.path}`);\n }\n }\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n","/**\n * Serve Command\n *\n * Start a local development server for generated documentation.\n * Enforces safe defaults per deployment stance:\n * - localhost binding\n * - mutations disabled\n * - SSE auto-switch for non-localhost\n */\n\nimport { existsSync } from 'node:fs';\nimport { join, resolve } from 'node:path';\nimport { OddDocsServer, type ServeOptions } from '../../server/index.js';\nimport { generate } from './generate.js';\n\nexport interface ServeCommandOptions {\n port?: number;\n host?: string;\n output?: string;\n watch?: boolean;\n watchMode?: 'auto' | 'poll';\n reload?: 'ws' | 'sse' | 'poll' | 'none';\n open?: boolean;\n introspect?: string;\n enableMutations?: boolean;\n mutationToken?: string;\n}\n\n/**\n * Serve documentation with live reload\n */\nexport async function serve(repoPath: string, options: ServeCommandOptions = {}): Promise<void> {\n const resolvedPath = resolve(repoPath);\n\n // Determine output directory\n const outputDir = options.output\n ? resolve(options.output)\n : join(resolvedPath, 'docs', 'generated');\n\n // Check if docs exist, generate if not\n if (!existsSync(outputDir)) {\n console.log('[odd-docs] Documentation not found, generating...');\n await generate(repoPath, { output: outputDir, format: 'html' });\n }\n\n // Determine reload mode\n let reloadMode: 'ws' | 'sse' | 'poll' | 'none' = options.reload ?? 'ws';\n\n // Use poll mode if explicitly requested via env or option\n if (options.watchMode === 'poll' || process.env.CHOKIDAR_USEPOLLING === '1') {\n reloadMode = 'poll';\n console.log('[odd-docs] Using poll-based watching (CPU intensive)');\n }\n\n const host = options.host ?? 'localhost';\n const port = options.port ?? 3000;\n\n // Auto-switch to SSE for non-localhost (safer for K8s)\n if (host !== 'localhost' && options.reload === undefined) {\n reloadMode = 'sse';\n console.log('[odd-docs] Using SSE for non-localhost binding');\n }\n\n // Create and start server\n const serverOptions: Partial<ServeOptions> & { outputDir: string } = {\n outputDir,\n host,\n port,\n watch: options.watch !== false,\n reloadMode,\n enableMutations: options.enableMutations ?? false,\n mutationToken: options.mutationToken,\n };\n\n const server = new OddDocsServer(serverOptions);\n\n // Handle shutdown\n const shutdown = async () => {\n console.log('\\n[odd-docs] Shutting down...');\n await server.stop();\n process.exit(0);\n };\n\n process.on('SIGINT', shutdown);\n process.on('SIGTERM', shutdown);\n\n try {\n await server.start();\n\n // Open browser if requested\n if (options.open !== false && host === 'localhost') {\n const url = `http://${host}:${port}`;\n try {\n const { default: open } = await import('open');\n await open(url);\n } catch {\n console.log(`[odd-docs] Open browser manually: ${url}`);\n }\n }\n } catch (error) {\n console.error('[odd-docs] Failed to start server:', error);\n process.exit(1);\n }\n}\n","/**\n * OddDocs Server\n *\n * HTTP server wrapper for serving generated documentation.\n * Enforces safe defaults: localhost binding, no mutations without explicit opt-in.\n */\n\nimport { createServer, type Server, type IncomingMessage, type ServerResponse } from 'node:http';\nimport { FileServer } from './fileServer.js';\nimport { LiveReload } from './livereload.js';\nimport { ApiHandler, type ServerState } from './api.js';\n\nexport interface ServeOptions {\n /** Port to listen on. Default: 3000 */\n port: number;\n /** Host to bind. Default: 'localhost' (safe) */\n host: string;\n /** Documentation output directory */\n outputDir: string;\n /** Enable file watching for live reload. Default: true */\n watch: boolean;\n /** Reload mechanism. Default: 'ws' for localhost, 'sse' for 0.0.0.0 */\n reloadMode: 'ws' | 'sse' | 'poll' | 'none';\n /** Enable mutation API endpoints. Default: false */\n enableMutations: boolean;\n /** Token for mutation endpoints. Required if enableMutations=true */\n mutationToken?: string;\n /** Request timeout in ms. Default: 30000 */\n requestTimeout: number;\n}\n\nexport const DEFAULT_OPTIONS: Omit<ServeOptions, 'outputDir'> = {\n port: 3000,\n host: 'localhost',\n watch: true,\n reloadMode: 'ws',\n enableMutations: false,\n requestTimeout: 30000,\n};\n\nexport class OddDocsServer {\n private server: Server | null = null;\n private fileServer: FileServer;\n private liveReload: LiveReload | null = null;\n private apiHandler: ApiHandler;\n private options: ServeOptions;\n private state: ServerState;\n\n constructor(options: Partial<ServeOptions> & { outputDir: string }) {\n // Apply defaults\n this.options = {\n ...DEFAULT_OPTIONS,\n ...options,\n // Auto-switch to SSE for non-localhost binding (safer for K8s)\n reloadMode:\n options.reloadMode ??\n (options.host && options.host !== 'localhost' ? 'sse' : DEFAULT_OPTIONS.reloadMode),\n };\n\n // Environment overrides\n this.options.host = process.env.ODD_DOCS_HOST ?? this.options.host;\n this.options.port = parseInt(process.env.ODD_DOCS_PORT ?? String(this.options.port), 10);\n this.options.mutationToken = process.env.ODD_DOCS_MUTATION_TOKEN ?? this.options.mutationToken;\n\n this.state = {\n lastGenerateSuccess: true,\n lastGenerateTime: new Date().toISOString(),\n outputDirAccessible: true,\n introspectionConnected: false,\n };\n\n this.fileServer = new FileServer(this.options.outputDir);\n this.apiHandler = new ApiHandler(this.state, this.options);\n }\n\n async start(): Promise<void> {\n // Validate mutation token if mutations enabled\n if (this.options.enableMutations && !this.options.mutationToken) {\n throw new Error(\n 'Mutation token required when --enable-mutations is set. ' +\n 'Set ODD_DOCS_MUTATION_TOKEN or --mutation-token'\n );\n }\n\n this.server = createServer((req, res) => this.handleRequest(req, res));\n\n // Set timeout\n this.server.timeout = this.options.requestTimeout;\n\n // Start live reload if enabled\n if (this.options.watch && this.options.reloadMode !== 'none') {\n this.liveReload = new LiveReload({\n outputDir: this.options.outputDir,\n mode: this.options.reloadMode,\n server: this.server,\n });\n await this.liveReload.start();\n }\n\n return new Promise((resolve, reject) => {\n this.server!.listen(this.options.port, this.options.host, () => {\n console.log(\n `[odd-docs] Server started at http://${this.options.host}:${this.options.port}`\n );\n console.log(`[odd-docs] Serving: ${this.options.outputDir}`);\n if (this.liveReload) {\n console.log(`[odd-docs] Live reload: ${this.options.reloadMode}`);\n }\n resolve();\n });\n\n this.server!.on('error', reject);\n });\n }\n\n async stop(): Promise<void> {\n if (this.liveReload) {\n await this.liveReload.stop();\n }\n if (this.server) {\n return new Promise((resolve) => {\n this.server!.close(() => resolve());\n });\n }\n }\n\n private async handleRequest(req: IncomingMessage, res: ServerResponse): Promise<void> {\n const url = req.url ?? '/';\n\n try {\n // API routes\n if (url.startsWith('/api/')) {\n await this.apiHandler.handle(req, res);\n return;\n }\n\n // Live reload endpoints\n if (this.liveReload && url === '/__livereload') {\n await this.liveReload.handleRequest(req, res);\n return;\n }\n\n // Static file serving\n await this.fileServer.serve(req, res);\n } catch (error) {\n console.error('[odd-docs] Request error:', error);\n res.statusCode = 500;\n res.end('Internal Server Error');\n }\n }\n\n updateState(updates: Partial<ServerState>): void {\n Object.assign(this.state, updates);\n }\n}\n","/**\n * File Server\n *\n * Static file serving with security protections.\n * - Path traversal protection via realpath + relative check\n * - MIME type detection\n * - ETag/304 support\n * - Max response size cap\n */\n\nimport { createReadStream, statSync } from 'node:fs';\nimport { realpath } from 'node:fs/promises';\nimport { join, extname, relative, isAbsolute } from 'node:path';\nimport { createHash } from 'node:crypto';\nimport type { IncomingMessage, ServerResponse } from 'node:http';\n\nconst MAX_RESPONSE_SIZE = 50 * 1024 * 1024; // 50MB\n\nconst MIME_TYPES: Record<string, string> = {\n '.html': 'text/html; charset=utf-8',\n '.css': 'text/css; charset=utf-8',\n '.js': 'application/javascript; charset=utf-8',\n '.json': 'application/json; charset=utf-8',\n '.md': 'text/markdown; charset=utf-8',\n '.png': 'image/png',\n '.jpg': 'image/jpeg',\n '.jpeg': 'image/jpeg',\n '.gif': 'image/gif',\n '.svg': 'image/svg+xml',\n '.ico': 'image/x-icon',\n '.woff': 'font/woff',\n '.woff2': 'font/woff2',\n '.ttf': 'font/ttf',\n};\n\nexport class FileServer {\n private rootDir: string;\n private resolvedRoot: string | null = null;\n\n constructor(rootDir: string) {\n this.rootDir = rootDir;\n }\n\n async serve(req: IncomingMessage, res: ServerResponse): Promise<void> {\n const url = new URL(req.url ?? '/', `http://${req.headers.host}`);\n let pathname = decodeURIComponent(url.pathname);\n\n // Default to index.html\n if (pathname === '/' || pathname.endsWith('/')) {\n pathname = join(pathname, 'index.html');\n }\n\n // Resolve and validate path\n const filePath = await this.resolvePath(pathname);\n if (!filePath) {\n res.statusCode = 403;\n res.end('Forbidden: Path traversal blocked');\n return;\n }\n\n // Check file exists and get stats\n let stats;\n try {\n stats = statSync(filePath);\n } catch {\n res.statusCode = 404;\n res.end('Not Found');\n return;\n }\n\n if (!stats.isFile()) {\n res.statusCode = 404;\n res.end('Not Found');\n return;\n }\n\n // Check size limit\n if (stats.size > MAX_RESPONSE_SIZE) {\n res.statusCode = 413;\n res.end('File too large');\n return;\n }\n\n // ETag handling\n const etag = this.computeETag(filePath, stats.mtime, stats.size);\n const ifNoneMatch = req.headers['if-none-match'];\n if (ifNoneMatch === etag) {\n res.statusCode = 304;\n res.end();\n return;\n }\n\n // Set headers\n const ext = extname(filePath).toLowerCase();\n const contentType = MIME_TYPES[ext] ?? 'application/octet-stream';\n\n res.setHeader('Content-Type', contentType);\n res.setHeader('Content-Length', stats.size);\n res.setHeader('ETag', etag);\n res.setHeader('Cache-Control', 'no-cache');\n\n // Stream file\n const stream = createReadStream(filePath);\n stream.pipe(res);\n stream.on('error', () => {\n res.statusCode = 500;\n res.end('Error reading file');\n });\n }\n\n /**\n * Resolve path with traversal protection\n */\n private async resolvePath(pathname: string): Promise<string | null> {\n // Ensure we have the real root path\n if (!this.resolvedRoot) {\n try {\n this.resolvedRoot = await realpath(this.rootDir);\n } catch {\n return null;\n }\n }\n\n // Construct target path\n const targetPath = join(this.rootDir, pathname);\n\n // Resolve to real path (follows symlinks, canonicalizes)\n let resolvedTarget: string;\n try {\n resolvedTarget = await realpath(targetPath);\n } catch {\n return null;\n }\n\n // Check containment: resolved path must be within root\n const rel = relative(this.resolvedRoot, resolvedTarget);\n if (rel.startsWith('..') || isAbsolute(rel)) {\n // Path escapes root directory\n console.warn(`[odd-docs] Path traversal blocked: ${pathname}`);\n return null;\n }\n\n return resolvedTarget;\n }\n\n private computeETag(path: string, mtime: Date, size: number): string {\n const hash = createHash('md5')\n .update(`${path}:${mtime.getTime()}:${size}`)\n .digest('hex')\n .slice(0, 16);\n return `\"${hash}\"`;\n }\n}\n","/**\n * Live Reload\n *\n * File watching and live reload for development.\n * Supports multiple mechanisms: WebSocket, SSE, Polling.\n * WS is dev-only default; SSE is K8s-safe.\n */\n\nimport { watch, type FSWatcher } from 'node:fs';\nimport type { Server, IncomingMessage, ServerResponse } from 'node:http';\n\nexport interface LiveReloadOptions {\n outputDir: string;\n mode: 'ws' | 'sse' | 'poll' | 'none';\n server: Server;\n pollInterval?: number; // for poll mode, ms\n}\n\ntype ReloadMode = 'ws' | 'sse' | 'poll' | 'none';\n\nexport class LiveReload {\n private options: LiveReloadOptions;\n private watcher: FSWatcher | null = null;\n private sseClients: Set<ServerResponse> = new Set();\n private lastChangeTime: number = Date.now();\n private debounceTimer: NodeJS.Timeout | null = null;\n\n constructor(options: LiveReloadOptions) {\n this.options = {\n pollInterval: 5000,\n ...options,\n };\n }\n\n async start(): Promise<void> {\n // Start file watcher with debounce\n const usePolling = process.env.CHOKIDAR_USEPOLLING === '1' || this.options.mode === 'poll';\n\n this.watcher = watch(\n this.options.outputDir,\n { recursive: true, persistent: true },\n (_eventType, filename) => {\n if (filename) {\n this.onFileChange(filename);\n }\n }\n );\n\n if (usePolling) {\n console.log('[odd-docs] Using poll-based file watching');\n }\n\n console.log(`[odd-docs] Live reload started (mode: ${this.options.mode})`);\n }\n\n async stop(): Promise<void> {\n if (this.debounceTimer) {\n clearTimeout(this.debounceTimer);\n }\n if (this.watcher) {\n this.watcher.close();\n }\n // Close SSE connections\n for (const client of this.sseClients) {\n client.end();\n }\n this.sseClients.clear();\n }\n\n private onFileChange(filename: string): void {\n // Debounce rapid changes\n if (this.debounceTimer) {\n clearTimeout(this.debounceTimer);\n }\n this.debounceTimer = setTimeout(() => {\n this.lastChangeTime = Date.now();\n console.log(`[odd-docs] Change detected: ${filename}`);\n this.notifyClients();\n }, 100);\n }\n\n private notifyClients(): void {\n const message = JSON.stringify({ type: 'reload', time: this.lastChangeTime });\n\n // Notify SSE clients\n for (const client of this.sseClients) {\n client.write(`data: ${message}\\n\\n`);\n }\n }\n\n async handleRequest(req: IncomingMessage, res: ServerResponse): Promise<void> {\n const mode = this.options.mode;\n\n if (mode === 'sse') {\n // SSE endpoint\n res.setHeader('Content-Type', 'text/event-stream');\n res.setHeader('Cache-Control', 'no-cache');\n res.setHeader('Connection', 'keep-alive');\n res.setHeader('X-Accel-Buffering', 'no'); // For nginx\n\n res.write(': ping\\n\\n');\n this.sseClients.add(res);\n\n req.on('close', () => {\n this.sseClients.delete(res);\n });\n } else if (mode === 'poll') {\n // Poll endpoint - return last change time\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ lastChange: this.lastChangeTime }));\n } else {\n // Not supported in this mode\n res.statusCode = 404;\n res.end('Live reload not available in this mode');\n }\n }\n\n /**\n * Get client-side script for live reload\n */\n static getClientScript(mode: ReloadMode, pollInterval: number = 5000): string {\n if (mode === 'none') return '';\n\n if (mode === 'sse') {\n return `\n<script>\n(function() {\n const es = new EventSource('/__livereload');\n es.onmessage = function(e) {\n const data = JSON.parse(e.data);\n if (data.type === 'reload') {\n console.log('[odd-docs] Reloading...');\n location.reload();\n }\n };\n es.onerror = function() {\n console.log('[odd-docs] SSE connection lost, will retry...');\n };\n})();\n</script>`;\n }\n\n if (mode === 'poll') {\n return `\n<script>\n(function() {\n let lastChange = 0;\n setInterval(async () => {\n try {\n const res = await fetch('/__livereload');\n const data = await res.json();\n if (lastChange && data.lastChange > lastChange) {\n console.log('[odd-docs] Reloading...');\n location.reload();\n }\n lastChange = data.lastChange;\n } catch (e) {}\n }, ${pollInterval});\n})();\n</script>`;\n }\n\n // WebSocket (ws mode) - requires separate ws server\n return `\n<script>\n(function() {\n const ws = new WebSocket('ws://' + location.host + '/__ws');\n ws.onmessage = function(e) {\n const data = JSON.parse(e.data);\n if (data.type === 'reload') {\n console.log('[odd-docs] Reloading...');\n location.reload();\n }\n };\n ws.onclose = function() {\n console.log('[odd-docs] WebSocket closed, will retry in 3s...');\n setTimeout(() => location.reload(), 3000);\n };\n})();\n</script>`;\n }\n}\n","/**\n * API Handler\n *\n * REST API endpoints for programmatic access.\n * Implements K8s-compatible health semantics.\n * Mutation endpoints require explicit opt-in + token.\n */\n\nimport type { IncomingMessage, ServerResponse } from 'node:http';\nimport type { ServeOptions } from './index.js';\n\nconst MAX_IR_SIZE = 10 * 1024 * 1024; // 10MB\n\nexport interface ServerState {\n lastGenerateSuccess: boolean;\n lastGenerateTime: string;\n outputDirAccessible: boolean;\n introspectionConnected: boolean;\n lastIntrospectionTime?: string;\n}\n\nexport class ApiHandler {\n private state: ServerState;\n private options: ServeOptions;\n\n constructor(state: ServerState, options: ServeOptions) {\n this.state = state;\n this.options = options;\n }\n\n async handle(req: IncomingMessage, res: ServerResponse): Promise<void> {\n const url = new URL(req.url ?? '/', `http://${req.headers.host}`);\n const path = url.pathname;\n const method = req.method ?? 'GET';\n\n // Route to handlers\n switch (path) {\n case '/api/health':\n return this.handleHealth(res);\n case '/api/ready':\n return this.handleReady(res);\n case '/api/introspection':\n return this.handleIntrospection(res);\n case '/api/docs':\n return this.handleDocs(res);\n case '/api/ir':\n return this.handleIR(res);\n case '/api/capabilities':\n return this.handleCapabilities(res);\n case '/api/regenerate':\n if (method === 'POST') {\n return this.handleRegenerate(req, res);\n }\n return this.methodNotAllowed(res);\n default:\n return this.notFound(res);\n }\n }\n\n /**\n * GET /api/health - Liveness probe\n * Returns 200 if process is running\n */\n private handleHealth(res: ServerResponse): void {\n this.json(res, {\n status: 'ok',\n timestamp: new Date().toISOString(),\n });\n }\n\n /**\n * GET /api/ready - Readiness probe\n * Returns 200 if last generate succeeded and output is accessible\n */\n private handleReady(res: ServerResponse): void {\n const ready = this.state.lastGenerateSuccess && this.state.outputDirAccessible;\n\n if (!ready) {\n res.statusCode = 503;\n }\n\n this.json(res, {\n ready,\n lastGenerateSuccess: this.state.lastGenerateSuccess,\n lastGenerateTime: this.state.lastGenerateTime,\n outputDirAccessible: this.state.outputDirAccessible,\n });\n }\n\n /**\n * GET /api/introspection - Introspection status\n */\n private handleIntrospection(res: ServerResponse): void {\n this.json(res, {\n connected: this.state.introspectionConnected,\n lastPollTime: this.state.lastIntrospectionTime ?? null,\n });\n }\n\n /**\n * GET /api/docs - List documentation sections\n */\n private handleDocs(res: ServerResponse): void {\n // TODO: Implement actual doc listing\n this.json(res, {\n sections: [],\n message: 'Not implemented yet',\n });\n }\n\n /**\n * GET /api/ir - Full IR dump (capped at 10MB)\n */\n private handleIR(res: ServerResponse): void {\n // TODO: Implement actual IR retrieval\n const ir = { tools: [], prompts: [], resources: [] };\n const irJson = JSON.stringify(ir);\n\n if (irJson.length > MAX_IR_SIZE) {\n this.json(res, {\n truncated: true,\n message: `IR exceeds ${MAX_IR_SIZE / 1024 / 1024}MB limit`,\n partial: null,\n });\n return;\n }\n\n res.setHeader('Content-Type', 'application/json');\n res.end(irJson);\n }\n\n /**\n * GET /api/capabilities - Tool capabilities summary\n */\n private handleCapabilities(res: ServerResponse): void {\n this.json(res, {\n serve: {\n host: this.options.host,\n port: this.options.port,\n reloadMode: this.options.reloadMode,\n mutationsEnabled: this.options.enableMutations,\n },\n });\n }\n\n /**\n * POST /api/regenerate - Trigger manual regeneration\n * Requires --enable-mutations and valid token\n */\n private handleRegenerate(req: IncomingMessage, res: ServerResponse): void {\n // Check if mutations are enabled\n if (!this.options.enableMutations) {\n res.statusCode = 403;\n this.json(res, {\n error: 'Mutations disabled',\n message: 'Start server with --enable-mutations to use this endpoint',\n });\n return;\n }\n\n // Validate token\n const token = req.headers['x-mutation-token'];\n if (token !== this.options.mutationToken) {\n res.statusCode = 401;\n this.json(res, {\n error: 'Unauthorized',\n message: 'Invalid or missing X-Mutation-Token header',\n });\n return;\n }\n\n // TODO: Trigger actual regeneration\n this.json(res, {\n status: 'queued',\n message: 'Regeneration triggered',\n timestamp: new Date().toISOString(),\n });\n }\n\n private json(res: ServerResponse, data: unknown): void {\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify(data, null, 2));\n }\n\n private notFound(res: ServerResponse): void {\n res.statusCode = 404;\n this.json(res, { error: 'Not Found' });\n }\n\n private methodNotAllowed(res: ServerResponse): void {\n res.statusCode = 405;\n this.json(res, { error: 'Method Not Allowed' });\n }\n}\n"],"mappings":"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","names":["join","join","resolve","resolve","join","resolve","join","createHash","resolve","resolve","join","require"]}
1
+ {"version":3,"sources":["../../src/cli/index.ts","../../src/cli/commands/generate.ts","../../src/core/parser/manifestParser.ts","../../src/core/ir/builder.ts","../../src/core/parser/schemaParser.ts","../../src/core/renderer/markdownRenderer.ts","../../src/core/renderer/htmlRenderer.ts","../../src/core/safety.ts","../../src/cli/commands/validate.ts","../../src/core/capabilities.ts","../../src/core/ir/validator.ts","../../src/cli/commands/serve.ts","../../src/server/index.ts","../../src/server/fileServer.ts","../../src/server/livereload.ts","../../src/server/api.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { Command } from 'commander';\nimport { createRequire } from 'node:module';\nimport { generate } from './commands/generate.js';\nimport { validate } from './commands/validate.js';\nimport { serve } from './commands/serve.js';\n\n// Use createRequire for cross-platform compatibility with npx\n// This approach works reliably when the package is installed via npm/npx\nconst require = createRequire(import.meta.url);\nconst packageJson = require('../../package.json') as { version: string };\n\n// Handle --version explicitly before commander for reliable npx output\n// Commander's .version() output may not be captured properly by npx\nif (process.argv.includes('--version') || process.argv.includes('-V')) {\n console.log(packageJson.version);\n process.exit(0);\n}\n\nconst program = new Command();\n\nprogram.name('odd-docs').description('MCP-native documentation generator');\n\nprogram\n .command('generate')\n .description('Generate documentation for an MCP repo')\n .argument('<repo-path>', 'Path to the repository')\n .option('-f, --format <format>', 'Output format: md, html, or both', 'md')\n .option('-o, --output <dir>', 'Output directory')\n .option('--introspect <url>', 'MCP server URL for live introspection')\n .action(async (repoPath: string, options) => {\n try {\n await generate(repoPath, {\n format: options.format,\n output: options.output,\n introspect: options.introspect,\n });\n } catch (error) {\n console.error('Error:', error instanceof Error ? error.message : error);\n process.exit(1);\n }\n });\n\nprogram\n .command('validate')\n .description('Validate documentation inputs for an MCP repo')\n .argument('<repo-path>', 'Path to the repository')\n .option('-s, --strict', 'Fail on unknown safety-affecting capabilities')\n .action(async (repoPath: string, options) => {\n try {\n const valid = await validate(repoPath, { strict: options.strict });\n process.exit(valid ? 0 : 1);\n } catch (error) {\n console.error('Error:', error instanceof Error ? error.message : error);\n process.exit(1);\n }\n });\n\nprogram\n .command('serve')\n .description('Start a local dev server for generated documentation')\n .argument('<repo-path>', 'Path to the repository')\n .option('-p, --port <port>', 'Port to listen on', '3000')\n .option('-H, --host <host>', 'Host to bind (default: localhost for safety)', 'localhost')\n .option('-o, --output <dir>', 'Documentation output directory')\n .option('--no-watch', 'Disable file watching')\n .option('--watch-mode <mode>', 'Watch mode: auto or poll (use poll for Docker/NFS)', 'auto')\n .option('--reload <mode>', 'Reload mechanism: ws, sse, poll, none', 'ws')\n .option('--no-open', 'Do not open browser on start')\n .option('--introspect <target>', 'MCP target: http://host:port or stdio:<cmd>')\n .option('--enable-mutations', 'Enable mutation API endpoints (requires token)')\n .option('--mutation-token <token>', 'Token for mutation endpoints (or ODD_DOCS_MUTATION_TOKEN)')\n .action(async (repoPath: string, options) => {\n try {\n await serve(repoPath, {\n port: parseInt(options.port, 10),\n host: options.host,\n output: options.output,\n watch: options.watch,\n watchMode: options.watchMode,\n reload: options.reload,\n open: options.open,\n introspect: options.introspect,\n enableMutations: options.enableMutations,\n mutationToken: options.mutationToken,\n });\n } catch (error) {\n console.error('Error:', error instanceof Error ? error.message : error);\n process.exit(1);\n }\n });\n\nprogram.parse();\n","import { writeFile, mkdir } from 'node:fs/promises';\nimport { join, resolve, relative } from 'node:path';\nimport { parseManifest } from '../../core/parser/manifestParser.js';\nimport { buildDocIR } from '../../core/ir/builder.js';\nimport { renderMarkdown } from '../../core/renderer/markdownRenderer.js';\nimport { renderHTML } from '../../core/renderer/htmlRenderer.js';\nimport { validateOutputPath } from '../../core/safety.js';\n\nexport interface GenerateOptions {\n format?: 'md' | 'html' | 'both';\n output?: string;\n introspect?: string;\n}\n\nexport async function generate(repoPath: string, options: GenerateOptions = {}): Promise<void> {\n const absPath = resolve(repoPath);\n const format = options.format ?? 'md';\n const outputDir = options.output ? resolve(options.output) : join(absPath, 'docs', 'generated');\n\n console.log(`Generating documentation for: ${absPath}`);\n\n // Parse manifest\n const manifestResult = await parseManifest(absPath);\n console.log(` Entity: ${manifestResult.entity.id}@${manifestResult.entity.version}`);\n\n // Build Doc IR\n const ir = buildDocIR(manifestResult);\n console.log(` Determinism key: ${ir.determinismKey}`);\n\n // Ensure output directory exists\n await mkdir(outputDir, { recursive: true });\n\n // Render formats with path safety validation\n if (format === 'md' || format === 'both') {\n const markdown = renderMarkdown(ir);\n const mdPath = validateOutputPath(\n absPath,\n relative(absPath, join(outputDir, `${ir.entity.id}.md`))\n );\n await writeFile(mdPath, markdown, 'utf-8');\n console.log(` ✓ Markdown: ${mdPath}`);\n }\n\n if (format === 'html' || format === 'both') {\n const html = renderHTML(ir);\n const htmlPath = validateOutputPath(\n absPath,\n relative(absPath, join(outputDir, `${ir.entity.id}.html`))\n );\n await writeFile(htmlPath, html, 'utf-8');\n console.log(` ✓ HTML: ${htmlPath}`);\n }\n\n // Write IR for debugging/caching\n const irPath = validateOutputPath(\n absPath,\n relative(absPath, join(outputDir, `${ir.entity.id}.ir.json`))\n );\n await writeFile(irPath, JSON.stringify(ir, null, 2), 'utf-8');\n console.log(` ✓ Doc IR: ${irPath}`);\n\n console.log('Done!');\n}\n","import { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { DocIR, Capability, SchemaSection } from '../ir/types.js';\n\ninterface ToolManifest {\n tool_id: string;\n version: string;\n description?: string;\n execution_mode?: 'IN_PROCESS' | 'RUNNER';\n parameters?: Record<string, unknown>;\n capabilities?: {\n network?: string[];\n filesystem?: string[];\n secrets?: string[];\n };\n timeout_ms?: number;\n resource_limits?: {\n memory_mb?: number;\n cpu_cores?: number;\n };\n deprecation?: {\n deprecated_at: string;\n sunset_date: string;\n migration_url?: string;\n };\n}\n\nexport interface ManifestParseResult {\n entity: DocIR['entity'];\n inputs: SchemaSection;\n constraints?: DocIR['constraints'];\n lifecycle?: DocIR['lifecycle'];\n}\n\n/**\n * Parse an MCP tool manifest file into partial Doc IR\n */\nexport async function parseManifest(repoPath: string): Promise<ManifestParseResult> {\n const manifestPath = join(repoPath, 'manifest.json');\n\n let content: string;\n try {\n content = await readFile(manifestPath, 'utf-8');\n } catch {\n throw new Error(`Manifest not found: ${manifestPath}`);\n }\n\n let manifest: ToolManifest;\n try {\n manifest = JSON.parse(content) as ToolManifest;\n } catch {\n throw new Error(`Invalid JSON in manifest: ${manifestPath}`);\n }\n\n // Validate required fields\n if (!manifest.tool_id) {\n throw new Error('Manifest missing required field: tool_id');\n }\n if (!manifest.version) {\n throw new Error('Manifest missing required field: version');\n }\n\n // Build capabilities array\n const capabilities: Capability[] = [];\n if (manifest.capabilities) {\n for (const [type, values] of Object.entries(manifest.capabilities)) {\n if (Array.isArray(values) && values.length > 0) {\n capabilities.push({ type, values, provenance: 'manifest' });\n }\n }\n }\n\n const result: ManifestParseResult = {\n entity: {\n type: 'tool',\n id: manifest.tool_id,\n version: manifest.version,\n description: manifest.description,\n },\n inputs: {\n schema: manifest.parameters,\n provenance: 'manifest',\n },\n };\n\n // Add constraints if present\n if (capabilities.length > 0 || manifest.timeout_ms || manifest.resource_limits) {\n result.constraints = {\n capabilities: capabilities.length > 0 ? capabilities : undefined,\n timeoutMs: manifest.timeout_ms,\n resourceLimits: manifest.resource_limits\n ? {\n memoryMb: manifest.resource_limits.memory_mb,\n cpuCores: manifest.resource_limits.cpu_cores,\n }\n : undefined,\n };\n }\n\n // Add lifecycle if deprecation present\n if (manifest.deprecation) {\n result.lifecycle = {\n version: manifest.version,\n deprecation: {\n deprecatedAt: manifest.deprecation.deprecated_at,\n sunsetDate: manifest.deprecation.sunset_date,\n migrationUrl: manifest.deprecation.migration_url,\n },\n };\n }\n\n return result;\n}\n","import { createHash } from 'node:crypto';\nimport type { DocIR } from './types.js';\nimport { enrichSchemaSection } from '../parser/schemaParser.js';\nimport type { ManifestParseResult } from '../parser/manifestParser.js';\n\n/**\n * Build a complete Doc IR from parsed sources\n */\nexport function buildDocIR(manifest: ManifestParseResult): DocIR {\n const enrichedInputs = enrichSchemaSection(manifest.inputs);\n\n const ir: DocIR = {\n version: '1.0.0',\n generatedAt: new Date().toISOString(),\n determinismKey: '', // Computed below\n entity: manifest.entity,\n inputs: enrichedInputs,\n constraints: manifest.constraints,\n lifecycle: manifest.lifecycle,\n provenance: {\n entity: 'manifest',\n inputs: 'manifest',\n },\n };\n\n // Compute determinism key\n ir.determinismKey = computeDeterminismKey(ir);\n\n return ir;\n}\n\n/**\n * Compute SHA-256 determinism key for caching and diffing\n */\nexport function computeDeterminismKey(ir: Omit<DocIR, 'determinismKey' | 'generatedAt'>): string {\n const canonical = JSON.stringify({\n entity: ir.entity,\n inputs: ir.inputs,\n constraints: ir.constraints,\n lifecycle: ir.lifecycle,\n });\n\n const hash = createHash('sha256').update(canonical).digest('hex');\n return `sha256:${hash}`;\n}\n","import type { Parameter, SchemaSection } from '../ir/types.js';\n\ninterface JSONSchema {\n type?: string;\n properties?: Record<string, JSONSchema>;\n required?: string[];\n description?: string;\n default?: unknown;\n enum?: unknown[];\n minimum?: number;\n maximum?: number;\n minLength?: number;\n maxLength?: number;\n pattern?: string;\n items?: JSONSchema;\n $ref?: string;\n}\n\n/**\n * Parse JSON Schema into a list of parameters for documentation\n */\nexport function parseSchema(schema: Record<string, unknown> | undefined): Parameter[] {\n if (!schema) return [];\n\n const jsonSchema = schema as JSONSchema;\n const parameters: Parameter[] = [];\n const required = new Set(jsonSchema.required ?? []);\n\n if (jsonSchema.properties) {\n for (const [name, propSchema] of Object.entries(jsonSchema.properties)) {\n parameters.push(parseProperty(name, propSchema, required.has(name)));\n }\n }\n\n return parameters;\n}\n\nfunction parseProperty(name: string, schema: JSONSchema, isRequired: boolean): Parameter {\n const param: Parameter = {\n name,\n type: resolveType(schema),\n required: isRequired,\n };\n\n if (schema.description) {\n param.description = schema.description;\n }\n\n if (schema.default !== undefined) {\n param.default = schema.default;\n }\n\n if (schema.enum) {\n param.enum = schema.enum;\n }\n\n // Build constraints string\n const constraints = buildConstraints(schema);\n if (constraints) {\n param.constraints = constraints;\n }\n\n return param;\n}\n\nfunction resolveType(schema: JSONSchema): string {\n if (schema.$ref) {\n // Extract type name from $ref\n const refParts = schema.$ref.split('/');\n return refParts[refParts.length - 1];\n }\n\n if (schema.enum) {\n return 'enum';\n }\n\n if (schema.type === 'array' && schema.items) {\n return `${resolveType(schema.items)}[]`;\n }\n\n return schema.type ?? 'unknown';\n}\n\nfunction buildConstraints(schema: JSONSchema): string | undefined {\n const parts: string[] = [];\n\n if (schema.minimum !== undefined) {\n parts.push(`min: ${schema.minimum}`);\n }\n if (schema.maximum !== undefined) {\n parts.push(`max: ${schema.maximum}`);\n }\n if (schema.minLength !== undefined) {\n parts.push(`minLength: ${schema.minLength}`);\n }\n if (schema.maxLength !== undefined) {\n parts.push(`maxLength: ${schema.maxLength}`);\n }\n if (schema.pattern) {\n parts.push(`pattern: ${schema.pattern}`);\n }\n\n return parts.length > 0 ? parts.join(', ') : undefined;\n}\n\n/**\n * Enrich a SchemaSection with parsed parameters\n */\nexport function enrichSchemaSection(section: SchemaSection): SchemaSection {\n return {\n ...section,\n parameters: parseSchema(section.schema),\n };\n}\n","import type { DocIR, Parameter, ProvenanceSource } from '../ir/types.js';\n\n/**\n * Render Doc IR to Markdown\n */\nexport function renderMarkdown(ir: DocIR): string {\n const lines: string[] = [];\n\n // Header\n lines.push(`# ${ir.entity.id}`);\n lines.push('');\n lines.push(`**Version:** ${ir.entity.version} `);\n lines.push(`**Type:** ${ir.entity.type} `);\n if (ir.entity.description) {\n lines.push('');\n lines.push(ir.entity.description);\n }\n lines.push('');\n\n // Overview\n if (ir.overview) {\n lines.push('## Overview');\n lines.push('');\n if (ir.overview.intent) {\n lines.push(`**Intent:** ${ir.overview.intent}`);\n lines.push('');\n }\n if (ir.overview.useCases?.length) {\n lines.push('### Use Cases');\n lines.push('');\n for (const useCase of ir.overview.useCases) {\n lines.push(`- ${useCase}`);\n }\n lines.push('');\n }\n if (ir.overview.sideEffects?.length) {\n lines.push('### Side Effects');\n lines.push('');\n for (const effect of ir.overview.sideEffects) {\n lines.push(\n `- **${effect.type}**: ${effect.description} ${provenanceBadge(effect.provenance)}`\n );\n }\n lines.push('');\n }\n }\n\n // Inputs\n if (ir.inputs?.parameters?.length) {\n lines.push('## Inputs');\n lines.push('');\n lines.push(provenanceBadge(ir.inputs.provenance));\n lines.push('');\n lines.push(renderParameterTable(ir.inputs.parameters));\n lines.push('');\n }\n\n // Outputs\n if (ir.outputs?.parameters?.length) {\n lines.push('## Outputs');\n lines.push('');\n lines.push(provenanceBadge(ir.outputs.provenance));\n lines.push('');\n lines.push(renderParameterTable(ir.outputs.parameters));\n lines.push('');\n }\n\n // Constraints\n if (ir.constraints) {\n lines.push('## Constraints');\n lines.push('');\n if (ir.constraints.capabilities?.length) {\n lines.push('### Capabilities');\n lines.push('');\n for (const cap of ir.constraints.capabilities) {\n const values = cap.values?.join(', ') ?? 'enabled';\n lines.push(`- **${cap.type}**: ${values} ${provenanceBadge(cap.provenance)}`);\n }\n lines.push('');\n }\n if (ir.constraints.timeoutMs) {\n lines.push(`**Timeout:** ${ir.constraints.timeoutMs}ms`);\n lines.push('');\n }\n if (ir.constraints.resourceLimits) {\n lines.push('### Resource Limits');\n lines.push('');\n if (ir.constraints.resourceLimits.memoryMb) {\n lines.push(`- Memory: ${ir.constraints.resourceLimits.memoryMb} MB`);\n }\n if (ir.constraints.resourceLimits.cpuCores) {\n lines.push(`- CPU: ${ir.constraints.resourceLimits.cpuCores} cores`);\n }\n lines.push('');\n }\n }\n\n // Errors\n if (ir.errors?.length) {\n lines.push('## Errors');\n lines.push('');\n lines.push('| Code | Description | Recovery |');\n lines.push('|------|-------------|----------|');\n for (const err of ir.errors) {\n lines.push(`| \\`${err.code}\\` | ${err.description ?? ''} | ${err.recovery ?? ''} |`);\n }\n lines.push('');\n }\n\n // Lifecycle\n if (ir.lifecycle?.deprecation) {\n lines.push('## Lifecycle');\n lines.push('');\n lines.push('> [!WARNING]');\n lines.push(`> This tool is deprecated as of ${ir.lifecycle.deprecation.deprecatedAt}.`);\n lines.push(`> Sunset date: ${ir.lifecycle.deprecation.sunsetDate}`);\n if (ir.lifecycle.deprecation.migrationUrl) {\n lines.push(`> Migration guide: ${ir.lifecycle.deprecation.migrationUrl}`);\n }\n lines.push('');\n }\n\n // Examples\n if (ir.narrative?.examples?.length) {\n lines.push('## Examples');\n lines.push('');\n for (const example of ir.narrative.examples) {\n if (example.title) {\n lines.push(`### ${example.title}`);\n lines.push('');\n }\n if (example.description) {\n lines.push(example.description);\n lines.push('');\n }\n if (example.input) {\n lines.push('**Input:**');\n lines.push('```json');\n lines.push(JSON.stringify(example.input, null, 2));\n lines.push('```');\n lines.push('');\n }\n if (example.output) {\n lines.push('**Output:**');\n lines.push('```json');\n lines.push(JSON.stringify(example.output, null, 2));\n lines.push('```');\n lines.push('');\n }\n }\n }\n\n // Notes\n if (ir.narrative?.notes?.length) {\n lines.push('## Notes');\n lines.push('');\n lines.push('*[author notes]*');\n lines.push('');\n for (const note of ir.narrative.notes) {\n lines.push(note);\n lines.push('');\n }\n }\n\n // Footer\n lines.push('---');\n lines.push('');\n lines.push(`*Generated at ${ir.generatedAt}* `);\n lines.push(`*Determinism key: \\`${ir.determinismKey}\\`*`);\n\n return lines.join('\\n');\n}\n\nfunction renderParameterTable(params: Parameter[]): string {\n const lines: string[] = [];\n lines.push('| Name | Type | Required | Default | Description |');\n lines.push('|------|------|----------|---------|-------------|');\n\n for (const param of params) {\n const required = param.required ? '✓' : '';\n const defaultVal = param.default !== undefined ? `\\`${JSON.stringify(param.default)}\\`` : '';\n const desc = param.description ?? '';\n lines.push(`| \\`${param.name}\\` | \\`${param.type}\\` | ${required} | ${defaultVal} | ${desc} |`);\n }\n\n return lines.join('\\n');\n}\n\nfunction provenanceBadge(source?: ProvenanceSource): string {\n if (!source) return '';\n const badges: Record<ProvenanceSource, string> = {\n introspection: '`[from introspection]`',\n manifest: '`[from schema]`',\n overlay: '`[from overlay]`',\n narrative: '`[author notes]`',\n };\n return badges[source] ?? '';\n}\n","import { marked } from 'marked';\nimport type { DocIR } from '../ir/types.js';\nimport { renderMarkdown } from './markdownRenderer.js';\n\n/**\n * Render Doc IR to static HTML\n */\nexport function renderHTML(ir: DocIR): string {\n // First render to markdown, then convert to HTML\n const markdown = renderMarkdown(ir);\n const htmlContent = marked.parse(markdown) as string;\n\n return `<!DOCTYPE html>\n<html lang=\"en\" data-theme=\"light\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <meta name=\"description\" content=\"${escapeHtml(ir.entity.description ?? `Documentation for ${ir.entity.id}`)}\">\n <title>${escapeHtml(ir.entity.id)} - odd-docs</title>\n <style>\n${getThemeStyles()}\n </style>\n</head>\n<body>\n <div class=\"container\">\n <header>\n <nav class=\"breadcrumb\">\n <a href=\"index.html\">Home</a> / <span>${escapeHtml(ir.entity.id)}</span>\n </nav>\n </header>\n <main class=\"content\">\n${htmlContent}\n </main>\n <footer>\n <p class=\"meta\">\n Generated by <a href=\"https://github.com/oddessentials/odd-docs\">odd-docs</a> at ${ir.generatedAt}\n </p>\n <p class=\"determinism\">\n <code>${ir.determinismKey}</code>\n </p>\n </footer>\n </div>\n <script>\n${getThemeScript()}\n </script>\n</body>\n</html>`;\n}\n\n/**\n * Generate index page for multiple docs\n */\nexport function renderIndexHTML(docs: DocIR[]): string {\n const items = docs\n .map(\n (ir) => `\n <li>\n <a href=\"${ir.entity.id}.html\">\n <strong>${escapeHtml(ir.entity.id)}</strong>\n <span class=\"version\">v${ir.entity.version}</span>\n </a>\n <p>${escapeHtml(ir.entity.description ?? '')}</p>\n </li>`\n )\n .join('\\n');\n\n return `<!DOCTYPE html>\n<html lang=\"en\" data-theme=\"light\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Documentation - odd-docs</title>\n <style>\n${getThemeStyles()}\n </style>\n</head>\n<body>\n <div class=\"container\">\n <header>\n <h1>Documentation</h1>\n </header>\n <main class=\"content\">\n <ul class=\"doc-list\">\n${items}\n </ul>\n </main>\n <footer>\n <p class=\"meta\">Generated by <a href=\"https://github.com/oddessentials/odd-docs\">odd-docs</a></p>\n </footer>\n </div>\n <script>\n${getThemeScript()}\n </script>\n</body>\n</html>`;\n}\n\nfunction escapeHtml(str: string): string {\n return str\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#039;');\n}\n\nfunction getThemeStyles(): string {\n return `\n /* CSS Variables for theming */\n :root {\n /* Colors - neutral palette */\n --color-bg: #ffffff;\n --color-bg-secondary: #f8f9fa;\n --color-text: #1a1a2e;\n --color-text-muted: #6c757d;\n --color-border: #dee2e6;\n --color-link: #0066cc;\n --color-link-hover: #004499;\n --color-accent: #0066cc;\n --color-success: #28a745;\n --color-warning: #ffc107;\n --color-error: #dc3545;\n \n /* Typography */\n --font-sans: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;\n --font-mono: 'SF Mono', Monaco, 'Cascadia Code', monospace;\n --font-size-base: 16px;\n --line-height: 1.6;\n \n /* Spacing */\n --space-xs: 0.25rem;\n --space-sm: 0.5rem;\n --space-md: 1rem;\n --space-lg: 1.5rem;\n --space-xl: 2rem;\n \n /* Layout */\n --max-width: 800px;\n --border-radius: 4px;\n }\n \n [data-theme=\"dark\"] {\n --color-bg: #1a1a2e;\n --color-bg-secondary: #16213e;\n --color-text: #e8e8e8;\n --color-text-muted: #a0a0a0;\n --color-border: #3a3a5e;\n --color-link: #66b3ff;\n --color-link-hover: #99ccff;\n }\n \n /* Reset */\n *, *::before, *::after {\n box-sizing: border-box;\n }\n \n body {\n margin: 0;\n padding: 0;\n font-family: var(--font-sans);\n font-size: var(--font-size-base);\n line-height: var(--line-height);\n color: var(--color-text);\n background: var(--color-bg);\n }\n \n /* Container */\n .container {\n max-width: var(--max-width);\n margin: 0 auto;\n padding: var(--space-lg);\n }\n \n /* Typography */\n h1, h2, h3, h4, h5, h6 {\n margin-top: var(--space-xl);\n margin-bottom: var(--space-md);\n line-height: 1.3;\n }\n \n h1 { font-size: 2rem; }\n h2 { font-size: 1.5rem; border-bottom: 1px solid var(--color-border); padding-bottom: var(--space-sm); }\n h3 { font-size: 1.25rem; }\n \n p { margin: var(--space-md) 0; }\n \n a {\n color: var(--color-link);\n text-decoration: none;\n }\n \n a:hover {\n color: var(--color-link-hover);\n text-decoration: underline;\n }\n \n /* Code */\n code {\n font-family: var(--font-mono);\n font-size: 0.9em;\n background: var(--color-bg-secondary);\n padding: var(--space-xs) var(--space-sm);\n border-radius: var(--border-radius);\n }\n \n pre {\n background: var(--color-bg-secondary);\n padding: var(--space-md);\n border-radius: var(--border-radius);\n overflow-x: auto;\n }\n \n pre code {\n background: none;\n padding: 0;\n }\n \n /* Tables */\n table {\n width: 100%;\n border-collapse: collapse;\n margin: var(--space-md) 0;\n }\n \n th, td {\n padding: var(--space-sm) var(--space-md);\n border: 1px solid var(--color-border);\n text-align: left;\n }\n \n th {\n background: var(--color-bg-secondary);\n font-weight: 600;\n }\n \n /* Provenance badges */\n code[class*=\"from\"] {\n font-size: 0.75em;\n color: var(--color-text-muted);\n background: transparent;\n }\n \n /* Blockquotes (for warnings/notes) */\n blockquote {\n margin: var(--space-md) 0;\n padding: var(--space-md);\n border-left: 4px solid var(--color-warning);\n background: var(--color-bg-secondary);\n }\n \n blockquote p:first-child { margin-top: 0; }\n blockquote p:last-child { margin-bottom: 0; }\n \n /* Lists */\n ul, ol {\n padding-left: var(--space-lg);\n }\n \n li { margin: var(--space-sm) 0; }\n \n /* Doc list (index page) */\n .doc-list {\n list-style: none;\n padding: 0;\n }\n \n .doc-list li {\n padding: var(--space-md);\n border: 1px solid var(--color-border);\n border-radius: var(--border-radius);\n margin-bottom: var(--space-md);\n }\n \n .doc-list a {\n display: flex;\n align-items: center;\n gap: var(--space-sm);\n }\n \n .doc-list .version {\n color: var(--color-text-muted);\n font-size: 0.875em;\n }\n \n .doc-list p {\n margin: var(--space-sm) 0 0;\n color: var(--color-text-muted);\n }\n \n /* Header */\n header {\n margin-bottom: var(--space-lg);\n }\n \n .breadcrumb {\n font-size: 0.875em;\n color: var(--color-text-muted);\n }\n \n .breadcrumb a {\n color: inherit;\n }\n \n /* Footer */\n footer {\n margin-top: var(--space-xl);\n padding-top: var(--space-lg);\n border-top: 1px solid var(--color-border);\n font-size: 0.875em;\n color: var(--color-text-muted);\n }\n \n .determinism code {\n font-size: 0.75em;\n }\n \n /* Theme toggle */\n .theme-toggle {\n position: fixed;\n top: var(--space-md);\n right: var(--space-md);\n padding: var(--space-sm) var(--space-md);\n border: 1px solid var(--color-border);\n border-radius: var(--border-radius);\n background: var(--color-bg);\n cursor: pointer;\n font-size: 0.875em;\n }\n \n /* Responsive */\n @media (max-width: 600px) {\n .container { padding: var(--space-md); }\n h1 { font-size: 1.5rem; }\n h2 { font-size: 1.25rem; }\n table { font-size: 0.875em; }\n }\n `;\n}\n\nfunction getThemeScript(): string {\n return `\n // Theme toggle\n const toggle = document.createElement('button');\n toggle.className = 'theme-toggle';\n toggle.textContent = '🌙';\n toggle.onclick = () => {\n const html = document.documentElement;\n const isDark = html.dataset.theme === 'dark';\n html.dataset.theme = isDark ? 'light' : 'dark';\n toggle.textContent = isDark ? '🌙' : '☀️';\n localStorage.setItem('theme', html.dataset.theme);\n };\n document.body.appendChild(toggle);\n \n // Restore saved theme\n const saved = localStorage.getItem('theme');\n if (saved) {\n document.documentElement.dataset.theme = saved;\n toggle.textContent = saved === 'dark' ? '☀️' : '🌙';\n } else if (window.matchMedia('(prefers-color-scheme: dark)').matches) {\n document.documentElement.dataset.theme = 'dark';\n toggle.textContent = '☀️';\n }\n `;\n}\n","/**\n * Path Safety Utilities\n *\n * Local implementation mirroring @oddessentials/odd-hive-mind/primitives/safety API.\n * When odd-hive-mind is published to npm, replace with:\n * import { resolveAndCheckPath, checkForbidden } from '@oddessentials/odd-hive-mind/primitives/safety';\n *\n * @see https://github.com/oddessentials/odd-hive-mind/blob/main/src/primitives/safety.ts\n */\n\nimport { resolve, relative, sep } from 'node:path';\nimport { realpathSync, existsSync } from 'node:fs';\n\n/**\n * Patterns forbidden for write operations\n */\nconst FORBIDDEN_PATTERNS = [\n '.git/**',\n 'node_modules/**',\n '.env*',\n 'package-lock.json',\n '*.log',\n] as const;\n\n/**\n * Resolve a path and check it doesn't escape the project root.\n * Throws if path escapes containment.\n *\n * @param projectRoot - The root directory to contain writes to\n * @param relPath - Relative path within the project\n * @returns Resolved absolute path\n * @throws Error if path escapes project root\n */\nexport function resolveAndCheckPath(projectRoot: string, relPath: string): string {\n const rootReal = realpathSync(projectRoot);\n const candidate = resolve(projectRoot, relPath);\n\n let resolved: string;\n if (existsSync(candidate)) {\n resolved = realpathSync(candidate);\n } else {\n // For new files, use path.resolve; still enforce boundary\n resolved = resolve(projectRoot, relPath);\n }\n\n const rootWithSep = rootReal.endsWith(sep) ? rootReal : rootReal + sep;\n\n if (!resolved.startsWith(rootWithSep) && resolved !== rootReal) {\n throw new Error(`Path escapes project root: ${relPath}`);\n }\n\n return resolved;\n}\n\n/**\n * Check if a path matches forbidden patterns.\n *\n * @param relPath - Relative path to check\n * @param extraPatterns - Additional patterns to check against\n * @returns Object indicating if forbidden and which rule matched\n */\nexport function checkForbidden(\n relPath: string,\n extraPatterns: string[] = []\n): { forbidden: boolean; rule?: string } {\n const p = relPath.replace(/\\\\/g, '/');\n\n if (!p) {\n return { forbidden: true, rule: '<empty path>' };\n }\n\n const patterns = [...FORBIDDEN_PATTERNS, ...extraPatterns];\n\n for (const rule of patterns) {\n if (matchesPattern(p, rule)) {\n return { forbidden: true, rule };\n }\n }\n\n return { forbidden: false };\n}\n\n/**\n * Simple glob pattern matching\n */\nfunction matchesPattern(path: string, pattern: string): boolean {\n const p = path.replace(/\\\\/g, '/');\n const pat = pattern.replace(/\\\\/g, '/');\n\n // Handle ** (any depth)\n if (pat.includes('**')) {\n const prefix = pat.split('**')[0];\n return p.startsWith(prefix);\n }\n\n // Handle * (single segment)\n if (pat.includes('*')) {\n const regex = new RegExp('^' + pat.replace(/\\*/g, '[^/]*') + '$');\n return regex.test(p);\n }\n\n return p === pat;\n}\n\n/**\n * Validate output path is safe for writing.\n * Combines containment check and forbidden pattern check.\n *\n * @param projectRoot - Project root for containment\n * @param outputPath - Path to validate\n * @returns Validated absolute path\n * @throws Error if path is forbidden or escapes root\n */\nexport function validateOutputPath(projectRoot: string, outputPath: string): string {\n const absPath = resolveAndCheckPath(projectRoot, outputPath);\n const relPath = relative(projectRoot, absPath);\n\n const forbidden = checkForbidden(relPath);\n if (forbidden.forbidden) {\n throw new Error(`Forbidden path: ${relPath} (matched: ${forbidden.rule})`);\n }\n\n return absPath;\n}\n","import { resolve } from 'node:path';\nimport { parseManifest } from '../../core/parser/manifestParser.js';\nimport { buildDocIR } from '../../core/ir/builder.js';\nimport { validateDocIR, formatValidationResult } from '../../core/ir/validator.js';\n\nexport interface ValidateOptions {\n strict?: boolean;\n}\n\nexport async function validate(repoPath: string, options: ValidateOptions = {}): Promise<boolean> {\n const absPath = resolve(repoPath);\n\n console.log(`Validating: ${absPath}`);\n console.log(`Mode: ${options.strict ? 'strict' : 'normal'}`);\n console.log('');\n\n try {\n // Parse manifest\n const manifestResult = await parseManifest(absPath);\n\n // Build Doc IR\n const ir = buildDocIR(manifestResult);\n\n // Validate\n const result = validateDocIR(ir, { strict: options.strict });\n\n // Format and print result\n console.log(formatValidationResult(result, absPath));\n\n return result.valid;\n } catch (error) {\n console.error('✗ Validation failed');\n console.error('');\n console.error(`Error: ${error instanceof Error ? error.message : error}`);\n return false;\n }\n}\n","/**\n * Known capabilities allowlist\n * Safety-affecting capabilities trigger stricter validation\n */\n\nexport const KNOWN_CAPABILITIES = [\n 'network',\n 'filesystem',\n 'secrets',\n 'exec',\n 'subprocess',\n 'database',\n 'queue',\n] as const;\n\nexport type KnownCapability = (typeof KNOWN_CAPABILITIES)[number];\n\n/**\n * Capabilities that imply safety-critical operations\n * Unknown capabilities matching these patterns fail in --strict mode\n */\nexport const SAFETY_AFFECTING_PATTERNS = ['network', 'exec', 'subprocess', 'write', 'delete'];\n\nexport function isKnownCapability(capability: string): capability is KnownCapability {\n return KNOWN_CAPABILITIES.includes(capability as KnownCapability);\n}\n\nexport function isSafetyAffecting(capability: string): boolean {\n return SAFETY_AFFECTING_PATTERNS.some((pattern) =>\n capability.toLowerCase().includes(pattern.toLowerCase())\n );\n}\n","import type { DocIR, ProvenanceSource } from '../ir/types.js';\nimport { isKnownCapability, isSafetyAffecting } from '../capabilities.js';\n\nexport type ValidationSeverity = 'error' | 'warning';\n\nexport interface ValidationIssue {\n severity: ValidationSeverity;\n code: string;\n message: string;\n path?: string;\n provenance?: ProvenanceSource;\n}\n\nexport interface ValidationResult {\n valid: boolean;\n issues: ValidationIssue[];\n}\n\nexport interface ValidateOptions {\n strict?: boolean;\n}\n\n/**\n * Validate Doc IR for completeness and consistency\n */\nexport function validateDocIR(ir: DocIR, options: ValidateOptions = {}): ValidationResult {\n const issues: ValidationIssue[] = [];\n\n // Required field checks\n if (!ir.entity.id) {\n issues.push({\n severity: 'error',\n code: 'MISSING_TOOL_ID',\n message: 'Tool ID is required',\n path: 'entity.id',\n });\n }\n\n if (!ir.entity.version) {\n issues.push({\n severity: 'error',\n code: 'MISSING_VERSION',\n message: 'Version is required',\n path: 'entity.version',\n });\n }\n\n if (!ir.inputs?.schema && !ir.inputs?.parameters?.length) {\n issues.push({\n severity: 'error',\n code: 'MISSING_PARAMETERS_SCHEMA',\n message: 'Parameters schema is required',\n path: 'inputs',\n });\n }\n\n // Capability validation\n if (ir.constraints?.capabilities) {\n for (const cap of ir.constraints.capabilities) {\n if (!isKnownCapability(cap.type)) {\n const isSafety = isSafetyAffecting(cap.type);\n issues.push({\n severity: options.strict && isSafety ? 'error' : 'warning',\n code: 'UNKNOWN_CAPABILITY',\n message: `Unknown capability: ${cap.type}${isSafety ? ' (safety-affecting)' : ''}`,\n path: `constraints.capabilities.${cap.type}`,\n provenance: cap.provenance,\n });\n }\n }\n }\n\n // Structural contradiction checks\n issues.push(...checkStructuralContradictions(ir));\n\n const hasErrors = issues.some((i) => i.severity === 'error');\n\n return {\n valid: !hasErrors,\n issues,\n };\n}\n\n/**\n * Check for structural contradictions between sources\n */\nfunction checkStructuralContradictions(ir: DocIR): ValidationIssue[] {\n const issues: ValidationIssue[] = [];\n\n // Check if narrative mentions parameters not in schema\n if (ir.narrative?.notes && ir.inputs?.parameters) {\n const schemaParams = new Set(ir.inputs.parameters.map((p) => p.name.toLowerCase()));\n\n for (const note of ir.narrative.notes) {\n // Match patterns like \"parameter X\" or \"the X parameter\"\n const paramMentions = note.match(/(?:parameter|param)\\s+[`\"']?(\\w+)[`\"']?/gi) ?? [];\n const theParamMentions = note.match(/the\\s+[`\"']?(\\w+)[`\"']?\\s+parameter/gi) ?? [];\n\n for (const match of [...paramMentions, ...theParamMentions]) {\n const paramName = match.replace(/.*?[`\"']?(\\w+)[`\"']?.*/i, '$1').toLowerCase();\n if (paramName && !schemaParams.has(paramName) && paramName !== 'parameter') {\n issues.push({\n severity: 'error',\n code: 'NARRATIVE_REFERENCES_UNDEFINED_PARAM',\n message: `Narrative references parameter \"${paramName}\" not in schema`,\n path: 'narrative.notes',\n provenance: 'narrative',\n });\n }\n }\n }\n }\n\n // Check if examples use parameters not in schema\n if (ir.narrative?.examples && ir.inputs?.parameters) {\n const schemaParams = new Set(ir.inputs.parameters.map((p) => p.name));\n\n for (const example of ir.narrative.examples) {\n if (example.input && typeof example.input === 'object') {\n for (const key of Object.keys(example.input as Record<string, unknown>)) {\n if (!schemaParams.has(key)) {\n issues.push({\n severity: 'warning',\n code: 'EXAMPLE_USES_UNDEFINED_PARAM',\n message: `Example uses parameter \"${key}\" not in schema`,\n path: `narrative.examples.${example.title ?? 'unnamed'}`,\n provenance: 'narrative',\n });\n }\n }\n }\n }\n }\n\n // Check for side effect / capability contradictions\n if (ir.overview?.sideEffects && ir.constraints?.capabilities) {\n const capTypes = new Set(ir.constraints.capabilities.map((c) => c.type));\n\n for (const effect of ir.overview.sideEffects) {\n // Map side effect types to capability types\n const expectedCap = mapSideEffectToCapability(effect.type);\n if (expectedCap && !capTypes.has(expectedCap)) {\n issues.push({\n severity: 'error',\n code: 'SIDE_EFFECT_CAPABILITY_MISMATCH',\n message: `Side effect \"${effect.type}\" requires capability \"${expectedCap}\" which is not declared`,\n path: `overview.sideEffects.${effect.type}`,\n provenance: effect.provenance,\n });\n }\n }\n }\n\n return issues;\n}\n\nfunction mapSideEffectToCapability(effectType: string): string | null {\n const mapping: Record<string, string> = {\n filesystem: 'filesystem',\n network: 'network',\n secrets: 'secrets',\n exec: 'exec',\n subprocess: 'subprocess',\n database: 'database',\n queue: 'queue',\n };\n return mapping[effectType] ?? null;\n}\n\n/**\n * Format validation result for CLI output\n */\nexport function formatValidationResult(result: ValidationResult, repoPath: string): string {\n const lines: string[] = [];\n\n lines.push(`Validating: ${repoPath}`);\n lines.push('');\n\n if (result.valid) {\n lines.push('✓ Validation passed');\n } else {\n lines.push('✗ Validation failed');\n }\n lines.push('');\n\n const errors = result.issues.filter((i) => i.severity === 'error');\n const warnings = result.issues.filter((i) => i.severity === 'warning');\n\n if (errors.length > 0) {\n lines.push(`Errors (${errors.length}):`);\n for (const issue of errors) {\n lines.push(` ✗ [${issue.code}] ${issue.message}`);\n if (issue.path) {\n lines.push(` at ${issue.path}`);\n }\n }\n lines.push('');\n }\n\n if (warnings.length > 0) {\n lines.push(`Warnings (${warnings.length}):`);\n for (const issue of warnings) {\n lines.push(` ⚠ [${issue.code}] ${issue.message}`);\n if (issue.path) {\n lines.push(` at ${issue.path}`);\n }\n }\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n","/**\n * Serve Command\n *\n * Start a local development server for generated documentation.\n * Enforces safe defaults per deployment stance:\n * - localhost binding\n * - mutations disabled\n * - SSE auto-switch for non-localhost\n */\n\nimport { existsSync } from 'node:fs';\nimport { join, resolve } from 'node:path';\nimport { OddDocsServer, type ServeOptions } from '../../server/index.js';\nimport { generate } from './generate.js';\n\nexport interface ServeCommandOptions {\n port?: number;\n host?: string;\n output?: string;\n watch?: boolean;\n watchMode?: 'auto' | 'poll';\n reload?: 'ws' | 'sse' | 'poll' | 'none';\n open?: boolean;\n introspect?: string;\n enableMutations?: boolean;\n mutationToken?: string;\n}\n\n/**\n * Serve documentation with live reload\n */\nexport async function serve(repoPath: string, options: ServeCommandOptions = {}): Promise<void> {\n const resolvedPath = resolve(repoPath);\n\n // Determine output directory\n const outputDir = options.output\n ? resolve(options.output)\n : join(resolvedPath, 'docs', 'generated');\n\n // Check if docs exist, generate if not\n if (!existsSync(outputDir)) {\n console.log('[odd-docs] Documentation not found, generating...');\n await generate(repoPath, { output: outputDir, format: 'html' });\n }\n\n // Determine reload mode\n let reloadMode: 'ws' | 'sse' | 'poll' | 'none' = options.reload ?? 'ws';\n\n // Use poll mode if explicitly requested via env or option\n if (options.watchMode === 'poll' || process.env.CHOKIDAR_USEPOLLING === '1') {\n reloadMode = 'poll';\n console.log('[odd-docs] Using poll-based watching (CPU intensive)');\n }\n\n const host = options.host ?? 'localhost';\n const port = options.port ?? 3000;\n\n // Auto-switch to SSE for non-localhost (safer for K8s)\n if (host !== 'localhost' && options.reload === undefined) {\n reloadMode = 'sse';\n console.log('[odd-docs] Using SSE for non-localhost binding');\n }\n\n // Create and start server\n const serverOptions: Partial<ServeOptions> & { outputDir: string } = {\n outputDir,\n host,\n port,\n watch: options.watch !== false,\n reloadMode,\n enableMutations: options.enableMutations ?? false,\n mutationToken: options.mutationToken,\n };\n\n const server = new OddDocsServer(serverOptions);\n\n // Handle shutdown\n const shutdown = async () => {\n console.log('\\n[odd-docs] Shutting down...');\n await server.stop();\n process.exit(0);\n };\n\n process.on('SIGINT', shutdown);\n process.on('SIGTERM', shutdown);\n\n try {\n await server.start();\n\n // Open browser if requested\n if (options.open !== false && host === 'localhost') {\n const url = `http://${host}:${port}`;\n try {\n const { default: open } = await import('open');\n await open(url);\n } catch {\n console.log(`[odd-docs] Open browser manually: ${url}`);\n }\n }\n } catch (error) {\n console.error('[odd-docs] Failed to start server:', error);\n process.exit(1);\n }\n}\n","/**\n * OddDocs Server\n *\n * HTTP server wrapper for serving generated documentation.\n * Enforces safe defaults: localhost binding, no mutations without explicit opt-in.\n */\n\nimport { createServer, type Server, type IncomingMessage, type ServerResponse } from 'node:http';\nimport { FileServer } from './fileServer.js';\nimport { LiveReload } from './livereload.js';\nimport { ApiHandler, type ServerState } from './api.js';\n\nexport interface ServeOptions {\n /** Port to listen on. Default: 3000 */\n port: number;\n /** Host to bind. Default: 'localhost' (safe) */\n host: string;\n /** Documentation output directory */\n outputDir: string;\n /** Enable file watching for live reload. Default: true */\n watch: boolean;\n /** Reload mechanism. Default: 'ws' for localhost, 'sse' for 0.0.0.0 */\n reloadMode: 'ws' | 'sse' | 'poll' | 'none';\n /** Enable mutation API endpoints. Default: false */\n enableMutations: boolean;\n /** Token for mutation endpoints. Required if enableMutations=true */\n mutationToken?: string;\n /** Request timeout in ms. Default: 30000 */\n requestTimeout: number;\n}\n\nexport const DEFAULT_OPTIONS: Omit<ServeOptions, 'outputDir'> = {\n port: 3000,\n host: 'localhost',\n watch: true,\n reloadMode: 'ws',\n enableMutations: false,\n requestTimeout: 30000,\n};\n\nexport class OddDocsServer {\n private server: Server | null = null;\n private fileServer: FileServer;\n private liveReload: LiveReload | null = null;\n private apiHandler: ApiHandler;\n private options: ServeOptions;\n private state: ServerState;\n\n constructor(options: Partial<ServeOptions> & { outputDir: string }) {\n // Apply defaults\n this.options = {\n ...DEFAULT_OPTIONS,\n ...options,\n // Auto-switch to SSE for non-localhost binding (safer for K8s)\n reloadMode:\n options.reloadMode ??\n (options.host && options.host !== 'localhost' ? 'sse' : DEFAULT_OPTIONS.reloadMode),\n };\n\n // Environment overrides\n this.options.host = process.env.ODD_DOCS_HOST ?? this.options.host;\n this.options.port = parseInt(process.env.ODD_DOCS_PORT ?? String(this.options.port), 10);\n this.options.mutationToken = process.env.ODD_DOCS_MUTATION_TOKEN ?? this.options.mutationToken;\n\n this.state = {\n lastGenerateSuccess: true,\n lastGenerateTime: new Date().toISOString(),\n outputDirAccessible: true,\n introspectionConnected: false,\n };\n\n this.fileServer = new FileServer(this.options.outputDir);\n this.apiHandler = new ApiHandler(this.state, this.options);\n }\n\n async start(): Promise<void> {\n // Validate mutation token if mutations enabled\n if (this.options.enableMutations && !this.options.mutationToken) {\n throw new Error(\n 'Mutation token required when --enable-mutations is set. ' +\n 'Set ODD_DOCS_MUTATION_TOKEN or --mutation-token'\n );\n }\n\n this.server = createServer((req, res) => this.handleRequest(req, res));\n\n // Set timeout\n this.server.timeout = this.options.requestTimeout;\n\n // Start live reload if enabled\n if (this.options.watch && this.options.reloadMode !== 'none') {\n this.liveReload = new LiveReload({\n outputDir: this.options.outputDir,\n mode: this.options.reloadMode,\n server: this.server,\n });\n await this.liveReload.start();\n }\n\n return new Promise((resolve, reject) => {\n this.server!.listen(this.options.port, this.options.host, () => {\n console.log(\n `[odd-docs] Server started at http://${this.options.host}:${this.options.port}`\n );\n console.log(`[odd-docs] Serving: ${this.options.outputDir}`);\n if (this.liveReload) {\n console.log(`[odd-docs] Live reload: ${this.options.reloadMode}`);\n }\n resolve();\n });\n\n this.server!.on('error', reject);\n });\n }\n\n async stop(): Promise<void> {\n if (this.liveReload) {\n await this.liveReload.stop();\n }\n if (this.server) {\n return new Promise((resolve) => {\n this.server!.close(() => resolve());\n });\n }\n }\n\n private async handleRequest(req: IncomingMessage, res: ServerResponse): Promise<void> {\n const url = req.url ?? '/';\n\n try {\n // API routes\n if (url.startsWith('/api/')) {\n await this.apiHandler.handle(req, res);\n return;\n }\n\n // Live reload endpoints\n if (this.liveReload && url === '/__livereload') {\n await this.liveReload.handleRequest(req, res);\n return;\n }\n\n // Static file serving\n await this.fileServer.serve(req, res);\n } catch (error) {\n console.error('[odd-docs] Request error:', error);\n res.statusCode = 500;\n res.end('Internal Server Error');\n }\n }\n\n updateState(updates: Partial<ServerState>): void {\n Object.assign(this.state, updates);\n }\n}\n","/**\n * File Server\n *\n * Static file serving with security protections.\n * - Path traversal protection via realpath + relative check\n * - MIME type detection\n * - ETag/304 support\n * - Max response size cap\n */\n\nimport { createReadStream, statSync } from 'node:fs';\nimport { realpath } from 'node:fs/promises';\nimport { join, extname, relative, isAbsolute } from 'node:path';\nimport { createHash } from 'node:crypto';\nimport type { IncomingMessage, ServerResponse } from 'node:http';\n\nconst MAX_RESPONSE_SIZE = 50 * 1024 * 1024; // 50MB\n\nconst MIME_TYPES: Record<string, string> = {\n '.html': 'text/html; charset=utf-8',\n '.css': 'text/css; charset=utf-8',\n '.js': 'application/javascript; charset=utf-8',\n '.json': 'application/json; charset=utf-8',\n '.md': 'text/markdown; charset=utf-8',\n '.png': 'image/png',\n '.jpg': 'image/jpeg',\n '.jpeg': 'image/jpeg',\n '.gif': 'image/gif',\n '.svg': 'image/svg+xml',\n '.ico': 'image/x-icon',\n '.woff': 'font/woff',\n '.woff2': 'font/woff2',\n '.ttf': 'font/ttf',\n};\n\nexport class FileServer {\n private rootDir: string;\n private resolvedRoot: string | null = null;\n\n constructor(rootDir: string) {\n this.rootDir = rootDir;\n }\n\n async serve(req: IncomingMessage, res: ServerResponse): Promise<void> {\n const url = new URL(req.url ?? '/', `http://${req.headers.host}`);\n let pathname = decodeURIComponent(url.pathname);\n\n // Default to index.html\n if (pathname === '/' || pathname.endsWith('/')) {\n pathname = join(pathname, 'index.html');\n }\n\n // Resolve and validate path\n const filePath = await this.resolvePath(pathname);\n if (!filePath) {\n res.statusCode = 403;\n res.end('Forbidden: Path traversal blocked');\n return;\n }\n\n // Check file exists and get stats\n let stats;\n try {\n stats = statSync(filePath);\n } catch {\n res.statusCode = 404;\n res.end('Not Found');\n return;\n }\n\n if (!stats.isFile()) {\n res.statusCode = 404;\n res.end('Not Found');\n return;\n }\n\n // Check size limit\n if (stats.size > MAX_RESPONSE_SIZE) {\n res.statusCode = 413;\n res.end('File too large');\n return;\n }\n\n // ETag handling\n const etag = this.computeETag(filePath, stats.mtime, stats.size);\n const ifNoneMatch = req.headers['if-none-match'];\n if (ifNoneMatch === etag) {\n res.statusCode = 304;\n res.end();\n return;\n }\n\n // Set headers\n const ext = extname(filePath).toLowerCase();\n const contentType = MIME_TYPES[ext] ?? 'application/octet-stream';\n\n res.setHeader('Content-Type', contentType);\n res.setHeader('Content-Length', stats.size);\n res.setHeader('ETag', etag);\n res.setHeader('Cache-Control', 'no-cache');\n\n // Stream file\n const stream = createReadStream(filePath);\n stream.pipe(res);\n stream.on('error', () => {\n res.statusCode = 500;\n res.end('Error reading file');\n });\n }\n\n /**\n * Resolve path with traversal protection\n */\n private async resolvePath(pathname: string): Promise<string | null> {\n // Ensure we have the real root path\n if (!this.resolvedRoot) {\n try {\n this.resolvedRoot = await realpath(this.rootDir);\n } catch {\n return null;\n }\n }\n\n // Construct target path\n const targetPath = join(this.rootDir, pathname);\n\n // Resolve to real path (follows symlinks, canonicalizes)\n let resolvedTarget: string;\n try {\n resolvedTarget = await realpath(targetPath);\n } catch {\n return null;\n }\n\n // Check containment: resolved path must be within root\n const rel = relative(this.resolvedRoot, resolvedTarget);\n if (rel.startsWith('..') || isAbsolute(rel)) {\n // Path escapes root directory\n console.warn(`[odd-docs] Path traversal blocked: ${pathname}`);\n return null;\n }\n\n return resolvedTarget;\n }\n\n private computeETag(path: string, mtime: Date, size: number): string {\n const hash = createHash('md5')\n .update(`${path}:${mtime.getTime()}:${size}`)\n .digest('hex')\n .slice(0, 16);\n return `\"${hash}\"`;\n }\n}\n","/**\n * Live Reload\n *\n * File watching and live reload for development.\n * Supports multiple mechanisms: WebSocket, SSE, Polling.\n * WS is dev-only default; SSE is K8s-safe.\n */\n\nimport { watch, type FSWatcher } from 'node:fs';\nimport type { Server, IncomingMessage, ServerResponse } from 'node:http';\n\nexport interface LiveReloadOptions {\n outputDir: string;\n mode: 'ws' | 'sse' | 'poll' | 'none';\n server: Server;\n pollInterval?: number; // for poll mode, ms\n}\n\ntype ReloadMode = 'ws' | 'sse' | 'poll' | 'none';\n\nexport class LiveReload {\n private options: LiveReloadOptions;\n private watcher: FSWatcher | null = null;\n private sseClients: Set<ServerResponse> = new Set();\n private lastChangeTime: number = Date.now();\n private debounceTimer: NodeJS.Timeout | null = null;\n\n constructor(options: LiveReloadOptions) {\n this.options = {\n pollInterval: 5000,\n ...options,\n };\n }\n\n async start(): Promise<void> {\n // Start file watcher with debounce\n const usePolling = process.env.CHOKIDAR_USEPOLLING === '1' || this.options.mode === 'poll';\n\n this.watcher = watch(\n this.options.outputDir,\n { recursive: true, persistent: true },\n (_eventType, filename) => {\n if (filename) {\n this.onFileChange(filename);\n }\n }\n );\n\n if (usePolling) {\n console.log('[odd-docs] Using poll-based file watching');\n }\n\n console.log(`[odd-docs] Live reload started (mode: ${this.options.mode})`);\n }\n\n async stop(): Promise<void> {\n if (this.debounceTimer) {\n clearTimeout(this.debounceTimer);\n }\n if (this.watcher) {\n this.watcher.close();\n }\n // Close SSE connections\n for (const client of this.sseClients) {\n client.end();\n }\n this.sseClients.clear();\n }\n\n private onFileChange(filename: string): void {\n // Debounce rapid changes\n if (this.debounceTimer) {\n clearTimeout(this.debounceTimer);\n }\n this.debounceTimer = setTimeout(() => {\n this.lastChangeTime = Date.now();\n console.log(`[odd-docs] Change detected: ${filename}`);\n this.notifyClients();\n }, 100);\n }\n\n private notifyClients(): void {\n const message = JSON.stringify({ type: 'reload', time: this.lastChangeTime });\n\n // Notify SSE clients\n for (const client of this.sseClients) {\n client.write(`data: ${message}\\n\\n`);\n }\n }\n\n async handleRequest(req: IncomingMessage, res: ServerResponse): Promise<void> {\n const mode = this.options.mode;\n\n if (mode === 'sse') {\n // SSE endpoint\n res.setHeader('Content-Type', 'text/event-stream');\n res.setHeader('Cache-Control', 'no-cache');\n res.setHeader('Connection', 'keep-alive');\n res.setHeader('X-Accel-Buffering', 'no'); // For nginx\n\n res.write(': ping\\n\\n');\n this.sseClients.add(res);\n\n req.on('close', () => {\n this.sseClients.delete(res);\n });\n } else if (mode === 'poll') {\n // Poll endpoint - return last change time\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ lastChange: this.lastChangeTime }));\n } else {\n // Not supported in this mode\n res.statusCode = 404;\n res.end('Live reload not available in this mode');\n }\n }\n\n /**\n * Get client-side script for live reload\n */\n static getClientScript(mode: ReloadMode, pollInterval: number = 5000): string {\n if (mode === 'none') return '';\n\n if (mode === 'sse') {\n return `\n<script>\n(function() {\n const es = new EventSource('/__livereload');\n es.onmessage = function(e) {\n const data = JSON.parse(e.data);\n if (data.type === 'reload') {\n console.log('[odd-docs] Reloading...');\n location.reload();\n }\n };\n es.onerror = function() {\n console.log('[odd-docs] SSE connection lost, will retry...');\n };\n})();\n</script>`;\n }\n\n if (mode === 'poll') {\n return `\n<script>\n(function() {\n let lastChange = 0;\n setInterval(async () => {\n try {\n const res = await fetch('/__livereload');\n const data = await res.json();\n if (lastChange && data.lastChange > lastChange) {\n console.log('[odd-docs] Reloading...');\n location.reload();\n }\n lastChange = data.lastChange;\n } catch (e) {}\n }, ${pollInterval});\n})();\n</script>`;\n }\n\n // WebSocket (ws mode) - requires separate ws server\n return `\n<script>\n(function() {\n const ws = new WebSocket('ws://' + location.host + '/__ws');\n ws.onmessage = function(e) {\n const data = JSON.parse(e.data);\n if (data.type === 'reload') {\n console.log('[odd-docs] Reloading...');\n location.reload();\n }\n };\n ws.onclose = function() {\n console.log('[odd-docs] WebSocket closed, will retry in 3s...');\n setTimeout(() => location.reload(), 3000);\n };\n})();\n</script>`;\n }\n}\n","/**\n * API Handler\n *\n * REST API endpoints for programmatic access.\n * Implements K8s-compatible health semantics.\n * Mutation endpoints require explicit opt-in + token.\n */\n\nimport type { IncomingMessage, ServerResponse } from 'node:http';\nimport type { ServeOptions } from './index.js';\n\nconst MAX_IR_SIZE = 10 * 1024 * 1024; // 10MB\n\nexport interface ServerState {\n lastGenerateSuccess: boolean;\n lastGenerateTime: string;\n outputDirAccessible: boolean;\n introspectionConnected: boolean;\n lastIntrospectionTime?: string;\n}\n\nexport class ApiHandler {\n private state: ServerState;\n private options: ServeOptions;\n\n constructor(state: ServerState, options: ServeOptions) {\n this.state = state;\n this.options = options;\n }\n\n async handle(req: IncomingMessage, res: ServerResponse): Promise<void> {\n const url = new URL(req.url ?? '/', `http://${req.headers.host}`);\n const path = url.pathname;\n const method = req.method ?? 'GET';\n\n // Route to handlers\n switch (path) {\n case '/api/health':\n return this.handleHealth(res);\n case '/api/ready':\n return this.handleReady(res);\n case '/api/introspection':\n return this.handleIntrospection(res);\n case '/api/docs':\n return this.handleDocs(res);\n case '/api/ir':\n return this.handleIR(res);\n case '/api/capabilities':\n return this.handleCapabilities(res);\n case '/api/regenerate':\n if (method === 'POST') {\n return this.handleRegenerate(req, res);\n }\n return this.methodNotAllowed(res);\n default:\n return this.notFound(res);\n }\n }\n\n /**\n * GET /api/health - Liveness probe\n * Returns 200 if process is running\n */\n private handleHealth(res: ServerResponse): void {\n this.json(res, {\n status: 'ok',\n timestamp: new Date().toISOString(),\n });\n }\n\n /**\n * GET /api/ready - Readiness probe\n * Returns 200 if last generate succeeded and output is accessible\n */\n private handleReady(res: ServerResponse): void {\n const ready = this.state.lastGenerateSuccess && this.state.outputDirAccessible;\n\n if (!ready) {\n res.statusCode = 503;\n }\n\n this.json(res, {\n ready,\n lastGenerateSuccess: this.state.lastGenerateSuccess,\n lastGenerateTime: this.state.lastGenerateTime,\n outputDirAccessible: this.state.outputDirAccessible,\n });\n }\n\n /**\n * GET /api/introspection - Introspection status\n */\n private handleIntrospection(res: ServerResponse): void {\n this.json(res, {\n connected: this.state.introspectionConnected,\n lastPollTime: this.state.lastIntrospectionTime ?? null,\n });\n }\n\n /**\n * GET /api/docs - List documentation sections\n */\n private handleDocs(res: ServerResponse): void {\n // TODO: Implement actual doc listing\n this.json(res, {\n sections: [],\n message: 'Not implemented yet',\n });\n }\n\n /**\n * GET /api/ir - Full IR dump (capped at 10MB)\n */\n private handleIR(res: ServerResponse): void {\n // TODO: Implement actual IR retrieval\n const ir = { tools: [], prompts: [], resources: [] };\n const irJson = JSON.stringify(ir);\n\n if (irJson.length > MAX_IR_SIZE) {\n this.json(res, {\n truncated: true,\n message: `IR exceeds ${MAX_IR_SIZE / 1024 / 1024}MB limit`,\n partial: null,\n });\n return;\n }\n\n res.setHeader('Content-Type', 'application/json');\n res.end(irJson);\n }\n\n /**\n * GET /api/capabilities - Tool capabilities summary\n */\n private handleCapabilities(res: ServerResponse): void {\n this.json(res, {\n serve: {\n host: this.options.host,\n port: this.options.port,\n reloadMode: this.options.reloadMode,\n mutationsEnabled: this.options.enableMutations,\n },\n });\n }\n\n /**\n * POST /api/regenerate - Trigger manual regeneration\n * Requires --enable-mutations and valid token\n */\n private handleRegenerate(req: IncomingMessage, res: ServerResponse): void {\n // Check if mutations are enabled\n if (!this.options.enableMutations) {\n res.statusCode = 403;\n this.json(res, {\n error: 'Mutations disabled',\n message: 'Start server with --enable-mutations to use this endpoint',\n });\n return;\n }\n\n // Validate token\n const token = req.headers['x-mutation-token'];\n if (token !== this.options.mutationToken) {\n res.statusCode = 401;\n this.json(res, {\n error: 'Unauthorized',\n message: 'Invalid or missing X-Mutation-Token header',\n });\n return;\n }\n\n // TODO: Trigger actual regeneration\n this.json(res, {\n status: 'queued',\n message: 'Regeneration triggered',\n timestamp: new Date().toISOString(),\n });\n }\n\n private json(res: ServerResponse, data: unknown): void {\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify(data, null, 2));\n }\n\n private notFound(res: ServerResponse): void {\n res.statusCode = 404;\n this.json(res, { error: 'Not Found' });\n }\n\n private methodNotAllowed(res: ServerResponse): void {\n res.statusCode = 405;\n this.json(res, { error: 'Method Not Allowed' });\n }\n}\n"],"mappings":"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","names":["join","resolve","relative","resolve","join","relative","resolve","resolve","existsSync","join","resolve","join","relative","createHash","resolve","resolve","join","existsSync","require"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oddessentials/odd-docs",
3
- "version": "2.1.0",
3
+ "version": "2.2.0",
4
4
  "description": "MCP-native documentation generator for clients, servers, and tools",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",