@12ui/design 0.2.42 → 0.2.44

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/README.md +10 -5
  2. package/SKILL.md +1 -1
  3. package/dist/cli-branch-command.d.ts.map +1 -1
  4. package/dist/cli-branch-command.js +10 -2
  5. package/dist/cli-branch-command.js.map +1 -1
  6. package/dist/cli-capabilities.d.ts +1 -1
  7. package/dist/cli-capabilities.js +1 -1
  8. package/dist/cli-capabilities.js.map +1 -1
  9. package/dist/cli-prototype-command.d.ts.map +1 -1
  10. package/dist/cli-prototype-command.js +4 -1
  11. package/dist/cli-prototype-command.js.map +1 -1
  12. package/dist/index.d.ts +2 -1
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +1 -1
  15. package/dist/index.js.map +1 -1
  16. package/dist/prototype-gates.d.ts +8 -0
  17. package/dist/prototype-gates.d.ts.map +1 -1
  18. package/dist/prototype-gates.js +39 -5
  19. package/dist/prototype-gates.js.map +1 -1
  20. package/dist/prototype-label-client.d.ts +6 -1
  21. package/dist/prototype-label-client.d.ts.map +1 -1
  22. package/dist/prototype-label-client.js +21 -2
  23. package/dist/prototype-label-client.js.map +1 -1
  24. package/dist/prototype-poststep.d.ts.map +1 -1
  25. package/dist/prototype-poststep.js +5 -0
  26. package/dist/prototype-poststep.js.map +1 -1
  27. package/dist/prototype-revision.d.ts +2 -0
  28. package/dist/prototype-revision.d.ts.map +1 -0
  29. package/dist/prototype-revision.js +2 -0
  30. package/dist/prototype-revision.js.map +1 -0
  31. package/dist/prototype-run-record.d.ts +5 -1
  32. package/dist/prototype-run-record.d.ts.map +1 -1
  33. package/dist/prototype-run-record.js +89 -7
  34. package/dist/prototype-run-record.js.map +1 -1
  35. package/dist/prototype-runner.d.ts +4 -1
  36. package/dist/prototype-runner.d.ts.map +1 -1
  37. package/dist/prototype-runner.js +15 -9
  38. package/dist/prototype-runner.js.map +1 -1
  39. package/dist/run-journal.d.ts +6 -1
  40. package/dist/run-journal.d.ts.map +1 -1
  41. package/dist/run-journal.js +10 -2
  42. package/dist/run-journal.js.map +1 -1
  43. package/open-design.json +2 -2
  44. package/package.json +2 -2
  45. package/prototype-kit/build.mjs +88 -40
  46. package/prototype-kit/lib/actions.mjs +52 -0
  47. package/prototype-kit/lib/shell-identity.mjs +139 -0
  48. package/prototype-kit/lib/shell-stitching.mjs +70 -29
  49. package/prototype-kit/tests/adversarial-runtime.mjs +16 -1
  50. package/prototype-kit/tests/fixtures/blocking-runtime/broken-interaction.html +7 -0
  51. package/prototype-kit/tests/fixtures/four-dropdown/branch.plan.json +29 -0
  52. package/prototype-kit/tests/fixtures/four-dropdown/pages/p2-stream-proposals.html +10 -0
  53. package/prototype-kit/tests/fixtures/four-dropdown/pages/p4-live-stream-results.html +7 -0
  54. package/prototype-kit/tests/fixtures/shell-stitching-runtime/PROVENANCE.md +22 -0
  55. package/prototype-kit/tests/fixtures/shell-stitching-runtime/branch.plan.json +40 -0
  56. package/prototype-kit/tests/fixtures/shell-stitching-runtime/pages/p0-donor.html +38 -0
  57. package/prototype-kit/tests/fixtures/shell-stitching-runtime/pages/p1-id-collision.html +38 -0
  58. package/prototype-kit/tests/fixtures/shell-stitching-runtime/pages/p2-canvas-control.html +39 -0
  59. package/prototype-kit/tests/offline-check.mjs +1 -1
  60. package/prototype-kit/tests/rules-check.mjs +71 -3
  61. package/prototype-kit/tests/shell-stitching-runtime.mjs +116 -0
@@ -0,0 +1,116 @@
1
+ #!/usr/bin/env node
2
+ import assert from 'node:assert/strict';
3
+ import fs from 'node:fs';
4
+ import os from 'node:os';
5
+ import path from 'node:path';
6
+ import { chromium } from '@playwright/test';
7
+ import { checkRuntime } from '../lib/runtime-check.mjs';
8
+ import { startStaticServer } from '../lib/static-server.mjs';
9
+ import { buildPrototype } from './lib/run-process.mjs';
10
+
11
+ const expectFailure = process.argv.includes('--expect-failure');
12
+ const unexpectedArgs = process.argv.slice(2).filter((arg) => arg !== '--expect-failure');
13
+ if (unexpectedArgs.length > 0) throw new Error(`usage: shell-stitching-runtime.mjs [--expect-failure]`);
14
+
15
+ const testsDir = path.dirname(new URL(import.meta.url).pathname);
16
+ const kitDir = path.resolve(testsDir, '..');
17
+ const fixtureDir = path.join(testsDir, 'fixtures', 'shell-stitching-runtime');
18
+ const scratch = fs.mkdtempSync(path.join(os.tmpdir(), 'proto-shell-stitching-'));
19
+ const runWorkDir = path.join(scratch, 'build');
20
+ let browser = null;
21
+ let server = null;
22
+
23
+ const regionAt = (audit, file, width) => audit.pages
24
+ .find((page) => page.file === file)?.viewports
25
+ .find((viewport) => viewport.width === width)?.shellState?.regions
26
+ .find((region) => region.region === 'header') || null;
27
+ const bandHeight = (inventory, pageId, key) => inventory.pages
28
+ .find((page) => page.pageId === pageId)?.bands
29
+ .find((band) => band.key === key)?.height;
30
+ const decisionFor = (manifest, unitId) => manifest.units
31
+ .find((unit) => unit.id === unitId)?.shellDecisions
32
+ .find((decision) => decision.region === 'header') || null;
33
+
34
+ try {
35
+ const built = buildPrototype({
36
+ kitDir,
37
+ run: { runDir: fixtureDir },
38
+ runWorkDir,
39
+ });
40
+ assert.equal(built.ok, true, `fixture pipeline must build: ${built.failedStage || 'unknown stage'} ${built.stages?.[built.failedStage]?.error || ''}`);
41
+
42
+ const inventory = JSON.parse(fs.readFileSync(built.inventoryFile, 'utf8'));
43
+ const manifest = JSON.parse(fs.readFileSync(path.join(built.protoDir, 'proto-manifest.json'), 'utf8'));
44
+ assert.equal(manifest.canonicalShellPage?.pageId, 'p0-donor', 'fixture contract: the approved donor is the one canonical shell page');
45
+ assert.deepEqual(decisionFor(manifest, 'id-collision'), { region: 'header', commit: true, reason: 'compatible' }, 'fixture contract: differing compatible bands request one atomic transplant');
46
+ assert.deepEqual(decisionFor(manifest, 'canvas-control'), { region: 'header', commit: false, reason: 'compatible' }, 'must stay silent: the already canonical control does not request a write');
47
+ assert.deepEqual([
48
+ bandHeight(inventory, 'p0-donor', 'mobile-390'),
49
+ bandHeight(inventory, 'p2-canvas-control', 'mobile-390'),
50
+ ], [900, 1400], 'fixture contract: the portrait control has a substantially taller canvas');
51
+
52
+ server = await startStaticServer(runWorkDir);
53
+ browser = await chromium.launch();
54
+ const audit = await checkRuntime({
55
+ browser,
56
+ baseUrl: server.baseUrl,
57
+ relativeProtoPath: 'proto',
58
+ protoDir: built.protoDir,
59
+ });
60
+
61
+ assert.equal(audit.pageErrors, 0, 'fixture pages must load without page errors');
62
+ assert.equal(audit.consoleErrors, 0, 'fixture pages must not emit console errors');
63
+ assert.equal(audit.duplicateIds, 0, 'shell replacement must not leave duplicate ids');
64
+
65
+ const donor390 = regionAt(audit, 'donor.html', 390);
66
+ const collision390 = regionAt(audit, 'id-collision.html', 390);
67
+ const control390 = regionAt(audit, 'canvas-control.html', 390);
68
+ const donor1536 = regionAt(audit, 'donor.html', 1536);
69
+ const collision1536 = regionAt(audit, 'id-collision.html', 1536);
70
+ assert.ok(donor390 && collision390 && control390 && donor1536 && collision1536, 'fixture contract: all audited header regions are present');
71
+ assert.deepEqual(donor390.actualGeometry, [0, 0, 390, 72], 'fixture contract: donor mobile shell geometry is fixed');
72
+ assert.deepEqual(collision390.actualGeometry, donor390.actualGeometry, 'outer shell geometry alone cannot conceal descendant displacement');
73
+ assert.equal(donor390.consistencyStatus, 'canonical', 'fixture contract: the donor makes the canonical shell claim');
74
+ assert.equal(collision390.consistencyStatus, 'canonical', 'fixture contract: the committed recipient makes the canonical shell claim');
75
+ assert.equal(control390.consistencyStatus, 'silent', 'must stay silent: canvas/content-only variation makes no canonical-write claim');
76
+ assert.equal(control390.actualSignature, donor390.actualSignature, 'must stay silent: canvas height and page content are outside the shell signature');
77
+ assert.equal(collision1536.actualSignature, donor1536.actualSignature, 'must stay silent: distinct native identities render the same canonical header');
78
+
79
+ const groups = audit.shellConsistencyFailures.map((failure) => failure.group);
80
+ if (expectFailure) {
81
+ assert.deepEqual(groups, ['390:mobile-390:header'], 'pre-fix evidence must isolate one canonical collision to the mobile header');
82
+ assert.notEqual(collision390.actualSignature, donor390.actualSignature, 'must fire before the fix: recipient offsets alter transplanted donor descendants');
83
+ const failure = audit.shellConsistencyFailures[0];
84
+ assert.equal(failure.reason, 'prototype-shell-signature-mismatch', 'pre-fix evidence is the rendered canonical-shell mismatch');
85
+ assert.deepEqual(failure.pages, [
86
+ { file: 'donor.html', signature: donor390.actualSignature, geometry: donor390.actualGeometry },
87
+ { file: 'id-collision.html', signature: collision390.actualSignature, geometry: collision390.actualGeometry },
88
+ ], 'pre-fix group carries the exact runtime signatures for only the donor and committed recipient');
89
+ } else {
90
+ assert.equal(collision390.actualSignature, donor390.actualSignature, 'must pass after the fix: transplanted donor render matches its canonical source at 390');
91
+ assert.deepEqual(audit.shellConsistencyFailures, [], 'post-fix runtime audit has no canonical shell consistency failures');
92
+ }
93
+
94
+ process.stdout.write(JSON.stringify({
95
+ expectation: expectFailure ? 'pre-fix-failure' : 'post-fix-pass',
96
+ groups,
97
+ mobile: {
98
+ donor: donor390.actualSignature,
99
+ collision: collision390.actualSignature,
100
+ control: control390.actualSignature,
101
+ geometry: donor390.actualGeometry,
102
+ },
103
+ native: {
104
+ donor: donor1536.actualSignature,
105
+ collision: collision1536.actualSignature,
106
+ },
107
+ canvasHeights: {
108
+ donor: bandHeight(inventory, 'p0-donor', 'mobile-390'),
109
+ control: bandHeight(inventory, 'p2-canvas-control', 'mobile-390'),
110
+ },
111
+ }, null, 2) + '\n');
112
+ } finally {
113
+ if (browser) await browser.close();
114
+ if (server) await server.close();
115
+ fs.rmSync(scratch, { recursive: true, force: true });
116
+ }