@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,177 @@
1
+ import { packageFileByteView, sha256Hex } from '../../../export/package.bytes.js';
2
+ import { qualifyHandoffWorkspaceTarget } from './workspaceTargetConformance.js';
3
+ import { inspectPortableToolingBootstrap } from './toolingBootstrap.js';
4
+ import { parseRecipientV2ExternalPayload, parseRecipientV2WorkspaceRepresentation } from './recipientV2.artifacts.js';
5
+ import {
6
+ finding,
7
+ inspectRecipientZipPayload,
8
+ oneRecipientFile,
9
+ recipientEntriesFingerprint,
10
+ recipientWorkspaceDescriptor,
11
+ virtualCacheMaterial
12
+ } from './recipientV2.inspect.helpers.js';
13
+ import {
14
+ inspectEndpointRolePointers,
15
+ inspectPackageLocalLineage,
16
+ inspectParticipantRolePointers,
17
+ parentTrace
18
+ } from './recipientV2.lineage.js';
19
+
20
+ export function inspectRecipientV2WorkspaceSurface({ generatedArtifacts = [], rootArtifact = null, index = new Map(), findings = [], transportManifest = null } = {}) {
21
+ const payloadArtifacts = generatedArtifacts.filter((item) => item.schemaId === 'tiinex.external.payload.v1' && item.status === 'qualified');
22
+ const workspaceArtifacts = generatedArtifacts.filter((item) => item.schemaId === 'tiinex.workspace.v1' && item.facts?.role === 'workspace-node' && item.status === 'qualified');
23
+ const workspaceRepresentationArtifacts = generatedArtifacts.filter((item) => item.schemaId === 'tiinex.workspace.representation.v1' && item.status === 'qualified');
24
+ const routePointers = generatedArtifacts.filter((item) => item.schemaId === 'tiinex.pointer.v1' && item.facts?.role === 'handoff-route' && item.status === 'qualified');
25
+ const endpointRolePointers = generatedArtifacts.filter((item) => item.schemaId === 'tiinex.pointer.v1' && item.facts?.role === 'endpoint-role' && item.status === 'qualified');
26
+ const participantRolePointers = generatedArtifacts.filter((item) => item.schemaId === 'tiinex.pointer.v1' && item.facts?.role === 'participant-role' && item.status === 'qualified');
27
+ const workspacePayloadArtifacts = payloadArtifacts.filter((item) => item.facts?.role === 'workspace-representation-payload');
28
+ const bootstrapPayloadArtifacts = payloadArtifacts.filter((item) => item.facts?.role === 'portable Tooling bootstrap runtime for recipient orientation and verification');
29
+ const cachePayloadArtifacts = payloadArtifacts.filter((item) => item.facts?.role === 'workspace-scoped Handoff dependency cache');
30
+ if (bootstrapPayloadArtifacts.length > 1) findings.push(finding('error', 'portable.handoff-v2-surface.bootstrap.ambiguous', 'Recipient-facing v2 package exposes more than one bootstrap payload artifact.'));
31
+
32
+ inspectPackageLocalLineage({ generatedArtifacts, rootArtifact, findings });
33
+
34
+ const workspaceParts = [];
35
+ const workspaceDescriptors = [];
36
+ const virtualWorkspaceTargetFiles = [];
37
+ const archiveClaims = new Map();
38
+ const representationClaims = new Map();
39
+ const workspacePayloadClaims = new Map();
40
+ const caches = cachePayloadArtifacts.map((artifact) => inspectCache(artifact, index, archiveClaims, findings, transportManifest)).filter(Boolean);
41
+ const recoveryEntriesByWorkspace = indexCacheRecoveryEntries(caches);
42
+ for (const artifact of workspaceArtifacts) {
43
+ const facts = artifact.facts || {};
44
+ const workspaceId = String(facts.workspaceId || '');
45
+ if (rootArtifact && parentTrace(artifact) !== rootArtifact.path) findings.push(finding('error', 'portable.handoff-v2-surface.workspace.parent-mismatch', 'Package-local Workspace node must be a direct child of the package-local root.', { workspaceId, path: artifact.path, expectedParent: rootArtifact.path, observedParent: parentTrace(artifact) }));
46
+ const representationCandidates = workspaceRepresentationArtifacts.filter((candidate) => parseRecipientV2WorkspaceRepresentation(candidate.markdown).workspaceArtifactPath === artifact.path);
47
+ if (representationCandidates.length !== 1) {
48
+ findings.push(finding('error', representationCandidates.length ? 'portable.handoff-v2-surface.workspace-representation.ambiguous' : 'portable.handoff-v2-surface.workspace-representation.missing', 'Each carried Workspace must resolve exactly one schema-valid canonical Workspace Representation binding.', { workspaceId, workspaceArtifactPath: artifact.path, count: representationCandidates.length }));
49
+ continue;
50
+ }
51
+ const representationArtifact = representationCandidates[0];
52
+ addRecipientClaim(representationClaims, representationArtifact.path, artifact.path);
53
+ const representation = parseRecipientV2WorkspaceRepresentation(representationArtifact.markdown);
54
+ if (parentTrace(representationArtifact) !== artifact.path) findings.push(finding('error', 'portable.handoff-v2-surface.workspace-representation.parent-mismatch', 'Workspace Representation must be a package-local child of the Workspace it binds.', { workspaceId, path: representationArtifact.path, expectedParent: artifact.path, observedParent: parentTrace(representationArtifact) }));
55
+ if (String(representationArtifact.facts?.workspaceId || '') !== workspaceId || String(representationArtifact.facts?.workspaceArtifactPath || '') !== artifact.path || String(representationArtifact.facts?.payloadArtifactPath || '') !== representation.payloadArtifactPath) findings.push(finding('error', 'portable.handoff-v2-surface.workspace-representation.stale-transport-witness', 'Workspace Representation transport witness diverges from the visible canonical binding and must be treated as stale.', { workspaceId, path: representationArtifact.path }));
56
+
57
+ const payloadArtifactMatches = workspacePayloadArtifacts.filter((candidate) => candidate.path === representation.payloadArtifactPath);
58
+ if (payloadArtifactMatches.length !== 1) {
59
+ findings.push(finding('error', payloadArtifactMatches.length ? 'portable.handoff-v2-surface.workspace-representation-payload.ambiguous' : 'portable.handoff-v2-surface.workspace-representation-payload.missing', 'Workspace Representation must resolve exactly one schema-valid External Payload endpoint.', { workspaceId, representationArtifactPath: representationArtifact.path, payloadArtifactPath: representation.payloadArtifactPath, count: payloadArtifactMatches.length }));
60
+ continue;
61
+ }
62
+ const payloadArtifact = payloadArtifactMatches[0];
63
+ addRecipientClaim(workspacePayloadClaims, payloadArtifact.path, representationArtifact.path);
64
+ if (parentTrace(payloadArtifact) !== artifact.path) findings.push(finding('error', 'portable.handoff-v2-surface.workspace-representation-payload.parent-mismatch', 'Workspace representation External Payload must be a package-local child of the bound Workspace.', { workspaceId, path: payloadArtifact.path, expectedParent: artifact.path, observedParent: parentTrace(payloadArtifact) }));
65
+ const payload = parseRecipientV2ExternalPayload(payloadArtifact.markdown);
66
+ if (payload.mediaType !== 'application/zip' || payload.format !== 'deterministic stored ZIP' || payload.integrityStatus !== 'verified' || payload.integrityMethod !== 'sha256' || payload.integrityTarget !== 'exact payload bytes as carried at the declared local Location') findings.push(finding('error', 'portable.handoff-v2-surface.workspace-representation-payload.contract-invalid', 'Workspace representation payload does not satisfy the exact archive/integrity contract required for provider activation.', { workspaceId, path: payloadArtifact.path }));
67
+ const archiveFile = oneRecipientFile(index, payload.location);
68
+ if (!archiveFile) { findings.push(finding('error', 'portable.handoff-v2-surface.workspace-representation-payload.location-unresolved', 'Workspace Representation payload Location does not resolve to exactly one package-local payload file.', { workspaceId, path: payload.location || '' })); continue; }
69
+ addRecipientClaim(archiveClaims, archiveFile.path, payloadArtifact.path);
70
+ const archive = inspectRecipientZipPayload(archiveFile, { archivePath: payload.location, archiveBytes: payload.bytes, archiveSha256: payload.integrityValue }, findings, 'workspace-representation-payload', transportManifest.identityByPath?.get?.(archiveFile.path));
71
+ if (!archive || archive.archive.state !== 'qualified') continue;
72
+ const entries = archive.archive.entries || [];
73
+ const totalBytes = entries.reduce((sum, entry) => sum + Number(entry.bytes || 0), 0);
74
+ const entriesFingerprint = recipientEntriesFingerprint(entries);
75
+ const coverage = representation.coverage === 'bounded' ? 'bounded' : 'complete';
76
+ if (Number(facts.entryCount || 0) !== entries.length || Number(facts.totalBytes || 0) !== totalBytes || String(facts.entriesFingerprint || '') !== entriesFingerprint || String(facts.coverage || 'complete') !== coverage || String(facts.coverageState || facts.completenessState || '') !== 'qualified') findings.push(finding('error', 'portable.handoff-v2-surface.workspace.transport-witness-stale', 'Workspace transport witness diverges from the canonical representation payload or exact archive entry set.', { workspaceId }));
77
+ if (String(representationArtifact.facts?.archivePath || '') !== payload.location || String(representationArtifact.facts?.archiveSha256 || '') !== archive.sha256 || Number(representationArtifact.facts?.entryCount || 0) !== entries.length || String(representationArtifact.facts?.entriesFingerprint || '') !== entriesFingerprint || String(representationArtifact.facts?.coverage || 'complete') !== coverage || String(representationArtifact.facts?.coverageState || representationArtifact.facts?.completenessState || '') !== 'qualified') findings.push(finding('error', 'portable.handoff-v2-surface.workspace-representation.stale-archive-witness', 'Workspace Representation transport witness diverges from the exact qualified payload and entry set.', { workspaceId, path: representationArtifact.path }));
78
+ if (String(payloadArtifact.facts?.workspaceId || '') !== workspaceId || String(payloadArtifact.facts?.archivePath || '') !== payload.location || String(payloadArtifact.facts?.archiveSha256 || '') !== archive.sha256) findings.push(finding('error', 'portable.handoff-v2-surface.workspace-representation-payload.stale-transport-witness', 'Workspace representation payload transport witness diverges from the visible payload contract or exact payload bytes.', { workspaceId, path: payloadArtifact.path }));
79
+
80
+ const targetInnerPath = String(representation.workspaceArtifactInnerPath || '');
81
+ const targetMatches = entries.filter((entry) => String(entry.path || '') === targetInnerPath);
82
+ if (targetMatches.length !== 1) { findings.push(finding('error', 'portable.handoff-v2-surface.workspace-source-target.unresolvable', 'Canonical Workspace Representation must resolve exactly one durable source Workspace artifact inside its payload.', { workspaceId, targetInnerPath, count: targetMatches.length })); continue; }
83
+ const targetEntry = targetMatches[0];
84
+ const targetData = packageFileByteView({ data: targetEntry.data });
85
+ const targetSha256 = sha256Hex(targetData);
86
+ if (String(facts.sourceWorkspaceTargetInnerPath || '') !== targetInnerPath || Number(facts.sourceWorkspaceTargetBytes || 0) !== targetData.byteLength || String(facts.sourceWorkspaceTargetSha256 || '') !== targetSha256) findings.push(finding('error', 'portable.handoff-v2-surface.workspace-source-target.stale-transport-witness', 'Workspace transport witness diverges from the canonical representation-selected durable Workspace artifact.', { workspaceId, targetInnerPath }));
87
+ if (String(representationArtifact.facts?.sourceWorkspaceTargetInnerPath || '') !== targetInnerPath) findings.push(finding('error', 'portable.handoff-v2-surface.workspace-representation.target-stale', 'Workspace Representation transport witness selects a different durable Workspace target than its visible canonical correlation.', { workspaceId, targetInnerPath }));
88
+ const targetQualification = qualifyHandoffWorkspaceTarget({ targetPath: targetInnerPath, targetData, entries, parentCandidates: recoveryEntriesByWorkspace.get(workspaceId) || [] });
89
+ if (targetQualification.state !== 'qualified') findings.push(finding('error', 'portable.handoff-v2-surface.workspace-source-target.unqualified', 'Exact durable source Workspace artifact inside the archive does not independently qualify.', { workspaceId, targetInnerPath, reasons: targetQualification.reasons || [] }));
90
+
91
+ const targetVirtualPath = `recipient.v2.workspace-target/${safeToken(workspaceId)}.workspace.md`;
92
+ const targetVirtualFile = Object.freeze({ path: targetVirtualPath, data: targetData, bytes: targetData.byteLength, sha256: targetSha256, kind: 'recipient-v2-virtual-source-workspace-target' });
93
+ virtualWorkspaceTargetFiles.push(targetVirtualFile);
94
+ const descriptorPart = recipientWorkspaceDescriptor({ workspaceId, facts, representation, payload, entries, targetMarkdown: decodeUtf8(targetData), targetPackagePath: targetVirtualPath, targetFile: { bytes: targetData.byteLength, sha256: targetSha256 }, archiveFile: { path: archiveFile.path, bytes: archive.bytes, sha256: archive.sha256 } });
95
+ workspaceDescriptors.push(descriptorPart);
96
+ workspaceParts.push({ workspaceId, artifact, facts, representationArtifact, representation, payloadArtifact, payload, targetFile: targetVirtualFile, sourceTargetEntry: targetEntry, targetQualification, archiveFile, archive, descriptorPart });
97
+ }
98
+ for (const artifact of workspaceRepresentationArtifacts) if ((representationClaims.get(artifact.path) || []).length !== 1) findings.push(finding('error', 'portable.handoff-v2-surface.workspace-representation.unowned', 'Every canonical Workspace Representation must bind exactly one carried Workspace.', { path: artifact.path, claims: (representationClaims.get(artifact.path) || []).length }));
99
+ for (const artifact of workspacePayloadArtifacts) if ((workspacePayloadClaims.get(artifact.path) || []).length !== 1) findings.push(finding('error', 'portable.handoff-v2-surface.workspace-representation-payload.unowned', 'Every Workspace representation External Payload must be selected by exactly one canonical Workspace Representation.', { path: artifact.path, claims: (workspacePayloadClaims.get(artifact.path) || []).length }));
100
+
101
+ const bootstrap = inspectBootstrap(bootstrapPayloadArtifacts[0], index, archiveClaims, findings, transportManifest);
102
+ const cacheWorkspaceIds = new Set();
103
+ for (const cache of caches) {
104
+ const workspaceId = String(cache.facts?.workspaceId || '');
105
+ if (!workspaceId) findings.push(finding('error', 'portable.handoff-v2-surface.cache.workspace-id-missing', 'Workspace-scoped dependency cache must declare its owning Workspace id.', { path: cache.artifact.path || '' }));
106
+ else if (cacheWorkspaceIds.has(workspaceId)) findings.push(finding('error', 'portable.handoff-v2-surface.cache.workspace-ambiguous', 'A Workspace may expose at most one package-local dependency cache.', { workspaceId }));
107
+ else cacheWorkspaceIds.add(workspaceId);
108
+ const workspace = workspaceParts.find((item) => item.workspaceId === workspaceId);
109
+ if (!workspace) findings.push(finding('error', 'portable.handoff-v2-surface.cache.workspace-unresolved', 'Workspace-scoped dependency cache does not resolve to a carried qualified Workspace.', { workspaceId, path: cache.artifact.path || '' }));
110
+ else if (parentTrace(cache.artifact) !== workspace.artifact.path) findings.push(finding('error', 'portable.handoff-v2-surface.cache.parent-mismatch', 'Workspace-scoped dependency cache Parent must be its owning package-local Workspace node.', { workspaceId, path: cache.artifact.path || '', expectedParent: workspace.artifact.path, observedParent: parentTrace(cache.artifact) }));
111
+ }
112
+ const virtualCacheParts = caches.map((cache) => virtualCacheMaterial(cache, findings));
113
+ const virtualCache = { files: Object.freeze(virtualCacheParts.flatMap((item) => item.files || [])), materialized: Object.freeze(virtualCacheParts.flatMap((item) => item.materialized || [])) };
114
+ inspectEndpointRolePointers(endpointRolePointers, workspaceParts, caches, findings);
115
+ inspectParticipantRolePointers(participantRolePointers, workspaceParts, caches, findings);
116
+
117
+ return Object.freeze({
118
+ routePointers: Object.freeze(routePointers),
119
+ endpointRolePointers: Object.freeze(endpointRolePointers),
120
+ participantRolePointers: Object.freeze(participantRolePointers),
121
+ bootstrap: bootstrap || null,
122
+ workspaceParts: Object.freeze(workspaceParts),
123
+ workspaceDescriptors: Object.freeze(workspaceDescriptors),
124
+ virtualWorkspaceTargetFiles: Object.freeze(virtualWorkspaceTargetFiles),
125
+ archiveClaims,
126
+ caches: Object.freeze(caches),
127
+ virtualCache: Object.freeze(virtualCache)
128
+ });
129
+ }
130
+
131
+ function indexCacheRecoveryEntries(caches = []) {
132
+ const map = new Map();
133
+ for (const cache of caches || []) {
134
+ const workspaceId = String(cache?.facts?.workspaceId || '');
135
+ if (!workspaceId || cache?.archive?.archive?.state !== 'qualified') continue;
136
+ const byArchivePath = new Map((cache.archive.archive.entries || []).map((entry) => [String(entry.path || ''), entry]));
137
+ const entries = map.get(workspaceId) || [];
138
+ for (const material of cache.facts?.materials || []) {
139
+ const originalPath = String(material.originalPath || '').replace(/\\/g, '/').replace(/^\/+/, '');
140
+ const entry = byArchivePath.get(String(material.archiveEntry || ''));
141
+ if (!originalPath || !entry) continue;
142
+ entries.push(Object.freeze({ path: originalPath, data: entry.data, bytes: Number(entry.bytes || 0), sha256: String(entry.sha256 || '') }));
143
+ }
144
+ map.set(workspaceId, entries);
145
+ }
146
+ return map;
147
+ }
148
+ function inspectBootstrap(artifact, index, claims, findings, transportManifest = null) {
149
+ if (!artifact) return null;
150
+ const facts = artifact.facts || {};
151
+ const file = oneRecipientFile(index, facts.archivePath);
152
+ if (!file) { findings.push(finding('error', 'portable.handoff-v2-surface.bootstrap.payload-missing', 'Bootstrap External Payload artifact does not resolve to its local ZIP companion.')); return null; }
153
+ addRecipientClaim(claims, file.path, artifact.path);
154
+ const archive = inspectRecipientZipPayload(file, facts, findings, 'bootstrap', transportManifest?.identityByPath?.get?.(file.path));
155
+ if (!archive || archive.archive.state !== 'qualified') return { artifact, file, facts, archive, inspection: null };
156
+ const entries = archive.archive.entries || [];
157
+ const totalBytes = entries.reduce((sum, entry) => sum + Number(entry.bytes || 0), 0);
158
+ if (Number(facts.entryCount || 0) !== entries.length || Number(facts.totalBytes || 0) !== totalBytes || String(facts.entriesFingerprint || '') !== recipientEntriesFingerprint(entries)) findings.push(finding('error', 'portable.handoff-v2-surface.bootstrap.identity-set-mismatch', 'Bootstrap archive entry identity set differs from its visible declaration.'));
159
+ const reconstructed = { files: entries.map((entry) => Object.freeze({ path: `tiinex.bootstrap/${entry.path}`, data: entry.data })) };
160
+ const inspection = inspectPortableToolingBootstrap(reconstructed);
161
+ if (inspection.status !== 'valid') findings.push(finding('error', 'portable.handoff-v2-surface.bootstrap.unqualified', 'Reconstructed bootstrap payload does not qualify against its embedded manifest.', { causes: inspection.findings || [] }));
162
+ return { artifact, file, facts, archive, inspection };
163
+ }
164
+
165
+ function inspectCache(artifact, index, claims, findings, transportManifest = null) {
166
+ if (!artifact) return null;
167
+ const facts = artifact.facts || {};
168
+ const file = oneRecipientFile(index, facts.archivePath);
169
+ if (!file) { findings.push(finding('error', 'portable.handoff-v2-surface.cache.payload-missing', 'Context cache External Payload artifact does not resolve to its local ZIP companion.')); return null; }
170
+ addRecipientClaim(claims, file.path, artifact.path);
171
+ const archive = inspectRecipientZipPayload(file, facts, findings, 'cache', transportManifest?.identityByPath?.get?.(file.path));
172
+ return { artifact, file, facts, archive };
173
+ }
174
+
175
+ export function addRecipientClaim(map, path, owner) { const key = String(path || ''); const list = map.get(key) || []; list.push(String(owner || '')); map.set(key, list); }
176
+ function decodeUtf8(data) { try { return new TextDecoder('utf-8', { fatal: true }).decode(data); } catch { return ''; } }
177
+ function safeToken(value = '') { return String(value || '').trim().toLowerCase().replace(/[^a-z0-9._-]+/g, '-').replace(/^-+|-+$/g, '').slice(0, 100) || 'workspace'; }
@@ -0,0 +1,142 @@
1
+ import { packageFileByteView, sha256Hex } from '../../../export/package.bytes.js';
2
+ import { finding, oneRecipientFile } from './recipientV2.inspect.helpers.js';
3
+
4
+ export function buildPackageLocalParentResolver(index) {
5
+ return ({ parent = {} } = {}) => {
6
+ const targets = new Set();
7
+ if (parent.trace) targets.add(String(parent.trace));
8
+ for (const entry of parent.originEntries || []) if (String(entry?.label || '') === 'relative' && entry?.target) targets.add(String(entry.target));
9
+ const resolved = [...targets].map((path) => oneRecipientFile(index, path)).filter(Boolean);
10
+ const unique = new Map(resolved.map((file) => [String(file.path || ''), file]));
11
+ if (unique.size !== 1) return Object.freeze({ state: unique.size > 1 ? 'ambiguous' : 'unavailable', reason: unique.size > 1 ? 'multiple-package-local-parent-candidates' : 'package-local-parent-not-carried' });
12
+ const file = [...unique.values()][0];
13
+ const markdown = decodeUtf8(packageFileByteView(file));
14
+ return markdown ? Object.freeze({ state: 'qualified', markdown, basis: 'package-local-parent-trace', packagePath: String(file.path || ''), sha256: sha256Hex(packageFileByteView(file)) }) : Object.freeze({ state: 'unavailable', reason: 'package-local-parent-not-markdown' });
15
+ };
16
+ }
17
+
18
+ export function inspectPackageLocalLineage({ generatedArtifacts = [], rootArtifact = null, findings = [] } = {}) {
19
+ if (!rootArtifact) return;
20
+ const byPath = new Map(generatedArtifacts.map((item) => [item.path, item]));
21
+ for (const artifact of generatedArtifacts) {
22
+ const path = String(artifact.path || '');
23
+ const trace = parentTrace(artifact);
24
+ const childDimension = numericDimension(path);
25
+ if (artifact === rootArtifact) {
26
+ if (childDimension !== '001') findings.push(finding('error', 'portable.handoff-v2-surface.lineage.root-dimension-invalid', 'Package root must occupy numeric dimension 001.', { path, dimension: childDimension }));
27
+ continue;
28
+ }
29
+ if (!trace) { findings.push(finding('error', 'portable.handoff-v2-surface.lineage.parent-missing', 'Every generated package-local artifact except the root must declare one Parent.', { path })); continue; }
30
+ const parent = byPath.get(trace);
31
+ if (!parent) { findings.push(finding('error', 'portable.handoff-v2-surface.lineage.parent-unresolved', 'Generated package-local Parent trace does not resolve to another carried generated artifact.', { path, parent: trace })); continue; }
32
+ const parentDimension = numericDimension(trace);
33
+ const expectedParentDimension = parentNumericDimension(childDimension);
34
+ if (!childDimension || !parentDimension || parentDimension !== expectedParentDimension) findings.push(finding('error', 'portable.handoff-v2-surface.lineage.path-parent-mismatch', 'Numeric pathing must mirror the explicitly declared package-local Parent relation.', { path, childDimension, parent: trace, parentDimension, expectedParentDimension }));
35
+
36
+ const seen = new Set([path]);
37
+ let cursor = artifact;
38
+ let reachedRoot = false;
39
+ while (cursor && cursor !== rootArtifact) {
40
+ const parentPath = parentTrace(cursor);
41
+ if (!parentPath || seen.has(parentPath)) break;
42
+ seen.add(parentPath);
43
+ cursor = byPath.get(parentPath) || null;
44
+ if (cursor === rootArtifact) reachedRoot = true;
45
+ }
46
+ if (!reachedRoot) findings.push(finding('error', 'portable.handoff-v2-surface.lineage.root-unreachable', 'Following declared Parent from a generated artifact must terminate at the single package-local root.', { path, root: rootArtifact.path }));
47
+ }
48
+ }
49
+
50
+ export function inspectParticipantRolePointers(pointers, workspaces, caches, findings) {
51
+ inspectRolePointers('participant-role', pointers, workspaces, caches, findings);
52
+ }
53
+
54
+ export function inspectEndpointRolePointers(pointers, workspaces, caches, findings) {
55
+ inspectRolePointers('endpoint-role', pointers, workspaces, caches, findings);
56
+ }
57
+
58
+ function inspectRolePointers(roleKind, pointers, workspaces, caches, findings) {
59
+ const codeKind = roleKind === 'endpoint-role' ? 'endpoint-role' : 'participant-role';
60
+ const labelKind = roleKind === 'endpoint-role' ? 'Endpoint Role' : 'Participant Role';
61
+ for (const pointer of pointers || []) {
62
+ const facts = pointer.facts || {};
63
+ const carrierKind = String(facts.targetCarrierKind || '');
64
+ let entry = null;
65
+ let archivePath = '';
66
+ if (carrierKind === 'workspace-archive-entry') {
67
+ const workspace = workspaces.find((item) => item.workspaceId === String(facts.targetWorkspaceId || ''));
68
+ archivePath = String(workspace?.archiveFile?.path || '');
69
+ entry = (workspace?.archive?.archive?.entries || []).find((item) => String(item.path || '') === String(facts.targetInnerPath || '')) || null;
70
+ } else if (carrierKind === 'workspace-cache-entry') {
71
+ const cache = caches.find((item) => item.artifact.path === String(facts.archivePath || '') || item.file.path === String(facts.archivePath || '') || String(item.facts?.workspaceId || '') === String(facts.workspaceId || ''));
72
+ archivePath = String(cache?.file?.path || '');
73
+ entry = (cache?.archive?.archive?.entries || []).find((item) => String(item.path || '') === String(facts.targetArchiveEntry || '')) || null;
74
+ } else {
75
+ findings.push(finding('error', `portable.handoff-v2-surface.${codeKind}.carrier-kind-invalid`, `${labelKind} Pointer declares an unsupported exact carrier kind.`, { path: pointer.path || '', carrierKind }));
76
+ continue;
77
+ }
78
+ if (!entry) {
79
+ findings.push(finding('error', `portable.handoff-v2-surface.${codeKind}.target-unresolved`, `${labelKind} Pointer target does not resolve to one exact carried archive entry.`, { path: pointer.path || '', carrierKind }));
80
+ continue;
81
+ }
82
+ const data = packageFileByteView({ data: entry.data });
83
+ const digest = sha256Hex(data);
84
+ if (String(facts.archivePath || '') !== archivePath) findings.push(finding('error', `portable.handoff-v2-surface.${codeKind}.archive-path-mismatch`, `${labelKind} Pointer archive path diverges from the independently resolved carrier.`, { path: pointer.path || '', expected: archivePath, observed: String(facts.archivePath || '') }));
85
+ if (Number(facts.targetBytes || 0) !== data.byteLength || String(facts.targetSha256 || '') !== digest) findings.push(finding('error', `portable.handoff-v2-surface.${codeKind}.target-identity-mismatch`, `${labelKind} Pointer byte identity diverges from the exact carried Role target.`, { path: pointer.path || '' }));
86
+ const markdown = decodeUtf8(data);
87
+ if (!/^\s*-\s+Current Schema:\s*(?:\[)?tiinex\.party\.role\.v1(?:\])?/mi.test(markdown)) findings.push(finding('error', `portable.handoff-v2-surface.${codeKind}.target-schema-invalid`, `${labelKind} Pointer target is not a readable tiinex.party.role.v1 artifact.`, { path: pointer.path || '' }));
88
+ const label = String(markdown.match(/^\s*-\s+Role Label:\s*(.+?)\s*$/mi)?.[1] || '').trim();
89
+ if (!label) findings.push(finding('error', `portable.handoff-v2-surface.${codeKind}.target-label-missing`, `${labelKind} Pointer target lacks a readable Role Label.`, { path: pointer.path || '' }));
90
+ if (facts.roleLabelHint && label && String(facts.roleLabelHint) !== label) findings.push(finding('error', `portable.handoff-v2-surface.${codeKind}.label-hint-mismatch`, `${labelKind} label hint contradicts the exact carried Role artifact.`, { path: pointer.path || '', expected: label, observed: String(facts.roleLabelHint || '') }));
91
+ if (roleKind === 'endpoint-role' && !['from', 'to'].includes(String(facts.endpointParty || '').toLowerCase())) findings.push(finding('error', 'portable.handoff-v2-surface.endpoint-role.party-invalid', 'Endpoint Role Pointer must visibly bind exactly one Handoff endpoint party.', { path: pointer.path || '', endpointParty: String(facts.endpointParty || '') }));
92
+ }
93
+ }
94
+
95
+ export function inspectRoutePointers(pointers, carrier, workspaces, endpointPointers, participantPointers, index, findings) {
96
+ const byKey = new Map((carrier.routes || []).map((route) => [`${route.workspaceId}\u0000${route.workspaceRelativePath}`, route]));
97
+ const roleByPath = new Map([...(endpointPointers || []), ...(participantPointers || [])].map((pointer) => [String(pointer.path || ''), pointer]));
98
+ for (const pointer of pointers) {
99
+ const facts = pointer.facts || {};
100
+ const key = `${String(facts.workspaceId || '')}\u0000${String(facts.workspaceRelativeHandoffPath || '')}`;
101
+ const route = byKey.get(key);
102
+ const workspace = workspaces.find((item) => item.workspaceId === String(facts.workspaceId || ''));
103
+ if (!route || route.state !== 'qualified' || !workspace) { findings.push(finding('error', 'portable.handoff-v2-surface.route-pointer.unqualified', 'Handoff route Pointer does not resolve to one independently qualified Handoff route.', { path: pointer.path || '' })); continue; }
104
+ const checks = [
105
+ [facts.workspaceArtifactPath, workspace.artifact.path, 'workspace-artifact-path'],
106
+ [facts.workspaceArtifactSha256, workspace.artifact.sha256, 'workspace-artifact-sha256'],
107
+ [facts.archivePath, workspace.archiveFile.path, 'archive-path'],
108
+ [facts.archiveSha256, String(workspace.archive?.sha256 || ''), 'archive-sha256'],
109
+ [facts.sourceWorkspaceTargetInnerPath, workspace.facts.sourceWorkspaceTargetInnerPath, 'source-workspace-target-inner-path'],
110
+ [facts.sourceWorkspaceTargetSha256, workspace.facts.sourceWorkspaceTargetSha256, 'source-workspace-target-sha256'],
111
+ [facts.handoffSha256, route.sha256, 'handoff-sha256']
112
+ ];
113
+ for (const [actual, expected, name] of checks) if (String(actual || '') !== String(expected || '')) findings.push(finding('error', `portable.handoff-v2-surface.route-pointer.${name}-mismatch`, 'Handoff route Pointer diverges from independently qualified Workspace/archive/Handoff truth.', { path: pointer.path || '' }));
114
+ const expectedBaseParent = facts.cacheArtifactPath ? String(facts.cacheArtifactPath) : workspace.artifact.path;
115
+ if (facts.cacheArtifactPath && !oneRecipientFile(index, facts.cacheArtifactPath)) findings.push(finding('error', 'portable.handoff-v2-surface.route-pointer.cache-missing', 'Handoff route Pointer declares a package-local Workspace dependency cache ancestor that is not carried.', { path: pointer.path || '', cacheArtifactPath: facts.cacheArtifactPath }));
116
+ let cursorParent = parentTrace(pointer);
117
+ const roleAncestors = [];
118
+ const seen = new Set();
119
+ while (roleByPath.has(cursorParent) && !seen.has(cursorParent)) {
120
+ seen.add(cursorParent);
121
+ const rolePointer = roleByPath.get(cursorParent);
122
+ roleAncestors.push(rolePointer);
123
+ if (String(rolePointer.facts?.routeId || '') !== String(route.id || '') || String(rolePointer.facts?.workspaceId || '') !== String(workspace.workspaceId || '')) findings.push(finding('error', 'portable.handoff-v2-surface.route-pointer.role-route-mismatch', 'Role Pointer ancestor is bound to a different Handoff route/Workspace.', { path: pointer.path || '', rolePointer: rolePointer.path || '' }));
124
+ cursorParent = parentTrace(rolePointer);
125
+ }
126
+ if (cursorParent !== expectedBaseParent) findings.push(finding('error', 'portable.handoff-v2-surface.route-pointer.parent-mismatch', 'Handoff route Pointer ancestry must pass only through route-bound endpoint/participant Role Pointers and terminate at its Workspace dependency cache when present, otherwise its package-local Workspace node.', { path: pointer.path || '', expectedParent: expectedBaseParent, observedTerminalParent: cursorParent }));
127
+ if (Number(facts.handoffBytes || 0) && Number(facts.handoffBytes || 0) !== Number(resolveRouteBytes(workspace, facts.workspaceRelativeHandoffPath))) findings.push(finding('error', 'portable.handoff-v2-surface.route-pointer.handoff-bytes-mismatch', 'Handoff route Pointer byte count differs from exact archive entry bytes.', { path: pointer.path || '' }));
128
+ }
129
+ }
130
+
131
+ function resolveRouteBytes(workspace, path) {
132
+ const entry = (workspace.archive?.archive?.entries || []).find((item) => String(item.path || '') === String(path || ''));
133
+ return Number(entry?.bytes || 0);
134
+ }
135
+
136
+ export function parentTrace(artifact = {}) {
137
+ return String(artifact?.conformance?.parentContinuity?.trace || '');
138
+ }
139
+
140
+ function numericDimension(path = '') { return String(path || '').match(/^(\d+(?:-\d+)*)-/)?.[1] || ''; }
141
+ function parentNumericDimension(dimension = '') { const parts = String(dimension || '').split('-').filter(Boolean); return parts.length > 1 ? parts.slice(0, -1).join('-') : ''; }
142
+ function decodeUtf8(data) { try { return new TextDecoder('utf-8', { fatal: true }).decode(data); } catch { return ''; } }
@@ -0,0 +1,147 @@
1
+ import { finalizeFile } from '../../../export/package.fileMap.js';
2
+ import { packageFileByteView } from '../../../export/package.bytes.js';
3
+ import { exportFileMapZipUint8Array } from '../../../export/package.zip.js';
4
+ import { qualifyHandoffWorkspaceTarget } from './workspaceTargetConformance.js';
5
+ import { inspectStoredWorkspaceArchive } from './workspaceByteProvider.js';
6
+ import { renderRecipientV2ExternalPayload, renderRecipientV2Pointer } from './recipientV2.artifacts.js';
7
+ import { RECIPIENT_V2_READ_PATH } from './recipientV2.topology.js';
8
+ import { RECIPIENT_V2_ROUTE_SELECTION_AUTHORITY, RECIPIENT_V2_SIBLING_ROUTE_INFERENCE, recipientV2EntryCurrentRead } from './recipientV2.entryContract.js';
9
+ import { recipientV2TransportFacts } from './recipientV2.transportManifest.js';
10
+ import { buildRecipientV2BootstrapCarrier, recipientV2ParentAuthority } from './recipientV2.topology.workspaces.js';
11
+ import { buildEndpointRolePointerChain, buildParticipantRolePointerChain } from './recipientV2.endpointRolePointers.js';
12
+ import { bindingForWorkspace, detachedMaterial, duplicates, finding, roleMaterialTarget, routeClaimsDetachedMaterial, safeToken, uniqueFileIndex } from './recipientV2.topology.materials.js';
13
+ import { RECIPIENT_V2_PACKAGE_V1_FORMAT_ID, RECIPIENT_V2_PACKAGE_V1_ROOT_PATH, RECIPIENT_V2_PACKAGE_V1_SCHEMA_ID, RECIPIENT_V2_PACKAGE_V1_SCHEMA_TARGET } from './recipientV2.packageV1.constants.js';
14
+ import { renderHandoffPackageV1 } from './recipientV2.packageV1.contract.js';
15
+ import { inspectRecipientFacingV2PackageV1 } from './recipientV2.packageV1.inspect.js';
16
+ import { blocked, deepFreeze, exactFile, workspaceSchemaTarget } from './recipientV2.packageV1.shared.js';
17
+
18
+ export function buildRecipientFacingV2PackageV1(input = {}) {
19
+ const sourceSurface = input.sourceSurface || null;
20
+ const descriptor = input.descriptor || input.bundle?.handoffClosure || {};
21
+ const carrier = input.carrierProjection || {};
22
+ const createdAt = input.createdAt || input.bundle?.manifest?.createdAt || input.bundle?.builtAt || '';
23
+ const findings = [];
24
+ if (!sourceSurface || sourceSurface.status !== 'ready') return blocked('source-surface-unready', sourceSurface?.findings || []);
25
+ const routes = (carrier.routes || []).filter((route) => route.state === 'qualified');
26
+ const selector = String(input.routeSelector || input.routeId || '').trim();
27
+ const selected = selector ? routes.filter((route) => route.id === selector || route.workspaceRelativePath === selector || `${String(route.workspaceId || '')}:${String(route.workspaceRelativePath || '')}` === selector || `handoff-route:${String(route.workspaceId || '')}:${String(route.workspaceRelativePath || '')}` === selector) : routes;
28
+ if (selected.length !== 1) return blocked('route-selection-unresolved', [finding('error', 'portable.handoff-package-v1.route-selection-unresolved', 'Package v1 manufacture requires exactly one qualified selected Handoff route.', { count: selected.length })]);
29
+ const route = selected[0];
30
+ const sourceWorkspaceById = new Map((sourceSurface.topology?.workspaces || []).map((item) => [String(item.workspaceId || ''), item]));
31
+ const sourceByPath = new Map((sourceSurface.files || []).map((file) => [String(file.path || ''), file]));
32
+ // The package-v1 carrier preserves the complete inherited Workspace source chain.
33
+ // Route closure remains selected and minimal, but complete package-local Workspace
34
+ // bindings are not pruned merely because one carried Workspace is not on the
35
+ // selected Handoff's pre-Handoff closure.
36
+ const workspaceIds = [...sourceWorkspaceById.keys()].filter(Boolean).sort();
37
+ const workspacePlans = workspaceIds.map((workspaceId, index) => Object.freeze({ workspaceId, ordinal: index + 3, prefix: `001-${index + 3}`, slug: safeToken(workspaceId) }));
38
+ const files = [];
39
+ const topology = { root: null, read: null, workspaces: [], caches: [], endpointRoles: [], participantRoles: [], routes: [], bootstrap: null };
40
+ const workspaceById = new Map();
41
+
42
+ for (const plan of workspacePlans) {
43
+ const source = sourceWorkspaceById.get(plan.workspaceId);
44
+ if (!source || String(source.coverage || '') !== 'complete') { findings.push(finding('error', 'portable.handoff-package-v1.workspace.complete-required', 'Package-local direct Workspace binding requires one complete source snapshot.', { workspaceId: plan.workspaceId })); continue; }
45
+ const sourceArchive = sourceByPath.get(String(source.archivePath || ''));
46
+ if (!sourceArchive) { findings.push(finding('error', 'portable.handoff-package-v1.workspace.archive-missing', 'Selected complete Workspace archive is unavailable.', { workspaceId: plan.workspaceId })); continue; }
47
+ const archiveData = packageFileByteView(sourceArchive);
48
+ const parsed = inspectStoredWorkspaceArchive(archiveData, { ownedBytes: true });
49
+ if (parsed.state !== 'qualified') { findings.push(finding('error', 'portable.handoff-package-v1.workspace.archive-invalid', 'Selected complete Workspace snapshot bytes do not qualify.', { workspaceId: plan.workspaceId })); continue; }
50
+ const innerPath = String(source.sourceWorkspaceTargetInnerPath || '');
51
+ const matches = (parsed.entries || []).filter((entry) => entry.path === innerPath);
52
+ if (matches.length !== 1) { findings.push(finding('error', 'portable.handoff-package-v1.workspace.target-unresolved', 'Workspace artifact inner path must resolve exactly once inside the complete snapshot.', { workspaceId: plan.workspaceId, innerPath, count: matches.length })); continue; }
53
+ const targetData = packageFileByteView({ data: matches[0].data });
54
+ const targetQualification = qualifyHandoffWorkspaceTarget({ targetPath: innerPath, targetData, entries: parsed.entries || [] });
55
+ if (targetQualification.state !== 'qualified') { findings.push(finding('error', 'portable.handoff-package-v1.workspace.target-unqualified', 'Exact Workspace artifact bytes inside the snapshot do not qualify.', { workspaceId: plan.workspaceId, reasons: targetQualification.reasons || [] })); continue; }
56
+ const workspacePath = `${plan.prefix}-${plan.slug}.workspace.md`;
57
+ const archivePath = `${plan.prefix}-${plan.slug}.workspace.zip`;
58
+ const workspaceFile = exactFile(workspacePath, targetData, 'recipient-v2-package-v1-exact-workspace-artifact', 'text/markdown');
59
+ const archiveFile = exactFile(archivePath, archiveData, 'recipient-v2-package-v1-complete-workspace-snapshot', 'application/zip');
60
+ files.push(workspaceFile, archiveFile);
61
+ const parent = recipientV2ParentAuthority(workspaceFile, 'tiinex.workspace.v1', workspaceSchemaTarget(targetQualification), createdAt);
62
+ const projection = Object.freeze({
63
+ workspaceId: plan.workspaceId, ordinal: plan.ordinal, workspacePath, workspaceSha256: workspaceFile.sha256,
64
+ archivePath, archiveSha256: archiveFile.sha256, sourceWorkspaceTargetInnerPath: innerPath,
65
+ sourceWorkspaceTargetSha256: workspaceFile.sha256, sourceWorkspaceTargetBytes: workspaceFile.bytes, coverage: 'complete'
66
+ });
67
+ topology.workspaces.push(projection);
68
+ workspaceById.set(plan.workspaceId, { ...projection, file: workspaceFile, parent });
69
+ }
70
+
71
+ if (findings.some((item) => item.severity === 'error')) return blocked('workspace-binding-blocked', findings);
72
+
73
+ const packageFile = finalizeFile({
74
+ path: RECIPIENT_V2_PACKAGE_V1_ROOT_PATH,
75
+ kind: 'tiinex-handoff-package-artifact',
76
+ logicalKind: 'recipient-v2-package-v1-root',
77
+ mediaType: 'text/markdown',
78
+ content: renderHandoffPackageV1({ createdAt, workspaces: topology.workspaces, carrierLineage: carrier.lineage || {}, carrierProfile: input.carrierProfile || null, startPath: RECIPIENT_V2_READ_PATH, bootstrapPath: hasBootstrap(input.bundle) ? '001-2-bootstrap.trace.md' : '' })
79
+ });
80
+ files.push(packageFile);
81
+ topology.root = Object.freeze({ path: packageFile.path, sha256: packageFile.sha256 });
82
+ const packageParent = recipientV2ParentAuthority(packageFile, RECIPIENT_V2_PACKAGE_V1_SCHEMA_ID, RECIPIENT_V2_PACKAGE_V1_SCHEMA_TARGET, createdAt);
83
+
84
+ const bootstrapSource = (input.bundle?.files || []).filter((file) => String(file.path || '').startsWith('tiinex.bootstrap/'));
85
+ if (bootstrapSource.length) {
86
+ const bootstrap = buildRecipientV2BootstrapCarrier(bootstrapSource, createdAt, findings, packageParent);
87
+ if (bootstrap) { files.push(bootstrap.artifact, bootstrap.payload); topology.bootstrap = bootstrap.projection; }
88
+ }
89
+
90
+ const byPath = uniqueFileIndex(input.bundle?.files || [], findings);
91
+ const detached = detachedMaterial(descriptor, byPath, findings);
92
+ const selectedDetached = detached.filter((item) => routeClaimsDetachedMaterial(route, item));
93
+ const owningWorkspace = workspaceById.get(String(route.workspaceId || ''));
94
+ let cache = null;
95
+ if (selectedDetached.length && owningWorkspace) {
96
+ const plan = workspacePlans.find((item) => item.workspaceId === owningWorkspace.workspaceId);
97
+ const artifactPath = `${plan.prefix}-1-cache.trace.md`;
98
+ const archivePath = `${plan.prefix}-1-cache.zip`;
99
+ const cacheEntries = selectedDetached.map((item, index) => ({ path: `material/${index + 1}-${safeToken(item.requirementId || item.referenceTarget || 'material')}.bin`, data: item.data }));
100
+ const cacheBytes = exportFileMapZipUint8Array(cacheEntries, 'portable.handoff-package-v1.cache.path.invalid');
101
+ const cacheFile = finalizeFile({ path: archivePath, kind: 'handoff-material-cache', logicalKind: 'recipient-v2-package-v1-workspace-dependency-cache', mediaType: 'application/zip', data: cacheBytes });
102
+ const cacheFacts = {
103
+ workspaceId: owningWorkspace.workspaceId, archivePath, archiveBytes: cacheFile.bytes, archiveSha256: cacheFile.sha256,
104
+ materials: selectedDetached.map((item, index) => ({ requirementId: item.requirementId, classification: item.classification, referenceTarget: item.referenceTarget, routeWorkspaceId: item.routeWorkspaceId, routePath: item.routePath, sourceRequirementId: item.sourceRequirementId, originalPath: item.originalPath, archiveEntry: cacheEntries[index].path, bytes: item.bytes, sha256: item.sha256 }))
105
+ };
106
+ const cacheArtifact = finalizeFile({ path: artifactPath, kind: 'tiinex-external-payload-artifact', logicalKind: 'recipient-v2-package-v1-workspace-dependency-cache-reference', mediaType: 'text/markdown', transportFacts: recipientV2TransportFacts('workspace-scoped Handoff dependency cache', cacheFacts), content: renderRecipientV2ExternalPayload({ createdAt, parent: owningWorkspace.parent, title: `Workspace Dependency Cache — ${owningWorkspace.workspaceId}`, summary: 'Exact route-bounded dependency bytes not satisfied by a complete carried Workspace snapshot.', label: `${owningWorkspace.workspaceId} Handoff dependency cache`, kind: 'zip export', role: 'workspace-scoped Handoff dependency cache', location: archivePath, bytes: cacheFile.bytes, sha256: cacheFile.sha256, facts: cacheFacts }) });
107
+ files.push(cacheArtifact, cacheFile);
108
+ cache = { workspaceId: owningWorkspace.workspaceId, artifactPath, archivePath, materials: cacheFacts.materials, parent: recipientV2ParentAuthority(cacheArtifact, 'tiinex.external.payload.v1', RECIPIENT_V2_EXTERNAL_PAYLOAD_SCHEMA_TARGET, createdAt) };
109
+ topology.caches.push(Object.freeze({ workspaceId: cache.workspaceId, artifactPath, archivePath, materials: cache.materials }));
110
+ }
111
+
112
+ if (!owningWorkspace) findings.push(finding('error', 'portable.handoff-package-v1.route.workspace-unresolved', 'Selected Handoff route owning Workspace is not carried.'));
113
+ else {
114
+ const plan = workspacePlans.find((item) => item.workspaceId === owningWorkspace.workspaceId);
115
+ const binding = bindingForWorkspace(descriptor, owningWorkspace.workspaceId);
116
+ let lineageParent = cache?.parent || owningWorkspace.parent;
117
+ let nextDimension = cache ? `${plan.prefix}-1-1` : `${plan.prefix}-1`;
118
+ const endpointChain = buildEndpointRolePointerChain({ requirements: route.materialRequirements?.endpointRoles || [], descriptor, workspaceById, cache, workspace: owningWorkspace, route, createdAt, lineageParent, nextDimension, resolveRoleMaterialTarget: roleMaterialTarget, parentAuthority: recipientV2ParentAuthority });
119
+ files.push(...endpointChain.files); topology.endpointRoles.push(...endpointChain.roles); findings.push(...endpointChain.findings); lineageParent = endpointChain.lineageParent; nextDimension = endpointChain.nextDimension;
120
+ const participantChain = buildParticipantRolePointerChain({ requirements: route.materialRequirements?.participantRoles || [], descriptor, workspaceById, cache, workspace: owningWorkspace, route, createdAt, lineageParent, nextDimension, resolveRoleMaterialTarget: roleMaterialTarget, parentAuthority: recipientV2ParentAuthority });
121
+ files.push(...participantChain.files); topology.participantRoles.push(...participantChain.roles); findings.push(...participantChain.findings); lineageParent = participantChain.lineageParent; nextDimension = participantChain.nextDimension;
122
+ const pointerPath = `${nextDimension}-handoff-pointer.trace.md`;
123
+ const routeEntry = (binding?.entryMap?.entries || []).find((entry) => String(entry.path || '') === String(route.workspaceRelativePath || ''));
124
+ const pointerFacts = {
125
+ workspaceId: owningWorkspace.workspaceId, workspaceArtifactPath: owningWorkspace.workspacePath, workspaceArtifactSha256: owningWorkspace.workspaceSha256,
126
+ archivePath: owningWorkspace.archivePath, archiveSha256: owningWorkspace.archiveSha256, sourceWorkspaceTargetInnerPath: owningWorkspace.sourceWorkspaceTargetInnerPath,
127
+ sourceWorkspaceTargetSha256: owningWorkspace.sourceWorkspaceTargetSha256, workspaceRelativeHandoffPath: String(route.workspaceRelativePath || ''), handoffBytes: Number(routeEntry?.bytes || 0), handoffSha256: String(route.sha256 || ''), routeId: String(route.id || ''), parties: route.parties || {}, cacheArtifactPath: cache?.artifactPath || '',
128
+ requiredContextBindings: Object.freeze((route.requiredClosure?.requirements || []).filter((entry) => entry.state === 'qualified' && entry.resolution?.kind === 'workspace-archive-entry').map((entry) => Object.freeze({ requirementId: String(entry.requirementId || ''), name: String(entry.name || ''), referenceTarget: String(entry.referenceTarget || ''), workspaceId: String(entry.resolution?.workspaceId || ''), workspaceRelativePath: String(entry.resolution?.workspaceRelativePath || entry.resolution?.innerPath || ''), bytes: Number(entry.resolution?.bytes || 0), sha256: String(entry.resolution?.sha256 || '') })))
129
+ };
130
+ const pointer = finalizeFile({ path: pointerPath, kind: 'handoff-route-pointer', logicalKind: 'recipient-v2-package-v1-handoff-route-pointer', mediaType: 'text/markdown', transportFacts: recipientV2TransportFacts('handoff-route', pointerFacts), content: renderRecipientV2Pointer({ createdAt, parent: lineageParent, role: 'handoff-route', title: `Handoff Route Pointer — ${String(route.parties?.to || owningWorkspace.workspaceId || 'recipient')}`, summary: 'Qualified package-local Pointer to one authoritative Handoff inside one complete Workspace snapshot.', prose: 'Follow only this Pointer carrier-ancestor closure for pre-Handoff package grounding, then resolve the authoritative Handoff path against the exact bound Workspace snapshot.', currentRead: [{ label: 'Workspace Id', value: `\`${owningWorkspace.workspaceId}\`` }, { label: 'Workspace', value: `[${owningWorkspace.workspaceId}](${owningWorkspace.workspacePath})` }, { label: 'Route Id', value: `\`${String(route.id || '')}\`` }, ...(pointerFacts.cacheArtifactPath ? [{ label: 'Workspace Dependency Cache', value: `[cache](${pointerFacts.cacheArtifactPath})` }] : []), { label: 'Handoff Workspace Path', value: `\`${String(route.workspaceRelativePath || '')}\`` }], destinations: [{ label: 'Workspace snapshot containing the qualified Handoff route', display: `${owningWorkspace.archivePath} :: ${String(route.workspaceRelativePath || '')}`, target: owningWorkspace.archivePath }], facts: pointerFacts }) });
131
+ files.push(pointer);
132
+ topology.routes.push(Object.freeze({ pointerPath, workspaceId: owningWorkspace.workspaceId, workspaceRelativeHandoffPath: String(route.workspaceRelativePath || ''), routeId: String(route.id || ''), sha256: String(route.sha256 || '') }));
133
+ }
134
+
135
+ const readFacts = { format: RECIPIENT_V2_PACKAGE_V1_FORMAT_ID, packageRootPath: RECIPIENT_V2_PACKAGE_V1_ROOT_PATH, entryArtifactPath: RECIPIENT_V2_READ_PATH, artifactSurface: 'tiinex.handoff.package.v1-plus-exact-complete-workspace-snapshots', routeAuthority: 'qualified-handoff-route-pointer-plus-exact-handoff-bytes', routeSelectionAuthority: RECIPIENT_V2_ROUTE_SELECTION_AUTHORITY, siblingRouteInference: RECIPIENT_V2_SIBLING_ROUTE_INFERENCE, carrierLineage: carrier.lineage || null, pathParentProjection: true, pathAuthority: false };
136
+ const readFile = finalizeFile({ path: RECIPIENT_V2_READ_PATH, kind: 'handoff-recovery-pointer', logicalKind: 'recipient-v2-package-v1-recovery-orientation', mediaType: 'text/markdown', transportFacts: recipientV2TransportFacts('recovery-orientation', readFacts), content: renderRecipientV2Pointer({ createdAt, parent: packageParent, role: 'recovery-orientation', title: 'READ BEFORE PROCEEDING — Tiinex Handoff Carrier', summary: 'Qualified recovery/orientation Pointer for the package-v1 recipient carrier.', prose: 'Read this Start artifact first, qualify the declared Tooling bootstrap, then continue from the exact supplied Handoff Pointer path. Do not infer sibling routes or derive semantic authority from package placement.', currentRead: [...recipientV2EntryCurrentRead(), { label: 'Package Artifact', value: `[Handoff Package](${RECIPIENT_V2_PACKAGE_V1_ROOT_PATH})` }, { label: 'Carrier Dimension', value: `\`${String(carrier.lineage?.dimension || '001')}\`` }, ...(carrier.lineage?.parentDimension ? [{ label: 'Parent Carrier Dimension', value: `\`${String(carrier.lineage.parentDimension)}\`` }] : []), { label: 'Carrier Checkpoint', value: String(carrier.lineage?.checkpointKind || 'progression') }], destinations: [{ label: 'Handoff Package contract', target: RECIPIENT_V2_PACKAGE_V1_ROOT_PATH }, ...(topology.bootstrap ? [{ label: 'Portable Tooling bootstrap', target: topology.bootstrap.artifactPath }] : []), ...topology.workspaces.map((workspace) => ({ label: `Workspace ${workspace.workspaceId}`, target: workspace.workspacePath })), ...topology.routes.map((item) => ({ label: `Selected Handoff route ${item.routeId || item.workspaceRelativeHandoffPath}`, target: item.pointerPath }))], facts: readFacts }) });
137
+ files.push(readFile); topology.read = Object.freeze({ path: readFile.path, sha256: readFile.sha256 });
138
+
139
+ for (const duplicate of duplicates(files.map((file) => file.path))) findings.push(finding('error', 'portable.handoff-package-v1.path-duplicate', 'Package v1 generated duplicate package-local paths.', { path: duplicate }));
140
+ for (const file of files) if (String(file.path || '').includes('/')) findings.push(finding('error', 'portable.handoff-package-v1.path-nonflat', 'Package v1 root surface must remain flat.', { path: file.path || '' }));
141
+ const sortedFiles = [...files].sort((a, b) => String(a.path || '').localeCompare(String(b.path || '')));
142
+ const bundle = { ...(input.bundle || {}), files: Object.freeze(sortedFiles), handoffClosure: null, transportFormat: RECIPIENT_V2_PACKAGE_V1_FORMAT_ID };
143
+ const inspection = inspectRecipientFacingV2PackageV1(bundle);
144
+ return Object.freeze({ status: inspection.status === 'valid' && !findings.some((item) => item.severity === 'error') ? 'ready' : 'blocked', files: Object.freeze(sortedFiles), topology: deepFreeze(topology), inspection, findings: Object.freeze([...findings, ...(inspection.findings || [])]), boundary: 'Recipient-facing tiinex.handoff.package.v1 carrier with exact complete Workspace artifacts/snapshots, bootstrap/cache External Payload ownership retained, and no redundant Workspace External Payload or Workspace Representation companions.' });
145
+ }
146
+
147
+ function hasBootstrap(bundle = {}) { return (bundle.files || []).some((file) => String(file.path || '').startsWith('tiinex.bootstrap/')); }
@@ -0,0 +1,4 @@
1
+ export const RECIPIENT_V2_PACKAGE_V1_FORMAT_ID = 'tiinex-recipient-facing-handoff-package-v1';
2
+ export const RECIPIENT_V2_PACKAGE_V1_SCHEMA_ID = 'tiinex.handoff.package.v1';
3
+ export const RECIPIENT_V2_PACKAGE_V1_ROOT_PATH = '001-tiinex-handoff-package.trace.md';
4
+ export const RECIPIENT_V2_PACKAGE_V1_SCHEMA_TARGET = 'https://github.com/Tiinex/docs/blob/3988951208eb9a8926e84ab42625d4b42fa00c2d/.topics/.schemas/coordination/handoff/package/tiinex.handoff.package.v1.schema.md';