#!/usr/bin/env node /** * cli:scaffold-doc — write the deterministic doc artifacts + emit a wiring plan. * * BIMODAL on the frontend deployment mode (auto-detected, overridable via * spec.mode) — see generate.ts: * - SOURCE: i18n files + docs-manifest upsert + wiring plan for the in-place * TSX edits (i18n config.ts, DocRoutes.tsx, DocPanelContext.tsx, * UserIndexPage.tsx) that Claude applies with Edit. * - CLIENT: i18n files (KEBAB namespace) + src/extensions/Registry.ts * (docs.* PageRegistry seam) + docs-manifest create/upsert + an instruction * to re-run aggregate-component-registry. * * A missing wiring target FAILS the run (exit 1) — never a silent skip. Does * NOT author the doc page body or i18n content — those stay LLM-authored per * templates.md. * * Usage: * npx --prefer-offline tsx skills/documentation/cli/scaffold-doc/index.ts --spec '' [--dry_run] */ import { parseArgs } from 'node:util' import { validate } from './validate.js' import { generate } from './generate.js' import { generateEnvelope, failGenerate, printEnvelope } from '../../../lib/output.js' const COMMAND = 'scaffold-doc' async function main(): Promise { const { values } = parseArgs({ options: { spec: { type: 'string' }, dry_run: { type: 'boolean', default: false } }, strict: true, }) if (!values.spec) { printEnvelope(failGenerate(COMMAND, ['--spec is required'])) process.exit(1) } let raw: unknown try { raw = JSON.parse(values.spec) } catch { printEnvelope(failGenerate(COMMAND, ['Invalid JSON in --spec'])) process.exit(1) } const validation = validate(raw) if (!validation.valid || !validation.value) { printEnvelope(failGenerate(COMMAND, validation.errors)) process.exit(1) } const spec = validation.value if (values.dry_run) spec.dryRun = true try { const result = await generate(spec) const envelope = generateEnvelope(COMMAND, { success: result.errors.length === 0, data: { dryRun: spec.dryRun, mode: result.mode, packageVersion: result.packageVersion, namespace: result.effectiveNamespace, wiring: result.wiring, }, filesCreated: result.filesCreated, filesModified: result.filesModified, errors: result.errors, warnings: [...validation.warnings, ...result.warnings], nextSteps: result.nextSteps, }) printEnvelope(envelope) // Loud failure: a missing wiring target / violated client invariant must // stop the skill flow, not degrade into an orphan (unrouted) doc page. if (result.errors.length > 0) process.exit(1) } catch (err) { printEnvelope(failGenerate(COMMAND, [err instanceof Error ? err.message : String(err)])) process.exit(1) } } void main()