@pixel-point/toolcraft 0.0.16 → 0.0.17
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.
- package/package.json +1 -1
- package/src/generate-performance-iteration-execution.test.mjs +2 -2
- package/src/generate-test-demand-only-lifecycle.mjs +14 -3
- package/src/generate-test-dependency-sandbox.mjs +42 -5
- package/src/generate-test-doc-assertions.mjs +68 -18
- package/src/generate-test-doc-assertions.test.mjs +22 -0
- package/src/generate-test-file-assertions.mjs +43 -76
- package/src/generate-test-output-assertions.mjs +95 -0
- package/src/generate-test-package-assertions.mjs +6 -0
- package/src/generate-test-performance-boundary-assertions.mjs +45 -0
- package/src/generate-test-product-fixture.mjs +1 -0
- package/src/generate-test-product-fixture.test.mjs +18 -0
- package/src/generate-test-product-iteration.mjs +1 -0
- package/src/generate-test-product-iteration.test.mjs +1 -0
- package/src/generate-test-standalone-delivery-stages.mjs +14 -6
- package/src/generate.test.mjs +14 -0
- package/templates/runtime/contracts/component-contracts.choices.test.ts +12 -9
- package/templates/runtime/contracts/component-contracts.choices.ts +10 -9
- package/templates/runtime/contracts/component-contracts.runtime-acceptance.test.ts +17 -2
- package/templates/runtime/contracts/component-contracts.runtime-panels.test.ts +1 -1
- package/templates/runtime/contracts/component-contracts.runtime-shell.test.ts +1 -1
- package/templates/runtime/contracts/component-contracts.runtime.ts +3 -2
- package/templates/runtime/contracts/decision-contracts.test.ts +25 -4
- package/templates/runtime/contracts/decision-contracts.ts +3 -3
- package/templates/runtime/contracts/performance-verification-policy.test.ts +59 -6
- package/templates/runtime/contracts/performance-verification-policy.ts +5 -2
- package/templates/runtime/export/artifact-download.test.ts +71 -0
- package/templates/runtime/export/artifact-download.ts +80 -0
- package/templates/runtime/export/artifact-export-request.ts +23 -0
- package/templates/runtime/export/artifact-export-settings.test.ts +75 -0
- package/templates/runtime/export/artifact-export-settings.ts +96 -0
- package/templates/runtime/export/artifact-frame-renderer.test.ts +107 -0
- package/templates/runtime/export/artifact-frame-renderer.ts +96 -0
- package/templates/runtime/export/artifact-frame-state.test.ts +54 -0
- package/templates/runtime/export/artifact-frame-state.ts +44 -0
- package/templates/runtime/export/artifact-scene-frame.test.ts +84 -0
- package/templates/runtime/export/artifact-scene-frame.ts +118 -0
- package/templates/runtime/export/export-background.ts +65 -0
- package/templates/runtime/export/export-error.ts +43 -0
- package/templates/runtime/export/export.test.ts +6 -186
- package/templates/runtime/export/image-artifact-export.test.ts +111 -0
- package/templates/runtime/export/image-artifact-export.ts +145 -0
- package/templates/runtime/export/index.ts +14 -1
- package/templates/runtime/export/product-export-renderer.test.ts +77 -0
- package/templates/runtime/export/product-export-renderer.ts +63 -0
- package/templates/runtime/export/video-artifact-export.test.ts +166 -0
- package/templates/runtime/export/video-artifact-export.ts +164 -0
- package/templates/runtime/export/video-encoding-backend.ts +124 -0
- package/templates/runtime/export/video-encoding-policy.test.ts +68 -0
- package/templates/runtime/export/video-encoding-policy.ts +86 -0
- package/templates/runtime/export/video-frame-schedule.test.ts +58 -0
- package/templates/runtime/export/video-frame-schedule.ts +42 -0
- package/templates/runtime/index.ts +1 -0
- package/templates/runtime/react/app-shell/runtime-public-api-runtime.test.tsx +291 -0
- package/templates/runtime/react/app-shell/runtime-public-api-test-support.ts +21 -0
- package/templates/runtime/react/app-shell/runtime-public-api.test.tsx +4 -303
- package/templates/runtime/react/app-shell/toolcraft-app.scene-export.test.tsx +12 -27
- package/templates/runtime/react/app-shell/toolcraft-app.tsx +22 -4
- package/templates/runtime/react/app-shell/toolcraft-source-asset-context.test.tsx +16 -57
- package/templates/runtime/react/app-shell/toolcraft-source-asset-context.tsx +75 -434
- package/templates/runtime/react/app-shell/toolcraft-source-asset-owner.test.ts +194 -0
- package/templates/runtime/react/app-shell/toolcraft-source-asset-owner.ts +227 -0
- package/templates/runtime/react/app-shell/toolcraft-source-asset-provider-ownership.test.tsx +243 -0
- package/templates/runtime/react/app-shell/toolcraft-source-asset-test-support.ts +51 -0
- package/templates/runtime/react/app-shell/toolcraft-unavailable-resource-proof.test.ts +138 -0
- package/templates/runtime/react/app-shell/toolcraft-unavailable-resource-proof.ts +378 -0
- package/templates/runtime/react/controls-panel/__tests__/controls-panel.footer-actions.test.tsx +7 -12
- package/templates/runtime/react/controls-panel/__tests__/controls-panel.scene-export-actions.test.tsx +17 -83
- package/templates/runtime/react/controls-panel/actions/controls-panel-actions.ts +42 -84
- package/templates/runtime/react/controls-panel/actions/export-action-runner.ts +62 -0
- package/templates/runtime/react/panel-host/panel-host-runtime-placement.test.tsx +30 -0
- package/templates/runtime/react/panel-host/panel-host.tsx +4 -0
- package/templates/runtime/scene/scene-bounds.ts +1 -2
- package/templates/runtime/schema/canvas-render-scale.ts +62 -0
- package/templates/runtime/schema/controls-panel-section-id.test.ts +1 -1
- package/templates/runtime/schema/controls-panel-section-roundtrip.test.ts +3 -3
- package/templates/runtime/schema/define-toolcraft.setup-background.test.ts +1 -1
- package/templates/runtime/schema/define-toolcraft.setup-render-scale-timeline.test.ts +71 -3
- package/templates/runtime/schema/define-toolcraft.ts +1 -1
- package/templates/runtime/schema/schema-resolvers.ts +0 -56
- package/templates/runtime/schema/types.ts +4 -4
- package/templates/runtime/state/canvas-background-state.ts +6 -0
- package/templates/runtime/testing/performance-render-plan-integration.test.ts +64 -0
- package/templates/runtime/testing/performance-renderer-pipeline-validation.ts +18 -1
- package/templates/starter/AGENTS.md +8 -7
- package/templates/starter/NOTICE.md +6 -0
- package/templates/starter/docs/toolcraft/README.md +2 -1
- package/templates/starter/docs/toolcraft/acceptance-testing.md +8 -6
- package/templates/starter/docs/toolcraft/agent-worklog.md +3 -3
- package/templates/starter/docs/toolcraft/assembly-workflow.md +4 -3
- package/templates/starter/docs/toolcraft/core/media-upload.md +2 -2
- package/templates/starter/docs/toolcraft/core/performance.md +14 -3
- package/templates/starter/docs/toolcraft/core/runtime-boundary.md +3 -1
- package/templates/starter/docs/toolcraft/core/setup-export.md +16 -12
- package/templates/starter/docs/toolcraft/core/timeline-animation.md +4 -4
- package/templates/starter/docs/toolcraft/performance.md +20 -6
- package/templates/starter/docs/toolcraft/renderer-technique.md +1 -1
- package/templates/starter/docs/toolcraft/schema-reference.md +2 -6
- package/templates/starter/docs/toolcraft/workflow.md +7 -2
- package/templates/starter/e2e/app-browser-control-coverage.spec.ts +33 -0
- package/templates/starter/e2e/app-browser-infinity-canvas-evidence.spec.ts +43 -1
- package/templates/starter/e2e/app-browser-render-scale-evidence.spec.ts +60 -6
- package/templates/starter/e2e/app-browser-render-scale-requirements.spec.ts +77 -1
- package/templates/starter/e2e/app-browser-runtime-provenance.spec.ts +8 -0
- package/templates/starter/e2e/app-browser-runtime-reporter.spec.ts +35 -0
- package/templates/starter/e2e/app-browser-runtime-requirements.spec.ts +4 -1
- package/templates/starter/e2e/app-browser-semantic-evidence.spec.ts +0 -1
- package/templates/starter/e2e/app-browser-shell.spec.ts +13 -5
- package/templates/starter/e2e/app-performance-path-adapters.ts +8 -1
- package/templates/starter/e2e/app-performance.spec.ts +16 -9
- package/templates/starter/e2e/browser-infinity-canvas-evidence.ts +9 -330
- package/templates/starter/e2e/browser-infinity-canvas-unavailable-image-evidence.ts +370 -0
- package/templates/starter/e2e/browser-media-export-evidence.spec.ts +77 -0
- package/templates/starter/e2e/browser-media-export-evidence.ts +208 -0
- package/templates/starter/e2e/browser-render-scale-evidence.ts +37 -29
- package/templates/starter/e2e/browser-runtime-evidence-reporter.ts +4 -1
- package/templates/starter/e2e/browser-runtime-evidence-requirements.ts +43 -9
- package/templates/starter/e2e/browser-standard-timeline-evidence.ts +106 -0
- package/templates/starter/e2e/decoded-pixel-observation.spec.ts +74 -0
- package/templates/starter/e2e/decoded-pixel-observation.ts +227 -0
- package/templates/starter/e2e/export-artifact-helpers.ts +206 -25
- package/templates/starter/e2e/image-artifact-inspection.spec.ts +41 -0
- package/templates/starter/e2e/image-artifact-inspection.ts +99 -0
- package/templates/starter/e2e/performance-canvas-helpers.ts +22 -21
- package/templates/starter/e2e/performance-canvas-quality-guard.spec.ts +312 -0
- package/templates/starter/e2e/performance-canvas-quality-guard.ts +196 -0
- package/templates/starter/e2e/performance-canvas-quality-observer.ts +351 -0
- package/templates/starter/e2e/performance-control-layout-helpers.ts +2 -2
- package/templates/starter/e2e/performance-path-adapter-contract.ts +4 -4
- package/templates/starter/e2e/performance-path-helpers.spec.ts +203 -70
- package/templates/starter/e2e/performance-path-helpers.ts +210 -91
- package/templates/starter/e2e/performance-pipeline-evidence-continuity.spec.ts +76 -0
- package/templates/starter/e2e/performance-pipeline-evidence-test-fixtures.ts +11 -2
- package/templates/starter/e2e/performance-pipeline-invariants.ts +47 -4
- package/templates/starter/e2e/performance-render-scale-runner.spec.ts +140 -38
- package/templates/starter/e2e/video-artifact-inspection.spec.ts +64 -0
- package/templates/starter/e2e/video-artifact-inspection.ts +281 -0
- package/templates/starter/gitignore +1 -0
- package/templates/starter/package.json +1 -0
- package/templates/starter/scripts/check-toolcraft-docs.mjs +17 -0
- package/templates/starter/scripts/toolcraft-delivery-plan-authority.test.mjs +60 -0
- package/templates/starter/scripts/toolcraft-delivery-plan-errors.test.mjs +7 -2
- package/templates/starter/scripts/toolcraft-delivery-plan.mjs +7 -3
- package/templates/starter/scripts/toolcraft-product-boundary-ast.mjs +24 -2
- package/templates/starter/scripts/toolcraft-product-boundary.mjs +12 -0
- package/templates/starter/scripts/toolcraft-product-boundary.test.mjs +46 -0
- package/templates/starter/scripts/toolcraft-product-evidence-boundary.test.mjs +85 -20
- package/templates/starter/scripts/toolcraft-product-evidence-import-policy.mjs +43 -0
- package/templates/starter/scripts/toolcraft-product-export-boundary.mjs +168 -0
- package/templates/starter/scripts/toolcraft-typescript-analysis.d.mts +73 -0
- package/templates/starter/scripts/toolcraft-unavailable-resource-evidence-facade-test-helpers.mjs +318 -0
- package/templates/starter/scripts/toolcraft-unavailable-resource-evidence-facade.test.mjs +155 -206
- package/templates/starter/scripts/toolcraft-verification-inventory.mjs +1 -0
- package/templates/starter/scripts/toolcraft-verification-receipt.test.mjs +51 -0
- package/templates/starter/scripts/toolcraft-vite-env-activation.test.mjs +128 -59
- package/templates/starter/src/app/acceptance/export-artifact-coverage.ts +113 -0
- package/templates/starter/src/app/acceptance/output-background-rules.ts +1 -1
- package/templates/starter/src/app/acceptance/output-export.ts +13 -2
- package/templates/starter/src/app/acceptance/types.ts +7 -0
- package/templates/starter/src/app/acceptance/validate-coverage.ts +2 -1
- package/templates/starter/src/app/starter-acceptance.export-artifact.test.ts +131 -0
- package/templates/starter/src/app/starter-acceptance.keyframes.test.ts +14 -4
- package/templates/starter/src/app/starter-acceptance.output-export-rules.test.ts +42 -1
- package/templates/starter/src/app/starter-acceptance.ts +2 -0
- package/templates/starter/src/app/starter-performance-test-utils.ts +103 -0
- package/templates/starter/src/app/starter-performance.gates.test.ts +231 -278
- package/templates/starter/src/app/starter-performance.lifecycle.test.ts +261 -0
- package/templates/starter/src/app/test-evidence/browser-runtime-contract.ts +2 -0
- package/templates/starter/src/routes/index.tsx +1 -0
- package/templates/runtime/export/export.ts +0 -166
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import {
|
|
2
|
-
existsSync,
|
|
3
2
|
mkdirSync,
|
|
4
3
|
mkdtempSync,
|
|
5
4
|
readFileSync,
|
|
@@ -10,6 +9,7 @@ import {
|
|
|
10
9
|
import { tmpdir } from "node:os";
|
|
11
10
|
import { join } from "node:path";
|
|
12
11
|
|
|
12
|
+
import ts from "typescript";
|
|
13
13
|
import { describe, expect, it } from "vitest";
|
|
14
14
|
import {
|
|
15
15
|
TOOLCRAFT_PERFORMANCE_VERIFICATION_LIFECYCLE,
|
|
@@ -28,27 +28,19 @@ import {
|
|
|
28
28
|
getToolcraftScriptProductionEntryPaths,
|
|
29
29
|
toolcraftScriptSourceExtensions,
|
|
30
30
|
} from "../../scripts/toolcraft-delivery-architecture-policy.mjs";
|
|
31
|
-
import {
|
|
32
|
-
TOOLCRAFT_DELIVERY_VERIFICATION_COMMAND,
|
|
33
|
-
TOOLCRAFT_FULL_PERFORMANCE_VERIFICATION_COMMAND,
|
|
34
|
-
} from "../../scripts/toolcraft-performance-authority-policy.mjs";
|
|
35
31
|
import { evaluateCodeHealth } from "../../scripts/toolcraft-code-health-core.mjs";
|
|
36
|
-
import { requiredPackageScriptNames } from "../../scripts/toolcraft-integrity-policy.mjs";
|
|
37
32
|
|
|
38
33
|
import { starterPerformance } from "./starter-performance";
|
|
39
34
|
import { starterSchema } from "./starter-schema";
|
|
40
35
|
import {
|
|
36
|
+
createToolcraftTypeScriptSourceAnalysis,
|
|
41
37
|
e2eDir,
|
|
38
|
+
getToolcraftImportedBinding,
|
|
42
39
|
playwrightConfigForbidsFocusedTests,
|
|
43
40
|
projectDir,
|
|
41
|
+
toolcraftExpressionReferencesImport,
|
|
44
42
|
} from "./starter-performance-test-utils";
|
|
45
43
|
|
|
46
|
-
const expectedRequiredPackageScriptNames = [
|
|
47
|
-
"ai:check", "build", "dev", "dev:restart", "docs:check", "preview",
|
|
48
|
-
"preview:restart", "test", "test:browser", "typecheck", "verify:delivery",
|
|
49
|
-
"verify:kernel", "verify:perf", "verify:receipt",
|
|
50
|
-
] as const;
|
|
51
|
-
|
|
52
44
|
async function evaluateGeneratedScriptBudgets(rootDir: string) {
|
|
53
45
|
return evaluateCodeHealth({
|
|
54
46
|
...createToolcraftScriptLineBudgetPolicy("scripts"),
|
|
@@ -59,198 +51,102 @@ async function evaluateGeneratedScriptBudgets(rootDir: string) {
|
|
|
59
51
|
});
|
|
60
52
|
}
|
|
61
53
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
expect(requiredPackageScriptNames).toEqual(expectedRequiredPackageScriptNames);
|
|
71
|
-
for (const scriptName of requiredPackageScriptNames) {
|
|
72
|
-
expect(packageJson.scripts?.[scriptName]).toBeDefined();
|
|
73
|
-
}
|
|
74
|
-
for (const removed of [
|
|
75
|
-
"test:delivery", "verify:final", "verify:perf:record-iteration",
|
|
76
|
-
"verify:quick", "verify:ui",
|
|
77
|
-
]) {
|
|
78
|
-
expect(packageJson.scripts?.[removed]).toBeUndefined();
|
|
54
|
+
function collectObjectPropertyAssignments(
|
|
55
|
+
value: ts.ObjectLiteralExpression,
|
|
56
|
+
): ReadonlyMap<string, ts.Expression> {
|
|
57
|
+
const properties = new Map<string, ts.Expression>();
|
|
58
|
+
for (const property of value.properties) {
|
|
59
|
+
if (ts.isShorthandPropertyAssignment(property)) {
|
|
60
|
+
properties.set(property.name.text, property.name);
|
|
61
|
+
continue;
|
|
79
62
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
"node scripts/check-toolcraft-docs.mjs && node scripts/check-toolcraft-integrity.mjs && node --test scripts/*.test.mjs && vitest run src --passWithNoTests --reporter=default --reporter=./scripts/toolcraft-vitest-runtime-evidence-reporter.mjs";
|
|
87
|
-
if (packageJson.scripts?.["test:generated"]) {
|
|
88
|
-
expect(packageJson.scripts.test).toBe(sourceTestScript);
|
|
89
|
-
expect(packageJson.scripts["test:generated"]).toBe(generatedTestScript);
|
|
90
|
-
} else {
|
|
91
|
-
expect(packageJson.scripts?.test).toBe(generatedTestScript);
|
|
63
|
+
if (
|
|
64
|
+
!ts.isPropertyAssignment(property) ||
|
|
65
|
+
(!ts.isIdentifier(property.name) &&
|
|
66
|
+
!ts.isStringLiteralLike(property.name))
|
|
67
|
+
) {
|
|
68
|
+
continue;
|
|
92
69
|
}
|
|
70
|
+
properties.set(property.name.text, property.initializer);
|
|
71
|
+
}
|
|
72
|
+
return properties;
|
|
73
|
+
}
|
|
93
74
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
75
|
+
function collectPerformanceSpecFacts(source: string, fileName: string) {
|
|
76
|
+
const analysis = createToolcraftTypeScriptSourceAnalysis(source, fileName);
|
|
77
|
+
function importedBinding(
|
|
78
|
+
expression: ts.Expression | undefined,
|
|
79
|
+
): Readonly<{ importedName: string; specifier: string }> | undefined {
|
|
80
|
+
return getToolcraftImportedBinding(analysis, expression);
|
|
81
|
+
}
|
|
98
82
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
);
|
|
147
|
-
expect(deliveryRunner).toContain("executeToolcraftDeliveryLifecycle");
|
|
148
|
-
expect(deliveryRunner).toContain("withToolcraftVerificationLock");
|
|
149
|
-
expect(deliveryLifecycle).toContain(
|
|
150
|
-
"executeToolcraftDeliveryLifecycleCore",
|
|
151
|
-
);
|
|
152
|
-
expect(deliveryLifecycle).toContain("executeToolcraftDeliveryPlan");
|
|
153
|
-
expect(deliveryLifecycle).not.toContain(
|
|
154
|
-
"runToolcraftFullPerformanceCertification",
|
|
155
|
-
);
|
|
156
|
-
expect(deliveryLifecycle).not.toContain(
|
|
157
|
-
"measureToolcraftPerformanceCheckpoint",
|
|
158
|
-
);
|
|
159
|
-
expect(proofProcess).toContain('from "cross-spawn"');
|
|
160
|
-
expect(proofProcess).toContain("ensureToolcraftChromium");
|
|
161
|
-
const deliverySources = `${deliveryRunner}\n${deliveryLifecycle}`;
|
|
162
|
-
expect(deliverySources).not.toContain('runPackageScript(projectDir, "verify:quick")');
|
|
163
|
-
expect(deliverySources).not.toContain('runPackageScript(projectDir, "verify:final")');
|
|
164
|
-
expect(deliverySources).not.toContain('runPackageScript(projectDir, "verify:perf")');
|
|
165
|
-
expect(packageJson.scripts?.["verify:perf"]).toBe(
|
|
166
|
-
"node scripts/run-browser-performance.mjs",
|
|
167
|
-
);
|
|
168
|
-
expect(packageJson.scripts?.["verify:perf:playwright"]).toBeUndefined();
|
|
169
|
-
expect(packageJson.scripts?.["verify:perf:refresh"]).toBeUndefined();
|
|
170
|
-
expect(
|
|
171
|
-
packageJson.scripts?.["verify:perf:record-agent-browser"],
|
|
172
|
-
"A terminal-only command must not mint an agent-browser performance receipt without browser evidence.",
|
|
173
|
-
).toBeUndefined();
|
|
174
|
-
expect(
|
|
175
|
-
packageJson.scripts?.["verify:perf:record-iteration"],
|
|
176
|
-
).toBeUndefined();
|
|
177
|
-
expect(packageJson.scripts?.["verify:kernel"]).toBe(
|
|
178
|
-
"node scripts/run-kernel-benchmarks.mjs",
|
|
179
|
-
);
|
|
180
|
-
const deliveryExecutor = readFileSync(
|
|
181
|
-
join(projectDir, "scripts/toolcraft-delivery-executor.mjs"),
|
|
182
|
-
"utf8",
|
|
183
|
-
);
|
|
184
|
-
const targetedPerformanceExecution = readFileSync(
|
|
185
|
-
join(projectDir, "scripts/toolcraft-targeted-performance-execution.mjs"),
|
|
186
|
-
"utf8",
|
|
187
|
-
);
|
|
188
|
-
expect(
|
|
189
|
-
deliveryExecutor.match(
|
|
190
|
-
/TOOLCRAFT_PERFORMANCE_FIXTURE_SELECTOR: "development"/g,
|
|
191
|
-
),
|
|
192
|
-
).toBeNull();
|
|
193
|
-
expect(
|
|
194
|
-
targetedPerformanceExecution.match(
|
|
195
|
-
/TOOLCRAFT_PERFORMANCE_FIXTURE_SELECTOR: "development"/g,
|
|
196
|
-
),
|
|
197
|
-
).toHaveLength(1);
|
|
198
|
-
expect(packageJson.scripts?.["verify:perf:record-exemption"]).toBeUndefined();
|
|
199
|
-
expect(receiptModule).not.toContain('command === "record-iteration"');
|
|
200
|
-
expect(packageJson.scripts?.["verify:receipt"]).toContain("validate");
|
|
83
|
+
const compilerCalls = analysis.importedCalls.filter(
|
|
84
|
+
({ target }) =>
|
|
85
|
+
target.specifier === "./performance-path-helpers" &&
|
|
86
|
+
target.importedName ===
|
|
87
|
+
"compileToolcraftPerformancePathAdapterMatrix" &&
|
|
88
|
+
target.memberPath === "",
|
|
89
|
+
);
|
|
90
|
+
const compilerBoundaries = compilerCalls.map(({ call }) => {
|
|
91
|
+
const [input] = call.arguments;
|
|
92
|
+
const properties =
|
|
93
|
+
input && ts.isObjectLiteralExpression(input)
|
|
94
|
+
? collectObjectPropertyAssignments(input)
|
|
95
|
+
: new Map<string, ts.Expression>();
|
|
96
|
+
const paths = properties.get("paths");
|
|
97
|
+
const canvasBackingBinding = importedBinding(
|
|
98
|
+
properties.get("canvasBacking"),
|
|
99
|
+
);
|
|
100
|
+
const schemaBinding = importedBinding(properties.get("schema"));
|
|
101
|
+
return Object.freeze({
|
|
102
|
+
adaptersFromCatalog: properties.has("adapters")
|
|
103
|
+
? toolcraftExpressionReferencesImport(
|
|
104
|
+
analysis,
|
|
105
|
+
properties.get("adapters"),
|
|
106
|
+
{
|
|
107
|
+
importedName: "appPerformancePathAdapters",
|
|
108
|
+
specifier: "./app-performance-path-adapters",
|
|
109
|
+
},
|
|
110
|
+
)
|
|
111
|
+
: false,
|
|
112
|
+
canvasBackingFromCatalog:
|
|
113
|
+
canvasBackingBinding?.importedName ===
|
|
114
|
+
"appPerformanceCanvasBacking" &&
|
|
115
|
+
canvasBackingBinding.specifier ===
|
|
116
|
+
"./app-performance-path-adapters",
|
|
117
|
+
pathShape:
|
|
118
|
+
paths && ts.isIdentifier(paths)
|
|
119
|
+
? "catalog"
|
|
120
|
+
: paths &&
|
|
121
|
+
ts.isArrayLiteralExpression(paths) &&
|
|
122
|
+
paths.elements.length === 1 &&
|
|
123
|
+
ts.isIdentifier(paths.elements[0])
|
|
124
|
+
? "single"
|
|
125
|
+
: "invalid",
|
|
126
|
+
propertyNames: Object.freeze([...properties.keys()].sort()),
|
|
127
|
+
schemaFromStarter:
|
|
128
|
+
schemaBinding?.importedName === "starterSchema" &&
|
|
129
|
+
schemaBinding.specifier === "../src/app/starter-schema",
|
|
130
|
+
});
|
|
201
131
|
});
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
source: readFileSync(join(projectDir, relativePath), "utf8"),
|
|
217
|
-
}));
|
|
218
|
-
|
|
219
|
-
for (const { relativePath, source } of docSources) {
|
|
220
|
-
expect(source, relativePath).toMatch(/first (?:product )?delivery/i);
|
|
221
|
-
expect(source, relativePath).toMatch(/later[^\n]{0,40}delivery/i);
|
|
222
|
-
expect(source, relativePath).toMatch(/performance complaint/i);
|
|
223
|
-
expect(source, relativePath).toMatch(/full audit/i);
|
|
224
|
-
expect(source, relativePath).toContain(
|
|
225
|
-
TOOLCRAFT_DELIVERY_VERIFICATION_COMMAND,
|
|
226
|
-
);
|
|
227
|
-
expect(source, relativePath).toContain(
|
|
228
|
-
TOOLCRAFT_FULL_PERFORMANCE_VERIFICATION_COMMAND,
|
|
229
|
-
);
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
const allRoutedDocs = docSources.map(({ source }) => source).join("\n");
|
|
233
|
-
const nonAgentsDocs = docSources
|
|
234
|
-
.filter(({ relativePath }) => relativePath !== "AGENTS.md")
|
|
235
|
-
.map(({ source }) => source)
|
|
236
|
-
.join("\n");
|
|
237
|
-
expect(nonAgentsDocs).not.toMatch(/\bTier (?:N|[0-4])\b/);
|
|
238
|
-
expect(allRoutedDocs).not.toMatch(
|
|
239
|
-
/verify:quick|verify:ui|verify:final|verify:perf:record-iteration|test:delivery/,
|
|
240
|
-
);
|
|
241
|
-
expect(allRoutedDocs).not.toMatch(
|
|
242
|
-
/verify:delivery\s+--|--tier|--unit-test|--browser-test|--performance-test/,
|
|
243
|
-
);
|
|
244
|
-
expect(allRoutedDocs).not.toMatch(
|
|
245
|
-
/performance modules require protected evidence|(?:add|run)[^\n]*affected path performance checks[^\n]*when an edit changes|during development[^\n]*affected performance scenarios|targeted performance scenarios only for touched/i,
|
|
246
|
-
);
|
|
247
|
-
expect(allRoutedDocs).toMatch(
|
|
248
|
-
/only exact request authority[^\n]*measured targeted performance/i,
|
|
249
|
-
);
|
|
250
|
-
expect(allRoutedDocs).not.toMatch(/matching (?:executed )?`?Run\b`?/i);
|
|
251
|
-
expect(allRoutedDocs).not.toContain("app-performance-impact.json");
|
|
132
|
+
const staticTestNames = analysis.importedCalls.flatMap(({ call, target }) => {
|
|
133
|
+
const [name] = call.arguments;
|
|
134
|
+
return target.specifier === "@playwright/test" &&
|
|
135
|
+
target.importedName === "test" &&
|
|
136
|
+
target.memberPath === "" &&
|
|
137
|
+
name &&
|
|
138
|
+
ts.isStringLiteralLike(name)
|
|
139
|
+
? [name.text]
|
|
140
|
+
: [];
|
|
141
|
+
});
|
|
142
|
+
return Object.freeze({
|
|
143
|
+
compilerBoundaries: Object.freeze(compilerBoundaries),
|
|
144
|
+
importedCallTargets: analysis.callTargets.importedCallTargets,
|
|
145
|
+
staticTestNames: Object.freeze(staticTestNames),
|
|
252
146
|
});
|
|
147
|
+
}
|
|
253
148
|
|
|
149
|
+
describe("Toolcraft starter performance gates", () => {
|
|
254
150
|
it(
|
|
255
151
|
"keeps generated verification scripts within shared recursive budgets",
|
|
256
152
|
async () => {
|
|
@@ -305,30 +201,150 @@ describe("Toolcraft starter performance gates", () => {
|
|
|
305
201
|
});
|
|
306
202
|
|
|
307
203
|
it("keeps the Playwright performance audit inside the browser perf tag", () => {
|
|
308
|
-
const
|
|
309
|
-
const
|
|
310
|
-
|
|
311
|
-
);
|
|
204
|
+
const sourcePath = join(e2eDir, "app-performance.spec.ts");
|
|
205
|
+
const source = readFileSync(sourcePath, "utf8");
|
|
206
|
+
const facts = collectPerformanceSpecFacts(source, sourcePath);
|
|
312
207
|
|
|
313
208
|
expect(source).not.toContain("TOOLCRAFT_PERF_CHECK");
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
209
|
+
for (const expected of [
|
|
210
|
+
["@repo/toolcraft-runtime", "deriveToolcraftPerformancePaths"],
|
|
211
|
+
["./performance-path-helpers", "getToolcraftPerformancePathTestName"],
|
|
212
|
+
["./performance-path-helpers", "runToolcraftPerformancePath"],
|
|
213
|
+
] as const) {
|
|
214
|
+
expect(
|
|
215
|
+
facts.importedCallTargets.some(
|
|
216
|
+
({ importedName, memberPath, specifier }) =>
|
|
217
|
+
specifier === expected[0] &&
|
|
218
|
+
importedName === expected[1] &&
|
|
219
|
+
memberPath === "",
|
|
220
|
+
),
|
|
221
|
+
).toBe(true);
|
|
222
|
+
}
|
|
223
|
+
expect(facts.compilerBoundaries).toHaveLength(2);
|
|
224
|
+
for (const boundary of facts.compilerBoundaries) {
|
|
225
|
+
expect(boundary.propertyNames).toEqual([
|
|
226
|
+
"adapters",
|
|
227
|
+
"canvasBacking",
|
|
228
|
+
"paths",
|
|
229
|
+
"schema",
|
|
230
|
+
]);
|
|
231
|
+
expect(boundary.adaptersFromCatalog).toBe(true);
|
|
232
|
+
expect(boundary.canvasBackingFromCatalog).toBe(true);
|
|
233
|
+
expect(boundary.schemaFromStarter).toBe(true);
|
|
234
|
+
}
|
|
235
|
+
expect(facts.compilerBoundaries.map(({ pathShape }) => pathShape).sort()).toEqual([
|
|
236
|
+
"catalog",
|
|
237
|
+
"single",
|
|
238
|
+
]);
|
|
239
|
+
expect(facts.staticTestNames).toContain(
|
|
240
|
+
"browser perf: toolcraft adapter catalog",
|
|
241
|
+
);
|
|
242
|
+
expect(facts.staticTestNames.length).toBeGreaterThan(0);
|
|
326
243
|
expect(
|
|
327
|
-
|
|
328
|
-
`app-performance.spec.ts tests must all be tagged for the dedicated perf checkpoint: ${
|
|
244
|
+
facts.staticTestNames.every((name) => name.includes("browser perf:")),
|
|
245
|
+
`app-performance.spec.ts tests must all be tagged for the dedicated perf checkpoint: ${facts.staticTestNames.join(", ")}`,
|
|
329
246
|
).toBe(true);
|
|
330
247
|
});
|
|
331
248
|
|
|
249
|
+
it("accepts harmless performance catalog import aliases", () => {
|
|
250
|
+
const facts = collectPerformanceSpecFacts(
|
|
251
|
+
`
|
|
252
|
+
import { starterSchema as schema } from "../src/app/starter-schema";
|
|
253
|
+
import {
|
|
254
|
+
appPerformanceCanvasBacking as backing,
|
|
255
|
+
appPerformancePathAdapters as adapters,
|
|
256
|
+
} from "./app-performance-path-adapters";
|
|
257
|
+
import {
|
|
258
|
+
compileToolcraftPerformancePathAdapterMatrix as compile,
|
|
259
|
+
} from "./performance-path-helpers";
|
|
260
|
+
|
|
261
|
+
const paths = [];
|
|
262
|
+
const path = paths[0];
|
|
263
|
+
compile({ adapters, canvasBacking: backing, paths, schema });
|
|
264
|
+
compile({
|
|
265
|
+
adapters: adapters.filter((candidate) => candidate.pathId === path.id),
|
|
266
|
+
canvasBacking: backing,
|
|
267
|
+
paths: [path],
|
|
268
|
+
schema,
|
|
269
|
+
});
|
|
270
|
+
`,
|
|
271
|
+
"aliased-performance-spec.ts",
|
|
272
|
+
);
|
|
273
|
+
|
|
274
|
+
expect(facts.compilerBoundaries).toHaveLength(2);
|
|
275
|
+
expect(facts.compilerBoundaries).toMatchObject([
|
|
276
|
+
{
|
|
277
|
+
adaptersFromCatalog: true,
|
|
278
|
+
canvasBackingFromCatalog: true,
|
|
279
|
+
schemaFromStarter: true,
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
adaptersFromCatalog: true,
|
|
283
|
+
canvasBackingFromCatalog: true,
|
|
284
|
+
schemaFromStarter: true,
|
|
285
|
+
},
|
|
286
|
+
]);
|
|
287
|
+
expect(facts.compilerBoundaries.map(({ pathShape }) => pathShape).sort()).toEqual([
|
|
288
|
+
"catalog",
|
|
289
|
+
"single",
|
|
290
|
+
]);
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
it("rejects compiler boundaries that omit product canvas backing", () => {
|
|
294
|
+
const facts = collectPerformanceSpecFacts(
|
|
295
|
+
`
|
|
296
|
+
import { starterSchema as schema } from "../src/app/starter-schema";
|
|
297
|
+
import {
|
|
298
|
+
appPerformanceCanvasBacking as backing,
|
|
299
|
+
appPerformancePathAdapters as adapters,
|
|
300
|
+
} from "./app-performance-path-adapters";
|
|
301
|
+
import {
|
|
302
|
+
compileToolcraftPerformancePathAdapterMatrix as compile,
|
|
303
|
+
} from "./performance-path-helpers";
|
|
304
|
+
|
|
305
|
+
const paths = [];
|
|
306
|
+
compile({ adapters, paths, schema });
|
|
307
|
+
`,
|
|
308
|
+
"missing-performance-canvas-backing.ts",
|
|
309
|
+
);
|
|
310
|
+
|
|
311
|
+
expect(facts.compilerBoundaries).toHaveLength(1);
|
|
312
|
+
expect(facts.compilerBoundaries[0]).toMatchObject({
|
|
313
|
+
adaptersFromCatalog: true,
|
|
314
|
+
canvasBackingFromCatalog: false,
|
|
315
|
+
propertyNames: ["adapters", "paths", "schema"],
|
|
316
|
+
schemaFromStarter: true,
|
|
317
|
+
});
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
it("rejects shadowed performance compiler and adapter identifiers", () => {
|
|
321
|
+
const facts = collectPerformanceSpecFacts(
|
|
322
|
+
`
|
|
323
|
+
import { starterSchema as schema } from "../src/app/starter-schema";
|
|
324
|
+
import {
|
|
325
|
+
appPerformanceCanvasBacking as backing,
|
|
326
|
+
appPerformancePathAdapters as adapters,
|
|
327
|
+
} from "./app-performance-path-adapters";
|
|
328
|
+
import {
|
|
329
|
+
compileToolcraftPerformancePathAdapterMatrix as compile,
|
|
330
|
+
} from "./performance-path-helpers";
|
|
331
|
+
|
|
332
|
+
const paths = [];
|
|
333
|
+
function ignoredShadow(compile) {
|
|
334
|
+
compile({ adapters, canvasBacking: backing, paths, schema });
|
|
335
|
+
}
|
|
336
|
+
{
|
|
337
|
+
const adapters = [];
|
|
338
|
+
compile({ adapters, canvasBacking: backing, paths, schema });
|
|
339
|
+
}
|
|
340
|
+
`,
|
|
341
|
+
"shadowed-performance-spec.ts",
|
|
342
|
+
);
|
|
343
|
+
|
|
344
|
+
expect(facts.compilerBoundaries).toHaveLength(1);
|
|
345
|
+
expect(facts.compilerBoundaries[0]?.adaptersFromCatalog).toBe(false);
|
|
346
|
+
});
|
|
347
|
+
|
|
332
348
|
it("keeps measured performance out of functional delivery", () => {
|
|
333
349
|
expect(readdirSync(e2eDir).filter((name) => name.includes("-smoke"))).toEqual(
|
|
334
350
|
[],
|
|
@@ -399,69 +415,6 @@ describe("Toolcraft starter performance gates", () => {
|
|
|
399
415
|
expect(collectToolcraftWorkloadControls(starterSchema)).toEqual([]);
|
|
400
416
|
});
|
|
401
417
|
|
|
402
|
-
it("keeps workload guidance structural instead of prescribing domain constants", () => {
|
|
403
|
-
const monorepoRoot = join(projectDir, "..");
|
|
404
|
-
const documentation = [
|
|
405
|
-
join(projectDir, "AGENTS.md"),
|
|
406
|
-
join(projectDir, "docs/toolcraft/core/performance.md"),
|
|
407
|
-
join(projectDir, "docs/toolcraft/performance.md"),
|
|
408
|
-
join(projectDir, "docs/toolcraft/renderer-technique.md"),
|
|
409
|
-
join(projectDir, "docs/toolcraft/assembly-workflow.md"),
|
|
410
|
-
join(projectDir, "docs/toolcraft/workflow.md"),
|
|
411
|
-
join(monorepoRoot, "apps/website/src/content/docs/toolcraft-core-performance.md"),
|
|
412
|
-
join(monorepoRoot, "apps/website/src/content/docs/toolcraft-performance.md"),
|
|
413
|
-
join(monorepoRoot, "apps/website/src/content/docs/toolcraft-renderer-technique.md"),
|
|
414
|
-
join(monorepoRoot, "apps/website/src/content/docs/toolcraft-assembly-workflow.md"),
|
|
415
|
-
join(monorepoRoot, "apps/website/src/content/docs/toolcraft-workflow.md"),
|
|
416
|
-
]
|
|
417
|
-
.filter((filePath) => existsSync(filePath))
|
|
418
|
-
.map((filePath) => readFileSync(filePath, "utf8"))
|
|
419
|
-
.join("\n");
|
|
420
|
-
|
|
421
|
-
expect(documentation).toMatch(/reachable controls and inputs/i);
|
|
422
|
-
expect(documentation).toMatch(/workload dimensions and enforced boundaries/i);
|
|
423
|
-
expect(documentation).toMatch(
|
|
424
|
-
/render-plan assessment(?: and| with).*protected kernel benchmark/i,
|
|
425
|
-
);
|
|
426
|
-
expect(documentation).toMatch(/derived paths and combined fixtures/i);
|
|
427
|
-
expect(documentation).not.toMatch(/50_000|1_000\s+lines|1920x1080-equivalent/i);
|
|
428
|
-
expect(documentation).not.toMatch(/classif(?:y|ication)[^\n]*(?:key name|key-name|keyword)/i);
|
|
429
|
-
expect(documentation).not.toMatch(
|
|
430
|
-
/bitmap-media|halftone|per-pixel|max text length|max media size/i,
|
|
431
|
-
);
|
|
432
|
-
expect(documentation).toMatch(/exact normalized development pressure `0\.8`/i);
|
|
433
|
-
expect(documentation).toMatch(/exhaustive-discrete/i);
|
|
434
|
-
expect(documentation).toMatch(/match(?:es)? every option one-to-one/i);
|
|
435
|
-
expect(documentation).toMatch(/toolcraftDiscreteCombinationBudget/);
|
|
436
|
-
expect(documentation).toMatch(/toolcraftDiscreteDimensionBudget/);
|
|
437
|
-
expect(documentation).toMatch(/bypasses search budgets because no (?:combination )?search runs/i);
|
|
438
|
-
expect(documentation).toMatch(/planning error/i);
|
|
439
|
-
expect(documentation).toMatch(/TOOLCRAFT_PERFORMANCE_VERIFICATION_LIFECYCLE/);
|
|
440
|
-
expect(documentation).toMatch(/exactly one scenario (?:for|per) (?:every )?(?:canonical |derived )?path/i);
|
|
441
|
-
expect(documentation).toMatch(/targeted failure[^\n]*(?:not|rather than)[^\n]*full[- ]suite/i);
|
|
442
|
-
expect(documentation).toMatch(
|
|
443
|
-
/first product delivery[^\n]*full functional acceptance[^\n]*no measured performance/i,
|
|
444
|
-
);
|
|
445
|
-
expect(documentation).toMatch(
|
|
446
|
-
/later delivery[^\n]*functional-targeted/i,
|
|
447
|
-
);
|
|
448
|
-
expect(documentation).toMatch(
|
|
449
|
-
/complaint[^\n]*one-authority-targeted-performance-iteration/i,
|
|
450
|
-
);
|
|
451
|
-
expect(documentation).toMatch(/full-performance/i);
|
|
452
|
-
expect(documentation).toMatch(/needs-agent-judgment/i);
|
|
453
|
-
expect(documentation).toMatch(
|
|
454
|
-
/later[^\n]{0,40}delivery[^\n]*(?:same )?bare command[^\n]*exact ownership/i,
|
|
455
|
-
);
|
|
456
|
-
expect(documentation).not.toMatch(
|
|
457
|
-
/first stable[^\n]*(?:full performance|full checkpoint|baseline)/i,
|
|
458
|
-
);
|
|
459
|
-
expect(documentation).not.toMatch(/compatibility mode|legacy preferred|legacy-only/i);
|
|
460
|
-
expect(documentation).not.toMatch(/loadProfile|smoothTargetRatio/i);
|
|
461
|
-
expect(documentation).not.toMatch(/without exceeding development pressure/i);
|
|
462
|
-
expect(documentation).not.toMatch(/\breachableValues\b/);
|
|
463
|
-
});
|
|
464
|
-
|
|
465
418
|
it("requires every visible control to classify its performance role", () => {
|
|
466
419
|
const unclassifiedControls =
|
|
467
420
|
collectToolcraftUnclassifiedPerformanceControls(starterSchema);
|