feat(sync): restore sync-design-system.mjs with an explicit source boundary

The script that produced the existing vendored copies was deleted with the
monorepo layout in 2026-06 and recovered from catalog's history
(e84dffd^:scripts/sync-design-system.mjs). It could not be restored unchanged:
it walks its source directory and copies everything, and this repo's root is no
longer a directory holding only the design system. Run verbatim it vendored 109
files instead of 27, STATE.md and the whole of .git/ among them - and STATE.md
is gitignored precisely because this repo's remote is public.

The boundary is an explicit allowlist (DELIVERED_FILES) rather than a dist/
directory: one definition, read directly by the tests, with no copy step to go
stale. The allowlist's own failure mode - a new design-system file forgotten
from the list ships nothing, and --check stays green because it hashes a
consumer's tree against that consumer's own MANIFEST - is closed by scanning
the source for unlisted root-level *.css, fonts/* and schemas/* and refusing to
run.

tests/sync-source-boundary.test.mjs pins both directions. It was red on the
verbatim script for the right reason (STATE.md present in the target, with
tokens.css as the known-positive control) before the boundary was written.

--target is the consumer's repo root; the script appends
playground/vendor/playground-design-system/ itself. --check verified read-only
against both consumers: MANIFEST OK (27 files) for ms-ai-architect and
llm-security alike. No re-sync was run, so both MANIFEST.json files are
untouched and the stale source_commit is still theirs to inherit at the first
real re-sync.

README and docs/vendoring-and-re-sync.md now publish the command, and warn that
a plain diff/cmp against this repo reports all nine stylesheets as drifted
because the sync injects a generated-header line the source does not have -
17/27 raw, 26/27 with line 1 stripped. Found by ms-ai-architect, re-measured
here.
This commit is contained in:
Kjell Tore Guttormsen 2026-08-27 00:45:58 +02:00
commit 7448cec304
4 changed files with 601 additions and 51 deletions

View file

@ -62,6 +62,10 @@ playground-design-system/ # This repo
│ ├── finding.schema.json # Used by llm-security, config-audit, ultraplan-review, ms-ai-review
│ ├── okr-set.schema.json # Used by OKR plugin
│ └── ros-threat.schema.json # Used by ms-ai-architect ROS workflow
├── scripts/
│ └── sync-design-system.mjs # Vendors the delivered files into a consumer (see Vendoring and re-sync)
├── tests/
│ └── sync-source-boundary.test.mjs # Pins what the sync may and may not copy
└── playground-examples/ # Showcase + reference scenarios (this repo's own demos)
├── index.html # System showcase (browse all components)
├── ros-lier-kommune.html # Scenario A — ms-ai-architect ROS report
@ -170,26 +174,57 @@ Vendoring remains the recommended consumer model. Measured 2026-08-27 across bot
current content three and a half months after their last sync, and neither copy has been edited
locally. The only file that differs is this README.
**There is no re-sync command today.** The `sync-design-system.mjs` script that produced the
existing vendored copies was deleted with the monorepo layout in 2026-06. It is recoverable in
full from the `catalog` repo's history and belongs in this repo once restored, but restoring it
unchanged would copy this repo's root wholesale — including files that are not part of the
delivered system. That boundary is an open decision, so no command is published here rather than
one that would be wrong.
### Re-sync
Until then, a consumer can still check its own copy without any script:
From a checkout of this repo, with the consumer repo checked out alongside it:
- **Integrity** — re-hash the vendored files against the SHA-256 values in that copy's own
`MANIFEST.json`. Answers "has anyone edited the vendored files locally?"
- **Drift** — hash each vendored file, stripping the
`/* Code generated by sync-design-system.mjs; DO NOT EDIT. */` header line the sync injects into
every `.css`, and compare against the same filename at this repo's root.
```sh
node scripts/sync-design-system.mjs <consumer-name> --target ../<consumer-repo>
```
`MANIFEST.json`'s `source` and `source_commit` fields in the existing copies point at the old
monorepo layout. Leave them alone for now — the recorded `source_commit` is not just unreachable
but inaccurate, and rewriting only the path would make a false pointer look plausible. See
[docs/vendoring-and-re-sync.md](docs/vendoring-and-re-sync.md) for the full decision, the
measurements behind it, and the recovery command.
That rewrites `<consumer-repo>/playground/vendor/playground-design-system/` — the 27 delivered
files plus a regenerated `MANIFEST.json`. `--target` is the consumer's **repo root**; the script
appends `playground/vendor/playground-design-system/` itself. `--source <dir>` selects a
different checkout of this repo to read from (default: the one the script lives in). Node 16.7+,
no npm dependencies, no install step.
The script refuses to overwrite a vendored file that was edited locally since the last sync;
`--force` overrides. It copies an explicit allowlist (`DELIVERED_FILES` in the script), not the
repo root — `STATE.md`, `.git/`, `docs/`, `playground-examples/`, `LICENSE` and `SECURITY.md`
stay here. `tests/sync-source-boundary.test.mjs` pins that boundary in both directions: nothing
outside the allowlist reaches a consumer, and a new design-system file that is missing *from* the
allowlist fails the sync loudly instead of silently not shipping.
```sh
node --test tests/sync-source-boundary.test.mjs
```
### Checking a vendored copy
Integrity, from the consumer side, needs no source checkout:
```sh
node scripts/sync-design-system.mjs <consumer-name> --target ../<consumer-repo> --check
```
It re-hashes the vendored tree against that copy's own `MANIFEST.json`, then prints
`MANIFEST OK (27 files, source_commit ...)` and exits 0, or lists the differing files and exits 2.
It reads only — `--check` writes nothing to the consumer.
**Without the script, do not compare a vendored copy to this repo with a plain `diff` or `cmp`.**
The sync injects `/* Code generated by sync-design-system.mjs; DO NOT EDIT. */` as line 1 of every
`.css`, and the source has no such line, so a raw comparison reports **all nine stylesheets as
drifted** when none of them is. Measured 2026-08-27 against `ms-ai-architect`: raw `cmp` matches
17 of 27 files; strip line 1 from the vendored `.css` files and it is 26 of 27, the only real
difference being this README. `--check` is immune, because it hashes the vendored tree against
`MANIFEST.json` — which was built after the header was injected — and never against the source.
`MANIFEST.json`'s `source` and `source_commit` fields in the existing copies still describe the
old monorepo layout, and the recorded commit is not merely unreachable but inaccurate. Leave them
alone: the next real re-sync rewrites both truthfully. Do not repair them by hand — rewriting only
the path would turn an obviously stale pointer into a plausible false one. See
[docs/vendoring-and-re-sync.md](docs/vendoring-and-re-sync.md) for the full decision and the
measurements behind it.
## Design principles