@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
package/package.json
CHANGED
|
@@ -99,7 +99,7 @@ test("generated standalone app preserves authority-bound performance iteration l
|
|
|
99
99
|
}
|
|
100
100
|
const output = `${stdout}\n${stderr}`;
|
|
101
101
|
assert.doesNotMatch(output, /ERR_MODULE_NOT_FOUND/u);
|
|
102
|
-
assert.match(output, /^# tests
|
|
103
|
-
assert.match(output, /^# pass
|
|
102
|
+
assert.match(output, /^# tests 11$/mu);
|
|
103
|
+
assert.match(output, /^# pass 11$/mu);
|
|
104
104
|
assert.match(output, /^# fail 0$/mu);
|
|
105
105
|
});
|
|
@@ -31,10 +31,20 @@ const materialBrowserTestNames = Object.freeze([
|
|
|
31
31
|
"browser: frosting color changes material output",
|
|
32
32
|
"browser: gloss changes material output",
|
|
33
33
|
"browser: layer mode changes material output",
|
|
34
|
-
"browser: material appearance reaches exported pixels",
|
|
34
|
+
"browser: material appearance reaches decoded exported pixels",
|
|
35
35
|
"browser: sprinkle color changes material output",
|
|
36
36
|
"browser: sprinkles visibility changes material output",
|
|
37
37
|
]);
|
|
38
|
+
const materialDeliveryBrowserTestNames = Object.freeze([
|
|
39
|
+
"browser: ambient speed changes product output",
|
|
40
|
+
...materialBrowserTestNames,
|
|
41
|
+
"browser: timeline playback drives product output",
|
|
42
|
+
]);
|
|
43
|
+
const materialDeliveryAcceptanceIds = Object.freeze([
|
|
44
|
+
"animation.speed",
|
|
45
|
+
...materialAcceptanceIds,
|
|
46
|
+
"runtime.timeline",
|
|
47
|
+
]);
|
|
38
48
|
const materialProductTestFiles = Object.freeze([
|
|
39
49
|
"src/app/acceptance/validation-pipeline.test.ts",
|
|
40
50
|
"src/app/app-acceptance.base-coverage.test.ts",
|
|
@@ -44,6 +54,7 @@ const materialProductTestFiles = Object.freeze([
|
|
|
44
54
|
"src/app/app-automated-runtime-evidence.test.ts",
|
|
45
55
|
"src/app/app-performance.fixture-helper.test.ts",
|
|
46
56
|
"src/app/app-performance.gates.test.ts",
|
|
57
|
+
"src/app/app-performance.lifecycle.test.ts",
|
|
47
58
|
"src/app/app-schema.test.ts",
|
|
48
59
|
"src/app/material-output.test.tsx",
|
|
49
60
|
]);
|
|
@@ -294,8 +305,8 @@ export async function assertGeneratedFreshDemandOnlyLifecycle({
|
|
|
294
305
|
browserEnv,
|
|
295
306
|
checkpointPath,
|
|
296
307
|
execFileAsync,
|
|
297
|
-
expectedAcceptanceIds:
|
|
298
|
-
expectedBrowserTestNames:
|
|
308
|
+
expectedAcceptanceIds: materialDeliveryAcceptanceIds,
|
|
309
|
+
expectedBrowserTestNames: materialDeliveryBrowserTestNames,
|
|
299
310
|
expectedChangedFiles: generatedProductMaterialIterationFixturePaths,
|
|
300
311
|
expectedProductTestFiles: materialProductTestFiles,
|
|
301
312
|
targetDir,
|
|
@@ -115,15 +115,13 @@ function createGeneratedCommandEnvironment(packageManager, overrides = {}) {
|
|
|
115
115
|
return childEnv;
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
-
|
|
118
|
+
async function executeGeneratedPackageManager(
|
|
119
119
|
execFileAsync,
|
|
120
120
|
targetDir,
|
|
121
|
-
|
|
121
|
+
packageManager,
|
|
122
|
+
packageManagerArgs,
|
|
122
123
|
{ env = {} } = {},
|
|
123
124
|
) {
|
|
124
|
-
const { packageManager } = await readGeneratedPackageManager(targetDir);
|
|
125
|
-
const packageManagerArgs =
|
|
126
|
-
packageManager === "npm" ? ["run", ...args] : args;
|
|
127
125
|
try {
|
|
128
126
|
return await execFileAsync(packageManager, packageManagerArgs, {
|
|
129
127
|
cwd: targetDir,
|
|
@@ -143,6 +141,45 @@ export async function runGeneratedCommand(
|
|
|
143
141
|
}
|
|
144
142
|
}
|
|
145
143
|
|
|
144
|
+
export async function runGeneratedCommand(
|
|
145
|
+
execFileAsync,
|
|
146
|
+
targetDir,
|
|
147
|
+
args,
|
|
148
|
+
options,
|
|
149
|
+
) {
|
|
150
|
+
const { packageManager } = await readGeneratedPackageManager(targetDir);
|
|
151
|
+
const packageManagerArgs =
|
|
152
|
+
packageManager === "npm" ? ["run", ...args] : args;
|
|
153
|
+
return executeGeneratedPackageManager(
|
|
154
|
+
execFileAsync,
|
|
155
|
+
targetDir,
|
|
156
|
+
packageManager,
|
|
157
|
+
packageManagerArgs,
|
|
158
|
+
options,
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export async function runGeneratedExecutable(
|
|
163
|
+
execFileAsync,
|
|
164
|
+
targetDir,
|
|
165
|
+
executableName,
|
|
166
|
+
args,
|
|
167
|
+
options,
|
|
168
|
+
) {
|
|
169
|
+
const { packageManager } = await readGeneratedPackageManager(targetDir);
|
|
170
|
+
const packageManagerArgs =
|
|
171
|
+
packageManager === "npm"
|
|
172
|
+
? ["exec", "--", executableName, ...args]
|
|
173
|
+
: ["exec", executableName, ...args];
|
|
174
|
+
return executeGeneratedPackageManager(
|
|
175
|
+
execFileAsync,
|
|
176
|
+
targetDir,
|
|
177
|
+
packageManager,
|
|
178
|
+
packageManagerArgs,
|
|
179
|
+
options,
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
|
|
146
183
|
export function runGeneratedScript(
|
|
147
184
|
execFileAsync,
|
|
148
185
|
targetDir,
|
|
@@ -26,6 +26,23 @@ const generatedDocPaths = [
|
|
|
26
26
|
const staleAgentPerformanceWorkflowPattern =
|
|
27
27
|
/app-performance-impact|explicit-performance-work|test:browser:perf|verify:(?:final|quick|ui)|verify:perf:(?:playwright|record-iteration|refresh)|--reason=performance-iteration|--performance-test/iu;
|
|
28
28
|
|
|
29
|
+
const generatedPerformanceLifecycleMarkers = [
|
|
30
|
+
"<!-- toolcraft-performance-lifecycle: first-delivery=functional; later-delivery=functional-targeted; complaint=one-authority-targeted-performance-iteration; full-audit=explicit-only -->",
|
|
31
|
+
"<!-- toolcraft-performance-iteration: authority=exact-request-evidence+canonical-path-ids; fixture=reachable-development; after-pass=return-app-to-user+stop -->",
|
|
32
|
+
"<!-- toolcraft-performance-full-authority: automatic=forbidden; recommendation=two-compatible-iterations-or-broad-unlocalizable-problem; command=pnpm verify:perf; authority=explicit-user-request-or-accepted-offer -->",
|
|
33
|
+
"<!-- toolcraft-performance-routing: localized=agent-targeted; ambiguous=one-user-facing-choice; broad=offer-targeted-or-full; full=explicit-only -->",
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
export function getMissingGeneratedPerformanceLifecycleMarkers(sources) {
|
|
37
|
+
return sources.flatMap(({ docPath, source }) =>
|
|
38
|
+
generatedPerformanceLifecycleMarkers.flatMap((marker) =>
|
|
39
|
+
source.includes(marker)
|
|
40
|
+
? []
|
|
41
|
+
: [`docs/toolcraft/${docPath} must include canonical marker: ${marker}`],
|
|
42
|
+
),
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
29
46
|
async function collectMarkdownPaths(rootDir, relativeDir = "") {
|
|
30
47
|
const currentDir = path.join(rootDir, relativeDir);
|
|
31
48
|
const entries = await fs.readdir(currentDir, { withFileTypes: true });
|
|
@@ -83,6 +100,10 @@ export async function assertGeneratedDocs(targetDir) {
|
|
|
83
100
|
await collectGeneratedAgentFacingDocs(targetDir),
|
|
84
101
|
);
|
|
85
102
|
|
|
103
|
+
assert.match(noticeSource, /Mediabunny/u);
|
|
104
|
+
assert.match(noticeSource, /MPL-2\.0/u);
|
|
105
|
+
assert.match(noticeSource, /https:\/\/github\.com\/Vanilagy\/mediabunny/u);
|
|
106
|
+
|
|
86
107
|
assert.deepEqual(
|
|
87
108
|
staleWorkflowFailures,
|
|
88
109
|
[],
|
|
@@ -139,6 +160,7 @@ export async function assertGeneratedDocs(targetDir) {
|
|
|
139
160
|
assert.match(agentsSource, /defineToolcraft/);
|
|
140
161
|
assert.match(agentsSource, /ToolcraftApp/);
|
|
141
162
|
assert.match(agentsSource, /canvasContent/);
|
|
163
|
+
assert.match(agentsSource, /exportRenderer/);
|
|
142
164
|
assert.match(agentsSource, /renderDefaultCanvasMedia=\{false\}/);
|
|
143
165
|
assert.match(agentsSource, /onPanelAction/);
|
|
144
166
|
assert.match(agentsSource, /MIT License/);
|
|
@@ -213,6 +235,8 @@ export async function assertGeneratedDocs(targetDir) {
|
|
|
213
235
|
assert.match(coreRuntimeBoundarySource, /immutable signed copy of the shared runtime/);
|
|
214
236
|
assert.match(coreRuntimeBoundarySource, /copied runtime tree or its signed integrity manifest is missing/);
|
|
215
237
|
assert.match(coreRuntimeBoundarySource, /modelPresentation/);
|
|
238
|
+
assert.match(coreRuntimeBoundarySource, /exportRenderer/);
|
|
239
|
+
assert.match(coreRuntimeBoundarySource, /runtime owns typed image\/video actions end to end/i);
|
|
216
240
|
assert.match(coreRuntimeBoundarySource, /does not suppress runtime model layers/);
|
|
217
241
|
assert.match(componentRulesSource, /Do not show Layers for a single-layer app/);
|
|
218
242
|
assert.match(coreTimelineSource, /Any app with `Export Video` must enable the top Toolcraft timeline/);
|
|
@@ -225,6 +249,17 @@ export async function assertGeneratedDocs(targetDir) {
|
|
|
225
249
|
assert.match(coreSetupExportSource, /renderScaleCoverage/);
|
|
226
250
|
assert.match(coreSetupExportSource, /selected-backing-pixels/);
|
|
227
251
|
assert.match(coreSetupExportSource, /canvas-render-scale-backing/);
|
|
252
|
+
assert.match(coreSetupExportSource, /Mediabunny/);
|
|
253
|
+
assert.match(coreSetupExportSource, /fixed 30 FPS offline schedule/);
|
|
254
|
+
assert.match(coreSetupExportSource, /Product code must not instantiate `MediaRecorder` or `VideoEncoder`/);
|
|
255
|
+
assert.doesNotMatch(
|
|
256
|
+
coreSetupExportSource,
|
|
257
|
+
/createToolcraftPngExportCanvas|renderRuntimeSceneToCanvas|renderModelsToCanvas/,
|
|
258
|
+
);
|
|
259
|
+
assert.doesNotMatch(
|
|
260
|
+
coreMediaUploadSource,
|
|
261
|
+
/createToolcraftPngExportCanvas|renderRuntimeSceneToCanvas|renderModelsToCanvas/,
|
|
262
|
+
);
|
|
228
263
|
assert.match(
|
|
229
264
|
coreSetupExportSource,
|
|
230
265
|
/interaction[\s\S]*steady[\s\S]*playback[\s\S]*timeline/i,
|
|
@@ -269,6 +304,8 @@ export async function assertGeneratedDocs(targetDir) {
|
|
|
269
304
|
acceptanceDocsSource,
|
|
270
305
|
/export-content proof is distinct from export mechanics/i,
|
|
271
306
|
);
|
|
307
|
+
assert.match(acceptanceDocsSource, /actual encoded packet metadata/i);
|
|
308
|
+
assert.match(acceptanceDocsSource, /distinct decoded frame hashes/i);
|
|
272
309
|
assert.match(
|
|
273
310
|
acceptanceDocsSource,
|
|
274
311
|
/Each browser file owns one acceptance domain/i,
|
|
@@ -312,24 +349,14 @@ export async function assertGeneratedDocs(targetDir) {
|
|
|
312
349
|
path.join(targetDir, "docs/toolcraft/core/performance.md"),
|
|
313
350
|
"utf8",
|
|
314
351
|
);
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
[
|
|
322
|
-
|
|
323
|
-
["core/performance.md", corePerformanceDocsSource],
|
|
324
|
-
]) {
|
|
325
|
-
for (const marker of performanceLifecycleMarkers) {
|
|
326
|
-
assert.equal(
|
|
327
|
-
source.includes(marker),
|
|
328
|
-
true,
|
|
329
|
-
`docs/toolcraft/${docPath} must include canonical marker: ${marker}`,
|
|
330
|
-
);
|
|
331
|
-
}
|
|
332
|
-
}
|
|
352
|
+
assert.deepEqual(
|
|
353
|
+
getMissingGeneratedPerformanceLifecycleMarkers([
|
|
354
|
+
{ docPath: "workflow.md", source: workflowDocsSource },
|
|
355
|
+
{ docPath: "performance.md", source: performanceDocsSource },
|
|
356
|
+
{ docPath: "core/performance.md", source: corePerformanceDocsSource },
|
|
357
|
+
]),
|
|
358
|
+
[],
|
|
359
|
+
);
|
|
333
360
|
assert.match(rendererDocsSource, /rendererTechnique/);
|
|
334
361
|
assert.match(rendererDocsSource, /sourceRepresentation/);
|
|
335
362
|
assert.match(rendererDocsSource, /whyNotAlternativeStrategies/);
|
|
@@ -339,6 +366,7 @@ export async function assertGeneratedDocs(targetDir) {
|
|
|
339
366
|
assert.match(rendererDocsSource, /canonical paths/i);
|
|
340
367
|
assert.match(rendererDocsSource, /combined fixtures/i);
|
|
341
368
|
assert.match(rendererDocsSource, /modelPresentation/);
|
|
369
|
+
assert.match(rendererDocsSource, /ToolcraftAppComposition\.exportRenderer/);
|
|
342
370
|
assert.match(rendererDocsSource, /useToolcraftModelPresentationConsumer/);
|
|
343
371
|
assert.match(rendererDocsSource, /acquirePresentation/);
|
|
344
372
|
assert.match(rendererDocsSource, /lease\.release/);
|
|
@@ -367,12 +395,34 @@ export async function assertGeneratedDocs(targetDir) {
|
|
|
367
395
|
corePerformanceDocsSource,
|
|
368
396
|
/functional failure[\s\S]*without measured performance/i,
|
|
369
397
|
);
|
|
398
|
+
assert.match(corePerformanceDocsSource, /exact 30 FPS packet cadence[\s\S]*functional correctness/i);
|
|
399
|
+
assert.match(performanceDocsSource, /exact 30 FPS packet cadence[\s\S]*functional proof/i);
|
|
370
400
|
assert.match(performanceDocsSource, /coherent (?:user-visible )?delivery batch/i);
|
|
371
401
|
assert.match(performanceDocsSource, /verify:delivery/);
|
|
372
402
|
assert.match(performanceDocsSource, /immediately previous successful delivery/i);
|
|
373
403
|
assert.match(performanceDocsSource, /performance-iteration/);
|
|
374
404
|
assert.match(performanceDocsSource, /renderScaleCoverage/);
|
|
375
405
|
assert.match(performanceDocsSource, /canvas-render-scale-backing/);
|
|
406
|
+
assert.match(
|
|
407
|
+
performanceDocsSource,
|
|
408
|
+
/localized complaint[^\n]*without (?:a |asking the user)/iu,
|
|
409
|
+
);
|
|
410
|
+
assert.match(
|
|
411
|
+
performanceDocsSource,
|
|
412
|
+
/ambiguous complaint[\s\S]*one user-facing/iu,
|
|
413
|
+
);
|
|
414
|
+
assert.match(
|
|
415
|
+
performanceDocsSource,
|
|
416
|
+
/targeted diagnosis[\s\S]*complete (?:performance )?review/iu,
|
|
417
|
+
);
|
|
418
|
+
assert.match(
|
|
419
|
+
performanceDocsSource,
|
|
420
|
+
/every measured path[\s\S]*devicePixelRatio × 2/iu,
|
|
421
|
+
);
|
|
422
|
+
assert.match(
|
|
423
|
+
coreSetupExportSource,
|
|
424
|
+
/product code may customize only the slider step/iu,
|
|
425
|
+
);
|
|
376
426
|
assert.match(performanceDocsSource, /Use bare `npm run verify:delivery` once/i);
|
|
377
427
|
assert.match(
|
|
378
428
|
workflowDocsSource,
|
|
@@ -6,6 +6,7 @@ import test from "node:test";
|
|
|
6
6
|
|
|
7
7
|
import {
|
|
8
8
|
collectGeneratedAgentFacingDocs,
|
|
9
|
+
getMissingGeneratedPerformanceLifecycleMarkers,
|
|
9
10
|
getStaleAgentPerformanceWorkflowFailures,
|
|
10
11
|
} from "./generate-test-doc-assertions.mjs";
|
|
11
12
|
|
|
@@ -41,3 +42,24 @@ test("scans every generated agent-facing Markdown source independently", async (
|
|
|
41
42
|
"docs/toolcraft/core/performance.md contains removed performance workflow guidance",
|
|
42
43
|
]);
|
|
43
44
|
});
|
|
45
|
+
|
|
46
|
+
test("requires adaptive routing in every generated performance lifecycle document", () => {
|
|
47
|
+
const routingMarker =
|
|
48
|
+
"<!-- toolcraft-performance-routing: localized=agent-targeted; ambiguous=one-user-facing-choice; broad=offer-targeted-or-full; full=explicit-only -->";
|
|
49
|
+
const existingMarkers = [
|
|
50
|
+
"<!-- toolcraft-performance-lifecycle: first-delivery=functional; later-delivery=functional-targeted; complaint=one-authority-targeted-performance-iteration; full-audit=explicit-only -->",
|
|
51
|
+
"<!-- toolcraft-performance-iteration: authority=exact-request-evidence+canonical-path-ids; fixture=reachable-development; after-pass=return-app-to-user+stop -->",
|
|
52
|
+
"<!-- toolcraft-performance-full-authority: automatic=forbidden; recommendation=two-compatible-iterations-or-broad-unlocalizable-problem; command=pnpm verify:perf; authority=explicit-user-request-or-accepted-offer -->",
|
|
53
|
+
].join("\n");
|
|
54
|
+
|
|
55
|
+
assert.deepEqual(
|
|
56
|
+
getMissingGeneratedPerformanceLifecycleMarkers([
|
|
57
|
+
{ docPath: "workflow.md", source: `${existingMarkers}\n${routingMarker}` },
|
|
58
|
+
{ docPath: "performance.md", source: existingMarkers },
|
|
59
|
+
{ docPath: "core/performance.md", source: `${existingMarkers}\n${routingMarker}` },
|
|
60
|
+
]),
|
|
61
|
+
[
|
|
62
|
+
`docs/toolcraft/performance.md must include canonical marker: ${routingMarker}`,
|
|
63
|
+
],
|
|
64
|
+
);
|
|
65
|
+
});
|
|
@@ -6,9 +6,15 @@ import {
|
|
|
6
6
|
assertGeneratedDeliveryArchitecture,
|
|
7
7
|
deliveryArchitecturePaths,
|
|
8
8
|
} from "./generate-test-delivery-architecture-assertions.mjs";
|
|
9
|
-
import { listRelativeFiles,
|
|
9
|
+
import { listRelativeFiles, repoRoot } from "./generate-test-fs-utils.mjs";
|
|
10
|
+
import { assertGeneratedPerformanceCanvasBoundary } from "./generate-test-performance-boundary-assertions.mjs";
|
|
10
11
|
import { isGeneratedTestSupportPath } from "./generated-source-policy.mjs";
|
|
11
12
|
|
|
13
|
+
export {
|
|
14
|
+
assertGeneratedRoutesAndStyles,
|
|
15
|
+
assertGeneratedTextIsStandalone,
|
|
16
|
+
} from "./generate-test-output-assertions.mjs";
|
|
17
|
+
|
|
12
18
|
function assertSignedProtectedFiles(manifest, relativePaths, responsibility) {
|
|
13
19
|
for (const relativePath of relativePaths) {
|
|
14
20
|
assert.ok(
|
|
@@ -68,6 +74,39 @@ export async function assertGeneratedFiles(targetDir) {
|
|
|
68
74
|
expectedRuntimeFiles,
|
|
69
75
|
"Generated standalone runtime must contain every production runtime module.",
|
|
70
76
|
);
|
|
77
|
+
for (const relativePath of [
|
|
78
|
+
"runtime/export/artifact-export-settings.ts",
|
|
79
|
+
"runtime/export/artifact-export-request.ts",
|
|
80
|
+
"runtime/export/artifact-frame-renderer.ts",
|
|
81
|
+
"runtime/export/artifact-frame-state.ts",
|
|
82
|
+
"runtime/export/artifact-scene-frame.ts",
|
|
83
|
+
"runtime/export/image-artifact-export.ts",
|
|
84
|
+
"runtime/export/product-export-renderer.ts",
|
|
85
|
+
"runtime/export/video-artifact-export.ts",
|
|
86
|
+
"runtime/export/video-encoding-backend.ts",
|
|
87
|
+
"runtime/export/video-frame-schedule.ts",
|
|
88
|
+
]) {
|
|
89
|
+
assert.ok(
|
|
90
|
+
generatedToolcraftFiles.includes(relativePath),
|
|
91
|
+
`Generated runtime must contain ${relativePath}.`,
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
assert.equal(
|
|
95
|
+
generatedToolcraftFiles.includes("runtime/export/export.ts"),
|
|
96
|
+
false,
|
|
97
|
+
"Generated runtime must not copy the removed legacy export helper.",
|
|
98
|
+
);
|
|
99
|
+
for (const relativePath of [
|
|
100
|
+
"e2e/browser-media-export-evidence.ts",
|
|
101
|
+
"e2e/decoded-pixel-observation.ts",
|
|
102
|
+
"e2e/image-artifact-inspection.ts",
|
|
103
|
+
"e2e/video-artifact-inspection.ts",
|
|
104
|
+
]) {
|
|
105
|
+
assert.ok(
|
|
106
|
+
await fs.stat(path.join(targetDir, relativePath)),
|
|
107
|
+
`Generated output must contain ${relativePath}.`,
|
|
108
|
+
);
|
|
109
|
+
}
|
|
71
110
|
for (const relativePath of generatedToolcraftFiles) {
|
|
72
111
|
assert.equal(
|
|
73
112
|
isGeneratedTestSupportPath(relativePath),
|
|
@@ -96,9 +135,7 @@ export async function assertGeneratedFiles(targetDir) {
|
|
|
96
135
|
await listRelativeFiles(path.join(repoRoot, "starter/e2e")),
|
|
97
136
|
);
|
|
98
137
|
assert.ok(await fs.stat(path.join(targetDir, "e2e/app-controls.spec.ts")));
|
|
99
|
-
|
|
100
|
-
await fs.stat(path.join(targetDir, "e2e/app-performance-path-adapters.ts")),
|
|
101
|
-
);
|
|
138
|
+
await assertGeneratedPerformanceCanvasBoundary(targetDir);
|
|
102
139
|
|
|
103
140
|
const generatedAppSourceFiles = await listRelativeFiles(path.join(targetDir, "src/app"));
|
|
104
141
|
assert.ok(await fs.stat(path.join(targetDir, "src/app/app-schema.ts")));
|
|
@@ -350,6 +387,8 @@ export async function assertGeneratedFiles(targetDir) {
|
|
|
350
387
|
"e2e/performance-measurement-evidence.ts",
|
|
351
388
|
"e2e/performance-path-adapter-contract.ts",
|
|
352
389
|
"e2e/performance-path-helpers.ts",
|
|
390
|
+
"e2e/performance-canvas-quality-observer.ts",
|
|
391
|
+
"e2e/performance-canvas-quality-guard.ts",
|
|
353
392
|
"e2e/performance-slider-helpers.ts",
|
|
354
393
|
"scripts/toolcraft-performance-report.mjs",
|
|
355
394
|
"scripts/toolcraft-kernel-benchmark-receipt.mjs",
|
|
@@ -415,75 +454,3 @@ export async function assertGeneratedFiles(targetDir) {
|
|
|
415
454
|
undefined,
|
|
416
455
|
);
|
|
417
456
|
}
|
|
418
|
-
|
|
419
|
-
export async function assertGeneratedRoutesAndStyles(targetDir) {
|
|
420
|
-
await assert.rejects(
|
|
421
|
-
() => fs.stat(path.join(targetDir, "src/toolcraft/runtime/react/canvas-shell.test.tsx")),
|
|
422
|
-
/ENOENT/,
|
|
423
|
-
);
|
|
424
|
-
|
|
425
|
-
const routeSource = await fs.readFile(path.join(targetDir, "src/routes/index.tsx"), "utf8");
|
|
426
|
-
assert.match(routeSource, /@\/toolcraft\/runtime\/react/);
|
|
427
|
-
assert.match(routeSource, /\.\.\/app\/app-composition/);
|
|
428
|
-
assert.match(routeSource, /canvasContent=\{appComposition\.canvasContent\}/);
|
|
429
|
-
assert.match(routeSource, /controlRenderers=\{appComposition\.controlRenderers\}/);
|
|
430
|
-
assert.match(routeSource, /modelPresentation=\{appComposition\.modelPresentation\}/);
|
|
431
|
-
assert.match(routeSource, /onPanelAction=\{appComposition\.onPanelAction\}/);
|
|
432
|
-
assert.match(
|
|
433
|
-
routeSource,
|
|
434
|
-
/renderDefaultCanvasMedia=\{appComposition\.renderDefaultCanvasMedia\}/,
|
|
435
|
-
);
|
|
436
|
-
assert.match(
|
|
437
|
-
routeSource,
|
|
438
|
-
/rendererPipelineRegistration=\{appComposition\.rendererPipelineRegistration\}/,
|
|
439
|
-
);
|
|
440
|
-
assert.match(
|
|
441
|
-
routeSource,
|
|
442
|
-
/sceneBoundsProvider=\{appComposition\.sceneBoundsProvider\}/,
|
|
443
|
-
);
|
|
444
|
-
assert.match(routeSource, /schema=\{appComposition\.schema\}/);
|
|
445
|
-
assert.match(routeSource, /className="h-dvh min-h-dvh"/);
|
|
446
|
-
assert.doesNotMatch(routeSource, /\{\.\.\.appComposition\}/);
|
|
447
|
-
assert.doesNotMatch(routeSource, /appSchema|ProductCanvas/);
|
|
448
|
-
|
|
449
|
-
const compositionSource = await fs.readFile(
|
|
450
|
-
path.join(targetDir, "src/app/app-composition.tsx"),
|
|
451
|
-
"utf8",
|
|
452
|
-
);
|
|
453
|
-
assert.match(
|
|
454
|
-
compositionSource,
|
|
455
|
-
/import type \{ ToolcraftAppComposition \} from "@\/toolcraft\/runtime\/react"/,
|
|
456
|
-
);
|
|
457
|
-
assert.match(compositionSource, /export const appComposition/);
|
|
458
|
-
assert.match(compositionSource, /appComposition\s*:\s*ToolcraftAppComposition\s*=/);
|
|
459
|
-
assert.match(compositionSource, /modelPresentation:\s*\{\s*mode:\s*"runtime"\s*\}/);
|
|
460
|
-
|
|
461
|
-
const stylesSource = await fs.readFile(path.join(targetDir, "src/styles.css"), "utf8");
|
|
462
|
-
assert.match(stylesSource, /@source "\.\/toolcraft\/ui";/);
|
|
463
|
-
assert.match(stylesSource, /@import "@\/toolcraft\/ui\/styles\.css";/);
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
export async function assertGeneratedTextIsStandalone(targetDir) {
|
|
467
|
-
const allText = await readTextFiles(targetDir);
|
|
468
|
-
assert.doesNotMatch(allText, /BEGIN PRIVATE KEY/);
|
|
469
|
-
assert.doesNotMatch(allText, /@repo\/ui|@repo\/toolcraft-runtime|workspace:/);
|
|
470
|
-
assert.doesNotMatch(allText, new RegExp("template" + "-runtime"));
|
|
471
|
-
assert.doesNotMatch(allText, /packages\/typescript-config/);
|
|
472
|
-
assert.doesNotMatch(
|
|
473
|
-
allText,
|
|
474
|
-
/prototype-smoke|browser-functional-smoke|performance-smoke|app-performance-smoke|toolcraft-performance-smoke-runner/,
|
|
475
|
-
);
|
|
476
|
-
assert.doesNotMatch(
|
|
477
|
-
allText,
|
|
478
|
-
/starterComposition|starter-composition|starterSchema|starter-schema|starterAcceptance|starterControlSectionInventory|starter-acceptance|starterProductReadiness|starterTransferMode|starterPerformance|starter-performance|StarterHome|Toolcraft Starter/,
|
|
479
|
-
);
|
|
480
|
-
|
|
481
|
-
const kernelReceiptDeclaration = await fs.readFile(
|
|
482
|
-
path.join(targetDir, "scripts/toolcraft-kernel-benchmark-receipt.d.mts"),
|
|
483
|
-
"utf8",
|
|
484
|
-
);
|
|
485
|
-
assert.match(
|
|
486
|
-
kernelReceiptDeclaration,
|
|
487
|
-
/from "@\/toolcraft\/runtime"/,
|
|
488
|
-
);
|
|
489
|
-
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import fs from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
|
|
5
|
+
import { readTextFiles } from "./generate-test-fs-utils.mjs";
|
|
6
|
+
|
|
7
|
+
export async function assertGeneratedRoutesAndStyles(targetDir) {
|
|
8
|
+
await assert.rejects(
|
|
9
|
+
() =>
|
|
10
|
+
fs.stat(
|
|
11
|
+
path.join(
|
|
12
|
+
targetDir,
|
|
13
|
+
"src/toolcraft/runtime/react/canvas-shell.test.tsx",
|
|
14
|
+
),
|
|
15
|
+
),
|
|
16
|
+
/ENOENT/,
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
const routeSource = await fs.readFile(
|
|
20
|
+
path.join(targetDir, "src/routes/index.tsx"),
|
|
21
|
+
"utf8",
|
|
22
|
+
);
|
|
23
|
+
assert.match(routeSource, /@\/toolcraft\/runtime\/react/);
|
|
24
|
+
assert.match(routeSource, /\.\.\/app\/app-composition/);
|
|
25
|
+
assert.match(routeSource, /canvasContent=\{appComposition\.canvasContent\}/);
|
|
26
|
+
assert.match(routeSource, /controlRenderers=\{appComposition\.controlRenderers\}/);
|
|
27
|
+
assert.match(routeSource, /modelPresentation=\{appComposition\.modelPresentation\}/);
|
|
28
|
+
assert.match(routeSource, /onPanelAction=\{appComposition\.onPanelAction\}/);
|
|
29
|
+
assert.match(
|
|
30
|
+
routeSource,
|
|
31
|
+
/renderDefaultCanvasMedia=\{appComposition\.renderDefaultCanvasMedia\}/,
|
|
32
|
+
);
|
|
33
|
+
assert.match(
|
|
34
|
+
routeSource,
|
|
35
|
+
/rendererPipelineRegistration=\{appComposition\.rendererPipelineRegistration\}/,
|
|
36
|
+
);
|
|
37
|
+
assert.match(
|
|
38
|
+
routeSource,
|
|
39
|
+
/sceneBoundsProvider=\{appComposition\.sceneBoundsProvider\}/,
|
|
40
|
+
);
|
|
41
|
+
assert.match(routeSource, /schema=\{appComposition\.schema\}/);
|
|
42
|
+
assert.match(routeSource, /className="h-dvh min-h-dvh"/);
|
|
43
|
+
assert.doesNotMatch(routeSource, /\{\.\.\.appComposition\}/);
|
|
44
|
+
assert.doesNotMatch(routeSource, /appSchema|ProductCanvas/);
|
|
45
|
+
|
|
46
|
+
const compositionSource = await fs.readFile(
|
|
47
|
+
path.join(targetDir, "src/app/app-composition.tsx"),
|
|
48
|
+
"utf8",
|
|
49
|
+
);
|
|
50
|
+
assert.match(
|
|
51
|
+
compositionSource,
|
|
52
|
+
/import type \{ ToolcraftAppComposition \} from "@\/toolcraft\/runtime\/react"/,
|
|
53
|
+
);
|
|
54
|
+
assert.match(compositionSource, /export const appComposition/);
|
|
55
|
+
assert.match(
|
|
56
|
+
compositionSource,
|
|
57
|
+
/appComposition\s*:\s*ToolcraftAppComposition\s*=/,
|
|
58
|
+
);
|
|
59
|
+
assert.match(
|
|
60
|
+
compositionSource,
|
|
61
|
+
/modelPresentation:\s*\{\s*mode:\s*"runtime"\s*\}/,
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
const stylesSource = await fs.readFile(
|
|
65
|
+
path.join(targetDir, "src/styles.css"),
|
|
66
|
+
"utf8",
|
|
67
|
+
);
|
|
68
|
+
assert.match(stylesSource, /@source "\.\/toolcraft\/ui";/);
|
|
69
|
+
assert.match(stylesSource, /@import "@\/toolcraft\/ui\/styles\.css";/);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export async function assertGeneratedTextIsStandalone(targetDir) {
|
|
73
|
+
const allText = await readTextFiles(targetDir);
|
|
74
|
+
assert.doesNotMatch(allText, /BEGIN PRIVATE KEY/);
|
|
75
|
+
assert.doesNotMatch(allText, /@repo\/ui|@repo\/toolcraft-runtime|workspace:/);
|
|
76
|
+
assert.doesNotMatch(allText, new RegExp("template" + "-runtime"));
|
|
77
|
+
assert.doesNotMatch(allText, /packages\/typescript-config/);
|
|
78
|
+
assert.doesNotMatch(
|
|
79
|
+
allText,
|
|
80
|
+
/prototype-smoke|browser-functional-smoke|performance-smoke|app-performance-smoke|toolcraft-performance-smoke-runner/,
|
|
81
|
+
);
|
|
82
|
+
assert.doesNotMatch(
|
|
83
|
+
allText,
|
|
84
|
+
/starterComposition|starter-composition|starterSchema|starter-schema|starterAcceptance|starterControlSectionInventory|starter-acceptance|starterProductReadiness|starterTransferMode|starterPerformance|starter-performance|StarterHome|Toolcraft Starter/,
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
const kernelReceiptDeclaration = await fs.readFile(
|
|
88
|
+
path.join(
|
|
89
|
+
targetDir,
|
|
90
|
+
"scripts/toolcraft-kernel-benchmark-receipt.d.mts",
|
|
91
|
+
),
|
|
92
|
+
"utf8",
|
|
93
|
+
);
|
|
94
|
+
assert.match(kernelReceiptDeclaration, /from "@\/toolcraft\/runtime"/);
|
|
95
|
+
}
|
|
@@ -16,6 +16,11 @@ export async function assertGeneratedPackageJson(targetDir) {
|
|
|
16
16
|
assert.equal(packageJson.dependencies.fflate, "0.8.3");
|
|
17
17
|
assert.equal(packageJson.dependencies.draco3dgltf, undefined);
|
|
18
18
|
assert.equal(packageJson.dependencies.meshoptimizer, "1.2.0");
|
|
19
|
+
assert.equal(
|
|
20
|
+
packageJson.dependencies.mediabunny,
|
|
21
|
+
"1.52.2",
|
|
22
|
+
"Generated apps must pin the runtime-owned timestamped video encoder.",
|
|
23
|
+
);
|
|
19
24
|
assert.equal(packageJson.dependencies["react-resizable-panels"], "^4.10.0");
|
|
20
25
|
assert.equal(packageJson.dependencies.sonner, "^2.0.7");
|
|
21
26
|
assert.equal(packageJson.dependencies.three, "0.185.1");
|
|
@@ -76,6 +81,7 @@ export async function assertGeneratedGitignore(targetDir) {
|
|
|
76
81
|
assert.match(gitignoreSource, /node_modules/);
|
|
77
82
|
assert.match(gitignoreSource, /dist/);
|
|
78
83
|
assert.match(gitignoreSource, /playwright-report/);
|
|
84
|
+
assert.match(gitignoreSource, /^\.playwright-mcp$/mu);
|
|
79
85
|
assert.match(gitignoreSource, /\.env\.\*/);
|
|
80
86
|
assert.match(gitignoreSource, /\.toolcraft/);
|
|
81
87
|
await assert.rejects(() => fs.stat(path.join(targetDir, "gitignore")), /ENOENT/);
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import fs from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
|
|
5
|
+
export async function assertGeneratedPerformanceCanvasBoundary(targetDir) {
|
|
6
|
+
const [
|
|
7
|
+
adaptersSource,
|
|
8
|
+
adapterContractSource,
|
|
9
|
+
guardSource,
|
|
10
|
+
helpersSource,
|
|
11
|
+
] = await Promise.all([
|
|
12
|
+
fs.readFile(
|
|
13
|
+
path.join(targetDir, "e2e/app-performance-path-adapters.ts"),
|
|
14
|
+
"utf8",
|
|
15
|
+
),
|
|
16
|
+
fs.readFile(
|
|
17
|
+
path.join(targetDir, "e2e/performance-path-adapter-contract.ts"),
|
|
18
|
+
"utf8",
|
|
19
|
+
),
|
|
20
|
+
fs.readFile(
|
|
21
|
+
path.join(targetDir, "e2e/performance-canvas-quality-guard.ts"),
|
|
22
|
+
"utf8",
|
|
23
|
+
),
|
|
24
|
+
fs.readFile(
|
|
25
|
+
path.join(targetDir, "e2e/performance-path-helpers.ts"),
|
|
26
|
+
"utf8",
|
|
27
|
+
),
|
|
28
|
+
fs.stat(path.join(targetDir, "e2e/performance-canvas-quality-observer.ts")),
|
|
29
|
+
fs.stat(
|
|
30
|
+
path.join(targetDir, "e2e/performance-canvas-quality-guard.spec.ts"),
|
|
31
|
+
),
|
|
32
|
+
]);
|
|
33
|
+
|
|
34
|
+
assert.match(adaptersSource, /appPerformanceCanvasBacking/u);
|
|
35
|
+
assert.doesNotMatch(adapterContractSource, /renderScaleBacking\?:/u);
|
|
36
|
+
assert.match(helpersSource, /schema\.canvas\.renderScale\.enabled/u);
|
|
37
|
+
assert.match(
|
|
38
|
+
guardSource,
|
|
39
|
+
/from "\.\/performance-canvas-quality-observer"/u,
|
|
40
|
+
);
|
|
41
|
+
assert.match(
|
|
42
|
+
helpersSource,
|
|
43
|
+
/from "\.\/performance-canvas-quality-guard"/u,
|
|
44
|
+
);
|
|
45
|
+
}
|
|
@@ -38,6 +38,7 @@ export const generatedProductFixturePaths = Object.freeze([
|
|
|
38
38
|
"e2e/product-canvas.spec.ts",
|
|
39
39
|
"e2e/product-export.spec.ts",
|
|
40
40
|
"e2e/product-material.spec.ts",
|
|
41
|
+
"e2e/product-media-export-fixture.ts",
|
|
41
42
|
"e2e/product-runtime.spec.ts",
|
|
42
43
|
"e2e/product-test-utils.ts",
|
|
43
44
|
generatedProductPresentationResourcePath,
|
|
@@ -15,6 +15,11 @@ import {
|
|
|
15
15
|
writeGeneratedProductFixture,
|
|
16
16
|
} from "./generate-test-product-fixture.mjs";
|
|
17
17
|
|
|
18
|
+
const generatedProductFixtureRoot = new URL(
|
|
19
|
+
"../fixtures/generated-product/",
|
|
20
|
+
import.meta.url,
|
|
21
|
+
);
|
|
22
|
+
|
|
18
23
|
it("rejects unknown and missing product fixture paths", () => {
|
|
19
24
|
assert.deepEqual(generatedProductAuthorityFixturePaths, [
|
|
20
25
|
"docs/toolcraft/agent-worklog.md",
|
|
@@ -106,6 +111,19 @@ it("rejects unknown and missing product fixture paths", () => {
|
|
|
106
111
|
);
|
|
107
112
|
});
|
|
108
113
|
|
|
114
|
+
it("keeps the vector product overlay explicit about canvas backing", async () => {
|
|
115
|
+
const adaptersSource = await fs.readFile(
|
|
116
|
+
new URL("e2e/app-performance-path-adapters.ts", generatedProductFixtureRoot),
|
|
117
|
+
"utf8",
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
assert.match(adaptersSource, /ToolcraftPerformanceCanvasBacking/u);
|
|
121
|
+
assert.match(
|
|
122
|
+
adaptersSource,
|
|
123
|
+
/appPerformanceCanvasBacking[\s\S]*undefined\s*=\s*undefined/u,
|
|
124
|
+
);
|
|
125
|
+
});
|
|
126
|
+
|
|
109
127
|
it("reads only an exact supported command from generated authority policy", async () => {
|
|
110
128
|
const targetDir = await fs.mkdtemp(
|
|
111
129
|
path.join(os.tmpdir(), "toolcraft-product-manager-"),
|