@auraindustry/aurajs 0.1.3 → 0.1.5

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 (108) hide show
  1. package/README.md +7 -0
  2. package/benchmarks/perf-thresholds.json +27 -0
  3. package/package.json +6 -1
  4. package/src/ai-guidance.mjs +302 -0
  5. package/src/authored-project.mjs +498 -2
  6. package/src/build-contract/capabilities.mjs +87 -1
  7. package/src/build-contract/constants.mjs +1 -0
  8. package/src/build-contract.mjs +2 -0
  9. package/src/bundler.mjs +143 -13
  10. package/src/cli.mjs +681 -13
  11. package/src/commands/packs.mjs +741 -0
  12. package/src/commands/project-authoring.mjs +128 -1
  13. package/src/conformance/cases/app-and-ui-runtime-cases.mjs +1 -2
  14. package/src/conformance/cases/core-runtime-cases.mjs +6 -2
  15. package/src/conformance/cases/scene3d-and-media-cases.mjs +238 -0
  16. package/src/conformance/cases/systems-and-gameplay-cases.mjs +265 -4
  17. package/src/conformance-mobile.mjs +166 -0
  18. package/src/conformance.mjs +89 -30
  19. package/src/evidence-bundle.mjs +242 -0
  20. package/src/headless-test/runtime-coordinator.mjs +186 -33
  21. package/src/headless-test.mjs +2 -0
  22. package/src/helpers/2d/index.mjs +183 -0
  23. package/src/helpers/index.mjs +26 -0
  24. package/src/helpers/starter-utils/adventure-objectives.js +102 -0
  25. package/src/helpers/starter-utils/adventure-world-2d.js +221 -0
  26. package/src/helpers/starter-utils/animation-2d.js +337 -0
  27. package/src/helpers/starter-utils/animation-packaging-2d.js +203 -0
  28. package/src/helpers/starter-utils/atlas-assets-2d.js +111 -0
  29. package/src/helpers/starter-utils/autoplay-debug-2d.js +215 -0
  30. package/src/helpers/starter-utils/avatar-3d.js +404 -0
  31. package/src/helpers/starter-utils/combat-feedback-2d.js +320 -0
  32. package/src/helpers/starter-utils/combat-runtime-2d.js +290 -0
  33. package/src/helpers/starter-utils/core.js +150 -0
  34. package/src/helpers/starter-utils/dialogue-2d.js +351 -0
  35. package/src/helpers/starter-utils/enemy-archetypes-2d.js +68 -0
  36. package/src/helpers/starter-utils/index.js +26 -0
  37. package/src/helpers/starter-utils/inventory-2d.js +268 -0
  38. package/src/helpers/starter-utils/journal-2d.js +267 -0
  39. package/src/helpers/starter-utils/platformer-3d.js +132 -0
  40. package/src/helpers/starter-utils/scene-audio-2d.js +236 -0
  41. package/src/helpers/starter-utils/streamed-world-2d.js +378 -0
  42. package/src/helpers/starter-utils/tilemap-nav-2d.js +499 -0
  43. package/src/helpers/starter-utils/tilemap-world-2d.js +205 -0
  44. package/src/helpers/starter-utils/triggers.js +662 -0
  45. package/src/helpers/starter-utils/tween-2d.js +615 -0
  46. package/src/helpers/starter-utils/wave-director.js +101 -0
  47. package/src/helpers/starter-utils/world-compositor-2d.js +253 -0
  48. package/src/helpers/starter-utils/world-persistence-2d.js +180 -0
  49. package/src/mobile/android/build.mjs +606 -0
  50. package/src/mobile/android/host-artifact.mjs +280 -0
  51. package/src/mobile/ios/build.mjs +1323 -0
  52. package/src/mobile/ios/host-artifact.mjs +819 -0
  53. package/src/mobile/shared/capabilities.mjs +174 -0
  54. package/src/packs/catalog.mjs +259 -0
  55. package/src/perf-benchmark-runner.mjs +17 -12
  56. package/src/perf-benchmark.mjs +408 -4
  57. package/src/publish-command.mjs +303 -6
  58. package/src/replay-runtime.mjs +257 -0
  59. package/src/scaffold/config.mjs +2 -0
  60. package/src/scaffold/fs.mjs +8 -1
  61. package/src/scaffold/project-docs.mjs +43 -1
  62. package/src/scaffold.mjs +4 -0
  63. package/src/session-runtime.mjs +4 -3
  64. package/src/web-conformance.mjs +0 -36
  65. package/templates/create/2d-adventure/config/gameplay/adventure.config.js +9 -6
  66. package/templates/create/2d-adventure/content/gameplay/dialogue.js +85 -0
  67. package/templates/create/2d-adventure/content/gameplay/world.js +32 -36
  68. package/templates/create/2d-adventure/content/gameplay/world.tilemap.json +273 -0
  69. package/templates/create/2d-adventure/docs/design/loop.md +4 -3
  70. package/templates/create/2d-adventure/prefabs/relic.prefab.js +10 -10
  71. package/templates/create/2d-adventure/prefabs/world.prefab.js +127 -74
  72. package/templates/create/2d-adventure/scenes/gameplay.scene.js +603 -112
  73. package/templates/create/2d-adventure/src/runtime/capabilities.js +16 -0
  74. package/templates/create/2d-adventure/ui/hud.screen.js +187 -4
  75. package/templates/create/2d-adventure/ui/journal.screen.js +183 -0
  76. package/templates/create/3d/scenes/gameplay.scene.js +30 -3
  77. package/templates/create/3d/src/runtime/capabilities.js +5 -0
  78. package/templates/create/3d/src/runtime/materials.js +10 -0
  79. package/templates/create/3d-adventure/scenes/gameplay.scene.js +30 -3
  80. package/templates/create/3d-adventure/src/runtime/capabilities.js +5 -0
  81. package/templates/create/3d-adventure/src/runtime/materials.js +11 -0
  82. package/templates/create/3d-collectathon/scenes/gameplay.scene.js +30 -3
  83. package/templates/create/3d-collectathon/src/runtime/capabilities.js +5 -0
  84. package/templates/create/3d-collectathon/src/runtime/materials.js +10 -0
  85. package/templates/create/shared/src/runtime/ui-forms.js +552 -0
  86. package/templates/create/shared/src/starter-utils/adventure-world-2d.js +221 -0
  87. package/templates/create/shared/src/starter-utils/animation-packaging-2d.js +203 -0
  88. package/templates/create/shared/src/starter-utils/atlas-assets-2d.js +111 -0
  89. package/templates/create/shared/src/starter-utils/autoplay-debug-2d.js +215 -0
  90. package/templates/create/shared/src/starter-utils/combat-runtime-2d.js +290 -0
  91. package/templates/create/shared/src/starter-utils/dialogue-2d.js +351 -0
  92. package/templates/create/shared/src/starter-utils/index.js +15 -1
  93. package/templates/create/shared/src/starter-utils/inventory-2d.js +268 -0
  94. package/templates/create/shared/src/starter-utils/journal-2d.js +267 -0
  95. package/templates/create/shared/src/starter-utils/scene-audio-2d.js +236 -0
  96. package/templates/create/shared/src/starter-utils/streamed-world-2d.js +378 -0
  97. package/templates/create/shared/src/starter-utils/tilemap-nav-2d.js +499 -0
  98. package/templates/create/shared/src/starter-utils/tilemap-world-2d.js +205 -0
  99. package/templates/create/shared/src/starter-utils/world-compositor-2d.js +253 -0
  100. package/templates/create/shared/src/starter-utils/world-persistence-2d.js +180 -0
  101. package/templates/create-bin/play.js +36 -7
  102. package/templates/skills/auramaxx/SKILL.md +46 -0
  103. package/templates/skills/auramaxx/project-requirements.md +68 -0
  104. package/templates/skills/auramaxx/starter-recipes.md +104 -0
  105. package/templates/skills/auramaxx/validation-checklist.md +49 -0
  106. package/templates/skills/aurajs/SKILL.md +0 -96
  107. package/templates/skills/aurajs/api-contract-3d.md +0 -7
  108. package/templates/skills/aurajs/api-contract.md +0 -7
@@ -61,10 +61,7 @@ export const STAGE_143_PARTIAL_PROOF_REFRESH_V1 = Object.freeze([
61
61
  ]),
62
62
  }),
63
63
  ]),
64
- exampleDirs: Object.freeze([
65
- 'starter-3d',
66
- 'procedural-geometry-shader-showcase',
67
- ]),
64
+ exampleDirs: Object.freeze([]),
68
65
  }),
69
66
  Object.freeze({
70
67
  category: 'navmesh_pathfinding',
@@ -78,9 +75,7 @@ export const STAGE_143_PARTIAL_PROOF_REFRESH_V1 = Object.freeze([
78
75
  ]),
79
76
  }),
80
77
  ]),
81
- exampleDirs: Object.freeze([
82
- 'navmesh-crowd-proof',
83
- ]),
78
+ exampleDirs: Object.freeze([]),
84
79
  }),
85
80
  Object.freeze({
86
81
  category: 'spatial_audio_3d',
@@ -94,9 +89,7 @@ export const STAGE_143_PARTIAL_PROOF_REFRESH_V1 = Object.freeze([
94
89
  ]),
95
90
  }),
96
91
  ]),
97
- exampleDirs: Object.freeze([
98
- 'media-presentation-proof',
99
- ]),
92
+ exampleDirs: Object.freeze([]),
100
93
  }),
101
94
  Object.freeze({
102
95
  category: 'custom_shaders',
@@ -111,9 +104,7 @@ export const STAGE_143_PARTIAL_PROOF_REFRESH_V1 = Object.freeze([
111
104
  ]),
112
105
  }),
113
106
  ]),
114
- exampleDirs: Object.freeze([
115
- 'shader-kit-proof',
116
- ]),
107
+ exampleDirs: Object.freeze([]),
117
108
  }),
118
109
  Object.freeze({
119
110
  category: 'sprite3d_billboards',
@@ -135,10 +126,7 @@ export const STAGE_143_PARTIAL_PROOF_REFRESH_V1 = Object.freeze([
135
126
  ]),
136
127
  }),
137
128
  ]),
138
- exampleDirs: Object.freeze([
139
- 'billboard-runtime-proof',
140
- 'worldspace-ui-proof',
141
- ]),
129
+ exampleDirs: Object.freeze([]),
142
130
  }),
143
131
  Object.freeze({
144
132
  category: 'gltf_scene_import',
@@ -153,9 +141,7 @@ export const STAGE_143_PARTIAL_PROOF_REFRESH_V1 = Object.freeze([
153
141
  ]),
154
142
  }),
155
143
  ]),
156
- exampleDirs: Object.freeze([
157
- 'billboard-runtime-proof',
158
- ]),
144
+ exampleDirs: Object.freeze([]),
159
145
  }),
160
146
  Object.freeze({
161
147
  category: 'skinned_mesh_instancing',
@@ -169,9 +155,7 @@ export const STAGE_143_PARTIAL_PROOF_REFRESH_V1 = Object.freeze([
169
155
  ]),
170
156
  }),
171
157
  ]),
172
- exampleDirs: Object.freeze([
173
- 'crowd-skinning-proof',
174
- ]),
158
+ exampleDirs: Object.freeze([]),
175
159
  }),
176
160
  Object.freeze({
177
161
  category: 'video_textures',
@@ -193,10 +177,7 @@ export const STAGE_143_PARTIAL_PROOF_REFRESH_V1 = Object.freeze([
193
177
  ]),
194
178
  }),
195
179
  ]),
196
- exampleDirs: Object.freeze([
197
- 'native-mp4-proof',
198
- 'media-presentation-proof',
199
- ]),
180
+ exampleDirs: Object.freeze([]),
200
181
  }),
201
182
  ]);
202
183
  const PHASER_VERTICAL_SLICE_PERF_BUDGETS = Object.freeze({
@@ -1469,6 +1450,44 @@ function normalizeRuntimeInspectorPhase2(phase2) {
1469
1450
  };
1470
1451
  }
1471
1452
 
1453
+ function normalizeRuntimeInspectorDraw2dRuntime(draw2dRuntime) {
1454
+ const source = draw2dRuntime && typeof draw2dRuntime === 'object' ? draw2dRuntime : {};
1455
+ return {
1456
+ fx: {
1457
+ pendingFxCommandCount: numericOr(source?.fx?.pendingFxCommandCount),
1458
+ lastSubmittedFxCommandCount: numericOr(source?.fx?.lastSubmittedFxCommandCount),
1459
+ lastExecutedFxCommandCount: numericOr(source?.fx?.lastExecutedFxCommandCount),
1460
+ lastReasonCode: typeof source?.fx?.lastReasonCode === 'string' ? source.fx.lastReasonCode : 'draw2d_fx_idle',
1461
+ lastOk: source?.fx?.lastOk !== false,
1462
+ },
1463
+ masking: {
1464
+ pendingPassCount: numericOr(source?.masking?.pendingPassCount),
1465
+ pendingAdvancedPassCount: numericOr(source?.masking?.pendingAdvancedPassCount),
1466
+ lastSubmittedPassCount: numericOr(source?.masking?.lastSubmittedPassCount),
1467
+ lastExecutedPassCount: numericOr(source?.masking?.lastExecutedPassCount),
1468
+ lastSubmittedCommandCount: numericOr(source?.masking?.lastSubmittedCommandCount),
1469
+ lastReasonCode: typeof source?.masking?.lastReasonCode === 'string' ? source.masking.lastReasonCode : 'draw2d_mask_idle',
1470
+ lastOk: source?.masking?.lastOk !== false,
1471
+ lastRequestedMaskKind: typeof source?.masking?.lastRequestedMaskKind === 'string' ? source.masking.lastRequestedMaskKind : 'none',
1472
+ lastRequestedMaskShape: typeof source?.masking?.lastRequestedMaskShape === 'string' ? source.masking.lastRequestedMaskShape : 'none',
1473
+ lastRequestedMaskFeather: normalizeRuntimeInspectorTiming(source?.masking?.lastRequestedMaskFeather, RUNTIME_INSPECTOR_TIMING_PRECISION.scalarDigits),
1474
+ },
1475
+ compositor: {
1476
+ knownGraphCount: numericOr(source?.compositor?.knownGraphCount),
1477
+ knownStageCount: numericOr(source?.compositor?.knownStageCount),
1478
+ lastGraphName: typeof source?.compositor?.lastGraphName === 'string' ? source.compositor.lastGraphName : '',
1479
+ lastGraphStageCount: numericOr(source?.compositor?.lastGraphStageCount),
1480
+ lastGraphCommandCount: numericOr(source?.compositor?.lastGraphCommandCount),
1481
+ lastGraphReasonCode: typeof source?.compositor?.lastGraphReasonCode === 'string' ? source.compositor.lastGraphReasonCode : 'draw2d_compositor_idle',
1482
+ lastGraphOk: source?.compositor?.lastGraphOk !== false,
1483
+ pendingExportCount: numericOr(source?.compositor?.pendingExportCount),
1484
+ lastSubmittedExportCount: numericOr(source?.compositor?.lastSubmittedExportCount),
1485
+ lastExecutedExportCount: numericOr(source?.compositor?.lastExecutedExportCount),
1486
+ lastExportReasonCode: typeof source?.compositor?.lastExportReasonCode === 'string' ? source.compositor.lastExportReasonCode : 'draw2d_export_idle',
1487
+ lastExportOk: source?.compositor?.lastExportOk !== false,
1488
+ },
1489
+ };
1490
+ }
1472
1491
  function normalizeRuntimeInspectorVec3(value) {
1473
1492
  return {
1474
1493
  x: normalizeRuntimeInspectorTiming(value?.x, RUNTIME_INSPECTOR_TIMING_PRECISION.scalarDigits),
@@ -1752,7 +1771,7 @@ function normalizeRuntimeInspectorSample(sample) {
1752
1771
  window: normalizeRuntimeInspectorWindow(sample.window),
1753
1772
  queues: normalizeRuntimeInspectorQueues(sample.queues),
1754
1773
  phase2: normalizeRuntimeInspectorPhase2(sample.phase2),
1755
- draw2dRuntime: sample.draw2dRuntime || null,
1774
+ draw2dRuntime: normalizeRuntimeInspectorDraw2dRuntime(sample.draw2dRuntime),
1756
1775
  scene3dRuntime: normalizeRuntimeInspectorScene3dRuntime(sample.scene3dRuntime),
1757
1776
  };
1758
1777
  }
@@ -1930,7 +1949,6 @@ export function buildRuntimeObservabilityReport({
1930
1949
  lastResetSequenceBefore: numericOr(vectors?.audioLastResetSequenceBeforeReset),
1931
1950
  lastResetSequenceAfter: numericOr(vectors?.audioLastResetSequenceAfterReset),
1932
1951
  };
1933
-
1934
1952
  return {
1935
1953
  schemaVersion: 'aurajs.runtime-observability.v1',
1936
1954
  generatedAt,
@@ -1961,7 +1979,6 @@ export function buildRuntimeObservabilityReport({
1961
1979
  vectors,
1962
1980
  };
1963
1981
  }
1964
-
1965
1982
  export function buildRuntimeInspectorSnapshotReport({
1966
1983
  generatedAt,
1967
1984
  mode,
@@ -1971,8 +1988,10 @@ export function buildRuntimeInspectorSnapshotReport({
1971
1988
  authoringState = null,
1972
1989
  }) {
1973
1990
  const snapshot = runtimeInspectorSnapshot?.snapshot || null;
1991
+ const draw2dSource = snapshot?.draw2dRuntime || snapshot?.raw?.active?.draw2dRuntime || null;
1974
1992
  const scene3dSource = snapshot?.scene3dRuntime || snapshot?.raw?.active?.scene3dRuntime || null;
1975
1993
  const phase2 = normalizeRuntimeInspectorPhase2(snapshot?.phase2);
1994
+ const draw2dRuntime = normalizeRuntimeInspectorDraw2dRuntime(draw2dSource);
1976
1995
  const scene3dRuntime = normalizeRuntimeInspectorScene3dRuntime(scene3dSource);
1977
1996
  const authoring3d = normalizeRuntimeInspectorAuthoringState(
1978
1997
  authoringState || runtimeInspectorSnapshot?.authoringState || snapshot?.authoring3d || null,
@@ -2003,6 +2022,7 @@ export function buildRuntimeInspectorSnapshotReport({
2003
2022
  queues: normalizeRuntimeInspectorQueues(snapshot?.queues),
2004
2023
  resetAfterDisable: normalizeRuntimeInspectorResetAfterDisable(snapshot?.resetAfterDisable),
2005
2024
  phase2,
2025
+ draw2dRuntime,
2006
2026
  scene3dRuntime,
2007
2027
  authoring3d,
2008
2028
  raw: normalizeRuntimeInspectorRaw(snapshot?.raw),
@@ -2300,7 +2320,9 @@ export function buildNativeProbeSource(conformanceCase, options = {}) {
2300
2320
  const queues = stats.queues || {};
2301
2321
  const phase2 = stats.phase2 || {};
2302
2322
  const draw2dRuntime = stats.draw2dRuntime || {};
2323
+ const draw2dFx = draw2dRuntime.fx || {};
2303
2324
  const draw2dMasking = draw2dRuntime.masking || {};
2325
+ const draw2dCompositor = draw2dRuntime.compositor || {};
2304
2326
  const scene3dRuntime = stats.scene3dRuntime || {};
2305
2327
  const scene3dSubmission = scene3dRuntime.submission || {};
2306
2328
  const scene3dCamera = scene3dRuntime.camera || {};
@@ -2348,8 +2370,18 @@ export function buildNativeProbeSource(conformanceCase, options = {}) {
2348
2370
  particles: toPhase2Row(phase2.particles),
2349
2371
  },
2350
2372
  draw2dRuntime: {
2373
+ fx: {
2374
+ pendingFxCommandCount: __num(draw2dFx.pendingFxCommandCount),
2375
+ lastSubmittedFxCommandCount: __num(draw2dFx.lastSubmittedFxCommandCount),
2376
+ lastExecutedFxCommandCount: __num(draw2dFx.lastExecutedFxCommandCount),
2377
+ lastReasonCode: typeof draw2dFx.lastReasonCode === 'string'
2378
+ ? draw2dFx.lastReasonCode
2379
+ : 'draw2d_fx_idle',
2380
+ lastOk: draw2dFx.lastOk !== false,
2381
+ },
2351
2382
  masking: {
2352
2383
  pendingPassCount: __num(draw2dMasking.pendingPassCount),
2384
+ pendingAdvancedPassCount: __num(draw2dMasking.pendingAdvancedPassCount),
2353
2385
  lastSubmittedPassCount: __num(draw2dMasking.lastSubmittedPassCount),
2354
2386
  lastExecutedPassCount: __num(draw2dMasking.lastExecutedPassCount),
2355
2387
  lastSubmittedCommandCount: __num(draw2dMasking.lastSubmittedCommandCount),
@@ -2357,6 +2389,33 @@ export function buildNativeProbeSource(conformanceCase, options = {}) {
2357
2389
  ? draw2dMasking.lastReasonCode
2358
2390
  : 'draw2d_mask_idle',
2359
2391
  lastOk: draw2dMasking.lastOk !== false,
2392
+ lastRequestedMaskKind: typeof draw2dMasking.lastRequestedMaskKind === 'string'
2393
+ ? draw2dMasking.lastRequestedMaskKind
2394
+ : 'none',
2395
+ lastRequestedMaskShape: typeof draw2dMasking.lastRequestedMaskShape === 'string'
2396
+ ? draw2dMasking.lastRequestedMaskShape
2397
+ : 'none',
2398
+ lastRequestedMaskFeather: __num(draw2dMasking.lastRequestedMaskFeather),
2399
+ },
2400
+ compositor: {
2401
+ knownGraphCount: __num(draw2dCompositor.knownGraphCount),
2402
+ knownStageCount: __num(draw2dCompositor.knownStageCount),
2403
+ lastGraphName: typeof draw2dCompositor.lastGraphName === 'string'
2404
+ ? draw2dCompositor.lastGraphName
2405
+ : '',
2406
+ lastGraphStageCount: __num(draw2dCompositor.lastGraphStageCount),
2407
+ lastGraphCommandCount: __num(draw2dCompositor.lastGraphCommandCount),
2408
+ lastGraphReasonCode: typeof draw2dCompositor.lastGraphReasonCode === 'string'
2409
+ ? draw2dCompositor.lastGraphReasonCode
2410
+ : 'draw2d_compositor_idle',
2411
+ lastGraphOk: draw2dCompositor.lastGraphOk !== false,
2412
+ pendingExportCount: __num(draw2dCompositor.pendingExportCount),
2413
+ lastSubmittedExportCount: __num(draw2dCompositor.lastSubmittedExportCount),
2414
+ lastExecutedExportCount: __num(draw2dCompositor.lastExecutedExportCount),
2415
+ lastExportReasonCode: typeof draw2dCompositor.lastExportReasonCode === 'string'
2416
+ ? draw2dCompositor.lastExportReasonCode
2417
+ : 'draw2d_export_idle',
2418
+ lastExportOk: draw2dCompositor.lastExportOk !== false,
2360
2419
  },
2361
2420
  },
2362
2421
  scene3dRuntime: {
@@ -0,0 +1,242 @@
1
+ import { mkdirSync, writeFileSync } from 'node:fs';
2
+ import { dirname, resolve } from 'node:path';
3
+
4
+ import { buildRuntimeInspectorSnapshotReport } from './conformance.mjs';
5
+ import {
6
+ advanceSessionFrames,
7
+ bootSessionRuntime,
8
+ exportSessionInspect,
9
+ exportSessionState,
10
+ } from './session-runtime.mjs';
11
+ import { runHeadlessReplay } from './replay-runtime.mjs';
12
+
13
+ export const EVIDENCE_BUNDLE_SCHEMA_VERSION = 'aurajs.evidence-bundle.v1';
14
+ export const EVIDENCE_PERF_SUMMARY_SCHEMA_VERSION = 'aurajs.evidence-perf-summary.v1';
15
+
16
+ export class EvidenceBundleError extends Error {
17
+ constructor(reasonCode, message, details = {}) {
18
+ super(message);
19
+ this.name = 'EvidenceBundleError';
20
+ this.reasonCode = reasonCode;
21
+ this.details = details;
22
+ }
23
+ }
24
+
25
+ function writeJsonFile(filePath, payload) {
26
+ mkdirSync(dirname(filePath), { recursive: true });
27
+ writeFileSync(filePath, `${JSON.stringify(payload, null, 2)}\n`, 'utf8');
28
+ }
29
+
30
+ function buildPerfSummary({ runtime, inspectReport, captureKind }) {
31
+ return {
32
+ schemaVersion: EVIDENCE_PERF_SUMMARY_SCHEMA_VERSION,
33
+ kind: 'headless-runtime-profile',
34
+ captureKind,
35
+ frame: inspectReport?.frame || null,
36
+ window: inspectReport?.window || null,
37
+ queues: inspectReport?.queues || null,
38
+ counters: {
39
+ assertionsPassed: runtime.testState.passes,
40
+ drawCalls: runtime.testState.drawCalls,
41
+ audioCalls: runtime.testState.audioCalls,
42
+ moduleCount: runtime.bundle.moduleCount,
43
+ framesExecuted: runtime.frameIndex,
44
+ elapsedSeconds: runtime.elapsedSeconds,
45
+ },
46
+ };
47
+ }
48
+
49
+ export async function captureHeadlessEvidenceBundle(options = {}) {
50
+ const projectRoot = resolve(options.projectRoot || process.cwd());
51
+ const outDir = resolve(projectRoot, options.outDir || '.aura/evidence/latest');
52
+ const capturedAt = new Date().toISOString();
53
+ const frames = Number.isInteger(Number(options.frames)) && Number(options.frames) >= 0
54
+ ? Number(options.frames)
55
+ : 1;
56
+ const mode = 'headless';
57
+ const captureKind = options.replayPayload ? 'replay' : 'frame-advance';
58
+ let replayBundle = null;
59
+ let activeRuntime = null;
60
+ if (options.replayPayload) {
61
+ replayBundle = await runHeadlessReplay({
62
+ projectRoot,
63
+ file: options.file,
64
+ width: options.width,
65
+ height: options.height,
66
+ payload: options.replayPayload,
67
+ });
68
+ activeRuntime = replayBundle.runtime;
69
+ if (frames > 0 && replayBundle.report.ok === true) {
70
+ await advanceSessionFrames(activeRuntime, frames);
71
+ }
72
+ } else {
73
+ activeRuntime = await bootSessionRuntime({
74
+ projectRoot,
75
+ file: options.file,
76
+ width: options.width,
77
+ height: options.height,
78
+ });
79
+ if (frames > 0) {
80
+ await advanceSessionFrames(activeRuntime, frames);
81
+ }
82
+ }
83
+
84
+ const stateResult = exportSessionState(activeRuntime, {
85
+ mode,
86
+ seed: replayBundle?.report?.seed || null,
87
+ capturedAt,
88
+ });
89
+ if (!stateResult || typeof stateResult !== 'object' || stateResult.ok !== true || !stateResult.payload) {
90
+ throw new EvidenceBundleError(
91
+ typeof stateResult?.reasonCode === 'string' ? stateResult.reasonCode : 'evidence_state_export_failed',
92
+ stateResult?.detail
93
+ ? `Evidence state export failed: ${stateResult.detail}`
94
+ : 'Evidence state export failed.',
95
+ { stateResult: stateResult || null },
96
+ );
97
+ }
98
+
99
+ const runtimeInspectorSnapshot = await exportSessionInspect(activeRuntime, {
100
+ frames: 0,
101
+ mode,
102
+ });
103
+ const inspectReport = buildRuntimeInspectorSnapshotReport({
104
+ generatedAt: capturedAt,
105
+ mode,
106
+ conformanceReportPath: null,
107
+ runtimeInspectorSnapshot,
108
+ hostBinary: null,
109
+ });
110
+ if (!inspectReport || typeof inspectReport !== 'object') {
111
+ throw new EvidenceBundleError(
112
+ 'evidence_inspect_export_failed',
113
+ 'Evidence inspect export returned an invalid report payload.',
114
+ { runtimeInspectorSnapshot },
115
+ );
116
+ }
117
+ if (inspectReport.status !== 'pass') {
118
+ throw new EvidenceBundleError(
119
+ typeof inspectReport.reasonCode === 'string' ? inspectReport.reasonCode : 'evidence_inspect_export_failed',
120
+ inspectReport.error
121
+ ? `Evidence inspect export failed: ${inspectReport.error}`
122
+ : 'Evidence inspect export failed.',
123
+ { inspectReport },
124
+ );
125
+ }
126
+
127
+ const perfSummary = buildPerfSummary({
128
+ runtime: activeRuntime,
129
+ inspectReport,
130
+ captureKind,
131
+ });
132
+ const replayReasonCode = replayBundle?.report?.ok === false
133
+ ? 'evidence_capture_replay_diverged'
134
+ : 'evidence_capture_ok';
135
+ const summary = {
136
+ schemaVersion: 'aurajs.evidence-summary.v1',
137
+ ok: replayBundle ? replayBundle.report.ok !== false : true,
138
+ reasonCode: replayReasonCode,
139
+ mode,
140
+ captureKind,
141
+ capturedAt,
142
+ projectRoot,
143
+ entryFile: activeRuntime.entryFile,
144
+ runtime: {
145
+ width: activeRuntime.width,
146
+ height: activeRuntime.height,
147
+ framesExecuted: activeRuntime.frameIndex,
148
+ elapsedSeconds: activeRuntime.elapsedSeconds,
149
+ bundleOutFile: activeRuntime.bundle.outFile,
150
+ moduleCount: activeRuntime.bundle.moduleCount,
151
+ assertionsPassed: activeRuntime.testState.passes,
152
+ drawCalls: activeRuntime.testState.drawCalls,
153
+ audioCalls: activeRuntime.testState.audioCalls,
154
+ },
155
+ state: {
156
+ schemaVersion: stateResult.payload.schemaVersion,
157
+ fingerprint: stateResult.payload.export?.fingerprint || null,
158
+ },
159
+ inspect: {
160
+ schemaVersion: inspectReport.schemaVersion,
161
+ status: inspectReport.status,
162
+ reasonCode: inspectReport.reasonCode,
163
+ },
164
+ perf: perfSummary,
165
+ };
166
+ if (replayBundle) {
167
+ summary.replay = {
168
+ schemaVersion: replayBundle.report.schemaVersion,
169
+ ok: replayBundle.report.ok,
170
+ reasonCode: replayBundle.report.reasonCode,
171
+ seed: replayBundle.report.seed,
172
+ totalSteps: replayBundle.report.totalSteps,
173
+ executedFrames: replayBundle.report.executedFrames,
174
+ divergence: replayBundle.report.divergence || null,
175
+ };
176
+ }
177
+
178
+ const manifest = {
179
+ schemaVersion: EVIDENCE_BUNDLE_SCHEMA_VERSION,
180
+ ok: summary.ok,
181
+ reasonCode: summary.reasonCode,
182
+ mode,
183
+ captureKind,
184
+ capturedAt,
185
+ projectRoot,
186
+ entryFile: activeRuntime.entryFile,
187
+ outDir,
188
+ artifacts: {
189
+ summary: 'summary.json',
190
+ state: 'state.json',
191
+ inspect: 'inspect.json',
192
+ perf: 'perf.json',
193
+ },
194
+ runtime: summary.runtime,
195
+ replay: replayBundle
196
+ ? {
197
+ enabled: true,
198
+ ok: replayBundle.report.ok,
199
+ reasonCode: replayBundle.report.reasonCode,
200
+ }
201
+ : {
202
+ enabled: false,
203
+ ok: null,
204
+ reasonCode: null,
205
+ },
206
+ };
207
+ if (replayBundle) {
208
+ manifest.artifacts.replay = 'replay.json';
209
+ manifest.artifacts.replayReport = 'replay-report.json';
210
+ }
211
+
212
+ writeJsonFile(resolve(outDir, 'summary.json'), summary);
213
+ writeJsonFile(resolve(outDir, 'state.json'), stateResult.payload);
214
+ writeJsonFile(resolve(outDir, 'inspect.json'), inspectReport);
215
+ writeJsonFile(resolve(outDir, 'perf.json'), perfSummary);
216
+ if (replayBundle) {
217
+ writeJsonFile(resolve(outDir, 'replay.json'), replayBundle.replay);
218
+ writeJsonFile(resolve(outDir, 'replay-report.json'), replayBundle.report);
219
+ }
220
+ writeJsonFile(resolve(outDir, 'manifest.json'), manifest);
221
+
222
+ return {
223
+ manifest,
224
+ summary,
225
+ state: stateResult.payload,
226
+ inspect: inspectReport,
227
+ perf: perfSummary,
228
+ replay: replayBundle
229
+ ? {
230
+ input: replayBundle.replay,
231
+ report: replayBundle.report,
232
+ }
233
+ : null,
234
+ outDir,
235
+ };
236
+ }
237
+
238
+ export function serializeEvidenceManifest(payload, compact = false) {
239
+ return compact
240
+ ? `${JSON.stringify(payload)}\n`
241
+ : `${JSON.stringify(payload, null, 2)}\n`;
242
+ }