diff --git a/CHANGELOG.md b/CHANGELOG.md
index aec4847..f9a7ff3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,9 @@
## Unreleased
+- Preserved no-config UI implementation contracts with the JudgmentKit package-default design-system source while validating malformed explicit `design_system_source` values as failures.
+- Retired public `/design-system` pages in favor of the canonical Surfaces contract without removing JudgmentKit's built-in package default.
+
## 0.5.0 - 2026-06-20
- Added `review_cognitive_dimensions_candidate` as a library and MCP tool for reviewing UI workflow or implementation candidates against activity mapping, evidence visibility, hidden dependencies, premature commitment, progressive evaluation, change cost, mental operations, role expressiveness, and disclosure discipline.
diff --git a/README.md b/README.md
index c46a012..dcc06a8 100644
--- a/README.md
+++ b/README.md
@@ -82,7 +82,7 @@ The canonical examples live beside it:
They cover setup/onboarding, an operational dashboard, and a high-stakes review/refund workflow. The renderer package is still deferred; these examples prove the contract and repair behavior before visual rendering.
-By default, `implementation_contract.design_system_source.mode` is `judgmentkit_default`: tokens, font roles, icon catalog policy, and component contracts come from JudgmentKit `/design-system/` exports. If a complete `design_system_adapter` is supplied to `create_ui_implementation_contract`, the mode becomes `external_design_system` and that adapter owns tokens, typography, icons, and renderer components. Incomplete external adapters fail instead of falling back to JudgmentKit defaults.
+By default, `implementation_contract.design_system_source.mode` is `judgmentkit_default`: tokens, font roles, icon catalog policy, and component contracts come from the JudgmentKit package default. Public `/design-system/` routes are retired and are not the source of truth for this default. If a complete `design_system_source` or `design_system_adapter` is supplied to `create_ui_implementation_contract`, the mode becomes `external_design_system` and that source owns tokens, typography, icons, and renderer components. Incomplete external sources or adapters fail instead of falling back to JudgmentKit defaults.
The JudgmentKit default source does not load a font CDN, runtime icon CDN, or external runtime icon package. Font guidance uses system stacks, and icon guidance points to the committed Lucide catalog exposed through `list_icon_catalog`, `search_icon_catalog`, and `get_icon_svg`.
diff --git a/api/design-system-retired.js b/api/design-system-retired.js
new file mode 100644
index 0000000..b761a3a
--- /dev/null
+++ b/api/design-system-retired.js
@@ -0,0 +1,47 @@
+const CANONICAL_SURFACES_DESIGN_SYSTEM_URL =
+ "https://surfaces.systems/design-system";
+const DESIGN_SYSTEM_MIGRATION_CODE = "judgmentkit_design_system_retired";
+
+function requestedPath(req) {
+ const queryPath = req.query?.requestedPath;
+
+ if (Array.isArray(queryPath)) {
+ return queryPath[0] ?? "/design-system";
+ }
+
+ if (typeof queryPath === "string" && queryPath.length > 0) {
+ return queryPath;
+ }
+
+ return req.url ?? "/design-system";
+}
+
+export default function handler(req, res) {
+ if (req.method !== "GET" && req.method !== "HEAD") {
+ res.statusCode = 405;
+ res.setHeader("Allow", "GET, HEAD");
+ res.end("Method not allowed.\n");
+ return;
+ }
+
+ const payload = {
+ code: DESIGN_SYSTEM_MIGRATION_CODE,
+ message:
+ "judgmentkit.ai/design-system is retired. Use the canonical Surfaces design-system contract.",
+ canonicalUrl: CANONICAL_SURFACES_DESIGN_SYSTEM_URL,
+ requestedPath: requestedPath(req),
+ };
+ const body = `${JSON.stringify(payload, null, 2)}\n`;
+
+ res.statusCode = 410;
+ res.setHeader("Content-Type", "application/json; charset=utf-8");
+ res.setHeader("Cache-Control", "public, max-age=300");
+ res.setHeader("Content-Length", Buffer.byteLength(body));
+
+ if (req.method === "HEAD") {
+ res.end();
+ return;
+ }
+
+ res.end(body);
+}
diff --git a/contracts/ai-ui-generation.activity-contract.json b/contracts/ai-ui-generation.activity-contract.json
index a0447e0..58b1135 100644
--- a/contracts/ai-ui-generation.activity-contract.json
+++ b/contracts/ai-ui-generation.activity-contract.json
@@ -1586,7 +1586,7 @@
"mode": "judgmentkit_default",
"name": "JudgmentKit",
"package": "judgmentkit",
- "definition_point": "implementation_contract",
+ "definition_point": "package_default",
"required_authorities": [
"tokens",
"fonts",
@@ -1596,13 +1596,13 @@
"fallback_policy": "fail_incomplete",
"provenance_required": true,
"source_exports": {
- "overview": "/design-system/",
- "manifest": "/design-system/manifest.json",
- "visual_token_adapter": "/design-system/visual-token-adapter.json",
- "component_contracts": "/design-system/component-contracts.json",
- "pattern_contracts": "/design-system/pattern-contracts.json",
- "accessibility_policy": "/design-system/accessibility-policy.json",
- "icon_catalog": "/design-system/icons/",
+ "overview": "package://judgmentkit/design-system/",
+ "manifest": "package://judgmentkit/design-system/manifest.json",
+ "visual_token_adapter": "package://judgmentkit/design-system/visual-token-adapter.json",
+ "component_contracts": "package://judgmentkit/design-system/component-contracts.json",
+ "pattern_contracts": "package://judgmentkit/design-system/pattern-contracts.json",
+ "accessibility_policy": "package://judgmentkit/design-system/accessibility-policy.json",
+ "icon_catalog": "package://judgmentkit/design-system/icons/",
"icon_tools": [
"list_icon_catalog",
"search_icon_catalog",
@@ -1658,9 +1658,9 @@
],
"component_contract_source": "implementation_contract.default_ai_native_design_system.component_contracts",
"provenance_rules": [
- "visual tokens, fonts, icons, and renderer components must come from this active design-system source",
+ "visual tokens, fonts, icons, and renderer components come from the JudgmentKit package default when no design system is supplied",
"local CSS may define layout and UI structure but must not become the source of visual tokens, typography, icon assets, or renderer components",
- "external design systems must be supplied as complete contract-time adapters; missing authorities do not fall back to JudgmentKit defaults"
+ "external design systems must be supplied as complete contract-time adapters or complete design-system sources; missing authorities do not fall back to JudgmentKit defaults"
]
},
"visual_token_adapter": {
diff --git a/contracts/judgmentkit-kernel.schema.json b/contracts/judgmentkit-kernel.schema.json
index ea893ba..52f5c78 100644
--- a/contracts/judgmentkit-kernel.schema.json
+++ b/contracts/judgmentkit-kernel.schema.json
@@ -334,19 +334,25 @@
"default_include_svg"
],
"properties": {
- "source": { "type": "string" },
- "library": { "type": "string" },
- "package": { "type": "string" },
- "version": { "type": "string" },
+ "source": { "type": "string", "minLength": 1 },
+ "library": { "type": "string", "minLength": 1 },
+ "package": { "type": "string", "minLength": 1 },
+ "version": { "type": "string", "minLength": 1 },
"icon_count": { "type": "number", "minimum": 1 },
- "license": { "type": "string" },
- "notice": { "type": "string" },
- "style_system": { "type": "string" },
+ "license": { "type": "string", "minLength": 1 },
+ "notice": { "type": "string", "minLength": 1 },
+ "style_system": { "type": "string", "minLength": 1 },
"style_attributes": {
"type": "object",
+ "minProperties": 1,
"additionalProperties": { "type": "string" }
},
- "mcp_tools": { "type": "array", "items": { "type": "string" } },
+ "mcp_tools": {
+ "type": "array",
+ "minItems": 1,
+ "uniqueItems": true,
+ "items": { "type": "string", "minLength": 1 }
+ },
"default_include_svg": { "type": "boolean" }
}
},
@@ -502,16 +508,18 @@
"provenance_rules"
],
"properties": {
- "id": { "type": "string" },
+ "id": { "type": "string", "minLength": 1 },
"mode": {
"type": "string",
"enum": ["judgmentkit_default", "external_design_system"]
},
- "name": { "type": "string" },
- "package": { "type": "string" },
- "definition_point": { "type": "string" },
+ "name": { "type": "string", "minLength": 1 },
+ "package": { "type": "string", "minLength": 1 },
+ "definition_point": { "type": "string", "minLength": 1 },
"required_authorities": {
"type": "array",
+ "minItems": 4,
+ "uniqueItems": true,
"items": {
"type": "string",
"enum": ["tokens", "fonts", "icons", "components"]
@@ -524,26 +532,36 @@
"provenance_required": { "type": "boolean" },
"source_exports": {
"type": "object",
+ "minProperties": 1,
"additionalProperties": {
"oneOf": [
- { "type": "string" },
- { "type": "array", "items": { "type": "string" } }
+ { "type": "string", "minLength": 1 },
+ {
+ "type": "array",
+ "minItems": 1,
+ "items": { "type": "string", "minLength": 1 }
+ }
]
}
},
"token_prefixes": {
"type": "array",
- "items": { "type": "string" }
+ "minItems": 1,
+ "uniqueItems": true,
+ "items": { "type": "string", "minLength": 1 }
},
"icon_catalog": { "$ref": "#/$defs/iconCatalog" },
"renderer_components": {
"type": "array",
- "items": { "type": "string" }
+ "minItems": 1,
+ "uniqueItems": true,
+ "items": { "type": "string", "minLength": 1 }
},
- "component_contract_source": { "type": "string" },
+ "component_contract_source": { "type": "string", "minLength": 1 },
"provenance_rules": {
"type": "array",
- "items": { "type": "string" }
+ "minItems": 1,
+ "items": { "type": "string", "minLength": 1 }
}
}
},
diff --git a/docs/agent-usage-contract.md b/docs/agent-usage-contract.md
index cafb4e2..3d43bff 100644
--- a/docs/agent-usage-contract.md
+++ b/docs/agent-usage-contract.md
@@ -10,7 +10,7 @@ Use JudgmentKit before UI generation, UI critique, implementation planning, or h
4. Call `recommend_surface_types` to classify the activity purpose before workflow or frontend implementation guidance.
5. If a model or agent proposes a UI workflow, call `review_ui_workflow_candidate` before treating it as acceptable.
6. Call `review_cognitive_dimensions_candidate` when a workflow or implementation candidate needs Cognitive Dimensions review for mapping, visibility, hidden dependencies, premature commitment, progressive evaluation, change cost, mental operations, or disclosure.
-7. Call `create_ui_implementation_contract`. Use the default JudgmentKit design-system source, or pass a complete `design_system_adapter` when an external design system should own tokens, typography, icons, and renderer components.
+7. Call `create_ui_implementation_contract`. Omit design-system fields to use the JudgmentKit package default, or pass a complete `design_system_source` or `design_system_adapter` when an external design system should own tokens, typography, icons, and renderer components.
8. Call `create_ui_generation_handoff` on the reviewed workflow with the implementation contract before generating UI. Pass the Cognitive Dimensions review when it should block handoff until ready.
9. Call `create_frontend_generation_context` when frontend implementation guidance needs a selected surface type, project frontend context, and verification expectations.
10. Call `create_frontend_implementation_skill_context` when the implementing agent needs a compiled frontend skill packet that is portable across MCP clients.
@@ -24,7 +24,7 @@ Use JudgmentKit before UI generation, UI critique, implementation planning, or h
- Treat `needs_source_context` as a prompt to gather source context or ask the packet's targeted questions.
- Treat surface type as activity-purpose guidance, not visual styling.
- Treat the implementation contract as the authority for allowed primitives, control semantics, states, static checks, browser QA, visual asset handling, and accessibility evidence.
-- Treat `implementation_contract.design_system_source` as the active authority for visual tokens, typography, icon assets, and renderer components. `judgmentkit_default` uses JudgmentKit `/design-system/` exports; `external_design_system` requires a complete adapter and has no implicit JudgmentKit fallback. `external_authority` is trace metadata unless paired with `design_system_adapter`.
+- Treat `implementation_contract.design_system_source` as the active authority for visual tokens, typography, icon assets, and renderer components. When no external source is supplied, JudgmentKit uses its package default. `external_design_system` requires a complete source or adapter and has no implicit JudgmentKit fallback. `external_authority` is trace metadata unless paired with `design_system_source` or `design_system_adapter`.
- Treat `visual_token_adapter` as the token/font/icon evidence envelope for the active design-system source. Asset guidance cannot replace activity fit, primitive coverage, state coverage, accessibility evidence, static checks, or browser QA.
- Keep implementation terms out of product UI unless the activity is setup, debugging, auditing, integration, or explicit source inspection.
- When a model proposes an activity model, call `review_activity_model_candidate` before trusting it.
@@ -53,7 +53,7 @@ Before handing off UI work, confirm:
- implementation terms contained in disclosure, evidence, or guardrails
- workflow topology, work units, surface set, primary actions, decision support, and handoff are named
- implementation contract names approved primitives and required states
-- token, font, icon, and renderer component guidance comes from `implementation_contract.design_system_source`, with no implied font CDN, remote icon package, or fallback from external systems to JudgmentKit defaults
+- token, font, icon, and renderer component guidance comes from `implementation_contract.design_system_source`, with no implied font CDN, remote icon package, or fallback from external systems to JudgmentKit default assets
- substantive visual requirements have an image-generation, premium 3D/rendering, or high-quality visualization path when present
- static checks, browser QA, core accessibility evidence, and any conditional visual-background contrast, non-text contrast, forced-colors, target-size, focus-not-obscured, no-keyboard-trap, reduced-motion, pause/stop/hide, form/error/status, media alternative, or semantic fallback evidence are specified when required
- review-packet terms are not copied into the product UI
diff --git a/docs/daily-agent-workflows.md b/docs/daily-agent-workflows.md
index 8cdb45f..5ed81da 100644
--- a/docs/daily-agent-workflows.md
+++ b/docs/daily-agent-workflows.md
@@ -224,7 +224,7 @@ review_cognitive_dimensions_candidate({ brief, candidate, activity_review, surfa
Use the returned `findings` and `repair_instructions` as diagnostic guidance. If a Cognitive Dimensions review is supplied to the handoff gate, it must be `ready_for_review`.
-Call `create_ui_implementation_contract` with the default JudgmentKit design-system source, or with a complete `design_system_adapter` when an external design system should own tokens, typography, icons, and renderer components. `external_authority` is trace metadata unless it is paired with a complete adapter. The implementation contract names approved primitives, required states, static checks, browser QA expectations, `design_system_source`, visual asset policy, and accessibility policy.
+Call `create_ui_implementation_contract`. Omit design-system fields to use the JudgmentKit package default, or pass a complete `design_system_source` or `design_system_adapter` when an external design system should own tokens, typography, icons, and renderer components. `external_authority` is trace metadata unless it is paired with a source or complete adapter. The implementation contract names approved primitives, required states, static checks, browser QA expectations, `design_system_source`, visual asset policy, and accessibility policy.
MCP handoff calls should pass this packet as `implementation_contract`.
@@ -241,6 +241,7 @@ Library equivalent:
```js
const workflowReview = reviewUiWorkflowCandidate(brief, workflowCandidate);
const implementationContract = createUiImplementationContract({
+ design_system_source: optionalCompleteExternalDesignSystemSource,
design_system_adapter: optionalCompleteExternalDesignSystemAdapter,
});
const handoff = createUiGenerationHandoff(workflowReview, {
@@ -276,7 +277,7 @@ create_frontend_implementation_skill_context({
The skill context compiles the local frontend implementation workflow into structured instructions, approved primitives, approved component families, active design-system policy, visual asset policy, accessibility policy, verification checklist, and disclosure guardrails. It requires a ready frontend context and does not expose raw `SKILL.md` contents. The legacy `design_system_adapter` argument is a compatibility path only; prefer passing the adapter to `create_ui_implementation_contract`.
-The JudgmentKit default source includes semantic token roles, system font stacks for body, heading, label, numeric, and diagnostic text, and a committed Lucide icon catalog exposed through `list_icon_catalog`, `search_icon_catalog`, and `get_icon_svg`. Normal implementation context returns only the catalog summary, policy, count, source/version, and tool names; it does not embed the full catalog. These defaults do not load a font CDN, ship font files, use a runtime icon CDN, or mix with an external design system unless the external adapter explicitly names those assets.
+JudgmentKit still exposes icon catalog tools for review and examples, and the package default remains the active design-system source when no external source is supplied. Normal implementation context returns only the active source metadata, catalog summary, policy, count, source/version, and tool names; it does not embed a full catalog or imply a fallback from external systems to JudgmentKit assets.
When a frontend spec calls for substantive visuals, the implementation path should use `imagegen`, premium Three.js/WebGL rendering, or D3-style data visualization. Deterministic CSS, SVG, and JavaScript remain appropriate for layout, exact text, UI chrome, icons, state indicators, simple diagrams, and accessible fallback structure.
diff --git a/docs/releases/v0.6.0.md b/docs/releases/v0.6.0.md
index cf1e17b..8841ba7 100644
--- a/docs/releases/v0.6.0.md
+++ b/docs/releases/v0.6.0.md
@@ -6,7 +6,7 @@ JudgmentKit 0.6.0 makes design-system provenance a contract authority for genera
## Improvements
-- Added `implementation_contract.design_system_source` with explicit `judgmentkit_default` and `external_design_system` modes.
+- Added `implementation_contract.design_system_source` with `judgmentkit_default` and `external_design_system` modes.
- Added complete external design-system adapter support for tokens, fonts, icons, and components.
- Added fail-fast validation for incomplete external design-system authority.
- Added a hard `design_system_provenance` implementation review gate.
diff --git a/docs/releases/v0.6.1.md b/docs/releases/v0.6.1.md
index df68939..a36503a 100644
--- a/docs/releases/v0.6.1.md
+++ b/docs/releases/v0.6.1.md
@@ -7,7 +7,7 @@ JudgmentKit 0.6.1 is the public release for contract-first design-system authori
## Improvements
- Carries the 0.6 design-system authority contract into the public MCP metadata and examples.
-- Normalizes committed model UI capture metadata to the new `judgmentkit_default` and `external_design_system` source modes.
+- Normalizes committed model UI capture metadata to the `judgmentkit_default` package source mode and `external_design_system` source mode.
- Keeps public model UI manifests, captures, and generated static routes aligned for release verification.
## Included from 0.6.0
diff --git a/evals/run-mcp-pilot-evals.mjs b/evals/run-mcp-pilot-evals.mjs
index 3099f66..85f7f42 100644
--- a/evals/run-mcp-pilot-evals.mjs
+++ b/evals/run-mcp-pilot-evals.mjs
@@ -1367,7 +1367,9 @@ export async function buildMcpContextForCase(testCase, mcpRuntime) {
toolCalls,
mcpRuntime,
"create_ui_implementation_contract",
- testCase.implementation_contract_args ?? {},
+ {
+ ...(testCase.implementation_contract_args ?? {}),
+ },
);
const repairAttempts = testCase.repair_loop?.attempts ?? null;
const attemptReviews = [];
diff --git a/examples/model-ui/b2b-renewal-risk/index.html b/examples/model-ui/b2b-renewal-risk/index.html
index b1d2121..b45b02b 100644
--- a/examples/model-ui/b2b-renewal-risk/index.html
+++ b/examples/model-ui/b2b-renewal-risk/index.html
@@ -1080,7 +1080,7 @@
@@ -4143,16 +4134,18 @@ function renderValueEvidenceLinks(links) {
}
function defaultVisualTokenAdapter() {
- return createUiImplementationContract().implementation_contract.visual_token_adapter;
+ return createUiImplementationContract({
+ }).implementation_contract.visual_token_adapter;
}
function defaultDesignSystemContract() {
- return createUiImplementationContract().implementation_contract
- .default_ai_native_design_system;
+ return createUiImplementationContract({
+ }).implementation_contract.default_ai_native_design_system;
}
function defaultAccessibilityPolicy() {
- return createUiImplementationContract().implementation_contract.accessibility_policy;
+ return createUiImplementationContract({
+ }).implementation_contract.accessibility_policy;
}
function stripIconScenarioForExport(scenario) {
@@ -7040,9 +7033,8 @@ async function examplesPage() {
Lucide icon smoke proof
-
Search, retrieve, and render every committed Lucide icon through the MCP catalog tools. The design-system icon page is the reference surface; this HTML remains the deterministic regression proof.
+
Search, retrieve, and render every committed Lucide icon through the MCP catalog tools. This HTML remains the deterministic regression proof.
@@ -7585,7 +7577,7 @@ function siteRebuildLogPage(designSystemModel) {
What changed
-
The rebuild changed the public site from a system-map-heavy homepage into an evidence-first product surface. The homepage now explains the failure JudgmentKit prevents, shows the repair path, and routes visitors into value examples, replayable examples, eval evidence, docs, install, and design-system review.
+
The rebuild changed the public site from a system-map-heavy homepage into an evidence-first product surface. The homepage now explains the failure JudgmentKit prevents, shows the repair path, and routes visitors into value examples, replayable examples, eval evidence, docs, and install.
New homepage structure
@@ -7610,16 +7602,16 @@ function siteRebuildLogPage(designSystemModel) {
Activity model reviewThe brief was reviewed as a public product-site rebuild for AI-agent users and evaluators.
Candidate repairAn early activity-model candidate exposed raw implementation vocabulary. It was revised before it was trusted.
Surface selectionThe homepage was treated as a marketing surface with proof and adoption paths, not a setup/debug tool.
-
Workflow reviewThe accepted workflow made value, proof, docs, design-system review, examples, evals, install, and MCP setup separate surfaces.
+
Workflow reviewThe accepted workflow made value, proof, docs, examples, evals, install, and MCP setup separate surfaces.
Implementation contractThe generator stayed static and deterministic, with source-controlled routes, semantic HTML, responsive behavior, and explicit tests.
Implementation reviewThe final implementation evidence passed after the review evidence was cleaned up and resubmitted.
-
Design-system evidence
-
The strongest evidence is in the build and test contract: the same static site generator builds the product pages and the JudgmentKit design-system pages, then exports the manifest, token adapter, component contracts, pattern contracts, specimens, provenance, accessibility policy, and icon scenarios.
-
+
Design-source evidence
+
JudgmentKit keeps a package-default design-system contract for no-config use. Complete external sources such as Surfaces can replace that authority, while public JudgmentKit design-system routes are no longer the source of truth.
This page should not be read as a claim that every visual rule on the homepage is mechanically generated from exported token JSON. The defensible claim is narrower: the rebuild is in the same source-controlled static generator, routes users into the JudgmentKit design-system surface, emits the design-system assets in the same build, and has tests that verify those assets, contracts, specimens, and provenance.
+
This page should not be read as a claim that every visual rule on the homepage is mechanically generated from exported token JSON. The defensible claim is narrower: the rebuild is in the same source-controlled static generator, and JudgmentKit records the active design-system source in implementation contracts.
If you are reviewing whether this is a real rebuild, start with the source diff and tests. If you are reviewing whether it uses the JudgmentKit design system, start with the design-system route, JSON exports, specimen provenance, and the tests that hash those outputs.
+
If you are reviewing whether this is a real rebuild, start with the source diff and tests. If you are reviewing design-system authority, start with the package-default source metadata, any supplied external contract, and the tests that preserve those boundaries.
The remaining judgment call is product-level: whether the public story should expose more of this evidence earlier, or keep the homepage focused on the offer and leave this page in evals.
@@ -7891,13 +7880,6 @@ export async function buildSite(outDir = DEFAULT_OUT_DIR) {
await fs.rm(outDir, { recursive: true, force: true });
await fs.mkdir(path.join(outDir, "assets"), { recursive: true });
await fs.mkdir(path.join(outDir, "docs"), { recursive: true });
- await fs.mkdir(path.join(outDir, "design-system"), { recursive: true });
- await fs.mkdir(path.join(outDir, "design-system", "tokens"), { recursive: true });
- await fs.mkdir(path.join(outDir, "design-system", "fonts"), { recursive: true });
- await fs.mkdir(path.join(outDir, "design-system", "icons"), { recursive: true });
- await fs.mkdir(path.join(outDir, "design-system", "components"), { recursive: true });
- await fs.mkdir(path.join(outDir, "design-system", "patterns"), { recursive: true });
- await fs.mkdir(path.join(outDir, "design-system", "accessibility"), { recursive: true });
await fs.mkdir(path.join(outDir, "evals"), { recursive: true });
await fs.mkdir(path.join(outDir, "evals", "judgmentkit-mcp"), { recursive: true });
await fs.mkdir(path.join(outDir, "evals", "site-rebuild-log"), { recursive: true });
@@ -7923,61 +7905,6 @@ export async function buildSite(outDir = DEFAULT_OUT_DIR) {
await fs.writeFile(path.join(outDir, "robots.txt"), "User-agent: *\nAllow: /\n");
await fs.writeFile(path.join(outDir, "value", "index.html"), await valuePage());
await fs.writeFile(path.join(outDir, "docs", "index.html"), docsPage());
- await fs.writeFile(path.join(outDir, "design-system", "index.html"), renderDesignSystemOverviewPage(designSystemModel));
- await fs.writeFile(path.join(outDir, "design-system", "tokens", "index.html"), renderDesignSystemTokensPage(designSystemModel));
- await fs.writeFile(path.join(outDir, "design-system", "fonts", "index.html"), renderDesignSystemFontsPage(designSystemModel));
- await fs.writeFile(path.join(outDir, "design-system", "icons", "index.html"), renderDesignSystemIconsPage(designSystemModel));
- await fs.writeFile(path.join(outDir, "design-system", "components", "index.html"), renderDesignSystemComponentsPage(designSystemModel));
- await fs.writeFile(path.join(outDir, "design-system", "patterns", "index.html"), renderDesignSystemPatternsPage(designSystemModel));
- await fs.writeFile(path.join(outDir, "design-system", "accessibility", "index.html"), renderDesignSystemAccessibilityPage(designSystemModel));
- await fs.writeFile(
- path.join(outDir, "design-system", "manifest.json"),
- jsonExport(designSystemModel.exports.manifest),
- );
- await fs.writeFile(
- path.join(outDir, "design-system", "visual-token-adapter.json"),
- jsonExport(designSystemModel.exports.visualTokenAdapter),
- );
- await fs.writeFile(
- path.join(outDir, "design-system", "component-contracts.json"),
- jsonExport(designSystemModel.exports.componentContracts),
- );
- await fs.writeFile(
- path.join(outDir, "design-system", "pattern-contracts.json"),
- jsonExport(designSystemModel.exports.patternContracts),
- );
- await fs.writeFile(
- path.join(outDir, "design-system", "component-specimens.json"),
- jsonExport(designSystemModel.exports.componentSpecimens),
- );
- await fs.writeFile(
- path.join(outDir, "design-system", "pattern-specimens.json"),
- jsonExport(designSystemModel.exports.patternSpecimens),
- );
- await fs.writeFile(
- path.join(outDir, "design-system", "specimen-provenance.json"),
- jsonExport(designSystemModel.exports.specimenProvenance),
- );
- await fs.writeFile(
- path.join(outDir, "design-system", "accessibility-policy.json"),
- jsonExport(designSystemModel.exports.accessibilityPolicy),
- );
- await fs.writeFile(
- path.join(outDir, "design-system", "icon-scenarios.json"),
- jsonExport(designSystemModel.exports.iconScenarios),
- );
- await fs.writeFile(path.join(outDir, "design-system", "llms.txt"), renderDesignSystemLlms(designSystemModel));
- await fs.writeFile(
- path.join(outDir, "design-system", "llms-full.txt"),
- renderDesignSystemLlmsFull(designSystemModel),
- );
- for (const pageEntry of designSystemModel.pages) {
- const markdownPath = pageEntry.markdown_path.replace(/^\/design-system\/?/, "");
- await fs.writeFile(
- path.join(outDir, "design-system", markdownPath),
- renderDesignSystemPageMarkdown(designSystemModel, pageEntry),
- );
- }
await fs.writeFile(path.join(outDir, "examples", "index.html"), await examplesPage());
await fs.writeFile(path.join(outDir, "install"), await bootstrapScript(), { mode: 0o755 });
await fs.writeFile(
@@ -7989,8 +7916,6 @@ export async function buildSite(outDir = DEFAULT_OUT_DIR) {
"",
"- /value/",
"- /docs/",
- "- /design-system/",
- "- /design-system/llms.txt",
"- /examples/",
"- /evals/",
"- /evals/judgmentkit-mcp/",
diff --git a/src/index.mjs b/src/index.mjs
index f91e8c9..9566665 100644
--- a/src/index.mjs
+++ b/src/index.mjs
@@ -5370,23 +5370,30 @@ const DESIGN_SYSTEM_REQUIRED_AUTHORITIES = [
"components",
];
+const CANONICAL_SURFACES_DESIGN_SYSTEM_URL =
+ "https://surfaces.systems/design-system";
+
const DEFAULT_DESIGN_SYSTEM_SOURCE = {
id: "judgmentkit.design-system.source-v1",
mode: "judgmentkit_default",
name: "JudgmentKit",
package: "judgmentkit",
- definition_point: "implementation_contract",
+ definition_point: "package_default",
required_authorities: DESIGN_SYSTEM_REQUIRED_AUTHORITIES,
fallback_policy: "fail_incomplete",
provenance_required: true,
source_exports: {
- overview: "/design-system/",
- manifest: "/design-system/manifest.json",
- visual_token_adapter: "/design-system/visual-token-adapter.json",
- component_contracts: "/design-system/component-contracts.json",
- pattern_contracts: "/design-system/pattern-contracts.json",
- accessibility_policy: "/design-system/accessibility-policy.json",
- icon_catalog: "/design-system/icons/",
+ overview: "package://judgmentkit/design-system/",
+ manifest: "package://judgmentkit/design-system/manifest.json",
+ visual_token_adapter:
+ "package://judgmentkit/design-system/visual-token-adapter.json",
+ component_contracts:
+ "package://judgmentkit/design-system/component-contracts.json",
+ pattern_contracts:
+ "package://judgmentkit/design-system/pattern-contracts.json",
+ accessibility_policy:
+ "package://judgmentkit/design-system/accessibility-policy.json",
+ icon_catalog: "package://judgmentkit/design-system/icons/",
icon_tools: ICON_CATALOG_TOOL_NAMES,
},
token_prefixes: ["--jk-"],
@@ -5394,12 +5401,21 @@ const DEFAULT_DESIGN_SYSTEM_SOURCE = {
component_contract_source:
"implementation_contract.default_ai_native_design_system.component_contracts",
provenance_rules: [
- "visual tokens, fonts, icons, and renderer components must come from this active design-system source",
+ "visual tokens, fonts, icons, and renderer components come from the JudgmentKit package default when no design system is supplied",
"local CSS may define layout and UI structure but must not become the source of visual tokens, typography, icon assets, or renderer components",
- "external design systems must be supplied as complete contract-time adapters; missing authorities do not fall back to JudgmentKit defaults",
+ "external design systems must be supplied as complete contract-time adapters or complete design-system sources; missing authorities do not fall back to JudgmentKit defaults",
],
};
+function designSystemSourceValidationDetails(missing = []) {
+ return {
+ code: "invalid_design_system_source",
+ canonical_surfaces_url: CANONICAL_SURFACES_DESIGN_SYSTEM_URL,
+ missing,
+ valid_modes: ["judgmentkit_default", "external_design_system"],
+ };
+}
+
const DEFAULT_ITERATION_POLICY = {
owner: "agent",
default_max_attempts: 3,
@@ -6019,6 +6035,190 @@ function designSystemAdapterFromInput(source) {
: null;
}
+function designSystemSourceFromInput(source) {
+ return isPlainObject(source)
+ ? source.design_system_source ?? source.designSystemSource
+ : null;
+}
+
+function hasDesignSystemSourceInput(source) {
+ return (
+ isPlainObject(source) &&
+ ("design_system_source" in source || "designSystemSource" in source)
+ );
+}
+
+function usesJudgmentKitDefaultDesignSystem(source) {
+ if (!isPlainObject(source)) {
+ return false;
+ }
+
+ const designSystemSource = designSystemSourceFromInput(source);
+
+ return (
+ source.fixture_design_system === true ||
+ source.fixtureDesignSystem === true ||
+ designSystemSource?.mode === "judgmentkit_default"
+ );
+}
+
+function validateExplicitDesignSystemSource(sourceValue) {
+ if (sourceValue === undefined || sourceValue === null) {
+ return;
+ }
+
+ if (!isPlainObject(sourceValue)) {
+ throw new JudgmentKitInputError(
+ "design_system_source must be an object when provided.",
+ {
+ code: "invalid_design_system_source",
+ details: designSystemSourceValidationDetails(["object"]),
+ },
+ );
+ }
+
+ const missing = [];
+ for (const field of ["id", "mode", "name", "package", "definition_point"]) {
+ if (!optionalString(sourceValue[field]).length) {
+ missing.push(field);
+ }
+ }
+
+ const mode = optionalString(sourceValue.mode);
+ if (
+ mode.length > 0 &&
+ !["judgmentkit_default", "external_design_system"].includes(mode)
+ ) {
+ missing.push("mode:judgmentkit_default|external_design_system");
+ }
+
+ if (
+ normalizePrimitiveList(
+ sourceValue.required_authorities ?? sourceValue.requiredAuthorities,
+ ).length < DESIGN_SYSTEM_REQUIRED_AUTHORITIES.length
+ ) {
+ missing.push("required_authorities");
+ }
+
+ if (
+ optionalString(sourceValue.fallback_policy ?? sourceValue.fallbackPolicy) !==
+ "fail_incomplete"
+ ) {
+ missing.push("fallback_policy");
+ }
+
+ if (
+ typeof (sourceValue.provenance_required ??
+ sourceValue.provenanceRequired) !== "boolean"
+ ) {
+ missing.push("provenance_required");
+ }
+
+ if (
+ !isPlainObject(sourceValue.source_exports ?? sourceValue.sourceExports) ||
+ Object.keys(sourceValue.source_exports ?? sourceValue.sourceExports).length === 0
+ ) {
+ missing.push("source_exports");
+ }
+
+ if (
+ normalizePrimitiveList(sourceValue.token_prefixes ?? sourceValue.tokenPrefixes)
+ .length === 0
+ ) {
+ missing.push("token_prefixes");
+ }
+
+ const iconCatalog = sourceValue.icon_catalog ?? sourceValue.iconCatalog;
+ if (!isPlainObject(iconCatalog)) {
+ missing.push("icon_catalog");
+ } else {
+ for (const field of [
+ "source",
+ "library",
+ "package",
+ "version",
+ "license",
+ "notice",
+ "style_system",
+ ]) {
+ if (!optionalString(iconCatalog[field]).length) {
+ missing.push(`icon_catalog.${field}`);
+ }
+ }
+
+ if (numberOrFallback(iconCatalog.icon_count ?? iconCatalog.iconCount, 0) < 1) {
+ missing.push("icon_catalog.icon_count");
+ }
+
+ if (
+ !isPlainObject(iconCatalog.style_attributes ?? iconCatalog.styleAttributes) ||
+ Object.keys(iconCatalog.style_attributes ?? iconCatalog.styleAttributes).length === 0
+ ) {
+ missing.push("icon_catalog.style_attributes");
+ }
+
+ if (
+ normalizePrimitiveList(
+ iconCatalog.mcp_tools ?? iconCatalog.mcpTools ?? iconCatalog.tools,
+ ).length === 0
+ ) {
+ missing.push("icon_catalog.mcp_tools");
+ }
+
+ if (
+ typeof (iconCatalog.default_include_svg ??
+ iconCatalog.defaultIncludeSvg) !== "boolean"
+ ) {
+ missing.push("icon_catalog.default_include_svg");
+ }
+ }
+
+ if (
+ normalizePrimitiveList(
+ sourceValue.renderer_components ?? sourceValue.rendererComponents,
+ ).length === 0
+ ) {
+ missing.push("renderer_components");
+ }
+
+ if (
+ !optionalString(
+ sourceValue.component_contract_source ??
+ sourceValue.componentContractSource,
+ ).length
+ ) {
+ missing.push("component_contract_source");
+ }
+
+ if (
+ normalizePrimitiveList(
+ sourceValue.provenance_rules ?? sourceValue.provenanceRules,
+ ).length === 0
+ ) {
+ missing.push("provenance_rules");
+ }
+
+ if (missing.length > 0) {
+ throw new JudgmentKitInputError(
+ "design_system_source must be complete when provided. Omit it to use the JudgmentKit package default.",
+ {
+ code: "invalid_design_system_source",
+ details: designSystemSourceValidationDetails(missing),
+ },
+ );
+ }
+}
+
+function assertValidDesignSystemInputs(source) {
+ if (!isPlainObject(source)) {
+ return;
+ }
+
+ if (hasDesignSystemSourceInput(source)) {
+ validateExplicitDesignSystemSource(designSystemSourceFromInput(source));
+ }
+}
+
function externalAdapterName(adapter) {
return optionalDesignSystemName(
adapter.design_system_name,
@@ -6260,11 +6460,11 @@ function externalVisualTokenAdapterFallback(adapter, iconSource) {
DEFAULT_ICON_SELECTION_POLICY.accessibility_guidance,
failure_signals: [
"icons bypass the active external design-system source",
- "icons are mixed with JudgmentKit defaults without explicit external authority",
+ "icons are mixed with JudgmentKit default assets without explicit external authority",
],
},
icon_rules: [
- "default JudgmentKit icon assets are not used while an external design system is active",
+ "JudgmentKit default icon assets are not used while an external design system is active",
"meaningful icons still require adjacent text or an accessible name",
],
adapter_rules: [
@@ -6486,10 +6686,14 @@ function resolveImplementationDesignSystem(source, base) {
source.visual_token_adapter ?? source.visualTokenAdapter,
base.visual_token_adapter,
);
+ const explicitDesignSystemSource = designSystemSourceFromInput(source);
+ const designSystemSourceValue = usesJudgmentKitDefaultDesignSystem(source)
+ ? isPlainObject(explicitDesignSystemSource)
+ ? explicitDesignSystemSource
+ : DEFAULT_DESIGN_SYSTEM_SOURCE
+ : explicitDesignSystemSource;
const designSystemSource = normalizeDesignSystemSource(
- source.design_system_source ??
- source.designSystemSource ??
- base.design_system_source,
+ designSystemSourceValue,
{
visualTokenAdapter,
componentContracts: sourceDefaultDesignSystem.component_contracts,
@@ -6725,6 +6929,17 @@ function implementationContractSource(input = {}) {
return "external_design_system";
}
+ if (isPlainObject(input) && usesJudgmentKitDefaultDesignSystem(input)) {
+ return "judgmentkit_default";
+ }
+
+ if (isPlainObject(input) && isPlainObject(designSystemSourceFromInput(input))) {
+ return (
+ optionalString(designSystemSourceFromInput(input).mode) ||
+ "explicit_design_system_source"
+ );
+ }
+
if (isPlainObject(input) && toStringArray(input.repo_evidence).length > 0) {
return "repo_evidence";
}
@@ -6747,6 +6962,7 @@ export function createUiImplementationContract(input = {}, options = {}) {
);
}
+ assertValidDesignSystemInputs(input ?? {});
const contract = options.contract ?? loadActivityContract(options.contractPath);
const normalized = normalizeUiImplementationContract(input ?? {}, { contract });
const packet = {
@@ -9790,10 +10006,13 @@ export function createUiGenerationHandoff(workflowReview, options = {}) {
const activityCandidate = workflowReview.activity_review.candidate;
const workflowCandidate = workflowReview.candidate;
const contract = options.contract ?? loadActivityContract(options.contractPath);
- const implementationContract = normalizeUiImplementationContract(
+ const implementationContractInput =
options.implementation_contract ??
- options.ui_implementation_contract ??
- contract.implementation_contract,
+ options.ui_implementation_contract ??
+ contract.implementation_contract;
+ assertValidDesignSystemInputs(implementationContractInput);
+ const implementationContract = normalizeUiImplementationContract(
+ implementationContractInput,
{ contract },
);
const workflowSurfaceSet = toSurfaceSetArray(workflowCandidate.surface_set);
@@ -10014,7 +10233,11 @@ function guidanceSourceName(hasSource, designSystemMode) {
return "external_design_system";
}
- return "judgmentkit_design_system";
+ if (designSystemMode === "judgmentkit_default") {
+ return "judgmentkit_design_system";
+ }
+
+ return "explicit_design_system_source";
}
function normalizeAdapterTokenGuidance(
@@ -10442,8 +10665,18 @@ export function createFrontendGenerationContext({
const normalizedVerification = normalizeVerificationContext(verification);
const requiredSurfaces = toSurfaceSetArray(uiGenerationHandoff.surface_set);
const requiredSurfaceAggregate = aggregateSurfaceSet(requiredSurfaces);
+ const sourceImplementationContract = isPlainObject(
+ uiGenerationHandoff.implementation_contract,
+ )
+ ? uiGenerationHandoff.implementation_contract
+ : {};
+ assertValidDesignSystemInputs(sourceImplementationContract);
+ const implementationContract = normalizeUiImplementationContract(
+ sourceImplementationContract,
+ { contract: resolvedContract },
+ );
const designSystemContract = normalizeDefaultAiNativeDesignSystem(
- uiGenerationHandoff.implementation_contract?.default_ai_native_design_system,
+ implementationContract.default_ai_native_design_system,
DEFAULT_AI_NATIVE_DESIGN_SYSTEM,
);
@@ -10468,7 +10701,7 @@ export function createFrontendGenerationContext({
surface_set: requiredSurfaces,
product_terms: toStringArray(uiGenerationHandoff.product_terms),
handoff: uiGenerationHandoff.handoff,
- implementation_contract: uiGenerationHandoff.implementation_contract,
+ implementation_contract: implementationContract,
disclosure_reminders: uiGenerationHandoff.disclosure_reminders,
frontend_context: {
target_runtime: optionalString(normalizedFrontendContext.target_runtime),
@@ -10492,15 +10725,13 @@ export function createFrontendGenerationContext({
interaction_implications: surfaceGuidance.interaction_implications,
disclosure_implications: surfaceGuidance.disclosure_implications,
frontend_posture: surfaceGuidance.frontend_posture,
- implementation_contract: uiGenerationHandoff.implementation_contract,
- design_system_source:
- uiGenerationHandoff.implementation_contract?.design_system_source ??
- DEFAULT_DESIGN_SYSTEM_SOURCE,
+ implementation_contract: implementationContract,
+ design_system_source: implementationContract.design_system_source,
visual_asset_policy:
- uiGenerationHandoff.implementation_contract?.visual_asset_policy ??
+ implementationContract.visual_asset_policy ??
DEFAULT_VISUAL_ASSET_POLICY,
accessibility_policy:
- uiGenerationHandoff.implementation_contract?.accessibility_policy ??
+ implementationContract.accessibility_policy ??
DEFAULT_ACCESSIBILITY_POLICY,
component_contracts: designSystemContract.component_contracts,
pattern_contracts: designSystemContract.pattern_contracts,
@@ -10521,11 +10752,8 @@ export function createFrontendGenerationContext({
uiGenerationHandoff.disclosure_reminders?.terms_to_keep_out_of_product_ui ?? [],
diagnostic_contexts:
uiGenerationHandoff.disclosure_reminders?.diagnostic_contexts ?? [],
- approved_primitives:
- uiGenerationHandoff.implementation_contract?.approved_primitives ?? [],
- design_system_source:
- uiGenerationHandoff.implementation_contract?.design_system_source ??
- DEFAULT_DESIGN_SYSTEM_SOURCE,
+ approved_primitives: implementationContract.approved_primitives ?? [],
+ design_system_source: implementationContract.design_system_source,
},
};
}
@@ -10574,7 +10802,7 @@ function buildFrontendImplementationInstructionMarkdown({
"- Use numbered wizard or stepper UI only when workflow.stepper_eligibility.allowed is true.",
"- Use approved primitives and approved component families before introducing new UI helpers.",
"- Use implementation_contract.design_system_source as the active source for visual tokens, typography, icon assets, and renderer components.",
- "- Use JudgmentKit design-system exports by default; when external_design_system is active, do not mix in JudgmentKit default assets unless the external adapter explicitly names them.",
+ "- Do not mix assets from another design system unless the active source or adapter explicitly grants that authority.",
"- Verify core accessibility evidence for semantics, landmarks/headings, name/role/value, keyboard navigation, focus order, focus-visible, responsive reflow/no-overflow, and automated checks.",
"- Add conditional accessibility evidence for visuals, custom widgets, forms, status messages, overlays, motion, media, dense controls, and hover/focus content when those patterns appear.",
"- For text over substantive visuals or rendered backgrounds, verify WCAG AA contrast from browser-rendered output, not screenshots alone.",
@@ -10702,6 +10930,8 @@ export function createFrontendImplementationSkillContext({
);
}
+ const designSystemAdapterWasProvided =
+ designSystemAdapter !== undefined && designSystemAdapter !== null;
const normalizedDesignSystemAdapter = normalizeDesignSystemAdapter(designSystemAdapter);
const normalizedTargetClient = optionalString(targetClient);
const normalizedInstructionFormat = normalizeInstructionFormat(instructionFormat);
@@ -10730,6 +10960,12 @@ export function createFrontendImplementationSkillContext({
implementationContract.default_ai_native_design_system,
DEFAULT_AI_NATIVE_DESIGN_SYSTEM,
);
+ if (
+ designSystemAdapterWasProvided &&
+ !hasDesignGuidanceValue(normalizedDesignSystemAdapter)
+ ) {
+ validateExternalDesignSystemAdapter(normalizedDesignSystemAdapter);
+ }
let designSystemSource = normalizeDesignSystemSource(
implementationContract.design_system_source ??
implementationGuidance.design_system_source,
@@ -10861,7 +11097,7 @@ export function createFrontendImplementationSkillContext({
"Use numbered wizard or stepper UI only when workflow.stepper_eligibility.allowed is true.",
"Use approved primitives and approved component families before introducing new UI helpers.",
"Use implementation_contract.design_system_source as the active source for visual tokens, typography, icon assets, and renderer components.",
- "Use JudgmentKit design-system exports by default; when external_design_system is active, do not mix in JudgmentKit default assets unless the external adapter explicitly names them.",
+ "Do not mix assets from another design system unless the active source or adapter explicitly grants that authority.",
"When the spec calls for substantive visuals, use imagegen or premium Three.js/WebGL/D3-style rendering instead of rudimentary deterministic geometry.",
"Verify core accessibility evidence: automated checks, semantic content, landmarks/headings, name-role-value, keyboard navigation, focus order, focus-visible, and responsive reflow/no-overflow.",
"Add conditional accessibility evidence for visuals, custom widgets, forms, status messages, overlays, motion, media, dense controls, and hover/focus content when those patterns appear.",
diff --git a/src/mcp.mjs b/src/mcp.mjs
index 28a59d7..7f2558b 100644
--- a/src/mcp.mjs
+++ b/src/mcp.mjs
@@ -234,7 +234,7 @@ const UI_GENERATION_HANDOFF_TOOL = {
const UI_IMPLEMENTATION_CONTRACT_TOOL = {
name: "create_ui_implementation_contract",
description:
- "Create an implementation contract for generated UI, using JudgmentKit design-system authority by default or a complete external design-system adapter when supplied.",
+ "Create an implementation contract for generated UI. When no design system is supplied, JudgmentKit uses its package default; explicit design_system_source and design_system_adapter inputs must be complete.",
inputSchema: {
type: "object",
properties: {
@@ -249,17 +249,17 @@ const UI_IMPLEMENTATION_CONTRACT_TOOL = {
external_authority: {
type: "string",
description:
- "Optional trace metadata for a named UI authority. It does not replace JudgmentKit defaults unless design_system_adapter is also supplied.",
+ "Optional trace metadata for a named UI authority. It does not replace the JudgmentKit package default unless design_system_source or design_system_adapter is also supplied.",
},
design_system_adapter: {
type: "object",
description:
- "Optional complete external design-system authority. Must define token, font, icon, and component authority or the contract fails with incomplete_design_system_authority.",
+ "Complete external design-system authority. Must define token, font, icon, and component authority or the contract fails with incomplete_design_system_authority.",
},
design_system_source: {
type: "object",
description:
- "Optional normalized active design-system source when passing an already-created implementation contract shape.",
+ "Complete normalized active design-system source. Omit this field to use the JudgmentKit package default.",
},
repo_evidence: {
type: "array",
@@ -303,7 +303,7 @@ const UI_IMPLEMENTATION_CONTRACT_TOOL = {
visual_token_adapter: {
type: "object",
description:
- "Optional JudgmentKit-default token, font, and icon metadata. Ignored when design_system_adapter supplies complete external authority.",
+ "Optional token, font, and icon metadata for the active source. Ignored when design_system_adapter supplies complete external authority.",
},
},
additionalProperties: false,
diff --git a/tests/demo-model-ui-matrix.test.mjs b/tests/demo-model-ui-matrix.test.mjs
index 1631891..dec8a5a 100644
--- a/tests/demo-model-ui-matrix.test.mjs
+++ b/tests/demo-model-ui-matrix.test.mjs
@@ -41,7 +41,9 @@ function visibleText(html) {
function normalizeFrontendSkillSummary(summary) {
if (!summary) return summary;
const designSystemMode =
- /^no_design_system_.*provided$/.test(summary.design_system_mode ?? "")
+ summary.design_system_mode === "judgmentkit_default"
+ ? "judgmentkit_default"
+ : /^no_design_system_.*provided$/.test(summary.design_system_mode ?? "")
? "judgmentkit_default"
: /^adapter_after_/.test(summary.design_system_mode ?? "")
? "external_design_system"
@@ -51,7 +53,8 @@ function normalizeFrontendSkillSummary(summary) {
...summary,
design_system_mode: designSystemMode,
design_system_name:
- designSystemMode === "judgmentkit_default" && !summary.design_system_name
+ designSystemMode === "judgmentkit_default" &&
+ (!summary.design_system_name || summary.design_system_name === "JudgmentKit")
? "JudgmentKit"
: summary.design_system_name,
};
diff --git a/tests/kernel-contract.test.mjs b/tests/kernel-contract.test.mjs
index 57e1b7d..aab3ace 100644
--- a/tests/kernel-contract.test.mjs
+++ b/tests/kernel-contract.test.mjs
@@ -508,8 +508,71 @@ assert.equal(defaultDesignSystemSource.fallback_policy, "fail_incomplete");
assert.equal(defaultDesignSystemSource.provenance_required, true);
assert.ok(defaultDesignSystemSource.token_prefixes.includes("--jk-"));
assert.ok(defaultDesignSystemSource.source_exports.icon_tools.includes("get_icon_svg"));
+assert.equal(
+ defaultDesignSystemSource.source_exports.manifest,
+ "package://judgmentkit/design-system/manifest.json",
+);
assert.ok(defaultDesignSystemSource.renderer_components.includes("action_button"));
+const surfacesSourceContract = createUiImplementationContract({
+ design_system_source: {
+ id: "surfaces.design-contract.v1",
+ mode: "external_design_system",
+ name: "Surfaces",
+ package: "@surfaces/ui",
+ definition_point: "implementation_contract.design_system_source",
+ source_exports: {
+ overview: "https://surfaces.systems/design-system",
+ manifest: "https://surfaces.systems/design-system/manifest.json",
+ visual_token_adapter:
+ "https://surfaces.systems/design-system/visual-token-adapter.json",
+ component_contracts:
+ "https://surfaces.systems/design-system/component-contracts.json",
+ pattern_contracts:
+ "https://surfaces.systems/design-system/pattern-contracts.json",
+ accessibility_policy:
+ "https://surfaces.systems/design-system/accessibility-policy.json",
+ icon_catalog: "https://surfaces.systems/design-system/icons/",
+ },
+ required_authorities: ["tokens", "fonts", "icons", "components"],
+ fallback_policy: "fail_incomplete",
+ provenance_required: true,
+ token_prefixes: ["--surfaces-"],
+ icon_catalog: {
+ source: "external_contract",
+ library: "surfaces",
+ package: "@surfaces/icons",
+ version: "1.0.0",
+ icon_count: 1,
+ license: "repo-approved",
+ notice: "Surfaces icon metadata is governed by the external contract.",
+ style_system: "Surfaces outline icons",
+ style_attributes: {
+ viewBox: "0 0 24 24",
+ fill: "none",
+ stroke: "currentColor",
+ },
+ mcp_tools: ["surfaces.list_icons"],
+ default_include_svg: false,
+ },
+ renderer_components: ["action_button"],
+ component_contract_source:
+ "https://surfaces.systems/design-system/component-contracts.json",
+ provenance_rules: [
+ "visual tokens, fonts, icons, and components must come from Surfaces",
+ ],
+ },
+});
+assert.equal(
+ surfacesSourceContract.implementation_contract.design_system_source.id,
+ "surfaces.design-contract.v1",
+);
+assert.equal(
+ surfacesSourceContract.implementation_contract.design_system_source.source_exports
+ .manifest,
+ "https://surfaces.systems/design-system/manifest.json",
+);
+
const externalTraceOnlyContract = createUiImplementationContract({
external_authority: "Material UI",
});
@@ -519,6 +582,32 @@ assert.equal(
"external_authority is trace metadata only without a complete design_system_adapter.",
);
+assert.throws(
+ () =>
+ createUiImplementationContract({
+ design_system_source: {},
+ }),
+ (error) =>
+ error instanceof JudgmentKitInputError &&
+ error.code === "invalid_design_system_source",
+ "An empty explicit design_system_source must fail instead of falling back.",
+);
+
+assert.throws(
+ () =>
+ createUiImplementationContract({
+ design_system_source: {
+ ...surfacesSourceContract.implementation_contract.design_system_source,
+ icon_catalog: {},
+ },
+ }),
+ (error) =>
+ error instanceof JudgmentKitInputError &&
+ error.code === "invalid_design_system_source" &&
+ error.details.missing.includes("icon_catalog.library"),
+ "An explicit design_system_source with an empty icon catalog must fail.",
+);
+
const externalDesignSystemContract = createUiImplementationContract({
design_system_adapter: completeMaterialDesignSystemAdapter(),
});
diff --git a/tests/lucide-icon-catalog.test.mjs b/tests/lucide-icon-catalog.test.mjs
index 42f2617..ff6d73d 100644
--- a/tests/lucide-icon-catalog.test.mjs
+++ b/tests/lucide-icon-catalog.test.mjs
@@ -2,6 +2,7 @@ import assert from "node:assert/strict";
import { execFileSync } from "node:child_process";
import {
+ JudgmentKitInputError,
createFrontendGenerationContext,
createFrontendImplementationSkillContext,
createUiGenerationHandoff,
@@ -161,3 +162,32 @@ assert.ok(skillContext.pattern_contracts.some((entry) => entry.id === "workbench
assert.ok(skillContext.instruction_markdown.includes("Icon catalog"));
assert.ok(skillContext.instruction_markdown.includes("--jk-color-surface"));
assert.ok(skillContext.instruction_markdown.includes("Component contracts"));
+
+const legacyHandoffWithoutSource = {
+ ...handoff,
+ implementation_contract: {
+ ...handoff.implementation_contract,
+ design_system_source: undefined,
+ },
+};
+delete legacyHandoffWithoutSource.implementation_contract.design_system_source;
+
+const defaultedFrontendContext = createFrontendGenerationContext({
+ ui_generation_handoff: legacyHandoffWithoutSource,
+});
+assert.equal(
+ defaultedFrontendContext.implementation_contract.design_system_source.mode,
+ "judgmentkit_default",
+);
+
+assert.throws(
+ () =>
+ createFrontendImplementationSkillContext({
+ frontend_generation_context: defaultedFrontendContext,
+ design_system_adapter: {},
+ }),
+ (error) =>
+ error instanceof JudgmentKitInputError &&
+ error.code === "incomplete_design_system_authority",
+ "An explicitly supplied empty frontend design_system_adapter must fail.",
+);
diff --git a/tests/mcp-http.test.mjs b/tests/mcp-http.test.mjs
index 2f3f121..62c01fe 100644
--- a/tests/mcp-http.test.mjs
+++ b/tests/mcp-http.test.mjs
@@ -136,6 +136,11 @@ async function runMcpClient(endpoint) {
.visual_token_adapter.mode,
"boundary_only",
);
+ assert.equal(
+ implementationContractResponse.structuredContent.implementation_contract
+ .design_system_source.mode,
+ "judgmentkit_default",
+ );
assert.ok(
implementationContractResponse.structuredContent.implementation_contract
.visual_token_adapter.token_families.includes("color"),
diff --git a/tests/mcp.test.mjs b/tests/mcp.test.mjs
index 57215cd..b2d5368 100644
--- a/tests/mcp.test.mjs
+++ b/tests/mcp.test.mjs
@@ -91,6 +91,10 @@ assert.equal(toolByName.create_ui_implementation_contract.inputSchema.properties
assert.equal(toolByName.create_ui_implementation_contract.inputSchema.properties.iteration_policy.type, "object");
assert.equal(toolByName.create_ui_implementation_contract.inputSchema.properties.design_system_adapter.type, "object");
assert.equal(toolByName.create_ui_implementation_contract.inputSchema.properties.design_system_source.type, "object");
+assert.equal(
+ "fixture_design_system" in toolByName.create_ui_implementation_contract.inputSchema.properties,
+ false,
+);
assert.equal(toolByName.create_ui_implementation_contract.inputSchema.properties.visual_token_adapter.type, "object");
assert.ok(
toolByName.create_ui_implementation_contract.inputSchema.properties.visual_token_adapter.description.includes(
diff --git a/tests/site-local-server.test.mjs b/tests/site-local-server.test.mjs
index 66de37f..c8d8a11 100644
--- a/tests/site-local-server.test.mjs
+++ b/tests/site-local-server.test.mjs
@@ -97,10 +97,6 @@ try {
"/value/",
"/docs/",
"/docs",
- "/design-system/",
- "/design-system/tokens/",
- "/design-system/fonts/",
- "/design-system/icons/",
"/examples/",
"/evals/",
"/install",
@@ -110,6 +106,47 @@ try {
assert.equal(response.status, 200, `${route} should return 200`);
}
+ for (const route of [
+ "/design-system/",
+ "/design-system",
+ "/design-system/index.html",
+ "/design-system/index.html.md",
+ "/design-system/llms.txt",
+ "/design-system/llms-full.txt",
+ "/design-system/tokens/",
+ "/design-system/tokens",
+ "/design-system/tokens/index.html",
+ "/design-system/tokens/index.html.md",
+ "/design-system/fonts",
+ "/design-system/fonts/",
+ "/design-system/fonts/index.html",
+ "/design-system/fonts/index.html.md",
+ "/design-system/icons",
+ "/design-system/icons/",
+ "/design-system/icons/index.html",
+ "/design-system/icons/index.html.md",
+ "/design-system/components",
+ "/design-system/components/",
+ "/design-system/components/index.html",
+ "/design-system/components/index.html.md",
+ "/design-system/patterns",
+ "/design-system/patterns/",
+ "/design-system/patterns/index.html",
+ "/design-system/patterns/index.html.md",
+ "/design-system/accessibility",
+ "/design-system/accessibility/",
+ "/design-system/accessibility/index.html",
+ "/design-system/accessibility/index.html.md",
+ ]) {
+ const response = await fetchRoute(url, route, { redirect: "manual" });
+
+ assert.equal(response.status, 308, `${route} should redirect to Surfaces`);
+ assert.equal(
+ response.headers.get("location"),
+ "https://surfaces.systems/design-system",
+ );
+ }
+
{
const response = await fetchRoute(url, "/install");
@@ -169,36 +206,43 @@ try {
const response = await fetchRoute(url, route);
const body = await response.json();
- assert.equal(response.status, 200, `${route} should return 200`);
+ assert.equal(response.status, 410, `${route} should return 410`);
assert.equal(response.headers.get("content-type"), "application/json; charset=utf-8");
- assert.equal(typeof body, "object");
+ assert.equal(body.code, "judgmentkit_design_system_retired");
+ assert.equal(body.canonicalUrl, "https://surfaces.systems/design-system");
+ assert.equal(body.requestedPath, route);
}
- for (const route of [
- "/design-system/index.html.md",
- "/design-system/tokens/index.html.md",
- "/design-system/fonts/index.html.md",
- "/design-system/icons/index.html.md",
- "/design-system/components/index.html.md",
- "/design-system/patterns/index.html.md",
- "/design-system/accessibility/index.html.md",
- ]) {
- const response = await fetchRoute(url, route);
- const body = await response.text();
+ {
+ const response = await fetchRoute(url, "/design-system/manifest.json", {
+ method: "HEAD",
+ });
- assert.equal(response.status, 200, `${route} should return 200`);
- assert.equal(response.headers.get("content-type"), "text/markdown; charset=utf-8");
- assert.ok(body.startsWith("# JudgmentKit"), `${route} should return Markdown`);
- assert.equal(body.includes("