@oddessentials/odd-docs 2.0.1 → 2.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +238 -0
- package/dist/cli/index.js +8 -6
- package/dist/cli/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
# odd-docs
|
|
2
|
+
|
|
3
|
+
`odd-docs` is a documentation generation utility that lives inside the **oddessentials-mcp** ecosystem. Its purpose is to generate deterministic, structured documentation for MCP-compatible tools, servers, or repositories by inspecting manifests, schemas, and related metadata.
|
|
4
|
+
|
|
5
|
+
It can be used in two distinct ways:
|
|
6
|
+
|
|
7
|
+
1. **Manually**, as a standalone CLI tool
|
|
8
|
+
2. **Indirectly**, when invoked by an MCP host (such as `oddessentials-mcp`)
|
|
9
|
+
|
|
10
|
+
These two modes differ significantly in how execution, file access, and persistence work. This README documents both paths explicitly.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## What odd-docs does
|
|
15
|
+
|
|
16
|
+
At a high level, `odd-docs`:
|
|
17
|
+
|
|
18
|
+
- Reads MCP-style manifests and schemas from a repository
|
|
19
|
+
- Builds an internal documentation representation
|
|
20
|
+
- Emits human-readable documentation (Markdown and/or HTML)
|
|
21
|
+
- Optionally validates documentation inputs
|
|
22
|
+
- Can serve generated documentation locally for inspection
|
|
23
|
+
|
|
24
|
+
It is intentionally **non-interactive** and **deterministic**: given the same inputs, it produces the same outputs.
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Installation (manual usage)
|
|
29
|
+
|
|
30
|
+
If you are using `odd-docs` outside of an MCP host, install it via npm:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npm install -g @oddessentials/odd-docs
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Or run it without installing:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
npx @oddessentials/odd-docs --help
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Manual CLI usage
|
|
45
|
+
|
|
46
|
+
### Basic command structure
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
odd-docs <command> <path> [options]
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
`<path>` is typically a repository root containing:
|
|
53
|
+
|
|
54
|
+
- an MCP-compatible manifest
|
|
55
|
+
- associated schema files
|
|
56
|
+
- optional descriptive markdown
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
### Generating documentation
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
odd-docs generate <repo-path>
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
By default, this:
|
|
67
|
+
|
|
68
|
+
- Reads documentation inputs from `<repo-path>`
|
|
69
|
+
- Writes generated output to a documentation directory inside the repository
|
|
70
|
+
|
|
71
|
+
Common options include:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
--format md|html|both
|
|
75
|
+
--output <directory>
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Example:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
odd-docs generate . --format both --output docs/generated
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Outputs typically include:
|
|
85
|
+
|
|
86
|
+
- One or more `.md` and/or `.html` files
|
|
87
|
+
- A machine-readable intermediate representation (IR) JSON file
|
|
88
|
+
|
|
89
|
+
These outputs **persist on disk** when running manually.
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
### Validating documentation inputs
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
odd-docs validate <repo-path>
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Validation checks include (non-exhaustive):
|
|
100
|
+
|
|
101
|
+
- Required manifest fields
|
|
102
|
+
- Schema presence and consistency
|
|
103
|
+
- Capability declarations
|
|
104
|
+
- Structural correctness
|
|
105
|
+
|
|
106
|
+
Validation **does not write output files**.
|
|
107
|
+
It exits non-zero if errors are found, making it suitable for CI.
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
### Serving documentation locally
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
odd-docs serve <repo-path>
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
This:
|
|
118
|
+
|
|
119
|
+
- Generates documentation (if not already generated)
|
|
120
|
+
- Starts a local HTTP server to view the docs
|
|
121
|
+
- Optionally watches for file changes
|
|
122
|
+
|
|
123
|
+
By default:
|
|
124
|
+
|
|
125
|
+
- Host: `localhost`
|
|
126
|
+
- Port: `3000`
|
|
127
|
+
|
|
128
|
+
This mode is intended for **local development only**.
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Temporary directories (manual usage)
|
|
133
|
+
|
|
134
|
+
When running manually:
|
|
135
|
+
|
|
136
|
+
- `odd-docs` operates directly on the paths you provide
|
|
137
|
+
- Generated documentation is written to real directories you control
|
|
138
|
+
- **Nothing is automatically deleted**
|
|
139
|
+
|
|
140
|
+
If a temporary directory is used internally (e.g. during processing), it is scoped to the execution and does not affect your outputs.
|
|
141
|
+
|
|
142
|
+
**You control persistence entirely** by choosing output paths.
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## Usage via MCP (oddessentials-mcp)
|
|
147
|
+
|
|
148
|
+
When `odd-docs` is used through **oddessentials-mcp**, you do **not** run the CLI yourself.
|
|
149
|
+
|
|
150
|
+
Instead:
|
|
151
|
+
|
|
152
|
+
- The MCP host launches `odd-docs` as a managed tool
|
|
153
|
+
- Inputs are staged into an isolated workspace
|
|
154
|
+
- Outputs are collected as artifacts
|
|
155
|
+
- Execution happens in a sandboxed environment
|
|
156
|
+
|
|
157
|
+
This has important implications.
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## Temporary directories (MCP-managed execution)
|
|
162
|
+
|
|
163
|
+
When invoked by an MCP host:
|
|
164
|
+
|
|
165
|
+
- A **temporary working directory** is created automatically
|
|
166
|
+
- Repository files are copied or mounted into that directory
|
|
167
|
+
- Documentation output is written **inside that temporary directory**
|
|
168
|
+
- After execution completes, the directory is **deleted**
|
|
169
|
+
|
|
170
|
+
### ⚠️ Persistence warning (important)
|
|
171
|
+
|
|
172
|
+
When running under MCP control:
|
|
173
|
+
|
|
174
|
+
- **You cannot persist the temporary directory**
|
|
175
|
+
- There is no supported flag to “keep” it
|
|
176
|
+
- The directory lifecycle is owned by the MCP host
|
|
177
|
+
- Files are removed even after successful execution
|
|
178
|
+
|
|
179
|
+
If you need persistent documentation files:
|
|
180
|
+
|
|
181
|
+
- Retrieve them from the MCP artifact output
|
|
182
|
+
- Or run `odd-docs` manually outside of MCP
|
|
183
|
+
|
|
184
|
+
Attempting to rely on MCP temp directories for persistence is unsupported and unsafe.
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## Why this design exists
|
|
189
|
+
|
|
190
|
+
The MCP execution model intentionally:
|
|
191
|
+
|
|
192
|
+
- Isolates tools from the host system
|
|
193
|
+
- Prevents unintended filesystem access
|
|
194
|
+
- Ensures repeatable, side-effect-free runs
|
|
195
|
+
|
|
196
|
+
`odd-docs` follows this model strictly.
|
|
197
|
+
Persistence is handled **by the MCP host**, not by `odd-docs` itself.
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## When to use which mode
|
|
202
|
+
|
|
203
|
+
### Use manual CLI mode if you:
|
|
204
|
+
|
|
205
|
+
- Want files written directly into your repository
|
|
206
|
+
- Need persistent documentation outputs
|
|
207
|
+
- Are developing or iterating on docs locally
|
|
208
|
+
|
|
209
|
+
### Use MCP-managed mode if you:
|
|
210
|
+
|
|
211
|
+
- Are generating docs as part of an automated pipeline
|
|
212
|
+
- Want documentation as artifacts, not files
|
|
213
|
+
- Are operating inside the oddessentials ecosystem
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
## Non-goals
|
|
218
|
+
|
|
219
|
+
`odd-docs` does **not**:
|
|
220
|
+
|
|
221
|
+
- Edit your source files
|
|
222
|
+
- Maintain long-lived state
|
|
223
|
+
- Act as a documentation CMS
|
|
224
|
+
- Guarantee persistence when run under MCP
|
|
225
|
+
|
|
226
|
+
---
|
|
227
|
+
|
|
228
|
+
## Summary
|
|
229
|
+
|
|
230
|
+
- `odd-docs` is deterministic, non-interactive, and filesystem-conscious
|
|
231
|
+
- Manual usage gives you full control and persistence
|
|
232
|
+
- MCP usage is sandboxed and ephemeral by design
|
|
233
|
+
- Temporary directories under MCP **cannot be persisted**
|
|
234
|
+
|
|
235
|
+
If you need persistence, run it manually.
|
|
236
|
+
If you need safety and automation, use MCP.
|
|
237
|
+
|
|
238
|
+
Both are valid — just not interchangeable.
|
package/dist/cli/index.js
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
// src/cli/index.ts
|
|
2
2
|
import { Command } from "commander";
|
|
3
|
-
import {
|
|
4
|
-
import { dirname, join as join5 } from "path";
|
|
5
|
-
import { fileURLToPath } from "url";
|
|
3
|
+
import { createRequire } from "module";
|
|
6
4
|
|
|
7
5
|
// src/cli/commands/generate.ts
|
|
8
6
|
import { writeFile, mkdir } from "fs/promises";
|
|
@@ -1438,10 +1436,14 @@ async function serve(repoPath, options = {}) {
|
|
|
1438
1436
|
}
|
|
1439
1437
|
|
|
1440
1438
|
// src/cli/index.ts
|
|
1441
|
-
var
|
|
1442
|
-
var packageJson =
|
|
1439
|
+
var require2 = createRequire(import.meta.url);
|
|
1440
|
+
var packageJson = require2("../../package.json");
|
|
1441
|
+
if (process.argv.includes("--version") || process.argv.includes("-V")) {
|
|
1442
|
+
console.log(packageJson.version);
|
|
1443
|
+
process.exit(0);
|
|
1444
|
+
}
|
|
1443
1445
|
var program = new Command();
|
|
1444
|
-
program.name("odd-docs").description("MCP-native documentation generator")
|
|
1446
|
+
program.name("odd-docs").description("MCP-native documentation generator");
|
|
1445
1447
|
program.command("generate").description("Generate documentation for an MCP repo").argument("<repo-path>", "Path to the repository").option("-f, --format <format>", "Output format: md, html, or both", "md").option("-o, --output <dir>", "Output directory").option("--introspect <url>", "MCP server URL for live introspection").action(async (repoPath, options) => {
|
|
1446
1448
|
try {
|
|
1447
1449
|
await generate(repoPath, {
|
package/dist/cli/index.js.map
CHANGED
|
@@ -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":["import { Command } from 'commander';\nimport { readFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { generate } from './commands/generate.js';\nimport { validate } from './commands/validate.js';\nimport { serve } from './commands/serve.js';\n\n// Read version from package.json\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst packageJson = JSON.parse(readFileSync(join(__dirname, '../../package.json'), 'utf-8'));\n\nconst program = new Command();\n\nprogram\n .name('odd-docs')\n .description('MCP-native documentation generator')\n .version(packageJson.version);\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, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\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","join","resolve","resolve","join","resolve","join","createHash","resolve","resolve","join","join"]}
|
|
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":["import { 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, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\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"]}
|