feat(ms-ai-architect): re-sync vendored design-system, source_commit now true [skip-docs]

DS-repo restored scripts/sync-design-system.mjs with an explicit source
allowlist and verified the command; ran their exact command (never one
reconstructed locally). MANIFEST.json was rewritten by the script itself,
never edited by hand.

source_commit now reads efaa3d0 (playground-design-system's main on the
public mirror), verified reachable via git ls-remote against the public
remote and git cat-file -t locally — in contrast to the previous c1b7bad,
which does not exist as a git object in that repo at all. 26/27 files
byte-identical to the source; only their README.md content differs.

Replaced the three stale prose points in README.md and docs/playground.md
that described the missing command and the untrustworthy source_commit.

Suite: 1070/1070 (tracked kb-update + kb-eval test files).

[skip-docs]: README.md and docs/playground.md are the doc update this task
required (vendoring section accuracy). CLAUDE.md's command/agent/skill
surface is unaffected — no new commands, agents, or skills.
This commit is contained in:
Kjell Tore Guttormsen 2026-08-27 10:40:57 +02:00
commit f1f27a4343
4 changed files with 181 additions and 50 deletions

View file

@ -472,8 +472,8 @@ The playground loads CSS from `playground/vendor/playground-design-system/` —
- **Drift detection:** `MANIFEST.json` records SHA-256 per file, so local modification of a vendored file is detectable.
- **Generated header:** Each vendored CSS file is prefixed with `/* Code generated by sync-design-system.mjs; DO NOT EDIT. */`. Never edit the vendored files directly.
- **⚠️ No re-sync command yet — restoration pending upstream.** Vendoring **stands** as the recommended consumer model (design-system repository's decision, 2026-08-27; there is no replacement — a submodule or npm package would break its no-build / no-bundler / `file://` constraints). The sync script is **not lost**: it survives complete in the catalog repository's pre-migration history — `git -C <marketplace>/catalog show e84dffd^:scripts/sync-design-system.mjs` (225 lines, no npm dependencies, and it already accepts `--source`, `--target` and `--check`). Restoring it is the design-system repository's call, and they are deliberately holding it back until the source-scoping question is settled: their repo root holds the design-system **plus** repo apparatus, so a naive `--source .` would vendor `STATE.md`, `LICENSE` and `docs/` into consumers. They will publish a command once it is verified. Do not reconstruct one locally.
- **🔴 Do not trust `source_commit` in `MANIFEST.json`.** It reads `c1b7bad`, which is not merely unreachable from this repo — it is **wrong**. The vendored tree contains `components-tier4-project-view.css`, and that file did not exist in `c1b7bad` (known-positive control: `components-tier3.css` in the same commit resolves fine). The sync labelled the copy with the marketplace HEAD while copying an uncommitted working tree. Leave the field alone: rewriting the path while keeping the commit would turn an obviously stale pointer into a credible false one. A future re-sync writes a true manifest.
- **Re-sync command exists and is verified (2026-08-27).** The design-system repository restored `scripts/sync-design-system.mjs` with an explicit source allowlist (`DELIVERED_FILES`), since its repo root holds the design system *plus* repo apparatus (`STATE.md`, `.git/`, `docs/`, etc.) that a naive walk would vendor too — pinned by `tests/sync-source-boundary.test.mjs` in that repo. Command, run from a checkout of `playground-design-system` alongside this repo: `node scripts/sync-design-system.mjs ms-ai-architect --target ../ms-ai-architect` (add `--check` for a read-only integrity check). This session ran it; `MANIFEST.json` was rewritten by the script itself, never edited by hand. Full record: `playground-design-system`'s `docs/vendoring-and-re-sync.md`.
- **`source_commit` in `MANIFEST.json` is now true and reachable.** It reads `efaa3d0e79f1b06976735831e5bf8cab42f7e6a9``playground-design-system`'s `main` on its public mirror, confirmed with `git ls-remote` against `git.fromaitochitta.com/open/playground-design-system.git` (not just a local ref). Unlike the previous `c1b7bad`, which does not exist as a git object in that repo at all (`git cat-file -t c1b7bad…``fatal: could not get object info`, confirmed here with a known-positive control on `efaa3d0` resolving to `commit`). The field comes from `git rev-parse HEAD` in the source checkout at sync time — the design-system repository documented that running a re-sync *before* its own commit reaches the public mirror reproduces the same false-pointer defect, so a future re-sync should confirm `git -C playground-design-system rev-parse HEAD` matches `origin/main` first.
- **What you can check today, without the script:** re-hash the vendored tree against `MANIFEST.json`. Measured 2026-08-27 — **27/27 match**, so nothing here has been edited locally, and **26 of 27 files are byte-identical** with the design-system repository's current content, 3.5 months after the last sync. The sole difference is that repository's own `README.md`, which documents the system rather than being part of it. When comparing by hand, discount the first line of each vendored CSS file: the generated header is added by the sync, so a raw `diff` reports all nine CSS files as differing when none of them do.
---

View file

@ -52,14 +52,14 @@ v1.14.0 (DS v0.4.0): root-cause fix for tre DS-bugs som tidligere ble symptomati
Alle PARALLEL-CSS-navngrupper migrert til DS-konvensjon. `renderPageShell` + `renderKeyStatsGrid` refaktorert til DS markup. Severity-coded card-borders på rapport-cards, app-header-restruktur, `.stack-lg` body spacing på home/project/catalog, AI Act-pyramide bredde-fix, eyebrow-label på home-projects.
Ved videre hoisting: dette er endringer i et delt asset og krever drift-deteksjons-håndtering per `MANIFEST.json`. ⚠️ Det finnes fortsatt ingen re-sync-kommando å kjøre — se «Vendored design-system» under for hva som er avklart og hva som gjenstår oppstrøms.
Ved videre hoisting: dette er endringer i et delt asset og krever drift-deteksjons-håndtering per `MANIFEST.json`. En re-sync-kommando finnes nå og er verifisert (2026-08-27) — se «Vendored design-system» under for kommando og verifiseringslogg.
## Vendored design-system
Playground laster CSS fra `playground/vendor/playground-design-system/` — en vendored kopi av det delte playground-designsystemet (27 filer + `MANIFEST.json`). Dette holder pluginen **standalone**: HTML-filen kan åpnes fra `file://` uavhengig av marketplace-roten.
- **⚠️ Ingen re-sync-kommando ennå — restaurering pågår oppstrøms.** Vendoring **består** som anbefalt konsumentmodell (designsystem-repoets beslutning 2026-08-27; ingen avløsning — en submodul eller npm-pakke ville brutt deres krav om ingen build, ingen bundler, `file://`). Skriptet er **ikke tapt**: det ligger komplett i catalog-repoets pre-migrasjonshistorikk — `git -C <marketplace>/catalog show e84dffd^:scripts/sync-design-system.mjs` (225 linjer, ingen npm-avhengigheter, og det tar allerede `--source`, `--target` og `--check`). Restaureringen er designsystem-repoets avgjørelse, og de holder den bevisst tilbake til kildeavgrensningen er valgt: deres repo-rot inneholder designsystemet **pluss** repo-apparatet, så en naiv `--source .` ville vendoret `STATE.md`, `LICENSE` og `docs/` inn hit. De publiserer en kommando når den er verifisert. **Ikke rekonstruer en lokalt.**
- **🔴 Ikke stol på `source_commit` i `MANIFEST.json`.** Feltet sier `c1b7bad`, som ikke bare er unåbar herfra — den er **usann**. Det vendorede treet inneholder `components-tier4-project-view.css`, og den fila fantes ikke i `c1b7bad` (kjent-positiv kontroll: `components-tier3.css` i samme commit slår opp fint). Syncen etikettmerket kopien med marketplace-HEAD mens den kopierte et ukommittert arbeidstre. **La feltet ligge:** å skrive om stien og beholde commiten ville gjort en åpenbart stale peker til en troverdig feil peker. En framtidig re-sync skriver et sant manifest.
- **Re-sync-kommando finnes og er verifisert (2026-08-27).** Designsystem-repoet har restaurert `scripts/sync-design-system.mjs` med en eksplisitt kilde-allowlist (`DELIVERED_FILES`), fordi deres repo-rot inneholder designsystemet **pluss** repo-apparatet (`STATE.md`, `.git/`, `docs/` m.m.) som en naiv gjennomgang ville vendoret med — pinnet av `tests/sync-source-boundary.test.mjs` i deres repo. Kommando, kjørt fra en sjekket-ut `playground-design-system` ved siden av dette repoet: `node scripts/sync-design-system.mjs ms-ai-architect --target ../ms-ai-architect` (legg til `--check` for en skrivefri integritetssjekk). Denne økten kjørte den; `MANIFEST.json` ble skrevet av skriptet selv, aldri redigert for hånd. Full protokoll: `playground-design-system`s `docs/vendoring-and-re-sync.md`.
- **`source_commit` i `MANIFEST.json` er nå sann og nåbar.** Feltet sier `efaa3d0e79f1b06976735831e5bf8cab42f7e6a9``playground-design-system`s `main` på det offentlige speilet, bekreftet med `git ls-remote` mot `git.fromaitochitta.com/open/playground-design-system.git` (ikke bare en lokal ref). Ulikt forrige `c1b7bad`, som ikke finnes som git-objekt i det repoet i det hele tatt (`git cat-file -t c1b7bad…``fatal: could not get object info`, bekreftet her med en kjent-positiv kontroll der `efaa3d0` slår opp som `commit`). Feltet kommer fra `git rev-parse HEAD` i kilde-sjekkouten ved synk-tidspunktet — designsystem-repoet har dokumentert at en re-sync kjørt **før** deres egen commit når det offentlige speilet, reproduserer nøyaktig samme falske-peker-defekt, så en framtidig re-sync bør bekrefte at `git -C playground-design-system rev-parse HEAD` matcher `origin/main` først.
- **Hva du kan sjekke i dag, uten skriptet:** re-hash det vendorede treet mot `MANIFEST.json`. Målt 2026-08-27 — **27/27 matcher**, så ingenting her er redigert lokalt, og **26 av 27 filer er byte-identiske** med designsystem-repoets nåværende innhold, 3,5 måned etter siste sync. Eneste avvik er deres egen `README.md`, som beskriver systemet framfor å være en del av det. Ved manuell sammenligning: se bort fra første linje i hver vendored CSS-fil — generated-headeren legges på av syncen, så en rå `diff` melder alle ni CSS-filer som avvikende når ingen av dem er det.
- **Drift-deteksjon:** `MANIFEST.json` lagrer SHA-256 per fil, så lokal endring av en vendored fil er detekterbar.
- **Lastes i HTML:** `<link>`-tags til `fonts.css`, `tokens.css`, `base.css`, `components.css`, `components-tier2.css`, `components-tier3.css`, `components-tier3-supplement.css` (i den rekkefølgen).

View file

@ -1,13 +1,13 @@
{
"generated_by": "scripts/sync-design-system.mjs",
"do_not_edit": true,
"source": "shared/playground-design-system/",
"source_commit": "c1b7bad3899c5cfe9ff90663003609b018aa79a0",
"sync_date": "2026-05-15T14:11:07.444Z",
"source": "playground-design-system",
"source_commit": "efaa3d0e79f1b06976735831e5bf8cab42f7e6a9",
"sync_date": "2026-08-27T08:37:47.101Z",
"file_count": 27,
"files": {
"CHANGELOG.md": "b5018b46cd0830334109e915d23b5554c060412c2b7e132f97f2933e5dd5d79c",
"README.md": "83de0e29b207c979b7b2a3327b7a4ec0c2e1b4d3705ee2677f26c28c3a3ee643",
"README.md": "8d8e86251f0c5a5d2f29e91d3b5a1fd2b40d7a79e4791ade237c10112ce9ce3c",
"base.css": "df0db874473412eb771b7355b589f7478042987756898f0921584286bd5ba70a",
"components-tier2.css": "c2cb7e9d76d6af28d50db654030413777feb2f2f2b93213e598de8b686b14523",
"components-tier3-supplement.css": "51fab10377d80029d6552613069d46fd14ce66af77fe6705b1c6bdf5c9e6481e",

View file

@ -1,8 +1,37 @@
# Playground Design System
# playground-design-system
A shared design system for plugin Playgrounds — visual self-service UIs that complement terminal slash-commands. Built for Norwegian public sector with WCAG 2.1 AA compliance, Aksel/Digdir-aligned aesthetics, and self-contained HTML deployment.
Vendored, framework-free CSS design system for plugin playgrounds — design tokens, four component tiers, self-hosted fonts, and file:// operation with no build step.
**Version:** 0.1 (Phase 1 — 2026-05-02)
Playgrounds are the visual self-service UIs that complement a plugin's terminal slash-commands. This system gives them one shared visual language: Aksel/Digdir-aligned aesthetics for Norwegian public-sector users, WCAG 2.1 AA contrast and focus handling, and pages that open straight from disk with no server.
**Version:** 0.6.0 — see [CHANGELOG.md](CHANGELOG.md).
## Table of Contents
- [Non-goals](#non-goals)
- [Provenance](#provenance)
- [Directory layout](#directory-layout)
- [Quick start](#quick-start)
- [Vendoring and re-sync](#vendoring-and-re-sync)
- [Design principles](#design-principles)
- [Token system](#token-system)
- [Component reference](#component-reference)
- [Schemas](#schemas)
- [Theming](#theming)
- [Print mode](#print-mode)
- [Known limitations](#known-limitations)
- [Self-hosted fonts](#self-hosted-fonts)
- [Versioning](#versioning)
- [License](#license)
- [Contributing](#contributing)
## Non-goals
- **Not a JavaScript component library.** The system is CSS-only. Interactivity (tab state, sidepanel toggling, live-meter updates) is wired by each Playground in vanilla JS.
- **Not a general-purpose web UI kit.** Scope is the Playgrounds in this marketplace; Aksel/Digdir conventions and domain visuals (NS 5814 matrices, EU AI Act tiers) are baked in rather than configurable.
- **No build step, bundler or npm package.** Files are vendored and linked with plain `<link>` tags. Nothing is compiled, and nothing is published to a package registry.
- **No icon set.** Iconography is left to each Playground so the shared system stays small.
- **Not open to pull requests.** Solo project — see [Contributing](#contributing).
## Provenance
@ -13,35 +42,38 @@ Integration into the marketplace (file organization, path normalization, README
## Directory layout
```
shared/
├── playground-design-system/ # The design system (this directory)
│ ├── README.md # This file
│ ├── tokens.css # CSS custom properties (Aksel/Digdir-aligned)
│ ├── base.css # Reset, typography, primitives, focus, print
│ ├── components.css # Tier 1: radar, matrix, findings-browser, critique-card, wizard, live-meter
│ ├── components-tier2.css # Tier 2: decision-tree, traffic-lights, diff-review, treemap, distribution, command-pipeline, pyramide, pipeline-cockpit, verdict-pill+risk-meter, codepoint-reveal, small-multiples, OWASP badges
│ ├── components-tier3.css # Tier 3 wave 1: pair-before-after, AI Act timeline, 3-track entry, FRIA rights-matrix, capability-matrix, parallel-agent-status, ErrorSummary, GuidePanel
│ ├── components-tier3-supplement.css # Tier 3 wave 2 (12): toxic-flow, fleet-overview, kanban Keep/Review/Remove, maturity-ladder, classify-and-transform, cycle-ribbon, persistent-antipattern, suppressed-signals, ExpansionCard, ReadMore, FormProgress, Aspirational-vs-Committed
│ ├── fonts.css # @font-face declarations for self-hosted fonts
│ ├── fonts/ # Self-hosted woff2 + license attribution
│ │ ├── Inter-{Regular,Medium,SemiBold,Bold}.woff2
│ │ ├── JetBrainsMono-{Regular,Medium,SemiBold}.woff2
│ │ ├── SourceSerif4-{Regular,Semibold}.woff2
│ │ └── LICENSES.md # All three are SIL OFL 1.1
│ ├── print.css # A4 print stylesheet with B/W severity patterns
│ └── schemas/ # Cross-plugin JSON schemas
│ ├── 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
└── playground-examples/ # Showcase + reference scenarios
├── index.html # System showcase (browse all components)
├── ros-lier-kommune.html # Scenario A — ms-ai-architect ROS report
├── okr-baerum.html # Scenario B — OKR live writer
├── security-direktorat.html # Scenario C — llm-security findings review
├── templates.html # Skeleton + print-template demos
├── tier3-preview.html # Tier 3 wave 1 visual preview
├── components/ # Tier 3 wave 2 — 12 isolated demo pages
playground-design-system/ # This repo
├── README.md # This file
├── tokens.css # CSS custom properties (Aksel/Digdir-aligned)
├── base.css # Reset, typography, primitives, focus, print
├── components.css # Tier 1: radar, matrix, findings-browser, critique-card, wizard, live-meter
├── components-tier2.css # Tier 2: decision-tree, traffic-lights, diff-review, treemap, distribution, command-pipeline, pyramide, pipeline-cockpit, verdict-pill+risk-meter, codepoint-reveal, small-multiples, OWASP badges
├── components-tier3.css # Tier 3 wave 1: pair-before-after, AI Act timeline, 3-track entry, FRIA rights-matrix, capability-matrix, parallel-agent-status, ErrorSummary, GuidePanel
├── components-tier3-supplement.css # Tier 3 wave 2 (12): toxic-flow, fleet-overview, kanban Keep/Review/Remove, maturity-ladder, classify-and-transform, cycle-ribbon, persistent-antipattern, suppressed-signals, ExpansionCard, ReadMore, FormProgress, Aspirational-vs-Committed
├── components-tier4-project-view.css # Tier 4: project-view arketype
├── fonts.css # @font-face declarations for self-hosted fonts
├── fonts/ # Self-hosted woff2 + license attribution
│ ├── Inter-{Regular,Medium,SemiBold,Bold}.woff2
│ ├── JetBrainsMono-{Regular,Medium,SemiBold}.woff2
│ ├── SourceSerif4-{Regular,Semibold}.woff2
│ └── LICENSES.md # All three are SIL OFL 1.1
├── print.css # A4 print stylesheet with B/W severity patterns
├── schemas/ # Cross-plugin JSON schemas
│ ├── 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
├── okr-baerum.html # Scenario B — OKR live writer
├── security-direktorat.html # Scenario C — llm-security findings review
├── templates.html # Skeleton + print-template demos
├── tier3-preview.html # Tier 3 wave 1 visual preview
├── components/ # Tier 3 wave 2 — 12 isolated demo pages
│ ├── sankey-toxic-flow.html
│ ├── fleet-overview.html
│ ├── kanban.html
@ -54,10 +86,14 @@ shared/
│ ├── read-more.html
│ ├── form-progress.html
│ └── aspirational-committed.html
├── ros-app.js # Scenario A interactivity
└── ros-data.js # Scenario A mock data
├── ros-app.js # Scenario A interactivity
└── ros-data.js # Scenario A mock data
```
Consumers vendor this repo (its CSS/fonts/schemas, not `playground-examples/`) into their own
Playground at `<plugin>/playground/vendor/playground-design-system/` — copied in, not a git
submodule or shared symlink. See [Quick start](#quick-start).
## Quick start
To use the design system from a plugin's Playground:
@ -67,16 +103,41 @@ To use the design system from a plugin's Playground:
<html lang="nb" data-theme="light">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="../../shared/playground-design-system/tokens.css">
<link rel="stylesheet" href="../../shared/playground-design-system/base.css">
<link rel="stylesheet" href="../../shared/playground-design-system/components.css">
<link rel="stylesheet" href="../../shared/playground-design-system/components-tier2.css">
<!-- Theme bootstrap. Must run before the stylesheets parse to avoid a
flash-of-wrong-theme (FOUC). Priority order:
1) saved choice (localStorage '<plugin-name>-theme')
2) OS preference via matchMedia('(prefers-color-scheme: dark)')
3) the HTML attribute default ('light' above)
Sets both data-theme + colorScheme for native form controls and scrollbars.
Wrapped in try/catch — file:// + private mode can block localStorage. -->
<script>
(function () {
var theme = null;
try {
var saved = localStorage.getItem('<plugin-name>-theme');
if (saved === 'light' || saved === 'dark') theme = saved;
} catch (e) { /* localStorage unavailable */ }
if (!theme && window.matchMedia) {
theme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
}
if (!theme) theme = document.documentElement.getAttribute('data-theme') || 'light';
document.documentElement.setAttribute('data-theme', theme);
document.documentElement.style.colorScheme = theme;
})();
</script>
<link rel="stylesheet" href="vendor/playground-design-system/tokens.css">
<link rel="stylesheet" href="vendor/playground-design-system/base.css">
<link rel="stylesheet" href="vendor/playground-design-system/components.css">
<link rel="stylesheet" href="vendor/playground-design-system/components-tier2.css">
<!-- Optional: include components-tier3.css for Tier 3 wave 1 components -->
<!-- Optional: include components-tier3-supplement.css for Tier 3 wave 2 (12 additional components) -->
<!-- Optional: include components-tier4-project-view.css for the Tier 4 project-view arketype -->
<!-- Optional: only include print.css if scenario produces a printable A4 report -->
<link rel="stylesheet" href="../../shared/playground-design-system/print.css">
<link rel="stylesheet" href="vendor/playground-design-system/print.css">
<!-- Self-hosted fonts (no external requests) -->
<link rel="stylesheet" href="../../shared/playground-design-system/fonts.css">
<link rel="stylesheet" href="vendor/playground-design-system/fonts.css">
</head>
<body>
<header class="app-header">
@ -93,7 +154,77 @@ To use the design system from a plugin's Playground:
</html>
```
The relative path `../../shared/playground-design-system/` assumes the plugin's Playground lives at `plugins/{plugin-name}/playground/index.html`. Adjust the prefix to match your plugin's structure.
The relative path `vendor/playground-design-system/` assumes the plugin's Playground HTML lives at
`<plugin-name>/playground/<plugin-name>-playground.html`, with the design system vendored (copied
in) at `<plugin-name>/playground/vendor/playground-design-system/`. Adjust the prefix to match your
plugin's structure.
The theme-bootstrap script is not part of the vendored CSS — copy it into each Playground's own
`<head>`, replacing `<plugin-name>-theme` with a key unique to that plugin (both `ms-ai-architect`
and `llm-security` follow this pattern today). The `data-theme-toggle` button's own click handler
(written per Playground, not vendored) is what writes that key via `localStorage.setItem` when the
reader switches theme — the bootstrap script only reads it back on the next load. Without the
bootstrap script, the page renders in the HTML attribute's default theme for one frame before
JavaScript applies the saved/OS preference — the FOUC it exists to prevent.
## Vendoring and re-sync
Vendoring remains the recommended consumer model. Measured 2026-08-27 across both consumers
(`ms-ai-architect`, `llm-security`): 26 of 27 vendored files are byte-identical to this repo's
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.
### Re-sync
From a checkout of this repo, with the consumer repo checked out alongside it:
```sh
node scripts/sync-design-system.mjs <consumer-name> --target ../<consumer-repo>
```
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