@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,502 @@
1
+ import { AdapterAvailability, makeAdapterDefinition, makeAdapterResult } from '../adapter.contracts.js';
2
+ import { createRecordFromMarkdown } from '../../artifacts/artifact.record.js';
3
+ import { filterArchiveTransportEntries } from './archive.transport.js';
4
+ import { qualifyPortableChangesetEntries } from './archive.portableChangeset.js';
5
+ import { resolveTransportPlan } from '../../sources/transport.levels.js';
6
+
7
+ export const ARCHIVE_ADAPTER_ID = 'archive';
8
+
9
+ const TEXT_DECODER = new TextDecoder();
10
+ const TEXT_ENCODER = new TextEncoder();
11
+ const MARKDOWN_RE = /(?:\.md|\.markdown|\.trace\.md|\.schema\.md|\.validator\.md|\.workspace\.md)$/i;
12
+ const TEXT_ASSET_RE = /\.(?:txt|json|yml|yaml|csv|svg|html|css|js)$/i;
13
+ const IMAGE_ASSET_RE = /\.(?:png|jpg|jpeg|gif|webp|svg)$/i;
14
+ const MAX_TEXT_ASSET_PREVIEW_BYTES = 128 * 1024;
15
+ const MAX_BINARY_ASSET_DATA_URL_BYTES = 512 * 1024;
16
+
17
+ export function createArchiveAdapter() {
18
+ return makeAdapterDefinition({
19
+ id: ARCHIVE_ADAPTER_ID,
20
+ label: 'Archive intake',
21
+ availability: AdapterAvailability.available,
22
+ sourceKinds: ['archive.zip', 'archive.local', 'archive.workspace-bundle'],
23
+ capabilities: {
24
+ registerSource: false,
25
+ materialize: true,
26
+ resolveAsset: true,
27
+ openExternal: false,
28
+ requiresBridge: false
29
+ },
30
+ configShape: {
31
+ files: 'File[] where .zip is parsed and other files are routed by extension',
32
+ paths: 'safe relative archive paths only',
33
+ encrypted: 'ZipCrypto stored entries supported with an explicit password; unsupported encrypted forms are reported'
34
+ },
35
+ boundary: 'user-provided local archive; paths are sanitized; material remains browser-local/session until explicitly exported or published',
36
+ resultShape: {
37
+ records: 'markdown leaf/trace records',
38
+ assets: 'non-markdown local assets',
39
+ workspaceEntries: '.workspace.md entries routed as workspace configuration candidates',
40
+ diagnostics: 'counts, skipped unsafe paths, encryption/unsupported entries'
41
+ },
42
+ notes: [
43
+ 'Ported from .old archive intake: preserve relative paths, split workspace files/leaves/assets, and support password-protected ZipCrypto stored entries through an explicit password boundary.',
44
+ 'This adapter never infers GitHub provenance from archive paths.'
45
+ ]
46
+ });
47
+ }
48
+
49
+ export function safeArchivePath(value = '', options = {}) {
50
+ const raw = String(value || '').replace(/\\/g, '/').trim();
51
+ if (!raw || raw.startsWith('/') || /^[A-Za-z]:\//.test(raw)) return '';
52
+ const segments = raw.split('/').filter((segment) => segment && segment !== '.');
53
+ if (!segments.length || segments.some((segment) => segment === '..')) return '';
54
+ if (options.excludeRepositoryInternals && (segments[0] === '.git' || segments[0] === '.mirrors')) return '';
55
+ return segments.join('/').replace(/\/+/g, '/');
56
+ }
57
+
58
+ export function isWorkspaceMarkdownPath(path = '') {
59
+ const name = String(path || '').trim();
60
+ return /\.workspace(?:\s*\(\d+\))?\.md$/iu.test(name);
61
+ }
62
+
63
+
64
+ export function looksLikeWorkspaceMarkdown(markdown = '') {
65
+ const text = String(markdown || '');
66
+ if (!text.trim()) return false;
67
+ if (/Current Schema:\s*(?:\[[^\]]*\]\([^)]*\)|[^\n]*)tiinex\.workspace\.v1/iu.test(text)) return true;
68
+ if (/Current Schema:\s*tiinex\.workspace\.v1/iu.test(text)) return true;
69
+ if (/^#\s+Tiinex Viewer\s*$/imu.test(text) && /^##\s+Workspace Entrypoints\s*$/imu.test(text)) return true;
70
+ if (/^##\s+Workspace State\s*$/imu.test(text) && /tiinex\.workspace\.machineState\.v1/iu.test(text)) return true;
71
+ if (/^##\s+Workspaces\s*$/imu.test(text) && /^##\s+Workspace Entrypoints\s*$/imu.test(text)) return true;
72
+ return false;
73
+ }
74
+
75
+ export function classifyArchiveEntry(path = '', content = null) {
76
+ const clean = safeArchivePath(path);
77
+ if (!clean) return 'unsafe';
78
+ const markdownPath = MARKDOWN_RE.test(clean);
79
+ if (isWorkspaceMarkdownPath(clean) || (markdownPath && content && looksLikeWorkspaceMarkdown(content))) return 'workspace';
80
+ if (markdownPath) return 'record';
81
+ return 'asset';
82
+ }
83
+
84
+ export function zipBufferHasEncryptedEntries(buffer) {
85
+ const bytes = bytesFrom(buffer);
86
+ let encrypted = false;
87
+ forEachCentralEntry(bytes, (entry) => {
88
+ if (entry.flag & 0x0001) encrypted = true;
89
+ });
90
+ return encrypted;
91
+ }
92
+
93
+ export async function decodeZipBufferEntries(zipBuffer, options = {}) {
94
+ const bytes = bytesFrom(zipBuffer);
95
+ const entries = [];
96
+ const warnings = [];
97
+ const errors = [];
98
+ const encrypted = [];
99
+ const unsupported = [];
100
+ const unsafe = [];
101
+
102
+ const centralEntries = readCentralEntries(bytes);
103
+ if (!centralEntries.length) throw new Error('zip.no.central.directory');
104
+
105
+ for (const central of centralEntries) {
106
+ if (central.isDirectory) continue;
107
+ const path = safeArchivePath(central.name, { excludeRepositoryInternals: Boolean(options.excludeRepositoryInternals) });
108
+ if (!path) {
109
+ unsafe.push(central.name);
110
+ warnings.push({ code: 'archive.unsafe-path-skipped', ref: central.name, message: 'Unsafe archive path skipped.' });
111
+ continue;
112
+ }
113
+ try {
114
+ let compressed = readLocalFileData(bytes, central);
115
+ if (central.flag & 0x0001) {
116
+ encrypted.push(path);
117
+ if (!options.password) {
118
+ errors.push({ code: 'archive.password-required', ref: path, message: 'Password required for password-protected zip material.' });
119
+ continue;
120
+ }
121
+ if (central.flag & 0x0008) throw new Error('zip.encrypted-data-descriptor.unsupported');
122
+ if (central.method !== 0) throw new Error(`zip.encrypted-method.unsupported:${central.method}`);
123
+ const plain = zipCryptoDecryptBytes(compressed, options.password);
124
+ const verificationByte = (central.crc >>> 24) & 0xff;
125
+ if (plain.byteLength < 12 || plain[11] !== verificationByte) throw new Error('zip.password.invalid');
126
+ compressed = plain.slice(12);
127
+ if (compressed.byteLength !== central.uncompressedSize) throw new Error('zip.encrypted-size-mismatch');
128
+ if (crc32Bytes(compressed) !== central.crc) throw new Error('zip.password.invalid-or-corrupt');
129
+ }
130
+ const data = await decompressZipEntry(compressed, central.method);
131
+ let content = null;
132
+ if (MARKDOWN_RE.test(path) || (TEXT_ASSET_RE.test(path) && data.byteLength <= MAX_TEXT_ASSET_PREVIEW_BYTES)) content = TEXT_DECODER.decode(data);
133
+ entries.push({
134
+ path,
135
+ bytes: data,
136
+ content,
137
+ type: mimeTypeForPath(path),
138
+ size: data.byteLength,
139
+ lastModified: '',
140
+ source: options.source || 'zip',
141
+ kind: classifyArchiveEntry(path, content)
142
+ });
143
+ } catch (error) {
144
+ unsupported.push(path);
145
+ errors.push({ code: 'archive.entry-read-failed', ref: path, message: String(error && error.message ? error.message : error) });
146
+ }
147
+ }
148
+
149
+ return {
150
+ entries,
151
+ errors,
152
+ warnings,
153
+ diagnostics: {
154
+ requestedCount: centralEntries.length,
155
+ encryptedCount: encrypted.length,
156
+ unsupportedCount: unsupported.length,
157
+ unsafeCount: unsafe.length,
158
+ archiveDecodePassCount: 1
159
+ }
160
+ };
161
+ }
162
+
163
+ export async function qualifyDecodedArchiveEntries(decoded = {}, options = {}) {
164
+ const warnings = [...(decoded.warnings || [])];
165
+ const errors = [...(decoded.errors || [])];
166
+ const filtered = await filterArchiveTransportEntries(decoded.entries || [], { ...options, stripPortableControl: false });
167
+ if (filtered.mergePreflight.status === 'blocked' && options.enforceMergePreflight !== false) {
168
+ for (const conflict of filtered.mergePreflight.conflicts || []) errors.push({ code: conflict.code, ref: conflict.path, message: 'Archive merge preflight detected missing or changed known lineage material.' });
169
+ }
170
+ const qualified = await qualifyPortableChangesetEntries(filtered.entries, warnings, errors, {
171
+ safePath: safeArchivePath,
172
+ isMarkdownPath: (value) => MARKDOWN_RE.test(value)
173
+ });
174
+ let materialEntries = qualified.entries;
175
+ let portableControlStrippedCount = 0;
176
+ if (!qualified.detected && filtered.portableControl && options.stripPortableControl !== false) {
177
+ const before = materialEntries.length;
178
+ materialEntries = materialEntries.filter((entry) => entry.path !== 'manifest.json' && entry.path !== 'checksums.json');
179
+ portableControlStrippedCount = before - materialEntries.length;
180
+ }
181
+ const blocked = filtered.mergePreflight.status === 'blocked' && options.enforceMergePreflight !== false;
182
+ return {
183
+ entries: blocked ? [] : materialEntries,
184
+ errors,
185
+ warnings,
186
+ diagnostics: {
187
+ ...(decoded.diagnostics || {}),
188
+ ...filtered.diagnostics,
189
+ portableControlStrippedCount,
190
+ portableChangesetCount: qualified.detected ? 1 : 0,
191
+ controlCount: qualified.controlCount
192
+ }
193
+ };
194
+ }
195
+
196
+ export async function zipBufferToImportEntries(zipBuffer, options = {}) {
197
+ const decoded = await decodeZipBufferEntries(zipBuffer, options);
198
+ return qualifyDecodedArchiveEntries(decoded, options);
199
+ }
200
+
201
+ export async function fileToArchiveDecodedEntries(file, options = {}) {
202
+ const relativePath = safeArchivePath(fileRelativePath(file) || file?.name || 'upload');
203
+ if (!relativePath) {
204
+ return { entries: [], errors: [{ code: 'archive.unsafe-path', ref: file?.name || 'upload', message: 'Unsafe local path skipped.' }], warnings: [], diagnostics: { unsafeCount: 1, archiveDecodePassCount: 0 } };
205
+ }
206
+ if (!/\.zip$/i.test(relativePath || file?.name || '')) throw new Error('archive.decoded-entries.zip-required');
207
+ const buffer = await file.arrayBuffer();
208
+ let password = options.password || '';
209
+ if (zipBufferHasEncryptedEntries(buffer) && !password && typeof options.passwordProvider === 'function') {
210
+ password = await options.passwordProvider(file);
211
+ }
212
+ return decodeZipBufferEntries(buffer, { ...options, password, source: options.source || 'zip', excludeRepositoryInternals: true });
213
+ }
214
+
215
+ export async function fileToArchiveImportEntries(file, options = {}) {
216
+ const relativePath = safeArchivePath(fileRelativePath(file) || file?.name || 'upload');
217
+ if (!relativePath) {
218
+ return { entries: [], errors: [{ code: 'archive.unsafe-path', ref: file?.name || 'upload', message: 'Unsafe local path skipped.' }], warnings: [], diagnostics: { unsafeCount: 1 } };
219
+ }
220
+ if (/\.zip$/i.test(relativePath || file?.name || '')) {
221
+ const decoded = await fileToArchiveDecodedEntries(file, options);
222
+ return qualifyDecodedArchiveEntries(decoded, options);
223
+ }
224
+ const bytes = new Uint8Array(await file.arrayBuffer?.() || TEXT_ENCODER.encode(await file.text?.() || ''));
225
+ let content = null;
226
+ if (MARKDOWN_RE.test(relativePath) || TEXT_ASSET_RE.test(relativePath)) content = typeof file.text === 'function' ? await file.text() : TEXT_DECODER.decode(bytes);
227
+ return { entries: [{ path: relativePath, bytes, content, type: file.type || mimeTypeForPath(relativePath), size: Number(file.size || bytes.byteLength || 0), lastModified: file.lastModified ? new Date(file.lastModified).toISOString() : '', source: 'upload', kind: classifyArchiveEntry(relativePath, content) }], errors: [], warnings: [], diagnostics: { requestedCount: 1 } };
228
+ }
229
+
230
+ export async function materializeArchiveFiles(files = [], options = {}) {
231
+ const records = [];
232
+ const assets = [];
233
+ const workspaceEntries = [];
234
+ const errors = [];
235
+ const warnings = [];
236
+ const transport = resolveTransportPlan(options.sourceConfig || {}, 'local-import', { defaultLevel: 'TL0', allowFallback: false });
237
+ const diagnostics = { sourceBoundary: 'local-archive', transportLevel: transport.selectedLevel, transportOperation: transport.operation, transport, fileCount: 0, entryCount: 0, recordCount: 0, assetCount: 0, workspaceCount: 0, controlCount: 0, portableChangesetCount: 0, encryptedCount: 0, unsafeCount: 0, unsupportedCount: 0, previewOmittedCount: 0, bootstrapDetected: false, bootstrapStrippedCount: 0, portableControlDetected: false, portableControlStrippedCount: 0, archiveDecodePassCount: 0, mergePreflight: null, suggestedWorkspaceName: suggestWorkspaceNameForFiles(files) };
238
+
239
+ for (const file of Array.from(files || []).filter(Boolean)) {
240
+ diagnostics.fileCount += 1;
241
+ try {
242
+ const result = options.predecodedArchive && Array.from(files || []).filter(Boolean).length === 1
243
+ ? await qualifyDecodedArchiveEntries(options.predecodedArchive, options)
244
+ : await fileToArchiveImportEntries(file, options);
245
+ errors.push(...(result.errors || []));
246
+ warnings.push(...(result.warnings || []));
247
+ diagnostics.encryptedCount += Number(result.diagnostics?.encryptedCount || 0);
248
+ diagnostics.unsafeCount += Number(result.diagnostics?.unsafeCount || 0);
249
+ diagnostics.unsupportedCount += Number(result.diagnostics?.unsupportedCount || 0);
250
+ diagnostics.archiveDecodePassCount += Number(result.diagnostics?.archiveDecodePassCount || 0);
251
+ diagnostics.bootstrapDetected = diagnostics.bootstrapDetected || Boolean(result.diagnostics?.bootstrapDetected);
252
+ diagnostics.bootstrapStrippedCount += Number(result.diagnostics?.bootstrapStrippedCount || 0);
253
+ diagnostics.portableControlDetected = diagnostics.portableControlDetected || Boolean(result.diagnostics?.portableControlDetected);
254
+ diagnostics.portableControlStrippedCount += Number(result.diagnostics?.portableControlStrippedCount || 0);
255
+ diagnostics.portableChangesetCount += Number(result.diagnostics?.portableChangesetCount || 0);
256
+ diagnostics.controlCount += Number(result.diagnostics?.controlCount || 0);
257
+ if (result.diagnostics?.mergePreflight && result.diagnostics.mergePreflight.status !== 'not-applicable') diagnostics.mergePreflight = result.diagnostics.mergePreflight;
258
+ for (const entry of result.entries || []) {
259
+ diagnostics.entryCount += 1;
260
+ if (entry.kind === 'control') {
261
+ continue;
262
+ } else if (entry.kind === 'workspace') {
263
+ workspaceEntries.push(workspaceEntryFromImportEntry(entry));
264
+ } else if (entry.kind === 'record') {
265
+ records.push(createRecordFromMarkdown(entry.content || '', { path: entry.path, name: fileName(entry.path), sourceMode: options.sourceMode || 'archive-local' }));
266
+ } else if (entry.kind === 'asset') {
267
+ {
268
+ const asset = assetFromImportEntry(entry);
269
+ if (asset.previewState && asset.previewState !== 'available') diagnostics.previewOmittedCount += 1;
270
+ assets.push(asset);
271
+ }
272
+ }
273
+ }
274
+ } catch (error) {
275
+ errors.push({ code: 'archive.read-failed', ref: file?.name || 'archive', message: String(error && error.message ? error.message : error) });
276
+ }
277
+ }
278
+
279
+ diagnostics.recordCount = records.length;
280
+ diagnostics.assetCount = assets.length;
281
+ diagnostics.workspaceCount = workspaceEntries.length;
282
+
283
+ return makeAdapterResult({
284
+ adapterId: ARCHIVE_ADAPTER_ID,
285
+ sourceId: 'local',
286
+ records,
287
+ assets,
288
+ workspaceEntries,
289
+ errors,
290
+ warnings,
291
+ diagnostics
292
+ });
293
+ }
294
+
295
+ export function workspaceEntryFromImportEntry(entry = {}) {
296
+ const markdown = String(entry.content || '');
297
+ return {
298
+ schema: 'tiinex.workspace.import.v1',
299
+ path: entry.path || 'workspace.workspace.md',
300
+ title: workspaceTitleFromMarkdown(markdown) || fileName(entry.path || 'workspace.workspace.md'),
301
+ markdown,
302
+ sourceMode: entry.source || 'zip',
303
+ boundary: 'browser-local workspace import candidate; open/merge decision belongs to workspace lifecycle/UI'
304
+ };
305
+ }
306
+
307
+ export function assetFromImportEntry(entry = {}) {
308
+ const path = entry.path || 'asset';
309
+ const size = Number(entry.size || entry.bytes?.byteLength || 0);
310
+ const type = entry.type || mimeTypeForPath(path);
311
+ const textPreview = typeof entry.content === 'string' && entry.content.length <= MAX_TEXT_ASSET_PREVIEW_BYTES ? entry.content : '';
312
+ const canPreviewBinary = !textPreview && IMAGE_ASSET_RE.test(path) && size > 0 && size <= MAX_BINARY_ASSET_DATA_URL_BYTES;
313
+ const dataUrl = canPreviewBinary ? bytesToDataUrl(entry.bytes || new Uint8Array(), type) : '';
314
+ const previewState = textPreview || dataUrl ? 'available' : (size > MAX_BINARY_ASSET_DATA_URL_BYTES || size > MAX_TEXT_ASSET_PREVIEW_BYTES ? 'omitted-large' : 'metadata-only');
315
+ return {
316
+ schema: 'tiinex.local.asset.v1',
317
+ id: `asset:local:${path}`,
318
+ path,
319
+ name: fileName(path),
320
+ type,
321
+ size,
322
+ content: textPreview,
323
+ dataUrl,
324
+ previewState,
325
+ sourceMode: entry.source || 'zip',
326
+ source: { kind: 'local-session', adapterId: 'archive', sourceKind: 'archive.zip', boundary: 'browser-local archive asset; no GitHub provenance inferred' }
327
+ };
328
+ }
329
+
330
+ export function workspaceTitleFromMarkdown(markdown = '') {
331
+ const text = String(markdown || '');
332
+ const browserTitle = text.match(/^\s*-\s*Browser Title:\s*(.+)$/mi)?.[1]?.trim();
333
+ if (browserTitle) return stripMarkdown(browserTitle).slice(0, 72);
334
+ const heading = text.match(/^#\s+(.+)\s*$/m)?.[1]?.trim();
335
+ return stripMarkdown(heading || '').slice(0, 72);
336
+ }
337
+
338
+ function readCentralEntries(bytes) {
339
+ const eocdOffset = findEndOfCentralDirectory(bytes);
340
+ if (eocdOffset < 0) return [];
341
+ const count = zipU16(bytes, eocdOffset + 10);
342
+ const cdOffset = zipU32(bytes, eocdOffset + 16);
343
+ const entries = [];
344
+ let offset = cdOffset;
345
+ for (let i = 0; i < count && offset + 46 <= bytes.length; i += 1) {
346
+ if (zipU32(bytes, offset) !== 0x02014b50) break;
347
+ const flag = zipU16(bytes, offset + 8);
348
+ const method = zipU16(bytes, offset + 10);
349
+ const compressedSize = zipU32(bytes, offset + 20);
350
+ const uncompressedSize = zipU32(bytes, offset + 24);
351
+ const nameLength = zipU16(bytes, offset + 28);
352
+ const extraLength = zipU16(bytes, offset + 30);
353
+ const commentLength = zipU16(bytes, offset + 32);
354
+ const crc = zipU32(bytes, offset + 16);
355
+ const localOffset = zipU32(bytes, offset + 42);
356
+ const name = decodeZipName(bytes.slice(offset + 46, offset + 46 + nameLength), flag);
357
+ entries.push({ flag, method, crc, compressedSize, uncompressedSize, name, localOffset, isDirectory: name.endsWith('/') });
358
+ offset += 46 + nameLength + extraLength + commentLength;
359
+ }
360
+ return entries;
361
+ }
362
+
363
+ function forEachCentralEntry(bytes, visitor) {
364
+ for (const entry of readCentralEntries(bytes)) visitor(entry);
365
+ }
366
+
367
+ function findEndOfCentralDirectory(bytes) {
368
+ const min = Math.max(0, bytes.length - 0xffff - 22);
369
+ for (let offset = bytes.length - 22; offset >= min; offset -= 1) {
370
+ if (zipU32(bytes, offset) === 0x06054b50) return offset;
371
+ }
372
+ return -1;
373
+ }
374
+
375
+ function readLocalFileData(bytes, central) {
376
+ const offset = central.localOffset;
377
+ if (zipU32(bytes, offset) !== 0x04034b50) throw new Error('zip.local-header-missing');
378
+ const nameLength = zipU16(bytes, offset + 26);
379
+ const extraLength = zipU16(bytes, offset + 28);
380
+ const start = offset + 30 + nameLength + extraLength;
381
+ const end = start + central.compressedSize;
382
+ if (end > bytes.length) throw new Error('zip.entry-truncated');
383
+ return bytes.slice(start, end);
384
+ }
385
+
386
+ async function decompressZipEntry(compressed, method) {
387
+ if (method === 0) return compressed;
388
+ if (method !== 8) throw new Error(`zip.method.unsupported:${method}`);
389
+ if (typeof DecompressionStream === 'undefined') throw new Error('zip.deflate.bridge-unavailable');
390
+ const stream = new Blob([compressed]).stream().pipeThrough(new DecompressionStream('deflate-raw'));
391
+ return new Uint8Array(await new Response(stream).arrayBuffer());
392
+ }
393
+
394
+
395
+ const CRC32_TABLE = (() => {
396
+ const table = new Uint32Array(256);
397
+ for (let n = 0; n < 256; n += 1) {
398
+ let c = n;
399
+ for (let k = 0; k < 8; k += 1) c = (c & 1) ? (0xedb88320 ^ (c >>> 1)) : (c >>> 1);
400
+ table[n] = c >>> 0;
401
+ }
402
+ return table;
403
+ })();
404
+ function crc32Update(crc, byte) { return (CRC32_TABLE[(crc ^ byte) & 0xff] ^ (crc >>> 8)) >>> 0; }
405
+ function crc32Bytes(bytes) { let crc = 0xffffffff; for (const byte of bytes) crc = crc32Update(crc, byte); return (crc ^ 0xffffffff) >>> 0; }
406
+ function zipCryptoKeys(password = '') {
407
+ const keys = { k0: 0x12345678 >>> 0, k1: 0x23456789 >>> 0, k2: 0x34567890 >>> 0 };
408
+ for (const byte of TEXT_ENCODER.encode(password)) zipCryptoUpdateKeys(keys, byte);
409
+ return keys;
410
+ }
411
+ function zipCryptoUpdateKeys(keys, byte) {
412
+ keys.k0 = crc32Update(keys.k0, byte);
413
+ keys.k1 = (Math.imul((keys.k1 + (keys.k0 & 0xff)) >>> 0, 134775813) + 1) >>> 0;
414
+ keys.k2 = crc32Update(keys.k2, (keys.k1 >>> 24) & 0xff);
415
+ }
416
+ function zipCryptoDecryptByte(keys) { const temp = (keys.k2 | 2) >>> 0; return ((Math.imul(temp, (temp ^ 1) >>> 0) >>> 8) & 0xff) >>> 0; }
417
+ function zipCryptoDecryptBytes(bytes, password) {
418
+ const keys = zipCryptoKeys(password);
419
+ const out = new Uint8Array(bytes.byteLength);
420
+ for (let i = 0; i < bytes.byteLength; i += 1) {
421
+ const plain = bytes[i] ^ zipCryptoDecryptByte(keys);
422
+ out[i] = plain;
423
+ zipCryptoUpdateKeys(keys, plain);
424
+ }
425
+ return out;
426
+ }
427
+
428
+ function bytesFrom(value) {
429
+ if (value instanceof Uint8Array) return value;
430
+ if (value instanceof ArrayBuffer) return new Uint8Array(value);
431
+ if (ArrayBuffer.isView(value)) return new Uint8Array(value.buffer, value.byteOffset, value.byteLength);
432
+ return new Uint8Array(value || []);
433
+ }
434
+
435
+ function zipU16(bytes, offset) {
436
+ return (bytes[offset] | (bytes[offset + 1] << 8)) >>> 0;
437
+ }
438
+
439
+ function zipU32(bytes, offset) {
440
+ return (bytes[offset] | (bytes[offset + 1] << 8) | (bytes[offset + 2] << 16) | (bytes[offset + 3] << 24)) >>> 0;
441
+ }
442
+
443
+ function decodeZipName(bytes, flag) {
444
+ // UTF-8 flag is 0x800. The legacy viewer treats zip entry names as UTF-8 in practice;
445
+ // falling back to TextDecoder keeps browser behavior deterministic without guessing provenance.
446
+ return TEXT_DECODER.decode(bytes);
447
+ }
448
+
449
+
450
+ function suggestWorkspaceNameForFiles(files = []) {
451
+ const list = Array.from(files || []).filter(Boolean);
452
+ if (!list.length) return 'Local import';
453
+ if (list.length === 1) {
454
+ const raw = fileRelativePath(list[0]) || list[0].name || 'Local import';
455
+ const base = fileName(raw).replace(/\.(?:zip|md|markdown|trace\.md|workspace\.md)$/i, '').replace(/[-_]+/g, ' ').trim();
456
+ return titleCase(base || 'Local import');
457
+ }
458
+ const roots = new Set(list.map((file) => String(fileRelativePath(file) || file.name || '').replace(/\\/g, '/').split('/').filter(Boolean)[0]).filter(Boolean));
459
+ if (roots.size === 1) return titleCase(Array.from(roots)[0].replace(/[-_]+/g, ' '));
460
+ return 'Local import';
461
+ }
462
+
463
+ function titleCase(value = '') {
464
+ return String(value || '').replace(/\s+/g, ' ').trim().replace(/\b\w/g, (m) => m.toUpperCase()).slice(0, 72) || 'Local import';
465
+ }
466
+
467
+ function fileRelativePath(file = {}) {
468
+ return file.tiinexRelativePath || file.relativePath || file.webkitRelativePath || file.path || file.name || '';
469
+ }
470
+
471
+ function fileName(path = '') {
472
+ return String(path || '').split('/').filter(Boolean).pop() || 'asset';
473
+ }
474
+
475
+ function stripMarkdown(value = '') {
476
+ return String(value || '').replace(/^\[([^\]]+)\]\([^)]*\)$/, '$1').trim();
477
+ }
478
+
479
+ function bytesToDataUrl(bytes, type = 'application/octet-stream') {
480
+ const body = base64FromBytes(bytes);
481
+ return `data:${type || 'application/octet-stream'};base64,${body}`;
482
+ }
483
+
484
+ function base64FromBytes(bytes) {
485
+ if (typeof Buffer !== 'undefined') return Buffer.from(bytes).toString('base64');
486
+ let binary = '';
487
+ for (const byte of bytes || []) binary += String.fromCharCode(byte);
488
+ return btoa(binary);
489
+ }
490
+
491
+ function mimeTypeForPath(path = '') {
492
+ const lower = String(path || '').toLowerCase();
493
+ if (lower.endsWith('.png')) return 'image/png';
494
+ if (lower.endsWith('.jpg') || lower.endsWith('.jpeg')) return 'image/jpeg';
495
+ if (lower.endsWith('.gif')) return 'image/gif';
496
+ if (lower.endsWith('.webp')) return 'image/webp';
497
+ if (lower.endsWith('.svg')) return 'image/svg+xml';
498
+ if (lower.endsWith('.md') || lower.endsWith('.markdown') || lower.endsWith('.trace.md') || lower.endsWith('.workspace.md')) return 'text/markdown;charset=utf-8';
499
+ if (lower.endsWith('.json')) return 'application/json';
500
+ if (lower.endsWith('.txt')) return 'text/plain;charset=utf-8';
501
+ return 'application/octet-stream';
502
+ }
@@ -0,0 +1,141 @@
1
+ const PORTABLE_CHANGESET_MANIFEST_SCHEMA_ID = 'tiinex.portable.changeset.manifest.v1';
2
+ const PORTABLE_CHANGESET_CHECKSUMS_SCHEMA_ID = 'tiinex.portable.changeset.checksums.v1';
3
+
4
+ export async function qualifyPortableChangesetEntries(entries = [], warnings = [], errors = [], options = {}) {
5
+ const safePath = typeof options.safePath === 'function' ? options.safePath : (value) => String(value || '').trim();
6
+ const isMarkdownPath = typeof options.isMarkdownPath === 'function' ? options.isMarkdownPath : () => false;
7
+ const manifestEntries = entries.filter((entry) => entry.path === 'manifest.json');
8
+ if (manifestEntries.length !== 1 || typeof manifestEntries[0].content !== 'string') return unchanged(entries);
9
+ const manifest = parseJsonObject(manifestEntries[0].content);
10
+ if (!manifest || manifest.schema !== PORTABLE_CHANGESET_MANIFEST_SCHEMA_ID) return unchanged(entries);
11
+
12
+ const checksumsEntries = entries.filter((entry) => entry.path === 'checksums.json');
13
+ const controls = [controlEntry(manifestEntries[0], 'manifest')];
14
+ if (checksumsEntries.length === 1) controls.push(controlEntry(checksumsEntries[0], 'checksums'));
15
+ const fail = (code, ref, message) => errors.push({ code, ref, message });
16
+
17
+ if (checksumsEntries.length !== 1 || typeof checksumsEntries[0]?.content !== 'string') {
18
+ fail('archive.portable-changeset.checksums-missing', 'checksums.json', 'Portable changeset requires exactly one readable root checksums.json control file.');
19
+ return blocked(controls);
20
+ }
21
+ const checksums = parseJsonObject(checksumsEntries[0].content);
22
+ if (!checksums || checksums.schema !== PORTABLE_CHANGESET_CHECKSUMS_SCHEMA_ID || checksums.algorithm !== 'sha256') {
23
+ fail('archive.portable-changeset.checksums-invalid', 'checksums.json', 'Portable changeset checksum control file is unsupported or invalid.');
24
+ return blocked(controls);
25
+ }
26
+
27
+ const material = Array.isArray(manifest.material) ? manifest.material : [];
28
+ const fileEntries = indexEntries(entries);
29
+ const checksumEntries = indexChecksums(checksums.files, safePath, fail);
30
+ await verifyPortableEntry(manifestEntries[0], checksumEntries.get('manifest.json'), '', fail);
31
+
32
+ const allowedPaths = new Set(['manifest.json', 'checksums.json']);
33
+ const materialEntries = [];
34
+ for (const declaration of material) {
35
+ const declaredPath = safePath(declaration?.path || '');
36
+ if (!declaredPath || declaredPath === '.bootstrap' || declaredPath.startsWith('.bootstrap/')) {
37
+ fail('archive.portable-changeset.material-path-invalid', String(declaration?.path || ''), 'Portable changeset material path is unsafe or transport-reserved.');
38
+ continue;
39
+ }
40
+ if (allowedPaths.has(declaredPath)) {
41
+ fail('archive.portable-changeset.material-path-duplicate', declaredPath, 'Portable changeset material paths must be unique and cannot replace control files.');
42
+ continue;
43
+ }
44
+ allowedPaths.add(declaredPath);
45
+ const matches = fileEntries.get(declaredPath) || [];
46
+ if (matches.length !== 1) {
47
+ fail(matches.length ? 'archive.portable-changeset.material-duplicate' : 'archive.portable-changeset.material-missing', declaredPath, matches.length ? 'Portable changeset material path appears more than once.' : 'Declared portable changeset material is missing.');
48
+ continue;
49
+ }
50
+ const kind = String(declaration?.kind || '').trim();
51
+ if (kind === 'artifact' && !isMarkdownPath(declaredPath)) {
52
+ fail('archive.portable-changeset.artifact-path-invalid', declaredPath, 'Portable artifact material must use a supported Markdown artifact path.');
53
+ continue;
54
+ }
55
+ if (kind !== 'artifact' && kind !== 'asset') {
56
+ fail('archive.portable-changeset.material-kind-unsupported', declaredPath, 'Portable changeset material kind must be artifact or asset.');
57
+ continue;
58
+ }
59
+ await verifyPortableEntry(matches[0], checksumEntries.get(declaredPath), String(declaration?.sha256 || ''), fail);
60
+ materialEntries.push(Object.freeze({
61
+ ...matches[0],
62
+ kind: kind === 'artifact' ? 'record' : 'asset',
63
+ packageRole: kind,
64
+ packageDeclaration: Object.freeze({ ...declaration })
65
+ }));
66
+ }
67
+
68
+ for (const entry of entries) {
69
+ if (allowedPaths.has(entry.path)) continue;
70
+ warnings.push({ code: 'archive.portable-changeset.undeclared-entry-skipped', ref: entry.path, message: 'Undeclared portable changeset entry was skipped instead of becoming workspace material.' });
71
+ }
72
+ if (errors.some((entry) => String(entry.code || '').startsWith('archive.portable-changeset.'))) return blocked(controls);
73
+ return Object.freeze({ entries: Object.freeze([...controls, ...materialEntries]), detected: true, controlCount: controls.length });
74
+ }
75
+
76
+ function unchanged(entries) {
77
+ return Object.freeze({ entries, detected: false, controlCount: 0 });
78
+ }
79
+ function blocked(controls) {
80
+ return Object.freeze({ entries: Object.freeze(controls), detected: true, controlCount: controls.length });
81
+ }
82
+ function controlEntry(entry, packageRole) {
83
+ return Object.freeze({ ...entry, kind: 'control', packageRole });
84
+ }
85
+ function indexEntries(entries) {
86
+ const output = new Map();
87
+ for (const entry of entries) {
88
+ if (!output.has(entry.path)) output.set(entry.path, []);
89
+ output.get(entry.path).push(entry);
90
+ }
91
+ return output;
92
+ }
93
+ function indexChecksums(files, safePath, fail) {
94
+ const output = new Map();
95
+ for (const entry of Array.isArray(files) ? files : []) {
96
+ const path = safePath(entry?.path || '');
97
+ if (!path || output.has(path)) {
98
+ fail('archive.portable-changeset.checksum-entry-invalid', String(entry?.path || ''), 'Portable changeset checksum paths must be safe and unique.');
99
+ continue;
100
+ }
101
+ output.set(path, entry);
102
+ }
103
+ return output;
104
+ }
105
+ async function verifyPortableEntry(entry, checksumEntry, manifestSha256, fail) {
106
+ if (!checksumEntry) {
107
+ fail('archive.portable-changeset.checksum-missing', entry?.path || '', 'Portable changeset entry has no checksum declaration.');
108
+ return;
109
+ }
110
+ const bytes = bytesFrom(entry?.bytes || []);
111
+ const actual = await sha256Hex(bytes);
112
+ const expected = String(checksumEntry.sha256 || '').trim();
113
+ const expectedBytes = Number(checksumEntry.bytes || 0);
114
+ if (!/^[a-f0-9]{64}$/.test(expected) || expectedBytes !== bytes.byteLength || expected !== actual) {
115
+ fail('archive.portable-changeset.checksum-mismatch', entry?.path || '', 'Portable changeset entry does not match its declared bytes and SHA-256 digest.');
116
+ }
117
+ if (manifestSha256 && manifestSha256 !== actual) {
118
+ fail('archive.portable-changeset.manifest-digest-mismatch', entry?.path || '', 'Portable changeset material does not match the digest declared in manifest.json.');
119
+ }
120
+ }
121
+ function parseJsonObject(value = '') {
122
+ try {
123
+ const parsed = JSON.parse(String(value || ''));
124
+ return parsed && typeof parsed === 'object' && !Array.isArray(parsed) ? parsed : null;
125
+ } catch {
126
+ return null;
127
+ }
128
+ }
129
+ async function sha256Hex(bytes) {
130
+ if (!globalThis.crypto?.subtle) throw new Error('archive.sha256.bridge-unavailable');
131
+ const view = bytesFrom(bytes);
132
+ const buffer = view.buffer.slice(view.byteOffset, view.byteOffset + view.byteLength);
133
+ const digest = new Uint8Array(await globalThis.crypto.subtle.digest('SHA-256', buffer));
134
+ return Array.from(digest, (byte) => byte.toString(16).padStart(2, '0')).join('');
135
+ }
136
+ function bytesFrom(value) {
137
+ if (value instanceof Uint8Array) return value;
138
+ if (value instanceof ArrayBuffer) return new Uint8Array(value);
139
+ if (ArrayBuffer.isView(value)) return new Uint8Array(value.buffer, value.byteOffset, value.byteLength);
140
+ return new Uint8Array(value || []);
141
+ }