#!/usr/bin/env node /** * cli:derive-code-specs — entry point. * * THE deterministic deriver of the coded-entities seam: from each * `- **Code pattern**` line of the module's entité.md, emits both scaffolder * halves (`scaffold-entity.codedEntity` fragment + full `scaffold-coded-entity` * entry) and reconciles the pagespec `"codedEntity": true` flags (single * source of truth = entité.md — additive AND stale-removing, idempotent). * * Invocation: * npx --prefer-offline tsx skills/ba-develop/cli/derive-code-specs/index.ts \ * --spec '{"moduleRoot":".smartstack/ba//"}' * * `mode:"check"` is the engine of audit-prd **PRD-132** (bidirectional * entité.md ⇔ pagespec parity) — drift is DATA (exit 0), the verdict belongs * to the audit. Runbook: THIS (Phase 1 spec assembly + create-prd post-step) * → scaffold-entity + scaffold-coded-entity from `entities[]` → gate * DEV-API-022 (presence + coherence) / DEV-API-034 (no hand-rolled generator). */ import { parseArgs } from 'node:util' import { validate } from './validate.js' import { deriveCodeSpecs } from './derive.js' import { CODE_PATTERN_CANONICAL_FORM } from '../../../lib/code-pattern-grammar.js' import { executeEnvelope, failExecute, printEnvelope } from '../../../lib/output.js' import type { DeriveCodeSpecsReport } from './types.js' const COMMAND = 'derive-code-specs' function main(): void { const { values } = parseArgs({ options: { spec: { type: 'string' } }, strict: true }) if (!values.spec) { printEnvelope(failExecute(COMMAND, ['--spec is required'])) process.exit(1) } let raw: unknown try { raw = JSON.parse(values.spec) } catch { printEnvelope(failExecute(COMMAND, ['Invalid JSON in --spec'])) process.exit(1) } const validation = validate(raw) if (!validation.valid || !validation.spec) { printEnvelope(failExecute(COMMAND, validation.errors)) process.exit(1) } const report = deriveCodeSpecs(validation.spec) const nextSteps: string[] = [ 'Phase 1: pass each entities[].scaffoldEntityCoded to scaffold-entity and each entities[].scaffoldCodedEntity to scaffold-coded-entity — never re-derive by hand.', 'Run /ba-audit-prd on the module — PRD-132 checks the entité.md ⇔ pagespec codedEntity parity this CLI reconciles.', ] if (report.totals.blocked > 0) { nextSteps.unshift( `BLOCKING — ${report.totals.blocked} **Code pattern** line(s) unusable (no mask / invalid format): ` + 'fix entité.md first; the seam CANNOT be scaffolded from a broken line and improvising it by hand is ' + 'exactly what DEV-API-034 errs on.', ) } if (report.totals.nearMisses > 0) { nextSteps.unshift( `BLOCKING — ${report.totals.nearMisses} Code pattern mention(s) that do NOT parse ` + '(table cell / wrong casing / unbolded bullet / prose): the chain derives NOTHING from them — ' + CODE_PATTERN_CANONICAL_FORM, ) } printEnvelope( executeEnvelope(COMMAND, { success: true, data: report.totals, report, warnings: report.warnings, nextSteps, }), ) process.exit(0) } main()