@tiinex/core 0.1.1

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 (517) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +31 -0
  3. package/README.md +45 -0
  4. package/package.json +176 -0
  5. package/src/actions/record.actions.js +312 -0
  6. package/src/adapters/adapter.contracts.js +143 -0
  7. package/src/adapters/archive/archive.adapter.js +502 -0
  8. package/src/adapters/archive/archive.portableChangeset.js +141 -0
  9. package/src/adapters/archive/archive.transport.js +124 -0
  10. package/src/artifacts/artifact.localDraft.js +27 -0
  11. package/src/artifacts/artifact.normalize.js +28 -0
  12. package/src/artifacts/artifact.parse.js +207 -0
  13. package/src/artifacts/artifact.record.js +83 -0
  14. package/src/audit/audit.run.js +103 -0
  15. package/src/audit/audit.summary.js +7 -0
  16. package/src/diagnostics/sourceBoundary.report.js +112 -0
  17. package/src/export/package.apply.js +349 -0
  18. package/src/export/package.builder.js +366 -0
  19. package/src/export/package.bytes.js +164 -0
  20. package/src/export/package.controlIntegrity.js +42 -0
  21. package/src/export/package.controlTopology.js +97 -0
  22. package/src/export/package.fileMap.js +174 -0
  23. package/src/export/package.manifest.js +401 -0
  24. package/src/export/package.preflight.js +204 -0
  25. package/src/export/package.sourceReference.js +81 -0
  26. package/src/export/package.workspaceContext.js +144 -0
  27. package/src/export/package.zip.js +128 -0
  28. package/src/export/tree.bundle.js +278 -0
  29. package/src/governance/governance.boundary.js +196 -0
  30. package/src/integrity/integrity.c14nV2.js +190 -0
  31. package/src/integrity/integrity.methodReference.js +73 -0
  32. package/src/integrity/integrity.validate.js +56 -0
  33. package/src/lineage/lineage.candidateResolution.js +46 -0
  34. package/src/lineage/lineage.githubIssueComment.js +106 -0
  35. package/src/lineage/lineage.githubIssueLocal.js +196 -0
  36. package/src/lineage/lineage.githubIssueTarget.js +89 -0
  37. package/src/lineage/lineage.integrity.js +133 -0
  38. package/src/lineage/lineage.materialPreference.js +26 -0
  39. package/src/lineage/lineage.model.js +63 -0
  40. package/src/lineage/lineage.parentAuthority.js +5 -0
  41. package/src/lineage/lineage.parentBinding.js +104 -0
  42. package/src/lineage/lineage.pathBasis.js +47 -0
  43. package/src/lineage/lineage.resolve.js +388 -0
  44. package/src/lineage/lineage.sourceScope.js +74 -0
  45. package/src/lineage/lineage.targetKeys.js +80 -0
  46. package/src/lineage/lineage.traverse.js +132 -0
  47. package/src/public/applicationProjection.js +236 -0
  48. package/src/public/companionResources.js +246 -0
  49. package/src/public/index.js +16 -0
  50. package/src/public/node.js +2 -0
  51. package/src/public/schemaAncestry.js +26 -0
  52. package/src/publication/publication.contract.js +196 -0
  53. package/src/publication/publication.preflight.js +159 -0
  54. package/src/publication/publication.targetContract.js +241 -0
  55. package/src/reingest/reingest.plan.js +162 -0
  56. package/src/release/plan.mjs +28 -0
  57. package/src/release/policy.mjs +100 -0
  58. package/src/release/run.mjs +74 -0
  59. package/src/schemas/capability.registry.js +226 -0
  60. package/src/schemas/companion.js +245 -0
  61. package/src/schemas/contracts.js +6 -0
  62. package/src/schemas/coordination/handoff/tiinex.handoff.v1.schema.js +14 -0
  63. package/src/schemas/coordination/handoff/tiinex.handoff.v1.schema.json +23 -0
  64. package/src/schemas/coordination/handoff/tiinex.handoff.v1.schema.runtime.json +4283 -0
  65. package/src/schemas/coordination/handoff/tiinex.handoff.v1.schema.source.js +9 -0
  66. package/src/schemas/coordination/project/tiinex.project.v1.schema.js +26 -0
  67. package/src/schemas/coordination/project/tiinex.project.v1.schema.json +23 -0
  68. package/src/schemas/coordination/project/tiinex.project.v1.schema.runtime.json +1985 -0
  69. package/src/schemas/coordination/project/tiinex.project.v1.schema.source.js +9 -0
  70. package/src/schemas/core/decision/tiinex.decision.v1.schema.js +14 -0
  71. package/src/schemas/core/decision/tiinex.decision.v1.schema.json +24 -0
  72. package/src/schemas/core/decision/tiinex.decision.v1.schema.runtime.json +1700 -0
  73. package/src/schemas/core/decision/tiinex.decision.v1.schema.source.js +9 -0
  74. package/src/schemas/core/evidence/tiinex.evidence.v1.capabilities.js +14 -0
  75. package/src/schemas/core/evidence/tiinex.evidence.v1.en.i18n.json +6 -0
  76. package/src/schemas/core/evidence/tiinex.evidence.v1.findings.js +9 -0
  77. package/src/schemas/core/evidence/tiinex.evidence.v1.presenter.js +1 -0
  78. package/src/schemas/core/evidence/tiinex.evidence.v1.schema.js +32 -0
  79. package/src/schemas/core/evidence/tiinex.evidence.v1.schema.json +24 -0
  80. package/src/schemas/core/evidence/tiinex.evidence.v1.schema.runtime.json +2184 -0
  81. package/src/schemas/core/evidence/tiinex.evidence.v1.schema.source.js +9 -0
  82. package/src/schemas/core/evidence/tiinex.evidence.v1.sv.i18n.json +6 -0
  83. package/src/schemas/core/evidence/tiinex.evidence.v1.transitions.js +1 -0
  84. package/src/schemas/core/evidence/tiinex.evidence.v1.validate.js +10 -0
  85. package/src/schemas/core/feedback/tiinex.feedback.v1.schema.js +14 -0
  86. package/src/schemas/core/feedback/tiinex.feedback.v1.schema.json +23 -0
  87. package/src/schemas/core/feedback/tiinex.feedback.v1.schema.runtime.json +1773 -0
  88. package/src/schemas/core/feedback/tiinex.feedback.v1.schema.source.js +9 -0
  89. package/src/schemas/core/interpretation/tiinex.interpretation.v1.capabilities.js +11 -0
  90. package/src/schemas/core/interpretation/tiinex.interpretation.v1.contract.js +40 -0
  91. package/src/schemas/core/interpretation/tiinex.interpretation.v1.en.i18n.json +9 -0
  92. package/src/schemas/core/interpretation/tiinex.interpretation.v1.findings.js +12 -0
  93. package/src/schemas/core/interpretation/tiinex.interpretation.v1.localMaterialization.js +89 -0
  94. package/src/schemas/core/interpretation/tiinex.interpretation.v1.presenter.js +8 -0
  95. package/src/schemas/core/interpretation/tiinex.interpretation.v1.schema.js +34 -0
  96. package/src/schemas/core/interpretation/tiinex.interpretation.v1.schema.json +23 -0
  97. package/src/schemas/core/interpretation/tiinex.interpretation.v1.schema.runtime.json +2029 -0
  98. package/src/schemas/core/interpretation/tiinex.interpretation.v1.schema.source.js +9 -0
  99. package/src/schemas/core/interpretation/tiinex.interpretation.v1.sv.i18n.json +9 -0
  100. package/src/schemas/core/interpretation/tiinex.interpretation.v1.transitions.js +1 -0
  101. package/src/schemas/core/interpretation/tiinex.interpretation.v1.validate.js +25 -0
  102. package/src/schemas/core/preservation/tiinex.preservation.v1.capabilities.js +14 -0
  103. package/src/schemas/core/preservation/tiinex.preservation.v1.en.i18n.json +6 -0
  104. package/src/schemas/core/preservation/tiinex.preservation.v1.findings.js +9 -0
  105. package/src/schemas/core/preservation/tiinex.preservation.v1.presenter.js +1 -0
  106. package/src/schemas/core/preservation/tiinex.preservation.v1.schema.js +31 -0
  107. package/src/schemas/core/preservation/tiinex.preservation.v1.schema.json +23 -0
  108. package/src/schemas/core/preservation/tiinex.preservation.v1.schema.runtime.json +2033 -0
  109. package/src/schemas/core/preservation/tiinex.preservation.v1.schema.source.js +9 -0
  110. package/src/schemas/core/preservation/tiinex.preservation.v1.sv.i18n.json +6 -0
  111. package/src/schemas/core/preservation/tiinex.preservation.v1.transitions.js +1 -0
  112. package/src/schemas/core/preservation/tiinex.preservation.v1.validate.js +10 -0
  113. package/src/schemas/core/relation/tiinex.relation.v1.capabilities.js +7 -0
  114. package/src/schemas/core/relation/tiinex.relation.v1.contract.js +3 -0
  115. package/src/schemas/core/relation/tiinex.relation.v1.en.i18n.json +4 -0
  116. package/src/schemas/core/relation/tiinex.relation.v1.findings.js +9 -0
  117. package/src/schemas/core/relation/tiinex.relation.v1.localMaterialization.js +153 -0
  118. package/src/schemas/core/relation/tiinex.relation.v1.presenter.js +3 -0
  119. package/src/schemas/core/relation/tiinex.relation.v1.schema.js +20 -0
  120. package/src/schemas/core/relation/tiinex.relation.v1.schema.json +23 -0
  121. package/src/schemas/core/relation/tiinex.relation.v1.schema.runtime.json +1668 -0
  122. package/src/schemas/core/relation/tiinex.relation.v1.schema.source.js +9 -0
  123. package/src/schemas/core/relation/tiinex.relation.v1.sv.i18n.json +4 -0
  124. package/src/schemas/core/relation/tiinex.relation.v1.transitions.js +1 -0
  125. package/src/schemas/core/relation/tiinex.relation.v1.validate.js +36 -0
  126. package/src/schemas/core/relation/workspace/representation/tiinex.workspace.representation.v1.capabilities.js +14 -0
  127. package/src/schemas/core/relation/workspace/representation/tiinex.workspace.representation.v1.contract.js +57 -0
  128. package/src/schemas/core/relation/workspace/representation/tiinex.workspace.representation.v1.en.i18n.json +4 -0
  129. package/src/schemas/core/relation/workspace/representation/tiinex.workspace.representation.v1.findings.js +13 -0
  130. package/src/schemas/core/relation/workspace/representation/tiinex.workspace.representation.v1.presenter.js +3 -0
  131. package/src/schemas/core/relation/workspace/representation/tiinex.workspace.representation.v1.schema.js +20 -0
  132. package/src/schemas/core/relation/workspace/representation/tiinex.workspace.representation.v1.schema.json +24 -0
  133. package/src/schemas/core/relation/workspace/representation/tiinex.workspace.representation.v1.schema.runtime.json +3315 -0
  134. package/src/schemas/core/relation/workspace/representation/tiinex.workspace.representation.v1.schema.source.js +9 -0
  135. package/src/schemas/core/relation/workspace/representation/tiinex.workspace.representation.v1.sv.i18n.json +4 -0
  136. package/src/schemas/core/relation/workspace/representation/tiinex.workspace.representation.v1.transitions.js +1 -0
  137. package/src/schemas/core/relation/workspace/representation/tiinex.workspace.representation.v1.validate.js +78 -0
  138. package/src/schemas/core/signal/tiinex.signal.v1.schema.js +14 -0
  139. package/src/schemas/core/signal/tiinex.signal.v1.schema.json +23 -0
  140. package/src/schemas/core/signal/tiinex.signal.v1.schema.runtime.json +1733 -0
  141. package/src/schemas/core/signal/tiinex.signal.v1.schema.source.js +9 -0
  142. package/src/schemas/core/task/tiinex.task.v1.capabilities.js +11 -0
  143. package/src/schemas/core/task/tiinex.task.v1.contract.js +3 -0
  144. package/src/schemas/core/task/tiinex.task.v1.en.i18n.json +15 -0
  145. package/src/schemas/core/task/tiinex.task.v1.findings.js +18 -0
  146. package/src/schemas/core/task/tiinex.task.v1.localMaterialization.js +148 -0
  147. package/src/schemas/core/task/tiinex.task.v1.presenter.js +8 -0
  148. package/src/schemas/core/task/tiinex.task.v1.schema.js +35 -0
  149. package/src/schemas/core/task/tiinex.task.v1.schema.json +23 -0
  150. package/src/schemas/core/task/tiinex.task.v1.schema.runtime.json +1708 -0
  151. package/src/schemas/core/task/tiinex.task.v1.schema.source.js +9 -0
  152. package/src/schemas/core/task/tiinex.task.v1.sv.i18n.json +15 -0
  153. package/src/schemas/core/task/tiinex.task.v1.transitions.js +3 -0
  154. package/src/schemas/core/task/tiinex.task.v1.validate.js +41 -0
  155. package/src/schemas/core/topic/tiinex.topic.v1.capabilities.js +14 -0
  156. package/src/schemas/core/topic/tiinex.topic.v1.creation.js +46 -0
  157. package/src/schemas/core/topic/tiinex.topic.v1.en.i18n.json +8 -0
  158. package/src/schemas/core/topic/tiinex.topic.v1.findings.js +11 -0
  159. package/src/schemas/core/topic/tiinex.topic.v1.localMaterialization.js +135 -0
  160. package/src/schemas/core/topic/tiinex.topic.v1.presenter.js +1 -0
  161. package/src/schemas/core/topic/tiinex.topic.v1.schema.js +34 -0
  162. package/src/schemas/core/topic/tiinex.topic.v1.schema.json +23 -0
  163. package/src/schemas/core/topic/tiinex.topic.v1.schema.runtime.json +1699 -0
  164. package/src/schemas/core/topic/tiinex.topic.v1.schema.source.js +9 -0
  165. package/src/schemas/core/topic/tiinex.topic.v1.sv.i18n.json +8 -0
  166. package/src/schemas/core/topic/tiinex.topic.v1.transitions.js +31 -0
  167. package/src/schemas/core/topic/tiinex.topic.v1.validate.js +11 -0
  168. package/src/schemas/creation.capability.js +289 -0
  169. package/src/schemas/creation.contracts.js +334 -0
  170. package/src/schemas/creation.executionSnapshot.js +79 -0
  171. package/src/schemas/creation.factoryQualification.js +73 -0
  172. package/src/schemas/creation.renderer.js +244 -0
  173. package/src/schemas/creation.representation.js +279 -0
  174. package/src/schemas/creation.rootMetadata.js +6 -0
  175. package/src/schemas/creation.schemaReferences.js +65 -0
  176. package/src/schemas/discovery/finding/tiinex.discovery.finding.v1.schema.js +14 -0
  177. package/src/schemas/discovery/finding/tiinex.discovery.finding.v1.schema.json +23 -0
  178. package/src/schemas/discovery/finding/tiinex.discovery.finding.v1.schema.runtime.json +1873 -0
  179. package/src/schemas/discovery/finding/tiinex.discovery.finding.v1.schema.source.js +9 -0
  180. package/src/schemas/discovery/tiinex.discovery.v1.schema.js +14 -0
  181. package/src/schemas/discovery/tiinex.discovery.v1.schema.json +23 -0
  182. package/src/schemas/discovery/tiinex.discovery.v1.schema.runtime.json +1839 -0
  183. package/src/schemas/discovery/tiinex.discovery.v1.schema.source.js +9 -0
  184. package/src/schemas/generic.artifact.module.js +25 -0
  185. package/src/schemas/party/organization/tiinex.party.organization.v1.schema.js +26 -0
  186. package/src/schemas/party/organization/tiinex.party.organization.v1.schema.json +23 -0
  187. package/src/schemas/party/organization/tiinex.party.organization.v1.schema.runtime.json +2249 -0
  188. package/src/schemas/party/organization/tiinex.party.organization.v1.schema.source.js +9 -0
  189. package/src/schemas/party/role/tiinex.party.role.v1.schema.js +26 -0
  190. package/src/schemas/party/role/tiinex.party.role.v1.schema.json +24 -0
  191. package/src/schemas/party/role/tiinex.party.role.v1.schema.runtime.json +2091 -0
  192. package/src/schemas/party/role/tiinex.party.role.v1.schema.source.js +9 -0
  193. package/src/schemas/presentation/surface/tiinex.presentation.surface.v1.capabilities.js +14 -0
  194. package/src/schemas/presentation/surface/tiinex.presentation.surface.v1.en.i18n.json +4 -0
  195. package/src/schemas/presentation/surface/tiinex.presentation.surface.v1.findings.js +1 -0
  196. package/src/schemas/presentation/surface/tiinex.presentation.surface.v1.presenter.js +1 -0
  197. package/src/schemas/presentation/surface/tiinex.presentation.surface.v1.schema.js +29 -0
  198. package/src/schemas/presentation/surface/tiinex.presentation.surface.v1.schema.json +21 -0
  199. package/src/schemas/presentation/surface/tiinex.presentation.surface.v1.schema.runtime.json +2180 -0
  200. package/src/schemas/presentation/surface/tiinex.presentation.surface.v1.schema.source.js +9 -0
  201. package/src/schemas/presentation/surface/tiinex.presentation.surface.v1.sv.i18n.json +4 -0
  202. package/src/schemas/presentation/surface/tiinex.presentation.surface.v1.transitions.js +1 -0
  203. package/src/schemas/presentation/surface/tiinex.presentation.surface.v1.validate.js +1 -0
  204. package/src/schemas/reduction/tiinex.reduction.v1.schema.js +26 -0
  205. package/src/schemas/reduction/tiinex.reduction.v1.schema.json +23 -0
  206. package/src/schemas/reduction/tiinex.reduction.v1.schema.runtime.json +1733 -0
  207. package/src/schemas/reduction/tiinex.reduction.v1.schema.source.js +9 -0
  208. package/src/schemas/reference.shapes.js +33 -0
  209. package/src/schemas/registry.js +36 -0
  210. package/src/schemas/resolver.js +13 -0
  211. package/src/schemas/schema/module/tiinex.schema.module.v1.capabilities.js +14 -0
  212. package/src/schemas/schema/module/tiinex.schema.module.v1.en.i18n.json +4 -0
  213. package/src/schemas/schema/module/tiinex.schema.module.v1.findings.js +1 -0
  214. package/src/schemas/schema/module/tiinex.schema.module.v1.presenter.js +1 -0
  215. package/src/schemas/schema/module/tiinex.schema.module.v1.schema.js +29 -0
  216. package/src/schemas/schema/module/tiinex.schema.module.v1.schema.json +21 -0
  217. package/src/schemas/schema/module/tiinex.schema.module.v1.schema.runtime.json +2093 -0
  218. package/src/schemas/schema/module/tiinex.schema.module.v1.schema.source.js +9 -0
  219. package/src/schemas/schema/module/tiinex.schema.module.v1.sv.i18n.json +4 -0
  220. package/src/schemas/schema/module/tiinex.schema.module.v1.transitions.js +1 -0
  221. package/src/schemas/schema/module/tiinex.schema.module.v1.validate.js +1 -0
  222. package/src/schemas/schema.factory.descriptor.js +104 -0
  223. package/src/schemas/schema.githubSourceTarget.js +131 -0
  224. package/src/schemas/schema.identity.js +10 -0
  225. package/src/schemas/schema.reference.js +133 -0
  226. package/src/schemas/schema.source.js +239 -0
  227. package/src/schemas/tiinex.root.v1.capabilities.js +14 -0
  228. package/src/schemas/tiinex.root.v1.classify.js +55 -0
  229. package/src/schemas/tiinex.root.v1.en.i18n.json +24 -0
  230. package/src/schemas/tiinex.root.v1.fallback.js +84 -0
  231. package/src/schemas/tiinex.root.v1.findings.js +19 -0
  232. package/src/schemas/tiinex.root.v1.presenter.js +5 -0
  233. package/src/schemas/tiinex.root.v1.schema.js +29 -0
  234. package/src/schemas/tiinex.root.v1.schema.json +24 -0
  235. package/src/schemas/tiinex.root.v1.schema.runtime.json +1574 -0
  236. package/src/schemas/tiinex.root.v1.schema.source.js +9 -0
  237. package/src/schemas/tiinex.root.v1.sv.i18n.json +24 -0
  238. package/src/schemas/tiinex.root.v1.transitions.js +1 -0
  239. package/src/schemas/tiinex.root.v1.validate.js +36 -0
  240. package/src/schemas/validation/finding/tiinex.validation.finding.v1.schema.js +14 -0
  241. package/src/schemas/validation/finding/tiinex.validation.finding.v1.schema.json +23 -0
  242. package/src/schemas/validation/finding/tiinex.validation.finding.v1.schema.runtime.json +2027 -0
  243. package/src/schemas/validation/finding/tiinex.validation.finding.v1.schema.source.js +9 -0
  244. package/src/schemas/validation/method/tiinex.validation.method.v1.schema.js +14 -0
  245. package/src/schemas/validation/method/tiinex.validation.method.v1.schema.json +23 -0
  246. package/src/schemas/validation/method/tiinex.validation.method.v1.schema.runtime.json +1848 -0
  247. package/src/schemas/validation/method/tiinex.validation.method.v1.schema.source.js +9 -0
  248. package/src/schemas/validation/report/tiinex.validation.report.v1.schema.js +14 -0
  249. package/src/schemas/validation/report/tiinex.validation.report.v1.schema.json +23 -0
  250. package/src/schemas/validation/report/tiinex.validation.report.v1.schema.runtime.json +2015 -0
  251. package/src/schemas/validation/report/tiinex.validation.report.v1.schema.source.js +9 -0
  252. package/src/schemas/workspace/tiinex.workspace.v1.capabilities.js +12 -0
  253. package/src/schemas/workspace/tiinex.workspace.v1.en.i18n.json +7 -0
  254. package/src/schemas/workspace/tiinex.workspace.v1.findings.js +5 -0
  255. package/src/schemas/workspace/tiinex.workspace.v1.presenter.js +27 -0
  256. package/src/schemas/workspace/tiinex.workspace.v1.schema.js +30 -0
  257. package/src/schemas/workspace/tiinex.workspace.v1.schema.json +23 -0
  258. package/src/schemas/workspace/tiinex.workspace.v1.schema.runtime.json +1596 -0
  259. package/src/schemas/workspace/tiinex.workspace.v1.schema.source.js +9 -0
  260. package/src/schemas/workspace/tiinex.workspace.v1.sv.i18n.json +7 -0
  261. package/src/schemas/workspace/tiinex.workspace.v1.transitions.js +10 -0
  262. package/src/schemas/workspace/tiinex.workspace.v1.validate.js +10 -0
  263. package/src/sources/github/github.issueTarget.js +127 -0
  264. package/src/sources/origin.references.js +249 -0
  265. package/src/sources/source.explicitTargets.js +49 -0
  266. package/src/sources/transport.levels.js +107 -0
  267. package/src/tooling/portable/adapters/cli/cli.cold-start-input.js +34 -0
  268. package/src/tooling/portable/adapters/cli/cli.command-input.js +455 -0
  269. package/src/tooling/portable/adapters/cli/cli.common-author.js +249 -0
  270. package/src/tooling/portable/adapters/cli/cli.common-output.js +330 -0
  271. package/src/tooling/portable/adapters/cli/cli.editor-assistance.js +13 -0
  272. package/src/tooling/portable/adapters/cli/cli.ground-materialize.js +96 -0
  273. package/src/tooling/portable/adapters/cli/cli.ground-recovery.js +99 -0
  274. package/src/tooling/portable/adapters/cli/cli.handoff-manufacture.js +345 -0
  275. package/src/tooling/portable/adapters/cli/cli.handoff-sibling-allocation.js +31 -0
  276. package/src/tooling/portable/adapters/cli/cli.help.js +80 -0
  277. package/src/tooling/portable/adapters/cli/cli.land.js +13 -0
  278. package/src/tooling/portable/adapters/cli/cli.local-output.js +72 -0
  279. package/src/tooling/portable/adapters/cli/cli.material-policy.js +6 -0
  280. package/src/tooling/portable/adapters/cli/cli.operator-bridge.js +18 -0
  281. package/src/tooling/portable/adapters/cli/cli.reduction-input.js +14 -0
  282. package/src/tooling/portable/adapters/cli/cli.run.js +434 -0
  283. package/src/tooling/portable/adapters/llm/llm.entrypoint.js +34 -0
  284. package/src/tooling/portable/adapters/node/checkpoint.verify.js +267 -0
  285. package/src/tooling/portable/adapters/node/handoff.manufacture.bootstrap.js +109 -0
  286. package/src/tooling/portable/adapters/node/handoff.manufacture.enumeration.js +94 -0
  287. package/src/tooling/portable/adapters/node/handoff.manufacture.js +193 -0
  288. package/src/tooling/portable/adapters/node/handoff.manufacture.multiRoot.js +49 -0
  289. package/src/tooling/portable/adapters/node/handoff.manufacture.packageParent.js +130 -0
  290. package/src/tooling/portable/adapters/node/handoff.manufacture.requirements.js +353 -0
  291. package/src/tooling/portable/adapters/node/handoff.manufacture.scope.js +147 -0
  292. package/src/tooling/portable/adapters/node/workspaceCarrier.manufacture.js +62 -0
  293. package/src/tooling/portable/assets/asset.operations.js +170 -0
  294. package/src/tooling/portable/audit/audit.capability.js +119 -0
  295. package/src/tooling/portable/bootstrap/artifact.result.selfverify.mjs +109 -0
  296. package/src/tooling/portable/bootstrap/bootstrap.case.mjs +43 -0
  297. package/src/tooling/portable/bootstrap/tiinex.llm.bootstrap.md +814 -0
  298. package/src/tooling/portable/bootstrap/tiinex.llm.bootstrap.pointer.json +25 -0
  299. package/src/tooling/portable/checkpoint/portable.checkpoint.js +89 -0
  300. package/src/tooling/portable/conformance/checkpoint.qualification.js +271 -0
  301. package/src/tooling/portable/draft/draft.create.js +389 -0
  302. package/src/tooling/portable/draft/draft.crud.js +175 -0
  303. package/src/tooling/portable/draft/draft.exact.js +173 -0
  304. package/src/tooling/portable/draft/draft.operations.js +265 -0
  305. package/src/tooling/portable/draft/draft.qualification.js +45 -0
  306. package/src/tooling/portable/draft/draft.set.js +193 -0
  307. package/src/tooling/portable/draft/draft.validation-context.js +7 -0
  308. package/src/tooling/portable/editor/authoring.parent.js +37 -0
  309. package/src/tooling/portable/editor/editor.assistance.js +221 -0
  310. package/src/tooling/portable/editor/staged.validation.js +96 -0
  311. package/src/tooling/portable/engine.facade.js +468 -0
  312. package/src/tooling/portable/findings.js +92 -0
  313. package/src/tooling/portable/grounding/grounding.capsule.js +128 -0
  314. package/src/tooling/portable/grounding/grounding.continuity.js +283 -0
  315. package/src/tooling/portable/grounding/grounding.participantAuthority.js +20 -0
  316. package/src/tooling/portable/grounding/grounding.planningContext.js +34 -0
  317. package/src/tooling/portable/grounding/grounding.readiness.authority.js +17 -0
  318. package/src/tooling/portable/grounding/grounding.readiness.js +316 -0
  319. package/src/tooling/portable/grounding/grounding.readiness.support.js +245 -0
  320. package/src/tooling/portable/grounding/grounding.sourceEvidence.js +71 -0
  321. package/src/tooling/portable/grounding/grounding.workContext.js +72 -0
  322. package/src/tooling/portable/grounding/grounding.workProvenance.js +153 -0
  323. package/src/tooling/portable/handoff/carrierLineage.js +214 -0
  324. package/src/tooling/portable/handoff/carrierProfile.js +54 -0
  325. package/src/tooling/portable/handoff/carrierProjection.js +193 -0
  326. package/src/tooling/portable/handoff/carrierProjection.routeQualification.js +228 -0
  327. package/src/tooling/portable/handoff/carrierProjection.shared.js +7 -0
  328. package/src/tooling/portable/handoff/carrierProjection.workspaces.js +54 -0
  329. package/src/tooling/portable/handoff/coldConsumerEntrypoint.js +185 -0
  330. package/src/tooling/portable/handoff/coldStartQualification.contract.js +184 -0
  331. package/src/tooling/portable/handoff/coldStartQualification.grounding.js +392 -0
  332. package/src/tooling/portable/handoff/coldStartQualification.js +22 -0
  333. package/src/tooling/portable/handoff/coldStartQualification.materials.js +364 -0
  334. package/src/tooling/portable/handoff/coldStartQualification.observation.js +220 -0
  335. package/src/tooling/portable/handoff/coldStartQualification.run.js +81 -0
  336. package/src/tooling/portable/handoff/coldStartQualification.shared.js +57 -0
  337. package/src/tooling/portable/handoff/coldStartRolePointers.js +39 -0
  338. package/src/tooling/portable/handoff/contextAudit.js +247 -0
  339. package/src/tooling/portable/handoff/contracts/tiinex.handoff.package.v1.schema.md +409 -0
  340. package/src/tooling/portable/handoff/handoffAuthoringPlan.js +35 -0
  341. package/src/tooling/portable/handoff/handoffEndpointProjection.js +61 -0
  342. package/src/tooling/portable/handoff/handoffLeafProjection.js +91 -0
  343. package/src/tooling/portable/handoff/humanOutputPresentation.js +21 -0
  344. package/src/tooling/portable/handoff/manufacture.js +84 -0
  345. package/src/tooling/portable/handoff/materialClosure.archiveV2.binding.js +72 -0
  346. package/src/tooling/portable/handoff/materialClosure.archiveV2.direct.js +160 -0
  347. package/src/tooling/portable/handoff/materialClosure.archiveV2.indexes.js +36 -0
  348. package/src/tooling/portable/handoff/materialClosure.archiveV2.js +247 -0
  349. package/src/tooling/portable/handoff/materialClosure.archiveV2.projectionProvider.js +44 -0
  350. package/src/tooling/portable/handoff/materialClosure.archiveV2.workspace.js +226 -0
  351. package/src/tooling/portable/handoff/materialClosure.descriptor.js +169 -0
  352. package/src/tooling/portable/handoff/materialClosure.inputBinding.js +372 -0
  353. package/src/tooling/portable/handoff/materialClosure.inputBinding.support.js +62 -0
  354. package/src/tooling/portable/handoff/materialClosure.materialized.js +143 -0
  355. package/src/tooling/portable/handoff/materialClosure.materials.js +116 -0
  356. package/src/tooling/portable/handoff/materialClosure.package.js +181 -0
  357. package/src/tooling/portable/handoff/materialClosure.plan.js +204 -0
  358. package/src/tooling/portable/handoff/materialClosure.readiness.js +36 -0
  359. package/src/tooling/portable/handoff/materialClosure.requirements.js +137 -0
  360. package/src/tooling/portable/handoff/operatorContextProjection.js +105 -0
  361. package/src/tooling/portable/handoff/pointerEntrypoint.js +138 -0
  362. package/src/tooling/portable/handoff/qualifiedHandoffFixture.js +34 -0
  363. package/src/tooling/portable/handoff/recipientV2.artifactFirst.build.js +321 -0
  364. package/src/tooling/portable/handoff/recipientV2.artifactFirst.closure.js +126 -0
  365. package/src/tooling/portable/handoff/recipientV2.artifactFirst.inspect.js +194 -0
  366. package/src/tooling/portable/handoff/recipientV2.artifactFirst.materials.js +207 -0
  367. package/src/tooling/portable/handoff/recipientV2.artifactFirst.projection.js +69 -0
  368. package/src/tooling/portable/handoff/recipientV2.artifactFirst.roles.js +166 -0
  369. package/src/tooling/portable/handoff/recipientV2.artifactFirst.routes.js +113 -0
  370. package/src/tooling/portable/handoff/recipientV2.artifactFirst.shared.js +87 -0
  371. package/src/tooling/portable/handoff/recipientV2.artifactFirst.workspaces.js +160 -0
  372. package/src/tooling/portable/handoff/recipientV2.artifactFirstPhase1.js +44 -0
  373. package/src/tooling/portable/handoff/recipientV2.artifactInspection.js +55 -0
  374. package/src/tooling/portable/handoff/recipientV2.artifacts.js +174 -0
  375. package/src/tooling/portable/handoff/recipientV2.coldProjection.js +24 -0
  376. package/src/tooling/portable/handoff/recipientV2.delivery.js +48 -0
  377. package/src/tooling/portable/handoff/recipientV2.endpointRolePointers.js +179 -0
  378. package/src/tooling/portable/handoff/recipientV2.entryContract.js +28 -0
  379. package/src/tooling/portable/handoff/recipientV2.humanOutput.js +78 -0
  380. package/src/tooling/portable/handoff/recipientV2.inspect.helpers.js +218 -0
  381. package/src/tooling/portable/handoff/recipientV2.inspect.js +194 -0
  382. package/src/tooling/portable/handoff/recipientV2.inspect.pathToken.js +9 -0
  383. package/src/tooling/portable/handoff/recipientV2.inspect.projection.js +58 -0
  384. package/src/tooling/portable/handoff/recipientV2.inspect.workspaces.js +177 -0
  385. package/src/tooling/portable/handoff/recipientV2.lineage.js +142 -0
  386. package/src/tooling/portable/handoff/recipientV2.packageV1.build.js +147 -0
  387. package/src/tooling/portable/handoff/recipientV2.packageV1.constants.js +4 -0
  388. package/src/tooling/portable/handoff/recipientV2.packageV1.contract.js +101 -0
  389. package/src/tooling/portable/handoff/recipientV2.packageV1.inspect.helpers.js +126 -0
  390. package/src/tooling/portable/handoff/recipientV2.packageV1.inspect.js +185 -0
  391. package/src/tooling/portable/handoff/recipientV2.packageV1.js +12 -0
  392. package/src/tooling/portable/handoff/recipientV2.packageV1.shared.js +24 -0
  393. package/src/tooling/portable/handoff/recipientV2.packageV1.workspaceProjection.js +22 -0
  394. package/src/tooling/portable/handoff/recipientV2.pointer.js +40 -0
  395. package/src/tooling/portable/handoff/recipientV2.routeSelection.js +16 -0
  396. package/src/tooling/portable/handoff/recipientV2.topology.helpers.js +20 -0
  397. package/src/tooling/portable/handoff/recipientV2.topology.js +320 -0
  398. package/src/tooling/portable/handoff/recipientV2.topology.materials.js +70 -0
  399. package/src/tooling/portable/handoff/recipientV2.topology.workspaces.js +193 -0
  400. package/src/tooling/portable/handoff/recipientV2.transportManifest.js +123 -0
  401. package/src/tooling/portable/handoff/recipientV2.workspaceRepresentation.js +163 -0
  402. package/src/tooling/portable/handoff/routeArtifactConformance.js +130 -0
  403. package/src/tooling/portable/handoff/toolingBootstrap.js +67 -0
  404. package/src/tooling/portable/handoff/transportCompanion.js +175 -0
  405. package/src/tooling/portable/handoff/workspaceByteProvider.archive.js +95 -0
  406. package/src/tooling/portable/handoff/workspaceByteProvider.js +271 -0
  407. package/src/tooling/portable/handoff/workspaceCarrier.manufacture.js +93 -0
  408. package/src/tooling/portable/handoff/workspaceLandingPlan.js +142 -0
  409. package/src/tooling/portable/handoff/workspacePackageSources.js +105 -0
  410. package/src/tooling/portable/handoff/workspaceQualifiedReference.js +10 -0
  411. package/src/tooling/portable/handoff/workspaceSourceIdentity.js +52 -0
  412. package/src/tooling/portable/handoff/workspaceTargetConformance.js +134 -0
  413. package/src/tooling/portable/host/host.capabilities.js +181 -0
  414. package/src/tooling/portable/host/tool.bindings.js +357 -0
  415. package/src/tooling/portable/host/tool.receiptNormalization.js +141 -0
  416. package/src/tooling/portable/index.js +52 -0
  417. package/src/tooling/portable/input/node.input.js +184 -0
  418. package/src/tooling/portable/input/portable.input.js +249 -0
  419. package/src/tooling/portable/lifecycle/lifecycle.action.js +11 -0
  420. package/src/tooling/portable/lifecycle/lifecycle.material.js +173 -0
  421. package/src/tooling/portable/lifecycle/lifecycle.operations.js +34 -0
  422. package/src/tooling/portable/lifecycle/lifecycle.readiness.js +247 -0
  423. package/src/tooling/portable/lineage/lineage.integrity.apply.audit.js +22 -0
  424. package/src/tooling/portable/lineage/lineage.integrity.apply.evidence.js +36 -0
  425. package/src/tooling/portable/lineage/lineage.integrity.apply.js +306 -0
  426. package/src/tooling/portable/lineage/lineage.integrity.apply.structure.js +178 -0
  427. package/src/tooling/portable/lineage/lineage.integrity.plan.js +377 -0
  428. package/src/tooling/portable/lineage/lineage.integrity.projection.human.js +82 -0
  429. package/src/tooling/portable/lineage/lineage.integrity.projection.js +349 -0
  430. package/src/tooling/portable/lineage/lineage.operations.js +32 -0
  431. package/src/tooling/portable/lineage/lineage.print.js +398 -0
  432. package/src/tooling/portable/lineage/lineage.print.render.js +88 -0
  433. package/src/tooling/portable/lineage/lineage.print.utils.js +58 -0
  434. package/src/tooling/portable/lineage/lineage.publicationProviderReceipts.js +141 -0
  435. package/src/tooling/portable/lineage/lineage.publicationQualification.js +183 -0
  436. package/src/tooling/portable/lineage/lineage.search.js +301 -0
  437. package/src/tooling/portable/live/live.artifact.js +192 -0
  438. package/src/tooling/portable/live/live.export.js +107 -0
  439. package/src/tooling/portable/live/live.lineage.closure.js +71 -0
  440. package/src/tooling/portable/live/live.lineage.js +338 -0
  441. package/src/tooling/portable/live/live.protocol.js +181 -0
  442. package/src/tooling/portable/materialization/durable.materialize.js +162 -0
  443. package/src/tooling/portable/materialization/epistemic.plan.js +239 -0
  444. package/src/tooling/portable/materialization/loaded.parent.js +54 -0
  445. package/src/tooling/portable/materialization/materialization.facade.js +30 -0
  446. package/src/tooling/portable/operation.catalog.js +393 -0
  447. package/src/tooling/portable/operation.catalog.package.js +183 -0
  448. package/src/tooling/portable/operation.result.js +25 -0
  449. package/src/tooling/portable/orchestration/task.prepare.js +191 -0
  450. package/src/tooling/portable/output/artifact.result.package.js +308 -0
  451. package/src/tooling/portable/output/deterministic.zip.js +88 -0
  452. package/src/tooling/portable/output/node.artifact-set.js +223 -0
  453. package/src/tooling/portable/output/node.draft.js +41 -0
  454. package/src/tooling/portable/output/node.zip.js +39 -0
  455. package/src/tooling/portable/output/recipientV2.zip.js +59 -0
  456. package/src/tooling/portable/overview/blockingCue.js +16 -0
  457. package/src/tooling/portable/overview/operatingOverview.js +413 -0
  458. package/src/tooling/portable/package/generation.binding.js +314 -0
  459. package/src/tooling/portable/package/generation.binding.projection.js +128 -0
  460. package/src/tooling/portable/package/material.graph.js +236 -0
  461. package/src/tooling/portable/package/runtime.package.js +321 -0
  462. package/src/tooling/portable/package/schema.transition.companion.js +196 -0
  463. package/src/tooling/portable/package/semantic.package.graph.js +272 -0
  464. package/src/tooling/portable/package/semantic.package.js +203 -0
  465. package/src/tooling/portable/package/semantic.package.schema-resolution.js +158 -0
  466. package/src/tooling/portable/package/semantic.package.transition-registry.js +189 -0
  467. package/src/tooling/portable/package/semantic.package.types.js +18 -0
  468. package/src/tooling/portable/providers/schema.bootstrap.provenance.js +10 -0
  469. package/src/tooling/portable/providers/schema.provider.qualification.js +52 -0
  470. package/src/tooling/portable/providers/schema.providers.js +458 -0
  471. package/src/tooling/portable/publication/runtime.publication.js +53 -0
  472. package/src/tooling/portable/qualification.js +150 -0
  473. package/src/tooling/portable/reduction/reduction.composition.js +229 -0
  474. package/src/tooling/portable/reduction/reduction.eligibility.helpers.js +258 -0
  475. package/src/tooling/portable/reduction/reduction.eligibility.js +191 -0
  476. package/src/tooling/portable/reduction/reduction.operations.js +30 -0
  477. package/src/tooling/portable/reduction/reduction.preflight.js +85 -0
  478. package/src/tooling/portable/reduction/reduction.shared.js +173 -0
  479. package/src/tooling/portable/schema/bootstrap/canonical.pack.js +24 -0
  480. package/src/tooling/portable/schema/bootstrap/docs-3988951208eb9a8926e84ab42625d4b42fa00c2d/party/role/tiinex.party.role.v1.schema.md +289 -0
  481. package/src/tooling/portable/schema/bootstrap/docs-3988951208eb9a8926e84ab42625d4b42fa00c2d/validation/report/tiinex.validation.report.v1.schema.md +300 -0
  482. package/src/tooling/portable/schema/bootstrap/qualified-local-root/tiinex.root.v1.runtime-projection.json +48 -0
  483. package/src/tooling/portable/schema/bootstrap/qualified-local-root/tiinex.root.v1.schema.md +865 -0
  484. package/src/tooling/portable/schema/contract.compile.js +406 -0
  485. package/src/tooling/portable/schema/contract.compile.utils.js +9 -0
  486. package/src/tooling/portable/schema/contract.constraints.js +117 -0
  487. package/src/tooling/portable/schema/contract.envelope.validate.js +177 -0
  488. package/src/tooling/portable/schema/contract.field-domain.compile.js +399 -0
  489. package/src/tooling/portable/schema/contract.field-domain.js +247 -0
  490. package/src/tooling/portable/schema/contract.field-shape.compile.js +34 -0
  491. package/src/tooling/portable/schema/contract.inheritance.inline.js +103 -0
  492. package/src/tooling/portable/schema/contract.inheritance.js +210 -0
  493. package/src/tooling/portable/schema/contract.inheritance.record.js +76 -0
  494. package/src/tooling/portable/schema/contract.machine-shape.js +309 -0
  495. package/src/tooling/portable/schema/contract.project.js +81 -0
  496. package/src/tooling/portable/schema/contract.semantic-resolution.js +82 -0
  497. package/src/tooling/portable/schema/contract.validate.js +0 -0
  498. package/src/tooling/portable/schema/lexical.shape.v1.js +338 -0
  499. package/src/tooling/portable/schema/llm.companion.js +108 -0
  500. package/src/tooling/portable/schema/named.declarations.js +162 -0
  501. package/src/tooling/portable/schema/ordinary.contract.js +193 -0
  502. package/src/tooling/portable/schema/ordinary.fields.js +205 -0
  503. package/src/tooling/portable/schema/qualifiedLocalRoot.projection.js +70 -0
  504. package/src/tooling/portable/schema/qualifiedLocalRoot.runtime.js +170 -0
  505. package/src/tooling/portable/schema/schema.contract.js +465 -0
  506. package/src/tooling/portable/schema/schema.guide.js +326 -0
  507. package/src/tooling/portable/schema/schema.snapshot.js +119 -0
  508. package/src/tooling/portable/session/portable.session.js +145 -0
  509. package/src/tooling/portable/transfer/transfer.plan.js +102 -0
  510. package/src/transitions/record.transitions.js +484 -0
  511. package/src/transitions/transition.validate.js +129 -0
  512. package/src/validation/findings.js +76 -0
  513. package/src/validation/validateArtifact.js +216 -0
  514. package/src/workspaces/workspace.entrypointCapability.js +44 -0
  515. package/src/workspaces/workspace.materialRole.js +242 -0
  516. package/src/workspaces/workspace.recordPaths.js +426 -0
  517. package/tools/tiinex-portable.mjs +6 -0
@@ -0,0 +1,44 @@
1
+ import { HANDOFF_WORKSPACE_BYTE_PROVIDER_SCHEMA_ID } from './workspaceByteProvider.js';
2
+
3
+ export function buildDirectArchiveProjectionProvider(records = []) {
4
+ const workspaces = records.map(({ workspace = {}, binding = {}, qualified = {}, archiveFile = null } = {}) => {
5
+ const archivePath = String(binding.representation?.packagePath || archiveFile?.path || '');
6
+ const entries = (qualified.entries || []).map((entry) => deepFreeze({
7
+ path: String(entry.path || ''),
8
+ innerPath: String(entry.path || ''),
9
+ archivePackagePath: archivePath,
10
+ packagePath: archivePath,
11
+ bytes: Number(entry.bytes || 0),
12
+ sha256: String(entry.sha256 || ''),
13
+ referenceTarget: String(entry.referenceTarget || ''),
14
+ data: entry.data
15
+ }));
16
+ return deepFreeze({
17
+ state: 'qualified',
18
+ id: String(workspace.id || ''),
19
+ title: String(workspace.title || workspace.id || ''),
20
+ mode: 'archive',
21
+ materialization: workspace,
22
+ entries: Object.freeze(entries),
23
+ workspaceTarget: deepFreeze({ ...(binding.workspaceTarget || {}), data: qualified.target?.data || new Uint8Array() }),
24
+ archive: deepFreeze({ ...(binding.representation || {}), data: archiveFile?.data || new Uint8Array() }),
25
+ binding,
26
+ reasons: Object.freeze([]),
27
+ authority: Object.freeze({ locatorAuthority: false, filenameAuthority: false, packagePlacementAuthority: false, bindingAuthority: 'manufacture-local-exact-qualified-workspace-source-plus-new-archive-byte-identity' })
28
+ });
29
+ });
30
+ return deepFreeze({
31
+ schema: HANDOFF_WORKSPACE_BYTE_PROVIDER_SCHEMA_ID,
32
+ status: workspaces.length && workspaces.every((workspace) => workspace.state === 'qualified') ? 'ready' : 'blocked',
33
+ workspaces: Object.freeze(workspaces),
34
+ findings: Object.freeze([]),
35
+ boundary: 'Manufacture-local projection provider only. It reuses already exact-qualified source bytes solely to construct the disposable carrier projection; serialized-byte closure verification independently reconstructs the authoritative archive provider.'
36
+ });
37
+ }
38
+
39
+ function deepFreeze(value) {
40
+ if (!value || typeof value !== 'object' || Object.isFrozen(value)) return value;
41
+ if (ArrayBuffer.isView(value) || value instanceof ArrayBuffer) return value;
42
+ for (const child of Object.values(value)) deepFreeze(child);
43
+ return Object.freeze(value);
44
+ }
@@ -0,0 +1,226 @@
1
+ import { packageFileByteView, packageFileBytes, sha256Hex, utf8Bytes } from '../../../export/package.bytes.js';
2
+ import { normalizeHandoffWorkspaceInnerPath } from './workspaceByteProvider.js';
3
+ import { qualifyHandoffWorkspaceTarget } from './workspaceTargetConformance.js';
4
+
5
+ export function qualifyWorkspaceForArchive(workspace = {}, byPath = new Map(), targetDeclarations = [], parentCandidates = []) {
6
+ const findings = [];
7
+ const workspaceId = String(workspace.id || '');
8
+ if (!workspaceId) findings.push(finding('error', 'portable.handoff-v2.workspace.id.unresolved', 'Archive-backed workspace binding requires an exact carrier workspace id.'));
9
+ const coverage = workspaceCoverage(workspace);
10
+ const evidence = workspaceEvidence(workspace, coverage);
11
+ if (!coverage || String(workspace.qualification || '') !== 'qualified' || String(workspace.correlationStatus || '') !== 'qualified' || String(evidence.state || '') !== 'qualified') findings.push(finding('error', 'portable.handoff-v2.workspace.coverage.unqualified', 'Archive-backed workspace representation requires explicit qualified complete or bounded entry-set evidence.', { workspaceId, coverage }));
12
+ if (targetDeclarations.length !== 1) {
13
+ findings.push(finding('error', targetDeclarations.length > 1 ? 'portable.handoff-v2.workspace-target.ambiguous' : 'portable.handoff-v2.workspace-target.missing', targetDeclarations.length > 1 ? 'More than one explicit Workspace target was declared for the carrier workspace id; v2 refuses ambiguous semantic binding.' : 'No explicit exact Workspace artifact target was declared for the carrier workspace id; v2 refuses filename/content scanning or transport-only semantic Workspace identity.', { workspaceId, targetCount: targetDeclarations.length }));
14
+ return blocked(workspaceId, findings);
15
+ }
16
+ const targetNormalized = normalizeHandoffWorkspaceInnerPath(targetDeclarations[0].path || '');
17
+ if (targetNormalized.state !== 'qualified') {
18
+ findings.push(finding('error', `portable.handoff-v2.${targetNormalized.reason || 'workspace-target-path-unsafe'}`, 'Explicit Workspace target locator is not a safe normalized workspace-relative path.', { workspaceId, path: targetDeclarations[0].path || '' }));
19
+ return blocked(workspaceId, findings);
20
+ }
21
+ if (!/\.workspace\.md$/i.test(targetNormalized.path)) {
22
+ findings.push(finding('error', 'portable.handoff-v2.workspace-target.path-contract-mismatch', 'Explicit Workspace target must identify a .workspace.md artifact under the tiinex.workspace.v1 artifact contract; schema-material filenames do not qualify as Workspace instances.', { workspaceId, path: targetNormalized.path }));
23
+ return blocked(workspaceId, findings);
24
+ }
25
+
26
+ const entries = qualifyWorkspaceEntries(workspace, byPath, workspaceId, findings);
27
+ const evidenceFingerprint = sha256Hex(utf8Bytes(stableJson(entries.map(projectEntryIdentity))));
28
+ if (String(evidence.entriesFingerprint || '') !== evidenceFingerprint || Number(evidence.entryCount || -1) !== entries.length || Number(evidence.totalBytes || -1) !== entries.reduce((sum, entry) => sum + entry.bytes, 0)) findings.push(finding('error', `portable.handoff-v2.workspace.${coverage}-evidence.stale`, 'Workspace coverage evidence does not exactly cover the archive entry set.', { workspaceId, coverage }));
29
+
30
+ const targetEntry = entries.find((entry) => entry.path === targetNormalized.path) || null;
31
+ if (!targetEntry) findings.push(finding('error', 'portable.handoff-v2.workspace-target.unresolvable', 'Explicit Workspace target is not present exactly once in the qualified Workspace Representation entry set.', { workspaceId, path: targetNormalized.path }));
32
+ const targetQualification = targetEntry ? qualifyHandoffWorkspaceTarget({ targetPath: targetNormalized.path, targetData: targetEntry.data, entries, parentCandidates }) : null;
33
+ if (targetQualification?.state !== 'qualified') {
34
+ for (const reason of targetQualification?.reasons || ['workspace-target-artifact-conformance-unqualified']) findings.push(workspaceTargetFinding(reason, workspaceId, targetNormalized.path));
35
+ }
36
+ const target = targetEntry && targetQualification?.state === 'qualified'
37
+ ? Object.freeze({ ...targetEntry, selfIntegrity: targetQualification.selfIntegrity, conformance: targetQualification.conformance })
38
+ : null;
39
+ return deepFreeze({ status: findings.some((item) => item.severity === 'error') ? 'blocked' : 'qualified', workspaceId, entries: Object.freeze(entries), target, findings: Object.freeze(findings) });
40
+ }
41
+
42
+
43
+ export function qualifyDirectWorkspaceForArchive(workspace = {}, rawWorkspace = null, targetDeclarations = [], parentCandidates = []) {
44
+ const findings = [];
45
+ const workspaceId = String(workspace.id || '');
46
+ if (!workspaceId) findings.push(finding('error', 'portable.handoff-v2.workspace.id.unresolved', 'Archive-backed workspace binding requires an exact carrier workspace id.'));
47
+ if (!rawWorkspace || typeof rawWorkspace !== 'object') {
48
+ findings.push(finding('error', 'portable.handoff-v2.workspace-direct-source.unavailable', 'Direct archive-backed manufacture requires the exact already-qualified workspace materialization bytes correlated to this closure workspace.', { workspaceId }));
49
+ return blocked(workspaceId, findings);
50
+ }
51
+ const coverage = workspaceCoverage(workspace);
52
+ const evidence = workspaceEvidence(workspace, coverage);
53
+ if (!coverage || String(workspace.qualification || '') !== 'qualified' || String(workspace.correlationStatus || '') !== 'qualified' || String(evidence.state || '') !== 'qualified') {
54
+ findings.push(finding('error', 'portable.handoff-v2.workspace.coverage.unqualified', 'Archive-backed workspace representation requires explicit qualified complete or bounded entry-set evidence.', { workspaceId, coverage }));
55
+ }
56
+ if (targetDeclarations.length !== 1) {
57
+ findings.push(finding('error', targetDeclarations.length > 1 ? 'portable.handoff-v2.workspace-target.ambiguous' : 'portable.handoff-v2.workspace-target.missing', targetDeclarations.length > 1 ? 'More than one explicit Workspace target was declared for the carrier workspace id; v2 refuses ambiguous semantic binding.' : 'No explicit exact Workspace artifact target was declared for the carrier workspace id; v2 refuses filename/content scanning or transport-only semantic Workspace identity.', { workspaceId, targetCount: targetDeclarations.length }));
58
+ return blocked(workspaceId, findings);
59
+ }
60
+ const targetNormalized = normalizeHandoffWorkspaceInnerPath(targetDeclarations[0].path || '');
61
+ if (targetNormalized.state !== 'qualified') {
62
+ findings.push(finding('error', `portable.handoff-v2.${targetNormalized.reason || 'workspace-target-path-unsafe'}`, 'Explicit Workspace target locator is not a safe normalized workspace-relative path.', { workspaceId, path: targetDeclarations[0].path || '' }));
63
+ return blocked(workspaceId, findings);
64
+ }
65
+ if (!/\.workspace\.md$/i.test(targetNormalized.path)) {
66
+ findings.push(finding('error', 'portable.handoff-v2.workspace-target.path-contract-mismatch', 'Explicit Workspace target must identify a .workspace.md artifact under the tiinex.workspace.v1 artifact contract; schema-material filenames do not qualify as Workspace instances.', { workspaceId, path: targetNormalized.path }));
67
+ return blocked(workspaceId, findings);
68
+ }
69
+
70
+ const rawEvidence = workspaceEvidence(rawWorkspace, coverage);
71
+ const declaredEvidence = evidence;
72
+ const evidenceMatches = workspaceCoverage(rawWorkspace) === coverage
73
+ && String(rawEvidence.state || '') === 'qualified'
74
+ && String(rawEvidence.entriesFingerprint || '') === String(declaredEvidence.entriesFingerprint || '')
75
+ && Number(rawEvidence.entryCount ?? -1) === Number(declaredEvidence.entryCount ?? -2)
76
+ && Number(rawEvidence.totalBytes ?? -1) === Number(declaredEvidence.totalBytes ?? -2);
77
+ if (!evidenceMatches) findings.push(finding('error', 'portable.handoff-v2.workspace-direct-source.coverage-evidence-mismatch', 'Direct Workspace source does not carry the same qualified complete-or-bounded evidence as the correlated closure Workspace.', { workspaceId, coverage }));
78
+
79
+ const declaredByPath = new Map();
80
+ for (const declared of workspace.includedEntries || []) {
81
+ const normalized = normalizeHandoffWorkspaceInnerPath(declared.path || '');
82
+ if (normalized.state !== 'qualified') {
83
+ findings.push(finding('error', `portable.handoff-v2.${normalized.reason || 'workspace-inner-path-unsafe'}`, 'Qualified Workspace Representation declaration contains an unsafe path.', { workspaceId, path: declared.path || '' }));
84
+ continue;
85
+ }
86
+ if (declaredByPath.has(normalized.path)) {
87
+ findings.push(finding('error', 'portable.handoff-v2.workspace-inner-path-duplicate', 'Qualified Workspace Representation declaration contains duplicate normalized inner paths.', { workspaceId, path: normalized.path }));
88
+ continue;
89
+ }
90
+ declaredByPath.set(normalized.path, Object.freeze({ ...declared, path: normalized.path }));
91
+ }
92
+
93
+ const rawByPath = new Map();
94
+ for (const raw of rawWorkspace.entries || []) {
95
+ const normalized = normalizeHandoffWorkspaceInnerPath(raw.path || '');
96
+ if (normalized.state !== 'qualified') {
97
+ findings.push(finding('error', `portable.handoff-v2.${normalized.reason || 'workspace-inner-path-unsafe'}`, 'Direct workspace source contains an unsafe path that cannot enter an archive-backed provider.', { workspaceId, path: raw.path || '' }));
98
+ continue;
99
+ }
100
+ if (rawByPath.has(normalized.path)) {
101
+ findings.push(finding('error', 'portable.handoff-v2.workspace-inner-path-duplicate', 'Direct workspace source contains duplicate normalized inner paths.', { workspaceId, path: normalized.path }));
102
+ continue;
103
+ }
104
+ const data = packageFileByteView(raw);
105
+ const bytes = data.byteLength;
106
+ const declaredBytes = Number(raw.bytes ?? -1);
107
+ const sha256 = String(raw.sha256 || '');
108
+ if (declaredBytes !== bytes || !/^[0-9a-f]{64}$/i.test(sha256)) {
109
+ findings.push(finding('error', 'portable.handoff-v2.workspace-direct-source.identity-unqualified', 'Direct Workspace source entry lacks the exact prequalified byte identity produced by Workspace enumeration.', { workspaceId, path: normalized.path }));
110
+ }
111
+ rawByPath.set(normalized.path, Object.freeze({ path: normalized.path, data, bytes, sha256, referenceTarget: String(raw.referenceTarget || '') }));
112
+ }
113
+
114
+ const entries = [];
115
+ for (const [declaredPath, declared] of declaredByPath) {
116
+ const raw = rawByPath.get(declaredPath);
117
+ if (!raw) {
118
+ findings.push(finding('error', 'portable.handoff-v2.workspace-direct-source.entry-missing', 'Qualified Workspace Representation declaration is missing from the direct source byte set.', { workspaceId, path: declaredPath }));
119
+ continue;
120
+ }
121
+ if (Number(declared.bytes || 0) !== raw.bytes || String(declared.sha256 || '') !== raw.sha256) {
122
+ findings.push(finding('error', 'portable.handoff-v2.workspace-direct-source.identity-mismatch', 'Direct workspace source prequalified byte identity diverges from the qualified complete-workspace declaration.', { workspaceId, path: declaredPath }));
123
+ }
124
+ entries.push(Object.freeze({ path: declaredPath, packagePath: '', bytes: raw.bytes, sha256: raw.sha256, referenceTarget: String(declared.referenceTarget || ''), data: raw.data }));
125
+ }
126
+ for (const rawPath of rawByPath.keys()) {
127
+ if (!declaredByPath.has(rawPath)) findings.push(finding('error', 'portable.handoff-v2.workspace-direct-source.entry-extra', 'Direct workspace source contains bytes outside the qualified complete-workspace declaration.', { workspaceId, path: rawPath }));
128
+ }
129
+ entries.sort((a, b) => a.path.localeCompare(b.path));
130
+
131
+ const evidenceFingerprint = sha256Hex(utf8Bytes(stableJson(entries.map(projectEntryIdentity))));
132
+ const totalBytes = entries.reduce((sum, entry) => sum + entry.bytes, 0);
133
+ if (String(declaredEvidence.entriesFingerprint || '') !== evidenceFingerprint || Number(declaredEvidence.entryCount ?? -1) !== entries.length || Number(declaredEvidence.totalBytes ?? -1) !== totalBytes) {
134
+ findings.push(finding('error', `portable.handoff-v2.workspace.${coverage}-evidence.stale`, 'Workspace coverage evidence does not exactly cover the direct archive entry identity set.', { workspaceId, coverage }));
135
+ }
136
+
137
+ const targetEntry = entries.find((entry) => entry.path === targetNormalized.path) || null;
138
+ if (!targetEntry) findings.push(finding('error', 'portable.handoff-v2.workspace-target.unresolvable', 'Explicit Workspace target is not present exactly once in the qualified Workspace Representation entry set.', { workspaceId, path: targetNormalized.path }));
139
+ const targetQualification = targetEntry ? qualifyHandoffWorkspaceTarget({ targetPath: targetNormalized.path, targetData: targetEntry.data, entries, parentCandidates }) : null;
140
+ if (targetQualification?.state !== 'qualified') {
141
+ for (const reason of targetQualification?.reasons || ['workspace-target-artifact-conformance-unqualified']) findings.push(workspaceTargetFinding(reason, workspaceId, targetNormalized.path));
142
+ }
143
+ const target = targetEntry && targetQualification?.state === 'qualified'
144
+ ? Object.freeze({ ...targetEntry, selfIntegrity: targetQualification.selfIntegrity, conformance: targetQualification.conformance })
145
+ : null;
146
+ return deepFreeze({ status: findings.some((item) => item.severity === 'error') ? 'blocked' : 'qualified', workspaceId, entries: Object.freeze(entries), target, findings: Object.freeze(findings) });
147
+ }
148
+
149
+ function workspaceCoverage(workspace = {}) {
150
+ const value = String(workspace.materialization || workspace.state || '');
151
+ return value === 'complete' || value === 'bounded' ? value : '';
152
+ }
153
+ function workspaceEvidence(workspace = {}, coverage = workspaceCoverage(workspace)) {
154
+ return coverage === 'bounded' ? (workspace.scopeEvidence || {}) : coverage === 'complete' ? (workspace.completenessEvidence || {}) : {};
155
+ }
156
+
157
+ function safeToken(value = '') { return String(value || '').trim().replace(/[^a-zA-Z0-9._-]+/g, '-').replace(/^-+|-+$/g, '').slice(0, 100) || 'workspace'; }
158
+
159
+ export function indexWorkspaceTargetDeclarations(value = []) {
160
+ const map = new Map();
161
+ const items = Array.isArray(value) ? value : (value && typeof value === 'object' ? Object.entries(value).map(([workspaceId, path]) => ({ workspaceId, path: typeof path === 'string' ? path : path?.path })) : []);
162
+ for (const item of items) {
163
+ const workspaceId = String(item?.workspaceId || item?.workspace || item?.id || '').trim();
164
+ const path = String(item?.path || item?.workspaceTargetPath || item?.workspaceArtifactPath || '').trim();
165
+ if (!workspaceId || !path) continue;
166
+ const list = map.get(workspaceId) || [];
167
+ list.push(Object.freeze({ workspaceId, path }));
168
+ map.set(workspaceId, list);
169
+ }
170
+ return map;
171
+ }
172
+
173
+ export function mapArchiveRequirements(requirements = {}, materialized = [], bindingByWorkspace = new Map()) {
174
+ const carrierByRequirement = new Map(materialized.map((entry) => [String(entry.requirementId || ''), entry]));
175
+ const mapOne = (item) => {
176
+ const carrier = carrierByRequirement.get(String(item.requirementId || ''));
177
+ if (!carrier || carrier.carrierKind !== 'workspace-archive-entry') return item;
178
+ const binding = bindingByWorkspace.get(carrier.workspaceId);
179
+ return deepFreeze({ ...item, materializedPackagePath: String(binding?.representation?.packagePath || ''), materializedCarrier: Object.freeze({ kind: 'workspace-archive-entry', workspaceId: carrier.workspaceId, workspaceRelativePath: carrier.workspaceRelativePath, archivePackagePath: String(binding?.representation?.packagePath || '') }) });
180
+ };
181
+ return Object.freeze({
182
+ required: Object.freeze((requirements.required || []).map(mapOne)),
183
+ reference: Object.freeze((requirements.reference || []).map(mapOne)),
184
+ endpointRoles: Object.freeze((requirements.endpointRoles || []).map(mapOne)),
185
+ participantRoles: Object.freeze((requirements.participantRoles || []).map(mapOne)),
186
+ dependencies: Object.freeze((requirements.dependencies || []).map(mapOne))
187
+ });
188
+ }
189
+
190
+ function qualifyWorkspaceEntries(workspace, byPath, workspaceId, findings) {
191
+ const entries = [];
192
+ const seen = new Set();
193
+ for (const declared of workspace.includedEntries || []) {
194
+ const normalized = normalizeHandoffWorkspaceInnerPath(declared.path || '');
195
+ if (normalized.state !== 'qualified') { findings.push(finding('error', `portable.handoff-v2.${normalized.reason || 'workspace-inner-path-unsafe'}`, 'Workspace contains an unsafe path that cannot enter an archive-backed provider.', { workspaceId, path: declared.path || '' })); continue; }
196
+ if (seen.has(normalized.path)) { findings.push(finding('error', 'portable.handoff-v2.workspace-inner-path-duplicate', 'Workspace contains duplicate normalized inner paths.', { workspaceId, path: normalized.path })); continue; }
197
+ seen.add(normalized.path);
198
+ const packagePath = String(declared.packagePath || '');
199
+ const matches = byPath.get(packagePath) || [];
200
+ const file = matches.length === 1 ? matches[0] : null;
201
+ if (!file) { findings.push(finding('error', 'portable.handoff-v2.workspace-entry.unresolvable', 'Qualified v1 workspace entry is not uniquely resolvable to exact package bytes.', { workspaceId, path: normalized.path, packagePath })); continue; }
202
+ const data = packageFileBytes(file);
203
+ const sha256 = sha256Hex(data);
204
+ if (Number(declared.bytes || 0) !== data.byteLength || String(declared.sha256 || '') !== sha256) findings.push(finding('error', 'portable.handoff-v2.workspace-entry.identity-mismatch', 'Workspace entry byte identity diverges from the v1 closure declaration.', { workspaceId, path: normalized.path }));
205
+ entries.push(Object.freeze({ path: normalized.path, packagePath, bytes: data.byteLength, sha256, referenceTarget: String(declared.referenceTarget || ''), data }));
206
+ }
207
+ return entries.sort((a, b) => a.path.localeCompare(b.path));
208
+ }
209
+
210
+ function projectEntryIdentity(entry) { return { path: entry.path, bytes: entry.bytes, sha256: entry.sha256, referenceTarget: entry.referenceTarget }; }
211
+ function workspaceTargetFinding(reason, workspaceId, path) {
212
+ const code = `portable.handoff-v2.${String(reason || 'workspace-target-artifact-conformance-unqualified')}`;
213
+ const messages = {
214
+ 'workspace-target-schema-unqualified': 'Explicit Workspace target does not qualify as tiinex.workspace.v1 under exact registered schema authority.',
215
+ 'workspace-target-self-integrity-unverified': 'Explicit Workspace target does not have verified primary c14n-v2 self integrity.',
216
+ 'workspace-target-self-integrity-mismatch': 'Explicit Workspace target primary c14n-v2 self integrity does not match its exact bytes.',
217
+ 'workspace-target-parent-continuity-unqualified': 'Explicit Workspace target declares Parent but its Parent-target continuity cannot be independently verified.',
218
+ 'workspace-target-artifact-conformance-unqualified': 'Explicit Workspace target fails Root/registered-schema/integrity artifact conformance.'
219
+ };
220
+ return finding('error', code, messages[reason] || messages['workspace-target-artifact-conformance-unqualified'], { workspaceId, path });
221
+ }
222
+ function blocked(workspaceId, findings) { return deepFreeze({ status: 'blocked', workspaceId, entries: Object.freeze([]), target: null, findings: Object.freeze(findings) }); }
223
+ function stableJson(value) { return JSON.stringify(sortJson(value)); }
224
+ function sortJson(value) { if (Array.isArray(value)) return value.map(sortJson); if (!value || typeof value !== 'object') return value; return Object.fromEntries(Object.keys(value).sort().map((key) => [key, sortJson(value[key])])); }
225
+ function finding(severity, code, message, extra = {}) { return Object.freeze({ severity, code, message, ...extra }); }
226
+ function deepFreeze(value) { if (!value || typeof value !== 'object' || Object.isFrozen(value)) return value; if (ArrayBuffer.isView(value) || value instanceof ArrayBuffer) return value; for (const child of Object.values(value)) deepFreeze(child); return Object.freeze(value); }
@@ -0,0 +1,169 @@
1
+ import { packageFileBytes, sha256Hex } from '../../../export/package.bytes.js';
2
+ import { qualifyHandoffMaterialClosurePlanReadiness } from './materialClosure.readiness.js';
3
+ import { buildHandoffWorkspaceByteProvider, resolveHandoffWorkspaceEntry } from './workspaceByteProvider.js';
4
+
5
+ export const HANDOFF_CLOSURE_DESCRIPTOR_SCHEMA_ID = 'tiinex.transport.handoff-material-closure-descriptor.v1';
6
+ export const HANDOFF_CLOSURE_DESCRIPTOR_V2_SCHEMA_ID = 'tiinex.transport.handoff-material-closure-descriptor.v2';
7
+ export const HANDOFF_CLOSURE_DESCRIPTOR_PATH = 'tiinex.package/handoff-closure.json';
8
+
9
+ export function buildHandoffClosureDescriptor(plan = {}, packageMaterial = {}) {
10
+ const materialized = (packageMaterial.materialized || []).map((entry) => descriptorMaterial(entry));
11
+ const packagedWorkspaceByCorrelation = indexPackagedWorkspaces(packageMaterial.workspaces || []);
12
+ const workspaces = (plan.workspaceMaterializations || []).map((workspace) => {
13
+ const packagedResolution = resolvePackagedWorkspace(packagedWorkspaceByCorrelation, workspace.transportCorrelationKey);
14
+ const packaged = packagedResolution.workspace || {};
15
+ const correlationStatus = packagedResolution.status === 'qualified' ? String(packaged.correlationStatus || 'unresolved') : packagedResolution.status;
16
+ const entries = correlationStatus === 'qualified' && (packaged.entries || []).length ? packaged.entries : workspace.includedEntries;
17
+ return Object.freeze({
18
+ id: workspace.id,
19
+ title: String(workspace.title || workspace.id || ''),
20
+ source: workspace.source,
21
+ materialization: workspace.materialization,
22
+ qualification: workspace.qualification,
23
+ completenessEvidence: workspace.completenessEvidence,
24
+ scopeEvidence: workspace.scopeEvidence || Object.freeze({}),
25
+ transportCorrelationKey: String(workspace.transportCorrelationKey || ''),
26
+ correlationStatus,
27
+ includedEntries: entries
28
+ });
29
+ });
30
+ return deepFreeze({
31
+ schema: HANDOFF_CLOSURE_DESCRIPTOR_SCHEMA_ID,
32
+ version: 1,
33
+ boundary: 'Disposable recipient-relative transport metadata. Safe to delete with the package; not a Tiinex artifact, semantic Parent, workspace owner, package identity, Handoff acceptance/completion state, or provider authority.',
34
+ handoff: Object.freeze({ id: String(plan.handoff?.id || ''), path: String(plan.handoff?.path || ''), reference: String(plan.handoff?.reference || ''), semanticStatus: String(plan.semanticHandoffStatus || 'unknown') }),
35
+ plan: Object.freeze({ status: String(plan.status || 'blocked'), requiredClosureReady: Boolean(plan.requiredClosureReady), localRunId: String(packageMaterial.localRunId || ''), inputBindingState: String(packageMaterial.planInputBinding?.state || 'unresolved'), inputBindingMode: String(packageMaterial.planInputBinding?.mode || 'unknown'), inputBindingFindings: Object.freeze([...(packageMaterial.planInputBinding?.findings || [])]), materializedOutputState: String(packageMaterial.materializedOutputQualification?.state || 'unresolved'), materializedOutputFindings: Object.freeze([...(packageMaterial.materializedOutputQualification?.findings || [])]) }),
36
+ requirements: Object.freeze({
37
+ required: Object.freeze((plan.requirements?.required || []).map(descriptorRequirement)),
38
+ reference: Object.freeze((plan.requirements?.reference || []).map(descriptorRequirement)),
39
+ endpointRoles: Object.freeze((plan.requirements?.endpointRoles || []).map(descriptorRequirement)),
40
+ participantRoles: Object.freeze((plan.requirements?.participantRoles || []).map(descriptorRequirement)),
41
+ dependencies: Object.freeze((plan.requirements?.dependencies || []).map(descriptorRequirement))
42
+ }),
43
+ materialized: Object.freeze(materialized),
44
+ workspaceMaterializations: Object.freeze(workspaces),
45
+ bootstrap: Object.freeze({ status: String(plan.bootstrap?.status || 'absent'), packagePath: String(packageMaterial.bootstrapPath || ''), boundary: String(plan.bootstrap?.boundary || '') }),
46
+ providerProvenance: Object.freeze(materialized.map((entry) => Object.freeze({ requirementId: entry.requirementId, provider: entry.provider, provenance: entry.provenance }))),
47
+ roundtripVerification: Object.freeze({
48
+ state: 'build-verified',
49
+ verifier: 'durable-file-map-plus-independent-archive-rehydration-required',
50
+ descriptorPath: HANDOFF_CLOSURE_DESCRIPTOR_PATH,
51
+ expectedMaterial: Object.freeze([
52
+ ...materialized.map((entry) => Object.freeze({ packagePath: entry.packagePath, bytes: entry.bytes, sha256: entry.sha256 })),
53
+ ...workspaces.flatMap((workspace) => (workspace.includedEntries || []).filter((entry) => entry.packagePath).map((entry) => Object.freeze({ packagePath: entry.packagePath, bytes: entry.bytes, sha256: entry.sha256 })))
54
+ ]),
55
+ note: 'Build evidence proves descriptor/material byte identities before archive serialization. Independent archive extraction/rehydration must verify the same governed bytes; descriptor presence does not prove delivery or Handoff acceptance.'
56
+ })
57
+ });
58
+ }
59
+
60
+ export function inspectHandoffClosureDescriptor(bundle = {}, options = {}) {
61
+ const findings = [];
62
+ const descriptorFile = (bundle.files || []).find((file) => String(file.path || '') === HANDOFF_CLOSURE_DESCRIPTOR_PATH);
63
+ const descriptor = descriptorFile ? parseJsonFile(descriptorFile) : null;
64
+ if (!descriptor) findings.push(finding('error', 'portable.handoff-closure.descriptor.missing', 'Handoff transport package is missing a readable package-local closure descriptor.'));
65
+ const supportedSchema = descriptor && [HANDOFF_CLOSURE_DESCRIPTOR_SCHEMA_ID, HANDOFF_CLOSURE_DESCRIPTOR_V2_SCHEMA_ID].includes(String(descriptor.schema || ''));
66
+ if (descriptor && !supportedSchema) findings.push(finding('error', 'portable.handoff-closure.descriptor.schema.invalid', 'Handoff closure descriptor schema/version is unsupported.'));
67
+ const isV2 = String(descriptor?.schema || '') === HANDOFF_CLOSURE_DESCRIPTOR_V2_SCHEMA_ID;
68
+ const byPath = new Map((bundle.files || []).map((file) => [String(file.path || ''), file]));
69
+ const suppliedProvider = options.workspaceByteProvider || (options.schema === 'tiinex.portable.handoff-workspace-byte-provider.v1' ? options : null);
70
+ const byteProvider = descriptor ? (suppliedProvider || buildHandoffWorkspaceByteProvider(bundle, descriptor)) : null;
71
+ if (isV2 && byteProvider?.status !== 'ready') findings.push(...(byteProvider?.findings || []));
72
+
73
+ for (const entry of descriptor?.materialized || []) {
74
+ if (String(entry.carrierKind || '') === 'workspace-archive-entry') {
75
+ const resolved = resolveHandoffWorkspaceEntry(byteProvider || {}, entry.workspaceId, entry.workspaceRelativePath);
76
+ if (resolved.state !== 'qualified') { findings.push(finding('error', 'portable.handoff-closure.material.workspace-provider-unqualified', 'Descriptor materialized entry cannot be resolved through its qualified workspace archive provider.', { requirementId: entry.requirementId || '', workspaceId: entry.workspaceId || '', workspaceRelativePath: entry.workspaceRelativePath || '', reason: resolved.reason || resolved.state })); continue; }
77
+ const data = packageFileBytes({ data: resolved.data });
78
+ if (Number(entry.bytes || 0) !== data.byteLength) findings.push(finding('error', 'portable.handoff-closure.material.bytes-mismatch', 'Descriptor materialized entry byte length differs from workspace-provider bytes.', { requirementId: entry.requirementId || '', workspaceId: entry.workspaceId || '', workspaceRelativePath: entry.workspaceRelativePath || '' }));
79
+ if (String(entry.sha256 || '') !== sha256Hex(data)) findings.push(finding('error', 'portable.handoff-closure.material.sha256-mismatch', 'Descriptor materialized entry digest differs from workspace-provider bytes.', { requirementId: entry.requirementId || '', workspaceId: entry.workspaceId || '', workspaceRelativePath: entry.workspaceRelativePath || '' }));
80
+ continue;
81
+ }
82
+ const file = byPath.get(String(entry.packagePath || ''));
83
+ if (!file) { findings.push(finding('error', 'portable.handoff-closure.material.missing', 'Descriptor materialized entry is missing from package bytes.', { requirementId: entry.requirementId || '', packagePath: entry.packagePath || '' })); continue; }
84
+ const data = packageFileBytes(file);
85
+ if (Number(entry.bytes || 0) !== data.byteLength) findings.push(finding('error', 'portable.handoff-closure.material.bytes-mismatch', 'Descriptor materialized entry byte length differs from package bytes.', { packagePath: entry.packagePath || '' }));
86
+ if (String(entry.sha256 || '') !== sha256Hex(data)) findings.push(finding('error', 'portable.handoff-closure.material.sha256-mismatch', 'Descriptor materialized entry digest differs from package bytes.', { packagePath: entry.packagePath || '' }));
87
+ }
88
+ for (const workspace of descriptor?.workspaceMaterializations || []) {
89
+ if (String(workspace.correlationStatus || '') !== 'qualified') findings.push(finding('error', 'portable.handoff-closure.workspace-correlation.unqualified', 'Descriptor workspace materialization is not uniquely correlated to one packaged workspace byte carrier.', { workspaceId: workspace.id || '', correlationStatus: workspace.correlationStatus || 'unresolved' }));
90
+ if (isV2) continue;
91
+ for (const entry of workspace.includedEntries || []) {
92
+ if (!entry.packagePath) continue;
93
+ const file = byPath.get(String(entry.packagePath || ''));
94
+ if (!file) { findings.push(finding('error', 'portable.handoff-closure.workspace-material.missing', 'Descriptor workspace material entry is missing from package bytes.', { workspaceId: workspace.id || '', packagePath: entry.packagePath || '' })); continue; }
95
+ const data = packageFileBytes(file);
96
+ if (Number(entry.bytes || 0) !== data.byteLength) findings.push(finding('error', 'portable.handoff-closure.workspace-material.bytes-mismatch', 'Descriptor workspace material entry byte length differs from package bytes.', { workspaceId: workspace.id || '', packagePath: entry.packagePath || '' }));
97
+ if (String(entry.sha256 || '') !== sha256Hex(data)) findings.push(finding('error', 'portable.handoff-closure.workspace-material.sha256-mismatch', 'Descriptor workspace material entry digest differs from package bytes.', { workspaceId: workspace.id || '', packagePath: entry.packagePath || '' }));
98
+ }
99
+ }
100
+ if (descriptor?.bootstrap?.status === 'present' && !byPath.has(String(descriptor.bootstrap.packagePath || ''))) findings.push(finding('error', 'portable.handoff-closure.bootstrap.missing', 'Descriptor declares bootstrap present but the package-local bootstrap file is missing.', { packagePath: descriptor.bootstrap.packagePath || '' }));
101
+ const readinessQualification = descriptor ? qualifyHandoffMaterialClosurePlanReadiness({
102
+ status: descriptor.plan?.status,
103
+ requiredClosureReady: descriptor.plan?.requiredClosureReady,
104
+ requirements: descriptor.requirements,
105
+ workspaceMaterializations: descriptor.workspaceMaterializations
106
+ }) : null;
107
+ if (readinessQualification?.findings.includes('required-closure-ready-contradictory')) findings.push(finding('error', 'portable.handoff-closure.readiness.inconsistent', 'Descriptor required closure readiness conflicts with blocking required-material or workspace-materialization truth.'));
108
+ if (readinessQualification?.findings.includes('plan-status-contradictory')) findings.push(finding('error', 'portable.handoff-closure.plan-status.inconsistent', 'Descriptor plan status conflicts with blocking required-material or workspace-materialization truth.'));
109
+ if (descriptor && String(descriptor.plan?.inputBindingState || '') !== 'qualified') findings.push(finding('error', 'portable.handoff-closure.plan-input-binding.unqualified', 'Descriptor plan is not qualified against the current parallel Handoff/recipient planning inputs.', { mode: descriptor.plan?.inputBindingMode || 'unknown', inputBindingFindings: descriptor.plan?.inputBindingFindings || [] }));
110
+ if (descriptor && String(descriptor.plan?.materializedOutputState || '') !== 'qualified') findings.push(finding('error', 'portable.handoff-closure.materialized-output.unqualified', 'Descriptor plan materialized output is not qualified against its own selected material-resolution truth.', { materializedOutputFindings: descriptor.plan?.materializedOutputFindings || [] }));
111
+ inspectRequirementMaterialCorrespondence(descriptor, findings);
112
+ return deepFreeze({ schema: 'tiinex.transport.handoff-material-closure-descriptor.inspection.v1', status: findings.some((item) => item.severity === 'error') ? 'invalid' : 'valid', descriptor, findings: Object.freeze(dedupeFindings(findings)), ...(isV2 ? { workspaceByteProvider: byteProvider } : {}) });
113
+ }
114
+
115
+
116
+ function indexPackagedWorkspaces(items = []) {
117
+ const index = new Map();
118
+ for (const workspace of items) {
119
+ const key = String(workspace?.transportCorrelationKey || '');
120
+ if (!key) continue;
121
+ const current = index.get(key);
122
+ if (!current) index.set(key, Object.freeze({ status: 'qualified', workspace }));
123
+ else index.set(key, Object.freeze({ status: 'ambiguous', workspace: null }));
124
+ }
125
+ return index;
126
+ }
127
+ function resolvePackagedWorkspace(index, key = '') {
128
+ if (!key) return Object.freeze({ status: 'unresolved', workspace: null });
129
+ return index.get(String(key || '')) || Object.freeze({ status: 'unresolved', workspace: null });
130
+ }
131
+
132
+
133
+ function descriptorRequirement(item = {}) {
134
+ return Object.freeze({ requirementId: String(item.requirementId || ''), name: String(item.requirementName || item.name || ''), classification: String(item.classification || ''), disposition: String(item.disposition || ''), referenceTarget: String(item.referenceTarget || ''), reason: String(item.reason || ''), recipientReferenceCapability: Boolean(item.recipientReferenceCapability), routeWorkspaceId: String(item.routeWorkspaceId || ''), routePath: String(item.routePath || ''), sourceRequirementId: String(item.sourceRequirementId || ''), materializedPackagePath: String(item.packagePath || item.selectedMaterial?.packagePath || ''), selectedMaterial: descriptorSelectedMaterial(item.selectedMaterial) });
135
+ }
136
+ function descriptorSelectedMaterial(material = null) {
137
+ if (!material) return null;
138
+ return Object.freeze({ path: String(material.path || ''), requestedPackagePath: String(material.packagePath || ''), bytes: Number(material.bytes || 0), sha256: String(material.sha256 || ''), mediaType: String(material.mediaType || ''), provider: material.provider || {}, provenance: material.provenance || {}, authority: material.authority || {} });
139
+ }
140
+ function inspectRequirementMaterialCorrespondence(descriptor, findings) {
141
+ if (!descriptor) return;
142
+ const requirements = [...(descriptor.requirements?.required || []), ...(descriptor.requirements?.reference || []), ...(descriptor.requirements?.endpointRoles || []), ...(descriptor.requirements?.participantRoles || []), ...(descriptor.requirements?.dependencies || [])];
143
+ const materialized = descriptor.materialized || [];
144
+ const byRequirement = new Map();
145
+ for (const carrier of materialized) {
146
+ const id = String(carrier.requirementId || '');
147
+ const list = byRequirement.get(id) || []; list.push(carrier); byRequirement.set(id, list);
148
+ }
149
+ const expectedIds = new Set();
150
+ for (const requirement of requirements) {
151
+ if (String(requirement.disposition || '') !== 'materialized') continue;
152
+ const id = String(requirement.requirementId || ''); expectedIds.add(id);
153
+ const carriers = byRequirement.get(id) || [];
154
+ if (carriers.length === 0) { findings.push(finding('error', 'portable.handoff-closure.materialized-output.required-carrier-missing', 'A materialized requirement has no exact packaged carrier.', { requirementId: id })); continue; }
155
+ if (carriers.length !== 1) { findings.push(finding('error', 'portable.handoff-closure.materialized-output.required-carrier-ambiguous', 'A materialized requirement has multiple packaged carriers without output-selection authority.', { requirementId: id, count: carriers.length })); continue; }
156
+ const selected = requirement.selectedMaterial || {}; const carrier = carriers[0];
157
+ if (!selected.sha256 || Number(selected.bytes || 0) <= 0) findings.push(finding('error', 'portable.handoff-closure.materialized-output.selected-material-unqualified', 'Materialized requirement lacks exact selected-material byte identity.', { requirementId: id }));
158
+ if (String(carrier.sha256 || '') !== String(selected.sha256 || '') || Number(carrier.bytes || 0) !== Number(selected.bytes || 0) || String(carrier.classification || '') !== String(requirement.classification || '') || String(carrier.referenceTarget || '') !== String(requirement.referenceTarget || '')) findings.push(finding('error', 'portable.handoff-closure.materialized-output.carrier-mismatch', 'Packaged material carrier diverges from the requirement selected-material truth.', { requirementId: id }));
159
+ }
160
+ for (const carrier of materialized) if (!expectedIds.has(String(carrier.requirementId || ''))) findings.push(finding('error', 'portable.handoff-closure.materialized-output.unbound-carrier', 'Packaged material carrier is not bound to a requirement whose disposition is materialized.', { requirementId: carrier.requirementId || '', packagePath: carrier.packagePath || '' }));
161
+ }
162
+
163
+ function descriptorMaterial(entry = {}) {
164
+ return Object.freeze({ requirementId: String(entry.requirementId || ''), classification: String(entry.classification || ''), referenceTarget: String(entry.referenceTarget || ''), routeWorkspaceId: String(entry.routeWorkspaceId || ''), routePath: String(entry.routePath || ''), sourceRequirementId: String(entry.sourceRequirementId || ''), packagePath: String(entry.packagePath || ''), originalPath: String(entry.path || ''), bytes: Number(entry.bytes || 0), sha256: String(entry.sha256 || ''), mediaType: String(entry.mediaType || ''), provider: entry.provider || {}, provenance: entry.provenance || {}, authority: entry.authority || {}, ...(entry.carrierKind ? { carrierKind: String(entry.carrierKind), workspaceId: String(entry.workspaceId || ''), workspaceRelativePath: String(entry.workspaceRelativePath || '') } : {}) });
165
+ }
166
+ function parseJsonFile(file = {}) { try { return JSON.parse(new TextDecoder().decode(packageFileBytes(file))); } catch { return null; } }
167
+ function finding(severity, code, message, extra = {}) { return Object.freeze({ severity, code, message, ...extra }); }
168
+ function dedupeFindings(items = []) { const map = new Map(); for (const item of items) { const key = `${item.severity || ''}:${item.code || ''}:${item.workspaceId || ''}:${item.requirementId || ''}:${item.packagePath || ''}:${item.workspaceRelativePath || ''}`; if (!map.has(key)) map.set(key, item); } return [...map.values()]; }
169
+ function deepFreeze(value) { if (!value || typeof value !== 'object' || Object.isFrozen(value)) return value; if (ArrayBuffer.isView(value) || value instanceof ArrayBuffer) return value; for (const child of Object.values(value)) deepFreeze(child); return Object.freeze(value); }