reflection-check 0.0.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 (133) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +55 -0
  3. package/dist/adapters/route-manifest.d.ts +3 -0
  4. package/dist/adapters/route-manifest.js +98 -0
  5. package/dist/adapters/route-manifest.js.map +1 -0
  6. package/dist/cli.d.ts +3 -0
  7. package/dist/cli.js +93 -0
  8. package/dist/cli.js.map +1 -0
  9. package/dist/commands/doctor.d.ts +4 -0
  10. package/dist/commands/doctor.js +5 -0
  11. package/dist/commands/doctor.js.map +1 -0
  12. package/dist/commands/gc.d.ts +8 -0
  13. package/dist/commands/gc.js +45 -0
  14. package/dist/commands/gc.js.map +1 -0
  15. package/dist/commands/review.d.ts +7 -0
  16. package/dist/commands/review.js +149 -0
  17. package/dist/commands/review.js.map +1 -0
  18. package/dist/commands/run.d.ts +10 -0
  19. package/dist/commands/run.js +168 -0
  20. package/dist/commands/run.js.map +1 -0
  21. package/dist/commands/update.d.ts +11 -0
  22. package/dist/commands/update.js +183 -0
  23. package/dist/commands/update.js.map +1 -0
  24. package/dist/contracts/browser/assertions.d.ts +34 -0
  25. package/dist/contracts/browser/assertions.js +87 -0
  26. package/dist/contracts/browser/assertions.js.map +1 -0
  27. package/dist/contracts/browser/browser-contract.d.ts +13 -0
  28. package/dist/contracts/browser/browser-contract.js +35 -0
  29. package/dist/contracts/browser/browser-contract.js.map +1 -0
  30. package/dist/contracts/browser/console-observer.d.ts +6 -0
  31. package/dist/contracts/browser/console-observer.js +14 -0
  32. package/dist/contracts/browser/console-observer.js.map +1 -0
  33. package/dist/contracts/browser/overflow-check.d.ts +6 -0
  34. package/dist/contracts/browser/overflow-check.js +15 -0
  35. package/dist/contracts/browser/overflow-check.js.map +1 -0
  36. package/dist/contracts/browser/route-runner.d.ts +21 -0
  37. package/dist/contracts/browser/route-runner.js +98 -0
  38. package/dist/contracts/browser/route-runner.js.map +1 -0
  39. package/dist/contracts/component/component-visual-contract.d.ts +30 -0
  40. package/dist/contracts/component/component-visual-contract.js +147 -0
  41. package/dist/contracts/component/component-visual-contract.js.map +1 -0
  42. package/dist/contracts/design/command-adapter.d.ts +17 -0
  43. package/dist/contracts/design/command-adapter.js +60 -0
  44. package/dist/contracts/design/command-adapter.js.map +1 -0
  45. package/dist/contracts/design/design-contract.d.ts +8 -0
  46. package/dist/contracts/design/design-contract.js +149 -0
  47. package/dist/contracts/design/design-contract.js.map +1 -0
  48. package/dist/contracts/visual/baseline-compare.d.ts +19 -0
  49. package/dist/contracts/visual/baseline-compare.js +94 -0
  50. package/dist/contracts/visual/baseline-compare.js.map +1 -0
  51. package/dist/contracts/visual/image-diff.d.ts +27 -0
  52. package/dist/contracts/visual/image-diff.js +58 -0
  53. package/dist/contracts/visual/image-diff.js.map +1 -0
  54. package/dist/contracts/visual/thresholds.d.ts +15 -0
  55. package/dist/contracts/visual/thresholds.js +11 -0
  56. package/dist/contracts/visual/thresholds.js.map +1 -0
  57. package/dist/contracts/visual/visual-contract.d.ts +11 -0
  58. package/dist/contracts/visual/visual-contract.js +32 -0
  59. package/dist/contracts/visual/visual-contract.js.map +1 -0
  60. package/dist/core/artifact-store.d.ts +18 -0
  61. package/dist/core/artifact-store.js +105 -0
  62. package/dist/core/artifact-store.js.map +1 -0
  63. package/dist/core/baseline-store.d.ts +18 -0
  64. package/dist/core/baseline-store.js +56 -0
  65. package/dist/core/baseline-store.js.map +1 -0
  66. package/dist/core/config.d.ts +129 -0
  67. package/dist/core/config.js +159 -0
  68. package/dist/core/config.js.map +1 -0
  69. package/dist/core/define-reflection.d.ts +2 -0
  70. package/dist/core/define-reflection.js +4 -0
  71. package/dist/core/define-reflection.js.map +1 -0
  72. package/dist/core/exit-codes.d.ts +7 -0
  73. package/dist/core/exit-codes.js +9 -0
  74. package/dist/core/exit-codes.js.map +1 -0
  75. package/dist/core/failure-classifier.d.ts +3 -0
  76. package/dist/core/failure-classifier.js +19 -0
  77. package/dist/core/failure-classifier.js.map +1 -0
  78. package/dist/core/gc.d.ts +19 -0
  79. package/dist/core/gc.js +161 -0
  80. package/dist/core/gc.js.map +1 -0
  81. package/dist/core/manifest.d.ts +23 -0
  82. package/dist/core/manifest.js +21 -0
  83. package/dist/core/manifest.js.map +1 -0
  84. package/dist/core/redaction.d.ts +3 -0
  85. package/dist/core/redaction.js +63 -0
  86. package/dist/core/redaction.js.map +1 -0
  87. package/dist/core/report-schema.d.ts +262 -0
  88. package/dist/core/report-schema.js +112 -0
  89. package/dist/core/report-schema.js.map +1 -0
  90. package/dist/core/report-writer.d.ts +4 -0
  91. package/dist/core/report-writer.js +77 -0
  92. package/dist/core/report-writer.js.map +1 -0
  93. package/dist/core/server-manager.d.ts +23 -0
  94. package/dist/core/server-manager.js +64 -0
  95. package/dist/core/server-manager.js.map +1 -0
  96. package/dist/core/target-ir.d.ts +64 -0
  97. package/dist/core/target-ir.js +85 -0
  98. package/dist/core/target-ir.js.map +1 -0
  99. package/dist/index.d.ts +2 -0
  100. package/dist/index.js +2 -0
  101. package/dist/index.js.map +1 -0
  102. package/dist/integrations/playwright/browser-manager.d.ts +2 -0
  103. package/dist/integrations/playwright/browser-manager.js +5 -0
  104. package/dist/integrations/playwright/browser-manager.js.map +1 -0
  105. package/dist/integrations/playwright/context-factory.d.ts +7 -0
  106. package/dist/integrations/playwright/context-factory.js +19 -0
  107. package/dist/integrations/playwright/context-factory.js.map +1 -0
  108. package/dist/integrations/playwright/trace-policy.d.ts +5 -0
  109. package/dist/integrations/playwright/trace-policy.js +7 -0
  110. package/dist/integrations/playwright/trace-policy.js.map +1 -0
  111. package/dist/integrations/storybook/index-json.d.ts +21 -0
  112. package/dist/integrations/storybook/index-json.js +44 -0
  113. package/dist/integrations/storybook/index-json.js.map +1 -0
  114. package/dist/integrations/storybook/server.d.ts +8 -0
  115. package/dist/integrations/storybook/server.js +23 -0
  116. package/dist/integrations/storybook/server.js.map +1 -0
  117. package/dist/integrations/storybook/story-url.d.ts +2 -0
  118. package/dist/integrations/storybook/story-url.js +13 -0
  119. package/dist/integrations/storybook/story-url.js.map +1 -0
  120. package/dist/utils/process.d.ts +9 -0
  121. package/dist/utils/process.js +69 -0
  122. package/dist/utils/process.js.map +1 -0
  123. package/docs/agent-workflows.md +146 -0
  124. package/docs/artifacts-and-gc.md +125 -0
  125. package/docs/browser-contract.md +98 -0
  126. package/docs/ci.md +44 -0
  127. package/docs/configuration.md +210 -0
  128. package/docs/getting-started.md +166 -0
  129. package/docs/plans/reflection-implementation-plan.md +898 -0
  130. package/docs/target-ir-and-adapters.md +111 -0
  131. package/docs/validation-process.md +172 -0
  132. package/docs/visual-contract.md +174 -0
  133. package/package.json +62 -0
@@ -0,0 +1,21 @@
1
+ import type { Browser } from 'playwright';
2
+ import type { ArtifactStore } from '../../core/artifact-store.js';
3
+ import type { CheckResult } from '../../core/report-schema.js';
4
+ import { type BrowserExpectation } from './assertions.js';
5
+ export type BrowserRoute = {
6
+ id: string;
7
+ name?: string | undefined;
8
+ path: string;
9
+ viewports: string[];
10
+ expects: BrowserExpectation[];
11
+ };
12
+ export type RouteRunInput = {
13
+ browser: Browser;
14
+ store: ArtifactStore;
15
+ baseUrl: string;
16
+ route: BrowserRoute;
17
+ viewport: string;
18
+ blocking: boolean;
19
+ maskSelectors?: string[];
20
+ };
21
+ export declare function runBrowserRoute(input: RouteRunInput): Promise<CheckResult>;
@@ -0,0 +1,98 @@
1
+ import { createBrowserContext } from '../../integrations/playwright/context-factory.js';
2
+ import { evaluateExpectation, shouldCaptureScreenshot } from './assertions.js';
3
+ import { observeConsoleErrors } from './console-observer.js';
4
+ export async function runBrowserRoute(input) {
5
+ const context = await createBrowserContext(input.browser, input.viewport);
6
+ const page = await context.newPage();
7
+ const consoleObserver = observeConsoleErrors(page);
8
+ const failures = [];
9
+ const artifacts = [];
10
+ const maskSelectors = input.maskSelectors ?? [];
11
+ let maskedSelectors = [];
12
+ try {
13
+ await page.goto(new URL(input.route.path, input.baseUrl).toString(), { waitUntil: 'domcontentloaded' });
14
+ await page.waitForLoadState('networkidle', { timeout: 2_000 }).catch(() => undefined);
15
+ for (const expectation of input.route.expects) {
16
+ const failure = await evaluateExpectation(page, expectation, consoleObserver.errors);
17
+ if (failure) {
18
+ failures.push(failure);
19
+ }
20
+ }
21
+ if (shouldCaptureScreenshot(input.route.expects)) {
22
+ maskedSelectors = await applyMaskSelectors(page, maskSelectors);
23
+ const screenshotPath = `browser/${input.route.id}/${input.viewport}/actual.png`;
24
+ const screenshot = await page.screenshot({ fullPage: true });
25
+ artifacts.push(await input.store.writeBuffer(screenshotPath, screenshot));
26
+ }
27
+ const metadataPath = `browser/${input.route.id}/${input.viewport}/metadata.json`;
28
+ artifacts.push(await input.store.writeJson(metadataPath, {
29
+ route: input.route.path,
30
+ viewport: input.viewport,
31
+ url: page.url(),
32
+ consoleErrors: consoleObserver.errors,
33
+ failures,
34
+ privacyWarning: shouldCaptureScreenshot(input.route.expects) ? 'Screenshots may contain private UI data. Use maskSelectors for sensitive regions.' : undefined,
35
+ maskSelectors,
36
+ maskedSelectors
37
+ }));
38
+ }
39
+ catch (error) {
40
+ failures.push({
41
+ classification: 'route-failure',
42
+ summary: `Route failed to render: ${error instanceof Error ? error.message : String(error)}`
43
+ });
44
+ }
45
+ finally {
46
+ consoleObserver.dispose();
47
+ await context.close();
48
+ }
49
+ const firstFailure = failures[0];
50
+ const status = failures.length > 0 ? 'fail' : 'pass';
51
+ const target = `${input.route.path} ${input.viewport}`;
52
+ return {
53
+ id: `browser.${input.route.id}.${input.viewport}`,
54
+ suite: 'browser',
55
+ target,
56
+ status,
57
+ severity: input.blocking ? 'blocking' : 'review',
58
+ summary: status === 'pass'
59
+ ? `${input.route.name ?? input.route.id} rendered on ${input.viewport}.`
60
+ : firstFailure?.summary ?? `${input.route.name ?? input.route.id} failed on ${input.viewport}.`,
61
+ ...(failures.length > 0 ? { details: failures.map((failure) => failure.details ?? failure.summary).join('\n') } : {}),
62
+ artifacts,
63
+ metadata: {
64
+ route: input.route.path,
65
+ routeId: input.route.id,
66
+ viewport: input.viewport,
67
+ classification: firstFailure?.classification,
68
+ failures,
69
+ ...(shouldCaptureScreenshot(input.route.expects)
70
+ ? {
71
+ privacyWarning: 'Screenshots may contain private UI data. Use maskSelectors for sensitive regions.',
72
+ maskSelectors,
73
+ maskedSelectors
74
+ }
75
+ : {})
76
+ },
77
+ ...(failures.length > 0 ? { suggestedNextStep: 'Inspect screenshot and browser metadata, then fix the rendered UI contract failure.' } : {})
78
+ };
79
+ }
80
+ async function applyMaskSelectors(page, selectors) {
81
+ const applied = [];
82
+ for (const selector of selectors) {
83
+ const count = await page.locator(selector).count().catch(() => 0);
84
+ if (count === 0) {
85
+ continue;
86
+ }
87
+ await page.locator(selector).evaluateAll((elements) => {
88
+ for (const element of elements) {
89
+ const target = element;
90
+ const previousStyle = target.getAttribute('style') ?? '';
91
+ target.setAttribute('style', `${previousStyle}; visibility: hidden !important;`);
92
+ }
93
+ });
94
+ applied.push(selector);
95
+ }
96
+ return applied;
97
+ }
98
+ //# sourceMappingURL=route-runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route-runner.js","sourceRoot":"","sources":["../../../src/contracts/browser/route-runner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import type { ArtifactStore } from '../../core/artifact-store.js';
2
+ import type { CheckResult } from '../../core/report-schema.js';
3
+ import type { ServerConfig } from '../../core/server-manager.js';
4
+ import type { VisualThreshold } from '../visual/thresholds.js';
5
+ export type ComponentVisualCase = {
6
+ id: string;
7
+ storyId: string;
8
+ baseline: string;
9
+ baselineRoot?: string | undefined;
10
+ viewport?: string | undefined;
11
+ threshold?: VisualThreshold | undefined;
12
+ blocking?: boolean | undefined;
13
+ strict?: boolean | undefined;
14
+ stateNote?: string | undefined;
15
+ browserState?: ComponentBrowserState | undefined;
16
+ };
17
+ export type ComponentBrowserState = {
18
+ kind: 'hover' | 'focus';
19
+ selector: string;
20
+ animationStabilization: {
21
+ disableAnimations?: boolean | undefined;
22
+ waitMs?: number | undefined;
23
+ };
24
+ };
25
+ export type ComponentVisualContractConfig = {
26
+ enabled?: boolean | undefined;
27
+ storybook: ServerConfig;
28
+ cases: ComponentVisualCase[];
29
+ };
30
+ export declare function runComponentVisualContract(config: ComponentVisualContractConfig | undefined, store: ArtifactStore): Promise<CheckResult[]>;
@@ -0,0 +1,147 @@
1
+ import { access, mkdir, readFile } from 'node:fs/promises';
2
+ import { dirname } from 'node:path';
3
+ import { createBaselineStore, createMissingBaselineCheck } from '../../core/baseline-store.js';
4
+ import { createBrowserContext } from '../../integrations/playwright/context-factory.js';
5
+ import { launchBrowser } from '../../integrations/playwright/browser-manager.js';
6
+ import { startStorybookServer } from '../../integrations/storybook/server.js';
7
+ import { resolveStoryUrl } from '../../integrations/storybook/story-url.js';
8
+ import { comparePngImages } from '../visual/image-diff.js';
9
+ export async function runComponentVisualContract(config, store) {
10
+ if (!config || config.enabled === false || config.cases.length === 0) {
11
+ return [];
12
+ }
13
+ const storybook = await startStorybookServer(config.storybook, {
14
+ cwd: process.cwd(),
15
+ logPath: store.resolveRunPath('server/storybook.log')
16
+ });
17
+ const browser = await launchBrowser();
18
+ try {
19
+ const checks = [];
20
+ for (const visualCase of config.cases) {
21
+ const storyUrl = resolveStoryUrl(storybook.index, storybook.baseUrl, visualCase.storyId);
22
+ checks.push(await runComponentVisualCase({ visualCase, storyUrl, store, browser }));
23
+ }
24
+ return checks;
25
+ }
26
+ finally {
27
+ await browser.close();
28
+ await storybook.server.stop();
29
+ }
30
+ }
31
+ async function runComponentVisualCase(input) {
32
+ const viewport = input.visualCase.viewport ?? 'component';
33
+ const target = `${input.visualCase.storyId} ${viewport}`;
34
+ const baselinePath = resolveCaseBaselinePath(input.visualCase);
35
+ const blocking = input.visualCase.blocking === true || input.visualCase.strict === true;
36
+ const strict = input.visualCase.strict === true || input.visualCase.blocking === true;
37
+ if (!(await pathExists(baselinePath))) {
38
+ return createMissingBaselineCheck({
39
+ id: `visual.${input.visualCase.id}`,
40
+ target,
41
+ baselinePath: input.visualCase.baseline,
42
+ blocking,
43
+ metadata: createComponentStateMetadata(input.visualCase)
44
+ });
45
+ }
46
+ const artifactBase = `visual/${input.visualCase.id}`;
47
+ const expectedArtifact = await input.store.writeBuffer(`${artifactBase}/expected.png`, await readFile(baselinePath));
48
+ const actualArtifact = await captureComponentScreenshot({
49
+ browser: input.browser,
50
+ store: input.store,
51
+ path: `${artifactBase}/actual.png`,
52
+ storyUrl: input.storyUrl,
53
+ viewport,
54
+ browserState: input.visualCase.browserState
55
+ });
56
+ const diffRelativePath = `${artifactBase}/diff.png`;
57
+ const diffPath = input.store.resolveRunPath(diffRelativePath);
58
+ await mkdir(dirname(diffPath), { recursive: true });
59
+ const result = await comparePngImages({
60
+ expectedPath: baselinePath,
61
+ actualPath: input.store.resolveRunPath(actualArtifact.path),
62
+ diffPath,
63
+ ...(input.visualCase.threshold ? { threshold: input.visualCase.threshold } : {}),
64
+ strict
65
+ });
66
+ const diffArtifact = result.diffPath ? await input.store.describeArtifact(diffRelativePath, 'visual-diff', 'diff') : undefined;
67
+ const severity = result.status === 'fail' && blocking ? 'blocking' : 'review';
68
+ return {
69
+ id: `visual.${input.visualCase.id}`,
70
+ suite: 'visual',
71
+ target,
72
+ status: result.status,
73
+ severity,
74
+ summary: createComponentVisualSummary(input.visualCase.id, result),
75
+ artifacts: [expectedArtifact, actualArtifact, ...(diffArtifact ? [diffArtifact] : [])],
76
+ metadata: {
77
+ ...result,
78
+ storyId: input.visualCase.storyId,
79
+ storyUrl: input.storyUrl,
80
+ viewport,
81
+ baselinePath: input.visualCase.baseline,
82
+ ...createComponentStateMetadata(input.visualCase)
83
+ },
84
+ ...(result.status === 'pass'
85
+ ? {}
86
+ : { suggestedNextStep: 'Inspect expected, actual, and diff artifacts. If intentional, update only this component visual baseline.' })
87
+ };
88
+ }
89
+ async function captureComponentScreenshot(input) {
90
+ const context = await createBrowserContext(input.browser, input.viewport);
91
+ try {
92
+ const page = await context.newPage();
93
+ await page.goto(input.storyUrl, { waitUntil: 'domcontentloaded' });
94
+ await page.waitForLoadState('networkidle', { timeout: 2_000 }).catch(() => undefined);
95
+ if (input.browserState) {
96
+ await applyBrowserState(page, input.browserState);
97
+ }
98
+ return input.store.writeBuffer(input.path, await page.screenshot());
99
+ }
100
+ finally {
101
+ await context.close();
102
+ }
103
+ }
104
+ async function applyBrowserState(page, browserState) {
105
+ if (browserState.animationStabilization.disableAnimations !== false) {
106
+ await page.addStyleTag({ content: '*, *::before, *::after { animation: none !important; transition: none !important; }' });
107
+ }
108
+ if (browserState.kind === 'hover') {
109
+ await page.locator(browserState.selector).hover();
110
+ }
111
+ else {
112
+ await page.locator(browserState.selector).focus();
113
+ }
114
+ if (browserState.animationStabilization.waitMs && browserState.animationStabilization.waitMs > 0) {
115
+ await page.waitForTimeout(browserState.animationStabilization.waitMs);
116
+ }
117
+ }
118
+ function createComponentStateMetadata(visualCase) {
119
+ return {
120
+ statePolicy: visualCase.browserState ? 'browser-forced-with-stabilization' : 'story-controlled',
121
+ ...(visualCase.stateNote ? { stateNote: visualCase.stateNote } : {}),
122
+ ...(visualCase.browserState ? { browserState: visualCase.browserState } : {})
123
+ };
124
+ }
125
+ function resolveCaseBaselinePath(visualCase) {
126
+ const store = createBaselineStore(visualCase.baselineRoot ? { rootDir: visualCase.baselineRoot } : {});
127
+ return store.resolveBaselinePath(visualCase.baseline);
128
+ }
129
+ async function pathExists(path) {
130
+ try {
131
+ await access(path);
132
+ return true;
133
+ }
134
+ catch {
135
+ return false;
136
+ }
137
+ }
138
+ function createComponentVisualSummary(id, result) {
139
+ if (result.classification === 'visual-match') {
140
+ return `${id} matches approved component visual baseline.`;
141
+ }
142
+ if (result.classification === 'visual-dimension-mismatch') {
143
+ return `${id} component screenshot dimensions differ from approved baseline.`;
144
+ }
145
+ return `${id} differs from approved component visual baseline by ${(result.diffRatio * 100).toFixed(2)}% (${result.diffPixels} pixels)${result.thresholdReason ? `, exceeding ${result.thresholdReason}` : ''}.`;
146
+ }
147
+ //# sourceMappingURL=component-visual-contract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"component-visual-contract.js","sourceRoot":"","sources":["../../../src/contracts/component/component-visual-contract.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type { ArtifactStore } from '../../core/artifact-store.js';
2
+ import type { ArtifactRef } from '../../core/report-schema.js';
3
+ export type DesignCommandConfig = {
4
+ id: string;
5
+ command: string;
6
+ cwd?: string | undefined;
7
+ blocking?: boolean | undefined;
8
+ };
9
+ export type DesignCommandResult = {
10
+ command: DesignCommandConfig;
11
+ exitCode: number | null;
12
+ signal: NodeJS.Signals | null;
13
+ stdout: string;
14
+ stderr: string;
15
+ artifact: ArtifactRef;
16
+ };
17
+ export declare function runDesignCommand(command: DesignCommandConfig, store: ArtifactStore): Promise<DesignCommandResult>;
@@ -0,0 +1,60 @@
1
+ import { spawn } from 'node:child_process';
2
+ export async function runDesignCommand(command, store) {
3
+ const result = await executeShellCommand(command);
4
+ const artifact = await store.writeText(`design/${safeArtifactName(command.id)}.log`, renderCommandLog(command, result));
5
+ return {
6
+ command,
7
+ ...result,
8
+ artifact: { ...artifact, type: 'log', role: 'debug' }
9
+ };
10
+ }
11
+ function executeShellCommand(command) {
12
+ return new Promise((resolve) => {
13
+ const child = spawn(command.command, {
14
+ cwd: command.cwd ?? process.cwd(),
15
+ shell: true,
16
+ windowsHide: true,
17
+ stdio: ['ignore', 'pipe', 'pipe']
18
+ });
19
+ const stdout = [];
20
+ const stderr = [];
21
+ child.stdout.on('data', (chunk) => stdout.push(chunk));
22
+ child.stderr.on('data', (chunk) => stderr.push(chunk));
23
+ child.on('close', (exitCode, signal) => {
24
+ resolve({
25
+ exitCode,
26
+ signal,
27
+ stdout: Buffer.concat(stdout).toString('utf8'),
28
+ stderr: Buffer.concat(stderr).toString('utf8')
29
+ });
30
+ });
31
+ child.on('error', (error) => {
32
+ resolve({ exitCode: 1, signal: null, stdout: '', stderr: error.message });
33
+ });
34
+ });
35
+ }
36
+ function renderCommandLog(command, result) {
37
+ return [
38
+ `# Reflection design command log`,
39
+ ``,
40
+ `Command: ${command.command}`,
41
+ `CWD: ${command.cwd ?? process.cwd()}`,
42
+ `Exit code: ${result.exitCode ?? 'signal'}`,
43
+ result.signal ? `Signal: ${result.signal}` : undefined,
44
+ ``,
45
+ `## stdout`,
46
+ ``,
47
+ result.stdout || '(empty)',
48
+ ``,
49
+ `## stderr`,
50
+ ``,
51
+ result.stderr || '(empty)',
52
+ ``
53
+ ]
54
+ .filter((line) => line !== undefined)
55
+ .join('\n');
56
+ }
57
+ function safeArtifactName(id) {
58
+ return id.replace(/[^a-zA-Z0-9._-]+/g, '-').replace(/^-+|-+$/g, '') || 'command';
59
+ }
60
+ //# sourceMappingURL=command-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-adapter.js","sourceRoot":"","sources":["../../../src/contracts/design/command-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAoB3C,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,OAA4B,EAAE,KAAoB;IACvF,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,OAAO,CAAC,CAAC;IAClD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,SAAS,CAAC,UAAU,gBAAgB,CAAC,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;IAExH,OAAO;QACL,OAAO;QACP,GAAG,MAAM;QACT,QAAQ,EAAE,EAAE,GAAG,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE;KACtD,CAAC;AACJ,CAAC;AASD,SAAS,mBAAmB,CAAC,OAA4B;IACvD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE;YACnC,GAAG,EAAE,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE;YACjC,KAAK,EAAE,IAAI;YACX,WAAW,EAAE,IAAI;YACjB,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;SAClC,CAAC,CAAC;QACH,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,MAAM,MAAM,GAAa,EAAE,CAAC;QAE5B,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QAC/D,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QAC/D,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE;YACrC,OAAO,CAAC;gBACN,QAAQ;gBACR,MAAM;gBACN,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC;gBAC9C,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC;aAC/C,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QACH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;YAC1B,OAAO,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QAC5E,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,gBAAgB,CAAC,OAA4B,EAAE,MAAmB;IACzE,OAAO;QACL,iCAAiC;QACjC,EAAE;QACF,YAAY,OAAO,CAAC,OAAO,EAAE;QAC7B,QAAQ,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,EAAE;QACtC,cAAc,MAAM,CAAC,QAAQ,IAAI,QAAQ,EAAE;QAC3C,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,SAAS;QACtD,EAAE;QACF,WAAW;QACX,EAAE;QACF,MAAM,CAAC,MAAM,IAAI,SAAS;QAC1B,EAAE;QACF,WAAW;QACX,EAAE;QACF,MAAM,CAAC,MAAM,IAAI,SAAS;QAC1B,EAAE;KACH;SACE,MAAM,CAAC,CAAC,IAAI,EAAkB,EAAE,CAAC,IAAI,KAAK,SAAS,CAAC;SACpD,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC;AAED,SAAS,gBAAgB,CAAC,EAAU;IAClC,OAAO,EAAE,CAAC,OAAO,CAAC,mBAAmB,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,IAAI,SAAS,CAAC;AACnF,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { ArtifactStore } from '../../core/artifact-store.js';
2
+ import { type CheckResult } from '../../core/report-schema.js';
3
+ import { type DesignCommandConfig } from './command-adapter.js';
4
+ export type DesignContractConfig = {
5
+ enabled?: boolean | undefined;
6
+ commands?: DesignCommandConfig[] | undefined;
7
+ };
8
+ export declare function runDesignContract(config: DesignContractConfig | undefined, store: ArtifactStore): Promise<CheckResult[]>;
@@ -0,0 +1,149 @@
1
+ import { CheckSeveritySchema, CheckStatusSchema } from '../../core/report-schema.js';
2
+ import { runDesignCommand } from './command-adapter.js';
3
+ import { z } from 'zod';
4
+ export async function runDesignContract(config, store) {
5
+ if (!config || config.enabled === false) {
6
+ return [];
7
+ }
8
+ const commands = config.commands ?? [];
9
+ const checks = [];
10
+ for (const command of commands) {
11
+ const result = await runDesignCommand(command, store);
12
+ checks.push(...normalizeDesignCommandResult(result));
13
+ }
14
+ return checks;
15
+ }
16
+ const StructuredDesignCheckSchema = z.object({
17
+ id: z.string().min(1),
18
+ family: z.string().min(1).optional(),
19
+ target: z.string().min(1),
20
+ status: CheckStatusSchema,
21
+ severity: CheckSeveritySchema.optional(),
22
+ summary: z.string().min(1),
23
+ details: z.string().optional(),
24
+ metadata: z.record(z.string(), z.unknown()).optional()
25
+ });
26
+ const StructuredDesignOutputSchema = z.object({
27
+ reflection: z.literal('design-checks-v1'),
28
+ checks: z.array(StructuredDesignCheckSchema).min(1)
29
+ });
30
+ function normalizeDesignCommandResult(result) {
31
+ const structured = parseStructuredDesignOutput(result.stdout);
32
+ if (structured) {
33
+ const checks = structured.checks.map((check) => normalizeStructuredDesignCheck(check, result));
34
+ const commandFailure = normalizeStructuredCommandFailure(result);
35
+ return commandFailure ? [...checks, commandFailure] : checks;
36
+ }
37
+ return [normalizeGlobalDesignCheck(result)];
38
+ }
39
+ function normalizeStructuredDesignCheck(check, result) {
40
+ const severity = check.severity ?? defaultDesignSeverity(check.status, result.command.blocking ?? true);
41
+ return {
42
+ id: `design.${stripDesignPrefix(check.id)}`,
43
+ suite: 'design',
44
+ target: check.target,
45
+ status: check.status,
46
+ severity,
47
+ summary: check.summary,
48
+ details: check.details,
49
+ artifacts: [result.artifact],
50
+ metadata: {
51
+ ...(check.metadata ?? {}),
52
+ ...(check.family ? { family: check.family } : {}),
53
+ commandId: result.command.id,
54
+ command: result.command.command,
55
+ cwd: result.command.cwd ?? process.cwd(),
56
+ exitCode: result.exitCode,
57
+ signal: result.signal,
58
+ classification: 'token-source-contract'
59
+ },
60
+ suggestedNextStep: check.status === 'pass' || check.status === 'skipped'
61
+ ? undefined
62
+ : 'Review the full command log artifact and update the token/source contract or implementation.'
63
+ };
64
+ }
65
+ function normalizeStructuredCommandFailure(result) {
66
+ if (result.exitCode === 0 && !result.signal) {
67
+ return undefined;
68
+ }
69
+ const blocking = result.command.blocking ?? true;
70
+ const status = blocking ? 'fail' : 'warn';
71
+ const severity = blocking ? 'blocking' : 'review';
72
+ return {
73
+ id: `design.${result.command.id}.command`,
74
+ suite: 'design',
75
+ target: result.command.id,
76
+ status,
77
+ severity,
78
+ summary: `Design token/source contract command "${result.command.id}" exited ${result.exitCode ?? `with signal ${result.signal}`}.`,
79
+ details: summarizeOutput(result.stdout, result.stderr),
80
+ artifacts: [result.artifact],
81
+ metadata: {
82
+ command: result.command.command,
83
+ cwd: result.command.cwd ?? process.cwd(),
84
+ exitCode: result.exitCode,
85
+ signal: result.signal,
86
+ classification: 'token-source-contract',
87
+ structuredOutput: true
88
+ },
89
+ suggestedNextStep: 'Review the full command log artifact and fix the validator command failure.'
90
+ };
91
+ }
92
+ function normalizeGlobalDesignCheck(result) {
93
+ const passed = result.exitCode === 0;
94
+ const blocking = result.command.blocking ?? true;
95
+ const status = passed ? 'pass' : blocking ? 'fail' : 'warn';
96
+ const severity = blocking ? 'blocking' : 'review';
97
+ return {
98
+ id: `design.${result.command.id}`,
99
+ suite: 'design',
100
+ target: result.command.id,
101
+ status,
102
+ severity,
103
+ summary: passed
104
+ ? `Design token/source contract command "${result.command.id}" passed.`
105
+ : `Design token/source contract command "${result.command.id}" exited ${result.exitCode ?? `with signal ${result.signal}`}.`,
106
+ details: summarizeOutput(result.stdout, result.stderr),
107
+ artifacts: [result.artifact],
108
+ metadata: {
109
+ command: result.command.command,
110
+ cwd: result.command.cwd ?? process.cwd(),
111
+ exitCode: result.exitCode,
112
+ signal: result.signal,
113
+ classification: 'token-source-contract'
114
+ },
115
+ suggestedNextStep: passed ? undefined : 'Review the full command log artifact and update the token/source contract or implementation.'
116
+ };
117
+ }
118
+ function defaultDesignSeverity(status, blocking) {
119
+ if (status === 'pass' || status === 'skipped') {
120
+ return 'review';
121
+ }
122
+ return blocking ? 'blocking' : 'review';
123
+ }
124
+ function parseStructuredDesignOutput(stdout) {
125
+ const trimmed = stdout.trim();
126
+ if (!trimmed) {
127
+ return undefined;
128
+ }
129
+ try {
130
+ const parsed = JSON.parse(trimmed);
131
+ const result = StructuredDesignOutputSchema.safeParse(parsed);
132
+ return result.success ? result.data : undefined;
133
+ }
134
+ catch {
135
+ return undefined;
136
+ }
137
+ }
138
+ function stripDesignPrefix(id) {
139
+ return id.startsWith('design.') ? id.slice('design.'.length) : id;
140
+ }
141
+ function summarizeOutput(stdout, stderr) {
142
+ const output = `${stdout}\n${stderr}`.trim();
143
+ if (!output) {
144
+ return 'No command output.';
145
+ }
146
+ const lines = output.split(/\r?\n/).filter(Boolean);
147
+ return lines.slice(0, 6).join('\n');
148
+ }
149
+ //# sourceMappingURL=design-contract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"design-contract.js","sourceRoot":"","sources":["../../../src/contracts/design/design-contract.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { ArtifactStore } from '../../core/artifact-store.js';
2
+ import type { CheckResult } from '../../core/report-schema.js';
3
+ import type { VisualThreshold } from './thresholds.js';
4
+ export type RouteVisualBaselineCase = {
5
+ id: string;
6
+ route: string;
7
+ viewport: string;
8
+ baseline: string;
9
+ baselineRoot?: string | undefined;
10
+ threshold?: VisualThreshold | undefined;
11
+ blocking?: boolean | undefined;
12
+ strict?: boolean | undefined;
13
+ };
14
+ export type CompareRouteVisualBaselineInput = {
15
+ visualCase: RouteVisualBaselineCase;
16
+ routeCheck: CheckResult;
17
+ store: ArtifactStore;
18
+ };
19
+ export declare function compareRouteVisualBaseline(input: CompareRouteVisualBaselineInput): Promise<CheckResult>;