@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,175 @@
1
+ import { packageFileBytes } from '../../../export/package.bytes.js';
2
+
3
+ export const HANDOFF_TRANSPORT_COMPANION_SCHEMA_ID = 'tiinex.portable.handoff-transport-companion-projection.v1';
4
+ export const HANDOFF_TRANSPORT_COMPANION_PATH = 'tiinex.package/handoff-companion.json';
5
+
6
+ const ACTIONS = Object.freeze({
7
+ providePackage: 'tiinex.handoff.transport.action.provide-package',
8
+ invokeRecipient: 'tiinex.handoff.transport.action.invoke-recipient',
9
+ carryResult: 'tiinex.handoff.transport.action.carry-result'
10
+ });
11
+
12
+ const KEYS = Object.freeze({
13
+ providePackage: 'handoff.transport.action.providePackage',
14
+ invokeRecipient: 'handoff.transport.action.invokeRecipient',
15
+ carryResult: 'handoff.transport.action.carryResult',
16
+ invocation: 'handoff.transport.invocation.workspaceArtifact',
17
+ routingDetail: 'handoff.transport.detail.routing',
18
+ participationDetail: 'handoff.transport.detail.participation',
19
+ blockerDetail: 'handoff.transport.detail.blockers'
20
+ });
21
+
22
+ export function buildHandoffTransportCompanionProjection(input = {}) {
23
+ const descriptor = input.descriptor || {};
24
+ const bundle = input.bundle || {};
25
+ const packageStatus = String(input.packageStatus || descriptor.plan?.status || bundle.status || 'blocked');
26
+ const routing = qualifyRouting(bundle, descriptor);
27
+ const participation = qualifyParticipation(input.participation || input.transportParticipation || {});
28
+ const blockers = [];
29
+ if (packageStatus === 'blocked') blockers.push(blocker('package-blocked', { packageStatus }));
30
+ if (routing.state !== 'qualified') blockers.push(blocker(`routing-${routing.state}`, routing.parameters));
31
+ if (participation.actingRole.state === 'ambiguous') blockers.push(blocker('acting-role-ambiguous', {}));
32
+ if (participation.actingRole.state === 'unresolved') blockers.push(blocker('acting-role-unresolved', {}));
33
+ if (participation.actingRole.state === 'invalid') blockers.push(blocker('acting-role-invalid', {}));
34
+ if (participation.transportPosture.state !== 'qualified') blockers.push(blocker('participation-posture-unqualified', { state: participation.transportPosture.state }));
35
+ const status = blockers.some((item) => item.id.includes('ambiguous')) ? 'ambiguous' : blockers.length ? 'blocked' : 'ready';
36
+ const routeParameters = Object.freeze({
37
+ workspaceId: routing.workspace.id,
38
+ workspaceTitle: routing.workspace.title,
39
+ controllingArtifactPath: routing.controllingArtifact.workspaceRelativePath
40
+ });
41
+ const actions = Object.freeze([
42
+ action(ACTIONS.providePackage, KEYS.providePackage, Object.freeze({ packageStatus })),
43
+ action(ACTIONS.invokeRecipient, KEYS.invokeRecipient, routeParameters),
44
+ action(ACTIONS.carryResult, KEYS.carryResult, Object.freeze({}))
45
+ ]);
46
+ return deepFreeze({
47
+ schema: HANDOFF_TRANSPORT_COMPANION_SCHEMA_ID,
48
+ version: 1,
49
+ boundary: 'non-authoritative-disposable-transport-projection',
50
+ status,
51
+ packageState: Object.freeze({ status: packageStatus, descriptorSchema: String(descriptor.schema || '') }),
52
+ routing,
53
+ participation,
54
+ recipientEntrypoint: Object.freeze({
55
+ kind: 'workspace-artifact-routing',
56
+ localizationKey: KEYS.invocation,
57
+ parameters: routeParameters
58
+ }),
59
+ actions,
60
+ progressiveDisclosure: Object.freeze({
61
+ expertActionIds: Object.freeze(actions.map((item) => item.id)),
62
+ details: Object.freeze([
63
+ disclosure('routing', KEYS.routingDetail, routeParameters),
64
+ disclosure('participation', KEYS.participationDetail, participationParameters(participation)),
65
+ disclosure('blockers', KEYS.blockerDetail, Object.freeze({ blockerIds: Object.freeze(blockers.map((item) => item.id)) }))
66
+ ])
67
+ }),
68
+ blockers: Object.freeze(blockers),
69
+ authority: Object.freeze({ semanticAuthority: 'none', carrierEndpointPromotion: false, acceptanceAuthority: false })
70
+ });
71
+ }
72
+
73
+ export function inspectHandoffTransportCompanion(bundle = {}) {
74
+ const findings = [];
75
+ const projectionFile = (bundle.files || []).find((file) => String(file.path || '') === HANDOFF_TRANSPORT_COMPANION_PATH);
76
+ const projection = projectionFile ? parseJsonFile(projectionFile) : null;
77
+ const descriptorFile = (bundle.files || []).find((file) => String(file.path || '') === 'tiinex.package/handoff-closure.json');
78
+ const descriptor = descriptorFile ? parseJsonFile(descriptorFile) : bundle.handoffClosure || null;
79
+ if (!projection) findings.push(finding('error', 'portable.handoff-companion.missing', 'Handoff package is missing a readable transport companion projection.'));
80
+ if (projection && projection.schema !== HANDOFF_TRANSPORT_COMPANION_SCHEMA_ID) findings.push(finding('error', 'portable.handoff-companion.schema.invalid', 'Transport companion projection runtime contract is unsupported.'));
81
+ if (projection && projection.boundary !== 'non-authoritative-disposable-transport-projection') findings.push(finding('error', 'portable.handoff-companion.boundary.invalid', 'Transport companion projection lost its non-authoritative disposable boundary.'));
82
+ if (projection && containsCarrierTopology(projection)) findings.push(finding('error', 'portable.handoff-companion.routing.carrier-topology-leak', 'Transport companion exposes disposable package carrier topology as host routing truth.'));
83
+ if (projection && descriptor) inspectProjectionCorrespondence(projection, descriptor, bundle, findings);
84
+ const errors = findings.filter((item) => item.severity === 'error').length;
85
+ return deepFreeze({ schema: 'tiinex.portable.handoff-transport-companion.inspection.v1', status: errors ? 'invalid' : 'valid', projection, findings: Object.freeze(findings), findingSummary: Object.freeze({ findings: findings.length, errors }) });
86
+ }
87
+
88
+ function qualifyRouting(bundle = {}, descriptor = {}) {
89
+ const manifest = bundle.manifest || parseJsonFile((bundle.files || []).find((file) => String(file.path || '') === 'tiinex.package/manifest.json')) || {};
90
+ const workspaceIds = unique([manifest.workspaceId, manifest.packageScope?.workspaceId].filter(Boolean).map(String));
91
+ const descriptorWorkspaces = descriptor.workspaceMaterializations || [];
92
+ if (!workspaceIds.length && descriptorWorkspaces.length === 1) workspaceIds.push(String(descriptorWorkspaces[0].id || ''));
93
+ if (workspaceIds.length !== 1 || !workspaceIds[0]) return routingResult(workspaceIds.length > 1 ? 'ambiguous' : 'unresolved', workspaceIds[0] || '', '', '', { workspaceCandidates: workspaceIds });
94
+ const workspaceId = workspaceIds[0];
95
+ const workspaceTitle = String(manifest.packageScope?.workspaceTitle || manifest.title || workspaceId);
96
+ const artifactPath = controllingArtifactPath(descriptor.handoff || {});
97
+ if (!artifactPath) return routingResult('unresolved', workspaceId, workspaceTitle, '', { workspaceId, reason: 'controlling-artifact-unqualified' });
98
+ const workspaceMatches = descriptorWorkspaces.filter((item) => String(item.id || '') === workspaceId);
99
+ if (descriptorWorkspaces.length && workspaceMatches.length !== 1) return routingResult(workspaceMatches.length > 1 ? 'ambiguous' : 'unresolved', workspaceId, workspaceTitle, artifactPath, { workspaceId, controllingArtifactPath: artifactPath });
100
+ if (workspaceMatches.length === 1) {
101
+ const workspace = workspaceMatches[0];
102
+ if (String(workspace.qualification || '') !== 'qualified' || String(workspace.correlationStatus || '') !== 'qualified') return routingResult('blocked', workspaceId, workspaceTitle, artifactPath, { workspaceId, controllingArtifactPath: artifactPath });
103
+ const matches = (workspace.includedEntries || []).filter((entry) => normalizeWorkspacePath(entry.path) === artifactPath);
104
+ if (matches.length !== 1) return routingResult(matches.length > 1 ? 'ambiguous' : 'unresolved', workspaceId, workspaceTitle, artifactPath, { workspaceId, controllingArtifactPath: artifactPath });
105
+ } else if (!manifestContainsArtifact(manifest, artifactPath)) {
106
+ return routingResult('unresolved', workspaceId, workspaceTitle, artifactPath, { workspaceId, controllingArtifactPath: artifactPath });
107
+ }
108
+ return routingResult('qualified', workspaceId, workspaceTitle, artifactPath, { workspaceId, controllingArtifactPath: artifactPath });
109
+ }
110
+
111
+ function qualifyParticipation(input = {}) {
112
+ const posture = String(input.transportPosture || input.posture || 'transport-only');
113
+ const transportPosture = Object.freeze({ state: posture === 'transport-only' ? 'qualified' : 'unresolved', id: posture });
114
+ const role = input.actingRole || null;
115
+ let actingRole = Object.freeze({ state: 'none', schemaId: '', reference: '', label: '' });
116
+ if (role) {
117
+ const state = String(role.qualification || role.state || 'unresolved');
118
+ if (state === 'ambiguous') actingRole = Object.freeze({ state: 'ambiguous', schemaId: '', reference: '', label: '' });
119
+ else if (state !== 'qualified') actingRole = Object.freeze({ state: 'unresolved', schemaId: String(role.schemaId || ''), reference: '', label: '' });
120
+ else if (String(role.schemaId || '') !== 'tiinex.party.role.v1' || !exactRoleReference(role.reference)) actingRole = Object.freeze({ state: 'invalid', schemaId: String(role.schemaId || ''), reference: '', label: '' });
121
+ else actingRole = Object.freeze({ state: 'qualified', schemaId: 'tiinex.party.role.v1', reference: String(role.reference), label: String(role.label || '') });
122
+ }
123
+ return deepFreeze({ transportPosture, actingRole, carrierAuthority: 'none', endpointPromotion: false });
124
+ }
125
+
126
+ function inspectProjectionCorrespondence(projection, descriptor, bundle, findings) {
127
+ const expected = buildHandoffTransportCompanionProjection({ bundle, descriptor, packageStatus: bundle.status || descriptor.plan?.status || 'blocked', participation: projectionParticipationInput(projection.participation) });
128
+ if (stableJson(expected.packageState) !== stableJson(projection.packageState)) findings.push(finding('error', 'portable.handoff-companion.package-state.mismatch', 'Transport companion package state diverges from package/closure truth.'));
129
+ if (stableJson(expected.routing) !== stableJson(projection.routing)) findings.push(finding('error', 'portable.handoff-companion.routing.mismatch', 'Transport companion routing diverges from package/closure truth.'));
130
+ if (stableJson(expected.participation) !== stableJson(projection.participation)) findings.push(finding('error', 'portable.handoff-companion.participation.mismatch', 'Transport companion participation projection is internally inconsistent.'));
131
+ if (stableJson(expected.blockers) !== stableJson(projection.blockers)) findings.push(finding('error', 'portable.handoff-companion.blockers.mismatch', 'Transport companion blockers diverge from projected package/routing/participation truth.'));
132
+ if (String(expected.status) !== String(projection.status)) findings.push(finding('error', 'portable.handoff-companion.status.mismatch', 'Transport companion status diverges from projected blocker truth.'));
133
+ if (projection.authority?.semanticAuthority !== 'none' || projection.authority?.carrierEndpointPromotion !== false || projection.authority?.acceptanceAuthority !== false) findings.push(finding('error', 'portable.handoff-companion.authority.promotion', 'Transport companion promotes carrier/projection metadata into semantic authority.'));
134
+ }
135
+
136
+ function projectionParticipationInput(participation = {}) {
137
+ return { transportPosture: participation.transportPosture?.id || 'transport-only', actingRole: participation.actingRole?.state === 'none' ? null : participation.actingRole };
138
+ }
139
+ function controllingArtifactPath(handoff = {}) {
140
+ for (const raw of [handoff.id, handoff.path]) {
141
+ const path = normalizeWorkspacePath(raw);
142
+ if (isWorkspaceRelativeArtifactPath(path)) return path;
143
+ }
144
+ return '';
145
+ }
146
+ function isWorkspaceRelativeArtifactPath(path = '') {
147
+ if (!path || path.startsWith('/') || path.startsWith('handoff.workspaces/') || path.startsWith('tiinex.package/')) return false;
148
+ if (/^[a-z][a-z0-9+.-]*:\/\//i.test(path) || path.includes('/../') || path.startsWith('../')) return false;
149
+ return path.includes('/') && /\.trace\.md$/i.test(path);
150
+ }
151
+ function exactRoleReference(value = '') {
152
+ const ref = String(value || '').trim().replace(/\\/g, '/');
153
+ return Boolean(ref) && !ref.startsWith('handoff.workspaces/') && !ref.includes('/../') && (ref.endsWith('.trace.md') || /^https:\/\//i.test(ref));
154
+ }
155
+ function manifestContainsArtifact(manifest = {}, artifactPath = '') {
156
+ const material = manifest.material || {};
157
+ const entries = [...(material.localDrafts || []), ...(material.sourceReferences || []), ...(material.workspaceArtifacts || [])];
158
+ return entries.some((entry) => normalizeWorkspacePath(entry.path || entry.sourceArtifactPath) === artifactPath);
159
+ }
160
+ function routingResult(state, id, title, path, parameters) {
161
+ return deepFreeze({ state, workspace: Object.freeze({ id, title }), controllingArtifact: Object.freeze({ workspaceRelativePath: path }), parameters: Object.freeze(parameters || {}) });
162
+ }
163
+ function participationParameters(participation) { return Object.freeze({ transportPosture: participation.transportPosture.id, actingRoleState: participation.actingRole.state, actingRoleReference: participation.actingRole.reference || '' }); }
164
+ function action(id, localizationKey, parameters) { return Object.freeze({ id, localizationKey, parameters }); }
165
+ function disclosure(id, localizationKey, parameters) { return Object.freeze({ id, localizationKey, parameters }); }
166
+ function blocker(id, parameters) { return Object.freeze({ id: `tiinex.handoff.transport.blocker.${id}`, localizationKey: `handoff.transport.blocker.${camel(id)}`, parameters: Object.freeze(parameters || {}) }); }
167
+ function camel(value = '') { return String(value).replace(/-([a-z])/g, (_, c) => c.toUpperCase()); }
168
+ function normalizeWorkspacePath(value = '') { return String(value || '').trim().replace(/\\/g, '/').replace(/^\.\//, '').replace(/^\/+/, ''); }
169
+ function unique(values = []) { return [...new Set(values.filter(Boolean))]; }
170
+ function containsCarrierTopology(value) { return stableJson(value).includes('handoff.workspaces/') || stableJson(value).includes('package://handoff.workspaces/'); }
171
+ function parseJsonFile(file = {}) { try { return JSON.parse(new TextDecoder().decode(packageFileBytes(file))); } catch { return null; } }
172
+ function stableJson(value) { return JSON.stringify(sortJson(value)); }
173
+ 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])])); }
174
+ function finding(severity, code, message, extra = {}) { return Object.freeze({ severity, code, message, ...extra }); }
175
+ function deepFreeze(value) { if (!value || typeof value !== 'object' || Object.isFrozen(value)) return value; for (const child of Object.values(value)) deepFreeze(child); return Object.freeze(value); }
@@ -0,0 +1,95 @@
1
+ import { packageFileBytes, sha256Hex } from '../../../export/package.bytes.js';
2
+
3
+ export function inspectStoredWorkspaceArchiveBytes(bytesInput = new Uint8Array(), normalizeInnerPath = () => Object.freeze({ state: 'invalid', path: '' }), options = {}) {
4
+ const bytes = options.ownedBytes === true && bytesInput instanceof Uint8Array ? bytesInput : packageFileBytes({ data: bytesInput });
5
+ const findings = [];
6
+ const entries = [];
7
+ if (bytes.byteLength < 22) return deepFreeze({ state: 'invalid', entries: Object.freeze([]), findings: Object.freeze([finding('error', 'portable.handoff-workspace-provider.archive.truncated', 'Workspace archive is too small to be a qualified ZIP representation.')]) });
8
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
9
+ const decoder = new TextDecoder('utf-8', { fatal: true });
10
+ let offset = 0;
11
+ while (offset + 4 <= bytes.byteLength && view.getUint32(offset, true) === 0x04034b50) {
12
+ if (offset + 30 > bytes.byteLength) { findings.push(finding('error', 'portable.handoff-workspace-provider.archive.local-header-truncated', 'Workspace archive local header is truncated.')); break; }
13
+ const flags = view.getUint16(offset + 6, true);
14
+ const method = view.getUint16(offset + 8, true);
15
+ const crc = view.getUint32(offset + 14, true);
16
+ const compressedSize = view.getUint32(offset + 18, true);
17
+ const uncompressedSize = view.getUint32(offset + 22, true);
18
+ const nameLength = view.getUint16(offset + 26, true);
19
+ const extraLength = view.getUint16(offset + 28, true);
20
+ const nameStart = offset + 30;
21
+ const dataStart = nameStart + nameLength + extraLength;
22
+ const dataEnd = dataStart + compressedSize;
23
+ if (dataEnd > bytes.byteLength) { findings.push(finding('error', 'portable.handoff-workspace-provider.archive.entry-truncated', 'Workspace archive entry bytes exceed archive bounds.')); break; }
24
+ let rawName = '';
25
+ try { rawName = decoder.decode(bytes.subarray(nameStart, nameStart + nameLength)); }
26
+ catch { findings.push(finding('error', 'portable.handoff-workspace-provider.archive.path-utf8-invalid', 'Workspace archive entry name is not valid UTF-8.')); }
27
+ const normalized = normalizeInnerPath(rawName);
28
+ if (normalized.state !== 'qualified') findings.push(finding('error', 'portable.handoff-workspace-provider.archive.path-unsafe', 'Workspace archive contains an unsafe inner path.', { path: rawName }));
29
+ if ((flags & 0x0001) !== 0) findings.push(finding('error', 'portable.handoff-workspace-provider.archive.encrypted-unsupported', 'Encrypted workspace archive entries are unavailable to the qualified provider.', { path: rawName }));
30
+ if ((flags & 0x0008) !== 0) findings.push(finding('error', 'portable.handoff-workspace-provider.archive.data-descriptor-unsupported', 'Workspace archive data-descriptor entries are unavailable to the deterministic provider.', { path: rawName }));
31
+ if (method !== 0) findings.push(finding('error', 'portable.handoff-workspace-provider.archive.decoder-unavailable', 'Workspace archive entry codec is unavailable to the package-local stored-ZIP provider.', { path: rawName, method }));
32
+ if (compressedSize !== uncompressedSize) findings.push(finding('error', 'portable.handoff-workspace-provider.archive.size-shape-invalid', 'Stored workspace archive entry has divergent compressed/uncompressed sizes.', { path: rawName }));
33
+ const data = bytes.subarray(dataStart, dataEnd);
34
+ if (method === 0 && crc32(data) !== crc) findings.push(finding('error', 'portable.handoff-workspace-provider.archive.crc-mismatch', 'Workspace archive entry CRC does not match exact carried bytes.', { path: rawName }));
35
+ entries.push(deepFreeze({ rawPath: rawName, path: normalized.path || rawName, bytes: data.byteLength, sha256: sha256Hex(data), crc32: crc, method, localOffset: offset, data }));
36
+ offset = dataEnd;
37
+ }
38
+ for (const path of duplicates(entries.map((entry) => entry.path))) findings.push(finding('error', 'portable.handoff-workspace-provider.archive.path-duplicate', 'Workspace archive contains duplicate normalized inner paths.', { path }));
39
+
40
+ const centralStart = offset;
41
+ let centralCount = 0;
42
+ const central = [];
43
+ while (offset + 4 <= bytes.byteLength && view.getUint32(offset, true) === 0x02014b50) {
44
+ if (offset + 46 > bytes.byteLength) { findings.push(finding('error', 'portable.handoff-workspace-provider.archive.central-header-truncated', 'Workspace archive central directory is truncated.')); break; }
45
+ const flags = view.getUint16(offset + 8, true);
46
+ const method = view.getUint16(offset + 10, true);
47
+ const crc = view.getUint32(offset + 16, true);
48
+ const compressedSize = view.getUint32(offset + 20, true);
49
+ const uncompressedSize = view.getUint32(offset + 24, true);
50
+ const nameLength = view.getUint16(offset + 28, true);
51
+ const extraLength = view.getUint16(offset + 30, true);
52
+ const commentLength = view.getUint16(offset + 32, true);
53
+ const localOffset = view.getUint32(offset + 42, true);
54
+ const nameStart = offset + 46;
55
+ const next = nameStart + nameLength + extraLength + commentLength;
56
+ if (next > bytes.byteLength) { findings.push(finding('error', 'portable.handoff-workspace-provider.archive.central-entry-truncated', 'Workspace archive central directory entry exceeds archive bounds.')); break; }
57
+ let rawName = '';
58
+ try { rawName = decoder.decode(bytes.subarray(nameStart, nameStart + nameLength)); } catch { /* local finding already covers malformed names */ }
59
+ central.push({ rawName, flags, method, crc, compressedSize, uncompressedSize, localOffset });
60
+ centralCount += 1;
61
+ offset = next;
62
+ }
63
+ if (offset + 22 > bytes.byteLength || view.getUint32(offset, true) !== 0x06054b50) findings.push(finding('error', 'portable.handoff-workspace-provider.archive.eocd-missing', 'Workspace archive is missing a canonical end-of-central-directory record.'));
64
+ else qualifyEndRecord({ bytes, view, offset, centralStart, centralCount, entries, findings });
65
+ if (central.length === entries.length) compareCentralEntries(entries, central, findings);
66
+ return deepFreeze({ state: findings.some((item) => item.severity === 'error') ? 'invalid' : 'qualified', entries: Object.freeze(entries), findings: Object.freeze(findings) });
67
+ }
68
+
69
+ function qualifyEndRecord({ bytes, view, offset, centralStart, centralCount, entries, findings }) {
70
+ const disk = view.getUint16(offset + 4, true);
71
+ const centralDisk = view.getUint16(offset + 6, true);
72
+ const entriesDisk = view.getUint16(offset + 8, true);
73
+ const entriesTotal = view.getUint16(offset + 10, true);
74
+ const centralSize = view.getUint32(offset + 12, true);
75
+ const declaredCentralOffset = view.getUint32(offset + 16, true);
76
+ const commentLength = view.getUint16(offset + 20, true);
77
+ if (disk !== 0 || centralDisk !== 0 || entriesDisk !== entriesTotal) findings.push(finding('error', 'portable.handoff-workspace-provider.archive.multidisk-unsupported', 'Workspace archive multi-disk topology is unavailable to the package-local provider.'));
78
+ if (entriesTotal !== entries.length || centralCount !== entries.length) findings.push(finding('error', 'portable.handoff-workspace-provider.archive.entry-count-mismatch', 'Workspace archive local and central entry counts diverge.', { local: entries.length, central: centralCount, declared: entriesTotal }));
79
+ if (declaredCentralOffset !== centralStart || centralSize !== (offset - centralStart)) findings.push(finding('error', 'portable.handoff-workspace-provider.archive.central-directory-mismatch', 'Workspace archive central-directory location/size diverges from exact bytes.'));
80
+ if (offset + 22 + commentLength !== bytes.byteLength) findings.push(finding('error', 'portable.handoff-workspace-provider.archive.trailing-bytes', 'Workspace archive contains unqualified trailing bytes after the end record.'));
81
+ }
82
+
83
+ function compareCentralEntries(entries, central, findings) {
84
+ for (let index = 0; index < entries.length; index += 1) {
85
+ const local = entries[index];
86
+ const item = central[index];
87
+ if (item.rawName !== local.rawPath || item.method !== local.method || item.crc !== local.crc32 || item.compressedSize !== local.bytes || item.uncompressedSize !== local.bytes || item.localOffset !== local.localOffset) findings.push(finding('error', 'portable.handoff-workspace-provider.archive.central-entry-mismatch', 'Workspace archive central entry diverges from its local-header/byte representation.', { path: local.rawPath }));
88
+ }
89
+ }
90
+ function duplicates(values = []) { const counts = new Map(); for (const value of values) counts.set(value, (counts.get(value) || 0) + 1); return [...counts.entries()].filter(([, count]) => count > 1).map(([value]) => value); }
91
+ function finding(severity, code, message, extra = {}) { return Object.freeze({ severity, code, message, ...extra }); }
92
+ 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); }
93
+ const CRC_TABLE = makeCrcTable();
94
+ function crc32(buffer) { let crc = 0xffffffff; for (const byte of buffer) crc = CRC_TABLE[(crc ^ byte) & 0xff] ^ (crc >>> 8); return (crc ^ 0xffffffff) >>> 0; }
95
+ function makeCrcTable() { const table = new Uint32Array(256); for (let index = 0; index < 256; index += 1) { let value = index; for (let bit = 0; bit < 8; bit += 1) value = (value & 1) ? (0xedb88320 ^ (value >>> 1)) : (value >>> 1); table[index] = value >>> 0; } return table; }
@@ -0,0 +1,271 @@
1
+ import { packageFileBytes, sha256Hex, utf8Bytes } from '../../../export/package.bytes.js';
2
+ import { inspectStoredWorkspaceArchiveBytes } from './workspaceByteProvider.archive.js';
3
+ import { qualifyHandoffWorkspaceTarget } from './workspaceTargetConformance.js';
4
+
5
+ export const HANDOFF_WORKSPACE_BYTE_PROVIDER_SCHEMA_ID = 'tiinex.portable.handoff-workspace-byte-provider.v1';
6
+ export const HANDOFF_WORKSPACE_ARCHIVE_BINDING_SCHEMA_ID = 'tiinex.transport.handoff-workspace-archive-binding.v1';
7
+ export const HANDOFF_WORKSPACE_ARCHIVE_PROVIDER_KIND = 'package-local-stored-zip-v1';
8
+ export const HANDOFF_WORKSPACE_ARCHIVE_CODEC = 'zip-store-v1';
9
+ export const HANDOFF_WORKSPACE_INNER_PATH_NORMALIZATION = 'tiinex.workspace-inner-path.v1';
10
+
11
+ export function buildHandoffWorkspaceByteProvider(bundle = {}, descriptor = {}) {
12
+ const workspaceItems = descriptor.workspaceMaterializations || [];
13
+ const archiveBindings = descriptor.workspaceArchiveBindings || [];
14
+ const workspaceCounts = countBy(workspaceItems, (item) => String(item.id || ''));
15
+ const bindingCounts = countBy(archiveBindings, (item) => String(item.workspaceId || ''));
16
+ const workspaces = [];
17
+ const findings = [];
18
+
19
+ for (const workspace of workspaceItems) {
20
+ const id = String(workspace.id || '');
21
+ if (!id) {
22
+ const provider = blockedWorkspace(workspace, 'exploded', ['workspace-id-unresolved']);
23
+ workspaces.push(provider);
24
+ findings.push(providerFinding(provider, 'workspace-id-unresolved'));
25
+ continue;
26
+ }
27
+ if ((workspaceCounts.get(id) || 0) !== 1) {
28
+ const provider = blockedWorkspace(workspace, 'exploded', ['workspace-id-ambiguous'], 'ambiguous');
29
+ workspaces.push(provider);
30
+ findings.push(providerFinding(provider, 'workspace-id-ambiguous'));
31
+ continue;
32
+ }
33
+ const matchingBindings = archiveBindings.filter((item) => String(item.workspaceId || '') === id);
34
+ let provider;
35
+ if (matchingBindings.length === 1) provider = qualifyArchiveWorkspace(bundle, workspace, matchingBindings[0]);
36
+ else if (matchingBindings.length > 1 || (bindingCounts.get(id) || 0) > 1) provider = blockedWorkspace(workspace, 'archive', ['workspace-archive-binding-ambiguous'], 'ambiguous');
37
+ else provider = qualifyExplodedWorkspace(bundle, workspace);
38
+ workspaces.push(provider);
39
+ for (const reason of provider.reasons || []) findings.push(providerFinding(provider, reason));
40
+ }
41
+
42
+ for (const binding of archiveBindings) {
43
+ const id = String(binding.workspaceId || '');
44
+ if (!id || !workspaceItems.some((workspace) => String(workspace.id || '') === id)) {
45
+ findings.push(finding('error', 'portable.handoff-workspace-provider.archive-binding.unbound', 'Workspace/archive binding does not resolve to exactly one descriptor workspace.', { workspaceId: id }));
46
+ }
47
+ }
48
+
49
+ const status = workspaces.length > 0 && workspaces.every((workspace) => workspace.state === 'qualified') && !findings.some((item) => item.severity === 'error') ? 'ready' : 'blocked';
50
+ return deepFreeze({
51
+ schema: HANDOFF_WORKSPACE_BYTE_PROVIDER_SCHEMA_ID,
52
+ status,
53
+ workspaces: Object.freeze(workspaces),
54
+ findings: Object.freeze(dedupeFindings(findings)),
55
+ boundary: 'Package-local manufacture/material-closure byte provider. Its tiinex.transport.handoff-workspace-archive-binding.v1 descriptor is mechanical transport evidence, not recipient semantic provider authority. Recipient-v2 archive activation separately requires a qualified tiinex.workspace.representation.v1 binding plus its explicit External Payload and exact payload bytes; filename, placement, declaration order, UI state, and path similarity have no semantic authority.'
56
+ });
57
+ }
58
+
59
+ export function handoffWorkspaceProviderForId(provider = {}, workspaceId = '') {
60
+ const matches = (provider.workspaces || []).filter((workspace) => String(workspace.id || '') === String(workspaceId || ''));
61
+ if (matches.length === 1) return matches[0];
62
+ return deepFreeze({ state: matches.length > 1 ? 'ambiguous' : 'unresolved', id: String(workspaceId || ''), mode: '', entries: Object.freeze([]), reasons: Object.freeze([matches.length > 1 ? 'workspace-id-ambiguous' : 'workspace-id-unresolved']) });
63
+ }
64
+
65
+ export function listHandoffWorkspaceEntries(provider = {}, workspaceId = '') {
66
+ const workspace = handoffWorkspaceProviderForId(provider, workspaceId);
67
+ return workspace.state === 'qualified' ? workspace.entries || Object.freeze([]) : Object.freeze([]);
68
+ }
69
+
70
+ export function resolveHandoffWorkspaceEntry(provider = {}, workspaceId = '', innerPath = '') {
71
+ const workspace = handoffWorkspaceProviderForId(provider, workspaceId);
72
+ if (workspace.state !== 'qualified') return deepFreeze({ state: workspace.state || 'blocked', reason: (workspace.reasons || [])[0] || 'workspace-provider-unqualified' });
73
+ const normalized = normalizeHandoffWorkspaceInnerPath(innerPath);
74
+ if (normalized.state !== 'qualified') return deepFreeze({ state: 'blocked', reason: normalized.reason || 'workspace-inner-path-unsafe' });
75
+ const matches = (workspace.entries || []).filter((entry) => entry.path === normalized.path);
76
+ if (matches.length !== 1) return deepFreeze({ state: matches.length > 1 ? 'ambiguous' : 'unresolved', reason: matches.length > 1 ? 'workspace-inner-path-ambiguous' : 'workspace-inner-path-unresolved', workspaceId: workspace.id, workspaceRelativePath: normalized.path });
77
+ const entry = matches[0];
78
+ return deepFreeze({
79
+ state: 'qualified',
80
+ kind: workspace.mode === 'archive' ? 'workspace-archive-entry' : 'workspace-material',
81
+ providerMode: workspace.mode,
82
+ workspaceId: workspace.id,
83
+ workspaceRelativePath: entry.path,
84
+ packagePath: String(entry.packagePath || workspace.archive?.packagePath || ''),
85
+ archivePackagePath: String(entry.archivePackagePath || workspace.archive?.packagePath || ''),
86
+ innerPath: String(entry.innerPath || entry.path || ''),
87
+ bytes: Number(entry.bytes || 0),
88
+ sha256: String(entry.sha256 || ''),
89
+ data: entry.data,
90
+ referenceTarget: String(entry.referenceTarget || '')
91
+ });
92
+ }
93
+
94
+ export function normalizeHandoffWorkspaceInnerPath(value = '') {
95
+ const raw = String(value || '');
96
+ if (!raw || raw.includes('\u0000') || /[\u0000-\u001f]/.test(raw)) return Object.freeze({ state: 'invalid', path: '', reason: 'workspace-inner-path-unsafe' });
97
+ const slashed = raw.replace(/\\/g, '/');
98
+ if (slashed.startsWith('/') || slashed.startsWith('//') || /^[A-Za-z]:\//.test(slashed)) return Object.freeze({ state: 'invalid', path: '', reason: 'workspace-inner-path-unsafe' });
99
+ const parts = [];
100
+ for (const part of slashed.split('/')) {
101
+ if (!part || part === '.') continue;
102
+ if (part === '..') return Object.freeze({ state: 'invalid', path: '', reason: 'workspace-inner-path-traversal' });
103
+ parts.push(part);
104
+ }
105
+ if (!parts.length) return Object.freeze({ state: 'invalid', path: '', reason: 'workspace-inner-path-unsafe' });
106
+ return Object.freeze({ state: 'qualified', path: parts.join('/'), reason: '' });
107
+ }
108
+
109
+ export function inspectStoredWorkspaceArchive(bytesInput = new Uint8Array(), options = {}) { return inspectStoredWorkspaceArchiveBytes(bytesInput, normalizeHandoffWorkspaceInnerPath, options); }
110
+
111
+ function qualifyExplodedWorkspace(bundle, workspace) {
112
+ const reasons = [];
113
+ if (String(workspace.qualification || '') !== 'qualified') reasons.push('workspace-qualification-unqualified');
114
+ if (String(workspace.correlationStatus || '') !== 'qualified') reasons.push('workspace-correlation-unqualified');
115
+ const entries = [];
116
+ const seen = new Set();
117
+ for (const declared of workspace.includedEntries || []) {
118
+ const normalized = normalizeHandoffWorkspaceInnerPath(declared.path || '');
119
+ if (normalized.state !== 'qualified') { reasons.push(normalized.reason || 'workspace-inner-path-unsafe'); continue; }
120
+ if (seen.has(normalized.path)) { reasons.push('workspace-inner-path-duplicate'); continue; }
121
+ seen.add(normalized.path);
122
+ const packagePath = String(declared.packagePath || '');
123
+ const matches = (bundle.files || []).filter((file) => String(file.path || '') === packagePath);
124
+ if (!packagePath || matches.length !== 1) { reasons.push(matches.length > 1 ? 'workspace-package-path-ambiguous' : 'workspace-package-path-unresolved'); continue; }
125
+ const data = packageFileBytes(matches[0]);
126
+ if (Number(declared.bytes || 0) !== data.byteLength) reasons.push('workspace-byte-count-mismatch');
127
+ if (String(declared.sha256 || '') !== sha256Hex(data)) reasons.push('workspace-byte-digest-mismatch');
128
+ entries.push(deepFreeze({ path: normalized.path, packagePath, innerPath: normalized.path, bytes: data.byteLength, sha256: sha256Hex(data), referenceTarget: String(declared.referenceTarget || ''), data }));
129
+ }
130
+ return deepFreeze({
131
+ state: reasons.length ? 'blocked' : 'qualified',
132
+ id: String(workspace.id || ''),
133
+ title: String(workspace.title || workspace.id || ''),
134
+ mode: 'exploded',
135
+ materialization: workspace,
136
+ entries: Object.freeze(entries),
137
+ workspaceTarget: null,
138
+ archive: null,
139
+ reasons: Object.freeze([...new Set(reasons)]),
140
+ authority: Object.freeze({ locatorAuthority: false, filenameAuthority: false, packagePlacementAuthority: false })
141
+ });
142
+ }
143
+
144
+ function qualifyArchiveWorkspace(bundle, workspace, binding = {}) {
145
+ const reasons = [];
146
+ if (String(binding.schema || '') !== HANDOFF_WORKSPACE_ARCHIVE_BINDING_SCHEMA_ID) reasons.push('workspace-archive-binding-schema-invalid');
147
+ if (String(binding.workspaceId || '') !== String(workspace.id || '')) reasons.push('workspace-archive-binding-workspace-id-mismatch');
148
+ if (String(binding.transportCorrelationKey || '') !== String(workspace.transportCorrelationKey || '')) reasons.push('workspace-archive-binding-stale');
149
+ const coverage = String(workspace.materialization || '') === 'bounded' ? 'bounded' : String(workspace.materialization || '') === 'complete' ? 'complete' : '';
150
+ const coverageEvidence = coverage === 'bounded' ? (workspace.scopeEvidence || {}) : (workspace.completenessEvidence || {});
151
+ if (!coverage || String(workspace.qualification || '') !== 'qualified' || String(coverageEvidence.state || '') !== 'qualified') reasons.push(coverage === 'bounded' ? 'workspace-archive-bounded-scope-unqualified' : 'workspace-archive-completeness-unqualified');
152
+ const expectedRepresentationKind = coverage === 'bounded' ? 'bounded-workspace-snapshot' : 'complete-workspace-snapshot';
153
+ if (String(binding.coverage || coverage) !== coverage || String(binding.representation?.kind || '') !== expectedRepresentationKind) reasons.push('workspace-archive-representation-kind-invalid');
154
+ if (String(binding.provider?.kind || '') !== HANDOFF_WORKSPACE_ARCHIVE_PROVIDER_KIND || String(binding.provider?.state || '') !== 'ready') reasons.push('workspace-archive-provider-unavailable');
155
+ if (String(binding.representation?.codec || '') !== HANDOFF_WORKSPACE_ARCHIVE_CODEC || String(binding.representation?.mediaType || '') !== 'application/zip') reasons.push('workspace-archive-decoder-unavailable');
156
+ if (String(binding.entryMap?.normalization || '') !== HANDOFF_WORKSPACE_INNER_PATH_NORMALIZATION) reasons.push('workspace-archive-normalization-unqualified');
157
+
158
+ const targetPath = String(binding.workspaceTarget?.packagePath || '');
159
+ const targetFiles = (bundle.files || []).filter((file) => String(file.path || '') === targetPath);
160
+ const targetData = targetFiles.length === 1 ? packageFileBytes(targetFiles[0]) : new Uint8Array();
161
+ if (!targetPath || targetFiles.length !== 1) reasons.push(targetFiles.length > 1 ? 'workspace-target-ambiguous' : 'workspace-target-unresolvable');
162
+ if (targetData.byteLength) {
163
+ if (Number(binding.workspaceTarget?.bytes || 0) !== targetData.byteLength) reasons.push('workspace-target-byte-count-mismatch');
164
+ if (String(binding.workspaceTarget?.sha256 || '') !== sha256Hex(targetData)) reasons.push('workspace-target-digest-mismatch');
165
+ }
166
+ if (String(binding.workspaceTarget?.schema || '') !== 'tiinex.workspace.v1') reasons.push('workspace-target-schema-binding-invalid');
167
+
168
+ const archivePath = String(binding.representation?.packagePath || '');
169
+ const archiveFiles = (bundle.files || []).filter((file) => String(file.path || '') === archivePath);
170
+ const archiveData = archiveFiles.length === 1 ? packageFileBytes(archiveFiles[0]) : new Uint8Array();
171
+ if (!archivePath || archiveFiles.length !== 1) reasons.push(archiveFiles.length > 1 ? 'workspace-archive-locator-ambiguous' : 'workspace-archive-locator-unresolved');
172
+ if (archiveData.byteLength) {
173
+ if (Number(binding.representation?.bytes || 0) !== archiveData.byteLength) reasons.push('workspace-archive-byte-count-mismatch');
174
+ if (String(binding.representation?.digest?.method || '') !== 'sha256') reasons.push('workspace-archive-digest-method-invalid');
175
+ if (String(binding.representation?.digest?.value || '') !== sha256Hex(archiveData)) reasons.push('workspace-archive-digest-mismatch');
176
+ if (String(binding.representation?.digest?.target || '') !== 'archive-bytes-as-carried') reasons.push('workspace-archive-digest-target-invalid');
177
+ }
178
+
179
+ const parsedArchive = archiveData.byteLength ? inspectStoredWorkspaceArchive(archiveData, { ownedBytes: true }) : deepFreeze({ state: 'invalid', entries: Object.freeze([]), findings: Object.freeze([]) });
180
+ if (archiveData.byteLength && parsedArchive.state !== 'qualified') reasons.push(...parsedArchive.findings.map((item) => archiveFindingReason(item.code)));
181
+ const declaredEntries = normalizeBindingEntries(binding.entryMap?.entries || [], reasons);
182
+ if (Number(binding.entryMap?.count || 0) !== declaredEntries.length) reasons.push('workspace-archive-entry-map-count-mismatch');
183
+ if (!sameEntryIdentitySet(declaredEntries, parsedArchive.entries || [])) reasons.push('workspace-archive-entry-map-mismatch');
184
+ if (!sameEntryIdentitySet(declaredEntries, workspace.includedEntries || [])) reasons.push('workspace-archive-binding-stale');
185
+
186
+ const bindingEvidence = coverage === 'bounded' ? (binding.scope || {}) : (binding.completeness || {});
187
+ if (String(bindingEvidence.state || '') !== 'qualified') reasons.push(coverage === 'bounded' ? 'workspace-archive-bounded-scope-unqualified' : 'workspace-archive-completeness-unqualified');
188
+ if (Number(bindingEvidence.entryCount || 0) !== declaredEntries.length) reasons.push(coverage === 'bounded' ? 'workspace-archive-bounded-scope-entry-count-mismatch' : 'workspace-archive-completeness-entry-count-mismatch');
189
+ const totalBytes = declaredEntries.reduce((sum, entry) => sum + Number(entry.bytes || 0), 0);
190
+ if (Number(bindingEvidence.totalBytes || 0) !== totalBytes) reasons.push(coverage === 'bounded' ? 'workspace-archive-bounded-scope-byte-count-mismatch' : 'workspace-archive-completeness-byte-count-mismatch');
191
+ if (String(bindingEvidence.entriesFingerprint || '') && String(bindingEvidence.entriesFingerprint || '') !== entrySetFingerprint(declaredEntries)) reasons.push(coverage === 'bounded' ? 'workspace-archive-bounded-scope-fingerprint-mismatch' : 'workspace-archive-completeness-fingerprint-mismatch');
192
+ if (String(coverageEvidence.entriesFingerprint || '') && String(coverageEvidence.entriesFingerprint) !== entrySetFingerprint(declaredEntries)) reasons.push(coverage === 'bounded' ? 'workspace-archive-bounded-scope-evidence-stale' : 'workspace-archive-completeness-evidence-stale');
193
+ if (Number(coverageEvidence.entryCount || declaredEntries.length) !== declaredEntries.length) reasons.push(coverage === 'bounded' ? 'workspace-archive-bounded-scope-evidence-stale' : 'workspace-archive-completeness-evidence-stale');
194
+ if (Number(coverageEvidence.totalBytes || totalBytes) !== totalBytes) reasons.push(coverage === 'bounded' ? 'workspace-archive-bounded-scope-evidence-stale' : 'workspace-archive-completeness-evidence-stale');
195
+ if (coverage === 'bounded') {
196
+ if (String(binding.selection?.rule || '') !== 'explicit-binding-per-bounded-scope') reasons.push('workspace-archive-bounded-selection-unqualified');
197
+ if (String(bindingEvidence.scopeBasis || '') !== 'exact-representation-entry-set' || String(bindingEvidence.includedEntryAuthority || '') !== 'qualified-decoded-entry-set' || String(bindingEvidence.omittedEntryMeaning || '') !== 'outside-representation-not-absent-from-workspace' || String(bindingEvidence.sourceMembershipClaim || '') !== 'represented-entries-are-workspace-relative-source-bytes' || String(bindingEvidence.recoveryClosureBoundary || '') !== 'separate-qualified-closure') reasons.push('workspace-archive-bounded-scope-unqualified');
198
+ }
199
+
200
+ const targetInner = normalizeHandoffWorkspaceInnerPath(binding.workspaceTarget?.innerPath || '');
201
+ if (targetInner.state !== 'qualified') reasons.push('workspace-target-inner-path-unqualified');
202
+ const parsedByPath = new Map((parsedArchive.entries || []).map((entry) => [entry.path, entry]));
203
+ const targetArchiveEntry = targetInner.state === 'qualified' ? parsedByPath.get(targetInner.path) : null;
204
+ if (!targetArchiveEntry) reasons.push('workspace-target-archive-entry-unresolved');
205
+ else if (targetData.byteLength && (targetArchiveEntry.bytes !== targetData.byteLength || targetArchiveEntry.sha256 !== sha256Hex(targetData))) reasons.push('workspace-target-archive-entry-mismatch');
206
+
207
+ if (targetData.byteLength && targetInner.state === 'qualified') {
208
+ const targetQualification = qualifyHandoffWorkspaceTarget({ targetPath: targetInner.path, targetData, entries: parsedArchive.entries || [] });
209
+ if (targetQualification.state !== 'qualified') reasons.push(...(targetQualification.reasons || ['workspace-target-artifact-conformance-unqualified']));
210
+ const declaredSelfState = String(binding.workspaceTarget?.selfIntegrity?.state || '');
211
+ if (declaredSelfState !== 'verified') reasons.push('workspace-target-self-integrity-descriptor-unverified');
212
+ if (declaredSelfState && declaredSelfState !== String(targetQualification.selfIntegrity?.state || '')) reasons.push('workspace-target-self-integrity-stale');
213
+ if (declaredSelfState === 'verified' && String(binding.workspaceTarget?.selfIntegrity?.value || '') !== String(targetQualification.selfIntegrity?.value || '')) reasons.push('workspace-target-self-integrity-mismatch');
214
+ }
215
+
216
+ const declaredByPath = new Map(declaredEntries.map((entry) => [entry.path, entry]));
217
+ const runtimeEntries = (parsedArchive.entries || []).map((entry) => {
218
+ const declared = declaredByPath.get(entry.path) || {};
219
+ return deepFreeze({ path: entry.path, innerPath: entry.path, archivePackagePath: archivePath, packagePath: archivePath, bytes: entry.bytes, sha256: entry.sha256, referenceTarget: String(declared.referenceTarget || ''), data: entry.data });
220
+ });
221
+ return deepFreeze({
222
+ state: reasons.length ? (reasons.includes('workspace-target-ambiguous') || reasons.includes('workspace-archive-locator-ambiguous') ? 'ambiguous' : 'blocked') : 'qualified',
223
+ id: String(workspace.id || ''),
224
+ title: String(workspace.title || workspace.id || ''),
225
+ mode: 'archive',
226
+ materialization: workspace,
227
+ entries: Object.freeze(runtimeEntries),
228
+ workspaceTarget: deepFreeze({ ...(binding.workspaceTarget || {}), data: targetData }),
229
+ archive: deepFreeze({ ...(binding.representation || {}), data: archiveData }),
230
+ binding,
231
+ reasons: Object.freeze([...new Set(reasons)]),
232
+ authority: Object.freeze({ locatorAuthority: false, filenameAuthority: false, packagePlacementAuthority: false, bindingAuthority: 'manufacture-material-closure-transport-evidence-only', recipientSemanticActivationAuthority: false })
233
+ });
234
+ }
235
+
236
+ function normalizeBindingEntries(entries = [], reasons = []) {
237
+ const out = [];
238
+ const seen = new Set();
239
+ for (const entry of entries) {
240
+ const normalized = normalizeHandoffWorkspaceInnerPath(entry.path || entry.innerPath || '');
241
+ if (normalized.state !== 'qualified') { reasons.push(normalized.reason || 'workspace-inner-path-unsafe'); continue; }
242
+ if (seen.has(normalized.path)) { reasons.push('workspace-inner-path-duplicate'); continue; }
243
+ seen.add(normalized.path);
244
+ const bytes = Number(entry.bytes || 0);
245
+ const sha256 = String(entry.sha256 || '');
246
+ if (bytes < 0 || !/^[0-9a-f]{64}$/i.test(sha256)) reasons.push('workspace-archive-entry-map-identity-invalid');
247
+ out.push(deepFreeze({ path: normalized.path, bytes, sha256: sha256.toLowerCase(), referenceTarget: String(entry.referenceTarget || '') }));
248
+ }
249
+ return out.sort((a, b) => a.path.localeCompare(b.path));
250
+ }
251
+
252
+ function sameEntryIdentitySet(a = [], b = []) {
253
+ const left = normalizeEntryIdentitySet(a);
254
+ const right = normalizeEntryIdentitySet(b);
255
+ return stableJson(left) === stableJson(right);
256
+ }
257
+ function normalizeEntryIdentitySet(entries = []) {
258
+ return entries.map((entry) => ({ path: String(entry.path || entry.innerPath || ''), bytes: Number(entry.bytes || 0), sha256: String(entry.sha256 || '').toLowerCase(), referenceTarget: String(entry.referenceTarget || '') })).sort((a, b) => a.path.localeCompare(b.path));
259
+ }
260
+ function entrySetFingerprint(entries = []) { return sha256Hex(utf8Bytes(stableJson(normalizeEntryIdentitySet(entries)))); }
261
+ function blockedWorkspace(workspace = {}, mode = '', reasons = [], state = 'blocked') { return deepFreeze({ state, id: String(workspace.id || ''), title: String(workspace.title || workspace.id || ''), mode, materialization: workspace, entries: Object.freeze([]), workspaceTarget: null, archive: null, reasons: Object.freeze(reasons), authority: Object.freeze({ locatorAuthority: false, filenameAuthority: false, packagePlacementAuthority: false }) }); }
262
+ function providerFinding(provider = {}, reason = '') { return finding('error', `portable.handoff-workspace-provider.${String(reason || 'unqualified').replace(/[^a-z0-9.-]+/gi, '-')}`, 'Workspace byte provider could not qualify exact workspace bytes.', { workspaceId: String(provider.id || ''), mode: String(provider.mode || ''), reason }); }
263
+ function archiveFindingReason(code = '') { const suffix = String(code || '').split('.').pop() || 'archive-invalid'; return `workspace-archive-${suffix}`; }
264
+ function countBy(items = [], keyFn) { const out = new Map(); for (const item of items) { const key = keyFn(item); if (key) out.set(key, (out.get(key) || 0) + 1); } return out; }
265
+ function decodeUtf8(data) { try { return new TextDecoder('utf-8', { fatal: true }).decode(data); } catch { return ''; } }
266
+ function stableJson(value) { return JSON.stringify(sortJson(value)); }
267
+ 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])])); }
268
+ function finding(severity, code, message, extra = {}) { return Object.freeze({ severity, code, message, ...extra }); }
269
+ function dedupeFindings(items = []) { const map = new Map(); for (const item of items) { const key = `${item.severity || ''}:${item.code || ''}:${item.workspaceId || ''}:${item.reason || ''}:${item.path || ''}`; if (!map.has(key)) map.set(key, item); } return [...map.values()]; }
270
+ 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); }
271
+