@warpgogol/werkstatt-shared 0.14.0 → 0.14.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/README.md +26 -16
  2. package/README.uk.md +24 -14
  3. package/package.json +7 -1
  4. package/src/checks/result-helpers.ts +21 -4
  5. package/src/checks/tests/remediation-auto-populate.test.ts +83 -0
  6. package/src/integration/vitest.config.ts +7 -0
  7. package/src/ontology/manifest.ts +19 -0
  8. package/src/ontology/schemas/system/tests/growth.test.ts +22 -0
  9. package/src/ontology/schemas/system/tests/integrations.test.ts +12 -0
  10. package/src/ontology/schemas/system/tests/manifest.test.ts +22 -0
  11. package/src/ontology/schemas/system/tests/page-output.test.ts +13 -0
  12. package/src/ontology/schemas/system/tests/release.test.ts +22 -0
  13. package/src/ontology/schemas/system/tests/text.test.ts +18 -0
  14. package/src/ontology/schemas/system/tests/verification.test.ts +12 -0
  15. package/src/ontology/schemas/tests/biome.test.ts +19 -0
  16. package/src/ontology/schemas/tests/capability.test.ts +22 -0
  17. package/src/ontology/schemas/tests/constellation.test.ts +22 -0
  18. package/src/ontology/schemas/tests/dns-records.test.ts +13 -0
  19. package/src/ontology/schemas/tests/manifest-resolver.test.ts +13 -0
  20. package/src/ontology/schemas/tests/page-entry.test.ts +22 -0
  21. package/src/ontology/schemas/tests/section-archetype.test.ts +12 -0
  22. package/src/ontology/schemas/tests/site-family.test.ts +18 -0
  23. package/src/ontology/schemas/tests/system.test.ts +20 -0
  24. package/src/share/agent/tests/api-catalog.test.ts +8 -0
  25. package/src/share/agent/tests/ard-catalog.test.ts +8 -0
  26. package/src/share/agent/tests/capability.test.ts +14 -0
  27. package/src/share/agent/tests/fleet-catalog.test.ts +15 -0
  28. package/src/share/agent/tests/knowledge.test.ts +20 -0
  29. package/src/share/agent/tests/manifest.test.ts +9 -0
  30. package/src/share/agent/tests/mcp-card.test.ts +8 -0
  31. package/src/share/agent/tests/omit-empty.test.ts +33 -0
  32. package/src/share/agent/tests/openapi.test.ts +8 -0
  33. package/src/share/agent/tests/proof.test.ts +15 -0
  34. package/src/share/knowledge/tests/claim.test.ts +11 -0
  35. package/src/share/knowledge/tests/derivation.test.ts +30 -0
  36. package/src/share/knowledge/tests/freshness.test.ts +18 -0
  37. package/src/share/knowledge/tests/ledger.test.ts +35 -0
  38. package/src/share/knowledge/tests/plan.test.ts +19 -0
  39. package/src/share/knowledge/tests/source.test.ts +19 -0
  40. package/src/share/remediation/remediation-catalog.ts +196 -0
  41. package/src/share/schemas/tests/claim-records.test.ts +52 -0
  42. package/src/share/schemas/tests/claims.test.ts +23 -0
  43. package/src/share/schemas/tests/effects.test.ts +116 -0
  44. package/src/share/schemas/tests/features.test.ts +61 -0
  45. package/src/share/schemas/tests/horizontal-align.test.ts +16 -0
  46. package/src/share/schemas/tests/icon-color.test.ts +16 -0
  47. package/src/share/schemas/tests/live-photo.test.ts +40 -0
  48. package/src/share/schemas/tests/material-credit.test.ts +51 -0
  49. package/src/share/schemas/tests/media.test.ts +26 -0
  50. package/src/share/schemas/tests/navigation.test.ts +58 -0
  51. package/src/share/schemas/tests/page-base.test.ts +19 -0
  52. package/src/share/schemas/tests/participant.test.ts +26 -0
  53. package/src/share/schemas/tests/person.test.ts +12 -0
  54. package/src/share/schemas/tests/print.test.ts +30 -0
  55. package/src/share/schemas/tests/section-background.test.ts +31 -0
  56. package/src/share/schemas/tests/section-body.test.ts +16 -0
  57. package/src/share/schemas/tests/section-cards.test.ts +17 -0
  58. package/src/share/schemas/tests/section-cta.test.ts +41 -0
  59. package/src/share/schemas/tests/section-header.test.ts +31 -0
  60. package/src/share/schemas/tests/section-image.test.ts +24 -0
  61. package/src/share/schemas/tests/section-motion.test.ts +29 -0
  62. package/src/share/schemas/tests/section-shell.test.ts +42 -0
  63. package/src/share/schemas/tests/section-stats.test.ts +17 -0
  64. package/src/share/schemas/tests/site-background.test.ts +33 -0
  65. package/src/share/schemas/tests/standard-list-item.test.ts +16 -0
  66. package/src/share/scripts/tests/external-link-qr.test.ts +8 -0
  67. package/src/share/scripts/tests/external-links.test.ts +25 -0
  68. package/src/share/scripts/tests/gsap-counter.test.ts +8 -0
  69. package/src/share/scripts/tests/gsap-mountain-journey.test.ts +8 -0
  70. package/src/share/scripts/tests/gsap-parallax.test.ts +8 -0
  71. package/src/share/scripts/tests/gsap-reveal.test.ts +8 -0
  72. package/src/share/scripts/tests/gsap-stagger.test.ts +8 -0
  73. package/src/share/scripts/tests/inline-number-animation.test.ts +8 -0
  74. package/src/share/scripts/tests/lenis.test.ts +8 -0
  75. package/src/share/scripts/tests/live-photos.test.ts +8 -0
  76. package/src/share/scripts/tests/lordicon.test.ts +8 -0
  77. package/src/share/scripts/tests/orchestrator.test.ts +8 -0
  78. package/src/share/scripts/tests/scheduler.test.ts +23 -0
  79. package/src/share/semantic/jsonld/tests/article.test.ts +89 -0
  80. package/src/share/semantic/jsonld/tests/breadcrumb.test.ts +62 -0
  81. package/src/share/semantic/jsonld/tests/collection-list.test.ts +39 -0
  82. package/src/share/semantic/jsonld/tests/faq.test.ts +60 -0
  83. package/src/share/semantic/jsonld/tests/initiative.test.ts +56 -0
  84. package/src/share/semantic/jsonld/tests/organization.test.ts +123 -0
  85. package/src/share/semantic/jsonld/tests/person.test.ts +89 -0
  86. package/src/share/semantic/jsonld/tests/service.test.ts +65 -0
  87. package/src/share/semantic/jsonld/tests/shared.test.ts +41 -0
  88. package/src/share/semantic/jsonld/tests/video.test.ts +84 -0
  89. package/src/share/semantic/jsonld/tests/webpage.test.ts +93 -0
  90. package/src/share/semantic/jsonld/tests/website.test.ts +27 -0
  91. package/src/share/semantic/jsonld/types.ts +1 -0
  92. package/src/share/semantic/models.ts +1 -0
  93. package/src/share/semantic/tests/ai.test.ts +55 -0
  94. package/src/share/semantic/tests/block-extraction.test.ts +34 -0
  95. package/src/share/semantic/tests/breadcrumbs.test.ts +127 -0
  96. package/src/share/semantic/tests/build-page.test.ts +122 -0
  97. package/src/share/semantic/tests/business-projection.test.ts +188 -0
  98. package/src/share/semantic/tests/derived-prices-loader.test.ts +46 -0
  99. package/src/share/semantic/tests/extract.test.ts +126 -0
  100. package/src/share/semantic/tests/feed.test.ts +113 -0
  101. package/src/share/semantic/tests/helpers.ts +32 -0
  102. package/src/share/semantic/tests/ids.test.ts +118 -0
  103. package/src/share/semantic/tests/image-sitemap.test.ts +109 -0
  104. package/src/share/semantic/tests/jsonld.test.ts +61 -0
  105. package/src/share/semantic/tests/llms-policy.test.ts +60 -0
  106. package/src/share/semantic/tests/llms.test.ts +118 -0
  107. package/src/share/semantic/tests/markdown-hygiene.test.ts +72 -0
  108. package/src/share/semantic/tests/markdown-page.test.ts +97 -0
  109. package/src/share/semantic/tests/markdown-twin-provenance.test.ts +152 -0
  110. package/src/share/semantic/tests/organization-profile.test.ts +107 -0
  111. package/src/share/semantic/tests/output-projection.test.ts +77 -0
  112. package/src/share/semantic/tests/page-markdown.test.ts +98 -0
  113. package/src/share/semantic/tests/page-utils.test.ts +88 -0
  114. package/src/share/semantic/tests/price-marker-resolver.test.ts +88 -0
  115. package/src/share/semantic/tests/robots.test.ts +70 -0
  116. package/src/share/semantic/tests/update-stamp.test.ts +102 -0
  117. package/src/share/utility-registry.yaml +14 -0
package/README.md CHANGED
@@ -4,6 +4,8 @@
4
4
 
5
5
  Stack-agnostic shared infrastructure extracted from `werkstatt-site` (RFC-0868). Owns checks, integration, ontology, passport, share, and surface domains consumed by both the Werkstatt engine and the site plugin.
6
6
 
7
+ > Engineered at [Warpgogol](https://warpgogol.com) · Released as open source.
8
+
7
9
  ---
8
10
 
9
11
  ## What this package does
@@ -62,36 +64,36 @@ const url = slugUrl("Über uns", "de"); // "ueber-uns"
62
64
 
63
65
  ### Semantic extraction (RFC-0901)
64
66
 
65
- | Export | Purpose |
66
- | --- | --- |
67
+ | Export | Purpose |
68
+ | ------------------------------- | ----------------------------------------------------------- |
67
69
  | `splitSentences(text, locale?)` | Locale-aware sentence boundary detection (`de`, `uk`, `en`) |
68
70
 
69
71
  ### Canonical entity URL (RFC-0910)
70
72
 
71
- | Export | Purpose |
72
- | --- | --- |
73
+ | Export | Purpose |
74
+ | --------------------------- | ----------------------------------------------- |
73
75
  | `canonicalRootUrl(baseUrl)` | Unprefixed root URL for JSON-LD entity identity |
74
76
 
75
77
  ### Placeholder route filtering (RFC-0917)
76
78
 
77
- | Export | Purpose |
78
- | --- | --- |
79
+ | Export | Purpose |
80
+ | ------------------------------ | ------------------------------------------------------------ |
79
81
  | `hasPlaceholderRoutes(routes)` | Detect Astro dynamic route templates (`[slug]`, `[version]`) |
80
82
 
81
83
  ---
82
84
 
83
85
  ## Architecture
84
86
 
85
- | Directory | Purpose |
86
- | --- | --- |
87
- | `src/index.ts` | Main barrel export |
88
- | `src/checks/` | Content validators, SEO validators, surface expand/bake |
89
- | `src/integration/` | CRM, funnel, hub, sharding, QStash adapters |
90
- | `src/ontology/` | Catalogs, enums, Sternsystem owner types |
91
- | `src/passport/` | DHT signing, identity signing, schema validation |
92
- | `src/share/` | Slug, semantic, URL canonicalization, routes, middleware, access protection |
93
- | `src/surface/` | Surface expand/bake helpers and labels |
94
- | `src/content/` | SystemManifest types and content schema |
87
+ | Directory | Purpose |
88
+ | ------------------ | --------------------------------------------------------------------------- |
89
+ | `src/index.ts` | Main barrel export |
90
+ | `src/checks/` | Content validators, SEO validators, surface expand/bake |
91
+ | `src/integration/` | CRM, funnel, hub, sharding, QStash adapters |
92
+ | `src/ontology/` | Catalogs, enums, Sternsystem owner types |
93
+ | `src/passport/` | DHT signing, identity signing, schema validation |
94
+ | `src/share/` | Slug, semantic, URL canonicalization, routes, middleware, access protection |
95
+ | `src/surface/` | Surface expand/bake helpers and labels |
96
+ | `src/content/` | SystemManifest types and content schema |
95
97
 
96
98
  ---
97
99
 
@@ -133,3 +135,11 @@ After CI completes, verify the new version on [npmjs.com/package/@warpgogol/werk
133
135
  ## License
134
136
 
135
137
  Apache-2.0
138
+
139
+ ## Open Engineering
140
+
141
+ This package originated from production engineering work at [Warpgogol](https://warpgogol.com), an engineering studio in Germany.
142
+
143
+ We publish reusable parts of our infrastructure when they can be useful beyond our own projects. It is published independently of any Warpgogol commercial service. Using this package does not create any dependency on Warpgogol.
144
+
145
+ Built for real systems. Shared openly.
package/README.uk.md CHANGED
@@ -4,6 +4,8 @@
4
4
 
5
5
  Спільна інфраструктура, незалежна від стеку, витягнута з `werkstatt-site` (RFC-0868). Володіє доменами checks, integration, ontology, passport, share та surface, які споживають рушій Werkstatt та site-плагін.
6
6
 
7
+ > Розроблено в [Warpgogol](https://warpgogol.com) · Опубліковано як open source.
8
+
7
9
  ---
8
10
 
9
11
  ## Що робить цей пакет
@@ -62,14 +64,14 @@ const url = slugUrl("Über uns", "de"); // "ueber-uns"
62
64
 
63
65
  ### Семантична екстракція (RFC-0901)
64
66
 
65
- | Експорт | Призначення |
66
- | --- | --- |
67
+ | Експорт | Призначення |
68
+ | ------------------------------- | ---------------------------------------------------- |
67
69
  | `splitSentences(text, locale?)` | Локалізоване виявлення меж речень (`de`, `uk`, `en`) |
68
70
 
69
71
  ### Канонічний URL сутності (RFC-0910)
70
72
 
71
- | Експорт | Призначення |
72
- | --- | --- |
73
+ | Експорт | Призначення |
74
+ | --------------------------- | --------------------------------------------------------------- |
73
75
  | `canonicalRootUrl(baseUrl)` | Непрефіксований кореневий URL для JSON-LD ідентичності сутності |
74
76
 
75
77
  ### Фільтрація плейсхолдер-маршрутів (RFC-0917)
@@ -82,16 +84,16 @@ const url = slugUrl("Über uns", "de"); // "ueber-uns"
82
84
 
83
85
  ## Архітектура
84
86
 
85
- | Директорія | Призначення |
86
- | --- | --- |
87
- | `src/index.ts` | Головний barrel-експорт |
88
- | `src/checks/` | Валідатори контенту, SEO-валідатори, surface expand/bake |
89
- | `src/integration/` | Адаптери CRM, funnel, hub, sharding, QStash |
90
- | `src/ontology/` | Каталоги, enum-и, типи Sternsystem owner |
91
- | `src/passport/` | DHT-підписування, підписування ідентичності, валідація схем |
92
- | `src/share/` | Slug, семантика, канонізація URL, маршрути, middleware, захист доступу |
93
- | `src/surface/` | Хелпери surface expand/bake та мітки |
94
- | `src/content/` | Типи SystemManifest та схема контенту |
87
+ | Директорія | Призначення |
88
+ | ------------------ | ---------------------------------------------------------------------- |
89
+ | `src/index.ts` | Головний barrel-експорт |
90
+ | `src/checks/` | Валідатори контенту, SEO-валідатори, surface expand/bake |
91
+ | `src/integration/` | Адаптери CRM, funnel, hub, sharding, QStash |
92
+ | `src/ontology/` | Каталоги, enum-и, типи Sternsystem owner |
93
+ | `src/passport/` | DHT-підписування, підписування ідентичності, валідація схем |
94
+ | `src/share/` | Slug, семантика, канонізація URL, маршрути, middleware, захист доступу |
95
+ | `src/surface/` | Хелпери surface expand/bake та мітки |
96
+ | `src/content/` | Типи SystemManifest та схема контенту |
95
97
 
96
98
  ---
97
99
 
@@ -133,3 +135,11 @@ pnpm exec repo-extract --config packages/werkstatt-shared/extract.config.yaml --
133
135
  ## Ліцензія
134
136
 
135
137
  Apache-2.0
138
+
139
+ ## Відкрита інженерія
140
+
141
+ Цей пакет походить із виробничої інженерної роботи в [Warpgogol](https://warpgogol.com), інженерній студії в Німеччині.
142
+
143
+ Ми публікуємо багаторазові частини нашої інфраструктури, коли вони можуть бути корисними поза нашими власними проєктами. Він публікується незалежно від будь-якого комерційного сервісу Warpgogol. Використання цього пакету не створює жодної залежності від Warpgogol.
144
+
145
+ Створено для реальних систем. Поширюється відкрито.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@warpgogol/werkstatt-shared",
3
- "version": "0.14.0",
3
+ "version": "0.14.1",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "engines": {
@@ -262,6 +262,10 @@
262
262
  "types": "./src/share/redirects.ts",
263
263
  "default": "./src/share/redirects.ts"
264
264
  },
265
+ "./share/remediation": {
266
+ "types": "./src/share/remediation/remediation-catalog.ts",
267
+ "default": "./src/share/remediation/remediation-catalog.ts"
268
+ },
265
269
  "./share/rfc0042-utils": {
266
270
  "types": "./src/share/rfc0042-utils.ts",
267
271
  "default": "./src/share/rfc0042-utils.ts"
@@ -1309,6 +1313,7 @@
1309
1313
  "build": "pnpm exec tsc -p tsconfig.json --noEmit",
1310
1314
  "build:check": "pnpm exec tsc -p tsconfig.json --noEmit",
1311
1315
  "test": "vitest run",
1316
+ "test:coverage": "vitest run --coverage",
1312
1317
  "test:watch": "vitest"
1313
1318
  },
1314
1319
  "publishConfig": {
@@ -1350,6 +1355,7 @@
1350
1355
  "gsap": "^3.15.0",
1351
1356
  "typescript": "^6.0.3",
1352
1357
  "typescript-eslint": "8.68.0",
1358
+ "@vitest/coverage-v8": "^4.1.11",
1353
1359
  "vitest": "^4.1.11"
1354
1360
  },
1355
1361
  "packageManager": "pnpm@11.10.0"
@@ -13,6 +13,7 @@ ruleId = command; diagnosticsResult takes rich Diagnostic[] with registered ids.
13
13
  </MODULE_CONTRACT>
14
14
  <CHANGE_SUMMARY>
15
15
  <item>RFC-0029 review: Initial creation to fix systemic exit-code bug across check files.</item>
16
+ <item>RFC-1027: Auto-populate Diagnostic.remediation from REMEDIATION_CATALOG in diagnosticsResult().</item>
16
17
  </CHANGE_SUMMARY>
17
18
  */
18
19
 
@@ -22,6 +23,7 @@ import type {
22
23
  KernelCommandResult,
23
24
  KernelNextStep,
24
25
  } from "@warpgogol/werkstatt-engine/kernel";
26
+ import { lookupRemediation } from "../share/remediation/remediation-catalog.ts";
25
27
 
26
28
  function defaultFailNextSteps(command: string): KernelNextStep[] {
27
29
  return [
@@ -66,10 +68,25 @@ export function diagnosticsResult(
66
68
  diagnostics: Diagnostic[],
67
69
  nextSteps?: KernelNextStep[],
68
70
  ): KernelCommandResult<CheckResult> {
71
+ const enrichedDiagnostics = diagnostics.map((d) => {
72
+ if (d.remediation) return d;
73
+ const pattern = lookupRemediation(d.ruleId);
74
+ if (!pattern) return d;
75
+ return {
76
+ ...d,
77
+ remediation: {
78
+ ruleId: pattern.ruleId,
79
+ action: pattern.action,
80
+ ...(pattern.template !== undefined && { template: pattern.template }),
81
+ ...(pattern.docRef !== undefined && { docRef: pattern.docRef }),
82
+ ...(pattern.targetFiles !== undefined && { targetFiles: pattern.targetFiles }),
83
+ },
84
+ };
85
+ });
69
86
  const summary = {
70
- error: diagnostics.filter((d) => d.severity === "error").length,
71
- warning: diagnostics.filter((d) => d.severity === "warning").length,
72
- info: diagnostics.filter((d) => d.severity === "info").length,
87
+ error: enrichedDiagnostics.filter((d) => d.severity === "error").length,
88
+ warning: enrichedDiagnostics.filter((d) => d.severity === "warning").length,
89
+ info: enrichedDiagnostics.filter((d) => d.severity === "info").length,
73
90
  };
74
91
  const status: CheckResult["status"] =
75
92
  summary.error > 0 ? "fail" : summary.warning > 0 ? "warn" : "pass";
@@ -77,7 +94,7 @@ export function diagnosticsResult(
77
94
  nextSteps ?? (summary.error > 0 ? defaultFailNextSteps(command) : undefined);
78
95
  const counts = formatCounts(summary.error, summary.warning);
79
96
  return {
80
- data: { command, status, diagnostics, summary },
97
+ data: { command, status, diagnostics: enrichedDiagnostics, summary },
81
98
  exitCode: summary.error > 0 ? 1 : 0,
82
99
  summary: counts ? `[${command}] ${counts}` : `[${command}]`,
83
100
  nextSteps: resolvedNextSteps,
@@ -0,0 +1,83 @@
1
+ /*
2
+ <MODULE_CONTRACT>
3
+ <purpose>RFC-1027: unit tests for diagnosticsResult() remediation auto-population.</purpose>
4
+ </MODULE_CONTRACT>
5
+ <CHANGE_SUMMARY>
6
+ <item>RFC-1027: initial tests for remediation auto-population from REMEDIATION_CATALOG.</item>
7
+ </CHANGE_SUMMARY>
8
+ */
9
+
10
+ import { test, expect } from "vitest";
11
+ import { diagnosticsResult } from "../result-helpers.ts";
12
+ import type { Diagnostic } from "@warpgogol/werkstatt-engine/kernel";
13
+
14
+ test("diagnosticsResult: auto-populates remediation from catalog for known ruleId", () => {
15
+ const diagnostics: Diagnostic[] = [
16
+ {
17
+ ruleId: "GEN-FILES-01",
18
+ severity: "error",
19
+ message: "Generated file is stale",
20
+ },
21
+ ];
22
+ const result = diagnosticsResult("test.command", diagnostics);
23
+ expect(result.data!.diagnostics[0].remediation).toBeDefined();
24
+ expect(result.data!.diagnostics[0].remediation?.ruleId).toBe("GEN-FILES-01");
25
+ expect(result.data!.diagnostics[0].remediation?.action).toContain("Regenerate");
26
+ expect(result.data!.diagnostics[0].remediation?.docRef).toBe(
27
+ "docs/authoring/generated-files-and-templates.md",
28
+ );
29
+ });
30
+
31
+ test("diagnosticsResult: does not overwrite existing remediation field", () => {
32
+ const diagnostics: Diagnostic[] = [
33
+ {
34
+ ruleId: "GEN-FILES-01",
35
+ severity: "error",
36
+ message: "Stale file",
37
+ remediation: {
38
+ ruleId: "GEN-FILES-01",
39
+ action: "Custom action — do not overwrite",
40
+ },
41
+ },
42
+ ];
43
+ const result = diagnosticsResult("test.command", diagnostics);
44
+ expect(result.data!.diagnostics[0].remediation?.action).toBe("Custom action — do not overwrite");
45
+ });
46
+
47
+ test("diagnosticsResult: no remediation for unknown ruleId", () => {
48
+ const diagnostics: Diagnostic[] = [
49
+ {
50
+ ruleId: "UNKNOWN-RULE-999",
51
+ severity: "warning",
52
+ message: "Some warning",
53
+ },
54
+ ];
55
+ const result = diagnosticsResult("test.command", diagnostics);
56
+ expect(result.data!.diagnostics[0].remediation).toBeUndefined();
57
+ });
58
+
59
+ test("diagnosticsResult: preserves fixHint alongside remediation", () => {
60
+ const diagnostics: Diagnostic[] = [
61
+ {
62
+ ruleId: "GEN-FILES-01",
63
+ severity: "error",
64
+ message: "Stale",
65
+ fixHint: "Run the generator",
66
+ },
67
+ ];
68
+ const result = diagnosticsResult("test.command", diagnostics);
69
+ expect(result.data!.diagnostics[0].fixHint).toBe("Run the generator");
70
+ expect(result.data!.diagnostics[0].remediation).toBeDefined();
71
+ });
72
+
73
+ test("diagnosticsResult: multiple diagnostics get independent remediation", () => {
74
+ const diagnostics: Diagnostic[] = [
75
+ { ruleId: "GEN-FILES-01", severity: "error", message: "err 1" },
76
+ { ruleId: "PARITY-SECTION-COUNT", severity: "error", message: "err 2" },
77
+ { ruleId: "UNKNOWN", severity: "info", message: "info 1" },
78
+ ];
79
+ const result = diagnosticsResult("test.command", diagnostics);
80
+ expect(result.data!.diagnostics[0].remediation?.ruleId).toBe("GEN-FILES-01");
81
+ expect(result.data!.diagnostics[1].remediation?.ruleId).toBe("PARITY-SECTION-COUNT");
82
+ expect(result.data!.diagnostics[2].remediation).toBeUndefined();
83
+ });
@@ -4,5 +4,12 @@ export default defineConfig({
4
4
  test: {
5
5
  environment: "node",
6
6
  include: ["src/**/*.test.ts"],
7
+ coverage: {
8
+ provider: "v8",
9
+ reporter: ["json", "json-summary", "text-summary", "html"],
10
+ reportsDirectory: "../../.coverage/integration",
11
+ include: ["src/integration/**/*.ts"],
12
+ exclude: ["src/integration/**/*.test.ts", "src/integration/**/*.d.ts"],
13
+ },
7
14
  },
8
15
  });
@@ -305,6 +305,25 @@ export const componentManifestSchema = manifestBaseSchema.extend({
305
305
  * Do not use these five names for any other component manifest.
306
306
  */
307
307
  cosmicName: moonNameSchema,
308
+ /**
309
+ * RFC-1023: JSON Schema (draft-07 compatible) describing the shape of
310
+ * resolved content returned by getResolvedComponentContent. This is the
311
+ * flat, merged content (after pageOverride merge), NOT the prose .md
312
+ * frontmatter schema. Used by props.types.generate to emit
313
+ * XxxComponentContent interfaces. Required for content-driven components
314
+ * (those that call getResolvedComponentContent). Optional for structural
315
+ * components that consume no content.
316
+ */
317
+ contentSchema: z.record(z.string(), z.unknown()).optional(),
318
+ /**
319
+ * RFC-1023: JSON Schema (draft-07 compatible) describing the shape of
320
+ * Astro.props accepted by the component — caller-supplied props such as
321
+ * lang, defaultLang, pageOverride, etc. Used by props.types.generate to
322
+ * emit XxxComponentProps interfaces. Distinct from contentSchema: propsSchema
323
+ * describes what the caller passes, contentSchema describes what the
324
+ * component resolves from content files.
325
+ */
326
+ propsSchema: z.record(z.string(), z.unknown()).optional(),
308
327
  });
309
328
 
310
329
  /**
@@ -0,0 +1,22 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { systemGrowthSchema, growthVendorSchema } from "../growth.ts";
3
+
4
+ describe("growthVendorSchema", () => {
5
+ it("is defined", () => {
6
+ expect(growthVendorSchema).toBeDefined();
7
+ });
8
+
9
+ it("rejects null", () => {
10
+ expect(() => growthVendorSchema.parse(null)).toThrow();
11
+ });
12
+ });
13
+
14
+ describe("systemGrowthSchema", () => {
15
+ it("is defined", () => {
16
+ expect(systemGrowthSchema).toBeDefined();
17
+ });
18
+
19
+ it("rejects null", () => {
20
+ expect(() => systemGrowthSchema.parse(null)).toThrow();
21
+ });
22
+ });
@@ -0,0 +1,12 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { systemIntegrationsSchema } from "../integrations.ts";
3
+
4
+ describe("systemIntegrationsSchema", () => {
5
+ it("is defined", () => {
6
+ expect(systemIntegrationsSchema).toBeDefined();
7
+ });
8
+
9
+ it("rejects null", () => {
10
+ expect(() => systemIntegrationsSchema.parse(null)).toThrow();
11
+ });
12
+ });
@@ -0,0 +1,22 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { systemManifestSchema, systemCollectionSchema } from "../manifest.ts";
3
+
4
+ describe("systemManifestSchema", () => {
5
+ it("is defined", () => {
6
+ expect(systemManifestSchema).toBeDefined();
7
+ });
8
+
9
+ it("rejects null", () => {
10
+ expect(() => systemManifestSchema.parse(null)).toThrow();
11
+ });
12
+ });
13
+
14
+ describe("systemCollectionSchema", () => {
15
+ it("is defined", () => {
16
+ expect(systemCollectionSchema).toBeDefined();
17
+ });
18
+
19
+ it("rejects null", () => {
20
+ expect(() => systemCollectionSchema.parse(null)).toThrow();
21
+ });
22
+ });
@@ -0,0 +1,13 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { semanticPageTypeSchema } from "../page-output.ts";
3
+
4
+ describe("semanticPageTypeSchema", () => {
5
+ it("accepts valid page types", () => {
6
+ const result = semanticPageTypeSchema.safeParse("home");
7
+ expect(result.success).toBe(true);
8
+ });
9
+
10
+ it("rejects invalid page type", () => {
11
+ expect(() => semanticPageTypeSchema.parse("invalid-type")).toThrow();
12
+ });
13
+ });
@@ -0,0 +1,22 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { systemPassportSchema, systemReleaseSchema } from "../release.ts";
3
+
4
+ describe("systemPassportSchema", () => {
5
+ it("is defined", () => {
6
+ expect(systemPassportSchema).toBeDefined();
7
+ });
8
+
9
+ it("rejects null", () => {
10
+ expect(() => systemPassportSchema.parse(null)).toThrow();
11
+ });
12
+ });
13
+
14
+ describe("systemReleaseSchema", () => {
15
+ it("is defined", () => {
16
+ expect(systemReleaseSchema).toBeDefined();
17
+ });
18
+
19
+ it("rejects null", () => {
20
+ expect(() => systemReleaseSchema.parse(null)).toThrow();
21
+ });
22
+ });
@@ -0,0 +1,18 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { systemTextSchema, systemTextNormalizeSchema } from "../text.ts";
3
+
4
+ describe("systemTextSchema", () => {
5
+ it("is defined", () => {
6
+ expect(systemTextSchema).toBeDefined();
7
+ });
8
+
9
+ it("rejects null", () => {
10
+ expect(() => systemTextSchema.parse(null)).toThrow();
11
+ });
12
+ });
13
+
14
+ describe("systemTextNormalizeSchema", () => {
15
+ it("is defined", () => {
16
+ expect(systemTextNormalizeSchema).toBeDefined();
17
+ });
18
+ });
@@ -0,0 +1,12 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { systemVerificationSchema } from "../verification.ts";
3
+
4
+ describe("systemVerificationSchema", () => {
5
+ it("is defined", () => {
6
+ expect(systemVerificationSchema).toBeDefined();
7
+ });
8
+
9
+ it("rejects null", () => {
10
+ expect(() => systemVerificationSchema.parse(null)).toThrow();
11
+ });
12
+ });
@@ -0,0 +1,19 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { biomeProvenanceSchema, biomeAxesSchema } from "../biome.ts";
3
+
4
+ describe("biomeProvenanceSchema", () => {
5
+ it("is defined", () => {
6
+ expect(biomeProvenanceSchema).toBeDefined();
7
+ });
8
+
9
+ it("rejects null", () => {
10
+ expect(() => biomeProvenanceSchema.parse(null)).toThrow();
11
+ });
12
+ });
13
+
14
+ describe("biomeAxesSchema", () => {
15
+ it("is defined and parseable", () => {
16
+ expect(biomeAxesSchema).toBeDefined();
17
+ expect(() => biomeAxesSchema.parse(null)).toThrow();
18
+ });
19
+ });
@@ -0,0 +1,22 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { capabilityInputOutputSchema, capabilityRecordSchema } from "../capability.ts";
3
+
4
+ describe("capabilityInputOutputSchema", () => {
5
+ it("is defined", () => {
6
+ expect(capabilityInputOutputSchema).toBeDefined();
7
+ });
8
+
9
+ it("rejects null", () => {
10
+ expect(() => capabilityInputOutputSchema.parse(null)).toThrow();
11
+ });
12
+ });
13
+
14
+ describe("capabilityRecordSchema", () => {
15
+ it("is defined", () => {
16
+ expect(capabilityRecordSchema).toBeDefined();
17
+ });
18
+
19
+ it("rejects null", () => {
20
+ expect(() => capabilityRecordSchema.parse(null)).toThrow();
21
+ });
22
+ });
@@ -0,0 +1,22 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { constellationSlotSchema, constellationSchema } from "../constellation.ts";
3
+
4
+ describe("constellationSlotSchema", () => {
5
+ it("is defined", () => {
6
+ expect(constellationSlotSchema).toBeDefined();
7
+ });
8
+
9
+ it("rejects null", () => {
10
+ expect(() => constellationSlotSchema.parse(null)).toThrow();
11
+ });
12
+ });
13
+
14
+ describe("constellationSchema", () => {
15
+ it("is defined", () => {
16
+ expect(constellationSchema).toBeDefined();
17
+ });
18
+
19
+ it("rejects null", () => {
20
+ expect(() => constellationSchema.parse(null)).toThrow();
21
+ });
22
+ });
@@ -0,0 +1,13 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { dnsRecordTypeSchema } from "../dns-records.ts";
3
+
4
+ describe("dnsRecordTypeSchema", () => {
5
+ it("accepts valid DNS record types", () => {
6
+ const result = dnsRecordTypeSchema.safeParse("A");
7
+ expect(result.success).toBe(true);
8
+ });
9
+
10
+ it("rejects invalid type", () => {
11
+ expect(() => dnsRecordTypeSchema.parse("INVALID")).toThrow();
12
+ });
13
+ });
@@ -0,0 +1,13 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { getSectionPropsSchema } from "../manifest-resolver.ts";
3
+
4
+ describe("getSectionPropsSchema", () => {
5
+ it("is an async function", () => {
6
+ expect(typeof getSectionPropsSchema).toBe("function");
7
+ });
8
+
9
+ it("returns null for unknown archetype", async () => {
10
+ const result = await getSectionPropsSchema("nonexistent-archetype", "/nonexistent");
11
+ expect(result).toBeNull();
12
+ });
13
+ });
@@ -0,0 +1,22 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { BlockEntrySchema, PageEntrySchema } from "../page-entry.ts";
3
+
4
+ describe("BlockEntrySchema", () => {
5
+ it("is defined", () => {
6
+ expect(BlockEntrySchema).toBeDefined();
7
+ });
8
+
9
+ it("rejects null", () => {
10
+ expect(() => BlockEntrySchema.parse(null)).toThrow();
11
+ });
12
+ });
13
+
14
+ describe("PageEntrySchema", () => {
15
+ it("is defined", () => {
16
+ expect(PageEntrySchema).toBeDefined();
17
+ });
18
+
19
+ it("rejects null", () => {
20
+ expect(() => PageEntrySchema.parse(null)).toThrow();
21
+ });
22
+ });
@@ -0,0 +1,12 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { sectionArchetypeSchema } from "../section-archetype.ts";
3
+
4
+ describe("sectionArchetypeSchema", () => {
5
+ it("is defined", () => {
6
+ expect(sectionArchetypeSchema).toBeDefined();
7
+ });
8
+
9
+ it("rejects null", () => {
10
+ expect(() => sectionArchetypeSchema.parse(null)).toThrow();
11
+ });
12
+ });
@@ -0,0 +1,18 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { siteFamilySchema, SiteFamilyContract } from "../site-family.ts";
3
+
4
+ describe("siteFamilySchema", () => {
5
+ it("is defined", () => {
6
+ expect(siteFamilySchema).toBeDefined();
7
+ });
8
+
9
+ it("rejects null", () => {
10
+ expect(() => siteFamilySchema.parse(null)).toThrow();
11
+ });
12
+ });
13
+
14
+ describe("SiteFamilyContract", () => {
15
+ it("is the same schema as siteFamilySchema", () => {
16
+ expect(SiteFamilyContract).toBe(siteFamilySchema);
17
+ });
18
+ });
@@ -0,0 +1,20 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import * as systemModule from "../system.ts";
3
+
4
+ describe("system.ts barrel re-exports", () => {
5
+ it("re-exports systemManifestSchema", () => {
6
+ expect(systemModule.systemManifestSchema).toBeDefined();
7
+ });
8
+
9
+ it("re-exports systemIntegrationsSchema", () => {
10
+ expect(systemModule.systemIntegrationsSchema).toBeDefined();
11
+ });
12
+
13
+ it("re-exports systemPassportSchema", () => {
14
+ expect(systemModule.systemPassportSchema).toBeDefined();
15
+ });
16
+
17
+ it("re-exports systemReleaseSchema", () => {
18
+ expect(systemModule.systemReleaseSchema).toBeDefined();
19
+ });
20
+ });