@semacode/cli 2.3.1 → 3.5.0

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 (281) hide show
  1. package/README.md +265 -217
  2. package/dist/agentContextPack.js +14 -10
  3. package/dist/agentEntryPoints.d.ts +5 -0
  4. package/dist/agentEntryPoints.js +592 -568
  5. package/dist/angular-consumer-standalone.js +1 -1
  6. package/dist/bin.d.ts +6 -0
  7. package/dist/bin.js +130 -0
  8. package/dist/cliArgs.js +4 -4
  9. package/dist/cliControlError.d.ts +12 -0
  10. package/dist/cliControlError.js +47 -0
  11. package/dist/cliGrammar.d.ts +11 -0
  12. package/dist/cliGrammar.js +551 -0
  13. package/dist/cliHelp.d.ts +13 -0
  14. package/dist/cliHelp.js +19 -0
  15. package/dist/cliHelpTexto.d.ts +3 -0
  16. package/dist/cliHelpTexto.js +168 -0
  17. package/dist/cliRuntime.d.ts +2 -0
  18. package/dist/cliRuntime.js +31 -0
  19. package/dist/comandos.js +9 -22
  20. package/dist/contexto.js +5 -5
  21. package/dist/dev/index.d.ts +1 -0
  22. package/dist/dev/index.js +51 -9
  23. package/dist/discovery/catalog.js +3 -3
  24. package/dist/distribuicao/filesystemGlobal.d.ts +63 -0
  25. package/dist/distribuicao/filesystemGlobal.js +701 -0
  26. package/dist/distribuicao/index.d.ts +7 -0
  27. package/dist/distribuicao/index.js +227 -0
  28. package/dist/distribuicao/launcherGlobal.d.ts +53 -0
  29. package/dist/distribuicao/launcherGlobal.js +643 -0
  30. package/dist/distribuicao/launcherWindows.d.ts +28 -0
  31. package/dist/distribuicao/launcherWindows.js +326 -0
  32. package/dist/distribuicao/lockContextGlobal.d.ts +10 -0
  33. package/dist/distribuicao/lockContextGlobal.js +17 -0
  34. package/dist/distribuicao/lockGlobal.d.ts +6 -0
  35. package/dist/distribuicao/lockGlobal.js +520 -0
  36. package/dist/distribuicao/skillGlobal.d.ts +48 -0
  37. package/dist/distribuicao/skillGlobal.js +652 -0
  38. package/dist/distribuicao/skillIntentPolicy.d.ts +21 -0
  39. package/dist/distribuicao/skillIntentPolicy.js +115 -0
  40. package/dist/distribuicao/tipos.d.ts +50 -0
  41. package/dist/distribuicao/tipos.js +10 -0
  42. package/dist/distribuicao/versaoSemantica.d.ts +3 -0
  43. package/dist/distribuicao/versaoSemantica.js +62 -0
  44. package/dist/docs.part01.d.ts +4 -1
  45. package/dist/docs.part01.js +8 -0
  46. package/dist/docs.part02.js +9 -1
  47. package/dist/drift.part01.d.ts +33 -25
  48. package/dist/drift.part01.js +2 -1
  49. package/dist/drift.part04.d.ts +26 -5
  50. package/dist/drift.part04.js +123 -19
  51. package/dist/drift.part05.d.ts +2 -2
  52. package/dist/drift.part05.js +8 -6
  53. package/dist/drift.part06.d.ts +2 -2
  54. package/dist/drift.part06.js +113 -26
  55. package/dist/drift.part07.d.ts +11 -11
  56. package/dist/drift.part07.js +261 -265
  57. package/dist/drift.part08.d.ts +2 -2
  58. package/dist/drift.part08.js +35 -26
  59. package/dist/drift.part09.d.ts +2 -2
  60. package/dist/drift.part09.js +10 -3
  61. package/dist/drift.part11.js +261 -58
  62. package/dist/drift.part12.d.ts +1 -1
  63. package/dist/drift.part12.js +193 -21
  64. package/dist/drift.part13.d.ts +20 -39
  65. package/dist/drift.part13.js +601 -647
  66. package/dist/drift.part14.js +23 -7
  67. package/dist/driftCacheCas.d.ts +43 -0
  68. package/dist/driftCacheCas.js +351 -0
  69. package/dist/driftCacheFilesystem.d.ts +64 -0
  70. package/dist/driftCacheFilesystem.js +313 -0
  71. package/dist/driftCacheModes.d.ts +38 -0
  72. package/dist/driftCacheModes.js +147 -0
  73. package/dist/driftCacheStore.d.ts +80 -0
  74. package/dist/driftCacheStore.js +603 -0
  75. package/dist/driftCatalogo.d.ts +2 -28
  76. package/dist/driftCatalogo.js +143 -284
  77. package/dist/driftEscopo.d.ts +1 -3
  78. package/dist/driftEscopo.js +235 -151
  79. package/dist/driftEscopoReferencias.d.ts +5 -1
  80. package/dist/driftEscopoReferencias.js +375 -28
  81. package/dist/driftOrcamento.d.ts +0 -6
  82. package/dist/driftOrcamento.js +2 -1
  83. package/dist/execucoesExternas.js +19 -5
  84. package/dist/exemplosOficiais.d.ts +2 -1
  85. package/dist/exemplosOficiais.js +9 -3
  86. package/dist/geracaoCore.d.ts +1 -0
  87. package/dist/geracaoCore.js +6 -6
  88. package/dist/iaPrompts.d.ts +3 -3
  89. package/dist/iaPrompts.js +312 -313
  90. package/dist/importador.part01.d.ts +1 -1
  91. package/dist/importador.part06.d.ts +2 -0
  92. package/dist/importador.part06.js +87 -1
  93. package/dist/importador.part09.js +7 -1
  94. package/dist/index.d.ts +4 -1
  95. package/dist/index.js +6 -25
  96. package/dist/index.part01.d.ts +20 -28
  97. package/dist/index.part01.js +16 -237
  98. package/dist/index.part02.js +36 -22
  99. package/dist/index.part03.d.ts +24 -2
  100. package/dist/index.part03.js +83 -19
  101. package/dist/index.part04.d.ts +10 -2
  102. package/dist/index.part04.js +152 -123
  103. package/dist/index.part05.js +80 -78
  104. package/dist/index.part06.js +34 -17
  105. package/dist/index.part07.d.ts +8 -2
  106. package/dist/index.part07.js +153 -7
  107. package/dist/index.part08.d.ts +1 -1
  108. package/dist/index.part08.js +25 -30
  109. package/dist/initCommand.d.ts +1 -0
  110. package/dist/initCommand.js +20 -4
  111. package/dist/initTemplatesBase.js +6 -4
  112. package/dist/pipelineConteudo/command.d.ts +1 -0
  113. package/dist/pipelineConteudo/command.js +9 -2
  114. package/dist/pipelineConteudo/help.d.ts +2 -0
  115. package/dist/pipelineConteudo/help.js +33 -0
  116. package/dist/profileAuthorCommand.js +3 -7
  117. package/dist/profileCommand.js +3 -7
  118. package/dist/projetoCarregar.js +35 -17
  119. package/dist/projetoCatalogo.d.ts +1 -0
  120. package/dist/projetoCatalogo.js +64 -25
  121. package/dist/projetoConfig.js +2 -0
  122. package/dist/projetoLegado.js +18 -0
  123. package/dist/projetoOrigens.d.ts +2 -0
  124. package/dist/projetoOrigens.js +65 -9
  125. package/dist/projetoTipos.d.ts +1 -0
  126. package/dist/resultadoCli.d.ts +20 -0
  127. package/dist/resultadoCli.js +57 -0
  128. package/dist/saidaCli.d.ts +35 -0
  129. package/dist/saidaCli.js +118 -0
  130. package/dist/sistemasInterativos/acceptanceEvidence.d.ts +22 -0
  131. package/dist/sistemasInterativos/acceptanceEvidence.js +345 -0
  132. package/dist/sistemasInterativos/engineObservation.d.ts +12 -0
  133. package/dist/sistemasInterativos/engineObservation.js +438 -0
  134. package/dist/sistemasInterativos/jobOrchestration.d.ts +2 -0
  135. package/dist/sistemasInterativos/jobOrchestration.js +204 -0
  136. package/dist/sistemasInterativos/operationPrimitives.d.ts +21 -0
  137. package/dist/sistemasInterativos/operationPrimitives.js +194 -0
  138. package/dist/sistemasInterativos/operations.d.ts +4 -39
  139. package/dist/sistemasInterativos/operations.js +5 -1164
  140. package/dist/skillCommand.d.ts +5 -0
  141. package/dist/skillCommand.js +88 -0
  142. package/dist/tipos.d.ts +1 -1
  143. package/dist/typescript-http-modelos.d.ts +1 -1
  144. package/dist/typescript-http-rotas.d.ts +1 -0
  145. package/dist/typescript-http-rotas.js +93 -0
  146. package/dist/typescript-http.d.ts +1 -1
  147. package/dist/typescript-http.js +1 -1
  148. package/dist/verificacaoCache.d.ts +25 -0
  149. package/dist/verificacaoCache.js +80 -0
  150. package/docs/README.md +34 -30
  151. package/docs/ai-integration.md +25 -12
  152. package/docs/ai-onboarding.md +37 -18
  153. package/docs/ai-workflow.md +9 -7
  154. package/docs/cli.md +125 -7
  155. package/docs/commands.md +41 -20
  156. package/docs/deploy.md +21 -8
  157. package/docs/descoberta-capacidades.md +106 -106
  158. package/docs/documentation.md +49 -39
  159. package/docs/drift-cache.md +108 -0
  160. package/docs/getting-started.md +43 -18
  161. package/docs/pipeline-conteudo.md +246 -246
  162. package/docs/profiles.md +54 -54
  163. package/docs/repositories.md +19 -2
  164. package/docs/rollback.md +15 -8
  165. package/docs/security.md +25 -3
  166. package/docs/sistemas-interativos.md +379 -374
  167. package/docs/syntax.md +14 -0
  168. package/docs/testing.md +139 -40
  169. package/exemplos/express_crud.sema +139 -0
  170. package/exemplos/fastify_crud.sema +146 -0
  171. package/exemplos/pipeline-conteudo/README.md +44 -44
  172. package/exemplos/pipeline-conteudo/alvos.json +23 -23
  173. package/exemplos/pipeline-conteudo/definicao.json +136 -136
  174. package/exemplos/profile_simulation.sema +211 -211
  175. package/exemplos/sistemas-interativos/README.md +100 -100
  176. package/exemplos/sistemas-interativos/advanced/acceptance-context-evaluate-valid.json +5 -5
  177. package/exemplos/sistemas-interativos/advanced/acceptance-lock-valid.json +16 -16
  178. package/exemplos/sistemas-interativos/advanced/asset-provenance-valid.json +32 -32
  179. package/exemplos/sistemas-interativos/advanced/autonomy-repair-valid.json +93 -93
  180. package/exemplos/sistemas-interativos/advanced/control-run-definition-valid.json +78 -78
  181. package/exemplos/sistemas-interativos/advanced/control-run-valid.json +27 -27
  182. package/exemplos/sistemas-interativos/advanced/distributed-workers-valid.json +79 -79
  183. package/exemplos/sistemas-interativos/advanced/editor-state-valid.json +42 -42
  184. package/exemplos/sistemas-interativos/advanced/engine-snapshot-after-valid.json +32 -32
  185. package/exemplos/sistemas-interativos/advanced/engine-snapshot-before-valid.json +23 -23
  186. package/exemplos/sistemas-interativos/advanced/job-orchestration-valid.json +39 -39
  187. package/exemplos/sistemas-interativos/advanced/multimodal-evidence-valid.json +46 -46
  188. package/exemplos/sistemas-interativos/advanced/multiplayer-authority-valid.json +39 -39
  189. package/exemplos/sistemas-interativos/advanced/playtest-fuzz-valid.json +37 -37
  190. package/exemplos/sistemas-interativos/advanced/portability-valid.json +104 -104
  191. package/exemplos/sistemas-interativos/advanced/temporal-evidence-valid.json +27 -27
  192. package/exemplos/sistemas-interativos/advanced/temporal-valid.json +118 -118
  193. package/exemplos/sistemas-interativos/experience-ir-valid.json +459 -459
  194. package/exemplos/sistemas-interativos/game-2d.json +83 -83
  195. package/exemplos/sistemas-interativos/game-3d-human.json +81 -81
  196. package/exemplos/sistemas-interativos/game-pixel-16-bit.json +97 -97
  197. package/exemplos/sistemas-interativos/game-pixel-8-bit.json +94 -94
  198. package/exemplos/sistemas-interativos/game-xr-human.json +80 -80
  199. package/exemplos/sistemas-interativos/hybrid-2-5d.json +108 -108
  200. package/exemplos/sistemas-interativos/protocol-mutating-rollback-valid.json +75 -75
  201. package/exemplos/sistemas-interativos/protocol-read-only-valid.json +58 -58
  202. package/exemplos/sistemas-interativos/simulation-2d-controlled.json +97 -97
  203. package/exemplos/sistemas-interativos/simulation-3d-calibrated-autonomous.json +141 -141
  204. package/exemplos/sistemas-interativos/simulation-headless-autonomous-batch.json +112 -112
  205. package/exemplos/sistemas-interativos/simulation-pixel-16-bit.json +103 -103
  206. package/exemplos/sistemas-interativos/simulation-text-controlled.json +95 -95
  207. package/node_modules/@sema/gerador-cpp/package.json +1 -1
  208. package/node_modules/@sema/gerador-dotnet/package.json +1 -1
  209. package/node_modules/@sema/gerador-lua/dist/index.js +51 -51
  210. package/node_modules/@sema/gerador-php/dist/index.js +113 -113
  211. package/node_modules/@sema/nucleo/dist/ir/conversor.part01.js +37 -38
  212. package/node_modules/@sema/nucleo/dist/ir/modelos.d.ts +1 -0
  213. package/node_modules/@sema/nucleo/dist/semantico/analisador.d.ts +1 -0
  214. package/node_modules/@sema/nucleo/dist/semantico/analisador.js +1 -0
  215. package/node_modules/@sema/nucleo/dist/semantico/analisador.part01.d.ts +7 -0
  216. package/node_modules/@sema/nucleo/dist/semantico/analisador.part01.js +33 -10
  217. package/package.json +9 -4
  218. package/scripts/postinstall.mjs +148 -0
  219. package/skills/sema/SKILL.md +199 -0
  220. package/skills/sema/agents/openai.yaml +4 -0
  221. package/dist/driftCache.d.ts +0 -49
  222. package/dist/driftCache.js +0 -311
  223. package/dist/driftCacheIncremental.d.ts +0 -98
  224. package/dist/driftCacheIncremental.js +0 -596
  225. package/dist/driftCatalogoPersistente.d.ts +0 -8
  226. package/dist/driftCatalogoPersistente.js +0 -77
  227. package/node_modules/@sema/gerador-cpp/dist/index.js.map +0 -1
  228. package/node_modules/@sema/gerador-css/dist/index.js.map +0 -1
  229. package/node_modules/@sema/gerador-css/dist/index.part01.js.map +0 -1
  230. package/node_modules/@sema/gerador-css/dist/index.part02.js.map +0 -1
  231. package/node_modules/@sema/gerador-dart/dist/index.js.map +0 -1
  232. package/node_modules/@sema/gerador-dotnet/dist/index.js.map +0 -1
  233. package/node_modules/@sema/gerador-html/dist/index.js.map +0 -1
  234. package/node_modules/@sema/gerador-javascript/dist/index.js.map +0 -1
  235. package/node_modules/@sema/gerador-lua/dist/index.js.map +0 -1
  236. package/node_modules/@sema/gerador-php/dist/index.js.map +0 -1
  237. package/node_modules/@sema/gerador-python/dist/index.js.map +0 -1
  238. package/node_modules/@sema/gerador-python/dist/index.part01.js.map +0 -1
  239. package/node_modules/@sema/gerador-python/dist/index.part02.js.map +0 -1
  240. package/node_modules/@sema/gerador-typescript/dist/index.js.map +0 -1
  241. package/node_modules/@sema/gerador-typescript/dist/index.part01.js.map +0 -1
  242. package/node_modules/@sema/gerador-typescript/dist/index.part02.js.map +0 -1
  243. package/node_modules/@sema/gerador-typescript/dist/index.part03.js.map +0 -1
  244. package/node_modules/@sema/nucleo/dist/ast/tipos.js.map +0 -1
  245. package/node_modules/@sema/nucleo/dist/diagnosticos/index.js.map +0 -1
  246. package/node_modules/@sema/nucleo/dist/diagnosticos/melhorador.js.map +0 -1
  247. package/node_modules/@sema/nucleo/dist/diagnosticos/snippets.js.map +0 -1
  248. package/node_modules/@sema/nucleo/dist/formatador/index.js.map +0 -1
  249. package/node_modules/@sema/nucleo/dist/formatador/index.part01.js.map +0 -1
  250. package/node_modules/@sema/nucleo/dist/formatador/index.part02.js.map +0 -1
  251. package/node_modules/@sema/nucleo/dist/index.js.map +0 -1
  252. package/node_modules/@sema/nucleo/dist/ir/conversor.js.map +0 -1
  253. package/node_modules/@sema/nucleo/dist/ir/conversor.part01.js.map +0 -1
  254. package/node_modules/@sema/nucleo/dist/ir/conversor.part02.js.map +0 -1
  255. package/node_modules/@sema/nucleo/dist/ir/conversor.part03.js.map +0 -1
  256. package/node_modules/@sema/nucleo/dist/ir/modelos.js.map +0 -1
  257. package/node_modules/@sema/nucleo/dist/lexer/lexer.js.map +0 -1
  258. package/node_modules/@sema/nucleo/dist/lexer/tokens.js.map +0 -1
  259. package/node_modules/@sema/nucleo/dist/parser/parser.declaracoes.js.map +0 -1
  260. package/node_modules/@sema/nucleo/dist/parser/parser.js.map +0 -1
  261. package/node_modules/@sema/nucleo/dist/parser/parser.modulo.js.map +0 -1
  262. package/node_modules/@sema/nucleo/dist/parser/parser.part01.js.map +0 -1
  263. package/node_modules/@sema/nucleo/dist/parser/parser.part02.js.map +0 -1
  264. package/node_modules/@sema/nucleo/dist/parser/parser.part03.js.map +0 -1
  265. package/node_modules/@sema/nucleo/dist/persistencia/contratos.js.map +0 -1
  266. package/node_modules/@sema/nucleo/dist/semantico/analisador.js.map +0 -1
  267. package/node_modules/@sema/nucleo/dist/semantico/analisador.part01.js.map +0 -1
  268. package/node_modules/@sema/nucleo/dist/semantico/analisador.part02.js.map +0 -1
  269. package/node_modules/@sema/nucleo/dist/semantico/analisador.part03.js.map +0 -1
  270. package/node_modules/@sema/nucleo/dist/semantico/analisador.part04.js.map +0 -1
  271. package/node_modules/@sema/nucleo/dist/semantico/analisador.part05.js.map +0 -1
  272. package/node_modules/@sema/nucleo/dist/semantico/analisador.part06.js.map +0 -1
  273. package/node_modules/@sema/nucleo/dist/semantico/analisador.part07.js.map +0 -1
  274. package/node_modules/@sema/nucleo/dist/semantico/analisador.part08.js.map +0 -1
  275. package/node_modules/@sema/nucleo/dist/semantico/estruturas.js.map +0 -1
  276. package/node_modules/@sema/nucleo/dist/semantico/estruturas.part01.js.map +0 -1
  277. package/node_modules/@sema/nucleo/dist/semantico/estruturas.part02.js.map +0 -1
  278. package/node_modules/@sema/nucleo/dist/semantico/orcamentoSemantico.js.map +0 -1
  279. package/node_modules/@sema/nucleo/dist/semantico/seguranca.js.map +0 -1
  280. package/node_modules/@sema/nucleo/dist/util/arquivos.js.map +0 -1
  281. package/node_modules/@sema/padroes/dist/index.js.map +0 -1
@@ -0,0 +1,438 @@
1
+ // SEMA-GOVERNED: sema.produto.sistemas_interativos.operacao, sema.produto.sistemas_interativos.operacao.observacao_engine
2
+ // Descricao: snapshots, diffs, proveniencia de assets e estado declarado de editor, sem sondar runtimes.
3
+ import { ASSET_PROVENANCE_SCHEMA_V1, EDITOR_STATE_SCHEMA_V1, ENGINE_DIFF_SCHEMA_V1, ENGINE_SNAPSHOT_SCHEMA_V1, } from "./operationsTypes.js";
4
+ import { digestJsonOperacional, failure, hasOnlyKeys, inspectPlainJson, isIntegerIn, isIsoTimestamp, isOpaqueSha256, isRecord, isSafeName, isSemanticId, isSha256, isVersion, issue, success, } from "./operationPrimitives.js";
5
+ export function validarSnapshotEngine(input) {
6
+ const issues = inspectPlainJson(input, "snapshot");
7
+ if (!isRecord(input))
8
+ return failure([...issues, issue("snapshot_object_required", "snapshot")]);
9
+ if (!hasOnlyKeys(input, [
10
+ "schemaVersion", "snapshotId", "projectId", "sceneId", "adapter",
11
+ "semanticObjects", "artifactDigest", "readOnly", "authoritative",
12
+ ]))
13
+ issues.push(issue("snapshot_unknown_field", "snapshot"));
14
+ if (input.schemaVersion !== ENGINE_SNAPSHOT_SCHEMA_V1)
15
+ issues.push(issue("snapshot_schema_invalid", "schemaVersion"));
16
+ if (!isSemanticId(input.snapshotId))
17
+ issues.push(issue("snapshot_id_invalid", "snapshotId"));
18
+ if (!isSemanticId(input.projectId))
19
+ issues.push(issue("project_id_invalid", "projectId"));
20
+ if (!isSemanticId(input.sceneId))
21
+ issues.push(issue("scene_id_invalid", "sceneId"));
22
+ if (!isSha256(input.artifactDigest))
23
+ issues.push(issue("artifact_digest_invalid", "artifactDigest"));
24
+ if (input.readOnly !== true)
25
+ issues.push(issue("snapshot_must_be_read_only", "readOnly"));
26
+ if (input.authoritative !== false)
27
+ issues.push(issue("snapshot_must_be_non_authoritative", "authoritative"));
28
+ const adapter = input.adapter;
29
+ if (!isRecord(adapter)
30
+ || !hasOnlyKeys(adapter, ["adapterId", "adapterVersion"])
31
+ || !isSafeName(adapter.adapterId)
32
+ || !isVersion(adapter.adapterVersion))
33
+ issues.push(issue("snapshot_adapter_invalid", "adapter"));
34
+ const objects = input.semanticObjects;
35
+ const ids = new Set();
36
+ if (!Array.isArray(objects) || objects.length === 0) {
37
+ issues.push(issue("snapshot_objects_required", "semanticObjects"));
38
+ }
39
+ else {
40
+ for (const object of objects) {
41
+ if (!isRecord(object) || !hasOnlyKeys(object, [
42
+ "semanticId", "kind", "parentSemanticId", "stateDigest", "componentDigests",
43
+ ])) {
44
+ issues.push(issue("snapshot_object_invalid", "semanticObjects"));
45
+ continue;
46
+ }
47
+ if (!isSemanticId(object.semanticId))
48
+ issues.push(issue("semantic_object_id_invalid", "semanticObjects"));
49
+ else if (ids.has(object.semanticId))
50
+ issues.push(issue("semantic_object_id_duplicate", "semanticObjects"));
51
+ else
52
+ ids.add(object.semanticId);
53
+ if (!isSafeName(object.kind))
54
+ issues.push(issue("semantic_object_kind_invalid", "semanticObjects"));
55
+ if (object.parentSemanticId !== undefined && !isSemanticId(object.parentSemanticId)) {
56
+ issues.push(issue("semantic_parent_id_invalid", "semanticObjects"));
57
+ }
58
+ if (!isSha256(object.stateDigest))
59
+ issues.push(issue("semantic_state_digest_invalid", "semanticObjects"));
60
+ if (!isRecord(object.componentDigests)) {
61
+ issues.push(issue("component_digests_invalid", "semanticObjects"));
62
+ }
63
+ else
64
+ for (const [name, digest] of Object.entries(object.componentDigests)) {
65
+ if (!isSafeName(name) || !isSha256(digest))
66
+ issues.push(issue("component_digest_invalid", "semanticObjects"));
67
+ }
68
+ }
69
+ for (const object of objects) {
70
+ if (isRecord(object) && typeof object.parentSemanticId === "string" && !ids.has(object.parentSemanticId)) {
71
+ issues.push(issue("semantic_parent_missing", "semanticObjects"));
72
+ }
73
+ }
74
+ const parentById = new Map();
75
+ for (const object of objects) {
76
+ if (!isRecord(object) || !isSemanticId(object.semanticId) || !isSemanticId(object.parentSemanticId))
77
+ continue;
78
+ if (object.parentSemanticId === object.semanticId) {
79
+ issues.push(issue("semantic_parent_self_reference", "semanticObjects"));
80
+ }
81
+ else if (ids.has(object.parentSemanticId))
82
+ parentById.set(object.semanticId, object.parentSemanticId);
83
+ }
84
+ for (const start of parentById.keys()) {
85
+ const path = new Set();
86
+ let cursor = start;
87
+ while (cursor !== undefined && parentById.has(cursor)) {
88
+ if (path.has(cursor)) {
89
+ issues.push(issue("semantic_parent_cycle", "semanticObjects"));
90
+ break;
91
+ }
92
+ path.add(cursor);
93
+ cursor = parentById.get(cursor);
94
+ }
95
+ if (issues.some((item) => item.code === "semantic_parent_cycle"))
96
+ break;
97
+ }
98
+ }
99
+ if (issues.length > 0)
100
+ return failure(issues);
101
+ const snapshot = input;
102
+ const normalized = {
103
+ ...snapshot,
104
+ adapter: { ...snapshot.adapter },
105
+ semanticObjects: snapshot.semanticObjects.map((object) => ({
106
+ ...object,
107
+ componentDigests: Object.fromEntries(Object.entries(object.componentDigests).sort(([left], [right]) => left.localeCompare(right))),
108
+ })).sort((left, right) => left.semanticId.localeCompare(right.semanticId)),
109
+ };
110
+ const snapshotDigest = digestJsonOperacional(normalized);
111
+ return success({ snapshot: normalized, snapshotDigest, localValidationOnly: true }, snapshotDigest);
112
+ }
113
+ export function derivarDiffSnapshotsEngine(beforeInput, afterInput) {
114
+ const beforeResult = validarSnapshotEngine(beforeInput);
115
+ const afterResult = validarSnapshotEngine(afterInput);
116
+ const issues = [];
117
+ if (!beforeResult.valid)
118
+ issues.push(issue("before_snapshot_invalid", "snapshotBefore"), ...beforeResult.issues);
119
+ if (!afterResult.valid)
120
+ issues.push(issue("after_snapshot_invalid", "snapshotAfter"), ...afterResult.issues);
121
+ if (!beforeResult.value || !afterResult.value)
122
+ return failure(issues);
123
+ const before = beforeResult.value.snapshot;
124
+ const after = afterResult.value.snapshot;
125
+ if (before.projectId !== after.projectId)
126
+ issues.push(issue("snapshot_project_binding_mismatch", "projectId"));
127
+ if (before.sceneId !== after.sceneId)
128
+ issues.push(issue("snapshot_scene_binding_mismatch", "sceneId"));
129
+ if (before.adapter.adapterId !== after.adapter.adapterId
130
+ || before.adapter.adapterVersion !== after.adapter.adapterVersion) {
131
+ issues.push(issue("snapshot_adapter_binding_mismatch", "adapter"));
132
+ }
133
+ if (issues.length > 0)
134
+ return failure(issues);
135
+ const beforeById = new Map(before.semanticObjects.map((item) => [item.semanticId, item]));
136
+ const afterById = new Map(after.semanticObjects.map((item) => [item.semanticId, item]));
137
+ const allIds = [...new Set([...beforeById.keys(), ...afterById.keys()])].sort();
138
+ const changes = [];
139
+ for (const semanticId of allIds) {
140
+ const previous = beforeById.get(semanticId);
141
+ const current = afterById.get(semanticId);
142
+ if (!previous && current) {
143
+ changes.push({ semanticId, change: "ADDED", afterDigest: digestJsonOperacional(current) });
144
+ }
145
+ else if (previous && !current) {
146
+ changes.push({ semanticId, change: "REMOVED", beforeDigest: digestJsonOperacional(previous) });
147
+ }
148
+ else if (previous && current) {
149
+ const beforeDigest = digestJsonOperacional(previous);
150
+ const afterDigest = digestJsonOperacional(current);
151
+ if (beforeDigest !== afterDigest)
152
+ changes.push({ semanticId, change: "MODIFIED", beforeDigest, afterDigest });
153
+ }
154
+ }
155
+ const withoutDigest = {
156
+ schemaVersion: ENGINE_DIFF_SCHEMA_V1,
157
+ beforeSnapshotDigest: beforeResult.value.snapshotDigest,
158
+ afterSnapshotDigest: afterResult.value.snapshotDigest,
159
+ bindingDigest: digestJsonOperacional({ projectId: before.projectId, sceneId: before.sceneId, adapter: before.adapter }),
160
+ artifactDigestChanged: before.artifactDigest !== after.artifactDigest,
161
+ changes,
162
+ readOnly: true,
163
+ authoritative: false,
164
+ };
165
+ const diff = { ...withoutDigest, diffDigest: digestJsonOperacional(withoutDigest) };
166
+ return success(diff, diff.diffDigest);
167
+ }
168
+ export function validarProvenienciaAsset(input) {
169
+ const issues = inspectPlainJson(input, "provenance");
170
+ if (!isRecord(input))
171
+ return failure([...issues, issue("provenance_object_required", "provenance")]);
172
+ if (!hasOnlyKeys(input, [
173
+ "schemaVersion", "assetId", "sourceUriRef", "sourceUriRedacted", "license",
174
+ "sourceHash", "contentHash", "transforms", "derivatives", "authoritative",
175
+ ]))
176
+ issues.push(issue("provenance_unknown_field", "provenance"));
177
+ if (input.schemaVersion !== ASSET_PROVENANCE_SCHEMA_V1)
178
+ issues.push(issue("provenance_schema_invalid", "schemaVersion"));
179
+ if (!isSemanticId(input.assetId))
180
+ issues.push(issue("asset_id_invalid", "assetId"));
181
+ if (!isOpaqueSha256(input.sourceUriRef))
182
+ issues.push(issue("source_uri_ref_must_be_opaque", "sourceUriRef"));
183
+ if (input.sourceUriRedacted !== true)
184
+ issues.push(issue("source_uri_must_be_redacted", "sourceUriRedacted"));
185
+ if (!isSha256(input.sourceHash))
186
+ issues.push(issue("source_hash_invalid", "sourceHash"));
187
+ if (!isSha256(input.contentHash))
188
+ issues.push(issue("content_hash_invalid", "contentHash"));
189
+ if (input.authoritative !== false)
190
+ issues.push(issue("provenance_must_be_non_authoritative", "authoritative"));
191
+ const license = input.license;
192
+ if (!isRecord(license)
193
+ || !hasOnlyKeys(license, ["licenseId", "evidenceDigest", "redistributable"])
194
+ || !isSafeName(license.licenseId)
195
+ || !isSha256(license.evidenceDigest)
196
+ || typeof license.redistributable !== "boolean")
197
+ issues.push(issue("asset_license_invalid", "license"));
198
+ const transforms = input.transforms;
199
+ const transformIds = new Set();
200
+ let previousDigest = input.sourceHash;
201
+ if (!Array.isArray(transforms)) {
202
+ issues.push(issue("asset_transforms_invalid", "transforms"));
203
+ }
204
+ else {
205
+ for (const transform of transforms) {
206
+ if (!isRecord(transform) || !hasOnlyKeys(transform, [
207
+ "transformId", "toolRef", "toolVersion", "inputDigest", "outputDigest", "parametersDigest",
208
+ ])) {
209
+ issues.push(issue("asset_transform_invalid", "transforms"));
210
+ continue;
211
+ }
212
+ if (!isSemanticId(transform.transformId))
213
+ issues.push(issue("transform_id_invalid", "transforms"));
214
+ else if (transformIds.has(transform.transformId))
215
+ issues.push(issue("transform_id_duplicate", "transforms"));
216
+ else
217
+ transformIds.add(transform.transformId);
218
+ if (!isSafeName(transform.toolRef) || !isVersion(transform.toolVersion))
219
+ issues.push(issue("transform_tool_invalid", "transforms"));
220
+ if (!isSha256(transform.inputDigest) || !isSha256(transform.outputDigest) || !isSha256(transform.parametersDigest)) {
221
+ issues.push(issue("transform_digest_invalid", "transforms"));
222
+ }
223
+ if (transform.inputDigest !== previousDigest)
224
+ issues.push(issue("transform_chain_broken", "transforms"));
225
+ previousDigest = transform.outputDigest;
226
+ }
227
+ if (previousDigest !== input.contentHash)
228
+ issues.push(issue("transform_final_hash_mismatch", "contentHash"));
229
+ }
230
+ const derivatives = input.derivatives;
231
+ const derivativeIds = new Set();
232
+ const derivativeHashes = new Set();
233
+ const parentByHash = new Map();
234
+ if (!Array.isArray(derivatives)) {
235
+ issues.push(issue("asset_derivatives_invalid", "derivatives"));
236
+ }
237
+ else {
238
+ for (const derivative of derivatives) {
239
+ if (!isRecord(derivative) || !hasOnlyKeys(derivative, [
240
+ "assetId", "parentContentHash", "contentHash", "transformDigest",
241
+ ])) {
242
+ issues.push(issue("asset_derivative_invalid", "derivatives"));
243
+ continue;
244
+ }
245
+ if (!isSemanticId(derivative.assetId))
246
+ issues.push(issue("derivative_asset_id_invalid", "derivatives"));
247
+ else if (derivativeIds.has(derivative.assetId))
248
+ issues.push(issue("derivative_asset_id_duplicate", "derivatives"));
249
+ else
250
+ derivativeIds.add(derivative.assetId);
251
+ if (!isSha256(derivative.parentContentHash)
252
+ || !isSha256(derivative.contentHash)
253
+ || !isSha256(derivative.transformDigest)) {
254
+ issues.push(issue("derivative_digest_invalid", "derivatives"));
255
+ continue;
256
+ }
257
+ if (derivativeHashes.has(derivative.contentHash) || derivative.contentHash === input.contentHash) {
258
+ issues.push(issue("derivative_content_hash_duplicate", "derivatives"));
259
+ }
260
+ derivativeHashes.add(derivative.contentHash);
261
+ parentByHash.set(derivative.contentHash, derivative.parentContentHash);
262
+ }
263
+ const knownHashes = new Set([input.contentHash, ...derivativeHashes]);
264
+ for (const [contentHash, parentHash] of parentByHash) {
265
+ if (!knownHashes.has(parentHash))
266
+ issues.push(issue("derivative_parent_missing", "derivatives"));
267
+ const visited = new Set();
268
+ let cursor = contentHash;
269
+ while (cursor !== undefined && cursor !== input.contentHash) {
270
+ if (visited.has(cursor)) {
271
+ issues.push(issue("derivative_cycle_detected", "derivatives"));
272
+ break;
273
+ }
274
+ visited.add(cursor);
275
+ cursor = parentByHash.get(cursor);
276
+ if (cursor === undefined)
277
+ issues.push(issue("derivative_lineage_incomplete", "derivatives"));
278
+ }
279
+ }
280
+ }
281
+ if (issues.length > 0)
282
+ return failure(issues);
283
+ const provenance = input;
284
+ const normalized = {
285
+ ...provenance,
286
+ license: { ...provenance.license },
287
+ transforms: provenance.transforms.map((item) => ({ ...item })),
288
+ derivatives: provenance.derivatives.map((item) => ({ ...item }))
289
+ .sort((left, right) => left.assetId.localeCompare(right.assetId)),
290
+ };
291
+ const provenanceDigest = digestJsonOperacional(normalized);
292
+ return success({ provenance: normalized, provenanceDigest }, provenanceDigest);
293
+ }
294
+ const BACKGROUND_JOB_STATES = new Set(["QUEUED", "RUNNING", "SUCCEEDED", "FAILED", "CANCELLED"]);
295
+ const EDITOR_MODES = new Set(["EDIT", "PLAY", "PAUSED"]);
296
+ const PROCESS_ROLES = new Set(["ENGINE", "EDITOR", "SHADER_COMPILER", "IMPORT_WORKER", "BUILD_WORKER"]);
297
+ const PROCESS_STATES = new Set(["IDLE", "RUNNING", "BLOCKED", "FAILED", "EXITED"]);
298
+ function validateBackgroundJobs(value, field, issues) {
299
+ const ids = new Set();
300
+ if (!Array.isArray(value)) {
301
+ issues.push(issue("editor_jobs_invalid", field));
302
+ return;
303
+ }
304
+ for (const job of value) {
305
+ if (!isRecord(job)
306
+ || !hasOnlyKeys(job, ["jobId", "status", "progressBasisPoints"])
307
+ || !isSemanticId(job.jobId)
308
+ || typeof job.status !== "string"
309
+ || !BACKGROUND_JOB_STATES.has(job.status)
310
+ || !isIntegerIn(job.progressBasisPoints, 0, 10_000)) {
311
+ issues.push(issue("editor_job_invalid", field));
312
+ continue;
313
+ }
314
+ if (ids.has(job.jobId))
315
+ issues.push(issue("editor_job_id_duplicate", field));
316
+ ids.add(job.jobId);
317
+ }
318
+ }
319
+ export function validarEstadoEditor(input) {
320
+ const issues = inspectPlainJson(input, "editorState");
321
+ if (!isRecord(input))
322
+ return failure([...issues, issue("editor_state_object_required", "editorState")]);
323
+ if (!hasOnlyKeys(input, [
324
+ "schemaVersion", "editorSessionId", "adapter", "scene", "selection", "mode",
325
+ "unsavedChanges", "shaderJobs", "importJobs", "plugins", "modals", "processes",
326
+ "observedAt", "readOnly", "authoritative",
327
+ ]))
328
+ issues.push(issue("editor_state_unknown_field", "editorState"));
329
+ if (input.schemaVersion !== EDITOR_STATE_SCHEMA_V1)
330
+ issues.push(issue("editor_state_schema_invalid", "schemaVersion"));
331
+ if (!isSemanticId(input.editorSessionId))
332
+ issues.push(issue("editor_session_id_invalid", "editorSessionId"));
333
+ if (typeof input.mode !== "string" || !EDITOR_MODES.has(input.mode))
334
+ issues.push(issue("editor_mode_invalid", "mode"));
335
+ if (typeof input.unsavedChanges !== "boolean")
336
+ issues.push(issue("unsaved_changes_invalid", "unsavedChanges"));
337
+ if (!isIsoTimestamp(input.observedAt))
338
+ issues.push(issue("editor_observed_at_invalid", "observedAt"));
339
+ if (input.readOnly !== true)
340
+ issues.push(issue("editor_state_must_be_read_only", "readOnly"));
341
+ if (input.authoritative !== false)
342
+ issues.push(issue("editor_state_must_be_non_authoritative", "authoritative"));
343
+ if (!isRecord(input.adapter)
344
+ || !hasOnlyKeys(input.adapter, ["adapterId", "adapterVersion"])
345
+ || !isSafeName(input.adapter.adapterId)
346
+ || !isVersion(input.adapter.adapterVersion))
347
+ issues.push(issue("editor_adapter_invalid", "adapter"));
348
+ if (!isRecord(input.scene)
349
+ || !hasOnlyKeys(input.scene, ["semanticId", "artifactDigest"])
350
+ || !isSemanticId(input.scene.semanticId)
351
+ || !isSha256(input.scene.artifactDigest))
352
+ issues.push(issue("editor_scene_invalid", "scene"));
353
+ const selectionIds = new Set();
354
+ if (!Array.isArray(input.selection))
355
+ issues.push(issue("editor_selection_invalid", "selection"));
356
+ else
357
+ for (const selected of input.selection) {
358
+ if (!isSemanticId(selected))
359
+ issues.push(issue("editor_selection_id_invalid", "selection"));
360
+ else if (selectionIds.has(selected))
361
+ issues.push(issue("editor_selection_duplicate", "selection"));
362
+ else
363
+ selectionIds.add(selected);
364
+ }
365
+ validateBackgroundJobs(input.shaderJobs, "shaderJobs", issues);
366
+ validateBackgroundJobs(input.importJobs, "importJobs", issues);
367
+ const pluginIds = new Set();
368
+ if (!Array.isArray(input.plugins))
369
+ issues.push(issue("editor_plugins_invalid", "plugins"));
370
+ else
371
+ for (const plugin of input.plugins) {
372
+ if (!isRecord(plugin)
373
+ || !hasOnlyKeys(plugin, ["pluginId", "version", "enabled", "provenanceDigest"])
374
+ || !isSafeName(plugin.pluginId)
375
+ || !isVersion(plugin.version)
376
+ || typeof plugin.enabled !== "boolean"
377
+ || !isSha256(plugin.provenanceDigest)) {
378
+ issues.push(issue("editor_plugin_invalid", "plugins"));
379
+ continue;
380
+ }
381
+ if (pluginIds.has(plugin.pluginId))
382
+ issues.push(issue("editor_plugin_id_duplicate", "plugins"));
383
+ pluginIds.add(plugin.pluginId);
384
+ }
385
+ const modalIds = new Set();
386
+ if (!Array.isArray(input.modals))
387
+ issues.push(issue("editor_modals_invalid", "modals"));
388
+ else
389
+ for (const modal of input.modals) {
390
+ if (!isRecord(modal)
391
+ || !hasOnlyKeys(modal, ["modalId", "kind", "blocking"])
392
+ || !isSemanticId(modal.modalId)
393
+ || !isSafeName(modal.kind)
394
+ || typeof modal.blocking !== "boolean") {
395
+ issues.push(issue("editor_modal_invalid", "modals"));
396
+ continue;
397
+ }
398
+ if (modalIds.has(modal.modalId))
399
+ issues.push(issue("editor_modal_id_duplicate", "modals"));
400
+ modalIds.add(modal.modalId);
401
+ }
402
+ const processRefs = new Set();
403
+ if (!Array.isArray(input.processes))
404
+ issues.push(issue("editor_processes_invalid", "processes"));
405
+ else
406
+ for (const process of input.processes) {
407
+ if (!isRecord(process)
408
+ || !hasOnlyKeys(process, ["processRef", "role", "state"])
409
+ || !isOpaqueSha256(process.processRef)
410
+ || typeof process.role !== "string"
411
+ || !PROCESS_ROLES.has(process.role)
412
+ || typeof process.state !== "string"
413
+ || !PROCESS_STATES.has(process.state)) {
414
+ issues.push(issue("editor_process_invalid", "processes"));
415
+ continue;
416
+ }
417
+ if (processRefs.has(process.processRef))
418
+ issues.push(issue("editor_process_ref_duplicate", "processes"));
419
+ processRefs.add(process.processRef);
420
+ }
421
+ if (issues.length > 0)
422
+ return failure(issues);
423
+ const state = input;
424
+ const normalized = {
425
+ ...state,
426
+ adapter: { ...state.adapter },
427
+ scene: { ...state.scene },
428
+ selection: [...state.selection].sort(),
429
+ shaderJobs: state.shaderJobs.map((item) => ({ ...item })).sort((a, b) => a.jobId.localeCompare(b.jobId)),
430
+ importJobs: state.importJobs.map((item) => ({ ...item })).sort((a, b) => a.jobId.localeCompare(b.jobId)),
431
+ plugins: state.plugins.map((item) => ({ ...item })).sort((a, b) => a.pluginId.localeCompare(b.pluginId)),
432
+ modals: state.modals.map((item) => ({ ...item })).sort((a, b) => a.modalId.localeCompare(b.modalId)),
433
+ processes: state.processes.map((item) => ({ ...item })).sort((a, b) => a.processRef.localeCompare(b.processRef)),
434
+ };
435
+ const editorStateDigest = digestJsonOperacional(normalized);
436
+ return success({ state: normalized, editorStateDigest, externallyObserved: false }, editorStateDigest);
437
+ }
438
+ //# sourceMappingURL=engineObservation.js.map
@@ -0,0 +1,2 @@
1
+ import { type JobOrchestrationPlanV1, type OperationResult } from "./operationsTypes.js";
2
+ export declare function planejarOrquestracaoJobs(input: unknown): OperationResult<JobOrchestrationPlanV1>;
@@ -0,0 +1,204 @@
1
+ // SEMA-GOVERNED: sema.produto.sistemas_interativos.operacao.orquestracao_jobs
2
+ // Descricao: planejamento deterministico de filas, locks, budgets, heartbeat, checkpoint e retomada.
3
+ import { JOB_ORCHESTRATION_SCHEMA_V1, } from "./operationsTypes.js";
4
+ import { digestJsonOperacional, failure, hasOnlyKeys, inspectPlainJson, isIntegerIn, isOpaqueSha256, isRecord, isSafeName, isSemanticId, isSha256, isVersion, issue, success, } from "./operationPrimitives.js";
5
+ const RESOURCE_LOCKS = ["GPU", "EDITOR", "CACHE"];
6
+ function validateBudget(value, field, issues) {
7
+ if (!isRecord(value)
8
+ || !hasOnlyKeys(value, ["ramMb", "vramMb", "diskMb"])
9
+ || !isIntegerIn(value.ramMb, 1, 16_777_216)
10
+ || !isIntegerIn(value.vramMb, 0, 16_777_216)
11
+ || !isIntegerIn(value.diskMb, 1, 1_073_741_824)) {
12
+ issues.push(issue("resource_budget_invalid", field));
13
+ return false;
14
+ }
15
+ return true;
16
+ }
17
+ export function planejarOrquestracaoJobs(input) {
18
+ const issues = inspectPlainJson(input, "jobRequest");
19
+ if (!isRecord(input))
20
+ return failure([...issues, issue("job_request_object_required", "jobRequest")]);
21
+ if (!hasOnlyKeys(input, ["schemaVersion", "queueId", "capacity", "lockCapacity", "jobs"])) {
22
+ issues.push(issue("job_request_unknown_field", "jobRequest"));
23
+ }
24
+ if (input.schemaVersion !== JOB_ORCHESTRATION_SCHEMA_V1)
25
+ issues.push(issue("job_schema_invalid", "schemaVersion"));
26
+ if (!isSemanticId(input.queueId))
27
+ issues.push(issue("queue_id_invalid", "queueId"));
28
+ const capacity = input.capacity;
29
+ const capacityValid = validateBudget(capacity, "capacity", issues);
30
+ const lockCapacity = input.lockCapacity;
31
+ if (!isRecord(lockCapacity)
32
+ || !hasOnlyKeys(lockCapacity, RESOURCE_LOCKS)
33
+ || !RESOURCE_LOCKS.every((lock) => isIntegerIn(lockCapacity[lock], 0, 1))) {
34
+ issues.push(issue("lock_capacity_invalid", "lockCapacity"));
35
+ }
36
+ const jobs = input.jobs;
37
+ const ids = new Set();
38
+ if (!Array.isArray(jobs) || jobs.length === 0) {
39
+ issues.push(issue("jobs_required", "jobs"));
40
+ }
41
+ else {
42
+ for (const job of jobs) {
43
+ if (!isRecord(job) || !hasOnlyKeys(job, [
44
+ "jobId", "kind", "priority", "dependencies", "locks", "budget",
45
+ "heartbeat", "checkpoint", "adapter",
46
+ ])) {
47
+ issues.push(issue("job_invalid", "jobs"));
48
+ continue;
49
+ }
50
+ if (!isSemanticId(job.jobId))
51
+ issues.push(issue("job_id_invalid", "jobs"));
52
+ else if (ids.has(job.jobId))
53
+ issues.push(issue("job_id_duplicate", "jobs"));
54
+ else
55
+ ids.add(job.jobId);
56
+ if (!isSafeName(job.kind))
57
+ issues.push(issue("job_kind_invalid", "jobs"));
58
+ if (!isIntegerIn(job.priority, 0, 100))
59
+ issues.push(issue("job_priority_invalid", "jobs"));
60
+ if (!Array.isArray(job.dependencies)
61
+ || job.dependencies.some((dependency) => !isSemanticId(dependency))
62
+ || new Set(job.dependencies).size !== job.dependencies.length
63
+ || job.dependencies.includes(job.jobId))
64
+ issues.push(issue("job_dependencies_invalid", "jobs"));
65
+ if (!Array.isArray(job.locks)
66
+ || job.locks.some((lock) => typeof lock !== "string" || !RESOURCE_LOCKS.includes(lock))
67
+ || new Set(job.locks).size !== job.locks.length)
68
+ issues.push(issue("job_locks_invalid", "jobs"));
69
+ const budget = job.budget;
70
+ const budgetValid = validateBudget(budget, "jobs", issues);
71
+ if (budgetValid && capacityValid
72
+ && (budget.ramMb > capacity.ramMb
73
+ || budget.vramMb > capacity.vramMb
74
+ || budget.diskMb > capacity.diskMb))
75
+ issues.push(issue("job_budget_exceeds_capacity", "jobs"));
76
+ if (Array.isArray(job.locks) && isRecord(lockCapacity)) {
77
+ for (const lock of job.locks) {
78
+ if (typeof lock === "string"
79
+ && RESOURCE_LOCKS.includes(lock)
80
+ && lockCapacity[lock] !== 1)
81
+ issues.push(issue("job_lock_unavailable", "jobs"));
82
+ }
83
+ if (job.locks.includes("GPU") && isRecord(job.budget) && job.budget.vramMb === 0) {
84
+ issues.push(issue("gpu_job_requires_vram", "jobs"));
85
+ }
86
+ }
87
+ if (!isRecord(job.heartbeat)
88
+ || !hasOnlyKeys(job.heartbeat, ["intervalMs", "timeoutMs"])
89
+ || !isIntegerIn(job.heartbeat.intervalMs, 100, 86_400_000)
90
+ || !isIntegerIn(job.heartbeat.timeoutMs, 100, 86_400_000)
91
+ || (typeof job.heartbeat.intervalMs === "number"
92
+ && typeof job.heartbeat.timeoutMs === "number"
93
+ && job.heartbeat.timeoutMs < job.heartbeat.intervalMs * 2))
94
+ issues.push(issue("job_heartbeat_invalid", "jobs"));
95
+ if (!isRecord(job.checkpoint)
96
+ || !hasOnlyKeys(job.checkpoint, ["intervalMs", "resume", "checkpointDigest", "recoveryToken"])
97
+ || !isIntegerIn(job.checkpoint.intervalMs, 100, 86_400_000)
98
+ || typeof job.checkpoint.resume !== "boolean"
99
+ || !isOpaqueSha256(job.checkpoint.recoveryToken)
100
+ || (job.checkpoint.checkpointDigest !== undefined && !isSha256(job.checkpoint.checkpointDigest))
101
+ || (job.checkpoint.resume === true && !isSha256(job.checkpoint.checkpointDigest))) {
102
+ issues.push(issue("job_checkpoint_invalid", "jobs"));
103
+ }
104
+ if (!isRecord(job.adapter)
105
+ || !hasOnlyKeys(job.adapter, ["adapterId", "adapterVersion"])
106
+ || !isSafeName(job.adapter.adapterId)
107
+ || !isVersion(job.adapter.adapterVersion))
108
+ issues.push(issue("job_adapter_invalid", "jobs"));
109
+ }
110
+ for (const job of jobs) {
111
+ if (!isRecord(job) || !Array.isArray(job.dependencies))
112
+ continue;
113
+ for (const dependency of job.dependencies) {
114
+ if (typeof dependency === "string" && !ids.has(dependency))
115
+ issues.push(issue("job_dependency_missing", "jobs"));
116
+ }
117
+ }
118
+ }
119
+ if (issues.length > 0)
120
+ return failure(issues);
121
+ const request = input;
122
+ const byId = new Map(request.jobs.map((job) => [job.jobId, job]));
123
+ const indegree = new Map(request.jobs.map((job) => [job.jobId, job.dependencies.length]));
124
+ const dependents = new Map();
125
+ for (const job of request.jobs)
126
+ for (const dependency of job.dependencies) {
127
+ const list = dependents.get(dependency) ?? [];
128
+ list.push(job.jobId);
129
+ dependents.set(dependency, list);
130
+ }
131
+ const compareJobs = (leftId, rightId) => {
132
+ const left = byId.get(leftId);
133
+ const right = byId.get(rightId);
134
+ return right.priority - left.priority || left.jobId.localeCompare(right.jobId);
135
+ };
136
+ const ready = request.jobs.filter((job) => job.dependencies.length === 0)
137
+ .map((job) => job.jobId).sort(compareJobs);
138
+ const ordered = [];
139
+ while (ready.length > 0) {
140
+ const id = ready.shift();
141
+ ordered.push(byId.get(id));
142
+ for (const dependent of (dependents.get(id) ?? []).sort()) {
143
+ const next = (indegree.get(dependent) ?? 0) - 1;
144
+ indegree.set(dependent, next);
145
+ if (next === 0) {
146
+ ready.push(dependent);
147
+ ready.sort(compareJobs);
148
+ }
149
+ }
150
+ }
151
+ if (ordered.length !== request.jobs.length)
152
+ return failure([issue("job_dependency_cycle", "jobs")]);
153
+ const normalizedRequest = {
154
+ schemaVersion: request.schemaVersion,
155
+ queueId: request.queueId,
156
+ capacity: { ...request.capacity },
157
+ lockCapacity: Object.fromEntries(RESOURCE_LOCKS.map((lock) => [lock, request.lockCapacity[lock]])),
158
+ jobs: request.jobs.map((job) => ({
159
+ jobId: job.jobId,
160
+ kind: job.kind,
161
+ priority: job.priority,
162
+ dependencies: [...job.dependencies].sort(),
163
+ locks: [...job.locks].sort((a, b) => RESOURCE_LOCKS.indexOf(a) - RESOURCE_LOCKS.indexOf(b)),
164
+ budget: { ...job.budget },
165
+ heartbeat: { ...job.heartbeat },
166
+ checkpoint: {
167
+ intervalMs: job.checkpoint.intervalMs,
168
+ resume: job.checkpoint.resume,
169
+ ...(job.checkpoint.checkpointDigest === undefined ? {} : { checkpointDigest: job.checkpoint.checkpointDigest }),
170
+ recoveryToken: job.checkpoint.recoveryToken,
171
+ },
172
+ adapter: { ...job.adapter },
173
+ })).sort((left, right) => left.jobId.localeCompare(right.jobId)),
174
+ };
175
+ const requestDigest = digestJsonOperacional(normalizedRequest);
176
+ const queue = ordered.map((job, index) => ({
177
+ position: index + 1,
178
+ jobId: job.jobId,
179
+ kind: job.kind,
180
+ priority: job.priority,
181
+ adapter: { ...job.adapter },
182
+ dependencies: [...job.dependencies].sort(),
183
+ locks: [...job.locks].sort((a, b) => RESOURCE_LOCKS.indexOf(a) - RESOURCE_LOCKS.indexOf(b)),
184
+ budget: { ...job.budget },
185
+ heartbeatIntervalMs: job.heartbeat.intervalMs,
186
+ heartbeatTimeoutMs: job.heartbeat.timeoutMs,
187
+ checkpointIntervalMs: job.checkpoint.intervalMs,
188
+ resume: job.checkpoint.resume,
189
+ ...(job.checkpoint.checkpointDigest === undefined ? {} : { checkpointDigest: job.checkpoint.checkpointDigest }),
190
+ recoveryToken: job.checkpoint.recoveryToken,
191
+ }));
192
+ const withoutDigest = {
193
+ schemaVersion: JOB_ORCHESTRATION_SCHEMA_V1,
194
+ queueId: request.queueId,
195
+ queue,
196
+ requestDigest,
197
+ externalRunnerRequired: true,
198
+ resourcesReserved: false,
199
+ authoritative: false,
200
+ };
201
+ const plan = { ...withoutDigest, planDigest: digestJsonOperacional(withoutDigest) };
202
+ return success(plan, plan.planDigest);
203
+ }
204
+ //# sourceMappingURL=jobOrchestration.js.map
@@ -0,0 +1,21 @@
1
+ import { type OpaqueSha256, type OperationIssue, type OperationResult, type Sha256 } from "./operationsTypes.js";
2
+ export declare const MEDIA_TYPE_PATTERN: RegExp;
3
+ export declare function issue(code: string, field: string): OperationIssue;
4
+ export declare function failure<T>(issues: readonly OperationIssue[]): OperationResult<T>;
5
+ export declare function success<T>(value: T, digest?: Sha256): OperationResult<T>;
6
+ export declare function isRecord(value: unknown): value is Record<string, unknown>;
7
+ export declare function isSha256(value: unknown): value is Sha256;
8
+ export declare function isOpaqueSha256(value: unknown): value is OpaqueSha256;
9
+ export declare function isSemanticId(value: unknown): value is string;
10
+ export declare function isSafeName(value: unknown): value is string;
11
+ export declare function isVersion(value: unknown): value is string;
12
+ export declare function isIsoTimestamp(value: unknown): value is string;
13
+ export declare function isIntegerIn(value: unknown, minimum: number, maximum: number): value is number;
14
+ export declare function hasOnlyKeys(value: Record<string, unknown>, allowed: readonly string[]): boolean;
15
+ export declare function inspectPlainJson(input: unknown, rootField: string): OperationIssue[];
16
+ export declare function canonicalJson(value: unknown): string;
17
+ export declare function digestJsonOperacional(value: unknown): Sha256;
18
+ export declare function criarReferenciaFonteOpaca(sourceUri: unknown): OperationResult<{
19
+ readonly sourceUriRef: OpaqueSha256;
20
+ readonly sourceUriRedacted: true;
21
+ }>;