From a52edf1d0f64d7e3bde7740d3598557f3068c585 Mon Sep 17 00:00:00 2001 From: Ryan Dombrowski Date: Mon, 10 Aug 2026 15:08:00 -0400 Subject: [PATCH] docs: fix a documented command that fails, the missing strict-surface exit code, and two stale descriptions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Found in an ecosystem-wide documentation audit; each item verified by running the code rather than reading it. - docs/PROFILES.md documented `dspack-emit --in … --profile … --out out`, which exits 2: `--a2ui-version` is REQUIRED for the a2ui target (the `?? "0.9.1"` default is unreachable). Corrected and re-run: the fixed command emits and passes A1/A2/A3. - README's exit-code list omitted `2` (usage / profile-load) and `5` (`--strict-surface`) — and `--strict-surface` itself appeared nowhere in the README despite shipping in 0.6.0. - docs/PROFILES.md described `scaffoldProfile` as deriving "subFlatten from declared acceptsChildren". That behavior was deliberately DELETED: it invented the judgment it should surface (wrong for repeated items like radio-group-item). The scaffold emits v2 and surfaces subs under `x-scaffold.unresolved`. - docs/CONTRACT-PIN.md listed eight unchecked blockers; six shipped in 0.6.0 and one landed in dspack-studio. Ticked with pointers to the implementing code, left the single genuine blocker open (the profile-parity invariant), and noted that the measured-gap table above it predates the release. Co-Authored-By: Claude Opus 4.8 --- README.md | 8 +++++--- docs/CONTRACT-PIN.md | 23 +++++++++++++++-------- docs/PROFILES.md | 11 +++++++---- 3 files changed, 27 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index a0aaf14..23d8fff 100644 --- a/README.md +++ b/README.md @@ -166,9 +166,11 @@ npm run transform -- --in input/shadcn-ui.dspack.json --a2ui-version 0.9.1 --out emits `out/delete-account.surface.json` (createSurface with dspack-token theme + updateComponents) and instance-validates it against the freshly generated catalog -(gate A3). Exit codes: `1` catalog gates failed, `3` strict-coverage, `4` the -surface could not be emitted (unknown component / structure the profile cannot -project). The projection is data in the profile (`surfacePlan` directives in +(gate A3). Exit codes: `1` catalog gates failed, `2` usage or profile-load error, +`3` strict-coverage, `4` the surface could not be emitted (unknown component / +structure the profile cannot project), `5` `--strict-surface` (a surface emitted, +but with fidelity losses you asked to treat as failures — bare, or scoped as +`--strict-surface=lossy,synthesis-defaults`). The projection is data in the profile (`surfacePlan` directives in `src/transform/profiles.ts`); the engine has no component-specific code. **Honest scope:** compound composition flattens per the documented casualties in diff --git a/docs/CONTRACT-PIN.md b/docs/CONTRACT-PIN.md index c291602..dc2aa62 100644 --- a/docs/CONTRACT-PIN.md +++ b/docs/CONTRACT-PIN.md @@ -44,14 +44,21 @@ Closing the gap by declaring 24 new casualties was considered and rejected: thos Replace the pin with the production contract **only after all of the following are implemented and measured**: -- [ ] profile v2 schema + explicit `profileVersion` dispatch -- [ ] v1 directive desugaring into the internal Identity/Route/Collect model -- [ ] load-time validation of selectors and destinations -- [ ] `EmitSurfaceResult.fidelity` + `--strict-surface` -- [ ] sub-component coverage derived and enforced from the internal model -- [ ] the six shadcn renderer drifts repaired, with props-level parity tests -- [ ] `functions` support on the profile/catalog path -- [ ] `profile-parity.test.ts` invariant 1 restated as *every worked example either emits, or refuses for a declared-casualty reason the contract itself acknowledges* +- [x] profile v2 schema + explicit `profileVersion` dispatch — `src/transform/profile-schema-v2.ts`, `profile-load.ts` +- [x] v1 directive desugaring into the internal Identity/Route/Collect model — `src/transform/desugar.ts`, byte-neutrality gated by `src/byte-neutral.test.ts` +- [x] load-time validation of selectors and destinations — `src/transform/parse-v2.ts` +- [x] `EmitSurfaceResult.fidelity` + `--strict-surface` — `src/targets/a2ui/surface.ts`, `src/cli.ts` (exit 5) +- [x] sub-component coverage derived and enforced from the internal model +- [x] the six shadcn renderer drifts repaired, with props-level parity tests — landed in dspack-studio (`packages/shadcn-renderers`) +- [x] `functions` support on the profile/catalog path — `src/transform/profiles.ts`, `profile-load.ts` +- [ ] `profile-parity.test.ts` invariant 1 restated as *every worked example either emits, or refuses for a declared-casualty reason the contract itself acknowledges* — **the one remaining blocker** (`src/profile-parity.test.ts` still asserts every example emits) + +Everything above except the last line shipped in **0.6.0** (see +[RELEASE-0.6.0.md](../RELEASE-0.6.0.md)): T1 transparent identity + control +donation, T2/T3 collect with declared joins, T4 multi-slot compounds, and +layered dissolution. The measured-gap table earlier in this document predates +that release — as of 0.6.0 the production contract is 34 components and 11 of +14 worked examples emit. At that point: `node scripts/check-sync.mjs --write` after removing the `pin` block, regenerate the derived catalogs and json-render goldens, and commit them together. diff --git a/docs/PROFILES.md b/docs/PROFILES.md index 83ab81d..6191c24 100644 --- a/docs/PROFILES.md +++ b/docs/PROFILES.md @@ -29,11 +29,14 @@ const profile = loadProfile(JSON.parse(readFileSync("acme.profile.json", "utf8") // throws ProfileLoadError with pathed issues if the document is malformed ``` -From the CLI: `dspack-emit --in acme.dspack.json --profile acme.profile.json --out out`. +From the CLI: `dspack-emit --in acme.dspack.json --profile acme.profile.json --a2ui-version 0.9.1 --out out`. To start from zero, `scaffoldProfile(doc, { catalogIdBase })` derives a -mechanical 1:1 draft (verbatim prop projections, subFlatten from declared -`acceptsChildren`, no valueMaps, no casualties) plus `notes` listing every -judgment call left to you. +mechanical **v2** draft (verbatim prop projections, no valueMaps, no +casualties) plus `notes` listing every judgment call left to you. It +deliberately does not guess sub-component treatment: auto-classifying subs +from declared `acceptsChildren` was measured wrong for repeated items such as +`radio-group-item`, so every sub is surfaced under `x-scaffold.unresolved` as +an explicit decision rather than an invented one. The schema fails closed: unknown keys are refused everywhere, with one deliberate, dspack-conventional exception — `x-*` keys are accepted (and