@holoscript/core 8.0.12 → 8.0.14
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/README.md +14 -0
- package/bin/holo-decision.mjs +133 -0
- package/dist/{GLTFPipeline-L76YTXKA.js → GLTFPipeline-6LS3UDYX.js} +6 -6
- package/dist/{GLTFPipeline-ZWJN7GI6.cjs → GLTFPipeline-VTI6PRRQ.cjs} +10 -10
- package/dist/{HoloCompositionParser-FLBZKFD3.js → HoloCompositionParser-GILABNN3.js} +5 -5
- package/dist/{HoloCompositionParser-3XEC7IJC.cjs → HoloCompositionParser-ZVRYVEA5.cjs} +12 -12
- package/dist/{HoloScriptPlusParser-RNUCHOAJ.cjs → HoloScriptPlusParser-WTPRPRPR.cjs} +8 -8
- package/dist/{HoloScriptPlusParser-55AY4MUF.js → HoloScriptPlusParser-ZP53ECSL.js} +5 -5
- package/dist/{SceneIRCompiler-KWUFHZ4O.cjs → SceneIRCompiler-7KQ5NKAU.cjs} +11 -11
- package/dist/{SceneIRCompiler-63KA3M2F.js → SceneIRCompiler-VX75RB6H.js} +6 -6
- package/dist/{chunk-EM2OGPYE.js → chunk-2GKF7JQ6.js} +3 -3
- package/dist/{chunk-HVX7QQYK.js → chunk-3KHRZTNW.js} +3 -3
- package/dist/{chunk-UTUD6GJI.js → chunk-42Z3SVHQ.js} +3 -3
- package/dist/{chunk-Z4IUBW46.js → chunk-47XZ62KM.js} +112 -55
- package/dist/{chunk-GGR7QUKK.cjs → chunk-4CRMVEON.cjs} +37 -37
- package/dist/{chunk-QBY7LRN2.js → chunk-4NEPHK2K.js} +3 -3
- package/dist/{chunk-65S62L4D.cjs → chunk-5B2AJKA5.cjs} +20 -20
- package/dist/{chunk-PJFTTSKE.js → chunk-5T6BWIB7.js} +4 -4
- package/dist/{chunk-KFVNCW4Q.js → chunk-62OYZT6Q.js} +3 -3
- package/dist/{chunk-3KMANSQJ.cjs → chunk-645EWDZW.cjs} +4 -4
- package/dist/{chunk-BP4KTMLY.js → chunk-6FCNMTL5.js} +4 -4
- package/dist/{chunk-77QI552M.js → chunk-73EDVY5D.js} +3 -3
- package/dist/{chunk-7IDJDMPU.cjs → chunk-7FYSSI3C.cjs} +27 -2
- package/dist/{chunk-WNYXT4TE.cjs → chunk-7ITJP33Q.cjs} +3 -3
- package/dist/chunk-7ZKQ32XK.js +1571 -0
- package/dist/{chunk-P7JEKJTZ.cjs → chunk-B6JHTTMR.cjs} +25 -14
- package/dist/{chunk-FG6PYGIZ.js → chunk-BLCWQ225.js} +4 -4
- package/dist/{chunk-7NPZZZD7.js → chunk-C73GVAYC.js} +16 -9
- package/dist/{chunk-RMOEL2GD.cjs → chunk-CESMPUEZ.cjs} +3794 -1137
- package/dist/{chunk-SQXAZHDG.js → chunk-CHIZSMWD.js} +3 -3
- package/dist/{chunk-G35CAQ7I.cjs → chunk-D44CEFY4.cjs} +5 -5
- package/dist/chunk-ERYKKPHW.cjs +1884 -0
- package/dist/{chunk-TYNRXRHF.js → chunk-EYHPTJ3F.js} +3695 -1045
- package/dist/{chunk-J3UHV5T4.cjs → chunk-FGXJPJ3W.cjs} +4 -4
- package/dist/{chunk-IJU6AS67.cjs → chunk-FHR2AVMA.cjs} +23 -23
- package/dist/{chunk-LMB555QB.cjs → chunk-FOM36K5I.cjs} +18 -18
- package/dist/{chunk-JBYBMBMW.js → chunk-FWKEY4LD.js} +3 -2
- package/dist/{chunk-ZRPALBQB.cjs → chunk-GGH3ZYDB.cjs} +5 -5
- package/dist/{chunk-2BYAUHBO.js → chunk-GI5YYZH6.js} +3 -3
- package/dist/{chunk-VTEXJOSD.cjs → chunk-GYJLP4BO.cjs} +30 -30
- package/dist/{chunk-OC6GV5QH.cjs → chunk-HCONR4J6.cjs} +38 -38
- package/dist/{chunk-B3CWTCK2.js → chunk-IA7FCSRY.js} +27 -2
- package/dist/{chunk-5FYMCVBY.js → chunk-IXFNA5TT.js} +4 -4
- package/dist/{chunk-G6KACNMO.js → chunk-JCVSCKUH.js} +4 -4
- package/dist/{chunk-FHVPN7BN.js → chunk-JQCXLKAU.js} +3 -3
- package/dist/{chunk-F3YT6GUF.cjs → chunk-KLM6QD6D.cjs} +14 -14
- package/dist/{chunk-UGQ3QNV6.js → chunk-KOGPVAP6.js} +24 -8
- package/dist/{chunk-CKV5NYAE.js → chunk-KYJD2UMV.js} +4 -4
- package/dist/{chunk-LB3ZZMKT.cjs → chunk-L4DBUX3N.cjs} +10 -10
- package/dist/{chunk-RXQNRZ5F.js → chunk-LGRKBTPM.js} +3 -3
- package/dist/{chunk-OMNHTCS4.cjs → chunk-LHUDAJQT.cjs} +3 -2
- package/dist/{chunk-PDXX5UI4.cjs → chunk-LQNL3IYV.cjs} +38 -38
- package/dist/{chunk-WWNCM473.js → chunk-M7XR3F53.js} +4 -4
- package/dist/{chunk-IFW5IW4L.cjs → chunk-ML4V5PVU.cjs} +670 -627
- package/dist/{chunk-656IAS7B.cjs → chunk-N7IYRAFG.cjs} +21 -14
- package/dist/chunk-N7MIIDLI.cjs +1605 -0
- package/dist/{chunk-USOUXQYD.js → chunk-NWKARJM2.js} +130 -22
- package/dist/{chunk-VVAAZITA.cjs → chunk-OOP4S3GU.cjs} +5 -5
- package/dist/{chunk-TX6ZBIF4.js → chunk-ORBVCOTC.js} +3 -3
- package/dist/{chunk-RRQIAJLQ.cjs → chunk-OSKGCXAQ.cjs} +5 -5
- package/dist/{chunk-QEDMOGF3.cjs → chunk-P65OIMJT.cjs} +7 -7
- package/dist/{chunk-QM7FJB5W.js → chunk-PSWCJQS4.js} +4 -4
- package/dist/{chunk-7N63JHUN.cjs → chunk-PZ46WRHX.cjs} +8 -8
- package/dist/{chunk-AATYYLYK.js → chunk-Q4J2K7FI.js} +16 -5
- package/dist/chunk-QLPRI3QW.js +1875 -0
- package/dist/{chunk-WTH23ISI.js → chunk-R5VKLUMR.js} +4 -4
- package/dist/{chunk-NQN5LFN4.cjs → chunk-REN3LHO6.cjs} +19 -19
- package/dist/{chunk-JEJ7TT54.js → chunk-RVN7OPCP.js} +4 -4
- package/dist/{chunk-ZK7KX5CD.cjs → chunk-SE2Y5BSL.cjs} +6 -6
- package/dist/{chunk-2X3IPCBK.cjs → chunk-SKVBUGMC.cjs} +7 -7
- package/dist/{chunk-GZPUA2TL.cjs → chunk-SNMQUWIO.cjs} +10 -10
- package/dist/{chunk-OIBRWLPY.cjs → chunk-TKDDIE3T.cjs} +54 -3
- package/dist/{chunk-5H5GFBMG.cjs → chunk-TMNAKNV2.cjs} +112 -55
- package/dist/{chunk-5LVFTGKH.js → chunk-TZQKJOPC.js} +3 -3
- package/dist/{chunk-TSTFYGGX.js → chunk-UKEK2NZJ.js} +3 -3
- package/dist/{chunk-3IUHTGDD.cjs → chunk-VA7THINF.cjs} +38 -38
- package/dist/{chunk-Z557DVYN.js → chunk-VMCR5QVI.js} +4 -4
- package/dist/{chunk-IS7NTKY5.cjs → chunk-VTFLKSJL.cjs} +14 -14
- package/dist/{chunk-VO52AJD5.js → chunk-VXHB6ZHY.js} +4 -4
- package/dist/{chunk-S4O7CFHQ.cjs → chunk-VZI7S7P6.cjs} +7 -7
- package/dist/{chunk-BQJ3YBF3.js → chunk-W4AJMMQR.js} +667 -628
- package/dist/{chunk-2KKOYZYI.cjs → chunk-XZC75AJ4.cjs} +5 -5
- package/dist/{chunk-FWCHPCD4.js → chunk-Y2OCKXVD.js} +4 -4
- package/dist/{chunk-EI5G5JLY.cjs → chunk-YBM34FUJ.cjs} +134 -22
- package/dist/{chunk-DUG3OQAS.js → chunk-YDSNDCV3.js} +3 -3
- package/dist/{chunk-566ZB4LZ.cjs → chunk-YM7UUYR5.cjs} +5 -5
- package/dist/{chunk-BCP4E7MD.cjs → chunk-YMI3ED3B.cjs} +26 -10
- package/dist/{chunk-CP7V3ATL.js → chunk-Z7NUL73U.js} +51 -4
- package/dist/cli/holoscript-runner.cjs +11 -11
- package/dist/cli/holoscript-runner.js +4 -4
- package/dist/compiler/agent-inference.cjs +8 -8
- package/dist/compiler/agent-inference.js +4 -4
- package/dist/compiler/android-xr.cjs +7 -7
- package/dist/compiler/android-xr.js +5 -5
- package/dist/compiler/android.cjs +6 -6
- package/dist/compiler/android.js +4 -4
- package/dist/compiler/context.cjs +6 -6
- package/dist/compiler/context.js +3 -3
- package/dist/compiler/daimon-seed.cjs +9 -9
- package/dist/compiler/daimon-seed.js +4 -4
- package/dist/compiler/domain-block-utils.cjs +165 -165
- package/dist/compiler/domain-block-utils.js +4 -4
- package/dist/compiler/dtdl.cjs +7 -7
- package/dist/compiler/dtdl.js +4 -4
- package/dist/compiler/gltf-pipeline.cjs +8 -8
- package/dist/compiler/gltf-pipeline.js +1 -1
- package/dist/compiler/godot.cjs +6 -6
- package/dist/compiler/godot.js +5 -5
- package/dist/compiler/incremental.cjs +8 -8
- package/dist/compiler/incremental.js +3 -3
- package/dist/compiler/index.cjs +871 -207
- package/dist/compiler/index.d.ts +21 -1
- package/dist/compiler/index.js +696 -60
- package/dist/compiler/ios.cjs +6 -6
- package/dist/compiler/ios.js +4 -4
- package/dist/compiler/llm-provider-capabilities.cjs +6 -6
- package/dist/compiler/llm-provider-capabilities.js +3 -3
- package/dist/compiler/openxr.cjs +6 -6
- package/dist/compiler/openxr.js +5 -5
- package/dist/compiler/sdf.cjs +7 -7
- package/dist/compiler/sdf.js +5 -5
- package/dist/compiler/state.cjs +6 -6
- package/dist/compiler/state.js +4 -4
- package/dist/compiler/trait-composition.cjs +7 -7
- package/dist/compiler/trait-composition.js +3 -3
- package/dist/compiler/unity.cjs +6 -6
- package/dist/compiler/unity.js +5 -5
- package/dist/compiler/unreal.cjs +7 -7
- package/dist/compiler/unreal.js +5 -5
- package/dist/compiler/urdf.cjs +14 -14
- package/dist/compiler/urdf.js +5 -5
- package/dist/compiler/usd-physics.cjs +7 -7
- package/dist/compiler/usd-physics.js +4 -4
- package/dist/compiler/visionos.cjs +6 -6
- package/dist/compiler/visionos.js +5 -5
- package/dist/compiler/vrchat.cjs +7 -7
- package/dist/compiler/vrchat.js +5 -5
- package/dist/compiler/wasm.cjs +10 -10
- package/dist/compiler/wasm.js +5 -5
- package/dist/compiler/webgpu.cjs +6 -6
- package/dist/compiler/webgpu.js +5 -5
- package/dist/constants.cjs +3 -3
- package/dist/constants.js +1 -1
- package/dist/entries/scripting.cjs +6 -6
- package/dist/entries/scripting.js +2 -2
- package/dist/evolution/index.cjs +21 -17
- package/dist/evolution/index.d.ts +9 -0
- package/dist/evolution/index.js +6 -6
- package/dist/index.cjs +930 -703
- package/dist/index.d.ts +70 -5
- package/dist/index.js +192 -109
- package/dist/parser.cjs +19 -19
- package/dist/parser.js +5 -5
- package/dist/reconstruction/index.cjs +127 -38
- package/dist/reconstruction/index.d.ts +159 -0
- package/dist/reconstruction/index.js +11 -2
- package/dist/runtime.d.ts +1 -0
- package/dist/traitDocs/traitDocs.cjs +8 -8
- package/dist/traitDocs/traitDocs.js +2 -2
- package/dist/traits/index.cjs +566 -471
- package/dist/traits/index.js +93 -11
- package/package.json +25 -41
- package/dist/chunk-G3BM3CT4.cjs +0 -639
- package/dist/chunk-KEYG7HGY.js +0 -1062
- package/dist/chunk-QX34ELJ7.js +0 -625
- package/dist/chunk-W2GA3EQB.cjs +0 -1065
package/dist/compiler/index.js
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
export { ContextCompileError, ContextCompiler, createContextCompiler } from '../chunk-
|
|
2
|
-
export { LLMCapabilityCompileError, LLMProviderCapabilitiesCompiler, createLLMProviderCapabilitiesCompiler } from '../chunk-
|
|
3
|
-
export { GLTF_PIPELINE_TOOLS, registerGLTFTools } from '../chunk-
|
|
1
|
+
export { ContextCompileError, ContextCompiler, createContextCompiler } from '../chunk-42Z3SVHQ.js';
|
|
2
|
+
export { LLMCapabilityCompileError, LLMProviderCapabilitiesCompiler, createLLMProviderCapabilitiesCompiler } from '../chunk-LGRKBTPM.js';
|
|
3
|
+
export { GLTF_PIPELINE_TOOLS, registerGLTFTools } from '../chunk-2GKF7JQ6.js';
|
|
4
4
|
export { BUSINESS_QUEST_TOOLS, buildVRRCompositionFromDraft, businessVRRDraftSchema, draftToHoloPreview, handleBusinessQuestToolCall, registerBusinessQuestTools, validateBusinessVRRDraft } from '../chunk-NWMJPTVL.js';
|
|
5
5
|
export { NodeToyMapper, mapNodeToyToShader } from '../chunk-TG7O4WBC.js';
|
|
6
6
|
export { createReproducibilityContext, parseReproducibilityFlags } from '../chunk-5GLCTO44.js';
|
|
7
|
-
export { QuantumCircuitCompiler } from '../chunk-
|
|
8
|
-
import { init_NextJSAPICompiler, init_DialectRegistry, DialectRegistry, init_HoloMCPCompiler, init_OmnigentAgentYamlCompiler, init_NodeServiceCompiler, init_SDKCompiler, init_LlamaServerCompiler, init_holoscript_gbnf, init_registerBuiltinDialects, init_PCGGraphCompiler } from '../chunk-
|
|
9
|
-
export { CodeEditorCompiler, CompileTimeAuthorityEffectError, CompilerBridge, DEFAULT_MATERIAL_KEYWORDS, DEFAULT_OBJECT_KEYWORDS, DEFAULT_PRIMITIVE_SHAPES, DialectRegistry, EdgeCompiler, FMUCompiler, GaussianSplattingCompiler, GaussianTrainCompiler, GaussianTrainConfigError, HOLOSCRIPT_GRAMMAR_PRESETS, HoloMCPCompiler, LlamaServerCompiler, NextJSAPICompiler, NodeServiceCompiler, OmnigentAgentYamlCompiler, PCGGraphCompiler, PCG_GRAPH_SCHEMA, REMOTE_TRAIN_EXECUTOR, REQUIRED_SANDBOX_AUTHORITY_EFFECT, SANDBOX_AUTHORITY_TRAIT, SCMCompiler, SDKCompiler, SHARED_SORT_SHADER_PATH, SOVEREIGN_TRAIN_EXECUTOR, SVGCompiler, SpatialPartitionPass, ThreeDTilesCompiler, USDZPipeline, absorbFMU, assertAuthorityEffects, bestCategoryForTraits, checkAuthorityEffects, collectAuthorityEffectNodes, compileAllToNextJSAPI, compilePCGGraphFromBlocks, compilePipelineSource, compilePipelineSourceToNode, compilePipelineSourceToPython, compilePipelineToNode, compilePipelineToPython, compileTo3DTiles, compileToFMU, compileToNextJSAPI, compileToPCGGraph, createGaussianSplattingCompiler, createGaussianTrainCompiler, createOmnigentAgentYamlCompiler, createThreeDTilesCompiler, detectMultiUserSharedSort, ensureDialectsBooted, generateHoloScriptGbnf, isHoloScriptGrammarPreset, pcgGraphToUnrealXml, quickSafetyCheck, registerBuiltinDialects, runSafetyPass, selectModality, selectModalityForAll, spatialPartition, streamWorldTiles } from '../chunk-
|
|
7
|
+
export { QuantumCircuitCompiler } from '../chunk-GI5YYZH6.js';
|
|
8
|
+
import { init_NextJSAPICompiler, init_DialectRegistry, DialectRegistry, init_HoloMCPCompiler, init_OmnigentAgentYamlCompiler, init_NodeServiceCompiler, init_SDKCompiler, init_LlamaServerCompiler, init_holoscript_gbnf, init_registerBuiltinDialects, init_PCGGraphCompiler } from '../chunk-EYHPTJ3F.js';
|
|
9
|
+
export { CodeEditorCompiler, CompileTimeAuthorityEffectError, CompilerBridge, ComputePhysicsCompiler, CpuPathTracer, DEFAULT_MATERIAL_KEYWORDS, DEFAULT_OBJECT_KEYWORDS, DEFAULT_PRIMITIVE_SHAPES, DesktopGPUCompiler, DialectRegistry, EdgeCompiler, FMUCompiler, GaussianSplattingCompiler, GaussianTrainCompiler, GaussianTrainConfigError, HOLOSCRIPT_GRAMMAR_PRESETS, HoloMCPCompiler, LlamaServerCompiler, MediaPipelineCompiler, NextJSAPICompiler, NodeServiceCompiler, OmnigentAgentYamlCompiler, PCGGraphCompiler, PCG_GRAPH_SCHEMA, PathTracerCompiler, PhysicsColliderCompiler, REMOTE_TRAIN_EXECUTOR, REQUIRED_SANDBOX_AUTHORITY_EFFECT, SANDBOX_AUTHORITY_TRAIT, SCMCompiler, SDKCompiler, SHARED_SORT_SHADER_PATH, SOVEREIGN_TRAIN_EXECUTOR, SVGCompiler, SpatialAudioCompiler, SpatialPartitionPass, ThreeDTilesCompiler, USDZPipeline, absorbFMU, assertAuthorityEffects, bestCategoryForTraits, checkAuthorityEffects, collectAuthorityEffectNodes, compileAllToNextJSAPI, compilePCGGraphFromBlocks, compilePipelineSource, compilePipelineSourceToNode, compilePipelineSourceToPython, compilePipelineToNode, compilePipelineToPython, compileTo3DTiles, compileToFMU, compileToNextJSAPI, compileToPCGGraph, createGaussianSplattingCompiler, createGaussianTrainCompiler, createOmnigentAgentYamlCompiler, createThreeDTilesCompiler, detectMultiUserSharedSort, ensureDialectsBooted, generateHoloScriptGbnf, isHoloScriptGrammarPreset, pcgGraphToUnrealXml, quickSafetyCheck, registerBuiltinDialects, runSafetyPass, selectModality, selectModalityForAll, spatialPartition, streamWorldTiles } from '../chunk-EYHPTJ3F.js';
|
|
10
10
|
export { generateHullGeometry, generateMembraneGeometry, generateSplineGeometry } from '../chunk-UDE4OZMR.js';
|
|
11
11
|
import '../chunk-3F7ZZWIN.js';
|
|
12
|
-
export { SceneIRCompiler } from '../chunk-
|
|
12
|
+
export { SceneIRCompiler } from '../chunk-PSWCJQS4.js';
|
|
13
13
|
import '../chunk-2MQKNDNH.js';
|
|
14
|
-
import { init_DaimonSeedCompiler } from '../chunk-
|
|
15
|
-
export { DaimonSeedCompiler, computeExportFidelity, createDaimonSeedCompiler, runHysteresisExp2 } from '../chunk-
|
|
14
|
+
import { init_DaimonSeedCompiler } from '../chunk-4NEPHK2K.js';
|
|
15
|
+
export { DaimonSeedCompiler, computeExportFidelity, createDaimonSeedCompiler, runHysteresisExp2 } from '../chunk-4NEPHK2K.js';
|
|
16
16
|
import { assertHoloMapManifestContract } from '../chunk-IXWGYWH6.js';
|
|
17
17
|
export { COCOExporterImpl as COCOExporter } from '../chunk-Q56TT7IL.js';
|
|
18
18
|
export { RemotionBridgeImpl as RemotionBridge } from '../chunk-YYXH45E2.js';
|
|
19
19
|
export { SemanticSceneGraph } from '../chunk-HHRZ6STP.js';
|
|
20
|
-
import { init_AgentInferenceExportTarget } from '../chunk-
|
|
21
|
-
export { AgentInferenceCompiler, AgentInferenceExportTarget_default as AgentInferenceExportTarget, createAgentInferenceCompiler, createPythonAgentInferenceCompiler } from '../chunk-
|
|
22
|
-
import { vrTraitRegistry } from '../chunk-
|
|
20
|
+
import { init_AgentInferenceExportTarget } from '../chunk-KOGPVAP6.js';
|
|
21
|
+
export { AgentInferenceCompiler, AgentInferenceExportTarget_default as AgentInferenceExportTarget, createAgentInferenceCompiler, createPythonAgentInferenceCompiler } from '../chunk-KOGPVAP6.js';
|
|
22
|
+
import { vrTraitRegistry } from '../chunk-W4AJMMQR.js';
|
|
23
23
|
import '../chunk-6TRX6AR2.js';
|
|
24
24
|
import '../chunk-ZVQMKUGJ.js';
|
|
25
25
|
import { isWebGpuEnvironmentPresent } from '../chunk-K56UVEXV.js';
|
|
@@ -28,50 +28,50 @@ import '../chunk-2M2DPHKB.js';
|
|
|
28
28
|
import '../chunk-TDCNJHWO.js';
|
|
29
29
|
import '../chunk-VKCTYLDN.js';
|
|
30
30
|
import '../chunk-YQELFNJV.js';
|
|
31
|
-
export { USDPhysicsCompiler } from '../chunk-
|
|
32
|
-
import { init_SDFCompiler } from '../chunk-
|
|
33
|
-
export { SDFCompiler } from '../chunk-
|
|
34
|
-
import { init_StateCompiler } from '../chunk-
|
|
35
|
-
export { StateCompiler } from '../chunk-
|
|
36
|
-
export { TraitCompositionCompiler } from '../chunk-
|
|
31
|
+
export { USDPhysicsCompiler } from '../chunk-BLCWQ225.js';
|
|
32
|
+
import { init_SDFCompiler } from '../chunk-IXFNA5TT.js';
|
|
33
|
+
export { SDFCompiler } from '../chunk-IXFNA5TT.js';
|
|
34
|
+
import { init_StateCompiler } from '../chunk-62OYZT6Q.js';
|
|
35
|
+
export { StateCompiler } from '../chunk-62OYZT6Q.js';
|
|
36
|
+
export { TraitCompositionCompiler } from '../chunk-UKEK2NZJ.js';
|
|
37
37
|
import '../chunk-DQRJ5RJG.js';
|
|
38
|
-
export { IncrementalCompiler, createIncrementalCompiler } from '../chunk-
|
|
38
|
+
export { IncrementalCompiler, createIncrementalCompiler } from '../chunk-VXHB6ZHY.js';
|
|
39
39
|
import '../chunk-4R6SBXDB.js';
|
|
40
|
-
import { init_AndroidCompiler } from '../chunk-
|
|
41
|
-
export { AndroidCompiler } from '../chunk-
|
|
42
|
-
import { init_AndroidXRCompiler, init_AndroidXRTraitMap, AndroidXRCompiler, getTraitMapping, ANDROIDXR_TRAIT_MAP } from '../chunk-
|
|
43
|
-
export { AndroidXRCompiler } from '../chunk-
|
|
40
|
+
import { init_AndroidCompiler } from '../chunk-3KHRZTNW.js';
|
|
41
|
+
export { AndroidCompiler } from '../chunk-3KHRZTNW.js';
|
|
42
|
+
import { init_AndroidXRCompiler, init_AndroidXRTraitMap, AndroidXRCompiler, getTraitMapping, ANDROIDXR_TRAIT_MAP } from '../chunk-JCVSCKUH.js';
|
|
43
|
+
export { AndroidXRCompiler } from '../chunk-JCVSCKUH.js';
|
|
44
44
|
import '../chunk-CBSDJF3B.js';
|
|
45
|
-
import { init_IOSCompiler } from '../chunk-
|
|
46
|
-
export { IOSCompiler } from '../chunk-
|
|
47
|
-
import { init_VisionOSCompiler, init_VisionOSTraitMap, getTraitMapping as getTraitMapping$1, listAllTraits, generateTraitCode } from '../chunk-
|
|
48
|
-
export { VisionOSCompiler } from '../chunk-
|
|
49
|
-
import { init_WASMCompiler } from '../chunk-
|
|
50
|
-
export { WASMCompiler } from '../chunk-
|
|
51
|
-
import { init_WebGPUCompiler, WebGPUCompiler } from '../chunk-
|
|
52
|
-
export { WebGPUCompiler } from '../chunk-
|
|
53
|
-
import { init_DTDLCompiler } from '../chunk-
|
|
54
|
-
export { DTDLCompiler } from '../chunk-
|
|
55
|
-
import { init_URDFCompiler } from '../chunk-
|
|
56
|
-
export { URDFCompiler, createURDFCompiler } from '../chunk-
|
|
45
|
+
import { init_IOSCompiler } from '../chunk-73EDVY5D.js';
|
|
46
|
+
export { IOSCompiler } from '../chunk-73EDVY5D.js';
|
|
47
|
+
import { init_VisionOSCompiler, init_VisionOSTraitMap, getTraitMapping as getTraitMapping$1, listAllTraits, generateTraitCode } from '../chunk-VMCR5QVI.js';
|
|
48
|
+
export { VisionOSCompiler } from '../chunk-VMCR5QVI.js';
|
|
49
|
+
import { init_WASMCompiler } from '../chunk-5T6BWIB7.js';
|
|
50
|
+
export { WASMCompiler } from '../chunk-5T6BWIB7.js';
|
|
51
|
+
import { init_WebGPUCompiler, WebGPUCompiler } from '../chunk-QLPRI3QW.js';
|
|
52
|
+
export { WebGPUCompiler } from '../chunk-QLPRI3QW.js';
|
|
53
|
+
import { init_DTDLCompiler } from '../chunk-CHIZSMWD.js';
|
|
54
|
+
export { DTDLCompiler } from '../chunk-CHIZSMWD.js';
|
|
55
|
+
import { init_URDFCompiler } from '../chunk-Q4J2K7FI.js';
|
|
56
|
+
export { URDFCompiler, createURDFCompiler } from '../chunk-Q4J2K7FI.js';
|
|
57
57
|
import '../chunk-JBQXZIWB.js';
|
|
58
|
-
import { init_OpenXRCompiler } from '../chunk-
|
|
59
|
-
export { OpenXRCompiler } from '../chunk-
|
|
60
|
-
import { init_VRChatCompiler } from '../chunk-
|
|
61
|
-
export { VRChatCompiler } from '../chunk-
|
|
62
|
-
import { init_UnityCompiler } from '../chunk-
|
|
63
|
-
export { UnityCompiler } from '../chunk-
|
|
64
|
-
import '../chunk-
|
|
58
|
+
import { init_OpenXRCompiler } from '../chunk-R5VKLUMR.js';
|
|
59
|
+
export { OpenXRCompiler } from '../chunk-R5VKLUMR.js';
|
|
60
|
+
import { init_VRChatCompiler } from '../chunk-6FCNMTL5.js';
|
|
61
|
+
export { VRChatCompiler } from '../chunk-6FCNMTL5.js';
|
|
62
|
+
import { init_UnityCompiler } from '../chunk-KYJD2UMV.js';
|
|
63
|
+
export { UnityCompiler } from '../chunk-KYJD2UMV.js';
|
|
64
|
+
import '../chunk-M7XR3F53.js';
|
|
65
65
|
import { init_PlatformConditionalCompilerMixin } from '../chunk-DJNH4HFW.js';
|
|
66
66
|
export { PlatformConditionalCompilerMixin, createPlatformTarget, filterCompositionForPlatform, matchesPlatformConstraint, normalizePlatformName } from '../chunk-DJNH4HFW.js';
|
|
67
|
-
import { init_GodotCompiler } from '../chunk-
|
|
68
|
-
export { GodotCompiler } from '../chunk-
|
|
69
|
-
import '../chunk-
|
|
67
|
+
import { init_GodotCompiler } from '../chunk-RVN7OPCP.js';
|
|
68
|
+
export { GodotCompiler } from '../chunk-RVN7OPCP.js';
|
|
69
|
+
import '../chunk-TZQKJOPC.js';
|
|
70
70
|
import { init_PerceptualColorPass } from '../chunk-UCVZXQ63.js';
|
|
71
71
|
export { SCIENTIFIC_COLOR_MAPS, analyzePerceptualColor, applyPerceptualColorPass, buildPerceptualGradient, buildPerceptualPalette, hexToSrgb, normalizeHexColor, srgbToHex } from '../chunk-UCVZXQ63.js';
|
|
72
|
-
import { init_CompilerBase, init_CompilerDocumentationGenerator, CompilerBase } from '../chunk-
|
|
73
|
-
export { CompilerBase, CompilerDocumentationGenerator, UnauthorizedCompilerAccessError, createTestCompilerToken, isCapabilityTokenCredential } from '../chunk-
|
|
74
|
-
import { init_traitDocs, getTraitDoc, getAllTraitNames } from '../chunk-
|
|
72
|
+
import { init_CompilerBase, init_CompilerDocumentationGenerator, CompilerBase } from '../chunk-YDSNDCV3.js';
|
|
73
|
+
export { CompilerBase, CompilerDocumentationGenerator, UnauthorizedCompilerAccessError, createTestCompilerToken, isCapabilityTokenCredential } from '../chunk-YDSNDCV3.js';
|
|
74
|
+
import { init_traitDocs, getTraitDoc, getAllTraitNames } from '../chunk-IA7FCSRY.js';
|
|
75
75
|
import '../chunk-5CURIYGT.js';
|
|
76
76
|
import '../chunk-33YHE7HX.js';
|
|
77
77
|
import '../chunk-GLEJ2TLS.js';
|
|
@@ -89,6 +89,7 @@ import '../chunk-ZVFHPMC5.js';
|
|
|
89
89
|
import { init_safeJsonParse, readJson } from '../chunk-RAN3ECAS.js';
|
|
90
90
|
import '../chunk-W4GABFCR.js';
|
|
91
91
|
import { ANSCapabilityPath } from '@holoscript/core-types/ans';
|
|
92
|
+
import { createHash } from 'crypto';
|
|
92
93
|
|
|
93
94
|
// src/compiler/index.ts
|
|
94
95
|
init_CompilerBase();
|
|
@@ -133,7 +134,7 @@ init_CompilerBase();
|
|
|
133
134
|
// src/compiler/Native2DCompiler.ts
|
|
134
135
|
init_CompilerBase();
|
|
135
136
|
init_safeJsonParse();
|
|
136
|
-
var
|
|
137
|
+
var _Native2DCompiler = class _Native2DCompiler extends CompilerBase {
|
|
137
138
|
constructor() {
|
|
138
139
|
super(...arguments);
|
|
139
140
|
this.compilerName = "Native2DCompiler";
|
|
@@ -146,7 +147,22 @@ var Native2DCompiler = class extends CompilerBase {
|
|
|
146
147
|
this._stateFields = /* @__PURE__ */ new Map();
|
|
147
148
|
this._fetchCalls = [];
|
|
148
149
|
this._hookCalls = [];
|
|
150
|
+
this._computedBindings = [];
|
|
149
151
|
this._options = {};
|
|
152
|
+
/** Honest mode (composition-level `@honest`): every data-bound element MUST carry
|
|
153
|
+
* `@provenance_bound` or the compiler refuses to emit it (HONEST-UNSOURCED). This is
|
|
154
|
+
* the Receipt-Bound Surface constitution — the surface cannot emit an unsourced pixel. */
|
|
155
|
+
this._honestMode = false;
|
|
156
|
+
this._verifiedViewMode = false;
|
|
157
|
+
/** Valid projection roots: composition state keys + @fetch into-slots (pre-scanned). */
|
|
158
|
+
this._projectionRoots = /* @__PURE__ */ new Set();
|
|
159
|
+
/**
|
|
160
|
+
* Verified projections collected during traversal (@verified_view v1): the machine-readable
|
|
161
|
+
* view contract that co-emits with the surface — a portable, hash-bound receipt of what
|
|
162
|
+
* every element renders, so an independent consumer can re-derive it from the ARTIFACT
|
|
163
|
+
* (not the source). Populated by resolveProjection; emitted as `export const holoViewContract`.
|
|
164
|
+
*/
|
|
165
|
+
this._collectedProjections = [];
|
|
150
166
|
}
|
|
151
167
|
// @ts-expect-error During migration
|
|
152
168
|
compile(composition, agentToken, outputPath, options) {
|
|
@@ -166,13 +182,46 @@ var Native2DCompiler = class extends CompilerBase {
|
|
|
166
182
|
this._stateFields.clear();
|
|
167
183
|
this._fetchCalls = [];
|
|
168
184
|
this._hookCalls = [];
|
|
185
|
+
this._computedBindings = [];
|
|
169
186
|
this._options = options || {};
|
|
187
|
+
this._honestMode = (composition?.traits ?? []).some((t) => t?.name === "honest");
|
|
188
|
+
this._verifiedViewMode = (composition?.traits ?? []).some((t) => t?.name === "verified_view");
|
|
170
189
|
const safeName = name.replace(/[^a-zA-Z0-9]/g, "");
|
|
171
190
|
if (composition?.state?.properties) {
|
|
172
191
|
for (const prop of composition.state.properties) {
|
|
173
192
|
this._stateFields.set(prop.key, prop.value ?? null);
|
|
174
193
|
}
|
|
175
194
|
}
|
|
195
|
+
this._projectionRoots = new Set(this._stateFields.keys());
|
|
196
|
+
this._collectedProjections = [];
|
|
197
|
+
const scanProjectionRoots = (objs) => {
|
|
198
|
+
for (const o of objs) {
|
|
199
|
+
for (const t of o.traits ?? []) {
|
|
200
|
+
if (t?.name === "fetch") {
|
|
201
|
+
const into = t.config?.into;
|
|
202
|
+
this._projectionRoots.add(typeof into === "string" && into ? into : "data");
|
|
203
|
+
}
|
|
204
|
+
if (t?.name === "each") {
|
|
205
|
+
const as = t.config?.as;
|
|
206
|
+
this._projectionRoots.add(typeof as === "string" && as ? as : "item");
|
|
207
|
+
}
|
|
208
|
+
if (t?.name === "computed") {
|
|
209
|
+
const nm = t.config?.name;
|
|
210
|
+
if (typeof nm === "string" && nm) this._projectionRoots.add(nm);
|
|
211
|
+
}
|
|
212
|
+
if (t?.name === "hook") {
|
|
213
|
+
const returns = t.config?.returns;
|
|
214
|
+
if (typeof returns === "string") {
|
|
215
|
+
for (const r of returns.split(",").map((s) => s.trim())) {
|
|
216
|
+
if (r) this._projectionRoots.add(r);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
if (Array.isArray(o.children)) scanProjectionRoots(o.children);
|
|
222
|
+
}
|
|
223
|
+
};
|
|
224
|
+
scanProjectionRoots(objects);
|
|
176
225
|
const jsx = objects.map((obj) => this.generateReactNode(obj)).join("\n ");
|
|
177
226
|
const imports = [];
|
|
178
227
|
const reactImports = /* @__PURE__ */ new Set();
|
|
@@ -190,6 +239,17 @@ var Native2DCompiler = class extends CompilerBase {
|
|
|
190
239
|
for (const h of this._hookCalls) {
|
|
191
240
|
imports.push(`import { ${h.name} } from '${h.import}';`);
|
|
192
241
|
}
|
|
242
|
+
const computedImports = /* @__PURE__ */ new Map();
|
|
243
|
+
for (const b of this._computedBindings) {
|
|
244
|
+
if (b.from && b.uses.length) {
|
|
245
|
+
const set = computedImports.get(b.from) || /* @__PURE__ */ new Set();
|
|
246
|
+
b.uses.forEach((u) => set.add(u));
|
|
247
|
+
computedImports.set(b.from, set);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
for (const [from, uses] of computedImports) {
|
|
251
|
+
imports.push(`import { ${[...uses].join(", ")} } from '${from}';`);
|
|
252
|
+
}
|
|
193
253
|
const stateHooks = [];
|
|
194
254
|
for (const [key, value] of this._stateFields) {
|
|
195
255
|
const capitalKey = key.charAt(0).toUpperCase() + key.slice(1);
|
|
@@ -212,25 +272,36 @@ var Native2DCompiler = class extends CompilerBase {
|
|
|
212
272
|
const hookBindings = [];
|
|
213
273
|
for (const h of this._hookCalls) {
|
|
214
274
|
const members = h.returns.split(",").map((s) => s.trim()).filter((s) => /^[A-Za-z_$][\w$]*$/.test(s));
|
|
275
|
+
const call = `${h.name}(${h.args ?? ""})`;
|
|
215
276
|
hookBindings.push(
|
|
216
|
-
members.length > 0 ? ` const { ${members.join(", ")} } = ${
|
|
277
|
+
members.length > 0 ? ` const { ${members.join(", ")} } = ${call};` : ` ${call};`
|
|
217
278
|
);
|
|
218
279
|
}
|
|
280
|
+
const computedLines = [];
|
|
281
|
+
for (const b of this._computedBindings) {
|
|
282
|
+
computedLines.push(` const ${b.name} = ${b.expr};`);
|
|
283
|
+
}
|
|
284
|
+
const viewContract = this.buildViewContract();
|
|
285
|
+
const rootAttrs = viewContract ? ` data-holo-view-contract="${viewContract.hash}"` : "";
|
|
286
|
+
const contractExport = viewContract ? `
|
|
287
|
+
|
|
288
|
+
export const holoViewContract = ${viewContract.json} as const;` : "";
|
|
219
289
|
return `${imports.join("\n")}
|
|
220
290
|
|
|
221
291
|
// @generated by HoloScript Native2DCompiler \u2014 DO NOT EDIT
|
|
222
292
|
export function ${safeName}Component() {${hookBindings.length > 0 ? "\n" + hookBindings.join("\n") : ""}
|
|
223
293
|
${stateHooks.join("\n")}
|
|
224
294
|
${fetchEffects.join("\n")}
|
|
295
|
+
${computedLines.join("\n")}
|
|
225
296
|
|
|
226
297
|
return (
|
|
227
|
-
<div className="holoscript-2d-root w-full h-full">
|
|
298
|
+
<div className="holoscript-2d-root w-full h-full"${rootAttrs}>
|
|
228
299
|
${jsx}
|
|
229
300
|
</div>
|
|
230
301
|
);
|
|
231
302
|
}
|
|
232
303
|
|
|
233
|
-
export default ${safeName}Component
|
|
304
|
+
export default ${safeName}Component;${contractExport}
|
|
234
305
|
`;
|
|
235
306
|
}
|
|
236
307
|
generateReactNode(obj) {
|
|
@@ -272,8 +343,39 @@ export default ${safeName}Component;
|
|
|
272
343
|
if (/['"`\\]/.test(importPath)) {
|
|
273
344
|
throw new Error(`Native2DCompiler @hook: invalid import path ${JSON.stringify(importPath)}`);
|
|
274
345
|
}
|
|
346
|
+
let hookArgs = "";
|
|
347
|
+
if (traits.hook.args != null) {
|
|
348
|
+
hookArgs = String(traits.hook.args);
|
|
349
|
+
if (!/^[a-zA-Z0-9_$.,(){}\[\]'"/\s*+\-%<>=?:!&|]+$/.test(hookArgs)) {
|
|
350
|
+
throw new Error(`Native2DCompiler @hook: unsafe args ${JSON.stringify(hookArgs)}`);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
275
353
|
if (!this._hookCalls.some((h) => h.name === hookName)) {
|
|
276
|
-
this._hookCalls.push({
|
|
354
|
+
this._hookCalls.push({
|
|
355
|
+
name: hookName,
|
|
356
|
+
import: importPath,
|
|
357
|
+
returns: String(traits.hook.returns || ""),
|
|
358
|
+
args: hookArgs || void 0
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
if (traits.computed?.name && traits.computed?.expr) {
|
|
363
|
+
const cname = String(traits.computed.name);
|
|
364
|
+
const expr = String(traits.computed.expr);
|
|
365
|
+
if (!/^[A-Za-z_$][\w$]*$/.test(cname)) {
|
|
366
|
+
throw new Error(`Native2DCompiler @computed: invalid name ${JSON.stringify(cname)}`);
|
|
367
|
+
}
|
|
368
|
+
if (!/^[a-zA-Z0-9_$.,()\[\]'"/\s*+\-%<>=?:!&|]+$/.test(expr)) {
|
|
369
|
+
throw new Error(`Native2DCompiler @computed: unsafe expr ${JSON.stringify(expr)}`);
|
|
370
|
+
}
|
|
371
|
+
const from = traits.computed.from ? String(traits.computed.from) : "";
|
|
372
|
+
if (from && /['"`\\]/.test(from)) {
|
|
373
|
+
throw new Error(`Native2DCompiler @computed: invalid import path ${JSON.stringify(from)}`);
|
|
374
|
+
}
|
|
375
|
+
const usesRaw = traits.computed.uses;
|
|
376
|
+
const uses = (Array.isArray(usesRaw) ? usesRaw : usesRaw ? [usesRaw] : []).map(String).filter((u) => /^[A-Za-z_$][\w$]*$/.test(u));
|
|
377
|
+
if (!this._computedBindings.some((b) => b.name === cname)) {
|
|
378
|
+
this._computedBindings.push({ name: cname, expr, from: from || void 0, uses });
|
|
277
379
|
}
|
|
278
380
|
}
|
|
279
381
|
let tag = traits.theme?.tag || traits.panel?.tag || (typeof obj.type === "string" ? obj.type.toLowerCase() : void 0) || "div";
|
|
@@ -307,6 +409,10 @@ export default ${safeName}Component;
|
|
|
307
409
|
const styles = this.buildStyles(traits);
|
|
308
410
|
const classes = this.buildClasses(traits);
|
|
309
411
|
let props = ``;
|
|
412
|
+
const prov = this.resolveProvenance(traits, obj);
|
|
413
|
+
if (prov) props += prov.propsStr;
|
|
414
|
+
const proj = this.resolveProjection(traits, obj);
|
|
415
|
+
if (proj) props += proj;
|
|
310
416
|
if (traits.theme?.className) {
|
|
311
417
|
classes.push(traits.theme.className);
|
|
312
418
|
}
|
|
@@ -329,10 +435,15 @@ export default ${safeName}Component;
|
|
|
329
435
|
props += ` style={${JSON.stringify(combinedStyles)}}`;
|
|
330
436
|
}
|
|
331
437
|
if (tierExpr) {
|
|
332
|
-
const
|
|
438
|
+
const tierFamilies = this.tierColorFamilies(traits);
|
|
439
|
+
const cleaned = this.stripColorFamilies(
|
|
440
|
+
this.resolveColorConflicts(classes.join(" ")),
|
|
441
|
+
tierFamilies
|
|
442
|
+
);
|
|
443
|
+
const staticPrefix = cleaned ? `${cleaned} ` : "";
|
|
333
444
|
props += ` className={\`${staticPrefix}\${${tierExpr}}\`}`;
|
|
334
445
|
} else if (classes.length > 0) {
|
|
335
|
-
props += ` className="${classes.join(" ")}"`;
|
|
446
|
+
props += ` className="${this.resolveColorConflicts(classes.join(" "))}"`;
|
|
336
447
|
}
|
|
337
448
|
if (traits.theme?.attributes) {
|
|
338
449
|
try {
|
|
@@ -383,7 +494,10 @@ export default ${safeName}Component;
|
|
|
383
494
|
if (stateVar) {
|
|
384
495
|
const setter = `set${stateVar.charAt(0).toUpperCase()}${stateVar.slice(1)}`;
|
|
385
496
|
const valueExpr = subPath ? `${stateVar}.${subPath}` : stateVar;
|
|
386
|
-
|
|
497
|
+
const inputType = String(traits.input?.type || "").toLowerCase();
|
|
498
|
+
const numeric = traits.model.cast === "number" || inputType === "range" || inputType === "number";
|
|
499
|
+
const getter = numeric ? "Number(e.target.value)" : "e.target.value";
|
|
500
|
+
props += ` value={${valueExpr}} onChange={(e) => ${setter}(${getter})}`;
|
|
387
501
|
}
|
|
388
502
|
}
|
|
389
503
|
if (traits.image?.src) props += ` src="${traits.image.src}"`;
|
|
@@ -392,6 +506,9 @@ export default ${safeName}Component;
|
|
|
392
506
|
if (traits.input?.placeholder) props += ` placeholder="${traits.input.placeholder}"`;
|
|
393
507
|
if (traits.input?.type) props += ` type="${traits.input.type}"`;
|
|
394
508
|
if (traits.input?.required) props += ` required`;
|
|
509
|
+
if (traits.input?.min != null) props += ` min="${String(traits.input.min)}"`;
|
|
510
|
+
if (traits.input?.max != null) props += ` max="${String(traits.input.max)}"`;
|
|
511
|
+
if (traits.input?.step != null) props += ` step="${String(traits.input.step)}"`;
|
|
395
512
|
if (traits.button?.type) props += ` type="${traits.button.type}"`;
|
|
396
513
|
const childrenMarkup = (obj.children || obj.objects || []).map((child) => this.generateReactNode(child)).join("\n");
|
|
397
514
|
const content = traits.text?.content || traits.button?.content || traits.link?.content || traits.icon?.name;
|
|
@@ -401,12 +518,23 @@ export default ${safeName}Component;
|
|
|
401
518
|
} else if (content) {
|
|
402
519
|
safeContent = `{\`${content.replace(/`/g, "\\`").replace(/\$/g, "\\$")}\`}`;
|
|
403
520
|
}
|
|
521
|
+
if (prov && safeContent && _Native2DCompiler.PROVENANCE_GLYPH[prov.cls]) {
|
|
522
|
+
safeContent += `<sup className="holo-prov-mark" title=${JSON.stringify(
|
|
523
|
+
`provenance: ${prov.cls}`
|
|
524
|
+
)}>${_Native2DCompiler.PROVENANCE_GLYPH[prov.cls]}</sup>`;
|
|
525
|
+
}
|
|
404
526
|
const each = this.buildEachIterator(traits);
|
|
405
527
|
const keyProp = each ? ` key={i}` : "";
|
|
406
528
|
let element;
|
|
407
529
|
if (tag === "style") {
|
|
408
530
|
const escapedStyle = (content || "").replace(/`/g, "\\`").replace(/\$/g, "\\$");
|
|
409
531
|
element = `<style${keyProp} dangerouslySetInnerHTML={{ __html: \`${escapedStyle}\` }} />`;
|
|
532
|
+
} else if (traits.sparkline?.state) {
|
|
533
|
+
element = this.buildSparklineElement(traits, props, keyProp);
|
|
534
|
+
} else if (traits.chart?.state) {
|
|
535
|
+
element = this.buildChartElement(traits, props, keyProp);
|
|
536
|
+
} else if (traits.live_proof?.claim) {
|
|
537
|
+
element = this.buildLiveProofElement(traits, keyProp);
|
|
410
538
|
} else if (tag === "img" || tag === "input") {
|
|
411
539
|
element = `<${tag}${props}${keyProp} />`;
|
|
412
540
|
} else {
|
|
@@ -913,7 +1041,13 @@ export default ${safeName}Component;
|
|
|
913
1041
|
* : (snap?.fps ?? 0) >= 30 ? "text-amber-400"
|
|
914
1042
|
* : "text-red-400"
|
|
915
1043
|
*
|
|
916
|
-
* Each tier may specify `gte` (>=), `gt` (>), `lte` (<=), and/or `lt` (<)
|
|
1044
|
+
* Each tier may specify `gte` (>=), `gt` (>), `lte` (<=), and/or `lt` (<) for
|
|
1045
|
+
* numeric thresholds, OR `eq`/`neq` for exact-match categories (e.g. a
|
|
1046
|
+
* security audit outcome: `{ eq: "denied", className: "text-red-400" }`).
|
|
1047
|
+
* `eq`/`neq` accept a string or a number; string operands pass the same
|
|
1048
|
+
* injection guard as `@when eq` and are emitted via JSON.stringify. When any
|
|
1049
|
+
* tier compares strings, the bound value is coerced to `''` (not `0`) so the
|
|
1050
|
+
* cascade stays total before state loads without mis-coercing a string to 0.
|
|
917
1051
|
* Conditions on one tier are AND-ed. A tier with no bounds is the
|
|
918
1052
|
* unconditional fallback (its className is the trailing `:` branch). If no
|
|
919
1053
|
* tier is unconditional, an empty-string fallback is appended so the
|
|
@@ -927,8 +1061,11 @@ export default ${safeName}Component;
|
|
|
927
1061
|
String(bind.path || ""),
|
|
928
1062
|
"@bind tiers"
|
|
929
1063
|
);
|
|
930
|
-
const valueRef = `(${baseExpr} ?? 0)`;
|
|
931
1064
|
const tiers = bind.tiers;
|
|
1065
|
+
const usesStringCompare = tiers.some(
|
|
1066
|
+
(t) => typeof t.eq === "string" || typeof t.neq === "string"
|
|
1067
|
+
);
|
|
1068
|
+
const valueRef = usesStringCompare ? `(${baseExpr} ?? '')` : `(${baseExpr} ?? 0)`;
|
|
932
1069
|
const branches = [];
|
|
933
1070
|
for (const tier of tiers) {
|
|
934
1071
|
const className = typeof tier.className === "string" ? tier.className : "";
|
|
@@ -937,6 +1074,16 @@ export default ${safeName}Component;
|
|
|
937
1074
|
if (typeof tier.gt === "number") conditions.push(`${valueRef} > ${tier.gt}`);
|
|
938
1075
|
if (typeof tier.lte === "number") conditions.push(`${valueRef} <= ${tier.lte}`);
|
|
939
1076
|
if (typeof tier.lt === "number") conditions.push(`${valueRef} < ${tier.lt}`);
|
|
1077
|
+
if (typeof tier.eq === "number") conditions.push(`${valueRef} === ${tier.eq}`);
|
|
1078
|
+
else if (typeof tier.eq === "string")
|
|
1079
|
+
conditions.push(
|
|
1080
|
+
`${valueRef} === ${JSON.stringify(this.assertSafeLiteral(tier.eq, "@bind tier eq"))}`
|
|
1081
|
+
);
|
|
1082
|
+
if (typeof tier.neq === "number") conditions.push(`${valueRef} !== ${tier.neq}`);
|
|
1083
|
+
else if (typeof tier.neq === "string")
|
|
1084
|
+
conditions.push(
|
|
1085
|
+
`${valueRef} !== ${JSON.stringify(this.assertSafeLiteral(tier.neq, "@bind tier neq"))}`
|
|
1086
|
+
);
|
|
940
1087
|
branches.push({
|
|
941
1088
|
condition: conditions.length > 0 ? conditions.join(" && ") : null,
|
|
942
1089
|
className
|
|
@@ -959,6 +1106,309 @@ export default ${safeName}Component;
|
|
|
959
1106
|
fallback
|
|
960
1107
|
);
|
|
961
1108
|
}
|
|
1109
|
+
/**
|
|
1110
|
+
* @sparkline: render a bound numeric array as an inline SVG polyline — the
|
|
1111
|
+
* smallest slice of native data-viz (no axes/legend). The points are computed
|
|
1112
|
+
* at render time from the array, normalized into a fixed viewBox
|
|
1113
|
+
* (`width`×`height`, default 100×30) with `preserveAspectRatio="none"` so the
|
|
1114
|
+
* SVG fills its CSS box. `state`(+optional `path`) is the array; `valueKey`
|
|
1115
|
+
* reads a number out of object items (e.g. items `{sizeKb}` → valueKey
|
|
1116
|
+
* "sizeKb"); `stroke` is a themeable line-color class (default
|
|
1117
|
+
* `stroke-studio-accent`). Container styling (`@theme`/`@layout`) rides in on
|
|
1118
|
+
* `props`. Dependency-free, injection-safe: identifiers are validated and the
|
|
1119
|
+
* points expression uses string concatenation (no inner template literals).
|
|
1120
|
+
*/
|
|
1121
|
+
buildSparklineElement(traits, props, keyProp) {
|
|
1122
|
+
const sp = traits.sparkline;
|
|
1123
|
+
const state = this.assertSafeDotPath(String(sp.state), "@sparkline state");
|
|
1124
|
+
const path = sp.path ? String(sp.path) : "";
|
|
1125
|
+
if (path) this.assertSafeDotPath(path, "@sparkline path");
|
|
1126
|
+
const arrayRef = this.buildStatePathExpr(state, path, "@sparkline");
|
|
1127
|
+
const W = Number.isInteger(sp.width) && sp.width > 0 ? sp.width : 100;
|
|
1128
|
+
const H = Number.isInteger(sp.height) && sp.height > 0 ? sp.height : 30;
|
|
1129
|
+
let valueExpr = "d";
|
|
1130
|
+
if (sp.valueKey != null) {
|
|
1131
|
+
const vk = String(sp.valueKey);
|
|
1132
|
+
if (!/^[A-Za-z_$][\w$]*$/.test(vk)) {
|
|
1133
|
+
throw new Error(`Native2DCompiler @sparkline: invalid valueKey ${JSON.stringify(vk)}`);
|
|
1134
|
+
}
|
|
1135
|
+
valueExpr = `d?.${vk}`;
|
|
1136
|
+
}
|
|
1137
|
+
const stroke = typeof sp.stroke === "string" ? this.assertSafeLiteral(sp.stroke, "@sparkline stroke") : "stroke-studio-accent";
|
|
1138
|
+
const strokeWidth = /^[0-9]+(\.[0-9]+)?$/.test(String(sp.strokeWidth ?? "")) ? String(sp.strokeWidth) : "1.5";
|
|
1139
|
+
const points = `((__a) => { const __v = (__a ?? []).map((d) => Number(${valueExpr}) || 0); if (!__v.length) return ''; const __mn = Math.min(...__v), __mx = Math.max(...__v), __r = (__mx - __mn) || 1, __sx = __v.length > 1 ? ${W} / (__v.length - 1) : 0; return __v.map((y, i) => (i * __sx).toFixed(2) + ',' + (${H} - ((y - __mn) / __r) * ${H}).toFixed(2)).join(' '); })(${arrayRef})`;
|
|
1140
|
+
return `<svg${props}${keyProp} data-baseline="min" viewBox="0 0 ${W} ${H}" preserveAspectRatio="none">
|
|
1141
|
+
<polyline fill="none" className="${stroke}" strokeWidth="${strokeWidth}" points={${points}} />
|
|
1142
|
+
</svg>`;
|
|
1143
|
+
}
|
|
1144
|
+
/**
|
|
1145
|
+
* @chart: the fuller native data-viz primitive — a bar / line / area chart with
|
|
1146
|
+
* a baseline axis and (bar) crisp category labels. Unlike @sparkline (fill-the-box,
|
|
1147
|
+
* no axes), @chart uses a fixed-aspect viewBox with margins so `<text>` labels stay
|
|
1148
|
+
* undistorted. Geometry is computed at render time from the bound array; a bar chart
|
|
1149
|
+
* emits one `<rect>` per item, line/area emit a `<polyline>`/`<polygon>` over the
|
|
1150
|
+
* plot region. Injection-safe: `state`/`path`/`valueKey`/`labelKey` are validated
|
|
1151
|
+
* identifiers/dot-paths, `stroke`/`fill` pass the literal guard, and the point math
|
|
1152
|
+
* uses string concatenation (no inner template literals).
|
|
1153
|
+
*
|
|
1154
|
+
* `@chart { kind: "bar"|"line"|"area", state, path?, valueKey?, labelKey?,
|
|
1155
|
+
* width?, height?, stroke?, fill? }`
|
|
1156
|
+
*/
|
|
1157
|
+
buildChartElement(traits, props, keyProp) {
|
|
1158
|
+
const ch = traits.chart;
|
|
1159
|
+
const kind = ch.kind === "line" || ch.kind === "area" ? ch.kind : "bar";
|
|
1160
|
+
const state = this.assertSafeDotPath(String(ch.state), "@chart state");
|
|
1161
|
+
const path = ch.path ? String(ch.path) : "";
|
|
1162
|
+
if (path) this.assertSafeDotPath(path, "@chart path");
|
|
1163
|
+
const arrayRef = this.buildStatePathExpr(state, path, "@chart");
|
|
1164
|
+
let valueExpr = "d";
|
|
1165
|
+
if (ch.valueKey != null) {
|
|
1166
|
+
const vk = String(ch.valueKey);
|
|
1167
|
+
if (!/^[A-Za-z_$][\w$]*$/.test(vk)) {
|
|
1168
|
+
throw new Error(`Native2DCompiler @chart: invalid valueKey ${JSON.stringify(vk)}`);
|
|
1169
|
+
}
|
|
1170
|
+
valueExpr = `d?.${vk}`;
|
|
1171
|
+
}
|
|
1172
|
+
let labelKey = "";
|
|
1173
|
+
if (ch.labelKey != null) {
|
|
1174
|
+
labelKey = String(ch.labelKey);
|
|
1175
|
+
if (!/^[A-Za-z_$][\w$]*$/.test(labelKey)) {
|
|
1176
|
+
throw new Error(`Native2DCompiler @chart: invalid labelKey ${JSON.stringify(labelKey)}`);
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
1179
|
+
let classKey = "";
|
|
1180
|
+
if (ch.classKey != null) {
|
|
1181
|
+
classKey = String(ch.classKey);
|
|
1182
|
+
if (!/^[A-Za-z_$][\w$]*$/.test(classKey)) {
|
|
1183
|
+
throw new Error(`Native2DCompiler @chart: invalid classKey ${JSON.stringify(classKey)}`);
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1186
|
+
const W = Number.isInteger(ch.width) && ch.width > 0 ? ch.width : 280;
|
|
1187
|
+
const H = Number.isInteger(ch.height) && ch.height > 0 ? ch.height : 140;
|
|
1188
|
+
const stroke = typeof ch.stroke === "string" ? this.assertSafeLiteral(ch.stroke, "@chart stroke") : "stroke-studio-accent";
|
|
1189
|
+
const fill = typeof ch.fill === "string" ? this.assertSafeLiteral(ch.fill, "@chart fill") : "fill-studio-accent";
|
|
1190
|
+
const PX = 6;
|
|
1191
|
+
const PT = 8;
|
|
1192
|
+
const PB = labelKey && kind === "bar" ? 16 : 6;
|
|
1193
|
+
const plotW = W - 2 * PX;
|
|
1194
|
+
const plotH = H - PT - PB;
|
|
1195
|
+
const baselineY = H - PB;
|
|
1196
|
+
const baseline = `<line x1="${PX}" y1="${baselineY}" x2="${W - PX}" y2="${baselineY}" className="stroke-studio-border" strokeWidth="0.5" />`;
|
|
1197
|
+
const provDefs = classKey ? `<defs><pattern id="holo-hatch" width="4" height="4" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="4" className="stroke-studio-accent" strokeWidth="1.2" /></pattern><pattern id="holo-dots" width="3" height="3" patternUnits="userSpaceOnUse"><circle cx="1.5" cy="1.5" r="0.6" className="fill-studio-accent" /></pattern></defs>` : "";
|
|
1198
|
+
let body;
|
|
1199
|
+
if (kind === "bar") {
|
|
1200
|
+
const label = labelKey ? `<text x={__x + __bw / 2} y={${H - 4}} textAnchor="middle" className="fill-studio-muted" fontSize="6">{String(d?.${labelKey} ?? '')}</text>` : "";
|
|
1201
|
+
const provFill = classKey ? ` fill={d?.${classKey} === "inferred" ? "url(#holo-hatch)" : d?.${classKey} === "generative" ? "url(#holo-dots)" : undefined} data-provenance-class={String(d?.${classKey} ?? "")}` : "";
|
|
1202
|
+
body = `{((__a) => { const __d = (__a ?? []); const __v = __d.map((d) => Number(${valueExpr}) || 0); const __max = Math.max(1, ...__v); const __n = __d.length || 1; const __slot = ${plotW} / __n; const __bw = Math.max(1, Math.min(__slot * 0.62, __slot - 1)); return __d.map((d, i) => { const __h = Math.max(0, Number(${valueExpr}) || 0) / __max * ${plotH}; const __x = ${PX} + i * __slot + (__slot - __bw) / 2; const __y = ${baselineY} - __h; return (<g key={i}><rect x={__x} y={__y} width={__bw} height={__h} className="${fill}"${provFill} rx="0.5" />${label}</g>); }); })(${arrayRef})}`;
|
|
1203
|
+
} else {
|
|
1204
|
+
const norm = this._honestMode ? `const __mn = 0, __r = Math.max(1, ...__v), ` : `const __mn = Math.min(...__v), __mx = Math.max(...__v), __r = (__mx - __mn) || 1, `;
|
|
1205
|
+
const yExpr = this._honestMode ? "Math.max(0, y)" : "y";
|
|
1206
|
+
const pts = `((__a) => { const __v = (__a ?? []).map((d) => Number(${valueExpr}) || 0); if (!__v.length) return ''; ` + norm + `__sx = __v.length > 1 ? ${plotW} / (__v.length - 1) : 0; return __v.map((y, i) => (${PX} + i * __sx).toFixed(2) + ',' + (${baselineY} - ((${yExpr} - __mn) / __r) * ${plotH}).toFixed(2)).join(' '); })(${arrayRef})`;
|
|
1207
|
+
const line = `<polyline fill="none" className="${stroke}" strokeWidth="1.5" points={${pts}} />`;
|
|
1208
|
+
if (kind === "area") {
|
|
1209
|
+
const areaPts = `((__p) => __p ? __p + ' ' + ${W - PX} + ',' + ${baselineY} + ' ' + ${PX} + ',' + ${baselineY} : '')(${pts})`;
|
|
1210
|
+
body = `<polygon className="${fill}" fillOpacity="0.25" points={${areaPts}} />
|
|
1211
|
+
${line}`;
|
|
1212
|
+
} else {
|
|
1213
|
+
body = line;
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
const baselineAttr = ` data-baseline="${kind === "bar" || this._honestMode ? "zero" : "min"}"`;
|
|
1217
|
+
const clampedAttr = kind === "bar" || this._honestMode ? ` data-clamped={String(((__a) => (__a ?? []).some((d) => (Number(${valueExpr}) || 0) < 0))(${arrayRef}))}` : "";
|
|
1218
|
+
return `<svg${props}${keyProp}${baselineAttr}${clampedAttr} viewBox="0 0 ${W} ${H}">
|
|
1219
|
+
${provDefs}
|
|
1220
|
+
${baseline}
|
|
1221
|
+
${body}
|
|
1222
|
+
</svg>`;
|
|
1223
|
+
}
|
|
1224
|
+
/**
|
|
1225
|
+
* Receipt-Bound Surface enforcement + emission (@honest / @provenance_bound).
|
|
1226
|
+
*
|
|
1227
|
+
* A "data-bound" element (one that renders a value from state via @bind/@chart/
|
|
1228
|
+
* @sparkline/@model) must, in honest mode, carry `@provenance_bound {source, class}`
|
|
1229
|
+
* — otherwise the compiler THROWS (HONEST-UNSOURCED): the surface cannot emit an
|
|
1230
|
+
* unsourced pixel. When provenance IS present, this returns the inline receipt
|
|
1231
|
+
* attributes (`data-holo-provenance` = a machine-readable {source,class,confidence}
|
|
1232
|
+
* an independent consumer can re-derive against, `data-provenance-class`) plus the
|
|
1233
|
+
* class so the caller can add a visible honesty glyph to text values. An unknown
|
|
1234
|
+
* class is rejected (fail toward lower trust — never silently upgraded to measured).
|
|
1235
|
+
* Returns null when the element is not provenance-bound (no attributes, no glyph).
|
|
1236
|
+
*/
|
|
1237
|
+
/**
|
|
1238
|
+
* @verified_view / @projects — the admission gate for agent-authored
|
|
1239
|
+
* surfaces (slice 4 of the Receipt-Bound Surface, honest v0).
|
|
1240
|
+
*
|
|
1241
|
+
* `@projects { node: "stats.sessions" }` is the AUTHOR'S CLAIM of which
|
|
1242
|
+
* world-model node an element renders. This compiler owns the actual data
|
|
1243
|
+
* path (@bind/@chart/@sparkline/@model → state[.path]), so the claim is
|
|
1244
|
+
* verified as compiler-owned DATA-FLOW — the two sides are independently
|
|
1245
|
+
* authored, which is exactly what the shallow "source is non-empty" version
|
|
1246
|
+
* (rejected as theater in the slice-4 warning) lacks. Checks, all fatal
|
|
1247
|
+
* (VIEW-UNGROUNDED):
|
|
1248
|
+
* 1. a declared projection must MATCH the element's actual bound path —
|
|
1249
|
+
* "the agent says sessions but wired revenue" fails to compile;
|
|
1250
|
+
* 2. a projection must root in a REAL node (composition state or a @fetch
|
|
1251
|
+
* into-slot) — a hallucinated node fails to compile;
|
|
1252
|
+
* 3. a projection on an element with NO data binding is a lie by
|
|
1253
|
+
* construction — fails to compile;
|
|
1254
|
+
* 4. under composition-level `@verified_view`, every data-bound element
|
|
1255
|
+
* MUST declare a projection (mirrors HONEST-UNSOURCED).
|
|
1256
|
+
* Checks 1–3 are always-on (a lying receipt is worse than none); check 4 is
|
|
1257
|
+
* the mode. Verified elements emit `data-holo-projects` so independent
|
|
1258
|
+
* consumers can re-check the claim against the artifact. HONEST SCOPE:
|
|
1259
|
+
* runtime re-derivation against a live graph.holo world model (the full
|
|
1260
|
+
* research-spec `projects:` semantics + SimulationContract co-emission) is
|
|
1261
|
+
* v1+ — this v0 proves what the compiler can prove, statically.
|
|
1262
|
+
*/
|
|
1263
|
+
resolveProjection(traits, obj) {
|
|
1264
|
+
const nm = () => String(obj.name ?? "element");
|
|
1265
|
+
const src = traits.bind?.state ? { state: traits.bind.state, path: traits.bind.path } : traits.chart?.state ? { state: traits.chart.state, path: traits.chart.path } : traits.sparkline?.state ? { state: traits.sparkline.state, path: traits.sparkline.path } : traits.model?.state ? { state: traits.model.state, path: traits.model.path } : (
|
|
1266
|
+
// @each renders a LIST from state — the element's provenance is the bound array.
|
|
1267
|
+
traits.each?.state ? { state: traits.each.state, path: traits.each.path } : null
|
|
1268
|
+
);
|
|
1269
|
+
const actualPath = src ? `${String(src.state)}${src.path ? "." + String(src.path) : ""}` : null;
|
|
1270
|
+
const pj = traits.projects;
|
|
1271
|
+
if (!pj) {
|
|
1272
|
+
if (this._verifiedViewMode && actualPath) {
|
|
1273
|
+
throw new Error(
|
|
1274
|
+
`Native2DCompiler @verified_view: VIEW-UNGROUNDED \u2014 "${nm()}" renders data without @projects {node}; an agent-authored surface ships only if every element declares what it renders`
|
|
1275
|
+
);
|
|
1276
|
+
}
|
|
1277
|
+
return null;
|
|
1278
|
+
}
|
|
1279
|
+
const node = this.assertSafeDotPath(String(pj.node ?? ""), "@projects node");
|
|
1280
|
+
if (!actualPath) {
|
|
1281
|
+
throw new Error(
|
|
1282
|
+
`Native2DCompiler @projects: VIEW-UNGROUNDED \u2014 "${nm()}" claims to project "${node}" but has no data binding at all; the claim is a lie by construction`
|
|
1283
|
+
);
|
|
1284
|
+
}
|
|
1285
|
+
if (node !== actualPath) {
|
|
1286
|
+
throw new Error(
|
|
1287
|
+
`Native2DCompiler @projects: VIEW-UNGROUNDED \u2014 "${nm()}" claims to project "${node}" but is actually bound to "${actualPath}"; the surface would lie about its source`
|
|
1288
|
+
);
|
|
1289
|
+
}
|
|
1290
|
+
const root = node.split(".")[0];
|
|
1291
|
+
if (!this._projectionRoots.has(root)) {
|
|
1292
|
+
throw new Error(
|
|
1293
|
+
`Native2DCompiler @projects: VIEW-UNGROUNDED \u2014 "${nm()}" projects "${node}" but no state node "${root}" exists (hallucinated node; declared state keys and @fetch slots: ${[...this._projectionRoots].join(", ") || "none"})`
|
|
1294
|
+
);
|
|
1295
|
+
}
|
|
1296
|
+
const b = traits.bind;
|
|
1297
|
+
const identity = !!b?.state && b.precision === void 0 && b.prefix === void 0 && b.suffix === void 0 && !b.tiers && !traits.chart && !traits.sparkline && !traits.each && !traits.model;
|
|
1298
|
+
let transform;
|
|
1299
|
+
if (b?.state && !traits.chart && !traits.sparkline && !traits.each && !traits.model && (b.precision !== void 0 || b.prefix !== void 0 || b.suffix !== void 0)) {
|
|
1300
|
+
transform = {};
|
|
1301
|
+
if (typeof b.precision === "number") transform.precision = b.precision;
|
|
1302
|
+
if (b.prefix !== void 0) transform.prefix = String(b.prefix);
|
|
1303
|
+
if (b.suffix !== void 0) transform.suffix = String(b.suffix);
|
|
1304
|
+
}
|
|
1305
|
+
let entity;
|
|
1306
|
+
if (pj.entity !== void 0) {
|
|
1307
|
+
const e = String(pj.entity);
|
|
1308
|
+
if (!/^[A-Za-z0-9_.:-]+$/.test(e)) {
|
|
1309
|
+
throw new Error(
|
|
1310
|
+
`Native2DCompiler @projects: invalid entity id ${JSON.stringify(e)} on "${nm()}" (allowed: alphanumerics and . : _ -)`
|
|
1311
|
+
);
|
|
1312
|
+
}
|
|
1313
|
+
entity = e;
|
|
1314
|
+
}
|
|
1315
|
+
this._collectedProjections.push({
|
|
1316
|
+
element: nm(),
|
|
1317
|
+
node,
|
|
1318
|
+
...entity ? { entity } : {},
|
|
1319
|
+
identity,
|
|
1320
|
+
...transform ? { transform } : {}
|
|
1321
|
+
});
|
|
1322
|
+
return ` data-holo-projects="${node}"`;
|
|
1323
|
+
}
|
|
1324
|
+
/**
|
|
1325
|
+
* @verified_view v1 — build the co-emitted view contract: a portable, sha256-bound JSON
|
|
1326
|
+
* receipt of every verified projection plus the valid state roots. The contract travels
|
|
1327
|
+
* WITH the compiled artifact (`export const holoViewContract` + a `data-holo-view-contract`
|
|
1328
|
+
* hash on the root), so an independent consumer re-derives the projection set from the
|
|
1329
|
+
* emitted `data-holo-projects` attributes and checks it against this contract — the two
|
|
1330
|
+
* emission paths cannot silently drift, and the surface's honesty becomes one verifiable
|
|
1331
|
+
* receipt instead of N scattered attributes (W.772). Returns null outside @verified_view
|
|
1332
|
+
* mode (un-gated surfaces carry no contract). Canonical: projections sorted by
|
|
1333
|
+
* (element, node) and roots sorted, so the hash is stable across traversal order.
|
|
1334
|
+
*
|
|
1335
|
+
* NOTE (v1 scope): this makes the projection contract portable and independently
|
|
1336
|
+
* re-checkable from the ARTIFACT — the foundation for runtime re-derivation. Verifying the
|
|
1337
|
+
* bound value against a LIVE graph.holo world model at runtime is the deeper v1 still to be
|
|
1338
|
+
* designed.
|
|
1339
|
+
*/
|
|
1340
|
+
buildViewContract() {
|
|
1341
|
+
if (!this._verifiedViewMode) return null;
|
|
1342
|
+
const projections = [...this._collectedProjections].sort(
|
|
1343
|
+
(a, b) => a.element === b.element ? a.node.localeCompare(b.node) : a.element.localeCompare(b.element)
|
|
1344
|
+
);
|
|
1345
|
+
const stateRoots = [...this._projectionRoots].sort();
|
|
1346
|
+
const body = { version: _Native2DCompiler.VIEW_CONTRACT_VERSION, projections, stateRoots };
|
|
1347
|
+
const hash = createHash("sha256").update(JSON.stringify(body)).digest("hex");
|
|
1348
|
+
return { json: JSON.stringify({ ...body, contractHash: hash }), hash };
|
|
1349
|
+
}
|
|
1350
|
+
resolveProvenance(traits, obj) {
|
|
1351
|
+
const dataBound = !!(traits.bind?.state || traits.chart?.state && !traits.chart?.classKey || traits.sparkline?.state || traits.model);
|
|
1352
|
+
const pb = traits.provenance_bound;
|
|
1353
|
+
if (this._honestMode && dataBound && !pb) {
|
|
1354
|
+
const nm = String(obj.name ?? "element");
|
|
1355
|
+
throw new Error(
|
|
1356
|
+
`Native2DCompiler @honest: HONEST-UNSOURCED \u2014 "${nm}" renders data without @provenance_bound {source, class}; the surface cannot emit an unsourced pixel`
|
|
1357
|
+
);
|
|
1358
|
+
}
|
|
1359
|
+
if (!pb) return null;
|
|
1360
|
+
const cls = String(pb.class ?? "");
|
|
1361
|
+
if (!_Native2DCompiler.PROVENANCE_CLASSES.has(cls)) {
|
|
1362
|
+
throw new Error(
|
|
1363
|
+
`Native2DCompiler @provenance_bound: invalid class ${JSON.stringify(cls)} \u2014 expected measured|derived|inferred|generative (unknown classes fail toward lower trust, never default to measured)`
|
|
1364
|
+
);
|
|
1365
|
+
}
|
|
1366
|
+
const source = this.assertSafeLiteral(String(pb.source ?? ""), "@provenance_bound source");
|
|
1367
|
+
const receipt = { source, class: cls };
|
|
1368
|
+
if (pb.confidence != null) {
|
|
1369
|
+
const c = Number(pb.confidence);
|
|
1370
|
+
if (Number.isFinite(c) && c >= 0 && c <= 1) receipt.confidence = c;
|
|
1371
|
+
}
|
|
1372
|
+
const propsStr = ` data-holo-provenance='${JSON.stringify(receipt)}' data-provenance-class="${cls}"`;
|
|
1373
|
+
return { propsStr, cls };
|
|
1374
|
+
}
|
|
1375
|
+
/**
|
|
1376
|
+
* @live_proof: the falsifiable surface — the receipt is load-bearing RENDER STATE.
|
|
1377
|
+
*
|
|
1378
|
+
* `@live_proof { claim, label? }` declares a boolean claim over state (a theorem the
|
|
1379
|
+
* element asserts). It compiles to a self-styled verdict badge whose colour + text
|
|
1380
|
+
* FLIP live as the claim breaks: `✓ <label> holds` (green) vs `✗ <label> FALSIFIED`
|
|
1381
|
+
* (red). Because the claim re-evaluates on every render, dragging a bound parameter
|
|
1382
|
+
* (via a sibling @model slider) past the point where the theorem fails flips the
|
|
1383
|
+
* badge in-band — FALSIFIED is a render state, not a console log.
|
|
1384
|
+
*
|
|
1385
|
+
* DISCIPLINE (W.767/W.769): the claim must re-derive from INDEPENDENT state fields
|
|
1386
|
+
* (e.g. `capacity >= load * factor`), never re-read the displayed value — a
|
|
1387
|
+
* self-referential claim proves nothing. The compiler cannot enforce independence,
|
|
1388
|
+
* but the emitted `data-proof-claim` makes the predicate auditable. The claim is
|
|
1389
|
+
* injection-safe (same char-class as @computed; no backticks/semicolons).
|
|
1390
|
+
*
|
|
1391
|
+
* HONESTY LABEL (@verified_view v1 groundwork): the emitted `data-proof-state` re-runs the
|
|
1392
|
+
* SAME `cond` the badge renders from, so today it proves DISPLAY-FAITHFULNESS (the badge
|
|
1393
|
+
* matches its own formula), NOT independently-verified TRUTH of the claim. We refuse to let
|
|
1394
|
+
* that masquerade — `data-proof-independence="self-referential"` marks it so no consumer (or
|
|
1395
|
+
* the moat's own claims) mistakes it for a real proof. A v1 runtime verifier that re-derives
|
|
1396
|
+
* the claim's inputs through a path the render did not author (an external state store or a
|
|
1397
|
+
* solver/StateAuthority oracle) flips this to `"verified"`. Until that oracle exists, honest
|
|
1398
|
+
* labeling is the only non-theatre option (see research/2026-07-10_verified-view-v1-design.md).
|
|
1399
|
+
*/
|
|
1400
|
+
buildLiveProofElement(traits, keyProp) {
|
|
1401
|
+
const lp = traits.live_proof;
|
|
1402
|
+
const claim = String(lp.claim ?? "");
|
|
1403
|
+
if (!claim.trim() || !/^[a-zA-Z0-9_$.,()\[\]'"/\s*+\-%<>=?:!&|]+$/.test(claim)) {
|
|
1404
|
+
throw new Error(`Native2DCompiler @live_proof: unsafe or empty claim ${JSON.stringify(claim)}`);
|
|
1405
|
+
}
|
|
1406
|
+
const label = lp.label != null ? this.assertSafeLiteral(String(lp.label), "@live_proof label") : "Claim";
|
|
1407
|
+
const cond = `(${claim})`;
|
|
1408
|
+
return `<div${keyProp} data-proof-claim={${JSON.stringify(claim)}} data-proof-independence="self-referential" data-proof-state={${cond} ? "pass" : "falsified"} className={\`rounded-md p-2 text-xs font-semibold \${${cond} ? "bg-studio-success/10 text-studio-success" : "bg-studio-error/10 text-studio-error"}\`}>
|
|
1409
|
+
{${cond} ? "\u2713 ${label} holds" : "\u2717 ${label} FALSIFIED"}
|
|
1410
|
+
</div>`;
|
|
1411
|
+
}
|
|
962
1412
|
buildHTMLBindAttributes(traits, staticClassName) {
|
|
963
1413
|
const bind = traits.bind;
|
|
964
1414
|
if (!bind?.state) return "";
|
|
@@ -1214,6 +1664,78 @@ export default ${safeName}Component;
|
|
|
1214
1664
|
}
|
|
1215
1665
|
return styles;
|
|
1216
1666
|
}
|
|
1667
|
+
/**
|
|
1668
|
+
* Resolve conflicting Tailwind COLOR utilities in a STATIC class string, keeping the LAST
|
|
1669
|
+
* of each color family. A node's @theme className is appended AFTER the variant defaults
|
|
1670
|
+
* (buildClasses), so this lets an authored token color win over a hardcoded default color
|
|
1671
|
+
* (e.g. @theme `text-studio-muted` overrides the caption default `text-gray-500`) — which
|
|
1672
|
+
* class actually wins otherwise depends on Tailwind's CSS emission order, not the class
|
|
1673
|
+
* attribute, so the default's raw color leaks unpredictably. Only color families are deduped
|
|
1674
|
+
* (text/bg/border/ring/…, incl. variant prefixes like hover:/focus:); sizes, spacing, and
|
|
1675
|
+
* layout are untouched, and text-<size> / border-<width> / ring-<width> are never colors.
|
|
1676
|
+
*/
|
|
1677
|
+
/**
|
|
1678
|
+
* The Tailwind COLOR family a token belongs to (incl. variant prefixes like
|
|
1679
|
+
* hover:/focus:), or null for a non-color token. Shared by conflict-resolution
|
|
1680
|
+
* and tier-family stripping. text-<size> / text-<align> / border|ring|divide-<width>
|
|
1681
|
+
* and arbitrary values ([10px], [#fff]) are NOT colors.
|
|
1682
|
+
*/
|
|
1683
|
+
colorFamilyKey(t) {
|
|
1684
|
+
const m = t.match(
|
|
1685
|
+
/^((?:[a-z-]+:)*)(text|bg|border|ring|ring-offset|divide|accent|fill|stroke|placeholder|caret|decoration|from|to|via)-(.+)$/
|
|
1686
|
+
);
|
|
1687
|
+
if (!m) return null;
|
|
1688
|
+
const [, variant, prop, rest] = m;
|
|
1689
|
+
if (rest.startsWith("[")) return null;
|
|
1690
|
+
if (prop === "text") {
|
|
1691
|
+
if (_Native2DCompiler.TEXT_SIZE_TOKENS.has(`text-${rest}`)) return null;
|
|
1692
|
+
if (["left", "center", "right", "justify", "start", "end"].includes(rest)) return null;
|
|
1693
|
+
}
|
|
1694
|
+
if (prop === "border" || prop === "divide") {
|
|
1695
|
+
if (/^([xytrbles]|\d+|[xytrbles]-\d+)$/.test(rest)) return null;
|
|
1696
|
+
}
|
|
1697
|
+
if (prop === "ring" && /^(\d+|inset)$/.test(rest)) return null;
|
|
1698
|
+
return `${variant}${prop}`;
|
|
1699
|
+
}
|
|
1700
|
+
resolveColorConflicts(classStr) {
|
|
1701
|
+
const tokens = classStr.split(/\s+/).filter(Boolean);
|
|
1702
|
+
const lastIndex = /* @__PURE__ */ new Map();
|
|
1703
|
+
tokens.forEach((t, i) => {
|
|
1704
|
+
const k = this.colorFamilyKey(t);
|
|
1705
|
+
if (k) lastIndex.set(k, i);
|
|
1706
|
+
});
|
|
1707
|
+
return tokens.filter((t, i) => {
|
|
1708
|
+
const k = this.colorFamilyKey(t);
|
|
1709
|
+
return k === null || lastIndex.get(k) === i;
|
|
1710
|
+
}).join(" ");
|
|
1711
|
+
}
|
|
1712
|
+
/**
|
|
1713
|
+
* The set of color families a @bind's tier classNames assign — so the caller
|
|
1714
|
+
* can strip those families from the static prefix (the dynamic tier cascade
|
|
1715
|
+
* owns them, and the static default would otherwise leak a raw color).
|
|
1716
|
+
*/
|
|
1717
|
+
tierColorFamilies(traits) {
|
|
1718
|
+
const families = /* @__PURE__ */ new Set();
|
|
1719
|
+
const tiers = traits?.bind?.tiers;
|
|
1720
|
+
if (!Array.isArray(tiers)) return families;
|
|
1721
|
+
for (const tier of tiers) {
|
|
1722
|
+
const cn = typeof tier?.className === "string" ? tier.className : "";
|
|
1723
|
+
for (const tok of cn.split(/\s+/).filter(Boolean)) {
|
|
1724
|
+
const k = this.colorFamilyKey(tok);
|
|
1725
|
+
if (k) families.add(k);
|
|
1726
|
+
}
|
|
1727
|
+
}
|
|
1728
|
+
return families;
|
|
1729
|
+
}
|
|
1730
|
+
/** Drop every token whose color family is in `families` (removes a static
|
|
1731
|
+
* default color that a dynamic @bind tier cascade will always override). */
|
|
1732
|
+
stripColorFamilies(classStr, families) {
|
|
1733
|
+
if (families.size === 0) return classStr;
|
|
1734
|
+
return classStr.split(/\s+/).filter(Boolean).filter((t) => {
|
|
1735
|
+
const k = this.colorFamilyKey(t);
|
|
1736
|
+
return k === null || !families.has(k);
|
|
1737
|
+
}).join(" ");
|
|
1738
|
+
}
|
|
1217
1739
|
buildClasses(traits) {
|
|
1218
1740
|
const classes = [];
|
|
1219
1741
|
if (traits.text) {
|
|
@@ -1256,6 +1778,48 @@ export default ${safeName}Component;
|
|
|
1256
1778
|
return str.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
|
|
1257
1779
|
}
|
|
1258
1780
|
};
|
|
1781
|
+
/** Version tag for the co-emitted `holoViewContract` (@verified_view v1). */
|
|
1782
|
+
_Native2DCompiler.VIEW_CONTRACT_VERSION = "holo-view-contract-v1";
|
|
1783
|
+
/**
|
|
1784
|
+
* 2D data-value provenance vocabulary, ordered by TRUST (highest → lowest),
|
|
1785
|
+
* aligned to the shipped 3D PointProvenanceClass idiom (observed | interpolated |
|
|
1786
|
+
* nlos-inferred | generative-extended). An UNKNOWN class is REJECTED, never
|
|
1787
|
+
* silently upgraded to `measured` — provenance fails toward lower trust, so a
|
|
1788
|
+
* typo can never make an inferred value read as sensor-attested.
|
|
1789
|
+
*/
|
|
1790
|
+
_Native2DCompiler.PROVENANCE_CLASSES = /* @__PURE__ */ new Set([
|
|
1791
|
+
"measured",
|
|
1792
|
+
// source-attested: a real sensor reading, DB value, on-chain fact
|
|
1793
|
+
"derived",
|
|
1794
|
+
// computed from measured values by a transparent bounded function
|
|
1795
|
+
"inferred",
|
|
1796
|
+
// model/heuristic estimate (a forecast) — honest that it is a guess
|
|
1797
|
+
"generative"
|
|
1798
|
+
// produced by a generative model (LLM-authored value)
|
|
1799
|
+
]);
|
|
1800
|
+
/** Visible honesty glyph appended to a non-`measured` text value (measured = trusted, no marker). */
|
|
1801
|
+
_Native2DCompiler.PROVENANCE_GLYPH = {
|
|
1802
|
+
measured: "",
|
|
1803
|
+
derived: "\xB0",
|
|
1804
|
+
inferred: "~",
|
|
1805
|
+
generative: "\u2726"
|
|
1806
|
+
};
|
|
1807
|
+
_Native2DCompiler.TEXT_SIZE_TOKENS = /* @__PURE__ */ new Set([
|
|
1808
|
+
"text-xs",
|
|
1809
|
+
"text-sm",
|
|
1810
|
+
"text-base",
|
|
1811
|
+
"text-lg",
|
|
1812
|
+
"text-xl",
|
|
1813
|
+
"text-2xl",
|
|
1814
|
+
"text-3xl",
|
|
1815
|
+
"text-4xl",
|
|
1816
|
+
"text-5xl",
|
|
1817
|
+
"text-6xl",
|
|
1818
|
+
"text-7xl",
|
|
1819
|
+
"text-8xl",
|
|
1820
|
+
"text-9xl"
|
|
1821
|
+
]);
|
|
1822
|
+
var Native2DCompiler = _Native2DCompiler;
|
|
1259
1823
|
|
|
1260
1824
|
// src/compiler/NextJSCompiler.ts
|
|
1261
1825
|
function findTrait(composition, traitName2) {
|
|
@@ -3285,8 +3849,8 @@ async function sha256Hex(input) {
|
|
|
3285
3849
|
const digest = await subtle.digest("SHA-256", new TextEncoder().encode(input));
|
|
3286
3850
|
return bytesToHex(new Uint8Array(digest));
|
|
3287
3851
|
}
|
|
3288
|
-
const { createHash } = await import('crypto');
|
|
3289
|
-
return
|
|
3852
|
+
const { createHash: createHash2 } = await import('crypto');
|
|
3853
|
+
return createHash2("sha256").update(input).digest("hex");
|
|
3290
3854
|
}
|
|
3291
3855
|
function bytesToHex(bytes) {
|
|
3292
3856
|
return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
@@ -4099,6 +4663,18 @@ platformPluginRegistry.register(new AndroidARCorePlugin());
|
|
|
4099
4663
|
var SOVEREIGN_TARGETS = [
|
|
4100
4664
|
"webgpu",
|
|
4101
4665
|
// WebGPUCompiler → WGSL compute+render shaders on our own WebGPU device (WebGPURenderer)
|
|
4666
|
+
"audio",
|
|
4667
|
+
// SpatialAudioCompiler → our own Web Audio graph (HRTF PannerNode + Convolver reverb + filters); no third-party audio engine
|
|
4668
|
+
"desktop-gpu",
|
|
4669
|
+
// DesktopGPUCompiler → standalone Rust wgpu project (Vulkan/Metal/DX12), renders the scene offscreen on the machine's own GPU; no browser, no third-party engine. Verified on Jetson Orin/Vulkan.
|
|
4670
|
+
"pathtrace",
|
|
4671
|
+
// PathTracerCompiler → standalone Rust wgpu COMPUTE path tracer (cosine-weighted GI, emissive area lights, multi-sample) → tonemapped PNG; our own tracer, no Cycles/OptiX. Verified on Jetson Orin/Vulkan.
|
|
4672
|
+
"pathtrace-cpu",
|
|
4673
|
+
// CpuPathTracer → the no-GPU fallback: pure-TS CPU path tracer (same algorithm + shared scene extraction) → PNG. Runs offline GI anywhere Node/JS runs (server/CI/old device). The "runs anywhere / no-WebGPU compute fallback" gap.
|
|
4674
|
+
"media",
|
|
4675
|
+
// MediaPipelineCompiler → renders an animated turntable of the scene (CPU) and encodes it to an APNG with our OWN encoder (node:zlib only, no ffmpeg/codec/muxer). The video/media-pipeline gap; a moving picture from a .holo.
|
|
4676
|
+
"physics-sim",
|
|
4677
|
+
// ComputePhysicsCompiler → WGSL COMPUTE rigid-body solver (gravity + sphere/sphere + sphere/AABB collisions, restitution, double-buffered) that steps on the GPU + renders the settled state. Our own solver, no third-party physics engine. Consumes the collider vocabulary; the DYNAMICS layer on top of PhysicsColliderCompiler. Verified on Jetson Orin/Vulkan.
|
|
4102
4678
|
"character-webgpu",
|
|
4103
4679
|
// CharacterWebGPUCompiler → authored .holo character → CharacterDrawSpec run by our renderCharacter (sovereign skinned-character path)
|
|
4104
4680
|
"nir",
|
|
@@ -4320,6 +4896,66 @@ var SOVEREIGN_ENGINES = [
|
|
|
4320
4896
|
tests: true,
|
|
4321
4897
|
promoted: false,
|
|
4322
4898
|
note: "Signed-distance-field \u2192 raymarch WGSL/GLSL. Native GPU renderer codegen."
|
|
4899
|
+
},
|
|
4900
|
+
{
|
|
4901
|
+
id: "spatial-audio",
|
|
4902
|
+
name: "SpatialAudioCompiler",
|
|
4903
|
+
file: "packages/core/src/compiler/SpatialAudioCompiler.ts",
|
|
4904
|
+
kind: "compiler",
|
|
4905
|
+
maturity: "real",
|
|
4906
|
+
tests: true,
|
|
4907
|
+
promoted: false,
|
|
4908
|
+
note: "The audio peer of WebGPU: emits our OWN Web Audio graph (HRTF PannerNode + Convolver reverb from synthesized rt60 impulses + directivity/occlusion/portal filters) from @audio_source/@audio_listener/@reverb_zone/@audio_material/@audio_occlusion/@audio_portal traits. Sovereign \u2014 no FMOD/Wwise/Resonance. Fills the #1 spatial-computing gap (no audio compiler existed)."
|
|
4909
|
+
},
|
|
4910
|
+
{
|
|
4911
|
+
id: "desktop-gpu",
|
|
4912
|
+
name: "DesktopGPUCompiler",
|
|
4913
|
+
file: "packages/core/src/compiler/DesktopGPUCompiler.ts",
|
|
4914
|
+
kind: "compiler",
|
|
4915
|
+
maturity: "real",
|
|
4916
|
+
tests: true,
|
|
4917
|
+
promoted: false,
|
|
4918
|
+
note: `Sovereign native-desktop GPU: emits a self-contained Rust wgpu project (Vulkan/Metal/DX12) that renders the scene offscreen to a PNG on the machine's OWN GPU \u2014 standalone, no browser, no third-party engine. WebGPU is browser/runtime-bound; this is the "runs standalone at native perf" gap. Matrices computed in the compiler; geometry generators + wgpu host emitted. VERIFIED on real hardware: Jetson Orin (Tegra) via Vulkan rendered a 6-object scene offscreen to PNG (adapter=NVIDIA Tegra Orin, backend=Vulkan). Consumes the same geometry-registry + geometry-purpose vocabulary as render/physics/audio.`
|
|
4919
|
+
},
|
|
4920
|
+
{
|
|
4921
|
+
id: "path-tracer",
|
|
4922
|
+
name: "PathTracerCompiler",
|
|
4923
|
+
file: "packages/core/src/compiler/PathTracerCompiler.ts",
|
|
4924
|
+
kind: "compiler",
|
|
4925
|
+
maturity: "real",
|
|
4926
|
+
tests: true,
|
|
4927
|
+
promoted: false,
|
|
4928
|
+
note: "Sovereign OFFLINE path-traced render \u2014 the film-grade-still gap the rasterizers (WebGPU/desktop-gpu) do not fill. Emits a self-contained Rust wgpu COMPUTE program: our OWN GPU path tracer (no Cycles/OptiX) that traces cosine-weighted diffuse bounces against analytic sphere/box primitives, accumulates many samples, and tonemaps to PNG. Global illumination \u2014 soft shadows, colour bleeding, emissive area lights. VERIFIED on Jetson Orin (Tegra/Vulkan): a Cornell-box scene rendered with visible GI colour-bleed + soft shadows. Fifth consumer of the shared geometry-registry + geometry-purpose vocabulary."
|
|
4929
|
+
},
|
|
4930
|
+
{
|
|
4931
|
+
id: "cpu-path-tracer",
|
|
4932
|
+
name: "CpuPathTracer",
|
|
4933
|
+
file: "packages/core/src/compiler/CpuPathTracer.ts",
|
|
4934
|
+
kind: "runtime",
|
|
4935
|
+
maturity: "real",
|
|
4936
|
+
tests: true,
|
|
4937
|
+
promoted: false,
|
|
4938
|
+
note: 'The sovereign no-GPU FALLBACK: a pure-TypeScript CPU path tracer that RUNS (not emits) the same GI algorithm as PathTracerCompiler, sharing extractRaytraceScene so the two render the same scene. Renders offline global-illumination stills anywhere Node/JS runs \u2014 server, CI, old device, no WebGPU/GPU needed. Ships its own PNG encoder (node:zlib), zero deps. Fills the "runs anywhere / no-WebGPU compute fallback" gap the audit named (compiler-wasm is a parser, not a compute backend).'
|
|
4939
|
+
},
|
|
4940
|
+
{
|
|
4941
|
+
id: "media-pipeline",
|
|
4942
|
+
name: "MediaPipelineCompiler",
|
|
4943
|
+
file: "packages/core/src/compiler/MediaPipelineCompiler.ts",
|
|
4944
|
+
kind: "runtime",
|
|
4945
|
+
maturity: "real",
|
|
4946
|
+
tests: true,
|
|
4947
|
+
promoted: false,
|
|
4948
|
+
note: "The sovereign VIDEO / media-pipeline: renders an animated turntable of the scene (orbiting camera, fast CPU flat projector over the shared raytrace-scene extraction) and encodes the frame sequence to an APNG with our OWN encoder (acTL/fcTL/fdAT via node:zlib) \u2014 no ffmpeg / codec / muxer dependency. A moving picture from a .holo, runs anywhere Node runs. Fills the media-pipeline gap the audit named; browser-native WebCodecs H.264/WebM is the follow-on encode path."
|
|
4949
|
+
},
|
|
4950
|
+
{
|
|
4951
|
+
id: "compute-physics",
|
|
4952
|
+
name: "ComputePhysicsCompiler",
|
|
4953
|
+
file: "packages/core/src/compiler/ComputePhysicsCompiler.ts",
|
|
4954
|
+
kind: "compiler",
|
|
4955
|
+
maturity: "real",
|
|
4956
|
+
tests: true,
|
|
4957
|
+
promoted: false,
|
|
4958
|
+
note: "The sovereign GPU rigid-body SIMULATION \u2014 the dynamics layer PhysicsColliderCompiler was missing. Emits a Rust wgpu program with a WGSL COMPUTE solver: gravity + sphere/sphere + sphere/static-AABB collisions with restitution + friction, double-buffered (gather, race-free), stepped N times on the GPU; then renders the settled state to PNG. Our own solver, no third-party physics engine. One .holo drives BOTH render and sim (Grok + Claude converged design). Dynamic bodies = @rigid_body spheres; statics = scene boxes. VERIFIED on Jetson Orin (Tegra/Vulkan): spheres dropped above a floor fall, collide and settle. Hooks the physics-discovery / provenance goals."
|
|
4323
4959
|
}
|
|
4324
4960
|
];
|
|
4325
4961
|
|