@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
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
|
|
4
|
+
import { describe, expect, it } from "vitest";
|
|
5
|
+
import {
|
|
6
|
+
TOOLCRAFT_DELIVERY_VERIFICATION_COMMAND,
|
|
7
|
+
TOOLCRAFT_FULL_PERFORMANCE_VERIFICATION_COMMAND,
|
|
8
|
+
} from "../../scripts/toolcraft-performance-authority-policy.mjs";
|
|
9
|
+
import { requiredPackageScriptNames } from "../../scripts/toolcraft-integrity-policy.mjs";
|
|
10
|
+
|
|
11
|
+
import { projectDir } from "./starter-performance-test-utils";
|
|
12
|
+
|
|
13
|
+
const expectedRequiredPackageScriptNames = [
|
|
14
|
+
"ai:check", "build", "dev", "dev:restart", "docs:check", "preview",
|
|
15
|
+
"preview:restart", "test", "test:browser", "typecheck", "verify:delivery",
|
|
16
|
+
"verify:kernel", "verify:perf", "verify:receipt",
|
|
17
|
+
] as const;
|
|
18
|
+
|
|
19
|
+
describe("Toolcraft starter performance lifecycle", () => {
|
|
20
|
+
it("publishes separate functional acceptance and performance gates", () => {
|
|
21
|
+
const packageJson = JSON.parse(readFileSync(join(projectDir, "package.json"), "utf8")) as {
|
|
22
|
+
scripts?: Record<string, string>;
|
|
23
|
+
};
|
|
24
|
+
const generatedAppTestScript =
|
|
25
|
+
packageJson.scripts?.["test:generated"] ?? packageJson.scripts?.test;
|
|
26
|
+
|
|
27
|
+
expect(requiredPackageScriptNames).toEqual(expectedRequiredPackageScriptNames);
|
|
28
|
+
for (const scriptName of requiredPackageScriptNames) {
|
|
29
|
+
expect(packageJson.scripts?.[scriptName]).toBeDefined();
|
|
30
|
+
}
|
|
31
|
+
for (const removed of [
|
|
32
|
+
"test:delivery", "verify:final", "verify:perf:record-iteration",
|
|
33
|
+
"verify:quick", "verify:ui",
|
|
34
|
+
]) {
|
|
35
|
+
expect(packageJson.scripts?.[removed]).toBeUndefined();
|
|
36
|
+
}
|
|
37
|
+
expect(packageJson.scripts?.["ai:check"]).toBe(
|
|
38
|
+
"node scripts/check-toolcraft-code-health.mjs",
|
|
39
|
+
);
|
|
40
|
+
const sourceTestScript =
|
|
41
|
+
"node scripts/check-toolcraft-docs.mjs && node --test scripts/*.test.mjs && vitest run src --passWithNoTests --reporter=default --reporter=./scripts/toolcraft-vitest-runtime-evidence-reporter.mjs";
|
|
42
|
+
const generatedTestScript =
|
|
43
|
+
"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";
|
|
44
|
+
if (packageJson.scripts?.["test:generated"]) {
|
|
45
|
+
expect(packageJson.scripts.test).toBe(sourceTestScript);
|
|
46
|
+
expect(packageJson.scripts["test:generated"]).toBe(generatedTestScript);
|
|
47
|
+
} else {
|
|
48
|
+
expect(packageJson.scripts?.test).toBe(generatedTestScript);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
expect(
|
|
52
|
+
generatedAppTestScript,
|
|
53
|
+
"Generated app tests must invoke the Toolcraft integrity checker.",
|
|
54
|
+
).toContain("node scripts/check-toolcraft-integrity.mjs");
|
|
55
|
+
expect(
|
|
56
|
+
packageJson.scripts?.["test:browser"],
|
|
57
|
+
"Generated apps must keep measured performance and kernel benchmark scenarios out of the default browser acceptance gate.",
|
|
58
|
+
).toBe(
|
|
59
|
+
'playwright install chromium && playwright test --grep-invert "browser perf:|toolcraft kernel:"',
|
|
60
|
+
);
|
|
61
|
+
expect(packageJson.scripts?.["test:browser:perf"]).toBeUndefined();
|
|
62
|
+
const performanceRunner = readFileSync(
|
|
63
|
+
join(projectDir, "scripts/run-browser-performance.mjs"),
|
|
64
|
+
"utf8",
|
|
65
|
+
);
|
|
66
|
+
const receiptModule = readFileSync(
|
|
67
|
+
join(projectDir, "scripts/toolcraft-verification-receipt.mjs"),
|
|
68
|
+
"utf8",
|
|
69
|
+
);
|
|
70
|
+
const deliveryRunner = readFileSync(
|
|
71
|
+
join(projectDir, "scripts/run-delivery-verification.mjs"),
|
|
72
|
+
"utf8",
|
|
73
|
+
);
|
|
74
|
+
const deliveryLifecycle = readFileSync(
|
|
75
|
+
join(projectDir, "scripts/toolcraft-delivery-lifecycle.mjs"),
|
|
76
|
+
"utf8",
|
|
77
|
+
);
|
|
78
|
+
const proofProcess = readFileSync(
|
|
79
|
+
join(projectDir, "scripts/toolcraft-proof-process.mjs"),
|
|
80
|
+
"utf8",
|
|
81
|
+
);
|
|
82
|
+
const deliveryReceiptModule = readFileSync(
|
|
83
|
+
join(projectDir, "scripts/toolcraft-delivery-receipt.mjs"),
|
|
84
|
+
"utf8",
|
|
85
|
+
);
|
|
86
|
+
expect(performanceRunner).toContain("runToolcraftFullPerformanceCertification");
|
|
87
|
+
expect(performanceRunner).not.toContain("runToolcraftDeliveryVerification");
|
|
88
|
+
expect(performanceRunner).not.toContain("--reason=");
|
|
89
|
+
expect(performanceRunner).toContain("withToolcraftVerificationLock");
|
|
90
|
+
expect(performanceRunner).toContain("measureToolcraftPerformanceCheckpoint");
|
|
91
|
+
expect(performanceRunner).not.toContain("writeCheckpointFile");
|
|
92
|
+
expect(receiptModule).not.toContain(
|
|
93
|
+
"export async function writeToolcraftPerformanceReceipt",
|
|
94
|
+
);
|
|
95
|
+
expect(deliveryReceiptModule).not.toContain(
|
|
96
|
+
"export async function writeToolcraftDeliveryReceipt",
|
|
97
|
+
);
|
|
98
|
+
expect(packageJson.scripts?.["verify:delivery"]).toBe(
|
|
99
|
+
"node scripts/run-delivery-verification.mjs",
|
|
100
|
+
);
|
|
101
|
+
expect(deliveryRunner).toContain("executeToolcraftDeliveryLifecycle");
|
|
102
|
+
expect(deliveryRunner).toContain("withToolcraftVerificationLock");
|
|
103
|
+
expect(deliveryLifecycle).toContain("executeToolcraftDeliveryLifecycleCore");
|
|
104
|
+
expect(deliveryLifecycle).toContain("executeToolcraftDeliveryPlan");
|
|
105
|
+
expect(deliveryLifecycle).not.toContain("runToolcraftFullPerformanceCertification");
|
|
106
|
+
expect(deliveryLifecycle).not.toContain("measureToolcraftPerformanceCheckpoint");
|
|
107
|
+
expect(proofProcess).toContain('from "cross-spawn"');
|
|
108
|
+
expect(proofProcess).toContain("ensureToolcraftChromium");
|
|
109
|
+
const deliverySources = `${deliveryRunner}\n${deliveryLifecycle}`;
|
|
110
|
+
expect(deliverySources).not.toContain('runPackageScript(projectDir, "verify:quick")');
|
|
111
|
+
expect(deliverySources).not.toContain('runPackageScript(projectDir, "verify:final")');
|
|
112
|
+
expect(deliverySources).not.toContain('runPackageScript(projectDir, "verify:perf")');
|
|
113
|
+
expect(packageJson.scripts?.["verify:perf"]).toBe(
|
|
114
|
+
"node scripts/run-browser-performance.mjs",
|
|
115
|
+
);
|
|
116
|
+
expect(packageJson.scripts?.["verify:perf:playwright"]).toBeUndefined();
|
|
117
|
+
expect(packageJson.scripts?.["verify:perf:refresh"]).toBeUndefined();
|
|
118
|
+
expect(packageJson.scripts?.["verify:perf:record-agent-browser"]).toBeUndefined();
|
|
119
|
+
expect(packageJson.scripts?.["verify:perf:record-iteration"]).toBeUndefined();
|
|
120
|
+
expect(packageJson.scripts?.["verify:kernel"]).toBe(
|
|
121
|
+
"node scripts/run-kernel-benchmarks.mjs",
|
|
122
|
+
);
|
|
123
|
+
const deliveryExecutor = readFileSync(
|
|
124
|
+
join(projectDir, "scripts/toolcraft-delivery-executor.mjs"),
|
|
125
|
+
"utf8",
|
|
126
|
+
);
|
|
127
|
+
const targetedPerformanceExecution = readFileSync(
|
|
128
|
+
join(projectDir, "scripts/toolcraft-targeted-performance-execution.mjs"),
|
|
129
|
+
"utf8",
|
|
130
|
+
);
|
|
131
|
+
expect(
|
|
132
|
+
deliveryExecutor.match(
|
|
133
|
+
/TOOLCRAFT_PERFORMANCE_FIXTURE_SELECTOR: "development"/g,
|
|
134
|
+
),
|
|
135
|
+
).toBeNull();
|
|
136
|
+
expect(
|
|
137
|
+
targetedPerformanceExecution.match(
|
|
138
|
+
/TOOLCRAFT_PERFORMANCE_FIXTURE_SELECTOR: "development"/g,
|
|
139
|
+
),
|
|
140
|
+
).toHaveLength(1);
|
|
141
|
+
expect(packageJson.scripts?.["verify:perf:record-exemption"]).toBeUndefined();
|
|
142
|
+
expect(receiptModule).not.toContain('command === "record-iteration"');
|
|
143
|
+
expect(packageJson.scripts?.["verify:receipt"]).toContain("validate");
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
it("documents adaptive delivery routing without command-shaped authority", () => {
|
|
147
|
+
const routedDocs = [
|
|
148
|
+
"AGENTS.md",
|
|
149
|
+
"docs/toolcraft/README.md",
|
|
150
|
+
"docs/toolcraft/acceptance-testing.md",
|
|
151
|
+
"docs/toolcraft/agent-worklog.md",
|
|
152
|
+
"docs/toolcraft/assembly-workflow.md",
|
|
153
|
+
"docs/toolcraft/core/performance.md",
|
|
154
|
+
"docs/toolcraft/performance.md",
|
|
155
|
+
"docs/toolcraft/workflow.md",
|
|
156
|
+
];
|
|
157
|
+
const docSources = routedDocs.map((relativePath) => ({
|
|
158
|
+
relativePath,
|
|
159
|
+
source: readFileSync(join(projectDir, relativePath), "utf8"),
|
|
160
|
+
}));
|
|
161
|
+
|
|
162
|
+
for (const { relativePath, source } of docSources) {
|
|
163
|
+
expect(source, relativePath).toMatch(/first (?:product )?delivery/i);
|
|
164
|
+
expect(source, relativePath).toMatch(/later[^\n]{0,40}delivery/i);
|
|
165
|
+
expect(source, relativePath).toMatch(
|
|
166
|
+
/(?:performance complaint|localized complaint)/i,
|
|
167
|
+
);
|
|
168
|
+
expect(source, relativePath).toMatch(
|
|
169
|
+
/(?:full audit|complete (?:performance )?(?:audit|review))/i,
|
|
170
|
+
);
|
|
171
|
+
expect(source, relativePath).toContain(
|
|
172
|
+
TOOLCRAFT_DELIVERY_VERIFICATION_COMMAND,
|
|
173
|
+
);
|
|
174
|
+
expect(source, relativePath).toContain(
|
|
175
|
+
TOOLCRAFT_FULL_PERFORMANCE_VERIFICATION_COMMAND,
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const allRoutedDocs = docSources.map(({ source }) => source).join("\n");
|
|
180
|
+
const nonAgentsDocs = docSources
|
|
181
|
+
.filter(({ relativePath }) => relativePath !== "AGENTS.md")
|
|
182
|
+
.map(({ source }) => source)
|
|
183
|
+
.join("\n");
|
|
184
|
+
expect(nonAgentsDocs).not.toMatch(/\bTier (?:N|[0-4])\b/);
|
|
185
|
+
expect(allRoutedDocs).not.toMatch(
|
|
186
|
+
/verify:quick|verify:ui|verify:final|verify:perf:record-iteration|test:delivery/,
|
|
187
|
+
);
|
|
188
|
+
expect(allRoutedDocs).not.toMatch(
|
|
189
|
+
/verify:delivery\s+--|--tier|--unit-test|--browser-test|--performance-test/,
|
|
190
|
+
);
|
|
191
|
+
expect(allRoutedDocs).not.toMatch(
|
|
192
|
+
/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,
|
|
193
|
+
);
|
|
194
|
+
expect(allRoutedDocs).toMatch(
|
|
195
|
+
/only exact request authority[^\n]*measured targeted performance/i,
|
|
196
|
+
);
|
|
197
|
+
expect(allRoutedDocs).not.toMatch(/matching (?:executed )?`?Run\b`?/i);
|
|
198
|
+
expect(allRoutedDocs).not.toContain("app-performance-impact.json");
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
it("keeps workload guidance structural instead of prescribing domain constants", () => {
|
|
202
|
+
const monorepoRoot = join(projectDir, "..");
|
|
203
|
+
const documentation = [
|
|
204
|
+
join(projectDir, "AGENTS.md"),
|
|
205
|
+
join(projectDir, "docs/toolcraft/core/performance.md"),
|
|
206
|
+
join(projectDir, "docs/toolcraft/performance.md"),
|
|
207
|
+
join(projectDir, "docs/toolcraft/renderer-technique.md"),
|
|
208
|
+
join(projectDir, "docs/toolcraft/assembly-workflow.md"),
|
|
209
|
+
join(projectDir, "docs/toolcraft/workflow.md"),
|
|
210
|
+
join(monorepoRoot, "apps/website/src/content/docs/toolcraft-core-performance.md"),
|
|
211
|
+
join(monorepoRoot, "apps/website/src/content/docs/toolcraft-performance.md"),
|
|
212
|
+
join(monorepoRoot, "apps/website/src/content/docs/toolcraft-renderer-technique.md"),
|
|
213
|
+
join(monorepoRoot, "apps/website/src/content/docs/toolcraft-assembly-workflow.md"),
|
|
214
|
+
join(monorepoRoot, "apps/website/src/content/docs/toolcraft-workflow.md"),
|
|
215
|
+
]
|
|
216
|
+
.filter((filePath) => existsSync(filePath))
|
|
217
|
+
.map((filePath) => readFileSync(filePath, "utf8"))
|
|
218
|
+
.join("\n");
|
|
219
|
+
|
|
220
|
+
expect(documentation).toMatch(/reachable controls and inputs/i);
|
|
221
|
+
expect(documentation).toMatch(/workload dimensions and enforced boundaries/i);
|
|
222
|
+
expect(documentation).toMatch(
|
|
223
|
+
/render-plan assessment(?: and| with).*protected kernel benchmark/i,
|
|
224
|
+
);
|
|
225
|
+
expect(documentation).toMatch(/derived paths and combined fixtures/i);
|
|
226
|
+
expect(documentation).not.toMatch(/50_000|1_000\s+lines|1920x1080-equivalent/i);
|
|
227
|
+
expect(documentation).not.toMatch(/classif(?:y|ication)[^\n]*(?:key name|key-name|keyword)/i);
|
|
228
|
+
expect(documentation).not.toMatch(
|
|
229
|
+
/bitmap-media|halftone|per-pixel|max text length|max media size/i,
|
|
230
|
+
);
|
|
231
|
+
expect(documentation).toMatch(/exact normalized development pressure `0\.8`/i);
|
|
232
|
+
expect(documentation).toMatch(/exhaustive-discrete/i);
|
|
233
|
+
expect(documentation).toMatch(/match(?:es)? every option one-to-one/i);
|
|
234
|
+
expect(documentation).toMatch(/toolcraftDiscreteCombinationBudget/);
|
|
235
|
+
expect(documentation).toMatch(/toolcraftDiscreteDimensionBudget/);
|
|
236
|
+
expect(documentation).toMatch(/bypasses search budgets because no (?:combination )?search runs/i);
|
|
237
|
+
expect(documentation).toMatch(/planning error/i);
|
|
238
|
+
expect(documentation).toMatch(/TOOLCRAFT_PERFORMANCE_VERIFICATION_LIFECYCLE/);
|
|
239
|
+
expect(documentation).toMatch(/exactly one scenario (?:for|per) (?:every )?(?:canonical |derived )?path/i);
|
|
240
|
+
expect(documentation).toMatch(/targeted failure[^\n]*(?:not|rather than)[^\n]*full[- ]suite/i);
|
|
241
|
+
expect(documentation).toMatch(
|
|
242
|
+
/first product delivery[^\n]*full functional acceptance[^\n]*no measured performance/i,
|
|
243
|
+
);
|
|
244
|
+
expect(documentation).toMatch(/later delivery[^\n]*functional-targeted/i);
|
|
245
|
+
expect(documentation).toMatch(
|
|
246
|
+
/complaint[^\n]*one-authority-targeted-performance-iteration/i,
|
|
247
|
+
);
|
|
248
|
+
expect(documentation).toMatch(/full-performance/i);
|
|
249
|
+
expect(documentation).toMatch(/needs-agent-judgment/i);
|
|
250
|
+
expect(documentation).toMatch(
|
|
251
|
+
/later[^\n]{0,40}delivery[^\n]*(?:same )?bare command[^\n]*exact ownership/i,
|
|
252
|
+
);
|
|
253
|
+
expect(documentation).not.toMatch(
|
|
254
|
+
/first stable[^\n]*(?:full performance|full checkpoint|baseline)/i,
|
|
255
|
+
);
|
|
256
|
+
expect(documentation).not.toMatch(/compatibility mode|legacy preferred|legacy-only/i);
|
|
257
|
+
expect(documentation).not.toMatch(/loadProfile|smoothTargetRatio/i);
|
|
258
|
+
expect(documentation).not.toMatch(/without exceeding development pressure/i);
|
|
259
|
+
expect(documentation).not.toMatch(/\breachableValues\b/);
|
|
260
|
+
});
|
|
261
|
+
});
|
|
@@ -27,6 +27,7 @@ export const TOOLCRAFT_BROWSER_RUNTIME_EVIDENCE_TYPES = [
|
|
|
27
27
|
"infinity-mode-restoration",
|
|
28
28
|
"infinity-scene-bounds-image-export",
|
|
29
29
|
"infinity-scene-bounds-video-export",
|
|
30
|
+
"image-export-artifact",
|
|
30
31
|
"layer-grouping",
|
|
31
32
|
"layer-media-lifecycle",
|
|
32
33
|
"layer-reorder",
|
|
@@ -78,6 +79,7 @@ export const TOOLCRAFT_BROWSER_RUNTIME_EVIDENCE_TYPES = [
|
|
|
78
79
|
"timeline-pause-resume",
|
|
79
80
|
"timeline-rendered-frame",
|
|
80
81
|
"timeline-scrub",
|
|
82
|
+
"video-export-artifact",
|
|
81
83
|
"viewport-side-effect",
|
|
82
84
|
] as const;
|
|
83
85
|
|
|
@@ -8,6 +8,7 @@ export function StarterHome(): React.JSX.Element {
|
|
|
8
8
|
canvasContent={starterComposition.canvasContent}
|
|
9
9
|
className="h-dvh min-h-dvh"
|
|
10
10
|
controlRenderers={starterComposition.controlRenderers}
|
|
11
|
+
exportRenderer={starterComposition.exportRenderer}
|
|
11
12
|
modelPresentation={starterComposition.modelPresentation}
|
|
12
13
|
onPanelAction={starterComposition.onPanelAction}
|
|
13
14
|
renderDefaultCanvasMedia={starterComposition.renderDefaultCanvasMedia}
|
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
import type { ResolvedToolcraftAppSchema } from "../schema/types";
|
|
2
|
-
import type { ToolcraftState } from "../state/types";
|
|
3
|
-
import {
|
|
4
|
-
resolveToolcraftExportFrame,
|
|
5
|
-
ToolcraftSceneExportError,
|
|
6
|
-
validateToolcraftArtifactSize,
|
|
7
|
-
type ToolcraftExportFrame,
|
|
8
|
-
} from "./export-frame";
|
|
9
|
-
import {
|
|
10
|
-
getToolcraftImageExportSize,
|
|
11
|
-
type ToolcraftImageExportResolution,
|
|
12
|
-
} from "./export-sizing";
|
|
13
|
-
|
|
14
|
-
export * from "./export-sizing";
|
|
15
|
-
|
|
16
|
-
export type ToolcraftExportFormat = "png" | "video";
|
|
17
|
-
|
|
18
|
-
export type ToolcraftExportBackgroundOptions = {
|
|
19
|
-
format: ToolcraftExportFormat;
|
|
20
|
-
schema: ResolvedToolcraftAppSchema;
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
export type ToolcraftPreviewBackgroundOptions = {
|
|
24
|
-
includeBackgroundTarget?: string;
|
|
25
|
-
state: ToolcraftState;
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
export type ToolcraftPngRenderContext = {
|
|
29
|
-
canvas: HTMLCanvasElement;
|
|
30
|
-
context: CanvasRenderingContext2D;
|
|
31
|
-
cssHeight: number;
|
|
32
|
-
cssWidth: number;
|
|
33
|
-
frame: ToolcraftExportFrame;
|
|
34
|
-
includeBackground: boolean;
|
|
35
|
-
pixelHeight: number;
|
|
36
|
-
pixelRatio: number;
|
|
37
|
-
pixelWidth: number;
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
export type ToolcraftPngExportCanvasOptions = {
|
|
41
|
-
background?: string;
|
|
42
|
-
canvasFactory?: () => HTMLCanvasElement;
|
|
43
|
-
devicePixelRatio?: number;
|
|
44
|
-
frame?: ToolcraftExportFrame;
|
|
45
|
-
includeBackground?: boolean;
|
|
46
|
-
render: (context: ToolcraftPngRenderContext) => void;
|
|
47
|
-
resolution?: ToolcraftImageExportResolution | string;
|
|
48
|
-
state: ToolcraftState;
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
export function shouldIncludeToolcraftExportBackground({
|
|
52
|
-
format,
|
|
53
|
-
schema,
|
|
54
|
-
}: ToolcraftExportBackgroundOptions): boolean {
|
|
55
|
-
if (format === "video") {
|
|
56
|
-
return true;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
return schema.export.png.background !== "transparent";
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export function shouldIncludeToolcraftPreviewBackground({
|
|
63
|
-
includeBackgroundTarget = "export.includeBackground",
|
|
64
|
-
state,
|
|
65
|
-
}: ToolcraftPreviewBackgroundOptions): boolean {
|
|
66
|
-
if (state.canvas.mode === "infinite") {
|
|
67
|
-
return false;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
const includeBackgroundValue = state.values[includeBackgroundTarget];
|
|
71
|
-
|
|
72
|
-
if (typeof includeBackgroundValue === "boolean") {
|
|
73
|
-
return includeBackgroundValue;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
if (typeof includeBackgroundValue === "string") {
|
|
77
|
-
const normalizedValue = includeBackgroundValue.trim().toLowerCase();
|
|
78
|
-
|
|
79
|
-
if (
|
|
80
|
-
normalizedValue === "false" ||
|
|
81
|
-
normalizedValue === "off" ||
|
|
82
|
-
normalizedValue === "no" ||
|
|
83
|
-
normalizedValue === "transparent" ||
|
|
84
|
-
normalizedValue === "exclude"
|
|
85
|
-
) {
|
|
86
|
-
return false;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
if (
|
|
90
|
-
normalizedValue === "true" ||
|
|
91
|
-
normalizedValue === "on" ||
|
|
92
|
-
normalizedValue === "yes" ||
|
|
93
|
-
normalizedValue === "include"
|
|
94
|
-
) {
|
|
95
|
-
return true;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
return true;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
export function createToolcraftPngExportCanvas({
|
|
103
|
-
background = "#000000",
|
|
104
|
-
canvasFactory = () => document.createElement("canvas"),
|
|
105
|
-
devicePixelRatio,
|
|
106
|
-
frame,
|
|
107
|
-
includeBackground: includeBackgroundOverride,
|
|
108
|
-
render,
|
|
109
|
-
resolution,
|
|
110
|
-
state,
|
|
111
|
-
}: ToolcraftPngExportCanvasOptions): HTMLCanvasElement {
|
|
112
|
-
const canvas = canvasFactory();
|
|
113
|
-
const frameResult = frame
|
|
114
|
-
? { frame, ok: true as const }
|
|
115
|
-
: resolveToolcraftExportFrame(state, null);
|
|
116
|
-
if (!frameResult.ok) throw new ToolcraftSceneExportError(frameResult);
|
|
117
|
-
const resolvedFrame = frameResult.frame;
|
|
118
|
-
const { height, pixelRatio, width } = getToolcraftImageExportSize({
|
|
119
|
-
devicePixelRatio,
|
|
120
|
-
frame: resolvedFrame,
|
|
121
|
-
resolution,
|
|
122
|
-
state,
|
|
123
|
-
});
|
|
124
|
-
const artifactSize = validateToolcraftArtifactSize({ height, width });
|
|
125
|
-
if (!artifactSize.ok) throw new ToolcraftSceneExportError(artifactSize);
|
|
126
|
-
const includeBackground =
|
|
127
|
-
includeBackgroundOverride ??
|
|
128
|
-
shouldIncludeToolcraftExportBackground({
|
|
129
|
-
format: "png",
|
|
130
|
-
schema: state.schema,
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
canvas.width = width;
|
|
134
|
-
canvas.height = height;
|
|
135
|
-
|
|
136
|
-
const context = canvas.getContext("2d");
|
|
137
|
-
|
|
138
|
-
if (!context) {
|
|
139
|
-
throw new Error("Toolcraft PNG export requires a 2D canvas context.");
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
context.save();
|
|
143
|
-
context.clearRect(0, 0, width, height);
|
|
144
|
-
|
|
145
|
-
if (includeBackground) {
|
|
146
|
-
context.fillStyle = background;
|
|
147
|
-
context.fillRect(0, 0, width, height);
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
context.scale(pixelRatio, pixelRatio);
|
|
151
|
-
context.translate(-resolvedFrame.x, -resolvedFrame.y);
|
|
152
|
-
render({
|
|
153
|
-
canvas,
|
|
154
|
-
context,
|
|
155
|
-
cssHeight: resolvedFrame.height,
|
|
156
|
-
cssWidth: resolvedFrame.width,
|
|
157
|
-
frame: resolvedFrame,
|
|
158
|
-
includeBackground,
|
|
159
|
-
pixelHeight: height,
|
|
160
|
-
pixelRatio,
|
|
161
|
-
pixelWidth: width,
|
|
162
|
-
});
|
|
163
|
-
context.restore();
|
|
164
|
-
|
|
165
|
-
return canvas;
|
|
166
|
-
}
|