@tiangong-lca/pcr 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (581) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE.md +5 -0
  3. package/README.md +107 -2
  4. package/node_modules/ajv/.runkit_example.js +23 -0
  5. package/node_modules/ajv/LICENSE +22 -0
  6. package/node_modules/ajv/README.md +207 -0
  7. package/node_modules/ajv/dist/2019.d.ts +19 -0
  8. package/node_modules/ajv/dist/2019.js +61 -0
  9. package/node_modules/ajv/dist/2019.js.map +1 -0
  10. package/node_modules/ajv/dist/2020.d.ts +19 -0
  11. package/node_modules/ajv/dist/2020.js +55 -0
  12. package/node_modules/ajv/dist/2020.js.map +1 -0
  13. package/node_modules/ajv/dist/ajv.d.ts +18 -0
  14. package/node_modules/ajv/dist/ajv.js +50 -0
  15. package/node_modules/ajv/dist/ajv.js.map +1 -0
  16. package/node_modules/ajv/dist/compile/codegen/code.d.ts +40 -0
  17. package/node_modules/ajv/dist/compile/codegen/code.js +156 -0
  18. package/node_modules/ajv/dist/compile/codegen/code.js.map +1 -0
  19. package/node_modules/ajv/dist/compile/codegen/index.d.ts +79 -0
  20. package/node_modules/ajv/dist/compile/codegen/index.js +697 -0
  21. package/node_modules/ajv/dist/compile/codegen/index.js.map +1 -0
  22. package/node_modules/ajv/dist/compile/codegen/scope.d.ts +79 -0
  23. package/node_modules/ajv/dist/compile/codegen/scope.js +143 -0
  24. package/node_modules/ajv/dist/compile/codegen/scope.js.map +1 -0
  25. package/node_modules/ajv/dist/compile/errors.d.ts +13 -0
  26. package/node_modules/ajv/dist/compile/errors.js +123 -0
  27. package/node_modules/ajv/dist/compile/errors.js.map +1 -0
  28. package/node_modules/ajv/dist/compile/index.d.ts +80 -0
  29. package/node_modules/ajv/dist/compile/index.js +242 -0
  30. package/node_modules/ajv/dist/compile/index.js.map +1 -0
  31. package/node_modules/ajv/dist/compile/jtd/parse.d.ts +4 -0
  32. package/node_modules/ajv/dist/compile/jtd/parse.js +350 -0
  33. package/node_modules/ajv/dist/compile/jtd/parse.js.map +1 -0
  34. package/node_modules/ajv/dist/compile/jtd/serialize.d.ts +4 -0
  35. package/node_modules/ajv/dist/compile/jtd/serialize.js +236 -0
  36. package/node_modules/ajv/dist/compile/jtd/serialize.js.map +1 -0
  37. package/node_modules/ajv/dist/compile/jtd/types.d.ts +6 -0
  38. package/node_modules/ajv/dist/compile/jtd/types.js +14 -0
  39. package/node_modules/ajv/dist/compile/jtd/types.js.map +1 -0
  40. package/node_modules/ajv/dist/compile/names.d.ts +20 -0
  41. package/node_modules/ajv/dist/compile/names.js +28 -0
  42. package/node_modules/ajv/dist/compile/names.js.map +1 -0
  43. package/node_modules/ajv/dist/compile/ref_error.d.ts +6 -0
  44. package/node_modules/ajv/dist/compile/ref_error.js +12 -0
  45. package/node_modules/ajv/dist/compile/ref_error.js.map +1 -0
  46. package/node_modules/ajv/dist/compile/resolve.d.ts +12 -0
  47. package/node_modules/ajv/dist/compile/resolve.js +155 -0
  48. package/node_modules/ajv/dist/compile/resolve.js.map +1 -0
  49. package/node_modules/ajv/dist/compile/rules.d.ts +28 -0
  50. package/node_modules/ajv/dist/compile/rules.js +26 -0
  51. package/node_modules/ajv/dist/compile/rules.js.map +1 -0
  52. package/node_modules/ajv/dist/compile/util.d.ts +40 -0
  53. package/node_modules/ajv/dist/compile/util.js +178 -0
  54. package/node_modules/ajv/dist/compile/util.js.map +1 -0
  55. package/node_modules/ajv/dist/compile/validate/applicability.d.ts +6 -0
  56. package/node_modules/ajv/dist/compile/validate/applicability.js +19 -0
  57. package/node_modules/ajv/dist/compile/validate/applicability.js.map +1 -0
  58. package/node_modules/ajv/dist/compile/validate/boolSchema.d.ts +4 -0
  59. package/node_modules/ajv/dist/compile/validate/boolSchema.js +50 -0
  60. package/node_modules/ajv/dist/compile/validate/boolSchema.js.map +1 -0
  61. package/node_modules/ajv/dist/compile/validate/dataType.d.ts +17 -0
  62. package/node_modules/ajv/dist/compile/validate/dataType.js +203 -0
  63. package/node_modules/ajv/dist/compile/validate/dataType.js.map +1 -0
  64. package/node_modules/ajv/dist/compile/validate/defaults.d.ts +2 -0
  65. package/node_modules/ajv/dist/compile/validate/defaults.js +35 -0
  66. package/node_modules/ajv/dist/compile/validate/defaults.js.map +1 -0
  67. package/node_modules/ajv/dist/compile/validate/index.d.ts +42 -0
  68. package/node_modules/ajv/dist/compile/validate/index.js +520 -0
  69. package/node_modules/ajv/dist/compile/validate/index.js.map +1 -0
  70. package/node_modules/ajv/dist/compile/validate/keyword.d.ts +8 -0
  71. package/node_modules/ajv/dist/compile/validate/keyword.js +124 -0
  72. package/node_modules/ajv/dist/compile/validate/keyword.js.map +1 -0
  73. package/node_modules/ajv/dist/compile/validate/subschema.d.ts +47 -0
  74. package/node_modules/ajv/dist/compile/validate/subschema.js +81 -0
  75. package/node_modules/ajv/dist/compile/validate/subschema.js.map +1 -0
  76. package/node_modules/ajv/dist/core.d.ts +174 -0
  77. package/node_modules/ajv/dist/core.js +618 -0
  78. package/node_modules/ajv/dist/core.js.map +1 -0
  79. package/node_modules/ajv/dist/jtd.d.ts +47 -0
  80. package/node_modules/ajv/dist/jtd.js +72 -0
  81. package/node_modules/ajv/dist/jtd.js.map +1 -0
  82. package/node_modules/ajv/dist/refs/data.json +13 -0
  83. package/node_modules/ajv/dist/refs/json-schema-2019-09/index.d.ts +2 -0
  84. package/node_modules/ajv/dist/refs/json-schema-2019-09/index.js +28 -0
  85. package/node_modules/ajv/dist/refs/json-schema-2019-09/index.js.map +1 -0
  86. package/node_modules/ajv/dist/refs/json-schema-2019-09/meta/applicator.json +53 -0
  87. package/node_modules/ajv/dist/refs/json-schema-2019-09/meta/content.json +17 -0
  88. package/node_modules/ajv/dist/refs/json-schema-2019-09/meta/core.json +57 -0
  89. package/node_modules/ajv/dist/refs/json-schema-2019-09/meta/format.json +14 -0
  90. package/node_modules/ajv/dist/refs/json-schema-2019-09/meta/meta-data.json +37 -0
  91. package/node_modules/ajv/dist/refs/json-schema-2019-09/meta/validation.json +90 -0
  92. package/node_modules/ajv/dist/refs/json-schema-2019-09/schema.json +39 -0
  93. package/node_modules/ajv/dist/refs/json-schema-2020-12/index.d.ts +2 -0
  94. package/node_modules/ajv/dist/refs/json-schema-2020-12/index.js +30 -0
  95. package/node_modules/ajv/dist/refs/json-schema-2020-12/index.js.map +1 -0
  96. package/node_modules/ajv/dist/refs/json-schema-2020-12/meta/applicator.json +48 -0
  97. package/node_modules/ajv/dist/refs/json-schema-2020-12/meta/content.json +17 -0
  98. package/node_modules/ajv/dist/refs/json-schema-2020-12/meta/core.json +51 -0
  99. package/node_modules/ajv/dist/refs/json-schema-2020-12/meta/format-annotation.json +14 -0
  100. package/node_modules/ajv/dist/refs/json-schema-2020-12/meta/meta-data.json +37 -0
  101. package/node_modules/ajv/dist/refs/json-schema-2020-12/meta/unevaluated.json +15 -0
  102. package/node_modules/ajv/dist/refs/json-schema-2020-12/meta/validation.json +90 -0
  103. package/node_modules/ajv/dist/refs/json-schema-2020-12/schema.json +55 -0
  104. package/node_modules/ajv/dist/refs/json-schema-draft-06.json +137 -0
  105. package/node_modules/ajv/dist/refs/json-schema-draft-07.json +151 -0
  106. package/node_modules/ajv/dist/refs/json-schema-secure.json +88 -0
  107. package/node_modules/ajv/dist/refs/jtd-schema.d.ts +3 -0
  108. package/node_modules/ajv/dist/refs/jtd-schema.js +118 -0
  109. package/node_modules/ajv/dist/refs/jtd-schema.js.map +1 -0
  110. package/node_modules/ajv/dist/runtime/equal.d.ts +6 -0
  111. package/node_modules/ajv/dist/runtime/equal.js +7 -0
  112. package/node_modules/ajv/dist/runtime/equal.js.map +1 -0
  113. package/node_modules/ajv/dist/runtime/parseJson.d.ts +18 -0
  114. package/node_modules/ajv/dist/runtime/parseJson.js +185 -0
  115. package/node_modules/ajv/dist/runtime/parseJson.js.map +1 -0
  116. package/node_modules/ajv/dist/runtime/quote.d.ts +5 -0
  117. package/node_modules/ajv/dist/runtime/quote.js +30 -0
  118. package/node_modules/ajv/dist/runtime/quote.js.map +1 -0
  119. package/node_modules/ajv/dist/runtime/re2.d.ts +6 -0
  120. package/node_modules/ajv/dist/runtime/re2.js +6 -0
  121. package/node_modules/ajv/dist/runtime/re2.js.map +1 -0
  122. package/node_modules/ajv/dist/runtime/timestamp.d.ts +5 -0
  123. package/node_modules/ajv/dist/runtime/timestamp.js +42 -0
  124. package/node_modules/ajv/dist/runtime/timestamp.js.map +1 -0
  125. package/node_modules/ajv/dist/runtime/ucs2length.d.ts +5 -0
  126. package/node_modules/ajv/dist/runtime/ucs2length.js +24 -0
  127. package/node_modules/ajv/dist/runtime/ucs2length.js.map +1 -0
  128. package/node_modules/ajv/dist/runtime/uri.d.ts +6 -0
  129. package/node_modules/ajv/dist/runtime/uri.js +6 -0
  130. package/node_modules/ajv/dist/runtime/uri.js.map +1 -0
  131. package/node_modules/ajv/dist/runtime/validation_error.d.ts +7 -0
  132. package/node_modules/ajv/dist/runtime/validation_error.js +11 -0
  133. package/node_modules/ajv/dist/runtime/validation_error.js.map +1 -0
  134. package/node_modules/ajv/dist/standalone/index.d.ts +6 -0
  135. package/node_modules/ajv/dist/standalone/index.js +90 -0
  136. package/node_modules/ajv/dist/standalone/index.js.map +1 -0
  137. package/node_modules/ajv/dist/standalone/instance.d.ts +12 -0
  138. package/node_modules/ajv/dist/standalone/instance.js +35 -0
  139. package/node_modules/ajv/dist/standalone/instance.js.map +1 -0
  140. package/node_modules/ajv/dist/types/index.d.ts +183 -0
  141. package/node_modules/ajv/dist/types/index.js +3 -0
  142. package/node_modules/ajv/dist/types/index.js.map +1 -0
  143. package/node_modules/ajv/dist/types/json-schema.d.ts +125 -0
  144. package/node_modules/ajv/dist/types/json-schema.js +3 -0
  145. package/node_modules/ajv/dist/types/json-schema.js.map +1 -0
  146. package/node_modules/ajv/dist/types/jtd-schema.d.ts +174 -0
  147. package/node_modules/ajv/dist/types/jtd-schema.js +3 -0
  148. package/node_modules/ajv/dist/types/jtd-schema.js.map +1 -0
  149. package/node_modules/ajv/dist/vocabularies/applicator/additionalItems.d.ts +8 -0
  150. package/node_modules/ajv/dist/vocabularies/applicator/additionalItems.js +49 -0
  151. package/node_modules/ajv/dist/vocabularies/applicator/additionalItems.js.map +1 -0
  152. package/node_modules/ajv/dist/vocabularies/applicator/additionalProperties.d.ts +6 -0
  153. package/node_modules/ajv/dist/vocabularies/applicator/additionalProperties.js +106 -0
  154. package/node_modules/ajv/dist/vocabularies/applicator/additionalProperties.js.map +1 -0
  155. package/node_modules/ajv/dist/vocabularies/applicator/allOf.d.ts +3 -0
  156. package/node_modules/ajv/dist/vocabularies/applicator/allOf.js +23 -0
  157. package/node_modules/ajv/dist/vocabularies/applicator/allOf.js.map +1 -0
  158. package/node_modules/ajv/dist/vocabularies/applicator/anyOf.d.ts +4 -0
  159. package/node_modules/ajv/dist/vocabularies/applicator/anyOf.js +12 -0
  160. package/node_modules/ajv/dist/vocabularies/applicator/anyOf.js.map +1 -0
  161. package/node_modules/ajv/dist/vocabularies/applicator/contains.d.ts +7 -0
  162. package/node_modules/ajv/dist/vocabularies/applicator/contains.js +95 -0
  163. package/node_modules/ajv/dist/vocabularies/applicator/contains.js.map +1 -0
  164. package/node_modules/ajv/dist/vocabularies/applicator/dependencies.d.ts +21 -0
  165. package/node_modules/ajv/dist/vocabularies/applicator/dependencies.js +85 -0
  166. package/node_modules/ajv/dist/vocabularies/applicator/dependencies.js.map +1 -0
  167. package/node_modules/ajv/dist/vocabularies/applicator/dependentSchemas.d.ts +3 -0
  168. package/node_modules/ajv/dist/vocabularies/applicator/dependentSchemas.js +11 -0
  169. package/node_modules/ajv/dist/vocabularies/applicator/dependentSchemas.js.map +1 -0
  170. package/node_modules/ajv/dist/vocabularies/applicator/if.d.ts +6 -0
  171. package/node_modules/ajv/dist/vocabularies/applicator/if.js +66 -0
  172. package/node_modules/ajv/dist/vocabularies/applicator/if.js.map +1 -0
  173. package/node_modules/ajv/dist/vocabularies/applicator/index.d.ts +13 -0
  174. package/node_modules/ajv/dist/vocabularies/applicator/index.js +44 -0
  175. package/node_modules/ajv/dist/vocabularies/applicator/index.js.map +1 -0
  176. package/node_modules/ajv/dist/vocabularies/applicator/items.d.ts +5 -0
  177. package/node_modules/ajv/dist/vocabularies/applicator/items.js +52 -0
  178. package/node_modules/ajv/dist/vocabularies/applicator/items.js.map +1 -0
  179. package/node_modules/ajv/dist/vocabularies/applicator/items2020.d.ts +6 -0
  180. package/node_modules/ajv/dist/vocabularies/applicator/items2020.js +30 -0
  181. package/node_modules/ajv/dist/vocabularies/applicator/items2020.js.map +1 -0
  182. package/node_modules/ajv/dist/vocabularies/applicator/not.d.ts +4 -0
  183. package/node_modules/ajv/dist/vocabularies/applicator/not.js +26 -0
  184. package/node_modules/ajv/dist/vocabularies/applicator/not.js.map +1 -0
  185. package/node_modules/ajv/dist/vocabularies/applicator/oneOf.d.ts +6 -0
  186. package/node_modules/ajv/dist/vocabularies/applicator/oneOf.js +60 -0
  187. package/node_modules/ajv/dist/vocabularies/applicator/oneOf.js.map +1 -0
  188. package/node_modules/ajv/dist/vocabularies/applicator/patternProperties.d.ts +3 -0
  189. package/node_modules/ajv/dist/vocabularies/applicator/patternProperties.js +75 -0
  190. package/node_modules/ajv/dist/vocabularies/applicator/patternProperties.js.map +1 -0
  191. package/node_modules/ajv/dist/vocabularies/applicator/prefixItems.d.ts +3 -0
  192. package/node_modules/ajv/dist/vocabularies/applicator/prefixItems.js +12 -0
  193. package/node_modules/ajv/dist/vocabularies/applicator/prefixItems.js.map +1 -0
  194. package/node_modules/ajv/dist/vocabularies/applicator/properties.d.ts +3 -0
  195. package/node_modules/ajv/dist/vocabularies/applicator/properties.js +54 -0
  196. package/node_modules/ajv/dist/vocabularies/applicator/properties.js.map +1 -0
  197. package/node_modules/ajv/dist/vocabularies/applicator/propertyNames.d.ts +6 -0
  198. package/node_modules/ajv/dist/vocabularies/applicator/propertyNames.js +38 -0
  199. package/node_modules/ajv/dist/vocabularies/applicator/propertyNames.js.map +1 -0
  200. package/node_modules/ajv/dist/vocabularies/applicator/thenElse.d.ts +3 -0
  201. package/node_modules/ajv/dist/vocabularies/applicator/thenElse.js +13 -0
  202. package/node_modules/ajv/dist/vocabularies/applicator/thenElse.js.map +1 -0
  203. package/node_modules/ajv/dist/vocabularies/code.d.ts +17 -0
  204. package/node_modules/ajv/dist/vocabularies/code.js +131 -0
  205. package/node_modules/ajv/dist/vocabularies/code.js.map +1 -0
  206. package/node_modules/ajv/dist/vocabularies/core/id.d.ts +3 -0
  207. package/node_modules/ajv/dist/vocabularies/core/id.js +10 -0
  208. package/node_modules/ajv/dist/vocabularies/core/id.js.map +1 -0
  209. package/node_modules/ajv/dist/vocabularies/core/index.d.ts +3 -0
  210. package/node_modules/ajv/dist/vocabularies/core/index.js +16 -0
  211. package/node_modules/ajv/dist/vocabularies/core/index.js.map +1 -0
  212. package/node_modules/ajv/dist/vocabularies/core/ref.d.ts +8 -0
  213. package/node_modules/ajv/dist/vocabularies/core/ref.js +122 -0
  214. package/node_modules/ajv/dist/vocabularies/core/ref.js.map +1 -0
  215. package/node_modules/ajv/dist/vocabularies/discriminator/index.d.ts +5 -0
  216. package/node_modules/ajv/dist/vocabularies/discriminator/index.js +104 -0
  217. package/node_modules/ajv/dist/vocabularies/discriminator/index.js.map +1 -0
  218. package/node_modules/ajv/dist/vocabularies/discriminator/types.d.ts +10 -0
  219. package/node_modules/ajv/dist/vocabularies/discriminator/types.js +9 -0
  220. package/node_modules/ajv/dist/vocabularies/discriminator/types.js.map +1 -0
  221. package/node_modules/ajv/dist/vocabularies/draft2020.d.ts +3 -0
  222. package/node_modules/ajv/dist/vocabularies/draft2020.js +23 -0
  223. package/node_modules/ajv/dist/vocabularies/draft2020.js.map +1 -0
  224. package/node_modules/ajv/dist/vocabularies/draft7.d.ts +3 -0
  225. package/node_modules/ajv/dist/vocabularies/draft7.js +17 -0
  226. package/node_modules/ajv/dist/vocabularies/draft7.js.map +1 -0
  227. package/node_modules/ajv/dist/vocabularies/dynamic/dynamicAnchor.d.ts +5 -0
  228. package/node_modules/ajv/dist/vocabularies/dynamic/dynamicAnchor.js +30 -0
  229. package/node_modules/ajv/dist/vocabularies/dynamic/dynamicAnchor.js.map +1 -0
  230. package/node_modules/ajv/dist/vocabularies/dynamic/dynamicRef.d.ts +5 -0
  231. package/node_modules/ajv/dist/vocabularies/dynamic/dynamicRef.js +51 -0
  232. package/node_modules/ajv/dist/vocabularies/dynamic/dynamicRef.js.map +1 -0
  233. package/node_modules/ajv/dist/vocabularies/dynamic/index.d.ts +3 -0
  234. package/node_modules/ajv/dist/vocabularies/dynamic/index.js +9 -0
  235. package/node_modules/ajv/dist/vocabularies/dynamic/index.js.map +1 -0
  236. package/node_modules/ajv/dist/vocabularies/dynamic/recursiveAnchor.d.ts +3 -0
  237. package/node_modules/ajv/dist/vocabularies/dynamic/recursiveAnchor.js +16 -0
  238. package/node_modules/ajv/dist/vocabularies/dynamic/recursiveAnchor.js.map +1 -0
  239. package/node_modules/ajv/dist/vocabularies/dynamic/recursiveRef.d.ts +3 -0
  240. package/node_modules/ajv/dist/vocabularies/dynamic/recursiveRef.js +10 -0
  241. package/node_modules/ajv/dist/vocabularies/dynamic/recursiveRef.js.map +1 -0
  242. package/node_modules/ajv/dist/vocabularies/errors.d.ts +9 -0
  243. package/node_modules/ajv/dist/vocabularies/errors.js +3 -0
  244. package/node_modules/ajv/dist/vocabularies/errors.js.map +1 -0
  245. package/node_modules/ajv/dist/vocabularies/format/format.d.ts +8 -0
  246. package/node_modules/ajv/dist/vocabularies/format/format.js +92 -0
  247. package/node_modules/ajv/dist/vocabularies/format/format.js.map +1 -0
  248. package/node_modules/ajv/dist/vocabularies/format/index.d.ts +3 -0
  249. package/node_modules/ajv/dist/vocabularies/format/index.js +6 -0
  250. package/node_modules/ajv/dist/vocabularies/format/index.js.map +1 -0
  251. package/node_modules/ajv/dist/vocabularies/jtd/discriminator.d.ts +6 -0
  252. package/node_modules/ajv/dist/vocabularies/jtd/discriminator.js +71 -0
  253. package/node_modules/ajv/dist/vocabularies/jtd/discriminator.js.map +1 -0
  254. package/node_modules/ajv/dist/vocabularies/jtd/elements.d.ts +5 -0
  255. package/node_modules/ajv/dist/vocabularies/jtd/elements.js +24 -0
  256. package/node_modules/ajv/dist/vocabularies/jtd/elements.js.map +1 -0
  257. package/node_modules/ajv/dist/vocabularies/jtd/enum.d.ts +6 -0
  258. package/node_modules/ajv/dist/vocabularies/jtd/enum.js +43 -0
  259. package/node_modules/ajv/dist/vocabularies/jtd/enum.js.map +1 -0
  260. package/node_modules/ajv/dist/vocabularies/jtd/error.d.ts +9 -0
  261. package/node_modules/ajv/dist/vocabularies/jtd/error.js +20 -0
  262. package/node_modules/ajv/dist/vocabularies/jtd/error.js.map +1 -0
  263. package/node_modules/ajv/dist/vocabularies/jtd/index.d.ts +10 -0
  264. package/node_modules/ajv/dist/vocabularies/jtd/index.js +29 -0
  265. package/node_modules/ajv/dist/vocabularies/jtd/index.js.map +1 -0
  266. package/node_modules/ajv/dist/vocabularies/jtd/metadata.d.ts +5 -0
  267. package/node_modules/ajv/dist/vocabularies/jtd/metadata.js +25 -0
  268. package/node_modules/ajv/dist/vocabularies/jtd/metadata.js.map +1 -0
  269. package/node_modules/ajv/dist/vocabularies/jtd/nullable.d.ts +4 -0
  270. package/node_modules/ajv/dist/vocabularies/jtd/nullable.js +22 -0
  271. package/node_modules/ajv/dist/vocabularies/jtd/nullable.js.map +1 -0
  272. package/node_modules/ajv/dist/vocabularies/jtd/optionalProperties.d.ts +3 -0
  273. package/node_modules/ajv/dist/vocabularies/jtd/optionalProperties.js +15 -0
  274. package/node_modules/ajv/dist/vocabularies/jtd/optionalProperties.js.map +1 -0
  275. package/node_modules/ajv/dist/vocabularies/jtd/properties.d.ts +22 -0
  276. package/node_modules/ajv/dist/vocabularies/jtd/properties.js +149 -0
  277. package/node_modules/ajv/dist/vocabularies/jtd/properties.js.map +1 -0
  278. package/node_modules/ajv/dist/vocabularies/jtd/ref.d.ts +4 -0
  279. package/node_modules/ajv/dist/vocabularies/jtd/ref.js +67 -0
  280. package/node_modules/ajv/dist/vocabularies/jtd/ref.js.map +1 -0
  281. package/node_modules/ajv/dist/vocabularies/jtd/type.d.ts +10 -0
  282. package/node_modules/ajv/dist/vocabularies/jtd/type.js +69 -0
  283. package/node_modules/ajv/dist/vocabularies/jtd/type.js.map +1 -0
  284. package/node_modules/ajv/dist/vocabularies/jtd/union.d.ts +3 -0
  285. package/node_modules/ajv/dist/vocabularies/jtd/union.js +12 -0
  286. package/node_modules/ajv/dist/vocabularies/jtd/union.js.map +1 -0
  287. package/node_modules/ajv/dist/vocabularies/jtd/values.d.ts +5 -0
  288. package/node_modules/ajv/dist/vocabularies/jtd/values.js +51 -0
  289. package/node_modules/ajv/dist/vocabularies/jtd/values.js.map +1 -0
  290. package/node_modules/ajv/dist/vocabularies/metadata.d.ts +3 -0
  291. package/node_modules/ajv/dist/vocabularies/metadata.js +18 -0
  292. package/node_modules/ajv/dist/vocabularies/metadata.js.map +1 -0
  293. package/node_modules/ajv/dist/vocabularies/next.d.ts +3 -0
  294. package/node_modules/ajv/dist/vocabularies/next.js +8 -0
  295. package/node_modules/ajv/dist/vocabularies/next.js.map +1 -0
  296. package/node_modules/ajv/dist/vocabularies/unevaluated/index.d.ts +3 -0
  297. package/node_modules/ajv/dist/vocabularies/unevaluated/index.js +7 -0
  298. package/node_modules/ajv/dist/vocabularies/unevaluated/index.js.map +1 -0
  299. package/node_modules/ajv/dist/vocabularies/unevaluated/unevaluatedItems.d.ts +6 -0
  300. package/node_modules/ajv/dist/vocabularies/unevaluated/unevaluatedItems.js +40 -0
  301. package/node_modules/ajv/dist/vocabularies/unevaluated/unevaluatedItems.js.map +1 -0
  302. package/node_modules/ajv/dist/vocabularies/unevaluated/unevaluatedProperties.d.ts +6 -0
  303. package/node_modules/ajv/dist/vocabularies/unevaluated/unevaluatedProperties.js +65 -0
  304. package/node_modules/ajv/dist/vocabularies/unevaluated/unevaluatedProperties.js.map +1 -0
  305. package/node_modules/ajv/dist/vocabularies/validation/const.d.ts +6 -0
  306. package/node_modules/ajv/dist/vocabularies/validation/const.js +25 -0
  307. package/node_modules/ajv/dist/vocabularies/validation/const.js.map +1 -0
  308. package/node_modules/ajv/dist/vocabularies/validation/dependentRequired.d.ts +5 -0
  309. package/node_modules/ajv/dist/vocabularies/validation/dependentRequired.js +12 -0
  310. package/node_modules/ajv/dist/vocabularies/validation/dependentRequired.js.map +1 -0
  311. package/node_modules/ajv/dist/vocabularies/validation/enum.d.ts +8 -0
  312. package/node_modules/ajv/dist/vocabularies/validation/enum.js +48 -0
  313. package/node_modules/ajv/dist/vocabularies/validation/enum.js.map +1 -0
  314. package/node_modules/ajv/dist/vocabularies/validation/index.d.ts +16 -0
  315. package/node_modules/ajv/dist/vocabularies/validation/index.js +33 -0
  316. package/node_modules/ajv/dist/vocabularies/validation/index.js.map +1 -0
  317. package/node_modules/ajv/dist/vocabularies/validation/limitContains.d.ts +3 -0
  318. package/node_modules/ajv/dist/vocabularies/validation/limitContains.js +15 -0
  319. package/node_modules/ajv/dist/vocabularies/validation/limitContains.js.map +1 -0
  320. package/node_modules/ajv/dist/vocabularies/validation/limitItems.d.ts +3 -0
  321. package/node_modules/ajv/dist/vocabularies/validation/limitItems.js +24 -0
  322. package/node_modules/ajv/dist/vocabularies/validation/limitItems.js.map +1 -0
  323. package/node_modules/ajv/dist/vocabularies/validation/limitLength.d.ts +3 -0
  324. package/node_modules/ajv/dist/vocabularies/validation/limitLength.js +27 -0
  325. package/node_modules/ajv/dist/vocabularies/validation/limitLength.js.map +1 -0
  326. package/node_modules/ajv/dist/vocabularies/validation/limitNumber.d.ts +11 -0
  327. package/node_modules/ajv/dist/vocabularies/validation/limitNumber.js +27 -0
  328. package/node_modules/ajv/dist/vocabularies/validation/limitNumber.js.map +1 -0
  329. package/node_modules/ajv/dist/vocabularies/validation/limitProperties.d.ts +3 -0
  330. package/node_modules/ajv/dist/vocabularies/validation/limitProperties.js +24 -0
  331. package/node_modules/ajv/dist/vocabularies/validation/limitProperties.js.map +1 -0
  332. package/node_modules/ajv/dist/vocabularies/validation/multipleOf.d.ts +8 -0
  333. package/node_modules/ajv/dist/vocabularies/validation/multipleOf.js +26 -0
  334. package/node_modules/ajv/dist/vocabularies/validation/multipleOf.js.map +1 -0
  335. package/node_modules/ajv/dist/vocabularies/validation/pattern.d.ts +8 -0
  336. package/node_modules/ajv/dist/vocabularies/validation/pattern.js +33 -0
  337. package/node_modules/ajv/dist/vocabularies/validation/pattern.js.map +1 -0
  338. package/node_modules/ajv/dist/vocabularies/validation/required.d.ts +8 -0
  339. package/node_modules/ajv/dist/vocabularies/validation/required.js +79 -0
  340. package/node_modules/ajv/dist/vocabularies/validation/required.js.map +1 -0
  341. package/node_modules/ajv/dist/vocabularies/validation/uniqueItems.d.ts +9 -0
  342. package/node_modules/ajv/dist/vocabularies/validation/uniqueItems.js +64 -0
  343. package/node_modules/ajv/dist/vocabularies/validation/uniqueItems.js.map +1 -0
  344. package/node_modules/ajv/lib/2019.ts +81 -0
  345. package/node_modules/ajv/lib/2020.ts +75 -0
  346. package/node_modules/ajv/lib/ajv.ts +70 -0
  347. package/node_modules/ajv/lib/compile/codegen/code.ts +169 -0
  348. package/node_modules/ajv/lib/compile/codegen/index.ts +852 -0
  349. package/node_modules/ajv/lib/compile/codegen/scope.ts +215 -0
  350. package/node_modules/ajv/lib/compile/errors.ts +184 -0
  351. package/node_modules/ajv/lib/compile/index.ts +324 -0
  352. package/node_modules/ajv/lib/compile/jtd/parse.ts +411 -0
  353. package/node_modules/ajv/lib/compile/jtd/serialize.ts +277 -0
  354. package/node_modules/ajv/lib/compile/jtd/types.ts +16 -0
  355. package/node_modules/ajv/lib/compile/names.ts +27 -0
  356. package/node_modules/ajv/lib/compile/ref_error.ts +13 -0
  357. package/node_modules/ajv/lib/compile/resolve.ts +149 -0
  358. package/node_modules/ajv/lib/compile/rules.ts +50 -0
  359. package/node_modules/ajv/lib/compile/util.ts +213 -0
  360. package/node_modules/ajv/lib/compile/validate/applicability.ts +22 -0
  361. package/node_modules/ajv/lib/compile/validate/boolSchema.ts +47 -0
  362. package/node_modules/ajv/lib/compile/validate/dataType.ts +230 -0
  363. package/node_modules/ajv/lib/compile/validate/defaults.ts +32 -0
  364. package/node_modules/ajv/lib/compile/validate/index.ts +582 -0
  365. package/node_modules/ajv/lib/compile/validate/keyword.ts +171 -0
  366. package/node_modules/ajv/lib/compile/validate/subschema.ts +135 -0
  367. package/node_modules/ajv/lib/core.ts +892 -0
  368. package/node_modules/ajv/lib/jtd.ts +132 -0
  369. package/node_modules/ajv/lib/refs/data.json +13 -0
  370. package/node_modules/ajv/lib/refs/json-schema-2019-09/index.ts +28 -0
  371. package/node_modules/ajv/lib/refs/json-schema-2019-09/meta/applicator.json +53 -0
  372. package/node_modules/ajv/lib/refs/json-schema-2019-09/meta/content.json +17 -0
  373. package/node_modules/ajv/lib/refs/json-schema-2019-09/meta/core.json +57 -0
  374. package/node_modules/ajv/lib/refs/json-schema-2019-09/meta/format.json +14 -0
  375. package/node_modules/ajv/lib/refs/json-schema-2019-09/meta/meta-data.json +37 -0
  376. package/node_modules/ajv/lib/refs/json-schema-2019-09/meta/validation.json +90 -0
  377. package/node_modules/ajv/lib/refs/json-schema-2019-09/schema.json +39 -0
  378. package/node_modules/ajv/lib/refs/json-schema-2020-12/index.ts +30 -0
  379. package/node_modules/ajv/lib/refs/json-schema-2020-12/meta/applicator.json +48 -0
  380. package/node_modules/ajv/lib/refs/json-schema-2020-12/meta/content.json +17 -0
  381. package/node_modules/ajv/lib/refs/json-schema-2020-12/meta/core.json +51 -0
  382. package/node_modules/ajv/lib/refs/json-schema-2020-12/meta/format-annotation.json +14 -0
  383. package/node_modules/ajv/lib/refs/json-schema-2020-12/meta/meta-data.json +37 -0
  384. package/node_modules/ajv/lib/refs/json-schema-2020-12/meta/unevaluated.json +15 -0
  385. package/node_modules/ajv/lib/refs/json-schema-2020-12/meta/validation.json +90 -0
  386. package/node_modules/ajv/lib/refs/json-schema-2020-12/schema.json +55 -0
  387. package/node_modules/ajv/lib/refs/json-schema-draft-06.json +137 -0
  388. package/node_modules/ajv/lib/refs/json-schema-draft-07.json +151 -0
  389. package/node_modules/ajv/lib/refs/json-schema-secure.json +88 -0
  390. package/node_modules/ajv/lib/refs/jtd-schema.ts +130 -0
  391. package/node_modules/ajv/lib/runtime/equal.ts +7 -0
  392. package/node_modules/ajv/lib/runtime/parseJson.ts +177 -0
  393. package/node_modules/ajv/lib/runtime/quote.ts +31 -0
  394. package/node_modules/ajv/lib/runtime/re2.ts +6 -0
  395. package/node_modules/ajv/lib/runtime/timestamp.ts +46 -0
  396. package/node_modules/ajv/lib/runtime/ucs2length.ts +20 -0
  397. package/node_modules/ajv/lib/runtime/uri.ts +6 -0
  398. package/node_modules/ajv/lib/runtime/validation_error.ts +13 -0
  399. package/node_modules/ajv/lib/standalone/index.ts +100 -0
  400. package/node_modules/ajv/lib/standalone/instance.ts +36 -0
  401. package/node_modules/ajv/lib/types/index.ts +244 -0
  402. package/node_modules/ajv/lib/types/json-schema.ts +187 -0
  403. package/node_modules/ajv/lib/types/jtd-schema.ts +273 -0
  404. package/node_modules/ajv/lib/vocabularies/applicator/additionalItems.ts +56 -0
  405. package/node_modules/ajv/lib/vocabularies/applicator/additionalProperties.ts +118 -0
  406. package/node_modules/ajv/lib/vocabularies/applicator/allOf.ts +22 -0
  407. package/node_modules/ajv/lib/vocabularies/applicator/anyOf.ts +14 -0
  408. package/node_modules/ajv/lib/vocabularies/applicator/contains.ts +109 -0
  409. package/node_modules/ajv/lib/vocabularies/applicator/dependencies.ts +112 -0
  410. package/node_modules/ajv/lib/vocabularies/applicator/dependentSchemas.ts +11 -0
  411. package/node_modules/ajv/lib/vocabularies/applicator/if.ts +80 -0
  412. package/node_modules/ajv/lib/vocabularies/applicator/index.ts +53 -0
  413. package/node_modules/ajv/lib/vocabularies/applicator/items.ts +59 -0
  414. package/node_modules/ajv/lib/vocabularies/applicator/items2020.ts +36 -0
  415. package/node_modules/ajv/lib/vocabularies/applicator/not.ts +38 -0
  416. package/node_modules/ajv/lib/vocabularies/applicator/oneOf.ts +82 -0
  417. package/node_modules/ajv/lib/vocabularies/applicator/patternProperties.ts +91 -0
  418. package/node_modules/ajv/lib/vocabularies/applicator/prefixItems.ts +12 -0
  419. package/node_modules/ajv/lib/vocabularies/applicator/properties.ts +57 -0
  420. package/node_modules/ajv/lib/vocabularies/applicator/propertyNames.ts +50 -0
  421. package/node_modules/ajv/lib/vocabularies/applicator/thenElse.ts +13 -0
  422. package/node_modules/ajv/lib/vocabularies/code.ts +168 -0
  423. package/node_modules/ajv/lib/vocabularies/core/id.ts +10 -0
  424. package/node_modules/ajv/lib/vocabularies/core/index.ts +16 -0
  425. package/node_modules/ajv/lib/vocabularies/core/ref.ts +129 -0
  426. package/node_modules/ajv/lib/vocabularies/discriminator/index.ts +113 -0
  427. package/node_modules/ajv/lib/vocabularies/discriminator/types.ts +12 -0
  428. package/node_modules/ajv/lib/vocabularies/draft2020.ts +23 -0
  429. package/node_modules/ajv/lib/vocabularies/draft7.ts +17 -0
  430. package/node_modules/ajv/lib/vocabularies/dynamic/dynamicAnchor.ts +31 -0
  431. package/node_modules/ajv/lib/vocabularies/dynamic/dynamicRef.ts +51 -0
  432. package/node_modules/ajv/lib/vocabularies/dynamic/index.ts +9 -0
  433. package/node_modules/ajv/lib/vocabularies/dynamic/recursiveAnchor.ts +14 -0
  434. package/node_modules/ajv/lib/vocabularies/dynamic/recursiveRef.ts +10 -0
  435. package/node_modules/ajv/lib/vocabularies/errors.ts +18 -0
  436. package/node_modules/ajv/lib/vocabularies/format/format.ts +120 -0
  437. package/node_modules/ajv/lib/vocabularies/format/index.ts +6 -0
  438. package/node_modules/ajv/lib/vocabularies/jtd/discriminator.ts +89 -0
  439. package/node_modules/ajv/lib/vocabularies/jtd/elements.ts +32 -0
  440. package/node_modules/ajv/lib/vocabularies/jtd/enum.ts +45 -0
  441. package/node_modules/ajv/lib/vocabularies/jtd/error.ts +23 -0
  442. package/node_modules/ajv/lib/vocabularies/jtd/index.ts +37 -0
  443. package/node_modules/ajv/lib/vocabularies/jtd/metadata.ts +24 -0
  444. package/node_modules/ajv/lib/vocabularies/jtd/nullable.ts +21 -0
  445. package/node_modules/ajv/lib/vocabularies/jtd/optionalProperties.ts +15 -0
  446. package/node_modules/ajv/lib/vocabularies/jtd/properties.ts +184 -0
  447. package/node_modules/ajv/lib/vocabularies/jtd/ref.ts +76 -0
  448. package/node_modules/ajv/lib/vocabularies/jtd/type.ts +75 -0
  449. package/node_modules/ajv/lib/vocabularies/jtd/union.ts +12 -0
  450. package/node_modules/ajv/lib/vocabularies/jtd/values.ts +58 -0
  451. package/node_modules/ajv/lib/vocabularies/metadata.ts +17 -0
  452. package/node_modules/ajv/lib/vocabularies/next.ts +8 -0
  453. package/node_modules/ajv/lib/vocabularies/unevaluated/index.ts +7 -0
  454. package/node_modules/ajv/lib/vocabularies/unevaluated/unevaluatedItems.ts +47 -0
  455. package/node_modules/ajv/lib/vocabularies/unevaluated/unevaluatedProperties.ts +85 -0
  456. package/node_modules/ajv/lib/vocabularies/validation/const.ts +28 -0
  457. package/node_modules/ajv/lib/vocabularies/validation/dependentRequired.ts +23 -0
  458. package/node_modules/ajv/lib/vocabularies/validation/enum.ts +54 -0
  459. package/node_modules/ajv/lib/vocabularies/validation/index.ts +49 -0
  460. package/node_modules/ajv/lib/vocabularies/validation/limitContains.ts +16 -0
  461. package/node_modules/ajv/lib/vocabularies/validation/limitItems.ts +26 -0
  462. package/node_modules/ajv/lib/vocabularies/validation/limitLength.ts +30 -0
  463. package/node_modules/ajv/lib/vocabularies/validation/limitNumber.ts +42 -0
  464. package/node_modules/ajv/lib/vocabularies/validation/limitProperties.ts +26 -0
  465. package/node_modules/ajv/lib/vocabularies/validation/multipleOf.ts +34 -0
  466. package/node_modules/ajv/lib/vocabularies/validation/pattern.ts +39 -0
  467. package/node_modules/ajv/lib/vocabularies/validation/required.ts +98 -0
  468. package/node_modules/ajv/lib/vocabularies/validation/uniqueItems.ts +79 -0
  469. package/node_modules/ajv/package.json +126 -0
  470. package/node_modules/fast-deep-equal/LICENSE +21 -0
  471. package/node_modules/fast-deep-equal/README.md +96 -0
  472. package/node_modules/fast-deep-equal/es6/index.d.ts +2 -0
  473. package/node_modules/fast-deep-equal/es6/index.js +72 -0
  474. package/node_modules/fast-deep-equal/es6/react.d.ts +2 -0
  475. package/node_modules/fast-deep-equal/es6/react.js +79 -0
  476. package/node_modules/fast-deep-equal/index.d.ts +4 -0
  477. package/node_modules/fast-deep-equal/index.js +46 -0
  478. package/node_modules/fast-deep-equal/package.json +61 -0
  479. package/node_modules/fast-deep-equal/react.d.ts +2 -0
  480. package/node_modules/fast-deep-equal/react.js +53 -0
  481. package/node_modules/fast-uri/.gitattributes +2 -0
  482. package/node_modules/fast-uri/.github/dependabot.yml +13 -0
  483. package/node_modules/fast-uri/.github/workflows/ci.yml +106 -0
  484. package/node_modules/fast-uri/.github/workflows/lock-threads.yml +19 -0
  485. package/node_modules/fast-uri/.github/workflows/package-manager-ci.yml +24 -0
  486. package/node_modules/fast-uri/LICENSE +30 -0
  487. package/node_modules/fast-uri/README.md +152 -0
  488. package/node_modules/fast-uri/benchmark/benchmark.mjs +159 -0
  489. package/node_modules/fast-uri/benchmark/equal.mjs +51 -0
  490. package/node_modules/fast-uri/benchmark/non-simple-domain.mjs +22 -0
  491. package/node_modules/fast-uri/benchmark/package.json +17 -0
  492. package/node_modules/fast-uri/benchmark/string-array-to-hex-stripped.mjs +24 -0
  493. package/node_modules/fast-uri/benchmark/ws-is-secure.mjs +65 -0
  494. package/node_modules/fast-uri/eslint.config.js +6 -0
  495. package/node_modules/fast-uri/index.js +627 -0
  496. package/node_modules/fast-uri/lib/schemes.js +272 -0
  497. package/node_modules/fast-uri/lib/utils.js +747 -0
  498. package/node_modules/fast-uri/package.json +68 -0
  499. package/node_modules/fast-uri/test/ajv.test.js +43 -0
  500. package/node_modules/fast-uri/test/component-safe-serialization.test.js +163 -0
  501. package/node_modules/fast-uri/test/equal.test.js +145 -0
  502. package/node_modules/fast-uri/test/fixtures/uri-js-parse.json +503 -0
  503. package/node_modules/fast-uri/test/fixtures/uri-js-serialize.json +120 -0
  504. package/node_modules/fast-uri/test/ipv6-canonical.test.js +34 -0
  505. package/node_modules/fast-uri/test/ipv6-validation.test.js +124 -0
  506. package/node_modules/fast-uri/test/malformed-percent.test.js +77 -0
  507. package/node_modules/fast-uri/test/malformed-urn.test.js +61 -0
  508. package/node_modules/fast-uri/test/parse.test.js +327 -0
  509. package/node_modules/fast-uri/test/query-fragment-normalization.test.js +33 -0
  510. package/node_modules/fast-uri/test/reserved-path-normalization.test.js +109 -0
  511. package/node_modules/fast-uri/test/resolve.test.js +87 -0
  512. package/node_modules/fast-uri/test/rfc-3986.test.js +90 -0
  513. package/node_modules/fast-uri/test/scheme-validation.test.js +124 -0
  514. package/node_modules/fast-uri/test/security-normalization.test.js +140 -0
  515. package/node_modules/fast-uri/test/security.test.js +431 -0
  516. package/node_modules/fast-uri/test/serialize.test.js +151 -0
  517. package/node_modules/fast-uri/test/uri-js-compatibility.test.js +33 -0
  518. package/node_modules/fast-uri/test/uri-js.test.js +912 -0
  519. package/node_modules/fast-uri/test/urn-full-input.test.js +29 -0
  520. package/node_modules/fast-uri/test/util.test.js +38 -0
  521. package/node_modules/fast-uri/test/websocket-query-preservation.test.js +24 -0
  522. package/node_modules/fast-uri/tsconfig.json +9 -0
  523. package/node_modules/fast-uri/types/index.d.ts +60 -0
  524. package/node_modules/fast-uri/types/index.test-d.ts +17 -0
  525. package/node_modules/json-schema-traverse/.eslintrc.yml +27 -0
  526. package/node_modules/json-schema-traverse/.github/FUNDING.yml +2 -0
  527. package/node_modules/json-schema-traverse/.github/workflows/build.yml +28 -0
  528. package/node_modules/json-schema-traverse/.github/workflows/publish.yml +27 -0
  529. package/node_modules/json-schema-traverse/LICENSE +21 -0
  530. package/node_modules/json-schema-traverse/README.md +95 -0
  531. package/node_modules/json-schema-traverse/index.d.ts +40 -0
  532. package/node_modules/json-schema-traverse/index.js +93 -0
  533. package/node_modules/json-schema-traverse/package.json +43 -0
  534. package/node_modules/json-schema-traverse/spec/.eslintrc.yml +6 -0
  535. package/node_modules/json-schema-traverse/spec/fixtures/schema.js +125 -0
  536. package/node_modules/json-schema-traverse/spec/index.spec.js +171 -0
  537. package/node_modules/require-from-string/index.js +34 -0
  538. package/node_modules/require-from-string/license +21 -0
  539. package/node_modules/require-from-string/package.json +28 -0
  540. package/node_modules/require-from-string/readme.md +56 -0
  541. package/package.json +33 -4
  542. package/packages/pcr-core/schemas/agent-review.schema.json +69 -0
  543. package/packages/pcr-core/schemas/classification-coverage.schema.json +187 -0
  544. package/packages/pcr-core/schemas/controlled-vocabulary.schema.json +189 -0
  545. package/packages/pcr-core/schemas/dataset-validation-input.schema.json +7 -0
  546. package/packages/pcr-core/schemas/feedback-draft-output.schema.json +12 -0
  547. package/packages/pcr-core/schemas/feedback.schema.json +27 -0
  548. package/packages/pcr-core/schemas/guidance-output.schema.json +97 -0
  549. package/packages/pcr-core/schemas/model-validation-input.schema.json +10 -0
  550. package/packages/pcr-core/schemas/pcr-id-aliases.schema.json +120 -0
  551. package/packages/pcr-core/schemas/readiness.schema.json +100 -0
  552. package/packages/pcr-core/schemas/structured-projection.schema.json +269 -0
  553. package/packages/pcr-core/schemas/validation-output.schema.json +117 -0
  554. package/packages/pcr-core/src/classification-coverage.mjs +732 -0
  555. package/packages/pcr-core/src/consumption-calculation.mjs +53 -0
  556. package/packages/pcr-core/src/consumption-data.mjs +88 -0
  557. package/packages/pcr-core/src/consumption-guidance.mjs +62 -0
  558. package/packages/pcr-core/src/consumption-review.mjs +83 -0
  559. package/packages/pcr-core/src/contracts.mjs +195 -0
  560. package/packages/pcr-core/src/generated/controlled-vocabulary.mjs +41 -0
  561. package/packages/pcr-core/src/index.mjs +2101 -0
  562. package/packages/pcr-core/src/languages.mjs +86 -0
  563. package/packages/pcr-core/src/offline-library.mjs +121 -0
  564. package/packages/pcr-core/src/output-semantics.mjs +228 -0
  565. package/packages/pcr-core/src/pcr-id-aliases.mjs +949 -0
  566. package/packages/pcr-core/src/projection-completeness.mjs +284 -0
  567. package/packages/pcr-core/src/projection-integrity.mjs +208 -0
  568. package/packages/pcr-core/src/read-context.mjs +505 -0
  569. package/packages/pcr-core/src/schema-validation.mjs +142 -0
  570. package/packages/pcr-core/src/source-context.mjs +13 -0
  571. package/packages/pcr-core/src/tidas-inspection.mjs +177 -0
  572. package/packages/pcr-core/src/yaml-lite.mjs +261 -0
  573. package/packages/tiangong-pcr-cli/bin/tiangong-pcr.mjs +12 -0
  574. package/packages/tiangong-pcr-cli/src/commands.mjs +1691 -0
  575. package/skills/tiangong-pcr/SKILL.md +90 -0
  576. package/skills/tiangong-pcr/references/cli-usage.md +66 -0
  577. package/skills/tiangong-pcr/references/feedback-loop.md +16 -0
  578. package/skills/tiangong-pcr/references/lca-authoring.md +30 -0
  579. package/skills/tiangong-pcr/references/model-authoring-loop.md +6 -0
  580. package/skills/tiangong-pcr/references/reviewing-tidas.md +71 -0
  581. package/skills/tiangong-pcr/references/tidas-authoring.md +45 -0
@@ -0,0 +1,2101 @@
1
+ import { pcrSource } from "./source-context.mjs";
2
+ import { createHash } from "node:crypto";
3
+ import {
4
+ closeSync,
5
+ constants as fsConstants,
6
+ fstatSync,
7
+ lstatSync,
8
+ openSync,
9
+ readFileSync,
10
+ realpathSync,
11
+ readdirSync,
12
+ } from "node:fs";
13
+ import path from "node:path";
14
+ import { TextDecoder } from "node:util";
15
+
16
+ import {
17
+ PcrClassificationCodeUnknownError,
18
+ PcrClassificationCoverageSemanticError,
19
+ readClassificationCoverage,
20
+ readClassificationCoverageSnapshot,
21
+ } from "./classification-coverage.mjs";
22
+ import { assertCoreContract, validateCoreContract } from "./contracts.mjs";
23
+ import {
24
+ inspectProjectionIntegrity,
25
+ projectionNotRequiredState,
26
+ } from "./projection-integrity.mjs";
27
+ import {
28
+ hasDeclaredUnresolvedReferenceProductFlow,
29
+ materialProjectionCompletenessIssues,
30
+ } from "./projection-completeness.mjs";
31
+ import { findPcrIdAlias as findRepositoryPcrIdAlias } from "./pcr-id-aliases.mjs";
32
+ import {
33
+ assertPcrReadContextFresh,
34
+ createPcrReadContext,
35
+ getPcrReadContextCatalog,
36
+ observePcrReadContextArtifactRead,
37
+ pcrReadContextAliasInputFingerprint,
38
+ withPcrReadContextSession,
39
+ } from "./read-context.mjs";
40
+ import { parseYaml } from "./yaml-lite.mjs";
41
+ import {
42
+ declaredPcrLanguages,
43
+ expectedPcrArtifactHashes,
44
+ LEGACY_PCR_ARTIFACT_HASH_FIELDS,
45
+ pcrArtifactFiles,
46
+ } from "./languages.mjs";
47
+ import {
48
+ CLASSIFICATION_MAPPING_RELATION_VALUES,
49
+ CONTENT_MATURITY_VALUES,
50
+ FEEDBACK_TYPE_VALUES,
51
+ PCR_STATUS_VALUES,
52
+ } from "./generated/controlled-vocabulary.mjs";
53
+
54
+ export const FEEDBACK_TYPES = FEEDBACK_TYPE_VALUES;
55
+ export { createPcrReadContext, pcrReadContextAliasInputFingerprint, withPcrReadContextSession };
56
+ export {
57
+ CLASSIFICATION_COVERAGE_STATUSES,
58
+ PcrClassificationCodeUnknownError,
59
+ PcrClassificationCoverageNotFoundError,
60
+ PcrClassificationCoverageSemanticError,
61
+ PcrClassificationCoverageStatusError,
62
+ classificationCoveragePath,
63
+ findClassificationCoverageEntry,
64
+ getClassificationCoverageSummary,
65
+ hasClassificationCoverage,
66
+ listClassificationCoverage,
67
+ readClassificationCoverage,
68
+ readClassificationCoverageSnapshot,
69
+ } from "./classification-coverage.mjs";
70
+ export const PCR_CATALOG_SCOPES = Object.freeze(["all", "material", "legacy"]);
71
+ export const PCR_RECORD_KINDS = Object.freeze([
72
+ "methodology",
73
+ "legacy_scaffold_reference",
74
+ "invalid_lifecycle_state",
75
+ ]);
76
+ const CLASSIFICATION_MAPPING_RELATIONS = new Set(CLASSIFICATION_MAPPING_RELATION_VALUES);
77
+ const PCR_CATALOG_SCOPE_SET = new Set(PCR_CATALOG_SCOPES);
78
+ const METHODOLOGY_LIFECYCLE_STATUSES = new Set(
79
+ PCR_STATUS_VALUES.filter((value) => value !== "scaffold"),
80
+ );
81
+ const METHODOLOGY_MATURITIES = new Set(
82
+ CONTENT_MATURITY_VALUES.filter((value) => value !== "empty_scaffold"),
83
+ );
84
+
85
+ const CURRENT_SNAPSHOT_MAX_ATTEMPTS = 3;
86
+ const pcrCatalogCache = new Map();
87
+ const RELEASE_ARTIFACTS = LEGACY_PCR_ARTIFACT_HASH_FIELDS;
88
+ const GUIDANCE_MATURITIES = new Set([
89
+ "authored_methodology",
90
+ "reviewed_methodology",
91
+ "published_methodology",
92
+ ]);
93
+ const REVIEWED_MATURITIES = new Set(["reviewed_methodology", "published_methodology"]);
94
+ const USABLE_LIFECYCLE_STATES = new Map([
95
+ ["candidate", new Set(["authored_methodology"])],
96
+ ["active", new Set(["reviewed_methodology"])],
97
+ ["published", new Set(["published_methodology"])],
98
+ ]);
99
+ const GUIDANCE_LIFECYCLE_STATUSES = new Set(["candidate", "active", "published"]);
100
+
101
+ export class PcrUsabilityError extends Error {
102
+ constructor({ pcrId, operation, readiness }) {
103
+ const blockers = readiness.blockers.map((blocker) => blocker.code).join(", ");
104
+ super(
105
+ `PCR ${pcrId} is not usable for ${operation}: content_maturity=${readiness.methodology_status}; blockers=${blockers || "unknown"}`,
106
+ );
107
+ this.name = "PcrUsabilityError";
108
+ this.code = `PCR_NOT_USABLE_FOR_${operation.toUpperCase()}`;
109
+ this.readiness = structuredClone(readiness);
110
+ }
111
+ }
112
+
113
+ export class PcrClassificationMappingError extends Error {
114
+ constructor({ system, version, code, mappingType, issue = null }) {
115
+ super(issue
116
+ ? `Classification mapping ${system}:${version}:${code} is not an accepted current mapping: ${issue}.`
117
+ : `Classification mapping ${system}:${version}:${code} uses unsupported mapping_type ${String(mappingType)}.`);
118
+ this.name = "PcrClassificationMappingError";
119
+ this.code = "PCR_INVALID_CLASSIFICATION_MAPPING";
120
+ this.details = {
121
+ classification: `${system}:${version}:${code}`,
122
+ mapping_type: mappingType ?? null,
123
+ allowed_mapping_types: [...CLASSIFICATION_MAPPING_RELATION_VALUES],
124
+ issue,
125
+ };
126
+ }
127
+ }
128
+
129
+ export class PcrLegacyIdRedirectError extends Error {
130
+ constructor(alias) {
131
+ const redirect = legacyPcrIdRedirect(alias);
132
+ super(
133
+ `PCR id ${redirect.source_pcr_id} is a retired legacy identity. ` +
134
+ `Use the redirect target with: ${redirect.next_command}`,
135
+ );
136
+ this.name = "PcrLegacyIdRedirectError";
137
+ this.code = "PCR_LEGACY_ID_REDIRECT";
138
+ this.details = redirect;
139
+ }
140
+ }
141
+
142
+ export class PcrClassificationTargetStateError extends Error {
143
+ constructor({ system, version, code, pcr }) {
144
+ super(
145
+ `Classification mapping ${system}:${version}:${code} points to PCR ${pcr.id} with invalid ` +
146
+ `lifecycle identity ${pcr.status}/${pcr.content_maturity}.`,
147
+ );
148
+ this.name = "PcrClassificationTargetStateError";
149
+ this.code = "PCR_INVALID_CLASSIFICATION_TARGET";
150
+ this.details = {
151
+ classification: `${system}:${version}:${code}`,
152
+ pcr_id: pcr.id,
153
+ status: pcr.status,
154
+ content_maturity: pcr.content_maturity,
155
+ record_kind: pcr.record_kind,
156
+ };
157
+ }
158
+ }
159
+
160
+ export class PcrCurrentSnapshotInconsistentError extends Error {
161
+ constructor({ pcrId, pcrPath, attempts, lastFailure }) {
162
+ super(
163
+ `PCR ${pcrId} current snapshot could not be read consistently after ${attempts} attempts.`,
164
+ );
165
+ this.name = "PcrCurrentSnapshotInconsistentError";
166
+ this.code = "PCR_CURRENT_SNAPSHOT_INCONSISTENT";
167
+ this.details = {
168
+ pcr_id: pcrId,
169
+ pcr_path: pcrPath,
170
+ attempts,
171
+ last_failure: lastFailure,
172
+ };
173
+ }
174
+ }
175
+
176
+ export class PcrDuplicateIdError extends Error {
177
+ constructor({ pcrId, paths }) {
178
+ super(`Duplicate canonical PCR id ${pcrId}: ${paths.join(", ")}`);
179
+ this.name = "PcrDuplicateIdError";
180
+ this.code = "PCR_DUPLICATE_ID";
181
+ this.details = { pcr_id: pcrId, paths: [...paths] };
182
+ }
183
+ }
184
+
185
+ export class PcrCatalogScopeError extends Error {
186
+ constructor(scope) {
187
+ super(`Unsupported PCR catalog scope ${String(scope)}. Expected one of: ${PCR_CATALOG_SCOPES.join(", ")}.`);
188
+ this.name = "PcrCatalogScopeError";
189
+ this.code = "PCR_INVALID_CATALOG_SCOPE";
190
+ this.details = {
191
+ scope: String(scope),
192
+ allowed_scopes: [...PCR_CATALOG_SCOPES],
193
+ };
194
+ }
195
+ }
196
+
197
+ function findPcrIdAlias(options) {
198
+ const source = pcrSource(options.root);
199
+ return source ? source.findAlias(options.pcrId) : findRepositoryPcrIdAlias(options);
200
+ }
201
+
202
+ export function listPcrs({ root, refresh = false, scope = "all" }) {
203
+ if (pcrSource(root)) return pcrSource(root).listPcrs(normalizeCatalogScope(scope));
204
+ const normalizedScope = normalizeCatalogScope(scope);
205
+ const normalizedRoot = path.resolve(root);
206
+ const catalog = getPcrCatalog({ root: normalizedRoot, refresh });
207
+ const candidates = normalizedScope === "all"
208
+ ? catalog
209
+ : catalog.filter((entry) => currentCatalogEntryMatchesScope(normalizedRoot, entry, normalizedScope));
210
+ return candidates
211
+ .map((entry) => currentPcrEntry(normalizedRoot, entry))
212
+ .filter((entry) => recordMatchesScope(entry, normalizedScope));
213
+ }
214
+
215
+ function getPcrCatalog({ root, refresh = false }) {
216
+ const normalizedRoot = path.resolve(root);
217
+ if (refresh || !pcrCatalogCache.has(normalizedRoot)) {
218
+ pcrCatalogCache.set(normalizedRoot, readPcrCatalog(normalizedRoot));
219
+ }
220
+ return pcrCatalogCache.get(normalizedRoot);
221
+ }
222
+
223
+ function readPcrCatalog(root) {
224
+ const pcrRoot = path.join(root, "library/pcrs");
225
+ if (!isCanonicalDirectory(pcrRoot)) {
226
+ throw new Error(`PCR catalog root not found: ${toPosix(path.relative(root, pcrRoot))}`);
227
+ }
228
+ const catalog = findManifestFiles(pcrRoot)
229
+ .map((manifestPath) => {
230
+ const manifest = parseYaml(readCanonicalFileBytes(manifestPath).toString("utf8"));
231
+ const pcrDir = path.dirname(manifestPath);
232
+ return {
233
+ id: manifest.id,
234
+ path: toPosix(path.relative(root, pcrDir)),
235
+ manifestPath,
236
+ };
237
+ })
238
+ .filter((entry) => entry.id);
239
+ const entriesById = new Map();
240
+ for (const entry of catalog) {
241
+ const existing = entriesById.get(entry.id);
242
+ if (existing) {
243
+ throw new PcrDuplicateIdError({
244
+ pcrId: entry.id,
245
+ paths: [existing.path, entry.path].sort(),
246
+ });
247
+ }
248
+ entriesById.set(entry.id, entry);
249
+ }
250
+ return catalog.sort((left, right) => left.id.localeCompare(right.id));
251
+ }
252
+
253
+ export function buildPcrTree({ root, depth = Infinity, scope = "all" }) {
254
+ const tree = {};
255
+ for (const pcr of listPcrs({ root, scope })) {
256
+ const segments = pcr.path.replace(/^library\/pcrs\//u, "").split("/");
257
+ let node = tree;
258
+ for (const [index, segment] of segments.entries()) {
259
+ if (index >= depth) {
260
+ break;
261
+ }
262
+ node[segment] ??= { children: {}, pcrs: [] };
263
+ if (index === segments.length - 1) {
264
+ node[segment].pcrs.push(pcr);
265
+ }
266
+ node = node[segment].children;
267
+ }
268
+ }
269
+ return tree;
270
+ }
271
+
272
+ export function resolveClassification({ root, system, version, code, context = null }) {
273
+ const normalizedSystem = String(system).toLowerCase();
274
+ const normalizedVersion = String(version);
275
+ const normalizedCode = String(code);
276
+ const coverageIndex = readClassificationCoverage({
277
+ root,
278
+ system: normalizedSystem,
279
+ version: normalizedVersion,
280
+ });
281
+ return resolveClassificationWithCoverage({
282
+ root,
283
+ system: normalizedSystem,
284
+ version: normalizedVersion,
285
+ code: normalizedCode,
286
+ coverageIndex,
287
+ context,
288
+ });
289
+ }
290
+
291
+ export function verifyDistributionCoverage({ root, snapshot, context }) {
292
+ const coverageIndex = snapshot.document;
293
+ for (const entry of coverageIndex.entries) {
294
+ if (entry.coverage_status === "mapped" || entry.legacy_reference) {
295
+ resolveClassificationWithCoverage({ root, system: String(coverageIndex.classification_system).toLowerCase(),
296
+ version: String(coverageIndex.classification_version), code: String(entry.code), coverageIndex, context });
297
+ }
298
+ }
299
+ }
300
+
301
+ function resolveClassificationWithCoverage({ root, system, version, code, coverageIndex, context = null }) {
302
+ const coverage = coverageIndex.entries.find(
303
+ (candidate) => String(candidate.code) === String(code),
304
+ );
305
+ if (!coverage) {
306
+ throw new PcrClassificationCodeUnknownError({ system, version, code });
307
+ }
308
+ if (coverage.coverage_status === "mapped") {
309
+ const canonical = readCanonicalClassificationMapping({
310
+ root,
311
+ system,
312
+ version,
313
+ code,
314
+ });
315
+ assertCoverageMappingMatchesCanonical({ coverage, canonical, system, version, code });
316
+ const pcr = getPcrById({ root, pcrId: canonical.mapping.pcr_id, context });
317
+ if (pcr.record_kind !== "methodology") {
318
+ throw invalidCoverageResolution({
319
+ system,
320
+ version,
321
+ code,
322
+ issue: `mapped coverage points to non-material PCR ${pcr.id}`,
323
+ });
324
+ }
325
+ return {
326
+ classification_system: canonical.mappingFile.classification_system,
327
+ classification_version: canonical.mappingFile.classification_version,
328
+ mapping: canonical.mapping,
329
+ pcr,
330
+ resolution_status: "mapped",
331
+ coverage_status: coverage.coverage_status,
332
+ coverage,
333
+ };
334
+ }
335
+
336
+ if (coverage.legacy_reference) {
337
+ const canonical = readCanonicalClassificationMapping({
338
+ root,
339
+ system,
340
+ version,
341
+ code,
342
+ });
343
+ if (canonical.mapping.pcr_id !== coverage.legacy_reference.pcr_id) {
344
+ throw invalidCoverageResolution({
345
+ system,
346
+ version,
347
+ code,
348
+ issue: `legacy reference ${coverage.legacy_reference.pcr_id} does not match canonical mapping ${canonical.mapping.pcr_id}`,
349
+ });
350
+ }
351
+ const pcr = getPcrById({ root, pcrId: canonical.mapping.pcr_id, context });
352
+ if (pcr.record_kind !== "legacy_scaffold_reference") {
353
+ throw invalidCoverageResolution({
354
+ system,
355
+ version,
356
+ code,
357
+ issue: `legacy reference points to material PCR ${pcr.id}`,
358
+ });
359
+ }
360
+ return {
361
+ classification_system: canonical.mappingFile.classification_system,
362
+ classification_version: canonical.mappingFile.classification_version,
363
+ mapping: canonical.mapping,
364
+ pcr,
365
+ resolution_status: "legacy_scaffold_compatibility",
366
+ coverage_status: coverage.coverage_status,
367
+ coverage,
368
+ };
369
+ }
370
+
371
+ return {
372
+ classification_system: String(coverageIndex.classification_system),
373
+ classification_version: String(coverageIndex.classification_version),
374
+ mapping: null,
375
+ pcr: null,
376
+ resolution_status: "unmapped",
377
+ coverage_status: coverage.coverage_status,
378
+ coverage,
379
+ review_candidate:
380
+ ["manual_review", "unknown"].includes(coverage.coverage_status) && coverage.mapping
381
+ ? structuredClone(coverage.mapping)
382
+ : null,
383
+ };
384
+ }
385
+
386
+ function readCanonicalClassificationMapping({ root, system, version, code }) {
387
+ const normalizedRoot = path.resolve(root);
388
+ const mappingPath = path.join(
389
+ normalizedRoot,
390
+ "classifications/mappings",
391
+ `${system}-${version}-to-pcr.yaml`,
392
+ );
393
+ const mappingRelativePath = toPosix(path.relative(normalizedRoot, mappingPath));
394
+ let mappingFile;
395
+ try {
396
+ const mappingBytes = pcrSource(root)?.readFile(mappingRelativePath) ?? readControlledRepositoryFileBytes({
397
+ root: normalizedRoot,
398
+ filePath: mappingPath,
399
+ relativePath: mappingRelativePath,
400
+ label: "classification mapping",
401
+ });
402
+ mappingFile = parseYaml(new TextDecoder("utf-8", { fatal: true }).decode(mappingBytes));
403
+ } catch (error) {
404
+ if (error instanceof PcrClassificationMappingError) {
405
+ throw error;
406
+ }
407
+ throw new PcrClassificationMappingError({
408
+ system,
409
+ version,
410
+ code,
411
+ issue:
412
+ `canonical mapping source ${mappingRelativePath} could not be read safely ` +
413
+ `(${error instanceof Error ? error.message : String(error)})`,
414
+ });
415
+ }
416
+ assertCurrentAcceptedMappingDocument({ mappingFile, system, version, code });
417
+ const matches = (mappingFile.mappings ?? []).filter(
418
+ (entry) => String(entry.code) === String(code),
419
+ );
420
+ if (matches.length === 0) {
421
+ throw new Error(`No PCR mapping found for ${system}:${version}:${code}`);
422
+ }
423
+ if (matches.length !== 1) {
424
+ throw new PcrClassificationMappingError({
425
+ system,
426
+ version,
427
+ code,
428
+ issue: `expected one selected edge, found ${matches.length}`,
429
+ });
430
+ }
431
+ const mapping = matches[0];
432
+ if (
433
+ !CLASSIFICATION_MAPPING_RELATIONS.has(mapping.mapping_type)
434
+ || mapping.mapping_type === "manual_review"
435
+ ) {
436
+ throw new PcrClassificationMappingError({
437
+ system,
438
+ version,
439
+ code,
440
+ mappingType: mapping.mapping_type,
441
+ });
442
+ }
443
+ assertAcceptedMappingDecision({ mapping, system, version, code });
444
+ return { mappingFile, mapping };
445
+ }
446
+
447
+ function assertCurrentAcceptedMappingDocument({ mappingFile, system, version, code }) {
448
+ if (mappingFile?.schema_version !== 2 || mappingFile?.status !== "current") {
449
+ throw new PcrClassificationMappingError({
450
+ system,
451
+ version,
452
+ code,
453
+ issue:
454
+ `expected schema_version 2 with status current, found ` +
455
+ `${String(mappingFile?.schema_version)}/${String(mappingFile?.status)}`,
456
+ });
457
+ }
458
+ if (
459
+ String(mappingFile.classification_system).toLowerCase() !== String(system).toLowerCase()
460
+ || String(mappingFile.classification_version) !== String(version)
461
+ || !Array.isArray(mappingFile.mappings)
462
+ ) {
463
+ throw new PcrClassificationMappingError({
464
+ system,
465
+ version,
466
+ code,
467
+ issue: "mapping document coordinate or mappings array does not match the requested classification",
468
+ });
469
+ }
470
+ }
471
+
472
+ function assertAcceptedMappingDecision({ mapping, system, version, code }) {
473
+ const acceptance = mapping?.acceptance;
474
+ if (
475
+ acceptance?.status !== "accepted"
476
+ || typeof acceptance?.decided_by !== "string"
477
+ || acceptance.decided_by.trim().length === 0
478
+ || !isRealCanonicalUtcTimestamp(acceptance?.decided_at_utc)
479
+ || typeof acceptance?.decision_ref !== "string"
480
+ || !/^(?:docs|classifications\/migrations)\/[A-Za-z0-9][A-Za-z0-9._/-]*\.(?:md|ya?ml|json)(?:#[A-Za-z0-9][A-Za-z0-9._-]*)?$/u.test(
481
+ acceptance.decision_ref,
482
+ )
483
+ ) {
484
+ throw new PcrClassificationMappingError({
485
+ system,
486
+ version,
487
+ code,
488
+ mappingType: mapping?.mapping_type,
489
+ issue:
490
+ "selected edge requires acceptance.status=accepted, decided_by, strict decided_at_utc, and decision_ref",
491
+ });
492
+ }
493
+ }
494
+
495
+ function isRealCanonicalUtcTimestamp(value) {
496
+ const match = typeof value === "string"
497
+ ? /^([0-9]{4})-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])T([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])(?:\.[0-9]+)?Z$/u.exec(value)
498
+ : null;
499
+ if (!match) {
500
+ return false;
501
+ }
502
+ const [, year, month, day, hour, minute, second] = match.map(Number);
503
+ const parsed = new Date(0);
504
+ parsed.setUTCFullYear(year, month - 1, day);
505
+ parsed.setUTCHours(hour, minute, second, 0);
506
+ return (
507
+ parsed.getUTCFullYear() === year
508
+ && parsed.getUTCMonth() === month - 1
509
+ && parsed.getUTCDate() === day
510
+ && parsed.getUTCHours() === hour
511
+ && parsed.getUTCMinutes() === minute
512
+ && parsed.getUTCSeconds() === second
513
+ );
514
+ }
515
+
516
+ function assertCoverageMappingMatchesCanonical({ coverage, canonical, system, version, code }) {
517
+ const coverageMapping = coverage.mapping;
518
+ const canonicalMapping = canonical.mapping;
519
+ for (const field of ["pcr_id", "mapping_type", "confidence"]) {
520
+ if (String(coverageMapping?.[field]) !== String(canonicalMapping?.[field])) {
521
+ throw invalidCoverageResolution({
522
+ system,
523
+ version,
524
+ code,
525
+ issue: `coverage mapping ${field} ${String(coverageMapping?.[field])} does not match canonical mapping ${String(canonicalMapping?.[field])}`,
526
+ });
527
+ }
528
+ }
529
+ for (const field of ["status", "decided_by", "decided_at_utc", "decision_ref"]) {
530
+ if (
531
+ String(coverageMapping?.acceptance?.[field])
532
+ !== String(canonicalMapping?.acceptance?.[field])
533
+ ) {
534
+ throw invalidCoverageResolution({
535
+ system,
536
+ version,
537
+ code,
538
+ issue:
539
+ `coverage mapping acceptance.${field} ${String(coverageMapping?.acceptance?.[field])} ` +
540
+ `does not match canonical mapping ${String(canonicalMapping?.acceptance?.[field])}`,
541
+ });
542
+ }
543
+ }
544
+ }
545
+
546
+ function invalidCoverageResolution({ system, version, code, issue }) {
547
+ return new PcrClassificationCoverageSemanticError({
548
+ system,
549
+ version,
550
+ source: `classifications/indexes/${system}-${version}-coverage.json`,
551
+ issues: [`entry ${code}: ${issue}`],
552
+ });
553
+ }
554
+
555
+ /**
556
+ * Resolve a PCR identity without silently following a retired id. Alias
557
+ * lookup intentionally happens before catalog lookup, including while the
558
+ * old scaffold directory still exists during a staged migration.
559
+ */
560
+ export function resolvePcrIdentity({ root, pcrId, context = null }) {
561
+ const readRoot = root ?? context?.root;
562
+ const normalizedPcrId = String(pcrId);
563
+ const alias = findPcrIdAlias({ root: readRoot, pcrId: normalizedPcrId, context });
564
+ if (alias) {
565
+ return {
566
+ resolution_status: "legacy_id_redirect",
567
+ requested_pcr_id: normalizedPcrId,
568
+ redirect: legacyPcrIdRedirect(alias),
569
+ pcr: null,
570
+ };
571
+ }
572
+ return {
573
+ resolution_status: "canonical",
574
+ requested_pcr_id: normalizedPcrId,
575
+ redirect: null,
576
+ pcr: getCurrentPcrSnapshotUnchecked({ root: readRoot, pcrId: normalizedPcrId, context }).pcr,
577
+ };
578
+ }
579
+
580
+ function legacyPcrIdRedirect(alias) {
581
+ return {
582
+ source_pcr_id: alias.source_pcr_id,
583
+ source_pcr_path: alias.source_pcr_path,
584
+ target: structuredClone(alias.target),
585
+ reason: alias.reason,
586
+ decision_ref: alias.decision_ref,
587
+ next_command: nextCommandForLegacyPcrAlias(alias.target),
588
+ };
589
+ }
590
+
591
+ function nextCommandForLegacyPcrAlias(target) {
592
+ if (target.kind === "classification_coverage") {
593
+ return (
594
+ "npm --silent run tiangong-pcr -- resolve --classification " +
595
+ `${target.classification_system}:${target.classification_version}:${target.code} --format json`
596
+ );
597
+ }
598
+ return (
599
+ "npm --silent run tiangong-pcr -- resolve --pcr " +
600
+ `${target.pcr_id} --format json`
601
+ );
602
+ }
603
+
604
+ function throwIfLegacyPcrId({ root, pcrId, context = null }) {
605
+ const alias = findPcrIdAlias({ root, pcrId: String(pcrId), context });
606
+ if (alias) {
607
+ throw new PcrLegacyIdRedirectError(alias);
608
+ }
609
+ }
610
+
611
+ export function getPcrById({ root, pcrId, refresh = false, context = null }) {
612
+ return getCurrentPcrSnapshot({ root: root ?? context?.root, pcrId, refresh, context }).pcr;
613
+ }
614
+
615
+ export function getPcrReadiness({ root, pcrId, refresh = false, context = null }) {
616
+ return structuredClone(getPcrById({ root: root ?? context?.root, pcrId, refresh, context }).readiness);
617
+ }
618
+
619
+ export function readPcrMarkdown({ root, pcrId, language = "en-US", context = null }) {
620
+ const readRoot = root ?? context?.root;
621
+ const snapshot = getCurrentPcrSnapshot({ root: readRoot, pcrId, context });
622
+ if (pcrSource(readRoot) && !pcrSource(readRoot).languages.includes(language)) {
623
+ throw Object.assign(new Error(`Offline library contains English only; requested ${language}. Use --lang en-US.`), { code: "PCR_LIBRARY_LANGUAGE_UNAVAILABLE" });
624
+ }
625
+ const markdownName = `pcr.${language}.md`;
626
+ const markdownPath = path.join(readRoot, snapshot.pcr.path, markdownName);
627
+ const artifact = snapshot.artifacts[markdownName];
628
+ if (!artifact?.bytes) {
629
+ throw new Error(`PCR Markdown not found: ${toPosix(path.relative(readRoot, markdownPath))}`);
630
+ }
631
+ return artifact.bytes.toString("utf8");
632
+ }
633
+
634
+ /** A complete current document, read once through the same integrity boundary as guidance. */
635
+ export function readPcrDocumentBundle({ root, pcrId, context = null }) {
636
+ root = root ?? context?.root;
637
+ const snapshot = getCurrentPcrSnapshot({ root, pcrId, context });
638
+ const { pcr, manifest, manifestBytes, structured } = snapshot;
639
+ assertPcrUsable({ pcr, operation: "guidance" });
640
+ const languages = pcrSource(root)?.languages ?? declaredPcrLanguages(manifest);
641
+ if (![1, 2].includes(manifest.schema_version)) throw new Error(`Unsupported document manifest schema: ${manifest.schema_version}`);
642
+ for (const language of languages) if (typeof manifest.title?.[language] !== "string" || !manifest.title[language].trim()) throw new Error(`Document requires a nonempty ${language} title.`);
643
+ const artifacts = {};
644
+ const decoder = new TextDecoder("utf-8", { fatal: true });
645
+ for (const name of ["manifest.yaml", ...(pcrSource(root) ? [...languages.map((language) => `pcr.${language}.md`), "structured.yaml"] : pcrArtifactFiles(manifest))]) {
646
+ const bytes = name === "manifest.yaml" ? manifestBytes : snapshot.artifacts[name]?.bytes;
647
+ if (!bytes) throw new Error(`PCR document artifact is unavailable: ${pcr.path}/${name}`);
648
+ // A copy prevents consumers from changing a cached snapshot through Buffer aliasing.
649
+ const copy = Buffer.from(bytes);
650
+ const text = decoder.decode(copy);
651
+ if (!text.trim()) throw new Error(`PCR document artifact is empty: ${pcr.path}/${name}`);
652
+ artifacts[name] = {
653
+ path: `${pcr.path}/${name}`,
654
+ bytes: copy,
655
+ text,
656
+ sha256: exactByteSha256(copy),
657
+ };
658
+ }
659
+ return {
660
+ schema_version: 1,
661
+ workspace: "current",
662
+ pcr: structuredClone(pcr),
663
+ manifest: structuredClone(manifest),
664
+ structured: structuredClone(structured),
665
+ languages,
666
+ artifacts,
667
+ };
668
+ }
669
+
670
+ /** Complete referenced legacy module source; scaffold status remains explicit. */
671
+ export function readPcrModuleDocumentBundle({ root, group, moduleId }) {
672
+ for (const value of [group, moduleId]) if (typeof value !== "string" || !/^[a-z0-9]+(?:-[a-z0-9]+)*$/u.test(value)) throw new Error("Invalid PCR module identity.");
673
+ const relativePath = `library/modules/${group}/${moduleId}.md`;
674
+ const filePath = path.join(root, relativePath);
675
+ const read = () => pcrSource(root)?.readFile(relativePath) ?? readControlledRepositoryFileBytes({ root, filePath, relativePath, label: "PCR module" });
676
+ const bytes = read();
677
+ const text = new TextDecoder("utf-8", { fatal: true }).decode(bytes);
678
+ const envelope = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/u.exec(text);
679
+ if (!envelope) throw new Error(`Module requires frontmatter: ${relativePath}`);
680
+ const frontmatter = parseYaml(envelope[1]);
681
+ if (frontmatter.id !== `module.${group}.${moduleId}` || frontmatter.module_type !== group) throw new Error(`Module identity mismatch: ${relativePath}`);
682
+ if (!text.slice(envelope[0].length).trim()) throw new Error(`Module body is empty: ${relativePath}`);
683
+ if (!bytes.equals(read())) throw new Error(`Module changed during read: ${relativePath}`);
684
+ return { frontmatter, language: frontmatter.language ?? "en-US", artifact: { path: relativePath, bytes: Buffer.from(bytes), text, sha256: exactByteSha256(bytes) } };
685
+ }
686
+
687
+ export function buildGuidance({ root, pcrId, context = null }) {
688
+ return buildGuidanceForOperation({ root: root ?? context?.root, pcrId, operation: "guidance", context });
689
+ }
690
+
691
+ export function getVerifiedPcrProjection({ root, pcrId, context = null }) {
692
+ root = root ?? context?.root;
693
+ const snapshot = getCurrentPcrSnapshot({ root, pcrId, context });
694
+ const { pcr, structured, structuredPath } = snapshot;
695
+ assertPcrUsable({ pcr, operation: "guidance" });
696
+ if (!structured) {
697
+ throw new Error(
698
+ `PCR ${pcrId} passed readiness without a verified structured projection.`,
699
+ );
700
+ }
701
+ return {
702
+ pcr: structuredClone(pcr),
703
+ readiness: structuredClone(pcr.readiness),
704
+ source_structured: toPosix(path.relative(root, structuredPath)),
705
+ structured: structuredClone(structured),
706
+ };
707
+ }
708
+
709
+ function buildGuidanceForOperation({ root, pcrId, operation, context = null }) {
710
+ const snapshot = getCurrentPcrSnapshot({ root, pcrId, context });
711
+ const { pcr, structured, structuredPath } = snapshot;
712
+ assertPcrUsable({ pcr, operation });
713
+ if (!structured) {
714
+ throw new Error(
715
+ `PCR ${pcrId} passed readiness without a verified structured projection.`,
716
+ );
717
+ }
718
+ const guidance = {
719
+ schema_version: 1,
720
+ guidance_kind: "tiangong-pcr-agent-guidance",
721
+ pcr,
722
+ readiness: structuredClone(pcr.readiness),
723
+ source_structured: toPosix(path.relative(root, structuredPath)),
724
+ system_boundary: structured.system_boundary ?? {},
725
+ reference_flow: structured.reference_flow_definition ?? {},
726
+ boundary_abstraction: structured.boundary_abstraction ?? {},
727
+ measurement_rules: structured.measurement_rules ?? structured.unit_conventions ?? [],
728
+ process_map: structured.process_map ?? [],
729
+ process_inventory: structured.process_inventory ?? [],
730
+ production_guidance: {
731
+ collection_protocols: structured.dataset_production?.collection_protocols ?? [],
732
+ calculation_rules: structured.dataset_production?.calculation_rules ?? [],
733
+ data_quality_requirements: structured.dataset_production?.data_quality_requirements ?? [],
734
+ },
735
+ published_dataset_profile: structured.published_dataset_profile ?? {},
736
+ allocation_rules: structured.allocation_rules ?? [],
737
+ data_quality_rules: structured.data_quality_rules ?? [],
738
+ validation_rules: structured.validation_rules ?? [],
739
+ data_sources: structured.data_sources ?? [],
740
+ validation_notes: [
741
+ "Use this guidance for LCA data authoring, optional TIDAS process authoring, or Agent-led review of existing process/model data. Select requirements for the declared scope.",
742
+ "Preserve PCR-derived UUID identities exactly. They are version-free suggestions; preserve and verify explicit versions on supplied TIDAS dataset references.",
743
+ "validate-model checks qualifier text presence; validate-dataset checks collection protocol ID presence. Neither performs TIDAS schema validation or semantic review. Use inspect and review prepare/check to support Agent-led review; a foreground package is optional.",
744
+ ],
745
+ };
746
+ assertCoreContract("guidance-output.schema.json", guidance, {
747
+ code: "PCR_INTERNAL_CONTRACT_INVALID",
748
+ entityKind: "Agent guidance output",
749
+ source: toPosix(path.relative(root, structuredPath)),
750
+ });
751
+ return guidance;
752
+ }
753
+
754
+ export function createFeedbackDraft({
755
+ root,
756
+ pcrId,
757
+ type,
758
+ affectedSection = "",
759
+ processId = "",
760
+ flowRole = "",
761
+ summary = "",
762
+ evidence = "",
763
+ proposedChange = "",
764
+ agent = "tiangong-pcr",
765
+ }) {
766
+ if (!FEEDBACK_TYPES.includes(type)) {
767
+ throw new Error(`Unsupported feedback type: ${type}`);
768
+ }
769
+ const pcr = pcrId ? getPcrById({ root, pcrId }) : null;
770
+ const title = `PCR feedback: ${type}${pcrId ? ` for ${pcrId}` : ""}`;
771
+ const body = `## Summary
772
+
773
+ ${summary || "Describe the PCR issue or improvement."}
774
+
775
+ ## Feedback metadata
776
+
777
+ | Field | Value |
778
+ | --- | --- |
779
+ | PCR id | ${pcrId || ""} |
780
+ | PCR version | ${pcr?.version ?? ""} |
781
+ | Feedback type | ${type} |
782
+ | Affected section | ${affectedSection} |
783
+ | Affected process_id | ${processId} |
784
+ | Affected flow role | ${flowRole} |
785
+ | Generated by | ${agent} |
786
+
787
+ ## Current PCR text or rule excerpt
788
+
789
+
790
+ ## Proposed change
791
+
792
+ ${proposedChange}
793
+
794
+ ## Evidence sources
795
+
796
+ ${evidence}
797
+
798
+ ## Impact on foreground data package construction
799
+
800
+
801
+ ## Maintainer intake checklist
802
+
803
+ - [ ] Classify the feedback as PCR content, classification mapping, UUID identity, translation, source evidence, or CLI/validator behavior.
804
+ - [ ] Verify cited evidence and Tiangong UUID references before changing PCR content.
805
+ - [ ] Update canonical \`pcr.en-US.md\` first when methodology changes.
806
+ - [ ] Align \`pcr.zh-CN.md\` when user-facing text changes.
807
+ - [ ] Run \`npm run pcr:sync-structured -- --pcr <library/pcrs/...>\` when canonical Markdown changes.
808
+ - [ ] Bump or publish the PCR manifest if lifecycle state changes.
809
+ `;
810
+
811
+ const draft = { title, body };
812
+ assertCoreContract("feedback-draft-output.schema.json", draft, {
813
+ code: "PCR_INTERNAL_CONTRACT_INVALID",
814
+ entityKind: "PCR feedback issue draft output",
815
+ });
816
+ return draft;
817
+ }
818
+
819
+ export function validateModelAgainstGuidance({ root, pcrId, model }) {
820
+ const guidance = buildGuidanceForOperation({ root, pcrId, operation: "validation" });
821
+ const findings = [];
822
+ const accepted = validateCoreContract("model-validation-input.schema.json", model).valid;
823
+ const text = typeof model === "string" ? model : accepted ? JSON.stringify(model) : "";
824
+ const checksPerformed = [];
825
+ const checksSkipped = [];
826
+
827
+ if (!accepted) {
828
+ findings.push({
829
+ severity: "error",
830
+ code: "invalid_model_input",
831
+ message: "Model input must be text or a JSON object.",
832
+ });
833
+ }
834
+
835
+ const requiredQualifiers = asArray(guidance.reference_flow.required_qualifiers);
836
+ if (accepted && requiredQualifiers.length > 0) {
837
+ checksPerformed.push(performedCheck(
838
+ "required_qualifier_presence",
839
+ "reference_flow.required_qualifiers",
840
+ requiredQualifiers.length,
841
+ ));
842
+ for (const qualifier of requiredQualifiers) {
843
+ if (!text.toLowerCase().includes(String(qualifier).toLowerCase())) {
844
+ findings.push({
845
+ severity: "warning",
846
+ code: "missing_required_qualifier",
847
+ message: `Model text does not mention required qualifier: ${qualifier}`,
848
+ });
849
+ }
850
+ }
851
+ }
852
+
853
+ if (accepted) {
854
+ addSkippedCheck(
855
+ checksSkipped,
856
+ "system_boundary_rules",
857
+ "system_boundary.rules",
858
+ asArray(guidance.system_boundary?.rules).length,
859
+ );
860
+ addSkippedCheck(
861
+ checksSkipped,
862
+ "boundary_abstraction",
863
+ "boundary_abstraction",
864
+ topLevelRequirementCount(guidance.boundary_abstraction),
865
+ );
866
+ addSkippedCheck(
867
+ checksSkipped,
868
+ "reference_flow_definition",
869
+ "reference_flow",
870
+ topLevelRequirementCount(guidance.reference_flow, ["required_qualifiers"]),
871
+ );
872
+ addSkippedCheck(checksSkipped, "measurement_rules", "measurement_rules", asArray(guidance.measurement_rules).length);
873
+ addSkippedCheck(checksSkipped, "process_map", "process_map", asArray(guidance.process_map).length);
874
+ addSkippedCheck(checksSkipped, "process_inventory", "process_inventory", countInventoryRows(guidance.process_inventory));
875
+ addSkippedCheck(
876
+ checksSkipped,
877
+ "collection_protocols",
878
+ "production_guidance.collection_protocols",
879
+ asArray(guidance.production_guidance.collection_protocols).length,
880
+ );
881
+ addSkippedCheck(
882
+ checksSkipped,
883
+ "calculation_rules",
884
+ "production_guidance.calculation_rules",
885
+ asArray(guidance.production_guidance.calculation_rules).length,
886
+ );
887
+ addSkippedCheck(
888
+ checksSkipped,
889
+ "data_quality_requirements",
890
+ "production_guidance.data_quality_requirements",
891
+ asArray(guidance.production_guidance.data_quality_requirements).length,
892
+ );
893
+ addSkippedCheck(checksSkipped, "data_quality_rules", "data_quality_rules", asArray(guidance.data_quality_rules).length);
894
+ addSkippedCheck(checksSkipped, "allocation_rules", "allocation_rules", asArray(guidance.allocation_rules).length);
895
+ addSkippedCheck(checksSkipped, "validation_rules", "validation_rules", asArray(guidance.validation_rules).length);
896
+ addSkippedCheck(
897
+ checksSkipped,
898
+ "published_dataset_profile",
899
+ "published_dataset_profile",
900
+ topLevelRequirementCount(guidance.published_dataset_profile),
901
+ );
902
+ }
903
+
904
+ return buildValidationReport({
905
+ validationKind: "tiangong-pcr-model-validation",
906
+ guidance,
907
+ input: {
908
+ input_kind: "process_or_lifecyclemodel",
909
+ representation: typeof model === "string" ? "text" : Array.isArray(model) ? "array" : typeof model,
910
+ accepted,
911
+ },
912
+ findings,
913
+ checksPerformed,
914
+ checksSkipped,
915
+ });
916
+ }
917
+
918
+ export function validateDatasetAgainstGuidance({ root, pcrId, dataset }) {
919
+ const guidance = buildGuidanceForOperation({ root, pcrId, operation: "validation" });
920
+ const findings = [];
921
+ const accepted = validateCoreContract("dataset-validation-input.schema.json", dataset).valid;
922
+ const checksPerformed = [];
923
+ const checksSkipped = [];
924
+ const records = accepted ? collectionRecordArrays(dataset) : [];
925
+ const requiredProtocolIds = asArray(guidance.production_guidance.collection_protocols)
926
+ .map((protocol) => protocol.protocol_id)
927
+ .filter(Boolean);
928
+ const presentProtocolIds = accepted ? collectCollectionRecordProtocolIds(dataset) : new Set();
929
+
930
+ if (!accepted) {
931
+ findings.push({
932
+ severity: "error",
933
+ code: "invalid_dataset_input",
934
+ message: "Foreground data package input must be a JSON object.",
935
+ });
936
+ }
937
+
938
+ if (accepted && requiredProtocolIds.length > 0) {
939
+ checksPerformed.push(performedCheck(
940
+ "collection_protocol_presence",
941
+ "production_guidance.collection_protocols",
942
+ requiredProtocolIds.length,
943
+ ));
944
+ for (const protocolId of requiredProtocolIds) {
945
+ if (!presentProtocolIds.has(String(protocolId))) {
946
+ findings.push({
947
+ severity: "error",
948
+ code: "missing_collection_protocol_record",
949
+ message: `Foreground data package is missing collection record for protocol_id ${protocolId}`,
950
+ });
951
+ }
952
+ }
953
+ }
954
+
955
+ if (accepted) {
956
+ addSkippedCheck(
957
+ checksSkipped,
958
+ "system_boundary_rules",
959
+ "system_boundary.rules",
960
+ asArray(guidance.system_boundary?.rules).length,
961
+ );
962
+ addSkippedCheck(
963
+ checksSkipped,
964
+ "boundary_abstraction",
965
+ "boundary_abstraction",
966
+ topLevelRequirementCount(guidance.boundary_abstraction),
967
+ );
968
+ addSkippedCheck(
969
+ checksSkipped,
970
+ "reference_flow_rules",
971
+ "reference_flow",
972
+ topLevelRequirementCount(guidance.reference_flow, ["required_qualifiers"]) +
973
+ asArray(guidance.reference_flow?.required_qualifiers).length,
974
+ );
975
+ addSkippedCheck(checksSkipped, "measurement_rules", "measurement_rules", asArray(guidance.measurement_rules).length);
976
+ addSkippedCheck(checksSkipped, "process_map", "process_map", asArray(guidance.process_map).length);
977
+ addSkippedCheck(checksSkipped, "process_inventory", "process_inventory", countInventoryRows(guidance.process_inventory));
978
+ addSkippedCheck(
979
+ checksSkipped,
980
+ "calculation_rules",
981
+ "production_guidance.calculation_rules",
982
+ asArray(guidance.production_guidance.calculation_rules).length,
983
+ );
984
+ addSkippedCheck(
985
+ checksSkipped,
986
+ "data_quality_requirements",
987
+ "production_guidance.data_quality_requirements",
988
+ asArray(guidance.production_guidance.data_quality_requirements).length,
989
+ );
990
+ addSkippedCheck(checksSkipped, "data_quality_rules", "data_quality_rules", asArray(guidance.data_quality_rules).length);
991
+ addSkippedCheck(checksSkipped, "allocation_rules", "allocation_rules", asArray(guidance.allocation_rules).length);
992
+ addSkippedCheck(checksSkipped, "validation_rules", "validation_rules", asArray(guidance.validation_rules).length);
993
+ addSkippedCheck(
994
+ checksSkipped,
995
+ "published_dataset_profile",
996
+ "published_dataset_profile",
997
+ topLevelRequirementCount(guidance.published_dataset_profile),
998
+ );
999
+ }
1000
+
1001
+ return buildValidationReport({
1002
+ validationKind: "tiangong-pcr-dataset-validation",
1003
+ guidance,
1004
+ input: {
1005
+ input_kind: "foreground_data_package",
1006
+ representation: Array.isArray(dataset) ? "array" : dataset === null ? "null" : typeof dataset,
1007
+ accepted,
1008
+ collection_record_count: records.length,
1009
+ distinct_protocol_id_count: presentProtocolIds.size,
1010
+ },
1011
+ findings,
1012
+ checksPerformed,
1013
+ checksSkipped,
1014
+ });
1015
+ }
1016
+
1017
+ function collectCollectionRecordProtocolIds(dataset) {
1018
+ if (typeof dataset === "string") {
1019
+ return new Set();
1020
+ }
1021
+ const ids = new Set();
1022
+ for (const record of collectionRecordArrays(dataset)) {
1023
+ const protocolId = record?.protocol_id ?? record?.collection_protocol_id;
1024
+ if (protocolId) {
1025
+ ids.add(String(protocolId));
1026
+ }
1027
+ }
1028
+ return ids;
1029
+ }
1030
+
1031
+ function collectionRecordArrays(value) {
1032
+ if (!value || typeof value !== "object") {
1033
+ return [];
1034
+ }
1035
+ const records = [];
1036
+ for (const key of ["collection_records", "foreground_records", "measurement_records"]) {
1037
+ if (Array.isArray(value[key])) {
1038
+ records.push(...value[key]);
1039
+ }
1040
+ }
1041
+ if (value.data && typeof value.data === "object") {
1042
+ records.push(...collectionRecordArrays(value.data));
1043
+ }
1044
+ return records;
1045
+ }
1046
+
1047
+ function currentPcrEntry(root, entry) {
1048
+ return currentPcrSnapshot(root, entry).pcr;
1049
+ }
1050
+
1051
+ function getCurrentPcrSnapshot({ root, pcrId, refresh = false, context = null }) {
1052
+ throwIfLegacyPcrId({ root, pcrId, context });
1053
+ return getCurrentPcrSnapshotUnchecked({ root, pcrId, refresh, context });
1054
+ }
1055
+
1056
+ export function readPcrDistributionCatalog({ root }) {
1057
+ return readPcrCatalog(path.resolve(root));
1058
+ }
1059
+
1060
+ // Builder-only: preserves legacy catalog records without following alias redirects.
1061
+ export function readPcrDistributionSnapshot(options) {
1062
+ return getCurrentPcrSnapshotUnchecked(options);
1063
+ }
1064
+
1065
+ function getCurrentPcrSnapshotUnchecked({ root, pcrId, refresh = false, context = null }) {
1066
+ if (pcrSource(root)) {
1067
+ const entry = pcrSource(root).entry(pcrId);
1068
+ if (!entry) throw new Error(`PCR not found: ${pcrId}`);
1069
+ return currentPcrSnapshot(root, entry);
1070
+ }
1071
+ const normalizedRoot = path.resolve(root);
1072
+ if (context) {
1073
+ assertPcrReadContextFresh({ context, root: normalizedRoot });
1074
+ }
1075
+ const catalog = context
1076
+ ? getPcrReadContextCatalog({
1077
+ context,
1078
+ root: normalizedRoot,
1079
+ readCatalog: readPcrCatalog,
1080
+ })
1081
+ : getPcrCatalog({ root: normalizedRoot, refresh });
1082
+ const entry = context
1083
+ ? catalog.get(pcrId)
1084
+ : catalog.find((candidate) => candidate.id === pcrId);
1085
+ if (!entry) {
1086
+ throw new Error(`PCR not found: ${pcrId}`);
1087
+ }
1088
+ return currentPcrSnapshot(normalizedRoot, entry, context);
1089
+ }
1090
+
1091
+ function currentPcrSnapshot(root, entry, context = null) {
1092
+ const snapshotFiles = pcrSource(root)?.snapshotFiles(entry) ?? readConsistentSnapshotFiles({ root, entry, context });
1093
+ const pcr = pcrFromManifest({
1094
+ root,
1095
+ pcrDir: path.dirname(entry.manifestPath),
1096
+ manifest: snapshotFiles.manifest,
1097
+ });
1098
+ let projection;
1099
+ try {
1100
+ projection = inspectPcrProjection({
1101
+ root,
1102
+ pcr,
1103
+ manifest: snapshotFiles.manifest,
1104
+ artifacts: snapshotFiles.artifacts,
1105
+ });
1106
+ } catch (error) {
1107
+ projection = failedProjectionInspection({ root, pcr, error });
1108
+ }
1109
+ pcr.readiness = assessPcrReadiness({
1110
+ pcr,
1111
+ projectionFingerprint: projection.fingerprint,
1112
+ structuredAvailable: projection.structuredAvailable,
1113
+ projectionCompletenessIssues: projection.completenessIssues,
1114
+ });
1115
+ return {
1116
+ pcr,
1117
+ manifest: snapshotFiles.manifest,
1118
+ manifestBytes: snapshotFiles.manifestBytes,
1119
+ artifacts: snapshotFiles.artifacts,
1120
+ ...projection,
1121
+ };
1122
+ }
1123
+
1124
+ function readConsistentSnapshotFiles({ root, entry, context = null }) {
1125
+ let lastFailure = null;
1126
+ for (let attempt = 1; attempt <= CURRENT_SNAPSHOT_MAX_ATTEMPTS; attempt += 1) {
1127
+ try {
1128
+ const locationA = assertCurrentSnapshotLocation({ root, entry });
1129
+ const manifestABytes = readCanonicalFileBytes(locationA.manifestPath);
1130
+ const manifest = parseYaml(manifestABytes.toString("utf8"));
1131
+ if (manifest.id !== entry.id) {
1132
+ throw snapshotAttemptError(
1133
+ "manifest_identity_changed",
1134
+ `Expected PCR id ${entry.id}, found ${String(manifest.id)}.`,
1135
+ { expected_pcr_id: entry.id, actual_pcr_id: manifest.id ?? null },
1136
+ );
1137
+ }
1138
+
1139
+ const managedMarkersA = currentManagedStateMarkers(locationA.pcrDir);
1140
+ assertManagedSnapshotHashesDeclared({ manifest, managedMarkers: managedMarkersA });
1141
+ const artifacts = Object.fromEntries(
1142
+ pcrArtifactFiles(manifest, { strict: false }).map((filename) => [
1143
+ filename,
1144
+ readObservedPcrArtifact({ root, context, pcrDir: locationA.pcrDir, filename }),
1145
+ ]),
1146
+ );
1147
+ const releaseFailures = releaseArtifactFailures({ manifest, artifacts });
1148
+ const locationB = assertCurrentSnapshotLocation({ root, entry });
1149
+ const managedMarkersB = currentManagedStateMarkers(locationB.pcrDir);
1150
+ if (!sameStrings(managedMarkersA, managedMarkersB)) {
1151
+ throw snapshotAttemptError(
1152
+ "managed_state_changed_during_read",
1153
+ "PCR managed release state changed while its current snapshot was being read.",
1154
+ {
1155
+ managed_markers_before: managedMarkersA,
1156
+ managed_markers_after: managedMarkersB,
1157
+ },
1158
+ );
1159
+ }
1160
+ const manifestBBytes = readCanonicalFileBytes(locationB.manifestPath);
1161
+ if (!manifestABytes.equals(manifestBBytes)) {
1162
+ throw snapshotAttemptError(
1163
+ "manifest_changed_during_read",
1164
+ "manifest.yaml changed while its current artifacts were being read.",
1165
+ );
1166
+ }
1167
+ if (releaseFailures.length > 0) {
1168
+ throw snapshotAttemptError(
1169
+ "release_artifact_hash_mismatch",
1170
+ "Current PCR artifacts do not match manifest.release_artifacts.",
1171
+ { manifest_status: manifest.status ?? null, artifacts: releaseFailures },
1172
+ );
1173
+ }
1174
+ return { manifest, manifestBytes: manifestABytes, artifacts };
1175
+ } catch (error) {
1176
+ lastFailure = snapshotFailureDetails(error);
1177
+ }
1178
+ }
1179
+ throw new PcrCurrentSnapshotInconsistentError({
1180
+ pcrId: entry.id,
1181
+ pcrPath: entry.path,
1182
+ attempts: CURRENT_SNAPSHOT_MAX_ATTEMPTS,
1183
+ lastFailure,
1184
+ });
1185
+ }
1186
+
1187
+ function readObservedPcrArtifact({ root, context, pcrDir, filename }) {
1188
+ const artifactPath = path.join(pcrDir, filename);
1189
+ if (context) {
1190
+ observePcrReadContextArtifactRead({
1191
+ context,
1192
+ root,
1193
+ relativePath: toPosix(path.relative(root, artifactPath)),
1194
+ });
1195
+ }
1196
+ return readOptionalCanonicalFile(artifactPath);
1197
+ }
1198
+
1199
+ function releaseArtifactFailures({ manifest, artifacts }) {
1200
+ if (!Object.hasOwn(manifest, "release_artifacts")) {
1201
+ return [];
1202
+ }
1203
+ const expectedHashes = expectedPcrArtifactHashes(manifest);
1204
+ const failures = [];
1205
+ for (const [filename, expected] of Object.entries(expectedHashes)) {
1206
+ const hashField = manifest.schema_version === 2 && filename !== "structured.yaml"
1207
+ ? `markdown_sha256.${filename.slice(4, -3)}`
1208
+ : Object.entries(RELEASE_ARTIFACTS).find(([, file]) => file === filename)?.[0];
1209
+ const artifact = artifacts[filename];
1210
+ if (!artifact?.bytes) {
1211
+ failures.push({
1212
+ artifact: filename,
1213
+ hash_field: hashField,
1214
+ expected: typeof expected === "string" ? expected : null,
1215
+ actual: null,
1216
+ reason: `artifact_unreadable:${errorCode(artifact?.error)}`,
1217
+ });
1218
+ continue;
1219
+ }
1220
+ const actual = exactByteSha256(artifact.bytes);
1221
+ if (typeof expected !== "string" || expected !== actual) {
1222
+ failures.push({
1223
+ artifact: filename,
1224
+ hash_field: hashField,
1225
+ expected: typeof expected === "string" ? expected : null,
1226
+ actual,
1227
+ reason: "sha256_mismatch",
1228
+ });
1229
+ }
1230
+ }
1231
+ return failures;
1232
+ }
1233
+
1234
+ function assertManagedSnapshotHashesDeclared({ manifest, managedMarkers }) {
1235
+ if (managedMarkers.length === 0 || Object.hasOwn(manifest, "release_artifacts")) {
1236
+ return;
1237
+ }
1238
+ throw snapshotAttemptError(
1239
+ "managed_release_artifacts_missing",
1240
+ "Managed PCR current state requires manifest.release_artifacts and cannot use legacy snapshot semantics.",
1241
+ {
1242
+ manifest_status: manifest.status ?? null,
1243
+ managed_markers: managedMarkers,
1244
+ required_field: "manifest.release_artifacts",
1245
+ required_hash_fields: Object.keys(RELEASE_ARTIFACTS),
1246
+ },
1247
+ );
1248
+ }
1249
+
1250
+ function currentManagedStateMarkers(pcrDir) {
1251
+ return ["release-history.yaml", "releases"]
1252
+ .filter((name) => pathEntryExists(path.join(pcrDir, name)))
1253
+ .sort((left, right) => left.localeCompare(right));
1254
+ }
1255
+
1256
+ function pathEntryExists(targetPath) {
1257
+ try {
1258
+ lstatSync(targetPath);
1259
+ return true;
1260
+ } catch (error) {
1261
+ if (error?.code === "ENOENT") {
1262
+ return false;
1263
+ }
1264
+ throw error;
1265
+ }
1266
+ }
1267
+
1268
+ function sameStrings(left, right) {
1269
+ return left.length === right.length && left.every((value, index) => value === right[index]);
1270
+ }
1271
+
1272
+ function assertCurrentSnapshotLocation({ root, entry }) {
1273
+ const normalizedRoot = path.resolve(root);
1274
+ const pathSegments = String(entry.path).split("/");
1275
+ if (
1276
+ pathSegments.length !== 5 ||
1277
+ pathSegments[0] !== "library" ||
1278
+ pathSegments[1] !== "pcrs" ||
1279
+ pathSegments.slice(2).some((segment) => !segment || segment === "." || segment === "..")
1280
+ ) {
1281
+ throw snapshotAttemptError(
1282
+ "canonical_pcr_path_invalid",
1283
+ "Cached PCR path is not a canonical domain/subdomain/leaf path.",
1284
+ {
1285
+ pcr_path: entry.path,
1286
+ reason: "non_canonical_relative_path",
1287
+ },
1288
+ );
1289
+ }
1290
+
1291
+ const directoryPaths = [normalizedRoot];
1292
+ for (const segment of pathSegments) {
1293
+ directoryPaths.push(path.join(directoryPaths.at(-1), segment));
1294
+ }
1295
+
1296
+ let rootRealPath = null;
1297
+ for (const [index, directoryPath] of directoryPaths.entries()) {
1298
+ const relativePath = toPosix(path.relative(normalizedRoot, directoryPath)) || ".";
1299
+ let stat;
1300
+ try {
1301
+ stat = lstatSync(directoryPath);
1302
+ } catch (error) {
1303
+ throw snapshotAttemptError(
1304
+ "canonical_pcr_path_invalid",
1305
+ `Canonical PCR directory is unavailable: ${relativePath}.`,
1306
+ {
1307
+ path_component: relativePath,
1308
+ reason: `directory_unreadable:${errorCode(error)}`,
1309
+ expected_type: "regular_directory",
1310
+ },
1311
+ );
1312
+ }
1313
+ if (stat.isSymbolicLink() || !stat.isDirectory()) {
1314
+ throw snapshotAttemptError(
1315
+ "canonical_pcr_path_invalid",
1316
+ `Canonical PCR path component is not a regular directory: ${relativePath}.`,
1317
+ {
1318
+ path_component: relativePath,
1319
+ reason: stat.isSymbolicLink() ? "symbolic_link" : "not_a_directory",
1320
+ expected_type: "regular_directory",
1321
+ },
1322
+ );
1323
+ }
1324
+
1325
+ let realPath;
1326
+ try {
1327
+ realPath = realpathSync(directoryPath);
1328
+ } catch (error) {
1329
+ throw snapshotAttemptError(
1330
+ "canonical_pcr_path_invalid",
1331
+ `Canonical PCR directory cannot be resolved: ${relativePath}.`,
1332
+ {
1333
+ path_component: relativePath,
1334
+ reason: `realpath_unavailable:${errorCode(error)}`,
1335
+ expected_type: "regular_directory",
1336
+ },
1337
+ );
1338
+ }
1339
+ if (index === 0) {
1340
+ rootRealPath = realPath;
1341
+ } else if (!pathIsInside(rootRealPath, realPath)) {
1342
+ throw snapshotAttemptError(
1343
+ "canonical_pcr_path_invalid",
1344
+ `Canonical PCR directory resolves outside the repository root: ${relativePath}.`,
1345
+ {
1346
+ path_component: relativePath,
1347
+ reason: "realpath_outside_root",
1348
+ expected_type: "regular_directory_within_root",
1349
+ },
1350
+ );
1351
+ }
1352
+ }
1353
+
1354
+ const pcrDir = directoryPaths.at(-1);
1355
+ const manifestPath = path.join(pcrDir, "manifest.yaml");
1356
+ if (path.resolve(entry.manifestPath) !== manifestPath) {
1357
+ throw snapshotAttemptError(
1358
+ "canonical_pcr_path_invalid",
1359
+ "Cached manifest path is not the direct manifest.yaml child of its canonical PCR leaf.",
1360
+ {
1361
+ pcr_path: entry.path,
1362
+ reason: "manifest_not_direct_leaf_child",
1363
+ },
1364
+ );
1365
+ }
1366
+ return { manifestPath, pcrDir };
1367
+ }
1368
+
1369
+ function pathIsInside(rootPath, candidatePath) {
1370
+ const relativePath = path.relative(rootPath, candidatePath);
1371
+ return relativePath === "" || (!path.isAbsolute(relativePath) && relativePath !== ".." && !relativePath.startsWith(`..${path.sep}`));
1372
+ }
1373
+
1374
+ function exactByteSha256(bytes) {
1375
+ return `sha256:${createHash("sha256").update(bytes).digest("hex")}`;
1376
+ }
1377
+
1378
+ function readOptionalCanonicalFile(filePath) {
1379
+ try {
1380
+ return { bytes: readCanonicalFileBytes(filePath), error: null };
1381
+ } catch (error) {
1382
+ return { bytes: null, error };
1383
+ }
1384
+ }
1385
+
1386
+ function readControlledRepositoryFileBytes({ root, filePath, relativePath, label }) {
1387
+ const normalizedRoot = path.resolve(root);
1388
+ const normalizedFilePath = path.resolve(filePath);
1389
+ const containedPath = path.relative(normalizedRoot, normalizedFilePath);
1390
+ if (
1391
+ containedPath.length === 0
1392
+ || path.isAbsolute(containedPath)
1393
+ || containedPath === ".."
1394
+ || containedPath.startsWith(`..${path.sep}`)
1395
+ ) {
1396
+ throw new Error(`${label} path escapes the repository root: ${relativePath}`);
1397
+ }
1398
+
1399
+ const expectedRelativePath = toPosix(containedPath);
1400
+ if (expectedRelativePath !== relativePath) {
1401
+ throw new Error(`${label} path is not canonical: ${relativePath}`);
1402
+ }
1403
+
1404
+ const before = assertControlledRepositoryPath({
1405
+ root: normalizedRoot,
1406
+ containedPath,
1407
+ relativePath,
1408
+ label,
1409
+ });
1410
+ let descriptor;
1411
+ try {
1412
+ descriptor = openSync(
1413
+ normalizedFilePath,
1414
+ fsConstants.O_RDONLY
1415
+ | (fsConstants.O_NOFOLLOW ?? 0)
1416
+ | (fsConstants.O_NONBLOCK ?? 0),
1417
+ );
1418
+ const opened = fstatSync(descriptor);
1419
+ if (!opened.isFile()) {
1420
+ throw new Error(`${label} is not a regular file: ${relativePath}`);
1421
+ }
1422
+ const after = assertControlledRepositoryPath({
1423
+ root: normalizedRoot,
1424
+ containedPath,
1425
+ relativePath,
1426
+ label,
1427
+ });
1428
+ if (
1429
+ opened.dev !== before.dev
1430
+ || opened.ino !== before.ino
1431
+ || opened.dev !== after.dev
1432
+ || opened.ino !== after.ino
1433
+ ) {
1434
+ throw new Error(`${label} path changed while it was being opened: ${relativePath}`);
1435
+ }
1436
+ return readFileSync(descriptor);
1437
+ } finally {
1438
+ if (descriptor !== undefined) {
1439
+ closeSync(descriptor);
1440
+ }
1441
+ }
1442
+ }
1443
+
1444
+ function assertControlledRepositoryPath({ root, containedPath, relativePath, label }) {
1445
+ let currentPath = root;
1446
+ let finalStats;
1447
+ const segments = containedPath.split(path.sep);
1448
+ for (const [index, segment] of segments.entries()) {
1449
+ currentPath = path.join(currentPath, segment);
1450
+ const stats = lstatSync(currentPath);
1451
+ if (stats.isSymbolicLink()) {
1452
+ throw new Error(`${label} path contains a symbolic link: ${relativePath}`);
1453
+ }
1454
+ const isLast = index === segments.length - 1;
1455
+ if (isLast ? !stats.isFile() : !stats.isDirectory()) {
1456
+ throw new Error(
1457
+ isLast
1458
+ ? `${label} is not a regular file: ${relativePath}`
1459
+ : `${label} parent is not a directory: ${relativePath}`,
1460
+ );
1461
+ }
1462
+ if (isLast) {
1463
+ finalStats = stats;
1464
+ }
1465
+ }
1466
+
1467
+ const realRoot = realpathSync(root);
1468
+ const realFile = realpathSync(path.join(root, containedPath));
1469
+ if (!pathIsInside(realRoot, realFile) || realRoot === realFile) {
1470
+ throw new Error(`${label} real path escapes the repository root: ${relativePath}`);
1471
+ }
1472
+ return finalStats;
1473
+ }
1474
+
1475
+ function readCanonicalFileBytes(filePath) {
1476
+ const stat = lstatSync(filePath);
1477
+ if (stat.isSymbolicLink() || !stat.isFile()) {
1478
+ const error = new Error(`Canonical PCR artifact is not a regular file: ${filePath}`);
1479
+ error.code = stat.isSymbolicLink()
1480
+ ? "PCR_CANONICAL_SYMLINK_REJECTED"
1481
+ : "PCR_CANONICAL_FILE_NOT_REGULAR";
1482
+ throw error;
1483
+ }
1484
+ const descriptor = openSync(
1485
+ filePath,
1486
+ fsConstants.O_RDONLY | (fsConstants.O_NOFOLLOW ?? 0),
1487
+ );
1488
+ try {
1489
+ if (!fstatSync(descriptor).isFile()) {
1490
+ const error = new Error(`Canonical PCR artifact is not a regular file: ${filePath}`);
1491
+ error.code = "PCR_CANONICAL_FILE_NOT_REGULAR";
1492
+ throw error;
1493
+ }
1494
+ return readFileSync(descriptor);
1495
+ } finally {
1496
+ closeSync(descriptor);
1497
+ }
1498
+ }
1499
+
1500
+ function snapshotAttemptError(code, message, details = {}) {
1501
+ const error = new Error(message);
1502
+ error.snapshotCode = code;
1503
+ error.snapshotDetails = details;
1504
+ return error;
1505
+ }
1506
+
1507
+ function snapshotFailureDetails(error) {
1508
+ return {
1509
+ code: error?.snapshotCode ?? errorCode(error),
1510
+ message: error instanceof Error ? error.message : String(error),
1511
+ ...(isRecord(error?.snapshotDetails) ? error.snapshotDetails : {}),
1512
+ };
1513
+ }
1514
+
1515
+ function pcrFromManifest({ root, pcrDir, manifest }) {
1516
+ const pcr = {
1517
+ id: manifest.id,
1518
+ path: toPosix(path.relative(root, pcrDir)),
1519
+ title: manifest.title ?? {},
1520
+ status: manifest.status ?? "unknown",
1521
+ version: manifest.version ?? null,
1522
+ content_maturity: manifest.content_maturity ?? null,
1523
+ languages: manifest.languages ?? {},
1524
+ translation_status: manifest.translation_status ?? {},
1525
+ classification_refs: manifest.classification_refs ?? [],
1526
+ };
1527
+ pcr.record_kind = recordKindForPcr(pcr);
1528
+ return pcr;
1529
+ }
1530
+
1531
+ function inspectPcrProjection({ root, pcr, manifest, artifacts }) {
1532
+ const pcrDir = path.join(root, pcr.path);
1533
+ const structuredPath = path.join(pcrDir, "structured.yaml");
1534
+ const structuredArtifact = artifacts["structured.yaml"];
1535
+ const markdownArtifact = artifacts["pcr.en-US.md"];
1536
+ if (!isMaterialPcr(pcr)) {
1537
+ return {
1538
+ fingerprint: {
1539
+ ...projectionNotRequiredState(),
1540
+ schema_valid: null,
1541
+ },
1542
+ structured: null,
1543
+ structuredPath,
1544
+ structuredAvailable: Boolean(structuredArtifact?.bytes),
1545
+ completenessIssues: [],
1546
+ };
1547
+ }
1548
+
1549
+ if (!structuredArtifact?.bytes && structuredArtifact?.error?.code === "ENOENT") {
1550
+ return unavailableProjectionInspection({
1551
+ structuredPath,
1552
+ structuredAvailable: false,
1553
+ fingerprint: missingProjectionState(
1554
+ "missing",
1555
+ "structured_projection_missing",
1556
+ "structured.yaml is required for material PCR guidance and validation.",
1557
+ ),
1558
+ });
1559
+ }
1560
+
1561
+ if (!markdownArtifact?.bytes && markdownArtifact?.error?.code === "ENOENT") {
1562
+ return unavailableProjectionInspection({
1563
+ structuredPath,
1564
+ structuredAvailable: Boolean(structuredArtifact?.bytes),
1565
+ fingerprint: missingProjectionState(
1566
+ "source_missing",
1567
+ "projection_source_missing",
1568
+ "Canonical pcr.en-US.md is required to verify the structured projection.",
1569
+ ),
1570
+ });
1571
+ }
1572
+
1573
+ if (!markdownArtifact?.bytes) {
1574
+ return unavailableProjectionInspection({
1575
+ structuredPath,
1576
+ structuredAvailable: Boolean(structuredArtifact?.bytes),
1577
+ fingerprint: invalidProjectionState(
1578
+ "projection_source_unreadable",
1579
+ `Canonical pcr.en-US.md could not be read (${errorCode(markdownArtifact?.error)}).`,
1580
+ null,
1581
+ ),
1582
+ });
1583
+ }
1584
+
1585
+ if (!structuredArtifact?.bytes) {
1586
+ return unavailableProjectionInspection({
1587
+ structuredPath,
1588
+ structuredAvailable: false,
1589
+ fingerprint: invalidProjectionState(
1590
+ "structured_projection_unreadable",
1591
+ `structured.yaml could not be read (${errorCode(structuredArtifact?.error)}).`,
1592
+ false,
1593
+ ),
1594
+ });
1595
+ }
1596
+
1597
+ const sourceMarkdown = markdownArtifact.bytes.toString("utf8");
1598
+ const structuredText = structuredArtifact.bytes.toString("utf8");
1599
+
1600
+ let structured;
1601
+ try {
1602
+ structured = parseYaml(structuredText);
1603
+ } catch (error) {
1604
+ return unavailableProjectionInspection({
1605
+ structuredPath,
1606
+ structuredAvailable: true,
1607
+ fingerprint: invalidProjectionState(
1608
+ "structured_projection_parse_error",
1609
+ `structured.yaml could not be parsed (${errorCode(error)}).`,
1610
+ false,
1611
+ ),
1612
+ });
1613
+ }
1614
+
1615
+ const schemaResult = validateCoreContract(
1616
+ "structured-projection.schema.json",
1617
+ structured,
1618
+ { entityKind: "material structured projection" },
1619
+ );
1620
+ const integrity = inspectProjectionIntegrity({
1621
+ sourceMarkdown,
1622
+ structuredText,
1623
+ metadata: structured?.projection_metadata,
1624
+ });
1625
+ const schemaIssues = schemaResult.valid
1626
+ ? []
1627
+ : [
1628
+ {
1629
+ code: "structured_schema_invalid",
1630
+ message: `structured.yaml violates the material projection schema (${schemaResult.errors.length} issue(s)).`,
1631
+ },
1632
+ ...schemaResult.errors.map((error) => ({
1633
+ code: `structured_schema.${error.keyword}`,
1634
+ message: `${error.instance_path}: ${error.message}`,
1635
+ })),
1636
+ ];
1637
+ const issues = deduplicateMessages([...schemaIssues, ...integrity.issues]);
1638
+ const fingerprint = {
1639
+ ...integrity,
1640
+ status: schemaResult.valid ? integrity.status : "invalid",
1641
+ schema_valid: schemaResult.valid,
1642
+ issues,
1643
+ };
1644
+
1645
+ return {
1646
+ fingerprint,
1647
+ structured: schemaResult.valid && integrity.status === "current" ? structured : null,
1648
+ structuredPath,
1649
+ structuredAvailable: true,
1650
+ completenessIssues: schemaResult.valid
1651
+ ? materialProjectionCompletenessIssues(structured, {
1652
+ expectedPcrId: pcr.id,
1653
+ allowUnresolvedProductFlowUuid:
1654
+ hasDeclaredUnresolvedReferenceProductFlow(structured, manifest),
1655
+ })
1656
+ : [],
1657
+ };
1658
+ }
1659
+
1660
+ function unavailableProjectionInspection({ fingerprint, structuredPath, structuredAvailable }) {
1661
+ return {
1662
+ fingerprint,
1663
+ structured: null,
1664
+ structuredPath,
1665
+ structuredAvailable,
1666
+ completenessIssues: [],
1667
+ };
1668
+ }
1669
+
1670
+ function failedProjectionInspection({ root, pcr, error }) {
1671
+ return unavailableProjectionInspection({
1672
+ structuredPath: path.join(root, pcr.path, "structured.yaml"),
1673
+ structuredAvailable: false,
1674
+ fingerprint: invalidProjectionState(
1675
+ "projection_inspection_failed",
1676
+ `Projection integrity inspection failed (${errorCode(error)}).`,
1677
+ false,
1678
+ ),
1679
+ });
1680
+ }
1681
+
1682
+ function invalidProjectionState(code, message, schemaValid) {
1683
+ return {
1684
+ required: true,
1685
+ status: "invalid",
1686
+ schema_valid: schemaValid,
1687
+ contract_version: null,
1688
+ source_sha256: null,
1689
+ generated_content_sha256: null,
1690
+ source_hash_valid: null,
1691
+ content_hash_valid: null,
1692
+ issues: [{ code, message }],
1693
+ };
1694
+ }
1695
+
1696
+ function errorCode(error) {
1697
+ return typeof error?.code === "string" && error.code
1698
+ ? error.code
1699
+ : "unknown_error";
1700
+ }
1701
+
1702
+ function missingProjectionState(status, code, message) {
1703
+ return {
1704
+ required: true,
1705
+ status,
1706
+ schema_valid: null,
1707
+ contract_version: null,
1708
+ source_sha256: null,
1709
+ generated_content_sha256: null,
1710
+ source_hash_valid: null,
1711
+ content_hash_valid: null,
1712
+ issues: [{ code, message }],
1713
+ };
1714
+ }
1715
+
1716
+ function isMaterialPcr(pcr) {
1717
+ return recordKindForPcr(pcr) === "methodology";
1718
+ }
1719
+
1720
+ function normalizeCatalogScope(scope) {
1721
+ const normalized = String(scope);
1722
+ if (!PCR_CATALOG_SCOPE_SET.has(normalized)) {
1723
+ throw new PcrCatalogScopeError(scope);
1724
+ }
1725
+ return normalized;
1726
+ }
1727
+
1728
+ function recordMatchesScope(pcr, scope) {
1729
+ if (scope === "all") {
1730
+ return true;
1731
+ }
1732
+ return scope === "material"
1733
+ ? pcr.record_kind === "methodology"
1734
+ : pcr.record_kind === "legacy_scaffold_reference";
1735
+ }
1736
+
1737
+ function currentCatalogEntryMatchesScope(root, entry, scope) {
1738
+ const manifest = readConsistentCurrentManifest({ root, entry });
1739
+ const recordKind = recordKindForPcr({
1740
+ status: manifest.status ?? "unknown",
1741
+ content_maturity: manifest.content_maturity ?? null,
1742
+ });
1743
+ return scope === "material"
1744
+ ? recordKind === "methodology"
1745
+ : recordKind === "legacy_scaffold_reference";
1746
+ }
1747
+
1748
+ function readConsistentCurrentManifest({ root, entry }) {
1749
+ let lastFailure = null;
1750
+ for (let attempt = 1; attempt <= CURRENT_SNAPSHOT_MAX_ATTEMPTS; attempt += 1) {
1751
+ try {
1752
+ const locationA = assertCurrentSnapshotLocation({ root, entry });
1753
+ const manifestABytes = readCanonicalFileBytes(locationA.manifestPath);
1754
+ const manifest = parseYaml(manifestABytes.toString("utf8"));
1755
+ if (manifest.id !== entry.id) {
1756
+ throw snapshotAttemptError(
1757
+ "manifest_identity_changed",
1758
+ `Expected PCR id ${entry.id}, found ${String(manifest.id)}.`,
1759
+ { expected_pcr_id: entry.id, actual_pcr_id: manifest.id ?? null },
1760
+ );
1761
+ }
1762
+
1763
+ const locationB = assertCurrentSnapshotLocation({ root, entry });
1764
+ const manifestBBytes = readCanonicalFileBytes(locationB.manifestPath);
1765
+ if (!manifestABytes.equals(manifestBBytes)) {
1766
+ throw snapshotAttemptError(
1767
+ "manifest_changed_during_read",
1768
+ "manifest.yaml changed while its catalog scope was being determined.",
1769
+ );
1770
+ }
1771
+ return manifest;
1772
+ } catch (error) {
1773
+ lastFailure = snapshotFailureDetails(error);
1774
+ }
1775
+ }
1776
+ throw new PcrCurrentSnapshotInconsistentError({
1777
+ pcrId: entry.id,
1778
+ pcrPath: entry.path,
1779
+ attempts: CURRENT_SNAPSHOT_MAX_ATTEMPTS,
1780
+ lastFailure,
1781
+ });
1782
+ }
1783
+
1784
+ function recordKindForPcr(pcr) {
1785
+ if (pcr.status === "scaffold" && pcr.content_maturity === "empty_scaffold") {
1786
+ return "legacy_scaffold_reference";
1787
+ }
1788
+ if (
1789
+ METHODOLOGY_LIFECYCLE_STATUSES.has(pcr.status) &&
1790
+ METHODOLOGY_MATURITIES.has(pcr.content_maturity)
1791
+ ) {
1792
+ return "methodology";
1793
+ }
1794
+ return "invalid_lifecycle_state";
1795
+ }
1796
+
1797
+ function assessPcrReadiness({
1798
+ pcr,
1799
+ projectionFingerprint,
1800
+ structuredAvailable,
1801
+ projectionCompletenessIssues = [],
1802
+ }) {
1803
+ const blockers = [];
1804
+ const warnings = [];
1805
+ const methodologyStatus = pcr.content_maturity ?? "unknown";
1806
+ const lifecycleStatus = pcr.status ?? "unknown";
1807
+ const chineseTranslationStatus = pcr.translation_status?.["zh-CN"] ?? "unknown";
1808
+ if (pcr.record_kind === "invalid_lifecycle_state") {
1809
+ blockers.push({
1810
+ code: "invalid_lifecycle_identity",
1811
+ message:
1812
+ `status ${lifecycleStatus} and content_maturity ${methodologyStatus} do not identify either ` +
1813
+ "a legacy scaffold or a material methodology record.",
1814
+ });
1815
+ }
1816
+ if (!GUIDANCE_MATURITIES.has(methodologyStatus)) {
1817
+ blockers.push({
1818
+ code: "methodology_not_authored",
1819
+ message: `content_maturity ${methodologyStatus} is not usable methodology.`,
1820
+ });
1821
+ }
1822
+ if (lifecycleStatus === "scaffold") {
1823
+ blockers.push({
1824
+ code: "scaffold_lifecycle",
1825
+ message: "PCR lifecycle status is scaffold.",
1826
+ });
1827
+ } else if (!GUIDANCE_LIFECYCLE_STATUSES.has(lifecycleStatus)) {
1828
+ blockers.push({
1829
+ code: "lifecycle_not_usable",
1830
+ message: `PCR lifecycle status ${lifecycleStatus} is not available for guidance.`,
1831
+ });
1832
+ }
1833
+ if (lifecycleStatus === "deprecated" || methodologyStatus === "deprecated_methodology") {
1834
+ blockers.push({
1835
+ code: "deprecated_methodology",
1836
+ message: "Deprecated PCR methodology must not guide new work.",
1837
+ });
1838
+ }
1839
+ if (projectionFingerprint.required && (
1840
+ projectionFingerprint.schema_valid !== true || projectionFingerprint.status !== "current"
1841
+ )) {
1842
+ blockers.push(...projectionFingerprint.issues);
1843
+ }
1844
+ if (
1845
+ projectionFingerprint.required &&
1846
+ projectionFingerprint.schema_valid === true &&
1847
+ projectionFingerprint.status === "current"
1848
+ ) {
1849
+ blockers.push(...projectionCompletenessIssues);
1850
+ }
1851
+ if (
1852
+ GUIDANCE_MATURITIES.has(methodologyStatus) &&
1853
+ !USABLE_LIFECYCLE_STATES.get(lifecycleStatus)?.has(methodologyStatus)
1854
+ ) {
1855
+ blockers.push({
1856
+ code: "incompatible_lifecycle_state",
1857
+ message: `status ${lifecycleStatus} is incompatible with content_maturity ${methodologyStatus}.`,
1858
+ });
1859
+ }
1860
+ if (
1861
+ lifecycleStatus === "active" &&
1862
+ !["aligned", "reviewed"].includes(chineseTranslationStatus)
1863
+ ) {
1864
+ blockers.push({
1865
+ code: "translation_not_aligned",
1866
+ message: `active PCR requires aligned or reviewed zh-CN translation; found ${chineseTranslationStatus}.`,
1867
+ });
1868
+ }
1869
+ if (lifecycleStatus === "published" && chineseTranslationStatus !== "reviewed") {
1870
+ blockers.push({
1871
+ code: "translation_not_reviewed",
1872
+ message: `published PCR requires reviewed zh-CN translation; found ${chineseTranslationStatus}.`,
1873
+ });
1874
+ }
1875
+
1876
+ if (methodologyStatus === "authored_methodology") {
1877
+ warnings.push({
1878
+ code: "methodology_not_reviewed",
1879
+ message: "Authored methodology is candidate guidance and still requires methodology review.",
1880
+ });
1881
+ }
1882
+ if (
1883
+ lifecycleStatus === "candidate" &&
1884
+ !["aligned", "reviewed"].includes(chineseTranslationStatus)
1885
+ ) {
1886
+ warnings.push({
1887
+ code: "translation_not_aligned",
1888
+ message: `Candidate zh-CN translation is ${chineseTranslationStatus}; use canonical en-US guidance for methodology decisions.`,
1889
+ });
1890
+ }
1891
+
1892
+ const uniqueBlockers = deduplicateMessages(blockers);
1893
+ const uniqueWarnings = deduplicateMessages(warnings);
1894
+ const usable = uniqueBlockers.length === 0;
1895
+ const readiness = {
1896
+ status: usable
1897
+ ? (REVIEWED_MATURITIES.has(methodologyStatus) && lifecycleStatus !== "candidate" ? "ready" : "review_required")
1898
+ : "unavailable",
1899
+ lifecycle_status: lifecycleStatus,
1900
+ methodology_status: methodologyStatus,
1901
+ structured_projection_available: structuredAvailable,
1902
+ projection_fingerprint: structuredClone(projectionFingerprint),
1903
+ usable_for_guidance: usable,
1904
+ usable_for_validation: usable,
1905
+ blockers: uniqueBlockers,
1906
+ warnings: uniqueWarnings,
1907
+ };
1908
+ assertCoreContract("readiness.schema.json", readiness, {
1909
+ code: "PCR_INTERNAL_CONTRACT_INVALID",
1910
+ entityKind: "PCR readiness",
1911
+ });
1912
+ return readiness;
1913
+ }
1914
+
1915
+ function assertPcrUsable({ pcr, operation }) {
1916
+ const usabilityKey = operation === "validation" ? "usable_for_validation" : "usable_for_guidance";
1917
+ if (!pcr.readiness?.[usabilityKey]) {
1918
+ throw new PcrUsabilityError({ pcrId: pcr.id, operation, readiness: pcr.readiness });
1919
+ }
1920
+ }
1921
+
1922
+ function buildValidationReport({
1923
+ validationKind,
1924
+ guidance,
1925
+ input,
1926
+ findings,
1927
+ checksPerformed,
1928
+ checksSkipped,
1929
+ }) {
1930
+ const checkedRequirementCount = checksPerformed.reduce((total, check) => total + check.requirement_count, 0);
1931
+ const skippedRequirementCount = checksSkipped.reduce((total, check) => total + check.requirement_count, 0);
1932
+ const completeness = checksPerformed.length === 0
1933
+ ? "none"
1934
+ : checksSkipped.length > 0
1935
+ ? "partial"
1936
+ : "complete";
1937
+ const findingSummary = countFindingsBySeverity(findings);
1938
+ const validationStatus = findingSummary.error > 0
1939
+ ? "failed"
1940
+ : checksPerformed.length === 0
1941
+ ? "inconclusive"
1942
+ : "passed";
1943
+
1944
+ const report = {
1945
+ schema_version: 1,
1946
+ validation_kind: validationKind,
1947
+ pcr: guidance.pcr,
1948
+ readiness: structuredClone(guidance.readiness),
1949
+ validation_status: validationStatus,
1950
+ completeness,
1951
+ input,
1952
+ check_coverage: {
1953
+ total_requirement_count: checkedRequirementCount + skippedRequirementCount,
1954
+ checked_requirement_count: checkedRequirementCount,
1955
+ skipped_requirement_count: skippedRequirementCount,
1956
+ checks_performed: checksPerformed,
1957
+ checks_skipped: checksSkipped,
1958
+ },
1959
+ finding_count: findings.length,
1960
+ finding_summary: findingSummary,
1961
+ findings,
1962
+ };
1963
+ assertCoreContract("validation-output.schema.json", report, {
1964
+ code: "PCR_INTERNAL_CONTRACT_INVALID",
1965
+ entityKind: "PCR validation report",
1966
+ });
1967
+ return report;
1968
+ }
1969
+
1970
+ function performedCheck(checkId, requirementFamily, requirementCount) {
1971
+ return {
1972
+ check_id: checkId,
1973
+ requirement_family: requirementFamily,
1974
+ requirement_count: requirementCount,
1975
+ evaluated_requirement_count: requirementCount,
1976
+ };
1977
+ }
1978
+
1979
+ function addSkippedCheck(checks, checkId, requirementFamily, requirementCount) {
1980
+ if (requirementCount <= 0) {
1981
+ return;
1982
+ }
1983
+ checks.push({
1984
+ check_id: checkId,
1985
+ requirement_family: requirementFamily,
1986
+ requirement_count: requirementCount,
1987
+ reason: "Validator does not yet implement this requirement family.",
1988
+ });
1989
+ }
1990
+
1991
+ function countFindingsBySeverity(findings) {
1992
+ const summary = { error: 0, warning: 0, info: 0 };
1993
+ for (const finding of findings) {
1994
+ if (Object.hasOwn(summary, finding.severity)) {
1995
+ summary[finding.severity] += 1;
1996
+ }
1997
+ }
1998
+ return summary;
1999
+ }
2000
+
2001
+ function deduplicateMessages(entries) {
2002
+ return [
2003
+ ...new Map(
2004
+ entries.map((entry) => [`${entry.code}\0${entry.message}`, entry]),
2005
+ ).values(),
2006
+ ];
2007
+ }
2008
+
2009
+ function countInventoryRows(processInventory) {
2010
+ let count = 0;
2011
+ for (const process of asArray(processInventory)) {
2012
+ for (const direction of ["inputs", "outputs"]) {
2013
+ const groups = process?.[direction];
2014
+ if (!isRecord(groups)) {
2015
+ continue;
2016
+ }
2017
+ for (const rows of Object.values(groups)) {
2018
+ count += asArray(rows).length;
2019
+ }
2020
+ }
2021
+ }
2022
+ return count;
2023
+ }
2024
+
2025
+ function topLevelRequirementCount(value, excludedKeys = []) {
2026
+ if (!isRecord(value)) {
2027
+ return 0;
2028
+ }
2029
+ const excluded = new Set(excludedKeys);
2030
+ return Object.entries(value).filter(
2031
+ ([key, requirement]) => !excluded.has(key) && hasRequirementValue(requirement),
2032
+ ).length;
2033
+ }
2034
+
2035
+ function hasRequirementValue(value) {
2036
+ if (Array.isArray(value)) {
2037
+ return value.some(hasRequirementValue);
2038
+ }
2039
+ if (isRecord(value)) {
2040
+ return Object.values(value).some(hasRequirementValue);
2041
+ }
2042
+ return value !== undefined && value !== null && String(value).trim() !== "";
2043
+ }
2044
+
2045
+ function asArray(value) {
2046
+ return Array.isArray(value) ? value : [];
2047
+ }
2048
+
2049
+ function isRecord(value) {
2050
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
2051
+ }
2052
+
2053
+ function findManifestFiles(directory) {
2054
+ const results = [];
2055
+ for (const domainDir of canonicalChildDirectories(directory)) {
2056
+ for (const subdomainDir of canonicalChildDirectories(domainDir)) {
2057
+ for (const pcrDir of canonicalChildDirectories(subdomainDir)) {
2058
+ const manifestPath = path.join(pcrDir, "manifest.yaml");
2059
+ if (isCanonicalFile(manifestPath)) {
2060
+ results.push(manifestPath);
2061
+ }
2062
+ }
2063
+ }
2064
+ }
2065
+ return results;
2066
+ }
2067
+
2068
+ function canonicalChildDirectories(directory) {
2069
+ return readdirSync(directory)
2070
+ .map((entry) => path.join(directory, entry))
2071
+ .filter(isCanonicalDirectory)
2072
+ .sort((left, right) => left.localeCompare(right));
2073
+ }
2074
+
2075
+ function isCanonicalDirectory(directory) {
2076
+ try {
2077
+ const stat = lstatSync(directory);
2078
+ return !stat.isSymbolicLink() && stat.isDirectory();
2079
+ } catch (error) {
2080
+ if (error?.code === "ENOENT") {
2081
+ return false;
2082
+ }
2083
+ throw error;
2084
+ }
2085
+ }
2086
+
2087
+ function isCanonicalFile(filePath) {
2088
+ try {
2089
+ const stat = lstatSync(filePath);
2090
+ return !stat.isSymbolicLink() && stat.isFile();
2091
+ } catch (error) {
2092
+ if (error?.code === "ENOENT") {
2093
+ return false;
2094
+ }
2095
+ throw error;
2096
+ }
2097
+ }
2098
+
2099
+ function toPosix(value) {
2100
+ return value.split(path.sep).join("/");
2101
+ }